7.3 KiB
Wire SurrealImportStore into @suaveplan/api-plugin-import
Package: @suaveplan/api-plugin-import
Status: PROPOSED
Type: modified-requirements (follow-up to add-api-plugin-import)
- Spec delta: ./specs/api-plugin-import/spec.md
Why
The initial migration (openspec/archive/2026-05-19-add-api-plugin-import/) explicitly scoped out the SurrealDB-backed ImportStoreAdapter implementation. The published ### Excluded from this migration section reads:
SurrealImportStore— requires@suaveplan/surrealdbmigrations + the Surreal-side schema. Genesis shipsMemoryImportStoreagainst the sameImportStoreAdapterinterface so the SurrealDB adapter lands as a sibling package without breaking consumers. Listed in pending follow-ups.
Both prerequisites now exist on genesis:
@suaveplan/surrealdbships atpackages/database/surrealdb/with theSurrealAdapterclass implementingDatabaseAdapter.@suaveplan/api-plugin-databaseships atpackages/api/api-plugin-database/exposing a pooledSurrealAdapterviaServiceRegistry["db"].@suaveplan/api-plugin-eventsships the canonical positional-SurQL adapter pattern ($p0,$p1, …) atpackages/api/api-plugin-events/src/repositories/.
This change adds the durable SurrealImportStore implementation of the existing ImportStoreAdapter interface, ships the matching .surql migration co-located with the package, and registers a corresponding spec requirement. The change does NOT rewrite the existing service, routes, parsers, transform pipeline, or MemoryImportStore — only adds the SurrealDB store as an alternative backend selectable by the host.
What changes
- ADDED:
SurrealImportStore implements ImportStoreAdapteratsrc/store/surreal/surreal-import-store.tswithcreate,get,update,delete,listparity. Uses positional SurQL placeholders per the@suaveplan/api-plugin-eventsrepository pattern ($p0,$p1, …). - ADDED:
SurrealImportStoreConfigZod boundary schema (db adapter handle + optional table name + optional logger + optional clock). - ADDED:
surql/tables/import_job.surqlmigration defining theimport_jobtable schema (id, owner_id, status, total_rows, processed_rows, success_count, error_count, errors, metadata, created_at, updated_at, completed_at) with the canonicalOVERWRITEform used byapi-plugin-events. - ADDED: 1 new error code (
STORAGE_ERRORalready exists — reused for adapter failures; no registry growth). - ADDED: OTel counters
import.store.writes_total{outcome}andimport.store.reads_total{outcome}registered on first use via the existinggetImportInstruments()bundle (extension — keeps the bundle accessor stable). - ADDED: Subpath export
./store/surreal/surreal-import-storeinpackage.json#exports. - ADDED: Unit tests with a fake
SurrealAdapterexercising every SurQL string, parameter ordering, and error path (mirrorsevent-repository.test.ts). - ADDED: Integration test under
tests/integration/surreal-import-store.test.tsusing a realSurrealDBFixturefrom@suaveplan/testing-integration-surrealdb. Applies the.surqlmigration, round-trips a record, exercises filter/limit/offset onlist, and asserts theupdate-on-missing error message. - ADDED:
@suaveplan/surrealdb+@suaveplan/testing-integration-surrealdbas deps if not present.
Out of scope
Not addressed in this change — each remains a separate proposal:
- Streaming
Readable/AsyncIterableinput onstartImport(§4 future enhancement). - Foreign-key resolution across rows (§4).
- Parallel batch workers (§4).
- S3 / HTTP URL source adapters (§4).
- SSE progress push from the route layer (§4).
- Mitata benchmarks for the SurrealDB store (covered by the monorepo-wide benchmark wave).
- Postgres / SQLite store adapters (separate sibling proposals —
ImportStoreAdapteris the contract that admits them). - Any change to the existing
MemoryImportStore,ImportService,createImportRoutes, parsers, transform pipeline, progress tracker, plugin descriptor, problem-json renderer, or OTel instrument bundle public surface beyond the additive counter pair noted above. - Any modification to other
packages/api/api-plugin-*/,MANIFEST.md,STATUS.md,CLAUDE.md, or the rootpackage.json(except an additivebun.lockrefresh if a workspace dep needs hoisting).
Source mapping
This change derives from the original archive's ### Excluded from this migration section
(openspec/archive/2026-05-19-add-api-plugin-import/proposal.md) and from the upstream
enterprise audit ../suaveplan/enterprise/api-plugin-import.md §3 row 5.
| Requirement | Source | Notes |
|---|---|---|
SurrealImportStore implements ImportStoreAdapter |
openspec/archive/2026-05-19-add-api-plugin-import/proposal.md (Excluded) + ../suaveplan/enterprise/api-plugin-import.md §3 row 5 |
Implements the SHIPPED ImportStoreAdapter interface — zero contract drift |
Positional $p0,$p1,… SurQL placeholders |
packages/api/api-plugin-events/src/repositories/event-repository/event-repository.ts L20-L25 |
Pattern shared across all genesis SurrealDB repositories |
Co-located .surql migration |
packages/api/api-plugin-events/surql/tables/event.surql |
Same surql/tables/<table>.surql layout |
| Zod boundary on store config | openspec/AGENTS.md §11 |
Named-interface + parse-at-boundary policy |
| OTel counters on write / read | openspec/AGENTS.md §13 step 0 |
Cached bundle accessor (getImportInstruments) extended additively |
| Integration test against real SurrealDB testcontainer | packages/api/api-plugin-events/tests/integration/full-boot.test.ts |
Same SurrealDBFixture lifecycle |
Update-on-missing rejects with Job "<id>" not found |
openspec/specs/api-plugin-import/spec.md (SHIPPED MemoryImportStore requirement) |
Contract parity with the in-memory store |
Impact
Affected dependents
bunx turbo ls --filter=...@suaveplan/api-plugin-import enumerates dependents.
- No dependents currently consume
MemoryImportStore-specific symbols; the store is selected at host wiring time via theImportStoreAdapterinterface. AddingSurrealImportStoreis purely additive. — [x] no action needed (reason: additive sibling implementation of an existing interface; existing consumers continue to receiveMemoryImportStoreunless they opt in)