uql-orm 0.61.0 → 0.63.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 (106) hide show
  1. package/dist/browser/uql-browser.min.js.map +1 -1
  2. package/dist/bunSql/bunSql.util.d.ts +15 -15
  3. package/dist/bunSql/bunSql.util.js +22 -35
  4. package/dist/bunSql/bunSqlQuerier.d.ts +2 -2
  5. package/dist/bunSql/bunSqlQuerier.js +3 -3
  6. package/dist/bunSql/bunSqlQuerierPool.d.ts +1 -13
  7. package/dist/bunSql/bunSqlQuerierPool.js +3 -34
  8. package/dist/d1/d1Querier.d.ts +12 -4
  9. package/dist/d1/d1Querier.js +6 -11
  10. package/dist/d1/d1QuerierPool.d.ts +7 -3
  11. package/dist/d1/d1QuerierPool.js +5 -3
  12. package/dist/dialect/abstractSqlDialect.d.ts +12 -7
  13. package/dist/dialect/abstractSqlDialect.js +51 -50
  14. package/dist/dialect/mysqlLikeSqlDialect.js +1 -1
  15. package/dist/dialect/pgLikeSqlDialect.d.ts +1 -0
  16. package/dist/dialect/pgLikeSqlDialect.js +8 -7
  17. package/dist/dialect/queryContext.d.ts +5 -6
  18. package/dist/dialect/queryContext.js +8 -8
  19. package/dist/entity/decorator/entity.d.ts +6 -10
  20. package/dist/entity/decorator/entity.js +4 -8
  21. package/dist/entity/decorator/members.d.ts +3 -2
  22. package/dist/entity/decorator/members.js +1 -0
  23. package/dist/entity/metadata/definition.d.ts +2 -2
  24. package/dist/entity/metadata/definition.js +23 -26
  25. package/dist/libsql/libsqlDialect.d.ts +1 -1
  26. package/dist/libsql/libsqlDialect.js +1 -1
  27. package/dist/libsql/libsqlQuerierPool.d.ts +18 -9
  28. package/dist/libsql/libsqlQuerierPool.js +32 -20
  29. package/dist/migrate/builder/migrationBuilder.js +3 -5
  30. package/dist/migrate/builder/tableBuilder.js +2 -4
  31. package/dist/migrate/builder/types.d.ts +11 -3
  32. package/dist/migrate/codegen/index.d.ts +1 -1
  33. package/dist/migrate/codegen/index.js +1 -1
  34. package/dist/migrate/codegen/indexDecoratorSource.d.ts +1 -1
  35. package/dist/migrate/codegen/indexDecoratorSource.js +4 -6
  36. package/dist/migrate/codegen/migrationFile.d.ts +0 -4
  37. package/dist/migrate/codegen/migrationFile.js +0 -2
  38. package/dist/migrate/generator/definitionToNode.d.ts +8 -5
  39. package/dist/migrate/generator/definitionToNode.js +13 -4
  40. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +2 -0
  41. package/dist/migrate/generator/mongoSchemaGenerator.js +6 -1
  42. package/dist/migrate/schemaGenerator.d.ts +5 -3
  43. package/dist/migrate/schemaGenerator.js +9 -2
  44. package/dist/mongo/mongoDialect.js +1 -1
  45. package/dist/mssql/mssqlDialect.js +3 -5
  46. package/dist/querier/abstractSharedHandleQuerierPool.d.ts +5 -5
  47. package/dist/querier/abstractSharedHandleQuerierPool.js +5 -5
  48. package/dist/schema/schemaASTBuilder.d.ts +6 -1
  49. package/dist/schema/schemaASTBuilder.js +17 -16
  50. package/dist/sqlite/abstractSqliteQuerier.d.ts +11 -28
  51. package/dist/sqlite/abstractSqliteQuerier.js +14 -33
  52. package/dist/sqlite/bunSqliteAdapter.bun.d.ts +5 -4
  53. package/dist/sqlite/bunSqliteAdapter.bun.js +1 -1
  54. package/dist/sqlite/hranaQuerier.d.ts +6 -4
  55. package/dist/sqlite/hranaQuerier.js +4 -13
  56. package/dist/sqlite/index.d.ts +0 -1
  57. package/dist/sqlite/index.js +0 -1
  58. package/dist/sqlite/localSqliteQuerierPool.d.ts +14 -5
  59. package/dist/sqlite/nodeSqliteAdapter.d.ts +3 -4
  60. package/dist/sqlite/nodeSqliteAdapter.js +3 -6
  61. package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -3
  62. package/dist/sqlite/nodeSqliteQuerierPool.js +3 -1
  63. package/dist/sqlite/sqliteDialect.d.ts +1 -1
  64. package/dist/sqlite/sqliteDialect.js +1 -1
  65. package/dist/sqlite/sqlitePragmas.d.ts +2 -11
  66. package/dist/sqlite/sqlitePragmas.js +1 -1
  67. package/dist/sqlite/sqliteQuerier.d.ts +29 -10
  68. package/dist/sqlite/sqliteQuerier.js +26 -4
  69. package/dist/sqlite/sqliteQuerierPool.d.ts +7 -3
  70. package/dist/sqlite/sqliteQuerierPool.js +12 -8
  71. package/dist/turso/index.d.ts +1 -0
  72. package/dist/turso/index.js +1 -0
  73. package/dist/turso/local.d.ts +1 -1
  74. package/dist/turso/local.js +1 -1
  75. package/dist/turso/tursoDialect.d.ts +4 -9
  76. package/dist/turso/tursoDialect.js +4 -12
  77. package/dist/turso/tursoLocalDialect.d.ts +10 -0
  78. package/dist/turso/tursoLocalDialect.js +13 -0
  79. package/dist/turso/tursoLocalQuerierPool.d.ts +8 -13
  80. package/dist/turso/tursoLocalQuerierPool.js +6 -5
  81. package/dist/turso/tursoQuerierPool.d.ts +15 -30
  82. package/dist/turso/tursoQuerierPool.js +13 -23
  83. package/dist/turso/tursoSessionQuerier.d.ts +57 -0
  84. package/dist/turso/tursoSessionQuerier.js +50 -0
  85. package/dist/type/dialect.d.ts +15 -6
  86. package/dist/type/entity.d.ts +108 -73
  87. package/dist/type/migration.d.ts +9 -2
  88. package/dist/type/query.d.ts +3 -3
  89. package/dist/type/queryLock.d.ts +7 -7
  90. package/dist/type/queryLock.js +8 -6
  91. package/dist/type/queryRaw.d.ts +30 -30
  92. package/dist/type/queryRaw.js +14 -9
  93. package/dist/util/ddlExpression.util.d.ts +8 -13
  94. package/dist/util/ddlExpression.util.js +14 -23
  95. package/dist/util/dialect.util.d.ts +1 -1
  96. package/dist/util/dialect.util.js +3 -4
  97. package/dist/util/field.util.d.ts +1 -1
  98. package/dist/util/raw.d.ts +24 -17
  99. package/dist/util/raw.js +46 -17
  100. package/dist/util/wideNumber.d.ts +2 -2
  101. package/dist/util/wideNumber.js +2 -2
  102. package/package.json +2 -2
  103. package/dist/sqlite/hranaQuerierPool.d.ts +0 -20
  104. package/dist/sqlite/hranaQuerierPool.js +0 -26
  105. package/dist/turso/tursoLocalQuerier.d.ts +0 -24
  106. package/dist/turso/tursoLocalQuerier.js +0 -20
