@prisma-next/target-mongo 0.4.0-dev.1 → 0.4.0-dev.3

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.
@@ -0,0 +1,196 @@
1
+ import type { MigrationOperationClass } from '@prisma-next/framework-components/control';
2
+ import type {
3
+ CollModOptions,
4
+ CreateCollectionOptions,
5
+ CreateIndexOptions,
6
+ MongoIndexKey,
7
+ } from '@prisma-next/mongo-query-ast/control';
8
+ import type {
9
+ MongoSchemaCollection,
10
+ MongoSchemaCollectionOptions,
11
+ MongoSchemaIndex,
12
+ MongoSchemaValidator,
13
+ } from '@prisma-next/mongo-schema-ir';
14
+
15
+ export interface CollModMeta {
16
+ readonly id?: string;
17
+ readonly label?: string;
18
+ readonly operationClass?: MigrationOperationClass;
19
+ }
20
+
21
+ export interface OpFactoryCallVisitor<R> {
22
+ createIndex(call: CreateIndexCall): R;
23
+ dropIndex(call: DropIndexCall): R;
24
+ createCollection(call: CreateCollectionCall): R;
25
+ dropCollection(call: DropCollectionCall): R;
26
+ collMod(call: CollModCall): R;
27
+ }
28
+
29
+ abstract class OpFactoryCallNode {
30
+ abstract readonly factory: string;
31
+ abstract readonly operationClass: MigrationOperationClass;
32
+ abstract readonly label: string;
33
+ abstract accept<R>(visitor: OpFactoryCallVisitor<R>): R;
34
+
35
+ protected freeze(): void {
36
+ Object.freeze(this);
37
+ }
38
+ }
39
+
40
+ function formatKeys(keys: ReadonlyArray<MongoIndexKey>): string {
41
+ return keys.map((k) => `${k.field}:${k.direction}`).join(', ');
42
+ }
43
+
44
+ export class CreateIndexCall extends OpFactoryCallNode {
45
+ readonly factory = 'createIndex' as const;
46
+ readonly operationClass = 'additive' as const;
47
+ readonly collection: string;
48
+ readonly keys: ReadonlyArray<MongoIndexKey>;
49
+ readonly options: CreateIndexOptions | undefined;
50
+ readonly label: string;
51
+
52
+ constructor(
53
+ collection: string,
54
+ keys: ReadonlyArray<MongoIndexKey>,
55
+ options?: CreateIndexOptions,
56
+ ) {
57
+ super();
58
+ this.collection = collection;
59
+ this.keys = keys;
60
+ this.options = options;
61
+ this.label = `Create index on ${collection} (${formatKeys(keys)})`;
62
+ this.freeze();
63
+ }
64
+
65
+ accept<R>(visitor: OpFactoryCallVisitor<R>): R {
66
+ return visitor.createIndex(this);
67
+ }
68
+ }
69
+
70
+ export class DropIndexCall extends OpFactoryCallNode {
71
+ readonly factory = 'dropIndex' as const;
72
+ readonly operationClass = 'destructive' as const;
73
+ readonly collection: string;
74
+ readonly keys: ReadonlyArray<MongoIndexKey>;
75
+ readonly label: string;
76
+
77
+ constructor(collection: string, keys: ReadonlyArray<MongoIndexKey>) {
78
+ super();
79
+ this.collection = collection;
80
+ this.keys = keys;
81
+ this.label = `Drop index on ${collection} (${formatKeys(keys)})`;
82
+ this.freeze();
83
+ }
84
+
85
+ accept<R>(visitor: OpFactoryCallVisitor<R>): R {
86
+ return visitor.dropIndex(this);
87
+ }
88
+ }
89
+
90
+ export class CreateCollectionCall extends OpFactoryCallNode {
91
+ readonly factory = 'createCollection' as const;
92
+ readonly operationClass = 'additive' as const;
93
+ readonly collection: string;
94
+ readonly options: CreateCollectionOptions | undefined;
95
+ readonly label: string;
96
+
97
+ constructor(collection: string, options?: CreateCollectionOptions) {
98
+ super();
99
+ this.collection = collection;
100
+ this.options = options;
101
+ this.label = `Create collection ${collection}`;
102
+ this.freeze();
103
+ }
104
+
105
+ accept<R>(visitor: OpFactoryCallVisitor<R>): R {
106
+ return visitor.createCollection(this);
107
+ }
108
+ }
109
+
110
+ export class DropCollectionCall extends OpFactoryCallNode {
111
+ readonly factory = 'dropCollection' as const;
112
+ readonly operationClass = 'destructive' as const;
113
+ readonly collection: string;
114
+ readonly label: string;
115
+
116
+ constructor(collection: string) {
117
+ super();
118
+ this.collection = collection;
119
+ this.label = `Drop collection ${collection}`;
120
+ this.freeze();
121
+ }
122
+
123
+ accept<R>(visitor: OpFactoryCallVisitor<R>): R {
124
+ return visitor.dropCollection(this);
125
+ }
126
+ }
127
+
128
+ export class CollModCall extends OpFactoryCallNode {
129
+ readonly factory = 'collMod' as const;
130
+ readonly collection: string;
131
+ readonly options: CollModOptions;
132
+ readonly meta: CollModMeta | undefined;
133
+ readonly operationClass: MigrationOperationClass;
134
+ readonly label: string;
135
+
136
+ constructor(collection: string, options: CollModOptions, meta?: CollModMeta) {
137
+ super();
138
+ this.collection = collection;
139
+ this.options = options;
140
+ this.meta = meta;
141
+ this.operationClass = meta?.operationClass ?? 'destructive';
142
+ this.label = meta?.label ?? `Modify collection ${collection}`;
143
+ this.freeze();
144
+ }
145
+
146
+ accept<R>(visitor: OpFactoryCallVisitor<R>): R {
147
+ return visitor.collMod(this);
148
+ }
149
+ }
150
+
151
+ export type OpFactoryCall =
152
+ | CreateIndexCall
153
+ | DropIndexCall
154
+ | CreateCollectionCall
155
+ | DropCollectionCall
156
+ | CollModCall;
157
+
158
+ export function schemaIndexToCreateIndexOptions(index: MongoSchemaIndex): CreateIndexOptions {
159
+ return {
160
+ unique: index.unique || undefined,
161
+ sparse: index.sparse,
162
+ expireAfterSeconds: index.expireAfterSeconds,
163
+ partialFilterExpression: index.partialFilterExpression,
164
+ wildcardProjection: index.wildcardProjection,
165
+ collation: index.collation,
166
+ weights: index.weights,
167
+ default_language: index.default_language,
168
+ language_override: index.language_override,
169
+ };
170
+ }
171
+
172
+ export function schemaCollectionToCreateCollectionOptions(
173
+ coll: MongoSchemaCollection,
174
+ ): CreateCollectionOptions | undefined {
175
+ const opts: MongoSchemaCollectionOptions | undefined = coll.options;
176
+ const validator: MongoSchemaValidator | undefined = coll.validator;
177
+ if (!opts && !validator) return undefined;
178
+ return {
179
+ capped: opts?.capped ? true : undefined,
180
+ size: opts?.capped?.size,
181
+ max: opts?.capped?.max,
182
+ timeseries: opts?.timeseries,
183
+ collation: opts?.collation,
184
+ clusteredIndex: opts?.clusteredIndex
185
+ ? {
186
+ key: { _id: 1 } as Record<string, number>,
187
+ unique: true as boolean,
188
+ ...(opts.clusteredIndex.name != null ? { name: opts.clusteredIndex.name } : {}),
189
+ }
190
+ : undefined,
191
+ validator: validator ? { $jsonSchema: validator.jsonSchema } : undefined,
192
+ validationLevel: validator?.validationLevel,
193
+ validationAction: validator?.validationAction,
194
+ changeStreamPreAndPostImages: opts?.changeStreamPreAndPostImages,
195
+ };
196
+ }
@@ -0,0 +1,39 @@
1
+ import type { MongoMigrationPlanOperation } from '@prisma-next/mongo-query-ast/control';
2
+ import {
3
+ collMod,
4
+ createCollection,
5
+ createIndex,
6
+ dropCollection,
7
+ dropIndex,
8
+ } from './migration-factories';
9
+ import type {
10
+ CollModCall,
11
+ CreateCollectionCall,
12
+ CreateIndexCall,
13
+ DropCollectionCall,
14
+ DropIndexCall,
15
+ OpFactoryCall,
16
+ OpFactoryCallVisitor,
17
+ } from './op-factory-call';
18
+
19
+ const renderVisitor: OpFactoryCallVisitor<MongoMigrationPlanOperation> = {
20
+ createIndex(call: CreateIndexCall) {
21
+ return createIndex(call.collection, call.keys, call.options);
22
+ },
23
+ dropIndex(call: DropIndexCall) {
24
+ return dropIndex(call.collection, call.keys);
25
+ },
26
+ createCollection(call: CreateCollectionCall) {
27
+ return createCollection(call.collection, call.options);
28
+ },
29
+ dropCollection(call: DropCollectionCall) {
30
+ return dropCollection(call.collection);
31
+ },
32
+ collMod(call: CollModCall) {
33
+ return collMod(call.collection, call.options, call.meta);
34
+ },
35
+ };
36
+
37
+ export function renderOps(calls: ReadonlyArray<OpFactoryCall>): MongoMigrationPlanOperation[] {
38
+ return calls.map((call) => call.accept(renderVisitor));
39
+ }
@@ -0,0 +1,137 @@
1
+ import type {
2
+ CollModCall,
3
+ CreateCollectionCall,
4
+ CreateIndexCall,
5
+ DropCollectionCall,
6
+ DropIndexCall,
7
+ OpFactoryCall,
8
+ OpFactoryCallVisitor,
9
+ } from './op-factory-call';
10
+
11
+ export interface RenderMigrationMeta {
12
+ readonly from: string;
13
+ readonly to: string;
14
+ readonly kind?: string;
15
+ readonly labels?: readonly string[];
16
+ }
17
+
18
+ export function renderTypeScript(
19
+ calls: ReadonlyArray<OpFactoryCall>,
20
+ meta?: RenderMigrationMeta,
21
+ ): string {
22
+ const factoryNames = collectFactoryNames(calls);
23
+ const imports = buildImports(factoryNames);
24
+ const planBody = calls.map((c) => c.accept(renderCallVisitor)).join(',\n');
25
+ const describeMethod = meta ? buildDescribeMethod(meta) : '';
26
+
27
+ return [
28
+ imports,
29
+ '',
30
+ 'class M extends Migration {',
31
+ describeMethod,
32
+ ' override plan() {',
33
+ ' return [',
34
+ indent(planBody, 6),
35
+ ' ];',
36
+ ' }',
37
+ '}',
38
+ '',
39
+ 'export default M;',
40
+ 'Migration.run(import.meta.url, M);',
41
+ '',
42
+ ].join('\n');
43
+ }
44
+
45
+ function collectFactoryNames(calls: ReadonlyArray<OpFactoryCall>): string[] {
46
+ const names = new Set<string>();
47
+ for (const call of calls) {
48
+ names.add(call.factory);
49
+ }
50
+ return [...names].sort();
51
+ }
52
+
53
+ function buildImports(factoryNames: string[]): string {
54
+ const lines = ["import { Migration } from '@prisma-next/family-mongo/migration';"];
55
+ if (factoryNames.length > 0) {
56
+ lines.push(`import { ${factoryNames.join(', ')} } from '@prisma-next/target-mongo/migration';`);
57
+ }
58
+ return lines.join('\n');
59
+ }
60
+
61
+ function buildDescribeMethod(meta: RenderMigrationMeta): string {
62
+ const lines: string[] = [];
63
+ lines.push(' override describe() {');
64
+ lines.push(' return {');
65
+ lines.push(` from: ${JSON.stringify(meta.from)},`);
66
+ lines.push(` to: ${JSON.stringify(meta.to)},`);
67
+ if (meta.kind) {
68
+ lines.push(` kind: ${JSON.stringify(meta.kind)},`);
69
+ }
70
+ if (meta.labels && meta.labels.length > 0) {
71
+ lines.push(` labels: ${renderLiteral(meta.labels)},`);
72
+ }
73
+ lines.push(' };');
74
+ lines.push(' }');
75
+ lines.push('');
76
+ return lines.join('\n');
77
+ }
78
+
79
+ const renderCallVisitor: OpFactoryCallVisitor<string> = {
80
+ createIndex(call: CreateIndexCall) {
81
+ return call.options
82
+ ? `createIndex(${renderLiteral(call.collection)}, ${renderLiteral(call.keys)}, ${renderLiteral(call.options)})`
83
+ : `createIndex(${renderLiteral(call.collection)}, ${renderLiteral(call.keys)})`;
84
+ },
85
+ dropIndex(call: DropIndexCall) {
86
+ return `dropIndex(${renderLiteral(call.collection)}, ${renderLiteral(call.keys)})`;
87
+ },
88
+ createCollection(call: CreateCollectionCall) {
89
+ return call.options
90
+ ? `createCollection(${renderLiteral(call.collection)}, ${renderLiteral(call.options)})`
91
+ : `createCollection(${renderLiteral(call.collection)})`;
92
+ },
93
+ dropCollection(call: DropCollectionCall) {
94
+ return `dropCollection(${renderLiteral(call.collection)})`;
95
+ },
96
+ collMod(call: CollModCall) {
97
+ return call.meta
98
+ ? `collMod(${renderLiteral(call.collection)}, ${renderLiteral(call.options)}, ${renderLiteral(call.meta)})`
99
+ : `collMod(${renderLiteral(call.collection)}, ${renderLiteral(call.options)})`;
100
+ },
101
+ };
102
+
103
+ function renderLiteral(value: unknown): string {
104
+ if (value === undefined) return 'undefined';
105
+ if (value === null) return 'null';
106
+ if (typeof value === 'string') return JSON.stringify(value);
107
+ if (typeof value === 'number' || typeof value === 'boolean') return String(value);
108
+ if (Array.isArray(value)) {
109
+ if (value.length === 0) return '[]';
110
+ const items = value.map((v) => renderLiteral(v));
111
+ const singleLine = `[${items.join(', ')}]`;
112
+ if (singleLine.length <= 80) return singleLine;
113
+ return `[\n${items.map((i) => ` ${i}`).join(',\n')},\n]`;
114
+ }
115
+ if (typeof value === 'object') {
116
+ const entries = Object.entries(value).filter(([, v]) => v !== undefined);
117
+ if (entries.length === 0) return '{}';
118
+ const items = entries.map(([k, v]) => `${renderKey(k)}: ${renderLiteral(v)}`);
119
+ const singleLine = `{ ${items.join(', ')} }`;
120
+ if (singleLine.length <= 80) return singleLine;
121
+ return `{\n${items.map((i) => ` ${i}`).join(',\n')},\n}`;
122
+ }
123
+ return String(value);
124
+ }
125
+
126
+ function renderKey(key: string): string {
127
+ if (key === '__proto__') return JSON.stringify(key);
128
+ return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
129
+ }
130
+
131
+ function indent(text: string, spaces: number): string {
132
+ const pad = ' '.repeat(spaces);
133
+ return text
134
+ .split('\n')
135
+ .map((line) => (line.trim() ? `${pad}${line}` : line))
136
+ .join('\n');
137
+ }
@@ -1 +1,26 @@
1
+ export { contractToMongoSchemaIR } from '../core/contract-to-schema';
2
+ export { formatMongoOperations } from '../core/ddl-formatter';
3
+ export { FilterEvaluator } from '../core/filter-evaluator';
1
4
  export { initMarker, readMarker, updateMarker, writeLedgerEntry } from '../core/marker-ledger';
