@prisma-next/family-mongo 0.5.0-dev.7 → 0.5.0-dev.71
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/dist/control.d.mts +3 -3
- package/dist/control.d.mts.map +1 -1
- package/dist/control.mjs +27 -8
- package/dist/control.mjs.map +1 -1
- package/dist/migration.d.mts +0 -1
- package/dist/migration.d.mts.map +1 -1
- package/dist/migration.mjs +1 -2
- package/dist/migration.mjs.map +1 -1
- package/dist/pack.d.mts.map +1 -1
- package/dist/pack.mjs +2 -3
- package/dist/pack.mjs.map +1 -1
- package/dist/schema-verify.mjs +1 -2
- package/package.json +18 -17
- package/src/core/control-instance.ts +57 -2
- package/src/core/mongo-target-descriptor.ts +1 -1
package/dist/control.d.mts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ControlFamilyDescriptor, ControlFamilyInstance, ControlStack, MigratableTargetDescriptor, SchemaViewCapable } from "@prisma-next/framework-components/control";
|
|
1
|
+
import { ControlFamilyDescriptor, ControlFamilyInstance, ControlStack, MigratableTargetDescriptor, OperationPreviewCapable, SchemaViewCapable } from "@prisma-next/framework-components/control";
|
|
2
2
|
import { Contract } from "@prisma-next/contract/types";
|
|
3
3
|
import { MongoSchemaIR } from "@prisma-next/mongo-schema-ir";
|
|
4
4
|
|
|
5
5
|
//#region src/core/control-instance.d.ts
|
|
6
|
-
interface MongoControlFamilyInstance extends ControlFamilyInstance<'mongo', MongoSchemaIR>, SchemaViewCapable<MongoSchemaIR
|
|
6
|
+
interface MongoControlFamilyInstance extends ControlFamilyInstance<'mongo', MongoSchemaIR>, SchemaViewCapable<MongoSchemaIR>, OperationPreviewCapable {
|
|
7
7
|
validateContract(contractJson: unknown): Contract;
|
|
8
8
|
}
|
|
9
9
|
declare function createMongoFamilyInstance(_controlStack: ControlStack): MongoControlFamilyInstance;
|
|
@@ -20,7 +20,7 @@ declare const mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoContr
|
|
|
20
20
|
* itself back to such a file; `MongoMigrationPlanner.emptyMigration()`
|
|
21
21
|
* returns the same shape for `migration new`. Users run the scaffolded
|
|
22
22
|
* `migration.ts` directly (via `node migration.ts`) to self-emit
|
|
23
|
-
* `ops.json` and attest the `
|
|
23
|
+
* `ops.json` and attest the `migrationHash`.
|
|
24
24
|
*/
|
|
25
25
|
declare const mongoTargetDescriptor: MigratableTargetDescriptor<'mongo', 'mongo', MongoControlFamilyInstance>;
|
|
26
26
|
//#endregion
|
package/dist/control.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-target-descriptor.ts"],"
|
|
1
|
+
{"version":3,"file":"control.d.mts","names":[],"sources":["../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-target-descriptor.ts"],"mappings":";;;;;UAoCiB,0BAAA,SACP,qBAAA,UAA+B,aAAA,GACrC,iBAAA,CAAkB,aAAA,GAClB,uBAAA;EACF,gBAAA,CAAiB,YAAA,YAAwB,QAAA;AAAA;AAAA,iBAgU3B,yBAAA,CAA0B,aAAA,EAAe,YAAA,GAAe,0BAAA;;;cCjV3D,qBAAA,EAAuB,uBAAA,UAAiC,0BAAA;;;;;;ADarE;;;;;;;cETa,qBAAA,EAAuB,0BAAA,mBAGlC,0BAAA"}
|
package/dist/control.mjs
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { mongoEmission } from "@prisma-next/mongo-emitter";
|
|
2
2
|
import { createMongoRunnerDeps, extractDb, introspectSchema } from "@prisma-next/adapter-mongo/control";
|
|
3
|
-
import { SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH } from "@prisma-next/framework-components/control";
|
|
3
|
+
import { APP_SPACE_ID, SchemaTreeNode, VERIFY_CODE_HASH_MISMATCH, VERIFY_CODE_MARKER_MISSING, VERIFY_CODE_TARGET_MISMATCH } from "@prisma-next/framework-components/control";
|
|
4
4
|
import { validateMongoContract } from "@prisma-next/mongo-contract";
|
|
5
|
-
import { MongoMigrationPlanner, MongoMigrationRunner, contractToMongoSchemaIR, initMarker, readMarker, updateMarker } from "@prisma-next/target-mongo/control";
|
|
5
|
+
import { MongoMigrationPlanner, MongoMigrationRunner, contractToMongoSchemaIR, formatMongoOperations, initMarker, readMarker, updateMarker } from "@prisma-next/target-mongo/control";
|
|
6
6
|
import { verifyMongoSchema } from "@prisma-next/target-mongo/schema-verify";
|
|
7
7
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
8
8
|
import { MongoDriverImpl } from "@prisma-next/driver-mongo";
|
|
9
9
|
import mongoTargetDescriptorMeta from "@prisma-next/target-mongo/pack";
|
|
10
|
-
|
|
11
10
|
//#region src/core/schema-to-view.ts
|
|
12
11
|
function mongoSchemaToView(schema) {
|
|
13
12
|
const collectionNodes = schema.collections.map((collection) => collectionToSchemaNode(collection.name, collection));
|
|
@@ -99,7 +98,6 @@ function collectionToSchemaNode(name, collection) {
|
|
|
99
98
|
...ifDefined("children", children.length > 0 ? children : void 0)
|
|
100
99
|
});
|
|
101
100
|
}
|
|
102
|
-
|
|
103
101
|
//#endregion
|
|
104
102
|
//#region src/core/control-instance.ts
|
|
105
103
|
function extractDb$1(driver) {
|
|
@@ -180,6 +178,14 @@ var MongoFamilyInstance = class {
|
|
|
180
178
|
}
|
|
181
179
|
});
|
|
182
180
|
}
|
|
181
|
+
schemaVerifyAgainstSchema(options) {
|
|
182
|
+
return verifyMongoSchema({
|
|
183
|
+
contract: validateMongoContract(options.contract).contract,
|
|
184
|
+
schema: options.schema,
|
|
185
|
+
strict: options.strict,
|
|
186
|
+
frameworkComponents: options.frameworkComponents
|
|
187
|
+
});
|
|
188
|
+
}
|
|
183
189
|
async sign(options) {
|
|
184
190
|
const { driver, contract: rawContract, contractPath, configPath } = options;
|
|
185
191
|
const startTime = Date.now();
|
|
@@ -240,14 +246,29 @@ var MongoFamilyInstance = class {
|
|
|
240
246
|
};
|
|
241
247
|
}
|
|
242
248
|
async readMarker(options) {
|
|
249
|
+
if (options.space !== APP_SPACE_ID) throw new Error(`Mongo target does not yet support per-space contract markers. readMarker was called with space="${options.space}", but only "${APP_SPACE_ID}" is supported. Per-space marker support is tracked separately for Mongo and is not part of the SQL-family contract-spaces work.`);
|
|
243
250
|
return readMarker(extractDb$1(options.driver));
|
|
244
251
|
}
|
|
252
|
+
async readAllMarkers(options) {
|
|
253
|
+
const appMarker = await this.readMarker({
|
|
254
|
+
...options,
|
|
255
|
+
space: APP_SPACE_ID
|
|
256
|
+
});
|
|
257
|
+
if (appMarker === null) return /* @__PURE__ */ new Map();
|
|
258
|
+
return new Map([[APP_SPACE_ID, appMarker]]);
|
|
259
|
+
}
|
|
245
260
|
async introspect(options) {
|
|
246
261
|
return introspectSchema(extractDb$1(options.driver));
|
|
247
262
|
}
|
|
248
263
|
toSchemaView(schema) {
|
|
249
264
|
return mongoSchemaToView(schema);
|
|
250
265
|
}
|
|
266
|
+
toOperationPreview(operations) {
|
|
267
|
+
return { statements: formatMongoOperations(operations).map((text) => ({
|
|
268
|
+
text,
|
|
269
|
+
language: "mongodb-shell"
|
|
270
|
+
})) };
|
|
271
|
+
}
|
|
251
272
|
};
|
|
252
273
|
function buildVerifyResult(opts) {
|
|
253
274
|
return {
|
|
@@ -276,7 +297,6 @@ function buildVerifyResult(opts) {
|
|
|
276
297
|
function createMongoFamilyInstance(_controlStack) {
|
|
277
298
|
return new MongoFamilyInstance();
|
|
278
299
|
}
|
|
279
|
-
|
|
280
300
|
//#endregion
|
|
281
301
|
//#region src/core/control-descriptor.ts
|
|
282
302
|
var MongoFamilyDescriptor = class {
|
|
@@ -290,7 +310,6 @@ var MongoFamilyDescriptor = class {
|
|
|
290
310
|
}
|
|
291
311
|
};
|
|
292
312
|
const mongoFamilyDescriptor = new MongoFamilyDescriptor();
|
|
293
|
-
|
|
294
313
|
//#endregion
|
|
295
314
|
//#region src/core/mongo-target-descriptor.ts
|
|
296
315
|
/**
|
|
@@ -301,7 +320,7 @@ const mongoFamilyDescriptor = new MongoFamilyDescriptor();
|
|
|
301
320
|
* itself back to such a file; `MongoMigrationPlanner.emptyMigration()`
|
|
302
321
|
* returns the same shape for `migration new`. Users run the scaffolded
|
|
303
322
|
* `migration.ts` directly (via `node migration.ts`) to self-emit
|
|
304
|
-
* `ops.json` and attest the `
|
|
323
|
+
* `ops.json` and attest the `migrationHash`.
|
|
305
324
|
*/
|
|
306
325
|
const mongoTargetDescriptor = {
|
|
307
326
|
...mongoTargetDescriptorMeta,
|
|
@@ -331,7 +350,7 @@ const mongoTargetDescriptor = {
|
|
|
331
350
|
};
|
|
332
351
|
}
|
|
333
352
|
};
|
|
334
|
-
|
|
335
353
|
//#endregion
|
|
336
354
|
export { createMongoFamilyInstance, mongoFamilyDescriptor, mongoTargetDescriptor };
|
|
355
|
+
|
|
337
356
|
//# sourceMappingURL=control.mjs.map
|
package/dist/control.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control.mjs","names":["children: SchemaTreeNode[]","options: string[]","validatorChildren: SchemaTreeNode[]","optLabels: string[]","extractDb","previousHashes: { storageHash?: string; profileHash?: string } | undefined","summary: string","mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance>","mongoTargetDescriptor: MigratableTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoControlFamilyInstance\n>","cachedDeps: MongoRunnerDependencies | undefined"],"sources":["../src/core/schema-to-view.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-target-descriptor.ts"],"sourcesContent":["import type { CoreSchemaView } from '@prisma-next/framework-components/control';\nimport { SchemaTreeNode } from '@prisma-next/framework-components/control';\nimport type { MongoSchemaCollection, MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\nexport function mongoSchemaToView(schema: MongoSchemaIR): CoreSchemaView {\n const collectionNodes = schema.collections.map((collection) =>\n collectionToSchemaNode(collection.name, collection),\n );\n\n return {\n root: new SchemaTreeNode({\n kind: 'root',\n id: 'mongo-schema',\n label: 'database',\n ...ifDefined('children', collectionNodes.length > 0 ? collectionNodes : undefined),\n }),\n };\n}\n\nfunction collectionToSchemaNode(name: string, collection: MongoSchemaCollection): SchemaTreeNode {\n const children: SchemaTreeNode[] = [];\n\n for (const index of collection.indexes) {\n const keysSummary = index.keys\n .map((k) => {\n if (k.direction === 1) return k.field;\n if (k.direction === -1) return `${k.field} desc`;\n return `${k.field} ${k.direction}`;\n })\n .join(', ');\n const prefix = index.unique ? 'unique index' : 'index';\n const options: string[] = [];\n if (index.sparse) options.push('sparse');\n if (index.expireAfterSeconds != null) options.push(`ttl: ${index.expireAfterSeconds}s`);\n if (index.partialFilterExpression) options.push('partial');\n const optsSuffix = options.length > 0 ? ` (${options.join(', ')})` : '';\n\n children.push(\n new SchemaTreeNode({\n kind: 'index',\n id: `index-${name}-${index.keys.map((k) => `${k.field}_${k.direction}`).join('_')}`,\n label: `${prefix} (${keysSummary})${optsSuffix}`,\n meta: {\n keys: index.keys,\n unique: index.unique,\n ...ifDefined('sparse', index.sparse || undefined),\n ...ifDefined('expireAfterSeconds', index.expireAfterSeconds ?? undefined),\n ...ifDefined('partialFilterExpression', index.partialFilterExpression ?? undefined),\n },\n }),\n );\n }\n\n if (collection.validator) {\n const validatorChildren: SchemaTreeNode[] = [];\n const jsonSchema = collection.validator.jsonSchema as Record<string, unknown>;\n const properties = jsonSchema['properties'] as\n | Record<string, Record<string, unknown>>\n | undefined;\n const required = new Set((jsonSchema['required'] as string[] | undefined) ?? []);\n\n if (properties) {\n for (const [propName, propDef] of Object.entries(properties)) {\n const bsonType = (propDef['bsonType'] as string) ?? 'unknown';\n const suffix = required.has(propName) ? ' (required)' : '';\n validatorChildren.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `field-${name}-${propName}`,\n label: `${propName}: ${bsonType}${suffix}`,\n }),\n );\n }\n }\n\n children.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `validator-${name}`,\n label: `validator (level: ${collection.validator.validationLevel}, action: ${collection.validator.validationAction})`,\n meta: {\n validationLevel: collection.validator.validationLevel,\n validationAction: collection.validator.validationAction,\n jsonSchema: collection.validator.jsonSchema,\n },\n ...ifDefined('children', validatorChildren.length > 0 ? validatorChildren : undefined),\n }),\n );\n }\n\n if (collection.options) {\n const opts = collection.options;\n const optLabels: string[] = [];\n if (opts.capped) optLabels.push('capped');\n if (opts.timeseries) optLabels.push('timeseries');\n if (opts.collation) optLabels.push('collation');\n if (opts.changeStreamPreAndPostImages) optLabels.push('changeStreamPreAndPostImages');\n if (opts.clusteredIndex) optLabels.push('clusteredIndex');\n\n if (optLabels.length > 0) {\n children.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `options-${name}`,\n label: `options (${optLabels.join(', ')})`,\n meta: {\n ...ifDefined('capped', opts.capped ?? undefined),\n ...ifDefined('timeseries', opts.timeseries ?? undefined),\n ...ifDefined('collation', opts.collation ?? undefined),\n ...ifDefined(\n 'changeStreamPreAndPostImages',\n opts.changeStreamPreAndPostImages ?? undefined,\n ),\n ...ifDefined('clusteredIndex', opts.clusteredIndex ?? undefined),\n },\n }),\n );\n }\n }\n\n return new SchemaTreeNode({\n kind: 'collection',\n id: `collection-${name}`,\n label: `collection ${name}`,\n ...ifDefined('children', children.length > 0 ? children : undefined),\n });\n}\n","import { introspectSchema } from '@prisma-next/adapter-mongo/control';\nimport type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n ControlStack,\n CoreSchemaView,\n SchemaViewCapable,\n SignDatabaseResult,\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n VERIFY_CODE_HASH_MISMATCH,\n VERIFY_CODE_MARKER_MISSING,\n VERIFY_CODE_TARGET_MISMATCH,\n} from '@prisma-next/framework-components/control';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport { validateMongoContract } from '@prisma-next/mongo-contract';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport { initMarker, readMarker, updateMarker } from '@prisma-next/target-mongo/control';\nimport { verifyMongoSchema } from '@prisma-next/target-mongo/schema-verify';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Db } from 'mongodb';\nimport { mongoSchemaToView } from './schema-to-view';\n\nexport interface MongoControlFamilyInstance\n extends ControlFamilyInstance<'mongo', MongoSchemaIR>,\n SchemaViewCapable<MongoSchemaIR> {\n validateContract(contractJson: unknown): Contract;\n}\n\nfunction extractDb(driver: ControlDriverInstance<'mongo', string>): Db {\n const mongoDriver = driver as ControlDriverInstance<'mongo', string> & { db?: Db };\n if (!mongoDriver.db) {\n throw new Error(\n 'Mongo control driver does not expose a db property. ' +\n 'Use createMongoControlDriver() from @prisma-next/adapter-mongo/control.',\n );\n }\n return mongoDriver.db;\n}\n\nclass MongoFamilyInstance implements MongoControlFamilyInstance {\n readonly familyId = 'mongo' as const;\n\n validateContract(contractJson: unknown): Contract {\n const validated = validateMongoContract<MongoContract>(contractJson);\n // MongoContract and Contract share structure but are typed independently;\n // validateMongoContract guarantees the shape, so the double cast is safe.\n return validated.contract as unknown as Contract;\n }\n\n async verify(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly expectedTargetId: string;\n readonly contractPath: string;\n readonly configPath?: string;\n }): Promise<VerifyDatabaseResult> {\n const { driver, contract: rawContract, expectedTargetId, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n const contractTarget = contract.target;\n\n const baseOpts = {\n contractStorageHash,\n contractProfileHash,\n expectedTargetId,\n contractPath,\n ...ifDefined('configPath', configPath),\n };\n\n if (contractTarget !== expectedTargetId) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_TARGET_MISMATCH,\n summary: 'Target mismatch',\n actualTargetId: contractTarget,\n totalTime: Date.now() - startTime,\n });\n }\n\n const db = extractDb(driver);\n const marker = await readMarker(db);\n\n if (!marker) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_MARKER_MISSING,\n summary: 'Marker missing',\n totalTime: Date.now() - startTime,\n });\n }\n\n if (marker.storageHash !== contractStorageHash) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_HASH_MISMATCH,\n summary: 'Hash mismatch',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n if (contractProfileHash && marker.profileHash !== contractProfileHash) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_HASH_MISMATCH,\n summary: 'Hash mismatch',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n return buildVerifyResult({\n ...baseOpts,\n ok: true,\n summary: 'Database matches contract',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n async schemaVerify(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly strict: boolean;\n readonly contractPath: string;\n readonly configPath?: string;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;\n }): Promise<VerifyDatabaseSchemaResult> {\n const { driver, contract: rawContract, strict, contractPath, configPath } = options;\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const db = extractDb(driver);\n const liveIR = await introspectSchema(db);\n\n return verifyMongoSchema({\n contract,\n schema: liveIR,\n strict,\n frameworkComponents: options.frameworkComponents,\n context: {\n contractPath,\n ...ifDefined('configPath', configPath),\n },\n });\n }\n\n async sign(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly contractPath: string;\n readonly configPath?: string;\n }): Promise<SignDatabaseResult> {\n const { driver, contract: rawContract, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n\n const db = extractDb(driver);\n\n const existingMarker = await readMarker(db);\n\n let markerCreated = false;\n let markerUpdated = false;\n let previousHashes: { storageHash?: string; profileHash?: string } | undefined;\n\n if (!existingMarker) {\n await initMarker(db, {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n });\n markerCreated = true;\n } else {\n const storageHashMatches = existingMarker.storageHash === contractStorageHash;\n const profileHashMatches = existingMarker.profileHash === contractProfileHash;\n\n if (!storageHashMatches || !profileHashMatches) {\n previousHashes = {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n };\n const updated = await updateMarker(db, existingMarker.storageHash, {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n });\n if (!updated) {\n throw new Error('CAS conflict: marker was modified by another process during sign');\n }\n markerUpdated = true;\n }\n }\n\n let summary: string;\n if (markerCreated) {\n summary = 'Database signed (marker created)';\n } else if (markerUpdated) {\n summary = `Database signed (marker updated from ${previousHashes?.storageHash ?? 'unknown'})`;\n } else {\n summary = 'Database already signed with this contract';\n }\n\n return {\n ok: true,\n summary,\n contract: {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n },\n target: {\n expected: contract.target,\n actual: contract.target,\n },\n marker: {\n created: markerCreated,\n updated: markerUpdated,\n ...ifDefined('previous', previousHashes),\n },\n meta: {\n contractPath,\n ...ifDefined('configPath', configPath),\n },\n timings: {\n total: Date.now() - startTime,\n },\n };\n }\n\n async readMarker(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n }): Promise<ContractMarkerRecord | null> {\n const db = extractDb(options.driver);\n return readMarker(db);\n }\n\n async introspect(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract?: unknown;\n }): Promise<MongoSchemaIR> {\n const db = extractDb(options.driver);\n return introspectSchema(db);\n }\n\n toSchemaView(schema: MongoSchemaIR): CoreSchemaView {\n return mongoSchemaToView(schema);\n }\n}\n\nfunction buildVerifyResult(opts: {\n ok: boolean;\n code?: string;\n summary: string;\n contractStorageHash: string;\n contractProfileHash?: string;\n marker?: ContractMarkerRecord;\n expectedTargetId: string;\n actualTargetId?: string;\n contractPath: string;\n configPath?: string;\n totalTime: number;\n}): VerifyDatabaseResult {\n return {\n ok: opts.ok,\n ...ifDefined('code', opts.code),\n summary: opts.summary,\n contract: {\n storageHash: opts.contractStorageHash,\n ...ifDefined('profileHash', opts.contractProfileHash),\n },\n ...ifDefined(\n 'marker',\n opts.marker\n ? { storageHash: opts.marker.storageHash, profileHash: opts.marker.profileHash }\n : undefined,\n ),\n target: {\n expected: opts.expectedTargetId,\n ...ifDefined('actual', opts.actualTargetId),\n },\n meta: {\n contractPath: opts.contractPath,\n ...ifDefined('configPath', opts.configPath),\n },\n timings: { total: opts.totalTime },\n };\n}\n\nexport function createMongoFamilyInstance(_controlStack: ControlStack): MongoControlFamilyInstance {\n return new MongoFamilyInstance();\n}\n","import type {\n ControlFamilyDescriptor,\n ControlStack,\n} from '@prisma-next/framework-components/control';\nimport { mongoEmission } from '@prisma-next/mongo-emitter';\nimport { createMongoFamilyInstance, type MongoControlFamilyInstance } from './control-instance';\n\nclass MongoFamilyDescriptor\n implements ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance>\n{\n readonly kind = 'family' as const;\n readonly id = 'mongo';\n readonly familyId = 'mongo' as const;\n readonly version = '0.0.1';\n readonly emission = mongoEmission;\n\n create<TTargetId extends string>(\n stack: ControlStack<'mongo', TTargetId>,\n ): MongoControlFamilyInstance {\n return createMongoFamilyInstance(stack);\n }\n}\n\nexport const mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance> =\n new MongoFamilyDescriptor();\n","import { createMongoRunnerDeps, extractDb } from '@prisma-next/adapter-mongo/control';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { MongoDriverImpl } from '@prisma-next/driver-mongo';\nimport type {\n MigratableTargetDescriptor,\n MigrationRunner,\n} from '@prisma-next/framework-components/control';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport {\n contractToMongoSchemaIR,\n MongoMigrationPlanner,\n MongoMigrationRunner,\n type MongoRunnerDependencies,\n} from '@prisma-next/target-mongo/control';\nimport mongoTargetDescriptorMeta from '@prisma-next/target-mongo/pack';\nimport type { MongoControlFamilyInstance } from './control-instance';\n\n/**\n * `migration.ts` default-exports a `Migration` subclass whose `operations`\n * getter returns the ordered list of operations and whose `describe()`\n * returns the manifest identity metadata. `MongoMigrationPlanner.plan()`\n * returns a `MigrationPlanWithAuthoringSurface` that knows how to render\n * itself back to such a file; `MongoMigrationPlanner.emptyMigration()`\n * returns the same shape for `migration new`. Users run the scaffolded\n * `migration.ts` directly (via `node migration.ts`) to self-emit\n * `ops.json` and attest the `migrationId`.\n */\nexport const mongoTargetDescriptor: MigratableTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoControlFamilyInstance\n> = {\n ...mongoTargetDescriptorMeta,\n migrations: {\n createPlanner(_family: MongoControlFamilyInstance) {\n return new MongoMigrationPlanner();\n },\n createRunner(family: MongoControlFamilyInstance) {\n // Deps are bound to the first driver passed to execute() and cached for\n // subsequent calls. Callers must not change the driver between calls.\n let cachedDeps: MongoRunnerDependencies | undefined;\n const runner: MigrationRunner<'mongo', 'mongo'> = {\n async execute(options) {\n cachedDeps ??= createMongoRunnerDeps(\n options.driver,\n MongoDriverImpl.fromDb(extractDb(options.driver)),\n family,\n );\n const { driver: _, ...runnerOptions } = options;\n // The framework `MigrationRunner` interface types `destinationContract`\n // as `unknown`; the Mongo runner narrows to `MongoContract`. Validation\n // happens upstream — `migration apply` calls\n // `familyInstance.validateContract(migration.toContract)` before\n // routing the contract here (see\n // `packages/1-framework/3-tooling/cli/src/control-api/operations/migration-apply.ts`),\n // so this cast simply preserves the framework signature without\n // weakening the runner's typed surface or duplicating validation.\n return new MongoMigrationRunner(cachedDeps).execute({\n ...runnerOptions,\n destinationContract: runnerOptions.destinationContract as MongoContract,\n });\n },\n };\n return runner;\n },\n contractToSchema(contract: Contract | null) {\n return contractToMongoSchemaIR(contract as MongoContract | null);\n },\n },\n create() {\n return { familyId: 'mongo' as const, targetId: 'mongo' as const };\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"control.mjs","names":["extractDb"],"sources":["../src/core/schema-to-view.ts","../src/core/control-instance.ts","../src/core/control-descriptor.ts","../src/core/mongo-target-descriptor.ts"],"sourcesContent":["import type { CoreSchemaView } from '@prisma-next/framework-components/control';\nimport { SchemaTreeNode } from '@prisma-next/framework-components/control';\nimport type { MongoSchemaCollection, MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\nexport function mongoSchemaToView(schema: MongoSchemaIR): CoreSchemaView {\n const collectionNodes = schema.collections.map((collection) =>\n collectionToSchemaNode(collection.name, collection),\n );\n\n return {\n root: new SchemaTreeNode({\n kind: 'root',\n id: 'mongo-schema',\n label: 'database',\n ...ifDefined('children', collectionNodes.length > 0 ? collectionNodes : undefined),\n }),\n };\n}\n\nfunction collectionToSchemaNode(name: string, collection: MongoSchemaCollection): SchemaTreeNode {\n const children: SchemaTreeNode[] = [];\n\n for (const index of collection.indexes) {\n const keysSummary = index.keys\n .map((k) => {\n if (k.direction === 1) return k.field;\n if (k.direction === -1) return `${k.field} desc`;\n return `${k.field} ${k.direction}`;\n })\n .join(', ');\n const prefix = index.unique ? 'unique index' : 'index';\n const options: string[] = [];\n if (index.sparse) options.push('sparse');\n if (index.expireAfterSeconds != null) options.push(`ttl: ${index.expireAfterSeconds}s`);\n if (index.partialFilterExpression) options.push('partial');\n const optsSuffix = options.length > 0 ? ` (${options.join(', ')})` : '';\n\n children.push(\n new SchemaTreeNode({\n kind: 'index',\n id: `index-${name}-${index.keys.map((k) => `${k.field}_${k.direction}`).join('_')}`,\n label: `${prefix} (${keysSummary})${optsSuffix}`,\n meta: {\n keys: index.keys,\n unique: index.unique,\n ...ifDefined('sparse', index.sparse || undefined),\n ...ifDefined('expireAfterSeconds', index.expireAfterSeconds ?? undefined),\n ...ifDefined('partialFilterExpression', index.partialFilterExpression ?? undefined),\n },\n }),\n );\n }\n\n if (collection.validator) {\n const validatorChildren: SchemaTreeNode[] = [];\n const jsonSchema = collection.validator.jsonSchema as Record<string, unknown>;\n const properties = jsonSchema['properties'] as\n | Record<string, Record<string, unknown>>\n | undefined;\n const required = new Set((jsonSchema['required'] as string[] | undefined) ?? []);\n\n if (properties) {\n for (const [propName, propDef] of Object.entries(properties)) {\n const bsonType = (propDef['bsonType'] as string) ?? 'unknown';\n const suffix = required.has(propName) ? ' (required)' : '';\n validatorChildren.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `field-${name}-${propName}`,\n label: `${propName}: ${bsonType}${suffix}`,\n }),\n );\n }\n }\n\n children.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `validator-${name}`,\n label: `validator (level: ${collection.validator.validationLevel}, action: ${collection.validator.validationAction})`,\n meta: {\n validationLevel: collection.validator.validationLevel,\n validationAction: collection.validator.validationAction,\n jsonSchema: collection.validator.jsonSchema,\n },\n ...ifDefined('children', validatorChildren.length > 0 ? validatorChildren : undefined),\n }),\n );\n }\n\n if (collection.options) {\n const opts = collection.options;\n const optLabels: string[] = [];\n if (opts.capped) optLabels.push('capped');\n if (opts.timeseries) optLabels.push('timeseries');\n if (opts.collation) optLabels.push('collation');\n if (opts.changeStreamPreAndPostImages) optLabels.push('changeStreamPreAndPostImages');\n if (opts.clusteredIndex) optLabels.push('clusteredIndex');\n\n if (optLabels.length > 0) {\n children.push(\n new SchemaTreeNode({\n kind: 'field',\n id: `options-${name}`,\n label: `options (${optLabels.join(', ')})`,\n meta: {\n ...ifDefined('capped', opts.capped ?? undefined),\n ...ifDefined('timeseries', opts.timeseries ?? undefined),\n ...ifDefined('collation', opts.collation ?? undefined),\n ...ifDefined(\n 'changeStreamPreAndPostImages',\n opts.changeStreamPreAndPostImages ?? undefined,\n ),\n ...ifDefined('clusteredIndex', opts.clusteredIndex ?? undefined),\n },\n }),\n );\n }\n }\n\n return new SchemaTreeNode({\n kind: 'collection',\n id: `collection-${name}`,\n label: `collection ${name}`,\n ...ifDefined('children', children.length > 0 ? children : undefined),\n });\n}\n","import { introspectSchema } from '@prisma-next/adapter-mongo/control';\nimport type { Contract, ContractMarkerRecord } from '@prisma-next/contract/types';\nimport type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlDriverInstance,\n ControlFamilyInstance,\n ControlStack,\n CoreSchemaView,\n MigrationPlanOperation,\n OperationPreview,\n OperationPreviewCapable,\n SchemaViewCapable,\n SignDatabaseResult,\n VerifyDatabaseResult,\n VerifyDatabaseSchemaResult,\n} from '@prisma-next/framework-components/control';\nimport {\n APP_SPACE_ID,\n VERIFY_CODE_HASH_MISMATCH,\n VERIFY_CODE_MARKER_MISSING,\n VERIFY_CODE_TARGET_MISMATCH,\n} from '@prisma-next/framework-components/control';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport { validateMongoContract } from '@prisma-next/mongo-contract';\nimport type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';\nimport {\n formatMongoOperations,\n initMarker,\n readMarker,\n updateMarker,\n} from '@prisma-next/target-mongo/control';\nimport { verifyMongoSchema } from '@prisma-next/target-mongo/schema-verify';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { Db } from 'mongodb';\nimport { mongoSchemaToView } from './schema-to-view';\n\nexport interface MongoControlFamilyInstance\n extends ControlFamilyInstance<'mongo', MongoSchemaIR>,\n SchemaViewCapable<MongoSchemaIR>,\n OperationPreviewCapable {\n validateContract(contractJson: unknown): Contract;\n}\n\nfunction extractDb(driver: ControlDriverInstance<'mongo', string>): Db {\n const mongoDriver = driver as ControlDriverInstance<'mongo', string> & { db?: Db };\n if (!mongoDriver.db) {\n throw new Error(\n 'Mongo control driver does not expose a db property. ' +\n 'Use createMongoControlDriver() from @prisma-next/adapter-mongo/control.',\n );\n }\n return mongoDriver.db;\n}\n\nclass MongoFamilyInstance implements MongoControlFamilyInstance {\n readonly familyId = 'mongo' as const;\n\n validateContract(contractJson: unknown): Contract {\n const validated = validateMongoContract<MongoContract>(contractJson);\n // MongoContract and Contract share structure but are typed independently;\n // validateMongoContract guarantees the shape, so the double cast is safe.\n return validated.contract as unknown as Contract;\n }\n\n async verify(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly expectedTargetId: string;\n readonly contractPath: string;\n readonly configPath?: string;\n }): Promise<VerifyDatabaseResult> {\n const { driver, contract: rawContract, expectedTargetId, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n const contractTarget = contract.target;\n\n const baseOpts = {\n contractStorageHash,\n contractProfileHash,\n expectedTargetId,\n contractPath,\n ...ifDefined('configPath', configPath),\n };\n\n if (contractTarget !== expectedTargetId) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_TARGET_MISMATCH,\n summary: 'Target mismatch',\n actualTargetId: contractTarget,\n totalTime: Date.now() - startTime,\n });\n }\n\n const db = extractDb(driver);\n const marker = await readMarker(db);\n\n if (!marker) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_MARKER_MISSING,\n summary: 'Marker missing',\n totalTime: Date.now() - startTime,\n });\n }\n\n if (marker.storageHash !== contractStorageHash) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_HASH_MISMATCH,\n summary: 'Hash mismatch',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n if (contractProfileHash && marker.profileHash !== contractProfileHash) {\n return buildVerifyResult({\n ...baseOpts,\n ok: false,\n code: VERIFY_CODE_HASH_MISMATCH,\n summary: 'Hash mismatch',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n return buildVerifyResult({\n ...baseOpts,\n ok: true,\n summary: 'Database matches contract',\n marker,\n totalTime: Date.now() - startTime,\n });\n }\n\n async schemaVerify(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly strict: boolean;\n readonly contractPath: string;\n readonly configPath?: string;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;\n }): Promise<VerifyDatabaseSchemaResult> {\n const { driver, contract: rawContract, strict, contractPath, configPath } = options;\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const db = extractDb(driver);\n const liveIR = await introspectSchema(db);\n\n return verifyMongoSchema({\n contract,\n schema: liveIR,\n strict,\n frameworkComponents: options.frameworkComponents,\n context: {\n contractPath,\n ...ifDefined('configPath', configPath),\n },\n });\n }\n\n schemaVerifyAgainstSchema(options: {\n readonly contract: unknown;\n readonly schema: MongoSchemaIR;\n readonly strict: boolean;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;\n }): VerifyDatabaseSchemaResult {\n const validated = validateMongoContract<MongoContract>(options.contract);\n return verifyMongoSchema({\n contract: validated.contract,\n schema: options.schema,\n strict: options.strict,\n frameworkComponents: options.frameworkComponents,\n });\n }\n\n async sign(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract: unknown;\n readonly contractPath: string;\n readonly configPath?: string;\n }): Promise<SignDatabaseResult> {\n const { driver, contract: rawContract, contractPath, configPath } = options;\n const startTime = Date.now();\n\n const validated = validateMongoContract<MongoContract>(rawContract);\n const contract = validated.contract;\n\n const contractStorageHash = contract.storage.storageHash;\n const contractProfileHash = contract.profileHash;\n\n const db = extractDb(driver);\n\n const existingMarker = await readMarker(db);\n\n let markerCreated = false;\n let markerUpdated = false;\n let previousHashes: { storageHash?: string; profileHash?: string } | undefined;\n\n if (!existingMarker) {\n await initMarker(db, {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n });\n markerCreated = true;\n } else {\n const storageHashMatches = existingMarker.storageHash === contractStorageHash;\n const profileHashMatches = existingMarker.profileHash === contractProfileHash;\n\n if (!storageHashMatches || !profileHashMatches) {\n previousHashes = {\n storageHash: existingMarker.storageHash,\n profileHash: existingMarker.profileHash,\n };\n const updated = await updateMarker(db, existingMarker.storageHash, {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n });\n if (!updated) {\n throw new Error('CAS conflict: marker was modified by another process during sign');\n }\n markerUpdated = true;\n }\n }\n\n let summary: string;\n if (markerCreated) {\n summary = 'Database signed (marker created)';\n } else if (markerUpdated) {\n summary = `Database signed (marker updated from ${previousHashes?.storageHash ?? 'unknown'})`;\n } else {\n summary = 'Database already signed with this contract';\n }\n\n return {\n ok: true,\n summary,\n contract: {\n storageHash: contractStorageHash,\n profileHash: contractProfileHash,\n },\n target: {\n expected: contract.target,\n actual: contract.target,\n },\n marker: {\n created: markerCreated,\n updated: markerUpdated,\n ...ifDefined('previous', previousHashes),\n },\n meta: {\n contractPath,\n ...ifDefined('configPath', configPath),\n },\n timings: {\n total: Date.now() - startTime,\n },\n };\n }\n\n async readMarker(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly space: string;\n }): Promise<ContractMarkerRecord | null> {\n if (options.space !== APP_SPACE_ID) {\n throw new Error(\n 'Mongo target does not yet support per-space contract markers. ' +\n `readMarker was called with space=\"${options.space}\", but only \"${APP_SPACE_ID}\" is supported. ` +\n 'Per-space marker support is tracked separately for Mongo and is not part of the SQL-family contract-spaces work.',\n );\n }\n const db = extractDb(options.driver);\n return readMarker(db);\n }\n\n // Mongo does not yet participate in the per-space mechanism — the\n // `space` column was introduced in the SQL family's marker only.\n // The bridge: surface the single app marker keyed by APP_SPACE_ID so\n // the per-space verifier sees a coherent input shape; per-space mongo\n // support is a future extension.\n async readAllMarkers(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n }): Promise<ReadonlyMap<string, ContractMarkerRecord>> {\n const appMarker = await this.readMarker({ ...options, space: APP_SPACE_ID });\n if (appMarker === null) return new Map();\n return new Map([[APP_SPACE_ID, appMarker]]);\n }\n\n async introspect(options: {\n readonly driver: ControlDriverInstance<'mongo', string>;\n readonly contract?: unknown;\n }): Promise<MongoSchemaIR> {\n const db = extractDb(options.driver);\n return introspectSchema(db);\n }\n\n toSchemaView(schema: MongoSchemaIR): CoreSchemaView {\n return mongoSchemaToView(schema);\n }\n\n toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview {\n return {\n statements: formatMongoOperations(operations).map((text) => ({\n text,\n language: 'mongodb-shell',\n })),\n };\n }\n}\n\nfunction buildVerifyResult(opts: {\n ok: boolean;\n code?: string;\n summary: string;\n contractStorageHash: string;\n contractProfileHash?: string;\n marker?: ContractMarkerRecord;\n expectedTargetId: string;\n actualTargetId?: string;\n contractPath: string;\n configPath?: string;\n totalTime: number;\n}): VerifyDatabaseResult {\n return {\n ok: opts.ok,\n ...ifDefined('code', opts.code),\n summary: opts.summary,\n contract: {\n storageHash: opts.contractStorageHash,\n ...ifDefined('profileHash', opts.contractProfileHash),\n },\n ...ifDefined(\n 'marker',\n opts.marker\n ? { storageHash: opts.marker.storageHash, profileHash: opts.marker.profileHash }\n : undefined,\n ),\n target: {\n expected: opts.expectedTargetId,\n ...ifDefined('actual', opts.actualTargetId),\n },\n meta: {\n contractPath: opts.contractPath,\n ...ifDefined('configPath', opts.configPath),\n },\n timings: { total: opts.totalTime },\n };\n}\n\nexport function createMongoFamilyInstance(_controlStack: ControlStack): MongoControlFamilyInstance {\n return new MongoFamilyInstance();\n}\n","import type {\n ControlFamilyDescriptor,\n ControlStack,\n} from '@prisma-next/framework-components/control';\nimport { mongoEmission } from '@prisma-next/mongo-emitter';\nimport { createMongoFamilyInstance, type MongoControlFamilyInstance } from './control-instance';\n\nclass MongoFamilyDescriptor\n implements ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance>\n{\n readonly kind = 'family' as const;\n readonly id = 'mongo';\n readonly familyId = 'mongo' as const;\n readonly version = '0.0.1';\n readonly emission = mongoEmission;\n\n create<TTargetId extends string>(\n stack: ControlStack<'mongo', TTargetId>,\n ): MongoControlFamilyInstance {\n return createMongoFamilyInstance(stack);\n }\n}\n\nexport const mongoFamilyDescriptor: ControlFamilyDescriptor<'mongo', MongoControlFamilyInstance> =\n new MongoFamilyDescriptor();\n","import { createMongoRunnerDeps, extractDb } from '@prisma-next/adapter-mongo/control';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { MongoDriverImpl } from '@prisma-next/driver-mongo';\nimport type {\n MigratableTargetDescriptor,\n MigrationRunner,\n} from '@prisma-next/framework-components/control';\nimport type { MongoContract } from '@prisma-next/mongo-contract';\nimport {\n contractToMongoSchemaIR,\n MongoMigrationPlanner,\n MongoMigrationRunner,\n type MongoRunnerDependencies,\n} from '@prisma-next/target-mongo/control';\nimport mongoTargetDescriptorMeta from '@prisma-next/target-mongo/pack';\nimport type { MongoControlFamilyInstance } from './control-instance';\n\n/**\n * `migration.ts` default-exports a `Migration` subclass whose `operations`\n * getter returns the ordered list of operations and whose `describe()`\n * returns the manifest identity metadata. `MongoMigrationPlanner.plan()`\n * returns a `MigrationPlanWithAuthoringSurface` that knows how to render\n * itself back to such a file; `MongoMigrationPlanner.emptyMigration()`\n * returns the same shape for `migration new`. Users run the scaffolded\n * `migration.ts` directly (via `node migration.ts`) to self-emit\n * `ops.json` and attest the `migrationHash`.\n */\nexport const mongoTargetDescriptor: MigratableTargetDescriptor<\n 'mongo',\n 'mongo',\n MongoControlFamilyInstance\n> = {\n ...mongoTargetDescriptorMeta,\n migrations: {\n createPlanner(_family: MongoControlFamilyInstance) {\n return new MongoMigrationPlanner();\n },\n createRunner(family: MongoControlFamilyInstance) {\n // Deps are bound to the first driver passed to execute() and cached for\n // subsequent calls. Callers must not change the driver between calls.\n let cachedDeps: MongoRunnerDependencies | undefined;\n const runner: MigrationRunner<'mongo', 'mongo'> = {\n async execute(options) {\n cachedDeps ??= createMongoRunnerDeps(\n options.driver,\n MongoDriverImpl.fromDb(extractDb(options.driver)),\n family,\n );\n const { driver: _, ...runnerOptions } = options;\n // The framework `MigrationRunner` interface types `destinationContract`\n // as `unknown`; the Mongo runner narrows to `MongoContract`. Validation\n // happens upstream — `migration apply` calls\n // `familyInstance.validateContract(migration.toContract)` before\n // routing the contract here (see\n // `packages/1-framework/3-tooling/cli/src/control-api/operations/migration-apply.ts`),\n // so this cast simply preserves the framework signature without\n // weakening the runner's typed surface or duplicating validation.\n return new MongoMigrationRunner(cachedDeps).execute({\n ...runnerOptions,\n destinationContract: runnerOptions.destinationContract as MongoContract,\n });\n },\n };\n return runner;\n },\n contractToSchema(contract: Contract | null) {\n return contractToMongoSchemaIR(contract as MongoContract | null);\n },\n },\n create() {\n return { familyId: 'mongo' as const, targetId: 'mongo' as const };\n },\n};\n"],"mappings":"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"}
|
package/dist/migration.d.mts
CHANGED
package/dist/migration.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration.d.mts","names":[],"sources":["../src/core/mongo-migration.ts"],"
|
|
1
|
+
{"version":3,"file":"migration.d.mts","names":[],"sources":["../src/core/mongo-migration.ts"],"mappings":";;;;;;AAiBA;;;;;;;;;;;;uBAAsB,cAAA,SAAuB,SAAA,CAAU,0BAAA;EAAA,SAC5C,QAAA;AAAA"}
|
package/dist/migration.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Migration } from "@prisma-next/migration-tools/migration";
|
|
2
|
-
|
|
3
2
|
//#region src/core/mongo-migration.ts
|
|
4
3
|
/**
|
|
5
4
|
* Family-owned base class for Mongo migrations.
|
|
@@ -18,7 +17,7 @@ import { Migration } from "@prisma-next/migration-tools/migration";
|
|
|
18
17
|
var MongoMigration = class extends Migration {
|
|
19
18
|
targetId = "mongo";
|
|
20
19
|
};
|
|
21
|
-
|
|
22
20
|
//#endregion
|
|
23
21
|
export { MongoMigration as Migration };
|
|
22
|
+
|
|
24
23
|
//# sourceMappingURL=migration.mjs.map
|
package/dist/migration.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration.mjs","names":[],"sources":["../src/core/mongo-migration.ts"],"sourcesContent":["import { Migration } from '@prisma-next/migration-tools/migration';\nimport type { AnyMongoMigrationOperation } from '@prisma-next/mongo-query-ast/control';\n\n/**\n * Family-owned base class for Mongo migrations.\n *\n * Provides the fixed `targetId = 'mongo'` so that user-authored migrations\n * and renderer-generated scaffolds (e.g. the output of\n * `renderCallsToTypeScript`) inherit it directly and don't have to re-declare\n * the abstract `targetId` member from `Migration`.\n *\n * The operation type parameter is `AnyMongoMigrationOperation` — the union\n * of DDL-shaped `MongoMigrationPlanOperation` and `MongoDataTransformOperation` —\n * so subclasses can return a mix of schema operations (e.g. `createIndex`,\n * `setValidation`) and data-transform operations (e.g. `dataTransform`).\n * Mirrors the generic parameter used by `PlannerProducedMongoMigration`.\n */\nexport abstract class MongoMigration extends Migration<AnyMongoMigrationOperation> {\n readonly targetId = 'mongo' as const;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"migration.mjs","names":[],"sources":["../src/core/mongo-migration.ts"],"sourcesContent":["import { Migration } from '@prisma-next/migration-tools/migration';\nimport type { AnyMongoMigrationOperation } from '@prisma-next/mongo-query-ast/control';\n\n/**\n * Family-owned base class for Mongo migrations.\n *\n * Provides the fixed `targetId = 'mongo'` so that user-authored migrations\n * and renderer-generated scaffolds (e.g. the output of\n * `renderCallsToTypeScript`) inherit it directly and don't have to re-declare\n * the abstract `targetId` member from `Migration`.\n *\n * The operation type parameter is `AnyMongoMigrationOperation` — the union\n * of DDL-shaped `MongoMigrationPlanOperation` and `MongoDataTransformOperation` —\n * so subclasses can return a mix of schema operations (e.g. `createIndex`,\n * `setValidation`) and data-transform operations (e.g. `dataTransform`).\n * Mirrors the generic parameter used by `PlannerProducedMongoMigration`.\n */\nexport abstract class MongoMigration extends Migration<AnyMongoMigrationOperation> {\n readonly targetId = 'mongo' as const;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAiBA,IAAsB,iBAAtB,cAA6C,UAAsC;CACjF,WAAoB"}
|
package/dist/pack.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack.d.mts","names":[],"sources":["../src/exports/pack.ts"],"
|
|
1
|
+
{"version":3,"file":"pack.d.mts","names":[],"sources":["../src/exports/pack.ts"],"mappings":";cAAM,eAAA;EAAA"}
|
package/dist/pack.mjs
CHANGED
package/dist/pack.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack.mjs","names":[],"sources":["../src/exports/pack.ts"],"sourcesContent":["const mongoFamilyPack = {\n kind: 'family',\n id: 'mongo',\n familyId: 'mongo',\n version: '0.0.1',\n} as const;\n\nexport default mongoFamilyPack;\n"],"mappings":";AAAA,MAAM,kBAAkB;CACtB,MAAM;CACN,IAAI;CACJ,UAAU;CACV,SAAS;CACV
|
|
1
|
+
{"version":3,"file":"pack.mjs","names":[],"sources":["../src/exports/pack.ts"],"sourcesContent":["const mongoFamilyPack = {\n kind: 'family',\n id: 'mongo',\n familyId: 'mongo',\n version: '0.0.1',\n} as const;\n\nexport default mongoFamilyPack;\n"],"mappings":";AAAA,MAAM,kBAAkB;CACtB,MAAM;CACN,IAAI;CACJ,UAAU;CACV,SAAS;CACV"}
|
package/dist/schema-verify.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/family-mongo",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.71",
|
|
4
|
+
"license": "Apache-2.0",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"sideEffects": false,
|
|
6
7
|
"description": "Mongo family descriptor for Prisma Next",
|
|
7
8
|
"dependencies": {
|
|
8
9
|
"mongodb": "^6.16.0",
|
|
9
10
|
"pathe": "^2.0.3",
|
|
10
|
-
"@prisma-next/
|
|
11
|
-
"@prisma-next/
|
|
12
|
-
"@prisma-next/driver-mongo": "0.5.0-dev.
|
|
13
|
-
"@prisma-next/
|
|
14
|
-
"@prisma-next/
|
|
15
|
-
"@prisma-next/
|
|
16
|
-
"@prisma-next/
|
|
17
|
-
"@prisma-next/
|
|
18
|
-
"@prisma-next/mongo-emitter": "0.5.0-dev.
|
|
19
|
-
"@prisma-next/mongo-
|
|
20
|
-
"@prisma-next/mongo-
|
|
21
|
-
"@prisma-next/
|
|
22
|
-
"@prisma-next/
|
|
11
|
+
"@prisma-next/adapter-mongo": "0.5.0-dev.71",
|
|
12
|
+
"@prisma-next/contract": "0.5.0-dev.71",
|
|
13
|
+
"@prisma-next/driver-mongo": "0.5.0-dev.71",
|
|
14
|
+
"@prisma-next/emitter": "0.5.0-dev.71",
|
|
15
|
+
"@prisma-next/errors": "0.5.0-dev.71",
|
|
16
|
+
"@prisma-next/framework-components": "0.5.0-dev.71",
|
|
17
|
+
"@prisma-next/migration-tools": "0.5.0-dev.71",
|
|
18
|
+
"@prisma-next/mongo-contract": "0.5.0-dev.71",
|
|
19
|
+
"@prisma-next/mongo-emitter": "0.5.0-dev.71",
|
|
20
|
+
"@prisma-next/mongo-schema-ir": "0.5.0-dev.71",
|
|
21
|
+
"@prisma-next/mongo-query-ast": "0.5.0-dev.71",
|
|
22
|
+
"@prisma-next/utils": "0.5.0-dev.71",
|
|
23
|
+
"@prisma-next/target-mongo": "0.5.0-dev.71"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|
|
25
|
-
"tsdown": "0.
|
|
26
|
+
"tsdown": "0.22.0",
|
|
26
27
|
"typescript": "5.9.3",
|
|
27
|
-
"vitest": "4.
|
|
28
|
-
"@prisma-next/mongo-contract-ts": "0.5.0-dev.7",
|
|
28
|
+
"vitest": "4.1.5",
|
|
29
29
|
"@prisma-next/tsconfig": "0.0.0",
|
|
30
|
+
"@prisma-next/mongo-contract-ts": "0.5.0-dev.71",
|
|
30
31
|
"@prisma-next/tsdown": "0.0.0"
|
|
31
32
|
},
|
|
32
33
|
"files": [
|
|
@@ -6,12 +6,16 @@ import type {
|
|
|
6
6
|
ControlFamilyInstance,
|
|
7
7
|
ControlStack,
|
|
8
8
|
CoreSchemaView,
|
|
9
|
+
MigrationPlanOperation,
|
|
10
|
+
OperationPreview,
|
|
11
|
+
OperationPreviewCapable,
|
|
9
12
|
SchemaViewCapable,
|
|
10
13
|
SignDatabaseResult,
|
|
11
14
|
VerifyDatabaseResult,
|
|
12
15
|
VerifyDatabaseSchemaResult,
|
|
13
16
|
} from '@prisma-next/framework-components/control';
|
|
14
17
|
import {
|
|
18
|
+
APP_SPACE_ID,
|
|
15
19
|
VERIFY_CODE_HASH_MISMATCH,
|
|
16
20
|
VERIFY_CODE_MARKER_MISSING,
|
|
17
21
|
VERIFY_CODE_TARGET_MISMATCH,
|
|
@@ -19,7 +23,12 @@ import {
|
|
|
19
23
|
import type { MongoContract } from '@prisma-next/mongo-contract';
|
|
20
24
|
import { validateMongoContract } from '@prisma-next/mongo-contract';
|
|
21
25
|
import type { MongoSchemaIR } from '@prisma-next/mongo-schema-ir';
|
|
22
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
formatMongoOperations,
|
|
28
|
+
initMarker,
|
|
29
|
+
readMarker,
|
|
30
|
+
updateMarker,
|
|
31
|
+
} from '@prisma-next/target-mongo/control';
|
|
23
32
|
import { verifyMongoSchema } from '@prisma-next/target-mongo/schema-verify';
|
|
24
33
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
25
34
|
import type { Db } from 'mongodb';
|
|
@@ -27,7 +36,8 @@ import { mongoSchemaToView } from './schema-to-view';
|
|
|
27
36
|
|
|
28
37
|
export interface MongoControlFamilyInstance
|
|
29
38
|
extends ControlFamilyInstance<'mongo', MongoSchemaIR>,
|
|
30
|
-
SchemaViewCapable<MongoSchemaIR
|
|
39
|
+
SchemaViewCapable<MongoSchemaIR>,
|
|
40
|
+
OperationPreviewCapable {
|
|
31
41
|
validateContract(contractJson: unknown): Contract;
|
|
32
42
|
}
|
|
33
43
|
|
|
@@ -160,6 +170,21 @@ class MongoFamilyInstance implements MongoControlFamilyInstance {
|
|
|
160
170
|
});
|
|
161
171
|
}
|
|
162
172
|
|
|
173
|
+
schemaVerifyAgainstSchema(options: {
|
|
174
|
+
readonly contract: unknown;
|
|
175
|
+
readonly schema: MongoSchemaIR;
|
|
176
|
+
readonly strict: boolean;
|
|
177
|
+
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'mongo', string>>;
|
|
178
|
+
}): VerifyDatabaseSchemaResult {
|
|
179
|
+
const validated = validateMongoContract<MongoContract>(options.contract);
|
|
180
|
+
return verifyMongoSchema({
|
|
181
|
+
contract: validated.contract,
|
|
182
|
+
schema: options.schema,
|
|
183
|
+
strict: options.strict,
|
|
184
|
+
frameworkComponents: options.frameworkComponents,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
163
188
|
async sign(options: {
|
|
164
189
|
readonly driver: ControlDriverInstance<'mongo', string>;
|
|
165
190
|
readonly contract: unknown;
|
|
@@ -246,11 +271,32 @@ class MongoFamilyInstance implements MongoControlFamilyInstance {
|
|
|
246
271
|
|
|
247
272
|
async readMarker(options: {
|
|
248
273
|
readonly driver: ControlDriverInstance<'mongo', string>;
|
|
274
|
+
readonly space: string;
|
|
249
275
|
}): Promise<ContractMarkerRecord | null> {
|
|
276
|
+
if (options.space !== APP_SPACE_ID) {
|
|
277
|
+
throw new Error(
|
|
278
|
+
'Mongo target does not yet support per-space contract markers. ' +
|
|
279
|
+
`readMarker was called with space="${options.space}", but only "${APP_SPACE_ID}" is supported. ` +
|
|
280
|
+
'Per-space marker support is tracked separately for Mongo and is not part of the SQL-family contract-spaces work.',
|
|
281
|
+
);
|
|
282
|
+
}
|
|
250
283
|
const db = extractDb(options.driver);
|
|
251
284
|
return readMarker(db);
|
|
252
285
|
}
|
|
253
286
|
|
|
287
|
+
// Mongo does not yet participate in the per-space mechanism — the
|
|
288
|
+
// `space` column was introduced in the SQL family's marker only.
|
|
289
|
+
// The bridge: surface the single app marker keyed by APP_SPACE_ID so
|
|
290
|
+
// the per-space verifier sees a coherent input shape; per-space mongo
|
|
291
|
+
// support is a future extension.
|
|
292
|
+
async readAllMarkers(options: {
|
|
293
|
+
readonly driver: ControlDriverInstance<'mongo', string>;
|
|
294
|
+
}): Promise<ReadonlyMap<string, ContractMarkerRecord>> {
|
|
295
|
+
const appMarker = await this.readMarker({ ...options, space: APP_SPACE_ID });
|
|
296
|
+
if (appMarker === null) return new Map();
|
|
297
|
+
return new Map([[APP_SPACE_ID, appMarker]]);
|
|
298
|
+
}
|
|
299
|
+
|
|
254
300
|
async introspect(options: {
|
|
255
301
|
readonly driver: ControlDriverInstance<'mongo', string>;
|
|
256
302
|
readonly contract?: unknown;
|
|
@@ -262,6 +308,15 @@ class MongoFamilyInstance implements MongoControlFamilyInstance {
|
|
|
262
308
|
toSchemaView(schema: MongoSchemaIR): CoreSchemaView {
|
|
263
309
|
return mongoSchemaToView(schema);
|
|
264
310
|
}
|
|
311
|
+
|
|
312
|
+
toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview {
|
|
313
|
+
return {
|
|
314
|
+
statements: formatMongoOperations(operations).map((text) => ({
|
|
315
|
+
text,
|
|
316
|
+
language: 'mongodb-shell',
|
|
317
|
+
})),
|
|
318
|
+
};
|
|
319
|
+
}
|
|
265
320
|
}
|
|
266
321
|
|
|
267
322
|
function buildVerifyResult(opts: {
|
|
@@ -23,7 +23,7 @@ import type { MongoControlFamilyInstance } from './control-instance';
|
|
|
23
23
|
* itself back to such a file; `MongoMigrationPlanner.emptyMigration()`
|
|
24
24
|
* returns the same shape for `migration new`. Users run the scaffolded
|
|
25
25
|
* `migration.ts` directly (via `node migration.ts`) to self-emit
|
|
26
|
-
* `ops.json` and attest the `
|
|
26
|
+
* `ops.json` and attest the `migrationHash`.
|
|
27
27
|
*/
|
|
28
28
|
export const mongoTargetDescriptor: MigratableTargetDescriptor<
|
|
29
29
|
'mongo',
|