@@ -1,6 +1,6 @@
1
1
  import { SOFT_DELETE_FILTER } from '../../type/index.js';
2
2
  import { isInlinedExpression } from '../../util/field.util.js';
3
- import { entityName, fieldOptionConflict, getKeys, ddlText, hasKeys, isToManyRelation, lowerFirst, normalizeIndexColumn, upperFirst, definedEntries, } from '../../util/index.js';
3
+ import { entityName, entitySql, entityWhere, fieldOptionConflict, getKeys, hasKeys, isToManyRelation, lowerFirst, memberRefs, normalizeIndexColumn, upperFirst, definedEntries, } from '../../util/index.js';
4
4
  import { ownRegistrations } from '../decorator/bag.js';
5
5
  /**
6
6
  * A map held on `globalThis` through the global symbol registry, so a single one survives multiple
@@ -31,8 +31,14 @@ export function defineField(entity, key, opts = {}) {
31
31
  // Flagged when the author gave `references` but no `type`, so schema generation knows to resolve the
32
32
  // column from the referenced primary key (picking up its `columnType`, length and chained keys)
33
33
  // instead of treating whatever ends up in `type` as deliberate.
34
- const resolved = opts.type ? opts : { ...opts, typeFromReference: true };
35
- meta.fields[fieldKey] = { ...meta.fields[fieldKey], name: key, ...resolved };
34
+ const { computed, ...rest } = opts;
35
+ const resolved = rest.type ? rest : { ...rest, typeFromReference: true };
36
+ meta.fields[fieldKey] = {
37
+ ...meta.fields[fieldKey],
38
+ name: key,
39
+ ...resolved,
40
+ ...(computed && { computed: entitySql(computed) }),
41
+ };
36
42
  return meta;
37
43
  }
38
44
  export function defineId(entity, key, opts) {
@@ -50,8 +56,8 @@ export function defineRelation(entity, key, opts) {
50
56
  export function relationRegistration({ mappedBy, references, ...opts }) {
51
57
  return {
52
58
  ...opts,
53
- ...(mappedBy ? { mappedBy: mappedBy(keyMap()) } : {}),
54
- ...(references ? { references: [...references(keyMap(), keyMap())] } : {}),
59
+ ...(mappedBy && { mappedBy: mappedBy(keyMap()) }),
60
+ ...(references && { references: [...references(keyMap(), keyMap())] }),
55
61
  };
56
62
  }
57
63
  /** Every entity's key map: a callback only reads one property off it, and that property is its own key. */
@@ -77,26 +83,22 @@ function addRelation(entity, key, registration) {
77
83
  }
78
84
  export function defineHook(entity, methodName, event) {
79
85
  const meta = ensureWritableMeta(entity);
80
- if (!meta.hooks)
81
- meta.hooks = {};
82
- if (!meta.hooks[event])
83
- meta.hooks[event] = [];
84
- meta.hooks[event].push({ methodName });
86
+ ((meta.hooks ??= {})[event] ??= []).push({ methodName });
85
87
  return meta;
86
88
  }
87
89
  /**
88
- * Declares a composite index, its columns read off the key map. `unique` and the authored column sugar
89
- * are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
90
+ * Declares a composite index, its columns read off the entity's refs. `unique` and the authored column
91
+ * sugar are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
90
92
  */
91
93
  export function defineIndex(entity, index) {
92
94
  const meta = ensureWritableMeta(entity);
93
- const keys = keyMap();
95
+ const refs = memberRefs();
94
96
  (meta.indexes ??= []).push({
95
97
  ...index,
96
98
  unique: index.unique ?? false,
97
- where: ddlText(index.where, 'a partial-index predicate'),
98
- columns: index.columns(keys).map(normalizeIndexColumn),
99
- include: index.include?.(keys),
99
+ where: index.where && entityWhere(index.where),
100
+ columns: index.columns(refs).map(normalizeIndexColumn),
101
+ include: index.include?.(refs).map((ref) => ref.key),
100
102
  });
101
103
  return meta;
102
104
  }
