@prisma-next/adapter-mongo 0.5.0-dev.5 → 0.5.0-dev.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,8 +4,10 @@ MongoDB adapter for Prisma Next. Lowers abstract MongoDB commands into wire-prot
4
4
 
5
5
  ## Responsibilities
6
6
 
7
- - **Command lowering**: Converts `MongoCommand` instances (find, aggregate) into MongoDB wire-protocol documents
8
- - **Codec application**: Applies codec transformations to query parameters and result documents
7
+ - **Command lowering**: `MongoAdapter.lower(plan)` converts a `MongoCommand` (find, aggregate, …) into a wire-protocol document. The method is `async` so it can await codec encode work on parameter values; the runtime (`MongoRuntime.execute`) awaits `adapter.lower(plan)` before issuing the command to the driver.
8
+ - **Codec application on encode**: `resolveValue` walks parameter trees and dispatches codec-encoded leaves concurrently via `Promise.all`. The codec's `encode` is awaited (whether the codec body is sync or async), and the resolved wire value is placed into the lowered document.
9
+
10
+ Mongo does not currently decode rows — documents pass through from the driver directly — so this adapter has no decode-side codec application today. See [ADR 204 — Single-Path Async Codec Runtime](../../../docs/architecture%20docs/adrs/ADR%20204%20-%20Single-Path%20Async%20Codec%20Runtime.md) for the codec runtime's async boundary contract.
9
11
 
10
12
  ## Dependencies
11
13
 
@@ -2,7 +2,7 @@ import { Db, Document, MongoClient } from "mongodb";
2
2
  import { CollModCommand, CreateCollectionCommand, CreateIndexCommand, DropCollectionCommand, DropIndexCommand, ListCollectionsCommand, ListIndexesCommand, MongoDdlCommandVisitor, MongoInspectionCommandVisitor } from "@prisma-next/mongo-query-ast/control";
3
3
  import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
4
4
  import { MongoRunnerDependencies } from "@prisma-next/target-mongo/control";
5
- import { ControlAdapterDescriptor, ControlDriverInstance } from "@prisma-next/framework-components/control";
5
+ import { ControlAdapterDescriptor, ControlDriverInstance, ControlFamilyInstance } from "@prisma-next/framework-components/control";
6
6
  import { MongoDriver } from "@prisma-next/mongo-lowering";
7
7
 
8
8
  //#region src/core/command-executor.d.ts
@@ -33,7 +33,7 @@ declare function createMongoControlDriver(db: Db, client: MongoClient): MongoCon
33
33
  //#endregion
34
34
  //#region src/core/runner-deps.d.ts
35
35
  declare function extractDb(driver: ControlDriverInstance<'mongo', 'mongo'>): Db;
36
- declare function createMongoRunnerDeps(controlDriver: ControlDriverInstance<'mongo', 'mongo'>, driver: MongoDriver): MongoRunnerDependencies;
36
+ declare function createMongoRunnerDeps(controlDriver: ControlDriverInstance<'mongo', 'mongo'>, driver: MongoDriver, family: ControlFamilyInstance<'mongo', MongoSchemaIR>): MongoRunnerDependencies;
37
37
  //#endregion
38
38
  //#region src/exports/control.d.ts
39
39
  declare const mongoAdapterDescriptor: ControlAdapterDescriptor<'mongo', 'mongo'>;
@@ -1 +1 @@
1
- {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/exports/control.ts"],"sourcesContent":[],"mappings":";;;;;;;;cAca,oBAAA,YAAgC,uBAAuB;;kBACjC;mBAEV,qBAAqB;iBAmBvB,mBAAmB;wBAIZ,0BAA0B;EA1B3C,cAAA,CAAA,GAAA,EA0Ce,qBA1CM,CAAA,EA0CkB,OA1ClB,CAAA,IAAA,CAAA;EAAkC,OAAA,CAAA,GAAA,EA8C/C,cA9C+C,CAAA,EA8C9B,OA9C8B,CAAA,IAAA,CAAA;;AAG3C,cAsDZ,uBAAA,YAAmC,6BAtDvB,CAsDqD,OAtDrD,CAsD6D,QAtD7D,EAAA,CAAA,CAAA,CAAA;EAAqB,iBAAA,EAAA;EAmBvB,WAAA,CAAA,EAAA,EAoCY,EApCZ;EAAmB,WAAA,CAAA,GAAA,EAsCjB,kBAtCiB,CAAA,EAsCI,OAtCJ,CAsCY,QAtCZ,EAAA,CAAA;EAIZ,eAAA,CAAA,IAAA,EA6CA,sBA7CA,CAAA,EA6CyB,OA7CzB,CA6CiC,QA7CjC,EAAA,CAAA;;;;iBC8CR,gBAAA,KAAqB,KAAK,QAAQ;;;UCnFvC,0BAAA,SAAmC;eACrC;;iBAuBC,wBAAA,KAA6B,YAAY,cAAc;;;iBCdvD,SAAA,SAAkB,0CAA0C;iBAW5D,qBAAA,gBACC,iDACP,cACP;;;cCPG,wBAAwB"}
1
+ {"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/exports/control.ts"],"sourcesContent":[],"mappings":";;;;;;;;cAca,oBAAA,YAAgC,uBAAuB;;kBACjC;mBAEV,qBAAqB;iBAmBvB,mBAAmB;wBAIZ,0BAA0B;EA1B3C,cAAA,CAAA,GAAA,EA0Ce,qBA1CM,CAAA,EA0CkB,OA1ClB,CAAA,IAAA,CAAA;EAAkC,OAAA,CAAA,GAAA,EA8C/C,cA9C+C,CAAA,EA8C9B,OA9C8B,CAAA,IAAA,CAAA;;AAG3C,cAsDZ,uBAAA,YAAmC,6BAtDvB,CAsDqD,OAtDrD,CAsD6D,QAtD7D,EAAA,CAAA,CAAA,CAAA;EAAqB,iBAAA,EAAA;EAmBvB,WAAA,CAAA,EAAA,EAoCY,EApCZ;EAAmB,WAAA,CAAA,GAAA,EAsCjB,kBAtCiB,CAAA,EAsCI,OAtCJ,CAsCY,QAtCZ,EAAA,CAAA;EAIZ,eAAA,CAAA,IAAA,EA6CA,sBA7CA,CAAA,EA6CyB,OA7CzB,CA6CiC,QA7CjC,EAAA,CAAA;;;;iBC8CR,gBAAA,KAAqB,KAAK,QAAQ;;;UCnFvC,0BAAA,SAAmC;eACrC;;iBAuBC,wBAAA,KAA6B,YAAY,cAAc;;;iBCVvD,SAAA,SAAkB,0CAA0C;iBAW5D,qBAAA,gBACC,iDACP,qBACA,+BAA+B,iBACtC;;;cCpBG,wBAAwB"}
package/dist/control.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as mongoInt32Codec, c as mongoVectorCodec, i as mongoDoubleCodec, n as mongoBooleanCodec, o as mongoObjectIdCodec, r as mongoDateCodec, s as mongoStringCodec, t as createMongoAdapter } from "./mongo-adapter-aVo8aZrf.mjs";
1
+ import { r as mongoStandardCodecs, t as createMongoAdapter } from "./mongo-adapter-ByNtvoHK.mjs";
2
2
  import { MongoServerError } from "mongodb";
3
3
  import { keysToKeySpec } from "@prisma-next/mongo-query-ast/control";
4
4
  import { MongoSchemaCollection, MongoSchemaCollectionOptions, MongoSchemaIR, MongoSchemaIndex, MongoSchemaValidator } from "@prisma-next/mongo-schema-ir";
@@ -186,7 +186,7 @@ function extractDb(driver) {
186
186
  if (!mongoDriver.db) throw new Error("Mongo control driver does not expose a db property. Use mongoControlDriver.create() from `@prisma-next/driver-mongo/control`.");
187
187
  return mongoDriver.db;
188
188
  }
189
- function createMongoRunnerDeps(controlDriver, driver) {
189
+ function createMongoRunnerDeps(controlDriver, driver, family) {
190
190
  const db = extractDb(controlDriver);
191
191
  return {
192
192
  commandExecutor: new MongoCommandExecutor(db),
@@ -198,7 +198,8 @@ function createMongoRunnerDeps(controlDriver, driver) {
198
198
  initMarker: (dest) => initMarker(db, dest),
199
199
  updateMarker: (expectedFrom, dest) => updateMarker(db, expectedFrom, dest),
200
200
  writeLedgerEntry: (entry) => writeLedgerEntry(db, entry)
201
- }
201
+ },
202
+ introspectSchema: () => family.introspect({ driver: controlDriver })
202
203
  };
203
204
  }
