@prisma-next/adapter-mongo 0.5.0-dev.4 → 0.5.0-dev.41
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 +4 -2
- package/dist/control.d.mts +2 -2
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +5 -12
- package/dist/control.mjs.map +1 -1
- package/dist/index.d.mts +16 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -9
- package/dist/index.mjs.map +1 -1
- package/dist/{mongo-adapter-aVo8aZrf.mjs → mongo-adapter-ByNtvoHK.mjs} +164 -54
- package/dist/mongo-adapter-ByNtvoHK.mjs.map +1 -0
- package/dist/runtime.d.mts +26 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +25 -0
- package/dist/runtime.mjs.map +1 -0
- package/package.json +20 -17
- package/src/core/codecs.ts +44 -1
- package/src/core/operations.ts +3 -3
- package/src/core/runner-deps.ts +7 -1
- package/src/exports/control.ts +2 -18
- package/src/exports/runtime.ts +57 -0
- package/src/lowering.ts +46 -17
- package/src/mongo-adapter.ts +78 -58
- package/src/resolve-value.ts +97 -6
- package/dist/mongo-adapter-aVo8aZrf.mjs.map +0 -1
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**:
|
|
8
|
-
- **Codec application**:
|
|
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
|
|
package/dist/control.d.mts
CHANGED
|
@@ -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'>;
|
package/dist/control.d.mts.map
CHANGED
|
@@ -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;;;
|
|
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 {
|
|
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",
|
package/dist/control.mjs.map
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/core/operations.ts","../src/lowering.ts","../src/mongo-adapter.ts"],"sourcesContent":[],"mappings":"
|
|
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 {
|
|
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
|
-
|
|
7
|
-
|
|
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
|
|
package/dist/index.mjs.map
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
|
55
|
+
if (value.codecId) {
|
|
21
56
|
const codec = codecs.get(value.codecId);
|
|
22
|
-
if (codec?.encode)
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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":
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
case "
|
|
420
|
-
case "
|
|
421
|
-
|
|
422
|
-
|
|
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
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
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 {
|
|
458
|
-
//# sourceMappingURL=mongo-adapter-
|
|
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
|