@@ -108,9 +110,7 @@ export function defineFilter(entity, name, opts) {
108
110
  if (opts.security && opts.onMissing === 'skip') {
109
111
  throw TypeError(`'${entity.name}' security filter '${name}' cannot use onMissing: 'skip' (it must fail closed)`);
110
112
  }
111
- if (!meta.filters)
112
- meta.filters = {};
113
- meta.filters[name] = opts;
113
+ (meta.filters ??= {})[name] = opts;
114
114
  return meta;
115
115
  }
116
116
  /**
@@ -161,7 +161,7 @@ export function defineEntity(entity, opts = {}) {
161
161
  });
162
162
  // Unnamed checks are named by the generator, as unnamed indexes are.
163
163
  for (const check of opts.checks ?? []) {
164
- (meta.checks ??= []).push({ name: check.name, expression: ddlText(check.expression, 'a check constraint') });
164
+ (meta.checks ??= []).push({ name: check.name, where: entityWhere(check.where) });
165
165
  }
166
166
  for (const index of opts.indexes ?? []) {
167
167
  defineIndex(entity, index);
@@ -202,9 +202,7 @@ export function defineEntity(entity, opts = {}) {
202
202
  }
203
203
  if (softDeleteKeys.length) {
204
204
  meta.softDelete = softDeleteKeys[0];
205
- if (!meta.filters)
206
- meta.filters = {};
207
- meta.filters[SOFT_DELETE_FILTER] = { condition: { [meta.softDelete]: null }, default: true };
205
+ (meta.filters ??= {})[SOFT_DELETE_FILTER] = { where: { [meta.softDelete]: null }, default: true };
208
206
  }
209
207
  const ids = getIdKeys(meta);
210
208
  if (!ids.length) {
@@ -500,10 +498,9 @@ function extendMeta(target, source) {
500
498
  }
501
499
  // Merge hooks from parent entity (parent hooks execute first)
502
500
  if (source.hooks) {
503
- if (!target.hooks)
504
- target.hooks = {};
501
+ const hooks = (target.hooks ??= {});
505
502
  for (const [event, sourceList] of definedEntries(source.hooks)) {
506
- target.hooks[event] = [...sourceList, ...(target.hooks[event] ?? [])];
503
+ hooks[event] = [...sourceList, ...(hooks[event] ?? [])];
507
504
  }
508
505
  }
509
506
  }
@@ -12,7 +12,7 @@ export declare class LibsqlDialect extends SqliteDialect {
12
12
  * functions this dialect would otherwise inherit are never present.
13
13
  *
14
14
  * @remarks `inner` and `l1` are left out: `vector_distance_dot` only exists in the newer Rust
15
- * engine (see `TursoDialect`) and no libSQL build has an L1 metric. Both raise the same
15
+ * engine (see `TursoLocalDialect`) and no libSQL build has an L1 metric. Both raise the same
16
16
  * "does not support vector distance metric" error as any other unsupported metric.
17
17
  */
18
18
  readonly vectorMetrics: ReadonlyMap<VectorDistance, VectorMetric>;