204
205
 
@@ -219,15 +220,7 @@ const mongoAdapterDescriptor = {
219
220
  ["Float", "mongo/double@1"]
220
221
  ]),
221
222
  types: { codecTypes: {
222
- codecInstances: [
223
- mongoObjectIdCodec,
224
- mongoStringCodec,
225
- mongoDoubleCodec,
226
- mongoInt32Codec,
227
- mongoBooleanCodec,
228
- mongoDateCodec,
229
- mongoVectorCodec
230
- ],
223
+ codecInstances: [...mongoStandardCodecs],
231
224
  import: {
232
225
  package: "@prisma-next/adapter-mongo/codec-types",
233
226
  named: "CodecTypes",
@@ -1 +1 @@
1
- {"version":3,"file":"control.mjs","names":["db: Db","keySpec: Document","options: Record<string, unknown>","command: Record<string, unknown>","error: unknown","keys: MongoIndexKey[]","collections: MongoSchemaCollection[]","#client","mongoAdapterDescriptor: ControlAdapterDescriptor<'mongo', 'mongo'>"],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/exports/control.ts"],"sourcesContent":["import type {\n CollModCommand,\n CreateCollectionCommand,\n CreateIndexCommand,\n DropCollectionCommand,\n DropIndexCommand,\n ListCollectionsCommand,\n ListIndexesCommand,\n MongoDdlCommandVisitor,\n MongoInspectionCommandVisitor,\n} from '@prisma-next/mongo-query-ast/control';\nimport { keysToKeySpec } from '@prisma-next/mongo-query-ast/control';\nimport { type Db, type Document, MongoServerError } from 'mongodb';\n\nexport class MongoCommandExecutor implements MongoDdlCommandVisitor<Promise<void>> {\n constructor(private readonly db: Db) {}\n\n async createIndex(cmd: CreateIndexCommand): Promise<void> {\n const keySpec: Document = keysToKeySpec(cmd.keys);\n const options: Record<string, unknown> = {};\n if (cmd.unique !== undefined) options['unique'] = cmd.unique;\n if (cmd.sparse !== undefined) options['sparse'] = cmd.sparse;\n if (cmd.expireAfterSeconds !== undefined)\n options['expireAfterSeconds'] = cmd.expireAfterSeconds;\n if (cmd.partialFilterExpression !== undefined)\n options['partialFilterExpression'] = cmd.partialFilterExpression;\n if (cmd.name !== undefined) options['name'] = cmd.name;\n if (cmd.wildcardProjection !== undefined)\n options['wildcardProjection'] = cmd.wildcardProjection;\n if (cmd.collation !== undefined) options['collation'] = cmd.collation;\n if (cmd.weights !== undefined) options['weights'] = cmd.weights;\n if (cmd.default_language !== undefined) options['default_language'] = cmd.default_language;\n if (cmd.language_override !== undefined) options['language_override'] = cmd.language_override;\n await this.db.collection(cmd.collection).createIndex(keySpec, options);\n }\n\n async dropIndex(cmd: DropIndexCommand): Promise<void> {\n await this.db.collection(cmd.collection).dropIndex(cmd.name);\n }\n\n async createCollection(cmd: CreateCollectionCommand): Promise<void> {\n const options: Record<string, unknown> = {};\n if (cmd.capped !== undefined) options['capped'] = cmd.capped;\n if (cmd.size !== undefined) options['size'] = cmd.size;\n if (cmd.max !== undefined) options['max'] = cmd.max;\n if (cmd.timeseries !== undefined) options['timeseries'] = cmd.timeseries;\n if (cmd.collation !== undefined) options['collation'] = cmd.collation;\n if (cmd.clusteredIndex !== undefined) options['clusteredIndex'] = cmd.clusteredIndex;\n if (cmd.validator !== undefined) options['validator'] = cmd.validator;\n if (cmd.validationLevel !== undefined) options['validationLevel'] = cmd.validationLevel;\n if (cmd.validationAction !== undefined) options['validationAction'] = cmd.validationAction;\n if (cmd.changeStreamPreAndPostImages !== undefined)\n options['changeStreamPreAndPostImages'] = cmd.changeStreamPreAndPostImages;\n await this.db.createCollection(cmd.collection, options);\n }\n\n async dropCollection(cmd: DropCollectionCommand): Promise<void> {\n await this.db.collection(cmd.collection).drop();\n }\n\n async collMod(cmd: CollModCommand): Promise<void> {\n const command: Record<string, unknown> = { collMod: cmd.collection };\n if (cmd.validator !== undefined) command['validator'] = cmd.validator;\n if (cmd.validationLevel !== undefined) command['validationLevel'] = cmd.validationLevel;\n if (cmd.validationAction !== undefined) command['validationAction'] = cmd.validationAction;\n if (cmd.changeStreamPreAndPostImages !== undefined)\n command['changeStreamPreAndPostImages'] = cmd.changeStreamPreAndPostImages;\n await this.db.command(command);\n }\n}\n\nexport class MongoInspectionExecutor implements MongoInspectionCommandVisitor<Promise<Document[]>> {\n constructor(private readonly db: Db) {}\n\n async listIndexes(cmd: ListIndexesCommand): Promise<Document[]> {\n try {\n return await this.db.collection(cmd.collection).listIndexes().toArray();\n } catch (error: unknown) {\n if (error instanceof MongoServerError && error.code === 26) {\n return [];\n }\n throw error;\n }\n }\n\n async listCollections(_cmd: ListCollectionsCommand): Promise<Document[]> {\n return this.db.listCollections().toArray();\n }\n}\n","import type { MongoIndexKey, MongoIndexKeyDirection } from '@prisma-next/mongo-contract';\nimport {\n MongoSchemaCollection,\n MongoSchemaCollectionOptions,\n MongoSchemaIndex,\n MongoSchemaIR,\n MongoSchemaValidator,\n} from '@prisma-next/mongo-schema-ir';\nimport type { Db, Document } from 'mongodb';\n\nconst PRISMA_MIGRATIONS_COLLECTION = '_prisma_migrations';\n\nfunction parseIndexKeys(keySpec: Record<string, unknown>): MongoIndexKey[] {\n const keys: MongoIndexKey[] = [];\n for (const [field, direction] of Object.entries(keySpec)) {\n keys.push({ field, direction: direction as MongoIndexKeyDirection });\n }\n return keys;\n}\n\nfunction isDefaultIdIndex(doc: Document): boolean {\n const key = doc['key'] as Record<string, unknown> | undefined;\n if (!key) return false;\n const entries = Object.entries(key);\n return entries.length === 1 && entries[0]?.[0] === '_id' && entries[0]?.[1] === 1;\n}\n\nfunction parseIndex(doc: Document): MongoSchemaIndex {\n const keySpec = doc['key'] as Record<string, unknown>;\n return new MongoSchemaIndex({\n keys: parseIndexKeys(keySpec),\n unique: doc['unique'] as boolean | undefined,\n sparse: doc['sparse'] as boolean | undefined,\n expireAfterSeconds: doc['expireAfterSeconds'] as number | undefined,\n partialFilterExpression: doc['partialFilterExpression'] as Record<string, unknown> | undefined,\n wildcardProjection: doc['wildcardProjection'] as Record<string, 0 | 1> | undefined,\n collation: doc['collation'] as Record<string, unknown> | undefined,\n weights: doc['weights'] as Record<string, number> | undefined,\n default_language: doc['default_language'] as string | undefined,\n language_override: doc['language_override'] as string | undefined,\n });\n}\n\nfunction parseValidator(options: Document): MongoSchemaValidator | undefined {\n const validator = options['validator'] as Record<string, unknown> | undefined;\n if (!validator) return undefined;\n\n const jsonSchema = validator['$jsonSchema'] as Record<string, unknown> | undefined;\n if (!jsonSchema) return undefined;\n\n return new MongoSchemaValidator({\n jsonSchema,\n validationLevel: (options['validationLevel'] as 'strict' | 'moderate') ?? 'strict',\n validationAction: (options['validationAction'] as 'error' | 'warn') ?? 'error',\n });\n}\n\nfunction parseCollectionOptions(info: Document): MongoSchemaCollectionOptions | undefined {\n const options = info['options'] as Record<string, unknown> | undefined;\n if (!options) return undefined;\n\n const capped = options['capped'] as boolean | undefined;\n const size = options['size'] as number | undefined;\n const max = options['max'] as number | undefined;\n const timeseries = options['timeseries'] as\n | { timeField: string; metaField?: string; granularity?: 'seconds' | 'minutes' | 'hours' }\n | undefined;\n const collation = options['collation'] as Record<string, unknown> | undefined;\n const changeStreamPreAndPostImages = options['changeStreamPreAndPostImages'] as\n | { enabled: boolean }\n | undefined;\n const clusteredIndex = options['clusteredIndex'] as { name?: string } | undefined;\n\n const hasMeaningfulOptions =\n capped || timeseries || collation || changeStreamPreAndPostImages || clusteredIndex;\n if (!hasMeaningfulOptions) return undefined;\n\n return new MongoSchemaCollectionOptions({\n ...(capped ? { capped: { size: size ?? 0, ...(max != null ? { max } : {}) } } : {}),\n ...(timeseries ? { timeseries } : {}),\n ...(collation ? { collation } : {}),\n ...(changeStreamPreAndPostImages ? { changeStreamPreAndPostImages } : {}),\n ...(clusteredIndex ? { clusteredIndex } : {}),\n });\n}\n\nexport async function introspectSchema(db: Db): Promise<MongoSchemaIR> {\n const collectionInfos = await db.listCollections().toArray();\n\n const collections: MongoSchemaCollection[] = [];\n\n for (const info of collectionInfos) {\n const name = info['name'] as string;\n const type = info['type'] as string | undefined;\n\n if (name === PRISMA_MIGRATIONS_COLLECTION) continue;\n if (name.startsWith('system.')) continue;\n if (type === 'view') continue;\n\n const indexDocs = await db.collection(name).listIndexes().toArray();\n const indexes = indexDocs.filter((doc) => !isDefaultIdIndex(doc)).map(parseIndex);\n\n const infoOptions = 'options' in info ? (info['options'] as Record<string, unknown>) : {};\n const validator = parseValidator(infoOptions);\n const options = parseCollectionOptions(info);\n\n collections.push(\n new MongoSchemaCollection({\n name,\n indexes,\n ...(validator ? { validator } : {}),\n ...(options ? { options } : {}),\n }),\n );\n }\n\n return new MongoSchemaIR(collections);\n}\n","import type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport type { Db, MongoClient } from 'mongodb';\n\nexport interface MongoControlDriverInstance extends ControlDriverInstance<'mongo', 'mongo'> {\n readonly db: Db;\n}\n\nclass MongoControlDriverImpl implements MongoControlDriverInstance {\n readonly familyId = 'mongo' as const;\n readonly targetId = 'mongo' as const;\n readonly db: Db;\n readonly #client: MongoClient;\n\n constructor(db: Db, client: MongoClient) {\n this.db = db;\n this.#client = client;\n }\n\n query(): Promise<never> {\n throw new Error('MongoDB control driver does not support SQL queries');\n }\n\n async close(): Promise<void> {\n await this.#client.close();\n }\n}\n\nexport function createMongoControlDriver(db: Db, client: MongoClient): MongoControlDriverInstance {\n return new MongoControlDriverImpl(db, client);\n}\n","import type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport type { MongoDriver } from '@prisma-next/mongo-lowering';\nimport {\n initMarker,\n type MongoRunnerDependencies,\n readMarker,\n updateMarker,\n writeLedgerEntry,\n} from '@prisma-next/target-mongo/control';\nimport type { Db } from 'mongodb';\nimport { createMongoAdapter } from '../mongo-adapter';\nimport { MongoCommandExecutor, MongoInspectionExecutor } from './command-executor';\n\nexport function extractDb(driver: ControlDriverInstance<'mongo', 'mongo'>): Db {\n const mongoDriver = driver as ControlDriverInstance<'mongo', 'mongo'> & { db?: Db };\n if (!mongoDriver.db) {\n throw new Error(\n 'Mongo control driver does not expose a db property. ' +\n 'Use mongoControlDriver.create() from `@prisma-next/driver-mongo/control`.',\n );\n }\n return mongoDriver.db;\n}\n\nexport function createMongoRunnerDeps(\n controlDriver: ControlDriverInstance<'mongo', 'mongo'>,\n driver: MongoDriver,\n): MongoRunnerDependencies {\n const db = extractDb(controlDriver);\n return {\n commandExecutor: new MongoCommandExecutor(db),\n inspectionExecutor: new MongoInspectionExecutor(db),\n adapter: createMongoAdapter(),\n driver,\n markerOps: {\n readMarker: () => readMarker(db),\n initMarker: (dest) => initMarker(db, dest),\n updateMarker: (expectedFrom, dest) => updateMarker(db, expectedFrom, dest),\n writeLedgerEntry: (entry) => writeLedgerEntry(db, entry),\n },\n };\n}\n","import type { ControlAdapterDescriptor } from '@prisma-next/framework-components/control';\n\nexport { MongoCommandExecutor, MongoInspectionExecutor } from '../core/command-executor';\nexport { introspectSchema } from '../core/introspect-schema';\nexport {\n createMongoControlDriver,\n type MongoControlDriverInstance,\n} from '../core/mongo-control-driver';\nexport { createMongoRunnerDeps, extractDb } from '../core/runner-deps';\n\nimport {\n mongoBooleanCodec,\n mongoDateCodec,\n mongoDoubleCodec,\n mongoInt32Codec,\n mongoObjectIdCodec,\n mongoStringCodec,\n mongoVectorCodec,\n} from '../core/codecs';\n\nconst mongoAdapterDescriptor: ControlAdapterDescriptor<'mongo', 'mongo'> = {\n kind: 'adapter',\n id: 'mongo',\n familyId: 'mongo',\n targetId: 'mongo',\n version: '0.0.1',\n scalarTypeDescriptors: new Map([\n ['String', 'mongo/string@1'],\n ['Int', 'mongo/int32@1'],\n ['Boolean', 'mongo/bool@1'],\n ['DateTime', 'mongo/date@1'],\n ['ObjectId', 'mongo/objectId@1'],\n ['Float', 'mongo/double@1'],\n ]),\n types: {\n codecTypes: {\n codecInstances: [\n mongoObjectIdCodec,\n mongoStringCodec,\n mongoDoubleCodec,\n mongoInt32Codec,\n mongoBooleanCodec,\n mongoDateCodec,\n mongoVectorCodec,\n ],\n import: {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'CodecTypes',\n alias: 'MongoCodecTypes',\n },\n typeImports: [\n {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'Vector',\n alias: 'Vector',\n },\n ],\n },\n },\n create(_stack) {\n return { familyId: 'mongo' as const, targetId: 'mongo' as const };\n },\n};\n\nexport default mongoAdapterDescriptor;\n"],"mappings":"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"}
1
+ {"version":3,"file":"control.mjs","names":["db: Db","keySpec: Document","options: Record<string, unknown>","command: Record<string, unknown>","error: unknown","keys: MongoIndexKey[]","collections: MongoSchemaCollection[]","#client","mongoAdapterDescriptor: ControlAdapterDescriptor<'mongo', 'mongo'>"],"sources":["../src/core/command-executor.ts","../src/core/introspect-schema.ts","../src/core/mongo-control-driver.ts","../src/core/runner-deps.ts","../src/exports/control.ts"],"sourcesContent":["import type {\n CollModCommand,\n CreateCollectionCommand,\n CreateIndexCommand,\n DropCollectionCommand,\n DropIndexCommand,\n ListCollectionsCommand,\n ListIndexesCommand,\n MongoDdlCommandVisitor,\n MongoInspectionCommandVisitor,\n} from '@prisma-next/mongo-query-ast/control';\nimport { keysToKeySpec } from '@prisma-next/mongo-query-ast/control';\nimport { type Db, type Document, MongoServerError } from 'mongodb';\n\nexport class MongoCommandExecutor implements MongoDdlCommandVisitor<Promise<void>> {\n constructor(private readonly db: Db) {}\n\n async createIndex(cmd: CreateIndexCommand): Promise<void> {\n const keySpec: Document = keysToKeySpec(cmd.keys);\n const options: Record<string, unknown> = {};\n if (cmd.unique !== undefined) options['unique'] = cmd.unique;\n if (cmd.sparse !== undefined) options['sparse'] = cmd.sparse;\n if (cmd.expireAfterSeconds !== undefined)\n options['expireAfterSeconds'] = cmd.expireAfterSeconds;\n if (cmd.partialFilterExpression !== undefined)\n options['partialFilterExpression'] = cmd.partialFilterExpression;\n if (cmd.name !== undefined) options['name'] = cmd.name;\n if (cmd.wildcardProjection !== undefined)\n options['wildcardProjection'] = cmd.wildcardProjection;\n if (cmd.collation !== undefined) options['collation'] = cmd.collation;\n if (cmd.weights !== undefined) options['weights'] = cmd.weights;\n if (cmd.default_language !== undefined) options['default_language'] = cmd.default_language;\n if (cmd.language_override !== undefined) options['language_override'] = cmd.language_override;\n await this.db.collection(cmd.collection).createIndex(keySpec, options);\n }\n\n async dropIndex(cmd: DropIndexCommand): Promise<void> {\n await this.db.collection(cmd.collection).dropIndex(cmd.name);\n }\n\n async createCollection(cmd: CreateCollectionCommand): Promise<void> {\n const options: Record<string, unknown> = {};\n if (cmd.capped !== undefined) options['capped'] = cmd.capped;\n if (cmd.size !== undefined) options['size'] = cmd.size;\n if (cmd.max !== undefined) options['max'] = cmd.max;\n if (cmd.timeseries !== undefined) options['timeseries'] = cmd.timeseries;\n if (cmd.collation !== undefined) options['collation'] = cmd.collation;\n if (cmd.clusteredIndex !== undefined) options['clusteredIndex'] = cmd.clusteredIndex;\n if (cmd.validator !== undefined) options['validator'] = cmd.validator;\n if (cmd.validationLevel !== undefined) options['validationLevel'] = cmd.validationLevel;\n if (cmd.validationAction !== undefined) options['validationAction'] = cmd.validationAction;\n if (cmd.changeStreamPreAndPostImages !== undefined)\n options['changeStreamPreAndPostImages'] = cmd.changeStreamPreAndPostImages;\n await this.db.createCollection(cmd.collection, options);\n }\n\n async dropCollection(cmd: DropCollectionCommand): Promise<void> {\n await this.db.collection(cmd.collection).drop();\n }\n\n async collMod(cmd: CollModCommand): Promise<void> {\n const command: Record<string, unknown> = { collMod: cmd.collection };\n if (cmd.validator !== undefined) command['validator'] = cmd.validator;\n if (cmd.validationLevel !== undefined) command['validationLevel'] = cmd.validationLevel;\n if (cmd.validationAction !== undefined) command['validationAction'] = cmd.validationAction;\n if (cmd.changeStreamPreAndPostImages !== undefined)\n command['changeStreamPreAndPostImages'] = cmd.changeStreamPreAndPostImages;\n await this.db.command(command);\n }\n}\n\nexport class MongoInspectionExecutor implements MongoInspectionCommandVisitor<Promise<Document[]>> {\n constructor(private readonly db: Db) {}\n\n async listIndexes(cmd: ListIndexesCommand): Promise<Document[]> {\n try {\n return await this.db.collection(cmd.collection).listIndexes().toArray();\n } catch (error: unknown) {\n if (error instanceof MongoServerError && error.code === 26) {\n return [];\n }\n throw error;\n }\n }\n\n async listCollections(_cmd: ListCollectionsCommand): Promise<Document[]> {\n return this.db.listCollections().toArray();\n }\n}\n","import type { MongoIndexKey, MongoIndexKeyDirection } from '@prisma-next/mongo-contract';\nimport {\n MongoSchemaCollection,\n MongoSchemaCollectionOptions,\n MongoSchemaIndex,\n MongoSchemaIR,\n MongoSchemaValidator,\n} from '@prisma-next/mongo-schema-ir';\nimport type { Db, Document } from 'mongodb';\n\nconst PRISMA_MIGRATIONS_COLLECTION = '_prisma_migrations';\n\nfunction parseIndexKeys(keySpec: Record<string, unknown>): MongoIndexKey[] {\n const keys: MongoIndexKey[] = [];\n for (const [field, direction] of Object.entries(keySpec)) {\n keys.push({ field, direction: direction as MongoIndexKeyDirection });\n }\n return keys;\n}\n\nfunction isDefaultIdIndex(doc: Document): boolean {\n const key = doc['key'] as Record<string, unknown> | undefined;\n if (!key) return false;\n const entries = Object.entries(key);\n return entries.length === 1 && entries[0]?.[0] === '_id' && entries[0]?.[1] === 1;\n}\n\nfunction parseIndex(doc: Document): MongoSchemaIndex {\n const keySpec = doc['key'] as Record<string, unknown>;\n return new MongoSchemaIndex({\n keys: parseIndexKeys(keySpec),\n unique: doc['unique'] as boolean | undefined,\n sparse: doc['sparse'] as boolean | undefined,\n expireAfterSeconds: doc['expireAfterSeconds'] as number | undefined,\n partialFilterExpression: doc['partialFilterExpression'] as Record<string, unknown> | undefined,\n wildcardProjection: doc['wildcardProjection'] as Record<string, 0 | 1> | undefined,\n collation: doc['collation'] as Record<string, unknown> | undefined,\n weights: doc['weights'] as Record<string, number> | undefined,\n default_language: doc['default_language'] as string | undefined,\n language_override: doc['language_override'] as string | undefined,\n });\n}\n\nfunction parseValidator(options: Document): MongoSchemaValidator | undefined {\n const validator = options['validator'] as Record<string, unknown> | undefined;\n if (!validator) return undefined;\n\n const jsonSchema = validator['$jsonSchema'] as Record<string, unknown> | undefined;\n if (!jsonSchema) return undefined;\n\n return new MongoSchemaValidator({\n jsonSchema,\n validationLevel: (options['validationLevel'] as 'strict' | 'moderate') ?? 'strict',\n validationAction: (options['validationAction'] as 'error' | 'warn') ?? 'error',\n });\n}\n\nfunction parseCollectionOptions(info: Document): MongoSchemaCollectionOptions | undefined {\n const options = info['options'] as Record<string, unknown> | undefined;\n if (!options) return undefined;\n\n const capped = options['capped'] as boolean | undefined;\n const size = options['size'] as number | undefined;\n const max = options['max'] as number | undefined;\n const timeseries = options['timeseries'] as\n | { timeField: string; metaField?: string; granularity?: 'seconds' | 'minutes' | 'hours' }\n | undefined;\n const collation = options['collation'] as Record<string, unknown> | undefined;\n const changeStreamPreAndPostImages = options['changeStreamPreAndPostImages'] as\n | { enabled: boolean }\n | undefined;\n const clusteredIndex = options['clusteredIndex'] as { name?: string } | undefined;\n\n const hasMeaningfulOptions =\n capped || timeseries || collation || changeStreamPreAndPostImages || clusteredIndex;\n if (!hasMeaningfulOptions) return undefined;\n\n return new MongoSchemaCollectionOptions({\n ...(capped ? { capped: { size: size ?? 0, ...(max != null ? { max } : {}) } } : {}),\n ...(timeseries ? { timeseries } : {}),\n ...(collation ? { collation } : {}),\n ...(changeStreamPreAndPostImages ? { changeStreamPreAndPostImages } : {}),\n ...(clusteredIndex ? { clusteredIndex } : {}),\n });\n}\n\nexport async function introspectSchema(db: Db): Promise<MongoSchemaIR> {\n const collectionInfos = await db.listCollections().toArray();\n\n const collections: MongoSchemaCollection[] = [];\n\n for (const info of collectionInfos) {\n const name = info['name'] as string;\n const type = info['type'] as string | undefined;\n\n if (name === PRISMA_MIGRATIONS_COLLECTION) continue;\n if (name.startsWith('system.')) continue;\n if (type === 'view') continue;\n\n const indexDocs = await db.collection(name).listIndexes().toArray();\n const indexes = indexDocs.filter((doc) => !isDefaultIdIndex(doc)).map(parseIndex);\n\n const infoOptions = 'options' in info ? (info['options'] as Record<string, unknown>) : {};\n const validator = parseValidator(infoOptions);\n const options = parseCollectionOptions(info);\n\n collections.push(\n new MongoSchemaCollection({\n name,\n indexes,\n ...(validator ? { validator } : {}),\n ...(options ? { options } : {}),\n }),\n );\n }\n\n return new MongoSchemaIR(collections);\n}\n","import type { ControlDriverInstance } from '@prisma-next/framework-components/control';\nimport type { Db, MongoClient } from 'mongodb';\n\nexport interface MongoControlDriverInstance extends ControlDriverInstance<'mongo', 'mongo'> {\n readonly db: Db;\n}\n\nclass MongoControlDriverImpl implements MongoControlDriverInstance {\n readonly familyId = 'mongo' as const;\n readonly targetId = 'mongo' as const;\n readonly db: Db;\n readonly #client: MongoClient;\n\n constructor(db: Db, client: MongoClient) {\n this.db = db;\n this.#client = client;\n }\n\n query(): Promise<never> {\n throw new Error('MongoDB control driver does not support SQL queries');\n }\n\n async close(): Promise<void> {\n await this.#client.close();\n }\n}\n\nexport function createMongoControlDriver(db: Db, client: MongoClient): MongoControlDriverInstance {\n return new MongoControlDriverImpl(db, client);\n}\n","import type {\n ControlDriverInstance,\n ControlFamilyInstance,\n} from '@prisma-next/framework-components/control';\nimport type { MongoDriver } from '@prisma-next/mongo-lowering';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport {\n initMarker,\n type MongoRunnerDependencies,\n readMarker,\n updateMarker,\n writeLedgerEntry,\n} from '@prisma-next/target-mongo/control';\nimport type { Db } from 'mongodb';\nimport { createMongoAdapter } from '../mongo-adapter';\nimport { MongoCommandExecutor, MongoInspectionExecutor } from './command-executor';\n\nexport function extractDb(driver: ControlDriverInstance<'mongo', 'mongo'>): Db {\n const mongoDriver = driver as ControlDriverInstance<'mongo', 'mongo'> & { db?: Db };\n if (!mongoDriver.db) {\n throw new Error(\n 'Mongo control driver does not expose a db property. ' +\n 'Use mongoControlDriver.create() from `@prisma-next/driver-mongo/control`.',\n );\n }\n return mongoDriver.db;\n}\n\nexport function createMongoRunnerDeps(\n controlDriver: ControlDriverInstance<'mongo', 'mongo'>,\n driver: MongoDriver,\n family: ControlFamilyInstance<'mongo', MongoSchemaIR>,\n): MongoRunnerDependencies {\n const db = extractDb(controlDriver);\n return {\n commandExecutor: new MongoCommandExecutor(db),\n inspectionExecutor: new MongoInspectionExecutor(db),\n adapter: createMongoAdapter(),\n driver,\n markerOps: {\n readMarker: () => readMarker(db),\n initMarker: (dest) => initMarker(db, dest),\n updateMarker: (expectedFrom, dest) => updateMarker(db, expectedFrom, dest),\n writeLedgerEntry: (entry) => writeLedgerEntry(db, entry),\n },\n introspectSchema: () => family.introspect({ driver: controlDriver }),\n };\n}\n","import type { ControlAdapterDescriptor } from '@prisma-next/framework-components/control';\n\nexport { MongoCommandExecutor, MongoInspectionExecutor } from '../core/command-executor';\nexport { introspectSchema } from '../core/introspect-schema';\nexport {\n createMongoControlDriver,\n type MongoControlDriverInstance,\n} from '../core/mongo-control-driver';\nexport { createMongoRunnerDeps, extractDb } from '../core/runner-deps';\n\nimport { mongoStandardCodecs } from '../core/codecs';\n\nconst mongoAdapterDescriptor: ControlAdapterDescriptor<'mongo', 'mongo'> = {\n kind: 'adapter',\n id: 'mongo',\n familyId: 'mongo',\n targetId: 'mongo',\n version: '0.0.1',\n scalarTypeDescriptors: new Map([\n ['String', 'mongo/string@1'],\n ['Int', 'mongo/int32@1'],\n ['Boolean', 'mongo/bool@1'],\n ['DateTime', 'mongo/date@1'],\n ['ObjectId', 'mongo/objectId@1'],\n ['Float', 'mongo/double@1'],\n ]),\n types: {\n codecTypes: {\n codecInstances: [...mongoStandardCodecs],\n import: {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'CodecTypes',\n alias: 'MongoCodecTypes',\n },\n typeImports: [\n {\n package: '@prisma-next/adapter-mongo/codec-types',\n named: 'Vector',\n alias: 'Vector',\n },\n ],\n },\n },\n create(_stack) {\n return { familyId: 'mongo' as const, targetId: 'mongo' as const };\n },\n};\n\nexport default mongoAdapterDescriptor;\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -3,29 +3,35 @@ import { Document } from "@prisma-next/mongo-value";
3
3
  import { MongoCodecRegistry } from "@prisma-next/mongo-codec";
4
4
  import { MongoAdapter } from "@prisma-next/mongo-lowering";
5
5
  import { OperationDescriptor } from "@prisma-next/operations";
6
+ import { CodecCallContext } from "@prisma-next/framework-components/codec";
6
7
 
7
8
  //#region src/core/operations.d.ts
8
9
  declare const mongoVectorNearOperation: Readonly<{
9
10
  method: "near";
10
- args: {
11
+ self: {
11
12
  codecId: "mongo/vector@1";
12
- nullable: boolean;
13
- }[];
14
- returns: {
15
- codecId: "mongo/int32@1";
16
- nullable: boolean;
17
13
  };
14
+ impl: () => never;
18
15
  }>;
19
16
  declare const mongoVectorOperationDescriptors: readonly OperationDescriptor[];
20
17
  //#endregion
21
18
  //#region src/lowering.d.ts
22
19
  declare function lowerAggExpr(expr: MongoAggExpr): unknown;
23
- declare function lowerFilter(filter: MongoFilterExpr): Document;
24
- declare function lowerStage(stage: MongoPipelineStage): Record<string, unknown>;
25
- declare function lowerPipeline(stages: ReadonlyArray<MongoPipelineStage>): Array<Record<string, unknown>>;
20
+ declare function lowerFilter(filter: MongoFilterExpr, codecs: MongoCodecRegistry, ctx: CodecCallContext): Promise<Document>;
21
+ declare function lowerStage(stage: MongoPipelineStage, codecs: MongoCodecRegistry, ctx: CodecCallContext): Promise<Record<string, unknown>>;
22
+ declare function lowerPipeline(stages: ReadonlyArray<MongoPipelineStage>, codecs: MongoCodecRegistry, ctx: CodecCallContext): Promise<Array<Record<string, unknown>>>;
26
23
  //#endregion
27
24
  //#region src/mongo-adapter.d.ts
28
- declare function createMongoAdapter(codecs?: MongoCodecRegistry): MongoAdapter;
25
+ /**
26
+ * Construct a Mongo adapter with the standard wire-type codecs registered
27
+ * for encode-side dispatch (`MongoParamRef.codecId` lookups).
28
+ *
29
+ * The runtime-side codec registry the runtime decodes against is composed
30
+ * separately by `createMongoExecutionContext`. This factory exists for
31
+ * direct adapter use (the runtime descriptor's `create(stack)` calls
32
+ * through it). User code should compose a stack/context instead.
33
+ */
34
+ declare function createMongoAdapter(): MongoAdapter;
29
35
  //#endregion
30
36
  export { createMongoAdapter, lowerAggExpr, lowerFilter, lowerPipeline, lowerStage, mongoVectorNearOperation, mongoVectorOperationDescriptors };
31
37
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/operations.ts","../src/lowering.ts","../src/mongo-adapter.ts"],"sourcesContent":[],"mappings":";;;;;;;cAGa,0BAAwB;;;;;;EAAxB,OAAA,EAAA;IAMA,OAAA,EAAA,eAAA;;;;AC6HG,cD7HH,+BC6HkC,EAAA,SD7HQ,mBC6HR,EAAA;;;iBAA/B,YAAA,OAAmB;iBAInB,WAAA,SAAoB,kBAAkB;iBA8DtC,UAAA,QAAkB,qBAAqB;iBAqMvC,aAAA,SACN,cAAc,sBACrB,MAAM;;;iBChPO,kBAAA,UAA4B,qBAAqB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/operations.ts","../src/lowering.ts","../src/mongo-adapter.ts"],"sourcesContent":[],"mappings":";;;;;;;;cAGa,0BAAwB;;;;;;;AAAxB,cAMA,+BANwB,EAAA,SAMkB,mBANlB,EAAA;;;iBCqIrB,YAAA,OAAmB;iBAIb,WAAA,SACZ,yBACA,yBACH,mBACJ,QAAQ;iBA8DW,UAAA,QACb,4BACC,yBACH,mBACJ,QAAQ;iBAsNW,aAAA,SACZ,cAAc,6BACd,yBACH,mBACJ,QAAQ,MAAM;;;;;;;;;ADzajB;AAMA;;iBE+JgB,kBAAA,CAAA,GAAsB"}
package/dist/index.mjs CHANGED
@@ -1,16 +1,10 @@
1
- import { d as lowerPipeline, f as lowerStage, l as lowerAggExpr, m as MONGO_VECTOR_CODEC_ID, p as MONGO_INT32_CODEC_ID, t as createMongoAdapter, u as lowerFilter } from "./mongo-adapter-aVo8aZrf.mjs";
1
+ import { a as lowerFilter, c as MONGO_VECTOR_CODEC_ID, i as lowerAggExpr, o as lowerPipeline, s as lowerStage, t as createMongoAdapter } from "./mongo-adapter-ByNtvoHK.mjs";
2
2
 
3
3
  //#region src/core/operations.ts
4
4
  const mongoVectorNearOperation = Object.freeze({
5
5
  method: "near",
6
- args: [{
7
- codecId: MONGO_VECTOR_CODEC_ID,
8
- nullable: false
9
- }],
10
- returns: {
11
- codecId: MONGO_INT32_CODEC_ID,
12
- nullable: false
13
- }
6
+ self: { codecId: MONGO_VECTOR_CODEC_ID },
7
+ impl: () => void 0
14
8
  });
15
9
  const mongoVectorOperationDescriptors = [mongoVectorNearOperation];
16
10
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["mongoVectorOperationDescriptors: readonly OperationDescriptor[]"],"sources":["../src/core/operations.ts"],"sourcesContent":["import type { OperationDescriptor } from '@prisma-next/operations';\nimport { MONGO_INT32_CODEC_ID, MONGO_VECTOR_CODEC_ID } from './codec-ids';\n\nexport const mongoVectorNearOperation = Object.freeze({\n method: 'near',\n args: [{ codecId: MONGO_VECTOR_CODEC_ID, nullable: false }],\n returns: { codecId: MONGO_INT32_CODEC_ID, nullable: false },\n}) satisfies OperationDescriptor;\n\nexport const mongoVectorOperationDescriptors: readonly OperationDescriptor[] = [\n mongoVectorNearOperation,\n];\n"],"mappings":";;;AAGA,MAAa,2BAA2B,OAAO,OAAO;CACpD,QAAQ;CACR,MAAM,CAAC;EAAE,SAAS;EAAuB,UAAU;EAAO,CAAC;CAC3D,SAAS;EAAE,SAAS;EAAsB,UAAU;EAAO;CAC5D,CAAC;AAEF,MAAaA,kCAAkE,CAC7E,yBACD"}
1
+ {"version":3,"file":"index.mjs","names":["mongoVectorOperationDescriptors: readonly OperationDescriptor[]"],"sources":["../src/core/operations.ts"],"sourcesContent":["import type { OperationDescriptor } from '@prisma-next/operations';\nimport { MONGO_VECTOR_CODEC_ID } from './codec-ids';\n\nexport const mongoVectorNearOperation = Object.freeze({\n method: 'near',\n self: { codecId: MONGO_VECTOR_CODEC_ID },\n impl: () => undefined as never,\n}) satisfies OperationDescriptor;\n\nexport const mongoVectorOperationDescriptors: readonly OperationDescriptor[] = [\n mongoVectorNearOperation,\n];\n"],"mappings":";;;AAGA,MAAa,2BAA2B,OAAO,OAAO;CACpD,QAAQ;CACR,MAAM,EAAE,SAAS,uBAAuB;CACxC,YAAY;CACb,CAAC;AAEF,MAAaA,kCAAkE,CAC7E,yBACD"}
@@ -1,7 +1,8 @@
1
1
  import { isExprArray, isRecordArgs } from "@prisma-next/mongo-query-ast/execution";
2
+ import { checkAborted, raceAgainstAbort, runtimeError } from "@prisma-next/framework-components/runtime";
2
3
  import { MongoParamRef } from "@prisma-next/mongo-value";
3
- import { createMongoCodecRegistry, mongoCodec } from "@prisma-next/mongo-codec";
4
4
  import { AggregateWireCommand, DeleteManyWireCommand, DeleteOneWireCommand, FindOneAndDeleteWireCommand, FindOneAndUpdateWireCommand, InsertManyWireCommand, InsertOneWireCommand, UpdateManyWireCommand, UpdateOneWireCommand } from "@prisma-next/mongo-wire";
5
+ import { createMongoCodecRegistry, mongoCodec } from "@prisma-next/mongo-codec";
5
6
  import { ObjectId } from "mongodb";
6
7
 
7
8
  //#region src/core/codec-ids.ts
@@ -15,21 +16,80 @@ const MONGO_VECTOR_CODEC_ID = "mongo/vector@1";
15
16
 
16
17
  //#endregion
17
18
  //#region src/resolve-value.ts
18
- function resolveValue(value, codecs) {
19
+ /**
20
+ * Resolves a `MongoValue` (which may contain `MongoParamRef` leaves) into the
21
+ * driver-ready wire shape. When a leaf has a `codecId` and the registry has a
22
+ * codec for it, the codec's async `encode` is awaited so codecs may perform
23
+ * asynchronous work (e.g. lookups, key derivations).
24
+ *
25
+ * Object/array nodes dispatch their child resolutions concurrently via
26
+ * `Promise.all` so independent leaves encode in parallel.
27
+ *
28
+ * Codec encode failures are wrapped in a `RUNTIME.ENCODE_FAILED` envelope
29
+ * (mirroring SQL's `wrapEncodeFailure` shape) with `{ label, codec }` details
30
+ * and the original error attached on `cause`. An already-wrapped envelope is
31
+ * re-thrown verbatim so nested resolvers don't double-wrap.
32
+ *
33
+ * `ctx: CodecCallContext` is forwarded verbatim to every
34
+ * `codec.encode(value, ctx)` call. The same `ctx` reference is also passed
35
+ * to nested `resolveValue` invocations so codec authors observe **signal
36
+ * identity** across the entire recursive walk for one `runtime.execute()`.
37
+ *
38
+ * Abort observation (only when `ctx.signal` is provided):
39
+ *
40
+ * - **Already-aborted at entry** — every recursive call pre-checks
41
+ * `ctx.signal.aborted` and short-circuits with
42
+ * `RUNTIME.ABORTED { phase: 'encode' }` before any codec is invoked.
43
+ * - **Mid-flight abort** — each per-level `Promise.all` races against the
44
+ * signal via `raceAgainstAbort`. The runtime returns
45
+ * `RUNTIME.ABORTED { phase: 'encode' }` promptly even if codec bodies
46
+ * ignore the signal; in-flight bodies run to completion in the background
47
+ * (cooperative cancellation, see ADR 204).
48
+ * - `RUNTIME.ENCODE_FAILED` envelopes thrown by a codec body before the
49
+ * runtime sees the abort pass through unchanged (AC-ERR4).
50
+ */
51
+ async function resolveValue(value, codecs, ctx) {
52
+ checkAborted(ctx, "encode");
53
+ const signal = ctx.signal;
19
54
  if (value instanceof MongoParamRef) {
20
- if (value.codecId && codecs) {
55
+ if (value.codecId) {
21
56
  const codec = codecs.get(value.codecId);
22
- if (codec?.encode) return codec.encode(value.value);
57
+ if (codec?.encode) try {
58
+ return await raceAgainstAbort(codec.encode(value.value, ctx), signal, "encode");
59
+ } catch (error) {
60
+ wrapEncodeFailure(error, value, codec.id);
61
+ }
23
62
  }
24
63
  return value.value;
25
64
  }
26
65
  if (value === null || typeof value !== "object") return value;
27
66
  if (value instanceof Date) return value;
28
- if (Array.isArray(value)) return value.map((v) => resolveValue(v, codecs));
67
+ if (Array.isArray(value)) return raceAgainstAbort(Promise.all(value.map((v) => resolveValue(v, codecs, ctx))), signal, "encode");
68
+ const entries = Object.entries(value);
69
+ const resolved = await raceAgainstAbort(Promise.all(entries.map(([, val]) => resolveValue(val, codecs, ctx))), signal, "encode");
29
70
  const result = {};
30
- for (const [key, val] of Object.entries(value)) result[key] = resolveValue(val, codecs);
71
+ for (let i = 0; i < entries.length; i++) {
72
+ const entry = entries[i];
73
+ if (entry) result[entry[0]] = resolved[i];
74
+ }
31
75
  return result;
32
76
  }
77
+ function paramRefLabel(ref, codecId) {
78
+ return ref.name ?? codecId;
79
+ }
80
+ function isAlreadyEncodeFailure(error) {
81
+ return error instanceof Error && "code" in error && error.code === "RUNTIME.ENCODE_FAILED";
82
+ }
83
+ function wrapEncodeFailure(error, ref, codecId) {
84
+ if (isAlreadyEncodeFailure(error)) throw error;
85
+ const label = paramRefLabel(ref, codecId);
86
+ const wrapped = runtimeError("RUNTIME.ENCODE_FAILED", `Failed to encode parameter ${label} with codec '${codecId}': ${error instanceof Error ? error.message : String(error)}`, {
87
+ label,
88
+ codec: codecId
89
+ });
90
+ wrapped.cause = error;
91
+ throw wrapped;
92
+ }
33
93
 
34
94
  //#endregion
35
95
  //#region src/lowering.ts
@@ -110,12 +170,12 @@ function needsLiteralWrap(value) {
110
170
  function lowerAggExpr(expr) {
111
171
  return expr.accept(aggExprLoweringVisitor);
112
172
  }
113
- function lowerFilter(filter) {
173
+ async function lowerFilter(filter, codecs, ctx) {
114
174
  switch (filter.kind) {
115
- case "field": return { [filter.field]: { [filter.op]: resolveValue(filter.value) } };
116
- case "and": return { $and: filter.exprs.map((e) => lowerFilter(e)) };
117
- case "or": return { $or: filter.exprs.map((e) => lowerFilter(e)) };
118
- case "not": return { $nor: [lowerFilter(filter.expr)] };
175
+ case "field": return { [filter.field]: { [filter.op]: await resolveValue(filter.value, codecs, ctx) } };
176
+ case "and": return { $and: await Promise.all(filter.exprs.map((e) => lowerFilter(e, codecs, ctx))) };
177
+ case "or": return { $or: await Promise.all(filter.exprs.map((e) => lowerFilter(e, codecs, ctx))) };
178
+ case "not": return { $nor: [await lowerFilter(filter.expr, codecs, ctx)] };
119
179
  case "exists": return { [filter.field]: { $exists: filter.exists } };
120
180
  case "expr": return { $expr: lowerAggExpr(filter.aggExpr) };
121
181
  default: {
@@ -149,9 +209,9 @@ function lowerWindowField(wf) {
149
209
  if (wf.window) result["window"] = { ...wf.window };
150
210
  return result;
151
211
  }
152
- function lowerStage(stage) {
212
+ async function lowerStage(stage, codecs, ctx) {
153
213
  switch (stage.kind) {
154
- case "match": return { $match: lowerFilter(stage.filter) };
214
+ case "match": return { $match: await lowerFilter(stage.filter, codecs, ctx) };
155
215
  case "project": {
156
216
  const projection = {};
157
217
  for (const [key, val] of Object.entries(stage.projection)) projection[key] = lowerProjectionValue(val);
@@ -167,7 +227,7 @@ function lowerStage(stage) {
167
227
  };
168
228
  if (stage.localField !== void 0) lookup["localField"] = stage.localField;
169
229
  if (stage.foreignField !== void 0) lookup["foreignField"] = stage.foreignField;
170
- if (stage.pipeline) lookup["pipeline"] = stage.pipeline.map((s) => lowerStage(s));
230
+ if (stage.pipeline) lookup["pipeline"] = await Promise.all(stage.pipeline.map((s) => lowerStage(s, codecs, ctx)));
171
231
  if (stage.let_) lookup["let"] = lowerExprRecord(stage.let_);
172
232
  return { $lookup: lookup };
173
233
  }
@@ -196,7 +256,7 @@ function lowerStage(stage) {
196
256
  } : stage.collection };
197
257
  case "unionWith": {
198
258
  const unionWith = { coll: stage.collection };
199
- if (stage.pipeline) unionWith["pipeline"] = stage.pipeline.map((s) => lowerStage(s));
259
+ if (stage.pipeline) unionWith["pipeline"] = await Promise.all(stage.pipeline.map((s) => lowerStage(s, codecs, ctx)));
200
260
  return { $unionWith: unionWith };
201
261
  }
202
262
  case "bucket": {
@@ -225,15 +285,20 @@ function lowerStage(stage) {
225
285
  if (stage.spherical !== void 0) geoNear["spherical"] = stage.spherical;
226
286
  if (stage.maxDistance !== void 0) geoNear["maxDistance"] = stage.maxDistance;
227
287
  if (stage.minDistance !== void 0) geoNear["minDistance"] = stage.minDistance;
228
- if (stage.query) geoNear["query"] = lowerFilter(stage.query);
288
+ if (stage.query) geoNear["query"] = await lowerFilter(stage.query, codecs, ctx);
229
289
  if (stage.key !== void 0) geoNear["key"] = stage.key;
230
290
  if (stage.distanceMultiplier !== void 0) geoNear["distanceMultiplier"] = stage.distanceMultiplier;
231
291
  if (stage.includeLocs !== void 0) geoNear["includeLocs"] = stage.includeLocs;
232
292
  return { $geoNear: geoNear };
233
293
  }
234
294
  case "facet": {
295
+ const facetEntries = Object.entries(stage.facets);
296
+ const facetPipelines = await Promise.all(facetEntries.map(([, pipeline]) => Promise.all(pipeline.map((s) => lowerStage(s, codecs, ctx)))));
235
297
  const facet = {};
236
- for (const [key, pipeline] of Object.entries(stage.facets)) facet[key] = pipeline.map((s) => lowerStage(s));
298
+ for (let i = 0; i < facetEntries.length; i++) {
299
+ const entry = facetEntries[i];
300
+ if (entry) facet[entry[0]] = facetPipelines[i];
301
+ }
237
302
  return { $facet: facet };
238
303
  }
239
304
  case "graphLookup": {
@@ -246,13 +311,13 @@ function lowerStage(stage) {
246
311
  };
247
312
  if (stage.maxDepth !== void 0) graphLookup["maxDepth"] = stage.maxDepth;
248
313
  if (stage.depthField !== void 0) graphLookup["depthField"] = stage.depthField;
249
- if (stage.restrictSearchWithMatch) graphLookup["restrictSearchWithMatch"] = lowerFilter(stage.restrictSearchWithMatch);
314
+ if (stage.restrictSearchWithMatch) graphLookup["restrictSearchWithMatch"] = await lowerFilter(stage.restrictSearchWithMatch, codecs, ctx);
250
315
  return { $graphLookup: graphLookup };
251
316
  }
252
317
  case "merge": {
253
318
  const merge = { into: stage.into };
254
319
  if (stage.on !== void 0) merge["on"] = stage.on;
255
- if (stage.whenMatched !== void 0) merge["whenMatched"] = Array.isArray(stage.whenMatched) ? stage.whenMatched.map((s) => lowerStage(s)) : stage.whenMatched;
320
+ if (stage.whenMatched !== void 0) merge["whenMatched"] = Array.isArray(stage.whenMatched) ? await Promise.all(stage.whenMatched.map((s) => lowerStage(s, codecs, ctx))) : stage.whenMatched;
256
321
  if (stage.whenNotMatched !== void 0) merge["whenNotMatched"] = stage.whenNotMatched;
257
322
  return { $merge: merge };
258
323
  }
@@ -315,8 +380,8 @@ function lowerStage(stage) {
315
380
  }
316
381
  }
317
382
  }
318
- function lowerPipeline(stages) {
319
- return stages.map(lowerStage);
383
+ async function lowerPipeline(stages, codecs, ctx) {
384
+ return Promise.all(stages.map((s) => lowerStage(s, codecs, ctx)));
320
385
  }
321
386
 
322
387
  //#endregion
@@ -373,7 +438,12 @@ const mongoDateCodec = mongoCodec({
373
438
  targetTypes: ["date"],
374
439
  traits: ["equality", "order"],
375
440
  decode: (wire) => wire,
376
- encode: (value) => value
441
+ encode: (value) => value,
442
+ encodeJson: (value) => value.toISOString(),
443
+ decodeJson: (json) => {
444
+ if (typeof json !== "string") throw new Error("expected ISO date string");
445
+ return new Date(json);
446
+ }
377
447
  });
378
448
  const mongoVectorCodec = mongoCodec({
379
449
  typeId: MONGO_VECTOR_CODEC_ID,
@@ -388,6 +458,36 @@ const mongoVectorCodec = mongoCodec({
388
458
  return `Vector<${length}>`;
389
459
  }
390
460
  });
461
+ /**
462
+ * The canonical set of Mongo wire-type codecs.
463
+ *
464
+ * Single source of truth for both control- and runtime-plane adapter
465
+ * descriptors. Don't duplicate this list — import it.
466
+ */
467
+ const mongoStandardCodecs = [
468
+ mongoObjectIdCodec,
469
+ mongoStringCodec,
470
+ mongoDoubleCodec,
471
+ mongoInt32Codec,
472
+ mongoBooleanCodec,
473
+ mongoDateCodec,
474
+ mongoVectorCodec
475
+ ];
476
+ /**
477
+ * Build a {@link MongoCodecRegistry} preloaded with the standard Mongo
478
+ * wire-type codecs.
479
+ *
480
+ * Single point of truth for adapter-side codec construction: used by the
481
+ * legacy synchronous `createMongoAdapter()` factory and by the runtime
482
+ * adapter descriptor's `codecs()` getter. Userland code obtains a registry
483
+ * via the framework's execution-stack composition (see
484
+ * `createMongoExecutionContext`) instead of calling this directly.
485
+ */
486
+ function buildStandardCodecRegistry() {
487
+ const registry = createMongoCodecRegistry();
488
+ for (const codec of mongoStandardCodecs) registry.register(codec);
489
+ return registry;
490
+ }
391
491
 
392
492
  //#endregion
393
493
  //#region src/mongo-adapter.ts
@@ -399,27 +499,41 @@ var MongoAdapterImpl = class {
399
499
  constructor(codecs) {
400
500
  this.#codecs = codecs;
401
501
  }
402
- #resolveDocument(expr) {
502
+ async #resolveDocument(expr, ctx) {
503
+ const entries = Object.entries(expr);
504
+ const resolved = await Promise.all(entries.map(([, val]) => resolveValue(val, this.#codecs, ctx)));
403
505
  const result = {};
404
- for (const [key, val] of Object.entries(expr)) result[key] = resolveValue(val, this.#codecs);
506
+ for (let i = 0; i < entries.length; i++) {
507
+ const entry = entries[i];
508
+ if (entry) result[entry[0]] = resolved[i];
509
+ }
405
510
  return result;
406
511
  }
407
- #lowerUpdate(update) {
408
- if (isUpdatePipeline(update)) return update.map((stage) => lowerStage(stage));
409
- return this.#resolveDocument(update);
512
+ async #lowerUpdate(update, ctx) {
513
+ if (isUpdatePipeline(update)) return Promise.all(update.map((stage) => lowerStage(stage, this.#codecs, ctx)));
514
+ return this.#resolveDocument(update, ctx);
410
515
  }
411
- lower(plan) {
516
+ async lower(plan, ctx) {
412
517
  const { command } = plan;
413
518
  switch (command.kind) {
414
- case "insertOne": return new InsertOneWireCommand(command.collection, this.#resolveDocument(command.document));
415
- case "updateOne": return new UpdateOneWireCommand(command.collection, lowerFilter(command.filter), this.#lowerUpdate(command.update), command.upsert);
416
- case "insertMany": return new InsertManyWireCommand(command.collection, command.documents.map((doc) => this.#resolveDocument(doc)));
417
- case "updateMany": return new UpdateManyWireCommand(command.collection, lowerFilter(command.filter), this.#lowerUpdate(command.update), command.upsert);
418
- case "deleteOne": return new DeleteOneWireCommand(command.collection, lowerFilter(command.filter));
419
- case "deleteMany": return new DeleteManyWireCommand(command.collection, lowerFilter(command.filter));
420
- case "findOneAndUpdate": return new FindOneAndUpdateWireCommand(command.collection, lowerFilter(command.filter), this.#lowerUpdate(command.update), command.upsert, command.sort, command.returnDocument);
421
- case "findOneAndDelete": return new FindOneAndDeleteWireCommand(command.collection, lowerFilter(command.filter), command.sort);
422
- case "aggregate": return new AggregateWireCommand(command.collection, lowerPipeline(command.pipeline));
519
+ case "insertOne": return new InsertOneWireCommand(command.collection, await this.#resolveDocument(command.document, ctx));
520
+ case "updateOne": {
521
+ const [filter, update] = await Promise.all([lowerFilter(command.filter, this.#codecs, ctx), this.#lowerUpdate(command.update, ctx)]);
522
+ return new UpdateOneWireCommand(command.collection, filter, update, command.upsert);
523
+ }
524
+ case "insertMany": return new InsertManyWireCommand(command.collection, await Promise.all(command.documents.map((doc) => this.#resolveDocument(doc, ctx))));
525
+ case "updateMany": {
526
+ const [filter, update] = await Promise.all([lowerFilter(command.filter, this.#codecs, ctx), this.#lowerUpdate(command.update, ctx)]);
527
+ return new UpdateManyWireCommand(command.collection, filter, update, command.upsert);
528
+ }
529
+ case "deleteOne": return new DeleteOneWireCommand(command.collection, await lowerFilter(command.filter, this.#codecs, ctx));
530
+ case "deleteMany": return new DeleteManyWireCommand(command.collection, await lowerFilter(command.filter, this.#codecs, ctx));
531
+ case "findOneAndUpdate": {
532
+ const [filter, update] = await Promise.all([lowerFilter(command.filter, this.#codecs, ctx), this.#lowerUpdate(command.update, ctx)]);
533
+ return new FindOneAndUpdateWireCommand(command.collection, filter, update, command.upsert, command.sort, command.returnDocument);
534
+ }
535
+ case "findOneAndDelete": return new FindOneAndDeleteWireCommand(command.collection, await lowerFilter(command.filter, this.#codecs, ctx), command.sort);
536
+ case "aggregate": return new AggregateWireCommand(command.collection, await lowerPipeline(command.pipeline, this.#codecs, ctx));
423
537
  case "rawAggregate": return new AggregateWireCommand(command.collection, command.pipeline);
424
538
  case "rawInsertOne": return new InsertOneWireCommand(command.collection, command.document);
425
539
  case "rawInsertMany": return new InsertManyWireCommand(command.collection, command.documents);
@@ -436,23 +550,19 @@ var MongoAdapterImpl = class {
436
550
  }
437
551
  }
438
552
  };
439
- function defaultCodecRegistry() {
440
- const registry = createMongoCodecRegistry();
441
- for (const codec of [
442
- mongoObjectIdCodec,
443
- mongoStringCodec,
444
- mongoDoubleCodec,
445
- mongoInt32Codec,
446
- mongoBooleanCodec,
447
- mongoDateCodec,
448
- mongoVectorCodec
449
- ]) registry.register(codec);
450
- return registry;
451
- }
452
- function createMongoAdapter(codecs) {
453
- return new MongoAdapterImpl(codecs ?? defaultCodecRegistry());
553
+ /**
554
+ * Construct a Mongo adapter with the standard wire-type codecs registered
555
+ * for encode-side dispatch (`MongoParamRef.codecId` lookups).
556
+ *
557
+ * The runtime-side codec registry the runtime decodes against is composed
558
+ * separately by `createMongoExecutionContext`. This factory exists for
559
+ * direct adapter use (the runtime descriptor's `create(stack)` calls
560
+ * through it). User code should compose a stack/context instead.
561
+ */
562
+ function createMongoAdapter() {
563
+ return new MongoAdapterImpl(buildStandardCodecRegistry());
454
564
  }
455
565
 
456
566
  //#endregion
457
- export { mongoInt32Codec as a, mongoVectorCodec as c, lowerPipeline as d, lowerStage as f, mongoDoubleCodec as i, lowerAggExpr as l, MONGO_VECTOR_CODEC_ID as m, mongoBooleanCodec as n, mongoObjectIdCodec as o, MONGO_INT32_CODEC_ID as p, mongoDateCodec as r, mongoStringCodec as s, createMongoAdapter as t, lowerFilter as u };
458
- //# sourceMappingURL=mongo-adapter-aVo8aZrf.mjs.map
567
+ export { lowerFilter as a, MONGO_VECTOR_CODEC_ID as c, lowerAggExpr as i, buildStandardCodecRegistry as n, lowerPipeline as o, mongoStandardCodecs as r, lowerStage as s, createMongoAdapter as t };
568
+ //# sourceMappingURL=mongo-adapter-ByNtvoHK.mjs.map