11 KiB
11 KiB
Tasks: enterprise-surrealdb
Change ID: enterprise-surrealdb
Package: @suaveplan/surrealdb
Target path: universal/database/surrealdb
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/db, @suaveplan/retry
1. Scaffold
- Create directory
universal/database/surrealdb/withsrc/,tests/,src/__benchmarks__/, and all feature subdirectories per the layout inproposal.md. - Write
package.jsonat version0.1.0with:"type": "module","sideEffects": falseexportsmap: top-level"."barrel plus subpaths for./connection/connection,./adapters/surreal-adapter,./schema/discovery,./init/init,./utils/version-detectordependencies:@suaveplan/error workspace:^,@suaveplan/types workspace:^,@suaveplan/db workspace:^,@suaveplan/retry workspace:^,surrealdb catalog:database,zod catalog:forms,@opentelemetry/api catalog:observability,tslib catalog:builddevDependencies:vitest catalog:testing,@vitest/coverage-istanbul catalog:testing,fast-check catalog:testing,mitata catalog:testing,@suaveplan/testing workspace:^
- Write
tsconfig.jsonextending@suaveplan/typescript-config/library.json. - Write
vitest.config.tsusingcreateTestConfig()from@suaveplan/testing/config(pool:forks). - Add
lint,typecheck,test,test:coverage,build,docs:check,benchscripts topackage.json.
2. Types + errors
2a. Common types (src/types/common.ts + src/types/common.md)
- Define all shared TS types:
SurrealVersion,MajorVersion,VersionInfo,ConnectionState,RecordId,RecordResult,QueryStatementResult,RawQueryResult,QueryResult,AuthCredentials. - Write
src/types/common.md(≥200 words, both simple + advanced examples, API reference).
2b. Error codes (src/error-codes.ts)
- Import
CodeMetadata,ErrorCodes,SuaveplanErrorfrom@suaveplan/error. - Define
SurrealErrorCodeunion — eight codes:SURREAL_CONNECT_FAILED,SURREAL_QUERY_FAILED,SURREAL_AUTH_FAILED,SURREAL_NOT_CONNECTED,SURREAL_TIMEOUT,SURREAL_VERSION_UNSUPPORTED,SURREAL_SCHEMA_LOAD_FAILED,SURREAL_INIT_FAILED. - Define
SURREAL_ERROR_METADATAwithhttpStatus,severity,retryable,userMessageKey,category,descriptionfor each code. - Export
registerSurrealErrorCodes()— callsErrorCodes.registerMany(SURREAL_ERROR_METADATA). Idempotent. - Call
registerSurrealErrorCodes()as an eager side-effect at module scope. - Export
SurrealErrorextendingSuaveplanErrorcarryingSurrealErrorCodeas its.codediscriminant.
2c. Zod option schemas
- Write
src/connection/connection/connection.types.tswithSurrealDBConfigSchemaand inferredSurrealDBConfig. - Write
src/init/init/init.types.tswithInitOptionsSchema,AdvancedInitOptionsSchema,SchemaFileSchema. - Write
src/schema/discovery/discovery.types.tswithDiscoverOptionsSchema.
3. Constants
- Write
src/constants/index.ts:DEFAULT_SCHEMA_ORDER:readonly string[]with sensible migration-first ordering.DEFAULT_SURREAL_URL,DEFAULT_SURREAL_NAMESPACE,DEFAULT_SURREAL_DATABASE.SURREAL_SUPPORTED_MAJOR_VERSIONS: readonly MajorVersion[]=[1, 2, 3].
4. Version detector (src/utils/version-detector.ts)
- Implement
detectVersion(db: Surreal): Promise<VersionInfo>:- Calls
db.version(), parses the semver string with a regex. - Returns typed
VersionInfofor major versions 1–3. - Throws
SurrealErrorwith codeSURREAL_VERSION_UNSUPPORTEDfor unknown major versions.
- Calls
- Write
version-detector.test.ts: known version strings for v1/v2/v3, prerelease string, unsupported major throws. - Write
version-detector.md(≥200 words).
5. Connection (src/connection/connection/)
- Implement
getDefaultConfig(): SurrealDBConfig— readsDB_URL,DB_NAMESPACE,DB_NAME,DB_USER,DB_PASSfromprocess.envwhere available; falls back to defaults. - Implement
createConnection(config?, options?):- Merges partial config with defaults.
- Instantiates
new Surreal(), callsdb.connect(url), then authenticates. - Accepts optional
signal?: AbortSignal— throwsSurrealError(SURREAL_TIMEOUT)on abort before connect completes. - Accepts optional
retry?: RetryStrategyOptions— wraps the connect+auth sequence with@suaveplan/retry'swithRetry. - OTel: span
surreal.connect, countersurreal.connect_total.
- Implement
connectWith,getSingleton,hasSingleton,closeSingleton— delegate to@suaveplan/db's singleton helpers where appropriate. - Write
connection.test.ts(requires real SurrealDB; gate withprocess.env.SURREALDB_URLskip guard). - Write
connection.md(≥200 words).
6. Adapter (src/adapters/surreal-adapter/)
- Define
SurrealAdapterinterface insurreal-adapter.types.ts— mirrors the main-branch surface; addsDatabaseAdapterfrom@suaveplan/dbas parent interface. - Implement
SurrealAdapterclass:- Internal
_state: ConnectionStatewith protected getter. connect(config)— callscreateConnection, transitions state.disconnect()— callsdb.close(), transitions todisconnected.query<T>(sql, params?, options?)— callsdb.query(sql, params), wraps errors asSurrealError(SURREAL_QUERY_FAILED), records OTel span + histogram.create,select,update,merge,delete— delegate to driver, wrap errors.- All methods accept optional
signal?: AbortSignal. - Fix: use
INSERT INTOquery instead ofdb.create()to avoid surrealdb.js v2 content-drop bug (see memoryfeedback_surrealdb_create_content_drop).
- Internal
- Write
surreal-adapter.test.ts(integration, real SurrealDB; SURREALDB_URL skip guard). - Write
surreal-adapter.md(≥200 words).
7. Schema discovery (src/schema/discovery/)
- Implement
discoverSchemas(dir, options?)— reads directory recursively for.surqlfiles; returnsSchemaFile[]sorted byDEFAULT_SCHEMA_ORDERthen alphabetically. - Implement
filterSchemas(files, filter)— apply caller-supplied predicate. - Implement
getSchemasToLoad(dir, filter?)—discoverSchemas+ optionalfilterSchemas. - Implement
readSchemaContent(file)— reads file content; caches infile.content. - Write
discovery.test.ts— in-memory fixture files (no real FS), happy path, empty dir, filter exclude/include. - Write
discovery.md(≥200 words).
8. Init (src/init/init/)
- Implement
initDatabase(db, options):- Calls
getSchemasToLoad, reads each file, executes viadb.query(content). - Runs
options.hooks?.before/afteraround each schema. - Dry-run mode: skip execution, record in
result.skipped. - Returns
InitResult { applied, skipped, errors }. - OTel: span
surreal.init, attributesurreal.schema_count.
- Calls
- Implement
initAndClose(options)— opens a singleton, runs init, closes. - Implement
createInitializer(options)— returns a closure(db) => initDatabase(db, options). - Write
init.test.ts(unit: mock schema files, real adapter not required; integration: SURREALDB_URL guard). - Write
init.md(≥200 words).
9. Public barrel (src/index.ts)
- Re-export all public symbols from connection, adapters, schema, init, utils, types, error-codes, constants.
- Re-export
RecordId,StringRecordId,Surreal,Table,Patch,RecordIdValuedirectly fromsurrealdbdriver (not wrapped).
10. OTel instrumentation (cross-cutting)
- Obtain tracer
surrealand metersurrealonce at module scope via lazytrace.getTracer/metrics.getMeter. createConnection— spansurreal.connectwith attributessurreal.url,surreal.namespace,surreal.database; countersurreal.connect_total.SurrealAdapter.query— spansurreal.query; histogramsurreal.query_duration_ms; countersurreal.query_totalwith attributesurreal.tablewhere parseable.closeSingleton/disconnect— spansurreal.disconnect.initDatabase— spansurreal.init; attributesurreal.schema_count.- All spans record exception on error and end in
finally.
11. Property-based tests (tests/property.test.ts)
Use fast-check. All test timeouts: { timeout: 30000 }.
detectVersionparser: for arbitrarymajor.minor.patchstrings (1–3), assert thatparseVersionStringreturns the same major/minor/patch. Does not require live DB.filterSchemascomplement: generate N random schema files (2–10); assert include filter with predicate P plus exclude filter with predicate P covers the full set without overlap.ConnectionStatestate machine: for a sequence ofconnectanddisconnectcalls on a mock adapter, assert the final state equals the result of applying transitions in order (always endsconnectedordisconnected).
12. Benchmarks (src/__benchmarks__/surreal.bench.ts)
Use mitata. Guard IO-bound benchmarks with SKIP_DB_BENCHMARKS env flag.
detectVersion_parse_10k: 10 000 pure semver parses.query_hot(conditional on!SKIP_DB_BENCHMARKS): 1000SELECT 1queries on a pre-connected adapter.- Document placeholder benchmark table in
README.mdunder## Benchmarks.
13. Docs
src/types/common.mdsrc/connection/connection/connection.mdsrc/adapters/surreal-adapter/surreal-adapter.mdsrc/schema/discovery/discovery.mdsrc/init/init/init.mdsrc/utils/version-detector.md- Root
universal/database/surrealdb/README.md— purpose, installation, quick-start, dep table, API symbol list, benchmarks table.
14. Verify and publish
- Run
bunx turbo lint --filter=@suaveplan/surrealdb— zero errors. - Run
bunx turbo typecheck --filter=@suaveplan/surrealdb— zero errors. - Run
bunx turbo test --filter=@suaveplan/surrealdb— all tests pass. - Run
bunx turbo test:coverage --filter=@suaveplan/surrealdb— 100% on all touched modules. - Run
bun run docs:check --filter=@suaveplan/surrealdb— zero errors. - Confirm no
TODO,FIXME,@deprecated, untypedany,ts-ignore, or.skipinsrc/ortests/. - Confirm
"sideEffects": falseinpackage.json. - Run
bun scripts/publish.ts --package @suaveplan/surrealdb. - Update
CLAUDE.mdpackage listing to include@suaveplan/surrealdb. - Archive: move
openspec/changes/enterprise-surrealdb/toopenspec/archive/2026-04-24-enterprise-surrealdb/and fold spec delta intoopenspec/specs/database/spec.md.