5
+ export {
6
+ deserializeMongoOp,
7
+ deserializeMongoOps,
8
+ serializeMongoOps,
9
+ } from '../core/mongo-ops-serializer';
10
+ export type { PlanCallsResult } from '../core/mongo-planner';
11
+ export { MongoMigrationPlanner } from '../core/mongo-planner';
12
+ export type { MarkerOperations, MongoRunnerDependencies } from '../core/mongo-runner';
13
+ export { MongoMigrationRunner } from '../core/mongo-runner';
14
+ export type { CollModMeta, OpFactoryCall, OpFactoryCallVisitor } from '../core/op-factory-call';
15
+ export {
16
+ CollModCall,
17
+ CreateCollectionCall,
18
+ CreateIndexCall,
19
+ DropCollectionCall,
20
+ DropIndexCall,
21
+ schemaCollectionToCreateCollectionOptions,
22
+ schemaIndexToCreateIndexOptions,
23
+ } from '../core/op-factory-call';
24
+ export { renderOps } from '../core/render-ops';
25
+ export type { RenderMigrationMeta } from '../core/render-typescript';
26
+ export { renderTypeScript } from '../core/render-typescript';
@@ -1,4 +1,5 @@
1
1
  export {
2
+ collMod,
2
3
  createCollection,
3
4
  createIndex,
4
5
  dropCollection,
@@ -1 +0,0 @@
1
- {"version":3,"file":"migration.mjs","names":[],"sources":["../src/core/migration-factories.ts"],"sourcesContent":["import type { MongoIndexKey } from '@prisma-next/mongo-query-ast/control';\nimport {\n buildIndexOpId,\n CollModCommand,\n CreateCollectionCommand,\n type CreateCollectionOptions,\n CreateIndexCommand,\n type CreateIndexOptions,\n DropCollectionCommand,\n DropIndexCommand,\n defaultMongoIndexName,\n keysToKeySpec,\n ListCollectionsCommand,\n ListIndexesCommand,\n MongoAndExpr,\n MongoFieldFilter,\n type MongoMigrationPlanOperation,\n} from '@prisma-next/mongo-query-ast/control';\n\nfunction formatKeys(keys: ReadonlyArray<MongoIndexKey>): string {\n return keys.map((k) => `${k.field}:${k.direction}`).join(', ');\n}\n\nfunction isTextIndex(keys: ReadonlyArray<MongoIndexKey>): boolean {\n return keys.some((k) => k.direction === 'text');\n}\n\nfunction keyFilter(keys: ReadonlyArray<MongoIndexKey>) {\n return isTextIndex(keys)\n ? MongoFieldFilter.eq('key._fts', 'text')\n : MongoFieldFilter.eq('key', keysToKeySpec(keys));\n}\n\nexport function createIndex(\n collection: string,\n keys: ReadonlyArray<MongoIndexKey>,\n options?: CreateIndexOptions,\n): MongoMigrationPlanOperation {\n const name = defaultMongoIndexName(keys);\n const filter = keyFilter(keys);\n const fullFilter = options?.unique\n ? MongoAndExpr.of([filter, MongoFieldFilter.eq('unique', true)])\n : filter;\n\n return {\n id: buildIndexOpId('create', collection, keys),\n label: `Create index on ${collection} (${formatKeys(keys)})`,\n operationClass: 'additive',\n precheck: [\n {\n description: `index does not already exist on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'notExists',\n },\n ],\n execute: [\n {\n description: `create index on ${collection}`,\n command: new CreateIndexCommand(collection, keys, {\n ...options,\n unique: options?.unique ?? undefined,\n name,\n }),\n },\n ],\n postcheck: [\n {\n description: `index exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter: fullFilter,\n expect: 'exists',\n },\n ],\n };\n}\n\nexport function dropIndex(\n collection: string,\n keys: ReadonlyArray<MongoIndexKey>,\n): MongoMigrationPlanOperation {\n const indexName = defaultMongoIndexName(keys);\n const filter = keyFilter(keys);\n\n return {\n id: buildIndexOpId('drop', collection, keys),\n label: `Drop index on ${collection} (${formatKeys(keys)})`,\n operationClass: 'destructive',\n precheck: [\n {\n description: `index exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'exists',\n },\n ],\n execute: [\n {\n description: `drop index on ${collection}`,\n command: new DropIndexCommand(collection, indexName),\n },\n ],\n postcheck: [\n {\n description: `index no longer exists on ${collection}`,\n source: new ListIndexesCommand(collection),\n filter,\n expect: 'notExists',\n },\n ],\n };\n}\n\nexport function createCollection(\n collection: string,\n options?: CreateCollectionOptions,\n): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.create`,\n label: `Create collection ${collection}`,\n operationClass: 'additive',\n precheck: [\n {\n description: `collection ${collection} does not exist`,\n source: new ListCollectionsCommand(),\n filter: MongoFieldFilter.eq('name', collection),\n expect: 'notExists',\n },\n ],\n execute: [\n {\n description: `create collection ${collection}`,\n command: new CreateCollectionCommand(collection, options),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function dropCollection(collection: string): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.drop`,\n label: `Drop collection ${collection}`,\n operationClass: 'destructive',\n precheck: [],\n execute: [\n {\n description: `drop collection ${collection}`,\n command: new DropCollectionCommand(collection),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function setValidation(\n collection: string,\n schema: Record<string, unknown>,\n options?: { validationLevel?: 'strict' | 'moderate'; validationAction?: 'error' | 'warn' },\n): MongoMigrationPlanOperation {\n return {\n id: `collection.${collection}.setValidation`,\n label: `Set validation on ${collection}`,\n operationClass: 'destructive',\n precheck: [],\n execute: [\n {\n description: `set validation on ${collection}`,\n command: new CollModCommand(collection, {\n validator: { $jsonSchema: schema },\n validationLevel: options?.validationLevel,\n validationAction: options?.validationAction,\n }),\n },\n ],\n postcheck: [],\n };\n}\n\nexport function validatedCollection(\n name: string,\n schema: Record<string, unknown>,\n indexes: ReadonlyArray<{ keys: MongoIndexKey[]; unique?: boolean }>,\n): MongoMigrationPlanOperation[] {\n return [\n createCollection(name, {\n validator: { $jsonSchema: schema },\n validationLevel: 'strict',\n validationAction: 'error',\n }),\n ...indexes.map((idx) => createIndex(name, idx.keys, { unique: idx.unique })),\n ];\n}\n"],"mappings":"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"}