uql-orm 0.63.0 → 0.64.0

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.
Files changed (34) hide show
  1. package/dist/migrate/builder/expressions.js +1 -15
  2. package/dist/migrate/builder/migrationBuilder.d.ts +6 -28
  3. package/dist/migrate/builder/migrationBuilder.js +9 -83
  4. package/dist/migrate/builder/types.d.ts +14 -24
  5. package/dist/migrate/cli.d.ts +1 -6
  6. package/dist/migrate/cli.js +3 -10
  7. package/dist/migrate/codegen/migrationFile.d.ts +9 -1
  8. package/dist/migrate/codegen/migrationFile.js +2 -1
  9. package/dist/migrate/ddl/indexDdl.d.ts +4 -2
  10. package/dist/migrate/ddl/indexDdl.js +16 -15
  11. package/dist/migrate/generator/mongoCommand.d.ts +9 -9
  12. package/dist/migrate/generator/mongoCommand.js +1 -1
  13. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +21 -26
  14. package/dist/migrate/generator/mongoSchemaGenerator.js +103 -80
  15. package/dist/migrate/index.d.ts +1 -1
  16. package/dist/migrate/index.js +1 -1
  17. package/dist/migrate/indexPredicate.d.ts +8 -0
  18. package/dist/migrate/indexPredicate.js +52 -0
  19. package/dist/migrate/migrationTarget.d.ts +23 -0
  20. package/dist/migrate/migrationTarget.js +48 -0
  21. package/dist/migrate/migrator.d.ts +17 -45
  22. package/dist/migrate/migrator.js +80 -179
  23. package/dist/migrate/schemaGenerator.d.ts +12 -13
  24. package/dist/migrate/schemaGenerator.js +43 -9
  25. package/dist/mongo/mongoDialect.d.ts +6 -1
  26. package/dist/schema/schemaASTBuilder.d.ts +2 -0
  27. package/dist/schema/schemaASTBuilder.js +9 -22
  28. package/dist/type/migration.d.ts +11 -40
  29. package/dist/util/ddlExpression.util.d.ts +3 -1
  30. package/dist/util/ddlExpression.util.js +14 -0
  31. package/dist/util/sqlLiteral.js +5 -3
  32. package/package.json +1 -1
  33. package/dist/migrate/schemaGeneratorAsync.d.ts +0 -7
  34. package/dist/migrate/schemaGeneratorAsync.js +0 -12
@@ -1,16 +1,18 @@
1
- import { AbstractDialect } from '../../dialect/abstractDialect.js';
2
1
  import { getMeta } from '../../entity/index.js';
3
- import { mongoDialectFeatures } from '../../mongo/mongoDialect.js';
4
- import { getKeys } from '../../util/index.js';
2
+ import { MongoDialect } from '../../mongo/mongoDialect.js';
3
+ import { QueryRaw, } from '../../type/index.js';
4
+ import { declaredIndexes, indexNameParts, renderIndexColumn } from '../../util/ddlExpression.util.js';
5
5
  import { derivedIndexName } from '../../util/sql.util.js';
6
+ import { assertIndexFeatures, assertIndexType } from '../ddl/indexDdl.js';
7
+ import { assertIndexPredicate, refusedIndexPredicate } from '../indexPredicate.js';
6
8
  import { renderIndexDefinition } from './definitionToNode.js';
7
- import { indexNodeToSchema } from './indexNodeToSchema.js';
8
9
  import { serializeMongoCommand } from './mongoCommand.js';