@@ -11,7 +11,7 @@ export class LibsqlDialect extends SqliteDialect {
11
11
  * functions this dialect would otherwise inherit are never present.
12
12
  *
13
13
  * @remarks `inner` and `l1` are left out: `vector_distance_dot` only exists in the newer Rust
14
- * engine (see `TursoDialect`) and no libSQL build has an L1 metric. Both raise the same
14
+ * engine (see `TursoLocalDialect`) and no libSQL build has an L1 metric. Both raise the same
15
15
  * "does not support vector distance metric" error as any other unsupported metric.
16
16
  */
17
17
  vectorMetrics = new Map([
@@ -1,19 +1,28 @@
1
1
  import type { Config } from '@libsql/client';
2
+ import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
2
3
  import { type HranaClient, HranaQuerier } from '../sqlite/hranaQuerier.js';
3
- import { AbstractHranaQuerierPool } from '../sqlite/hranaQuerierPool.js';
4
4
  import type { ExtraOptions } from '../type/index.js';
5
5
  import { LibsqlDialect } from './libsqlDialect.js';
6
- /** Embedded replica: local `file:` DB + `syncUrl` remote - DDL should run on the remote (sqld). */
7
- export declare function libsqlUseRemoteForMigrations(config: Pick<Config, 'url' | 'syncUrl'>): boolean;
8
- export declare class LibsqlQuerierPool extends AbstractHranaQuerierPool<LibsqlDialect> {
6
+ /**
7
+ * Pool for libSQL. One client serves every querier, since Hrana keeps no per-connection state: a
8
+ * transaction takes its own session handle. The pool builds that client from `@libsql/client`'s
9
+ * `Config`, or shares one the caller built (`@libsql/client/web`, `@libsql/client-wasm`), which stays
10
+ * theirs to close.
11
+ */
12
+ export declare class LibsqlQuerierPool extends AbstractSharedHandleQuerierPool<HranaClient, HranaQuerier, LibsqlDialect> {
9
13
  private readonly conf;
10
- constructor(conf: Config, extra?: ExtraOptions);
11
- protected openClient(): Promise<HranaClient>;
14
+ constructor(conf: Config | HranaClient, extra?: ExtraOptions);
15
+ protected openDb(): Promise<HranaClient>;
16
+ protected buildQuerier(client: HranaClient): HranaQuerier;
17
+ end(): Promise<void>;
12
18
  /**
13
- * For embedded replicas (`file:` + `syncUrl`), returns a querier connected to `syncUrl` so migrations hit sqld.
14
- * Otherwise same as `getQuerier`. The migrator calls this for `up`/`down`, `syncForce`, and `autoSync` DDL.
19
+ * For an embedded replica - a `file:` url with a `syncUrl` - a querier on the sync url, so migrations
20
+ * reach sqld, its client closing with it. Anything else migrates like any other querier.
15
21
  */
16
22
  getMigrationQuerier(): Promise<HranaQuerier>;
17
- /** Imported on use, so `uql-orm/libsql` loads without the optional `@libsql/client` peer installed. */
23
+ /**
24
+ * Imported on use, so `uql-orm/libsql` loads without the optional `@libsql/client` peer installed.
25
+ * Integers read as `bigint` whatever the config asks, so the querier decodes one past 2^53 exactly.
26
+ */
18
27
  private createClient;
19
28
  }
@@ -1,39 +1,51 @@
1
1
  import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
2
+ import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
2
3
  import { HranaQuerier } from '../sqlite/hranaQuerier.js';
3
- import { AbstractHranaQuerierPool } from '../sqlite/hranaQuerierPool.js';
4
4
  import { LibsqlDialect } from './libsqlDialect.js';
5
- /** Embedded replica: local `file:` DB + `syncUrl` remote - DDL should run on the remote (sqld). */
6
- export function libsqlUseRemoteForMigrations(config) {
7
- return Boolean(config.syncUrl && config.url.startsWith('file:'));
8
- }
9
- /** Remote-only client: same options as the replica, but `url` is `syncUrl` and embedded-replica fields are dropped. */
10
- function remoteMigrationClientConfig(config) {
11
- const { syncUrl, url: _localUrl, ...rest } = config;
12
- return { ...rest, url: syncUrl };
13
- }
14
- export class LibsqlQuerierPool extends AbstractHranaQuerierPool {
5
+ /**
6
+ * Pool for libSQL. One client serves every querier, since Hrana keeps no per-connection state: a
7
+ * transaction takes its own session handle. The pool builds that client from `@libsql/client`'s
8
+ * `Config`, or shares one the caller built (`@libsql/client/web`, `@libsql/client-wasm`), which stays
9
+ * theirs to close.
10
+ */
11
+ export class LibsqlQuerierPool extends AbstractSharedHandleQuerierPool {
15
12
  conf;
16
13
  constructor(conf, extra) {
17
14
  super(new LibsqlDialect(dialectOptionsFrom(extra)), extra);
18
15
  this.conf = conf;
19
16
  }
20
- openClient() {
21
- return this.createClient(this.conf);
17
+ async openDb() {
18
+ return 'execute' in this.conf ? this.conf : this.createClient(this.conf);
19
+ }
20
+ buildQuerier(client) {
21
+ return new HranaQuerier(client, this.dialect, this.extra);
22
+ }
23
+ async end() {
24
+ if (!('execute' in this.conf)) {
25
+ await super.end();
26
+ }
22
27
  }
23
28
  /**
24
- * For embedded replicas (`file:` + `syncUrl`), returns a querier connected to `syncUrl` so migrations hit sqld.
25
- * Otherwise same as `getQuerier`. The migrator calls this for `up`/`down`, `syncForce`, and `autoSync` DDL.
29
+ * For an embedded replica - a `file:` url with a `syncUrl` - a querier on the sync url, so migrations
30
+ * reach sqld, its client closing with it. Anything else migrates like any other querier.
26
31
  */
27
32
  async getMigrationQuerier() {
28
- if (!libsqlUseRemoteForMigrations(this.conf)) {
33
+ if ('execute' in this.conf) {
29
34
  return this.getQuerier();
30
35
  }
31
- const remote = await this.createClient(remoteMigrationClientConfig(this.conf));
32
- return new HranaQuerier(remote, this.dialect, this.extra, { closeClientOnRelease: true });
36
+ const { syncUrl, url, ...remote } = this.conf;
37
+ if (!syncUrl || !url.startsWith('file:')) {
38
+ return this.getQuerier();
39
+ }
40
+ const client = await this.createClient({ ...remote, url: syncUrl });
41
+ return new HranaQuerier(client, this.dialect, this.extra, { closeClientOnRelease: true });
33
42
  }
34
- /** Imported on use, so `uql-orm/libsql` loads without the optional `@libsql/client` peer installed. */
43
+ /**
44
+ * Imported on use, so `uql-orm/libsql` loads without the optional `@libsql/client` peer installed.
45
+ * Integers read as `bigint` whatever the config asks, so the querier decodes one past 2^53 exactly.
46
+ */
35
47
  async createClient(conf) {
36
48
  const { createClient } = await import('@libsql/client');
37
- return createClient(conf);
49
+ return createClient({ ...conf, intMode: 'bigint' });
38
50
  }
39
51
  }
@@ -5,7 +5,7 @@
5
5
  * - OperationRecorder: Record operations only (for code generation)
6
6
  * - MigrationBuilder: Execute DDL operations (for integration tests/runtime)
7
7
  */
8
- import { ddlText, normalizeIndexColumn } from '../../util/index.js';
8
+ import { indexNameParts, normalizeIndexColumn } from '../../util/index.js';
9
9
  import { derivedIndexName } from '../../util/sql.util.js';
10
10
  import { createSchemaGenerator } from '../schemaGenerator.js';
11
11
  import { splitSqlStatements } from './splitSqlStatements.js';
@@ -23,9 +23,7 @@ function createIndexOperation(tableName, columns, options = {}) {
23
23
  tableName,
24
24
  index: {
25
25
  ...index,
26
- name: name ??
27
- derivedIndexName(tableName, entries.map((entry) => entry.column)),
28
- where: ddlText(index.where, 'a partial-index predicate'),
26
+ name: name ?? derivedIndexName(tableName, indexNameParts(entries)),
29
27
  entries,
30
28
  unique: unique ?? false,
31
29
  },
@@ -310,7 +308,7 @@ export class MigrationBuilder extends OperationRecorder {
310
308
  case 'alterColumn':
311
309
  return this.sqlGenerator.generateAlterColumnSql(operation.tableName, operation.columnName, operation.changes);
312
310
  case 'createIndex':
313
- return this.sqlGenerator.generateCreateIndex(operation.tableName, operation.index);
311
+ return this.sqlGenerator.generateCreateIndexFromDefinition(operation.tableName, operation.index);
314
312
  case 'dropIndex':
315
313
  return this.sqlGenerator.generateDropIndex(operation.tableName, operation.indexName);
316
314
  case 'addForeignKey':
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Fluent API for defining tables in migrations.
5
5
  */
6
- import { ddlText, normalizeIndexColumn } from '../../util/index.js';
6
+ import { indexNameParts, normalizeIndexColumn } from '../../util/index.js';
7
7
  import { derivedIndexName } from '../../util/sql.util.js';
8
8
  import { columnForeignKey, columnIndex } from '../generator/definitionToNode.js';
9
9
  import { ColumnBuilder } from './columnBuilder.js';
@@ -171,9 +171,7 @@ export class TableBuilder {
171
171
  const entries = columns.map(normalizeIndexColumn);
172
172
  this._indexes.push({
173
173
  ...rest,
174
- name: name ??
175
- derivedIndexName(this._name, entries.map((entry) => entry.column), unique),
176
- where: ddlText(rest.where, 'a partial-index predicate'),
174
+ name: name ?? derivedIndexName(this._name, indexNameParts(entries), unique),
177
175
  entries,
178
176
  unique,
179
177
  });
@@ -5,7 +5,7 @@
5
5
  * Enables type-safe migrations without raw SQL.
6
6
  */
7
7
  import type { ColumnNode, EnumValues, ForeignKeyAction } from '../../schema/types.js';
8
- import type { IndexColumnInput, IndexOptions, IndexSchema } from '../../type/index.js';
8
+ import type { EntityIndexColumn, Except, IndexColumnInput, IndexOptions, IndexSchema, QueryRaw } from '../../type/index.js';
9
9
  import type { ForeignKeySchema } from '../../type/migration.js';
10
10
  /**
11
11
  * Foreign key reference options.
@@ -91,6 +91,14 @@ export interface FullColumnDefinition extends ColumnDefinition {
91
91
  /** Index name (if indexed) */
92
92
  index?: string | boolean;
93
93
  }
94
+ /**
95
+ * An index as the builder records it, with the entries and options `@Index` takes: its SQL kept as `raw`
96
+ * until a generator renders it for the engine the migration runs on.
97
+ */
98
+ export type IndexDefinition = Except<IndexSchema, 'entries' | 'where'> & {
99
+ readonly entries: readonly EntityIndexColumn[];
100
+ readonly where?: QueryRaw;
101
+ };
94
102
  /**
95
103
  * Complete table definition.
96
104
  */
@@ -102,7 +110,7 @@ export interface TableDefinition {
102
110
  /** Primary key columns (for composite keys) */
103
111
  primaryKey?: string[];
104
112
  /** Index definitions */
105
- indexes: IndexSchema[];
113
+ indexes: IndexDefinition[];
106
114
  /** Foreign key definitions at table level */
107
115
  foreignKeys: ForeignKeySchema[];
108
116
  /** Table comment */
@@ -183,7 +191,7 @@ export interface RenameColumnOperation extends MigrationOperation {
183
191
  export interface CreateIndexOperation extends MigrationOperation {
184
192
  type: 'createIndex';
185
193
  tableName: string;
186
- index: IndexSchema;
194
+ index: IndexDefinition;
187
195
  ifNotExists?: boolean;
188
196
  }
189
197
  /**
@@ -5,4 +5,4 @@
5
5
  */
6
6
  export { createEntityCodeGenerator, EntityCodeGenerator, type EntityCodeGeneratorOptions, type GeneratedEntity, } from './entityCodeGenerator.js';
7
7
  export { entityTypesSource } from './entityTypes.js';
8
- export { buildMigrationModule, buildSqlQuerierMigrationModule, EMPTY_MANUAL_MIGRATION_DOWN_INNER, EMPTY_MANUAL_MIGRATION_UP_INNER, emitMongoCommandCalls, emitSqlRunCall, emitSqlRunCalls, type MigrationModuleOptions, type MigrationQuerierType, type SqlMigrationModuleOptions, } from './migrationFile.js';
8
+ export { buildMigrationModule, EMPTY_MANUAL_MIGRATION_DOWN_INNER, EMPTY_MANUAL_MIGRATION_UP_INNER, emitMongoCommandCalls, emitSqlRunCall, emitSqlRunCalls, type MigrationModuleOptions, type MigrationQuerierType, } from './migrationFile.js';
@@ -6,4 +6,4 @@
6
6
  // Entity code generator
7
7
  export { createEntityCodeGenerator, EntityCodeGenerator, } from './entityCodeGenerator.js';
8
8
  export { entityTypesSource } from './entityTypes.js';
9
- export { buildMigrationModule, buildSqlQuerierMigrationModule, EMPTY_MANUAL_MIGRATION_DOWN_INNER, EMPTY_MANUAL_MIGRATION_UP_INNER, emitMongoCommandCalls, emitSqlRunCall, emitSqlRunCalls, } from './migrationFile.js';
9
+ export { buildMigrationModule, EMPTY_MANUAL_MIGRATION_DOWN_INNER, EMPTY_MANUAL_MIGRATION_UP_INNER, emitMongoCommandCalls, emitSqlRunCall, emitSqlRunCalls, } from './migrationFile.js';
@@ -7,7 +7,7 @@ import type { IndexNode } from '../../schema/types.js';
7
7
  export declare function isPlainFieldIndex(index: IndexNode): boolean;
8
8
  /**
9
9
  * One `@Index((user) => [...])` as source, for an index no `@Field` can express, its columns read off the
10
- * key map `param` names. Emits `raw(...)` for an expression entry, so callers import `raw` when
10
+ * refs `param` names. Emits `raw` for an expression entry, so callers import `raw` when
11
11
  * {@link indexNeedsRaw} holds.
12
12
  */
13
13
  export declare function buildIndexDecoratorSource(index: IndexNode, propertyName: (column: string) => string, param: string): string;
@@ -1,3 +1,4 @@
1
+ import { isVectorIndexType } from '../../type/index.js';
1
2
  import { isIdentifierName, quoted, rawTag } from './sourceLiteral.js';
2
3
  /**
3
4
  * A vector index carries its metric in the operator class pgvector names after it
@@ -54,12 +55,12 @@ export function isPlainFieldIndex(index) {
54
55
  }
55
56
  /**
56
57
  * One `@Index((user) => [...])` as source, for an index no `@Field` can express, its columns read off the
57
- * key map `param` names. Emits `raw(...)` for an expression entry, so callers import `raw` when
58
+ * refs `param` names. Emits `raw` for an expression entry, so callers import `raw` when
58
59
  * {@link indexNeedsRaw} holds.
59
60
  */
60
61
  export function buildIndexDecoratorSource(index, propertyName, param) {
61
62
  const entries = index.entries.map((entry) => indexEntrySource(entry, propertyName, param)).join(', ');
62
- const isVector = index.type === 'hnsw' || index.type === 'ivfflat';
63
+ const isVector = isVectorIndexType(index.type);
63
64
  const distance = isVector ? vectorDistance(index) : undefined;
64
65
  const options = [];
65
66
  if (index.name)
@@ -88,10 +89,7 @@ export function indexNeedsRaw(index) {
88
89
  return Boolean(index.where) || index.entries.some((entry) => entry.expression);
89
90
  }
90
91
  function indexEntrySource(entry, propertyName, param) {
91
- if (entry.expression) {
92
- return rawTag(entry.column);
93
- }
94
- const column = memberSource(param, propertyName(entry.column));
92
+ const column = entry.expression ? rawTag(entry.column) : memberSource(param, propertyName(entry.column));
95
93
  const modifiers = significantModifiers(entry);
96
94
  return modifiers.length === 0 ? column : `{ column: ${column}, ${modifiers.join(', ')} }`;
97
95
  }
@@ -15,8 +15,6 @@ export type MigrationModuleOptions = {
15
15
  /** Indented body inside `async down` (including newlines). */
16
16
  downInner: string;
17
17
  };
18
- /** @deprecated Use {@link MigrationModuleOptions}. */
19
- export type SqlMigrationModuleOptions = MigrationModuleOptions;
20
18
  /**
21
19
  * Emit one `await querier.run(...)` line for entity-generated migrations.
22
20
  * Uses `JSON.stringify` so SQL with backticks (SQLite/LibSQL), quotes, `${`, etc. stays valid TS source.
@@ -47,5 +45,3 @@ export declare const migrationSource: {
47
45
  * Full contents of a `export default { async up/down(querier) { ... } }` migration module.
48
46
  */
49
47
  export declare function buildMigrationModule(options: MigrationModuleOptions): string;
50
- /** @deprecated Use {@link buildMigrationModule}. */
51
- export declare const buildSqlQuerierMigrationModule: typeof buildMigrationModule;
@@ -65,5 +65,3 @@ ${options.downInner}
65
65
  };
66
66
  `;
67
67
  }
68
- /** @deprecated Use {@link buildMigrationModule}. */
69
- export const buildSqlQuerierMigrationModule = buildMigrationModule;
@@ -1,12 +1,13 @@
1
1
  import type { ColumnNode, TableNode } from '../../schema/types.js';
2
2
  import type { ForeignKeySchema, IndexSchema } from '../../type/migration.js';
3
- import type { FullColumnDefinition, TableDefinition } from '../builder/types.js';
3
+ import type { QueryRaw } from '../../type/queryRaw.js';
4
+ import type { FullColumnDefinition, IndexDefinition, TableDefinition } from '../builder/types.js';
4
5
  /**
5
6
  * A migration builder's table definition as the AST nodes the generators render from, so a hand-written
6
- * `createTable` and an entity reach `generateCreateTableFromNode` in the same shape. Free functions and
7
- * not generator methods: nothing here consults the dialect.
7
+ * `createTable` and an entity reach `generateCreateTableFromNode` in the same shape, its SQL rendered by
8
+ * `render`. Free functions and not generator methods: the dialect reaches them only through `render`.
8
9
  */
9
- export declare function tableDefinitionToNode(def: TableDefinition): TableNode;
10
+ export declare function tableDefinitionToNode(def: TableDefinition, render: (sql: QueryRaw) => string): TableNode;
10
11
  /**
11
12
  * A builder's column as the AST node the generators render from.
12
13
  *
@@ -25,6 +26,8 @@ export declare function fullColumnDefinitionToNode(col: FullColumnDefinition, ta
25
26
  * Shared with `TableBuilder.build`, which lifts these into the table it is creating: written twice,
26
27
  * `addColumn` had no lift at all and silently emitted a column with no index.
27
28
  */
28
- export declare function columnIndex(tableName: string, col: FullColumnDefinition): IndexSchema | undefined;
29
+ export declare function columnIndex(tableName: string, col: FullColumnDefinition): Pick<IndexSchema, 'name' | 'entries' | 'unique'> | undefined;
30
+ /** An index the builder recorded, its SQL rendered by `render` into the text the schema holds. */
31
+ export declare function renderIndexDefinition(index: IndexDefinition, render: (sql: QueryRaw) => string): IndexSchema;
29
32
  /** The foreign key a column-level `references` declares, or nothing. Shared for the same reason. */
30
33
  export declare function columnForeignKey(col: FullColumnDefinition): ForeignKeySchema | undefined;
@@ -1,3 +1,4 @@
1
+ import { renderIndexColumn } from '../../util/ddlExpression.util.js';
1
2
  import { derivedForeignKeyName, derivedIndexName } from '../../util/sql.util.js';
2
3
  /**
3
4
  * A table the builder names but has not seen.
@@ -12,10 +13,10 @@ function unresolvedTable(name) {
12
13
  }
13
14
  /**
14
15
  * A migration builder's table definition as the AST nodes the generators render from, so a hand-written
15
- * `createTable` and an entity reach `generateCreateTableFromNode` in the same shape. Free functions and
16
- * not generator methods: nothing here consults the dialect.
16
+ * `createTable` and an entity reach `generateCreateTableFromNode` in the same shape, its SQL rendered by
17
+ * `render`. Free functions and not generator methods: the dialect reaches them only through `render`.
17
18
  */
18
- export function tableDefinitionToNode(def) {
19
+ export function tableDefinitionToNode(def, render) {
19
20
  const columns = new Map();
20
21
  const pkNodes = [];
21
22
  const table = {
@@ -40,7 +41,7 @@ export function tableDefinitionToNode(def) {
40
41
  : pkNodes;
41
42
  table.primaryKey = finalPrimaryKey;
42
43
  for (const idxDef of def.indexes) {
43
- table.indexes.push({ ...idxDef, table });
44
+ table.indexes.push({ ...renderIndexDefinition(idxDef, render), table });
44
45
  }
45
46
  for (const fkDef of def.foreignKeys) {
46
47
  const relNode = {
@@ -92,6 +93,14 @@ export function columnIndex(tableName, col) {
92
93
  unique: col.isUnique,
93
94
  };
94
95
  }
96
+ /** An index the builder recorded, its SQL rendered by `render` into the text the schema holds. */
97
+ export function renderIndexDefinition(index, render) {
98
+ return {
99
+ ...index,
100
+ entries: index.entries.map((entry) => renderIndexColumn(entry, render)),
101
+ where: index.where && render(index.where),
102
+ };
103
+ }
95
104
  /** The foreign key a column-level `references` declares, or nothing. Shared for the same reason. */
96
105
  export function columnForeignKey(col) {
97
106
  if (!col.foreignKey) {
@@ -8,6 +8,8 @@ export declare class MongoSchemaGenerator extends AbstractDialect implements Sch
8
8
  protected readonly featureDefaults: import("../../type/dialect.js").DialectFeatures;
9
9
  readonly insertIdSource: InsertIdSource;
10
10
  constructor(namingStrategy?: NamingStrategy, defaultForeignKeyAction?: ForeignKeyAction | undefined);
11
+ /** A collection has no SQL to render a check, a computed column or an index expression into. */
12
+ compileDdl(): string;
11
13
  /**
12
14
  * A document store has no cross-collection constraint, so unlike the SQL generator there is nothing to
13
15
  * defer and no order to respect: this is each collection and nothing more. `foreignKeys` is accepted
@@ -3,6 +3,7 @@ import { getMeta } from '../../entity/index.js';
3
3
  import { mongoDialectFeatures } from '../../mongo/mongoDialect.js';
4
4
  import { getKeys } from '../../util/index.js';
5
5
  import { derivedIndexName } from '../../util/sql.util.js';
6
+ import { renderIndexDefinition } from './definitionToNode.js';
6
7
  import { indexNodeToSchema } from './indexNodeToSchema.js';
7
8
  import { serializeMongoCommand } from './mongoCommand.js';
8
9
  export class MongoSchemaGenerator extends AbstractDialect {
@@ -14,6 +15,10 @@ export class MongoSchemaGenerator extends AbstractDialect {
14
15
  super({ namingStrategy });
15
16
  this.defaultForeignKeyAction = defaultForeignKeyAction;
16
17
  }
18
+ /** A collection has no SQL to render a check, a computed column or an index expression into. */
19
+ compileDdl() {
20
+ throw new TypeError('mongodb has no SQL to render a check, a computed column or an index expression into');
21
+ }
17
22
  /**
18
23
  * A document store has no cross-collection constraint, so unlike the SQL generator there is nothing to
19
24
  * defer and no order to respect: this is each collection and nothing more. `foreignKeys` is accepted
@@ -135,7 +140,7 @@ export class MongoSchemaGenerator extends AbstractDialect {
135
140
  generateCreateTableFromDefinition(table, _options) {
136
141
  return [
137
142
  serializeMongoCommand({ action: 'createCollection', name: table.name }),
138
- ...table.indexes.map((index) => this.generateCreateIndex(table.name, index)),
143
+ ...table.indexes.map((index) => this.generateCreateIndex(table.name, renderIndexDefinition(index, () => this.compileDdl()))),
139
144
  ];
140
145
  }
141
146
  generateRenameTableSql(oldName, newName) {
@@ -2,8 +2,8 @@ import type { AbstractSqlDialect } from '../dialect/index.js';
2
2
  import type { SchemaAST } from '../schema/schemaAST.js';
3
3
  import { type DiffOptions } from '../schema/schemaASTDiffer.js';
4
4
  import type { CanonicalType, ColumnNode, ForeignKeyAction, IndexNode, TableNode } from '../schema/types.js';
5
- import type { ColumnSchema, CreateSchemaOptions, DialectFeatures, DropSchemaOptions, EntityMeta, FieldMeta, FieldOptions, ForeignKeySchema, IndexSchema, MigratorDialect, NamingStrategy, SchemaDiff, SchemaGenerator, SqlDdlGenerator, Type } from '../type/index.js';
6
- import type { FullColumnDefinition, TableDefinition } from './builder/types.js';
5
+ import type { ColumnSchema, CreateSchemaOptions, DialectFeatures, DropSchemaOptions, EntityMeta, EntityWhereMeta, FieldMeta, FieldOptions, ForeignKeySchema, IndexSchema, MigratorDialect, NamingStrategy, SchemaDiff, SchemaGenerator, SqlDdlGenerator, Type } from '../type/index.js';
6
+ import type { FullColumnDefinition, IndexDefinition, TableDefinition } from './builder/types.js';
7
7
  import { type IndexDdl, type TableDdl } from './ddl/index.js';
8
8
  /**
9
9
  * Unified SQL schema generator.
@@ -23,6 +23,7 @@ export declare class SqlSchemaGenerator implements SqlDdlGenerator {
23
23
  resolveTableAlias<E>(meta: EntityMeta<E>): string;
24
24
  resolveSchema<E>(meta: EntityMeta<E>): string | undefined;
25
25
  resolveColumnName(key: string, field: FieldOptions): string;
26
+ compileDdl(sql: EntityWhereMeta<object>, entity: Type<object>): string;
26
27
  /** Escape an identifier (table name, column name, etc.) */
27
28
  protected escapeId(identifier: string): string;
28
29
  /**
@@ -165,6 +166,7 @@ export declare class SqlSchemaGenerator implements SqlDdlGenerator {
165
166
  generateCreateTableFromDefinition(table: TableDefinition, options?: {
166
167
  ifNotExists?: boolean;
167
168
  }): string[];
169
+ generateCreateIndexFromDefinition(tableName: string, index: IndexDefinition): string;
168
170
  generateRenameTableSql(oldName: string, newName: string): string;
169
171
  /**
170
172
  * `ADD COLUMN`, plus the constraint and index the column declares.
@@ -217,7 +219,7 @@ export declare class SqlSchemaGenerator implements SqlDdlGenerator {
217
219
  * other way and the table is created under one name and compared under another, which reports every
218
220
  * table of a project using a naming strategy as both missing and unexpected.
219
221
  */
220
- export declare function buildEntityAST(generator: Pick<SchemaGenerator, 'resolveTableAlias' | 'resolveSchema' | 'resolveColumnName'>, entities: readonly Type<object>[], defaultForeignKeyAction?: ForeignKeyAction): SchemaAST;
222
+ export declare function buildEntityAST(generator: Pick<SchemaGenerator, 'resolveTableAlias' | 'resolveSchema' | 'resolveColumnName' | 'compileDdl'>, entities: readonly Type<object>[], defaultForeignKeyAction?: ForeignKeyAction): SchemaAST;
221
223
  /**
222
224
  * Synchronous factory for SQL schema generators only.
223
225
  * For MongoDB, use `createSchemaGeneratorAsync` from `./schemaGeneratorAsync.js` so the optional `mongodb` peer is not loaded at import time.
@@ -8,7 +8,7 @@ import { derivedCheckName, derivedForeignKeyName, derivedPrimaryKeyName } from '
8
8
  import { formatDefaultValue, SqlExpression } from './builder/expressions.js';
9
9
  import { indexDdlFor, tableDdlFor } from './ddl/index.js';
10
10
  import { sizedType } from './ddl/tableDdl.js';
11
- import { columnForeignKey, columnIndex, fullColumnDefinitionToNode, tableDefinitionToNode, } from './generator/definitionToNode.js';
11
+ import { columnForeignKey, columnIndex, fullColumnDefinitionToNode, renderIndexDefinition, tableDefinitionToNode, } from './generator/definitionToNode.js';
12
12
  import { indexNodeToSchema } from './generator/indexNodeToSchema.js';
13
13
  /**
14
14
  * Unified SQL schema generator.
@@ -45,6 +45,9 @@ export class SqlSchemaGenerator {
45
45
  resolveColumnName(key, field) {
46
46
  return this.dialect.resolveColumnName(key, field);
47
47
  }
48
+ compileDdl(sql, entity) {
49
+ return this.dialect.compileDdl(sql, entity);
50
+ }
48
51
  /** Escape an identifier (table name, column name, etc.) */
49
52
  escapeId(identifier) {
50
53
  return this.dialect.escapeId(identifier);
@@ -565,9 +568,12 @@ export class SqlSchemaGenerator {
565
568
  return this.generateCreateIndex(qualifyName(index.table.name, index.table.schema), indexNodeToSchema(index), options);
566
569
  }
567
570
  generateCreateTableFromDefinition(table, options = {}) {
568
- const tableNode = tableDefinitionToNode(table);
571
+ const tableNode = tableDefinitionToNode(table, (sql) => this.dialect.compileDdl(sql));
569
572
  return this.generateCreateTableFromNode(tableNode, options);
570
573
  }
574
+ generateCreateIndexFromDefinition(tableName, index) {
575
+ return this.generateCreateIndex(tableName, renderIndexDefinition(index, (sql) => this.dialect.compileDdl(sql)));
576
+ }
571
577
  generateRenameTableSql(oldName, newName) {
572
578
  return this.tableDdl.renameTable(oldName, newName);
573
579
  }
@@ -719,6 +725,7 @@ export function buildEntityAST(generator, entities, defaultForeignKeyAction) {
719
725
  resolveTableName: (meta) => generator.resolveTableAlias(meta),
720
726
  resolveSchema: (meta) => generator.resolveSchema(meta),
721
727
  resolveColumnName: (key, field) => generator.resolveColumnName(key, field),
728
+ compileDdl: (sql, entity) => generator.compileDdl(sql, entity),
722
729
  defaultForeignKeyAction,
723
730
  });
724
731
  }
@@ -263,7 +263,7 @@ export class MongoDialect extends AbstractDialect {
263
263
  * lock silently removes the mutual exclusion the caller asked for.
264
264
  */
265
265
  assertNoLock(q) {
266
- if (q.$lock !== undefined) {
266
+ if (q.$lock) {
267
267
  throw new TypeError('$lock (row-level locking) is not supported on MongoDB');
268
268
  }
269
269
  }