9
- export class MongoSchemaGenerator extends AbstractDialect {
10
+ /** The index types a key spec can say: a plain key, or `'text'`. */
11
+ const MONGO_INDEX_TYPES = new Set(['btree', 'fulltext']);
12
+ /** A key spec's one feature beyond its keys: a partial filter. */
13
+ const MONGO_INDEX_FEATURES = new Set(['partial']);
14
+ export class MongoSchemaGenerator extends MongoDialect {
10
15
  defaultForeignKeyAction;
11
- dialectName = 'mongodb';
12
- featureDefaults = mongoDialectFeatures;
13
- insertIdSource = 'returning';
14
16
  constructor(namingStrategy, defaultForeignKeyAction) {
15
17
  super({ namingStrategy });
16
18
  this.defaultForeignKeyAction = defaultForeignKeyAction;
@@ -38,113 +40,117 @@ export class MongoSchemaGenerator extends AbstractDialect {
38
40
  return entities.filter((entity) => wanted.has(this.resolveTableName(getMeta(entity))));
39
41
  }
40
42
  /**
41
- * The indexes `@Field({ index })` declares, as the collection would hold them.
42
- *
43
- * One owner because two paths need it: creating a collection, and working out which of its indexes
44
- * are missing. Derived twice, they drifted the moment either changed how a name is settled.
43
+ * The indexes an entity declares, as the collection would hold them. One owner because two paths need
44
+ * it: creating a collection, and working out which of its indexes are missing.
45
45
  */
46
- fieldIndexes(meta, collectionName) {
47
- return getKeys(meta.fields).flatMap((key) => {
48
- const field = meta.fields[key];
49
- if (!field?.index) {
50
- return [];
51
- }
52
- const columnName = this.resolveColumnName(key, field);
53
- return [
54
- {
55
- name: typeof field.index === 'string' ? field.index : derivedIndexName(collectionName, [columnName]),
56
- entries: [{ column: columnName }],
57
- unique: !!field.unique,
58
- },
59
- ];
60
- });
46
+ indexesOf(meta, collectionName) {
47
+ return declaredIndexes(meta).map((index) => this.indexSchema(meta, collectionName, index));
48
+ }
49
+ /** One declared index, its members resolved to document paths and its `where` to a filter document. */
50
+ indexSchema(meta, collectionName, index) {
51
+ const entries = index.columns
52
+ .map((entry) => renderIndexColumn(entry, () => this.compileDdl()))
53
+ .map((entry) => ({ ...entry, column: this.columnOf(meta, entry.column) }));
54
+ const name = index.name ?? derivedIndexName(collectionName, indexNameParts(entries));
55
+ return {
56
+ name,
57
+ entries,
58
+ unique: index.unique ?? false,
59
+ type: index.type,
60
+ include: index.include,
61
+ where: index.where && this.compileIndexPredicate(index.where, meta.entity, name),
62
+ };
63
+ }
64
+ /**
65
+ * The JSON of the document `partialFilterExpression` takes, refused where the predicate reaches past
66
+ * what that holds or what a migration carries as JSON.
67
+ */
68
+ compileIndexPredicate(where, entity, indexName) {
69
+ if (where instanceof QueryRaw) {
70
+ throw new TypeError(`mongodb does not support partial indexes from a SQL predicate (index "${indexName}")`);
71
+ }
72
+ assertIndexPredicate(where, this.dialectName, indexName);
73
+ const filter = this.renderFilter(entity, where);
74
+ const refused = refusedFilterValue(filter);
75
+ if (refused) {
76
+ throw refusedIndexPredicate(this.dialectName, refused, indexName);
77
+ }
78
+ return JSON.stringify(filter);
61
79
  }
62
80
  generateCreateTable(entity, _options) {
63
81
  const meta = getMeta(entity);
64
82
  const collectionName = this.resolveTableName(meta);
65
- const indexes = this.fieldIndexes(meta, collectionName);
66
83
  // One `createIndex` command each, mirroring the SQL generator's `[CREATE TABLE, ...CREATE INDEX]`,
67
84
  // so the key spec is built here and the migrator only executes it.
68
85
  return [
69
86
  serializeMongoCommand({ action: 'createCollection', name: collectionName }),
70
- ...indexes.map((index) => this.generateCreateIndex(collectionName, index)),
87
+ ...this.indexesOf(meta, collectionName).map((index) => this.generateCreateIndex(collectionName, index)),
71
88
  ];
72
89
  }
73
90
  generateDropTable(tableName) {
74
91
  return serializeMongoCommand({ action: 'dropCollection', name: tableName });
75
92
  }
76
93
  generateAlterTable(diff) {
77
- const statements = [];
78
- if (diff.indexesToAdd?.length) {
79
- for (const index of diff.indexesToAdd) {
80
- statements.push(this.generateCreateIndex(diff.tableName, index));
81
- }
82
- }
83
- return statements;
94
+ return (diff.indexesToAdd ?? []).map((index) => this.generateCreateIndex(diff.tableName, index));
84
95
  }
85
96
  generateAlterTableDown(diff) {
86
- const statements = [];
87
- if (diff.indexesToAdd?.length) {
88
- for (const index of diff.indexesToAdd) {
89
- statements.push(this.generateDropIndex(diff.tableName, index.name));
90
- }
91
- }
92
- return statements;
97
+ return (diff.indexesToAdd ?? []).map((index) => this.generateDropIndex(diff.tableName, index.name));
93
98
  }
94
99
  /**
95
100
  * MongoDB's key spec is where its index options live: `-1` for a descending entry and `'text'` for a
96
101
  * full-text index, which is what `$text` needs since a text index declares its own fields.
97
102
  *
98
- * @remarks The SQL-only modifiers are refused rather than dropped, for the same reason the SQL
99
- * dialects refuse each other's - a silently weaker index is worse than a clear failure. `where`
100
- * included: MongoDB's partial indexes take a filter document, not a SQL predicate.
103
+ * @remarks The SQL-only options are refused by the checks the SQL dialects refuse each other's with - a
104
+ * silently weaker index is worse than a clear failure. `where` is the filter's JSON, as
105
+ * {@link compileIndexPredicate} writes it.
101
106
  */
102
107
  generateCreateIndex(tableName, index) {
108
+ assertIndexType(index, MONGO_INDEX_TYPES, this.dialectName);
109
+ assertIndexFeatures(index, MONGO_INDEX_FEATURES, this.dialectName);
103
110
  const key = {};
104
111
  for (const entry of index.entries) {
105
- if (entry.expression || entry.jsonArray || entry.length !== undefined || entry.nulls || entry.opsClass) {
106
- throw new TypeError(`mongodb does not support that index column option (index "${index.name}")`);
107
- }
108
112
  key[entry.column] = index.type === 'fulltext' ? 'text' : entry.order === 'desc' ? -1 : 1;
109
113
  }
110
- if (index.where) {
111
- throw new TypeError(`mongodb does not support partial indexes from a SQL predicate (index "${index.name}")`);
112
- }
113
114
  return serializeMongoCommand({
114
115
  action: 'createIndex',
115
116
  collection: tableName,
116
117
  name: index.name,
117
118
  key,
118
- options: { unique: index.unique, name: index.name },
119
+ options: {
120
+ unique: index.unique,
121
+ name: index.name,
122
+ partialFilterExpression: index.where && JSON.parse(index.where),
123
+ },
119
124
  });
120
125
  }
121
126
  generateDropIndex(tableName, indexName) {
122
- return serializeMongoCommand({
123
- action: 'dropIndex',
124
- collection: tableName,
125
- name: indexName,
126
- });
127
- }
128
- getSqlType(fieldOptions) {
129
- return '';
130
- }
131
- generateCreateTableFromNode(table, _options) {
132
- return [
133
- serializeMongoCommand({ action: 'createCollection', name: table.name }),
134
- ...table.indexes.map((index) => this.generateCreateIndexFromNode(index)),
135
- ];
136
- }
137
- generateCreateIndexFromNode(index) {
138
- return this.generateCreateIndex(index.table.name, indexNodeToSchema(index));
139
- }
140
- generateCreateTableFromDefinition(table, _options) {
141
- return [
142
- serializeMongoCommand({ action: 'createCollection', name: table.name }),
143
- ...table.indexes.map((index) => this.generateCreateIndex(table.name, renderIndexDefinition(index, () => this.compileDdl()))),
144
- ];
145
- }
146
- generateRenameTableSql(oldName, newName) {
147
- return serializeMongoCommand({ action: 'renameCollection', from: oldName, to: newName });
127
+ return serializeMongoCommand({ action: 'dropIndex', collection: tableName, name: indexName });
128
+ }
129
+ /** A collection and its indexes, which is all a document store has: a column, a constraint or SQL throws. */
130
+ generateOperation(operation) {
131
+ const render = (index) => renderIndexDefinition(index, () => this.compileDdl());
132
+ switch (operation.type) {
133
+ case 'createTable': {
134
+ const { name, columns, indexes } = operation.table;
135
+ if (columns.length) {
136
+ throw new TypeError(`mongodb does not support columns in a migration (collection "${name}")`);
137
+ }
138
+ return [
139
+ serializeMongoCommand({ action: 'createCollection', name }),
140
+ ...indexes.map((index) => this.generateCreateIndex(name, render(index))),
141
+ ];
142
+ }
143
+ case 'dropTable':
144
+ return [this.generateDropTable(operation.tableName)];
145
+ case 'renameTable':
146
+ return [serializeMongoCommand({ action: 'renameCollection', from: operation.oldName, to: operation.newName })];
147
+ case 'createIndex':
148
+ return [this.generateCreateIndex(operation.tableName, render(operation.index))];
149
+ case 'dropIndex':
150
+ return [this.generateDropIndex(operation.tableName, operation.indexName)];
151
+ default:
152
+ throw new TypeError(`mongodb does not support ${operation.type} in a migration`);
153
+ }
148
154
  }
149
155
  diffSchema(entity, currentTable) {
150
156
  const meta = getMeta(entity);
@@ -153,7 +159,7 @@ export class MongoSchemaGenerator extends AbstractDialect {
153
159
  return { tableName: collectionName, type: 'create' };
154
160
  }
155
161
  const existingIndexes = new Set(currentTable.indexes.map((i) => i.name));
156
- const indexesToAdd = this.fieldIndexes(meta, collectionName).filter((index) => !existingIndexes.has(index.name));
162
+ const indexesToAdd = this.indexesOf(meta, collectionName).filter((index) => !existingIndexes.has(index.name));
157
163
  if (indexesToAdd.length === 0) {
158
164
  return undefined;
159
165
  }
@@ -164,3 +170,20 @@ export class MongoSchemaGenerator extends AbstractDialect {
164
170
  };
165
171
  }
166
172
  }
173
+ /** The first value `partialFilterExpression` refuses, `null`, or a migration cannot carry as JSON, such as a `Date`. */
174
+ function refusedFilterValue(value) {
175
+ if (value === null) {
176
+ return 'null';
177
+ }
178
+ if (Array.isArray(value)) {
179
+ return value.map(refusedFilterValue).find(Boolean);
180
+ }
181
+ if (typeof value !== 'object') {
182
+ return typeof value === 'bigint' ? 'a bigint' : undefined;
183
+ }
184
+ if (Object.getPrototypeOf(value) === Object.prototype) {
185
+ return Object.values(value).map(refusedFilterValue).find(Boolean);
186
+ }
187
+ const typeName = value.constructor.name;
188
+ return `${/^[aeiou]/i.test(typeName) ? 'an' : 'a'} ${typeName}`;
189
+ }
@@ -8,9 +8,9 @@ export * from './codegen/index.js';
8
8
  export * from './ddl/index.js';
9
9
  export * from './drift/index.js';
10
10
  export * from './introspection/index.js';
11
+ export { migrationBuilderFor } from './migrationTarget.js';
11
12
  export { type BuilderMigrationDefinition, defineBuilderMigration, defineMigration, Migrator } from './migrator.js';
12
13
  export { createSchemaGenerator, SqlSchemaGenerator } from './schemaGenerator.js';
13
- export { createSchemaGeneratorAsync } from './schemaGeneratorAsync.js';
14
14
  export { DatabaseMigrationStorage } from './storage/databaseStorage.js';
15
15
  export { JsonMigrationStorage } from './storage/jsonStorage.js';
16
16
  export { MongoMigrationStorage } from './storage/mongoStorage.js';
@@ -13,10 +13,10 @@ export * from './drift/index.js';
13
13
  // Schema introspection
14
14
  export * from './introspection/index.js';
15
15
  // Main migrator
16
+ export { migrationBuilderFor } from './migrationTarget.js';
16
17
  export { defineBuilderMigration, defineMigration, Migrator } from './migrator.js';
17
18
  // Schema generators
18
19
  export { createSchemaGenerator, SqlSchemaGenerator } from './schemaGenerator.js';
19
- export { createSchemaGeneratorAsync } from './schemaGeneratorAsync.js';
20
20
  // Storage implementations
21
21
  export { DatabaseMigrationStorage } from './storage/databaseStorage.js';
22
22
  export { JsonMigrationStorage } from './storage/jsonStorage.js';
@@ -0,0 +1,8 @@
1
+ import type { DialectName, EntityWhereMeta } from '../type/index.js';
2
+ /**
3
+ * Refuses a partial index's predicate reaching past what the engine takes, before it compiles to what
4
+ * only the server would reject, naming the operator as its author wrote it. A `raw` one is left to the server.
5
+ */
6
+ export declare function assertIndexPredicate<E>(where: EntityWhereMeta<E>, dialectName: DialectName, indexName: string): void;
7
+ /** What refusing any part of a partial index's predicate reports. */
8
+ export declare function refusedIndexPredicate(dialectName: string, part: string, indexName: string): TypeError;
@@ -0,0 +1,52 @@
1
+ import { QueryRaw } from '../type/queryRaw.js';
2
+ import { isOperatorObject } from '../util/object.util.js';
3
+ /**
4
+ * The `$where` a partial index takes, on the engines where that is less than a query's: SQL Server's
5
+ * `CREATE INDEX` `<filter_predicate>` (comparisons and `IN` on plain columns, joined by `AND`), and
6
+ * MongoDB's `partialFilterExpression` (https://www.mongodb.com/docs/manual/core/index-partial/).
7
+ */
8
+ const PREDICATE_GRAMMARS = {
9
+ mssql: {
10
+ rootOps: new Set(['$and']),
11
+ fieldOps: new Set(['$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in', '$isNull', '$isNotNull']),
12
+ jsonPaths: false,
13
+ },
14
+ mongodb: {
15
+ rootOps: new Set(['$and', '$or']),
16
+ fieldOps: new Set(['$eq', '$gt', '$gte', '$lt', '$lte', '$between', '$in']),
17
+ jsonPaths: true,
18
+ },
19
+ };
20
+ /**
21
+ * Refuses a partial index's predicate reaching past what the engine takes, before it compiles to what
22
+ * only the server would reject, naming the operator as its author wrote it. A `raw` one is left to the server.
23
+ */
24
+ export function assertIndexPredicate(where, dialectName, indexName) {
25
+ const grammar = PREDICATE_GRAMMARS[dialectName];
26
+ const refused = grammar && !(where instanceof QueryRaw) ? refusedOperator(where, grammar) : undefined;
27
+ if (refused) {
28
+ throw refusedIndexPredicate(dialectName, refused, indexName);
29
+ }
30
+ }
31
+ /** What refusing any part of a partial index's predicate reports. */
32
+ export function refusedIndexPredicate(dialectName, part, indexName) {
33
+ return new TypeError(`${dialectName} does not support ${part} in a partial index predicate (index "${indexName}")`);
34
+ }
35
+ /** The first part of `where` outside `grammar`, depth-first; a `raw` clause is left alone. */
36
+ function refusedOperator(where, grammar) {
37
+ return Object.entries(where)
38
+ .map(([key, value]) => {
39
+ if (key.includes('.') && !grammar.jsonPaths) {
40
+ return 'a JSON path';
41
+ }
42
+ if (!key.startsWith('$')) {
43
+ return isOperatorObject(value) ? Object.keys(value).find((op) => !grammar.fieldOps.has(op)) : undefined;
44
+ }
45
+ if (!grammar.rootOps.has(key)) {
46
+ return key;
47
+ }
48
+ const clauses = Array.isArray(value) ? value.filter((clause) => !(clause instanceof QueryRaw)) : [];
49
+ return clauses.map((clause) => refusedOperator(clause, grammar)).find(Boolean);
50
+ })
51
+ .find(Boolean);
52
+ }
@@ -0,0 +1,23 @@
1
+ import type { ForeignKeyAction } from '../schema/types.js';
2
+ import { type MigrationStorage, type MigratorDialect, type Querier, type QuerierPool, type SchemaGenerator } from '../type/index.js';
3
+ import { MigrationBuilder } from './builder/migrationBuilder.js';
4
+ import { type MigrationSource } from './codegen/migrationFile.js';
5
+ /** A migration querier as its engine family drives it. */
6
+ export type MigrationSession = {
7
+ readonly querier: Querier;
8
+ /** Runs one statement its generator wrote. */
9
+ run(statement: string): Promise<unknown>;
10
+ /** `work` in one transaction where the engine takes DDL in one; MongoDB creates collections outside any. */
11
+ transaction(work: () => Promise<void>): Promise<void>;
12
+ };
13
+ /** Everything a migrator does differently per engine family, chosen once from its dialect. */
14
+ export type MigrationTarget = {
15
+ readonly source: MigrationSource;
16
+ storage(pool: QuerierPool, tableName: string | undefined): MigrationStorage;
17
+ /** The schema generator, `undefined` for a dialect with none. Async because MongoDB's loads its optional peer. */
18
+ generator(dialect: MigratorDialect, defaultForeignKeyAction?: ForeignKeyAction): Promise<SchemaGenerator | undefined>;
19
+ withSession<T>(pool: QuerierPool, task: (session: MigrationSession) => Promise<T>): Promise<T>;
20
+ };
21
+ export declare function migrationTargetFor(dialect: MigratorDialect): MigrationTarget;
22
+ /** A builder running each operation on `querier`, as SQL or as MongoDB driver commands. */
23
+ export declare function migrationBuilderFor(querier: Querier): Promise<MigrationBuilder>;
@@ -0,0 +1,48 @@
1
+ import { isKnownMigratorDialect, isMongoQuerier, isSqlQuerier, } from '../type/index.js';
2
+ import { withMongoQuerierForMigrations, withSqlQuerierForMigrations } from './acquireQuerierForMigrations.js';
3
+ import { MigrationBuilder } from './builder/migrationBuilder.js';
4
+ import { migrationSource } from './codegen/migrationFile.js';
5
+ import { runMongoCommand } from './generator/mongoCommand.js';
6
+ import { createSchemaGenerator, SqlSchemaGenerator } from './schemaGenerator.js';
7
+ import { DatabaseMigrationStorage } from './storage/databaseStorage.js';
8
+ import { MongoMigrationStorage } from './storage/mongoStorage.js';
9
+ const sqlSession = (querier) => ({
10
+ querier,
11
+ run: (statement) => querier.run(statement),
12
+ transaction: (work) => querier.transaction(work),
13
+ });
14
+ const mongoSession = (querier) => ({
15
+ querier,
16
+ run: (statement) => runMongoCommand(querier.db, statement),
17
+ transaction: (work) => work(),
18
+ });
19
+ /** Imported on use, so the optional `mongodb` peer loads only on MongoDB. */
20
+ async function mongoSchemaGenerator(namingStrategy, defaultForeignKeyAction) {
21
+ const { MongoSchemaGenerator } = await import('./generator/mongoSchemaGenerator.js');
22
+ return new MongoSchemaGenerator(namingStrategy, defaultForeignKeyAction);
23
+ }
24
+ const sqlTarget = {
25
+ source: migrationSource.SqlQuerier,
26
+ storage: (pool, tableName) => new DatabaseMigrationStorage(pool, { tableName }),
27
+ generator: async (dialect, defaultForeignKeyAction) => isKnownMigratorDialect(dialect.dialectName) ? createSchemaGenerator(dialect, defaultForeignKeyAction) : undefined,
28
+ withSession: (pool, task) => withSqlQuerierForMigrations(pool, 'Migrator', (querier) => task(sqlSession(querier))),
29
+ };
30
+ const mongoTarget = {
31
+ source: migrationSource.MongoQuerier,
32
+ storage: (pool, tableName) => new MongoMigrationStorage(pool, { tableName }),
33
+ generator: (dialect, defaultForeignKeyAction) => mongoSchemaGenerator(dialect.namingStrategy, defaultForeignKeyAction),
34
+ withSession: (pool, task) => withMongoQuerierForMigrations(pool, 'Migrator', (querier) => task(mongoSession(querier))),
35
+ };
36
+ export function migrationTargetFor(dialect) {
37
+ return dialect.dialectName === 'mongodb' ? mongoTarget : sqlTarget;
38
+ }
39
+ /** A builder running each operation on `querier`, as SQL or as MongoDB driver commands. */
40
+ export async function migrationBuilderFor(querier) {
41
+ if (isSqlQuerier(querier)) {
42
+ return new MigrationBuilder(new SqlSchemaGenerator(querier.dialect), sqlSession(querier).run);
43
+ }
44
+ if (isMongoQuerier(querier)) {
45
+ return new MigrationBuilder(await mongoSchemaGenerator(), mongoSession(querier).run);
46
+ }
47
+ throw new TypeError('A migration builder needs a SQL or a MongoDB querier');
48
+ }
@@ -1,4 +1,4 @@
1
- import type { DialectName, LoggingOptions, Migration, MigrationDefinition, MigrationResult, MigrationStorage, MigratorDialect, MigratorOptions, MongoQuerier, Querier, QuerierPool, SchemaDiff, SchemaGenerator, SchemaIntrospector, SqlQuerier, SyncOptions, Type } from '../type/index.js';
1
+ import type { DialectName, LoggingOptions, Migration, MigrationDefinition, MigrationResult, MigrationStorage, MigratorDialect, MigratorOptions, Querier, QuerierPool, SchemaDiff, SchemaGenerator, SchemaIntrospector, SqlQuerier, SyncOptions, Type } from '../type/index.js';
2
2
  import { LoggerWrapper } from '../util/index.js';
3
3
  import type { IMigrationBuilder } from './builder/types.js';
4
4
  /**
@@ -14,23 +14,16 @@ export declare class Migrator {
14
14
  private readonly _entities?;
15
15
  get entities(): Type<object>[];
16
16
  readonly dialectName: DialectName;
17
+ /** The generator given, or this dialect's once {@link getSchemaGenerator} has loaded it. */
17
18
  schemaGenerator?: SchemaGenerator;
18
19
  schemaIntrospector?: SchemaIntrospector;
19
- private readonly _defaultForeignKeyAction?;
20
- private _mongoSchemaLoadPromise?;
20
+ private readonly defaultForeignKeyAction?;
21
+ private readonly target;
21
22
  constructor(pool: QuerierPool<Querier, MigratorDialect>, options?: MigratorOptions);
22
- /**
23
- * Loads MongoDB's schema generator on first use, so the optional `mongodb` peer loads only then. SQL
24
- * generators are set in the constructor (or via {@link setSchemaGenerator}).
25
- */
26
- ensureSchemaGenerator(): Promise<void>;
27
- /**
28
- * Set the schema generator for DDL operations
29
- */
30
- setSchemaGenerator(generator: SchemaGenerator): void;
23
+ /** The schema generator, loaded on first use: MongoDB's needs its optional peer. */
24
+ getSchemaGenerator(): Promise<SchemaGenerator>;
31
25
  /** `schema` reads one namespace instead of the connection's own; see {@link BaseSqlIntrospector.schema}. */
32
26
  protected createIntrospector(schema?: string): SchemaIntrospector | undefined;
33
- protected createGenerator(): SchemaGenerator | undefined;
34
27
  /**
35
28
  * Get all discovered migrations from the migrations directory
36
29
  */
@@ -69,14 +62,6 @@ export declare class Migrator {
69
62
  * Run a single migration, within a transaction where the dialect has one for it
70
63
  */
71
64
  runMigration(migration: Migration<Querier>, direction: 'up' | 'down'): Promise<MigrationResult>;
72
- /**
73
- * A migration querier, and how to run work in one transaction on it. MongoDB gets none: it creates
74
- * collections and indexes outside any transaction. SQL asserts its querier before opening one, so a
75
- * wrong querier reports which one the dialect needs rather than a missing `transaction`.
76
- */
77
- private withMigrationQuerier;
78
- /** What this dialect's migration files are written against. */
79
- private get migrationQuerier();
80
65
  /**
81
66
  * Generate a new migration file
82
67
  */
@@ -99,7 +84,6 @@ export declare class Migrator {
99
84
  * {@link schemaIntrospector} so a caller that replaced it still wins.
100
85
  */
101
86
  private introspectClaimedSchemas;
102
- findEntityForTable(tableName: string): Promise<Type<object> | undefined>;
103
87
  /**
104
88
  * Applies the entity schema to the database: every registered entity, or the one `entity` names.
105
89
  *
@@ -123,8 +107,6 @@ export declare class Migrator {
123
107
  * settle instead of colliding; an existing one still pays for introspection, as a diff needs columns.
124
108
  */
125
109
  private planEntity;
126
- /** An alter diff as statements, narrowed to what the caller allows. */
127
- private alterFromDiff;
128
110
  /** The same for one entity against the table it already has, and nothing where the two agree. */
129
111
  private alterFromEntity;
130
112
  /** The configured entities, with `entity` among them however the migrator was built. */
@@ -146,30 +128,19 @@ export declare class Migrator {
146
128
  */
147
129
  private createSchema;
148
130
  /**
149
- * Each pending diff with the entity it came from, since resolving that is async and every caller
150
- * needs it. What to emit stays with the caller: a sync narrows the forward direction to what the
151
- * caller allows and never asks for the rollback, which on SQLite cannot even be expressed (no
152
- * `ALTER COLUMN`), so computing it eagerly for everyone would throw there.
153
- */
154
- private pendingDiffs;
155
- /**
156
- * The schema generator. A getter because MongoDB's loads lazily (see {@link ensureSchemaGenerator}),
157
- * so every caller had to repeat the same assertion after awaiting it.
131
+ * The pending diffs a sync or a generated migration acts on: the tables to create and the tables to
132
+ * alter. What to emit for each stays with the caller: a sync narrows an alter to what it allows and
133
+ * never asks for the rollback, which on SQLite cannot even be expressed (no `ALTER COLUMN`).
158
134
  */
159
- private get generator();
135
+ private pendingChanges;
160
136
  protected filterDiff(diff: SchemaDiff, options: {
161
137
  safe?: boolean;
162
138
  drop?: boolean;
163
139
  }): SchemaDiff;
140
+ /** Runs the statements a generator wrote, in one transaction where the engine takes DDL in one. */
164
141
  executeSyncStatements(statements: string[], options: {
165
142
  logging?: boolean;
166
143
  }): Promise<void>;
167
- executeMongoSyncStatements(statements: string[], options: {
168
- logging?: boolean;
169
- }, querier: MongoQuerier): Promise<void>;
170
- executeSqlSyncStatements(statements: string[], options: {
171
- logging?: boolean;
172
- }, querier: Querier): Promise<void>;
173
144
  /**
174
145
  * Get migration status
175
146
  */
@@ -208,12 +179,13 @@ export declare class Migrator {
208
179
  export declare function defineMigration<Q extends Querier = SqlQuerier>(migration: MigrationDefinition<Q>): MigrationDefinition<Q>;
209
180
  /**
210
181
  * Migration definition that uses the type-safe builder API. The querier is the builder's own, so a
211
- * data backfill it runs lands in the same transaction as the schema change.
182
+ * data backfill it runs lands in the same transaction as the schema change. On MongoDB, `Q` is
183
+ * `MongoQuerier` and the builder takes collections and their indexes.
212
184
  */
213
- export interface BuilderMigrationDefinition {
185
+ export interface BuilderMigrationDefinition<Q extends Querier = SqlQuerier> {
214
186
  readonly name?: string;
215
- up(builder: IMigrationBuilder, querier: SqlQuerier): Promise<void>;
216
- down(builder: IMigrationBuilder, querier: SqlQuerier): Promise<void>;
187
+ up(builder: IMigrationBuilder, querier: Q): Promise<void>;
188
+ down(builder: IMigrationBuilder, querier: Q): Promise<void>;
217
189
  }
218
190
  /**
219
191
  * Define a migration using the type-safe builder API.
@@ -234,4 +206,4 @@ export interface BuilderMigrationDefinition {
234
206
  * });
235
207
  * ```
236
208
  */
237
- export declare function defineBuilderMigration(migration: BuilderMigrationDefinition): MigrationDefinition;
209
+ export declare function defineBuilderMigration<Q extends Querier = SqlQuerier>(migration: BuilderMigrationDefinition<Q>): MigrationDefinition<Q>;