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.
- package/dist/browser/uql-browser.min.js.map +1 -1
- package/dist/bunSql/bunSql.util.d.ts +15 -15
- package/dist/bunSql/bunSql.util.js +22 -35
- package/dist/bunSql/bunSqlQuerier.d.ts +2 -2
- package/dist/bunSql/bunSqlQuerier.js +3 -3
- package/dist/bunSql/bunSqlQuerierPool.d.ts +1 -13
- package/dist/bunSql/bunSqlQuerierPool.js +3 -34
- package/dist/d1/d1Querier.d.ts +12 -4
- package/dist/d1/d1Querier.js +6 -11
- package/dist/d1/d1QuerierPool.d.ts +7 -3
- package/dist/d1/d1QuerierPool.js +5 -3
- package/dist/dialect/abstractSqlDialect.d.ts +12 -7
- package/dist/dialect/abstractSqlDialect.js +51 -50
- package/dist/dialect/mysqlLikeSqlDialect.js +1 -1
- package/dist/dialect/pgLikeSqlDialect.d.ts +1 -0
- package/dist/dialect/pgLikeSqlDialect.js +8 -7
- package/dist/dialect/queryContext.d.ts +5 -6
- package/dist/dialect/queryContext.js +8 -8
- package/dist/entity/decorator/entity.d.ts +6 -10
- package/dist/entity/decorator/entity.js +4 -8
- package/dist/entity/decorator/members.d.ts +3 -2
- package/dist/entity/decorator/members.js +1 -0
- package/dist/entity/metadata/definition.d.ts +2 -2
- package/dist/entity/metadata/definition.js +23 -26
- package/dist/libsql/libsqlDialect.d.ts +1 -1
- package/dist/libsql/libsqlDialect.js +1 -1
- package/dist/libsql/libsqlQuerierPool.d.ts +18 -9
- package/dist/libsql/libsqlQuerierPool.js +32 -20
- package/dist/migrate/builder/migrationBuilder.js +3 -5
- package/dist/migrate/builder/tableBuilder.js +2 -4
- package/dist/migrate/builder/types.d.ts +11 -3
- package/dist/migrate/codegen/index.d.ts +1 -1
- package/dist/migrate/codegen/index.js +1 -1
- package/dist/migrate/codegen/indexDecoratorSource.d.ts +1 -1
- package/dist/migrate/codegen/indexDecoratorSource.js +4 -6
- package/dist/migrate/codegen/migrationFile.d.ts +0 -4
- package/dist/migrate/codegen/migrationFile.js +0 -2
- package/dist/migrate/generator/definitionToNode.d.ts +8 -5
- package/dist/migrate/generator/definitionToNode.js +13 -4
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +2 -0
- package/dist/migrate/generator/mongoSchemaGenerator.js +6 -1
- package/dist/migrate/schemaGenerator.d.ts +5 -3
- package/dist/migrate/schemaGenerator.js +9 -2
- package/dist/mongo/mongoDialect.js +1 -1
- package/dist/mssql/mssqlDialect.js +3 -5
- package/dist/querier/abstractSharedHandleQuerierPool.d.ts +5 -5
- package/dist/querier/abstractSharedHandleQuerierPool.js +5 -5
- package/dist/schema/schemaASTBuilder.d.ts +6 -1
- package/dist/schema/schemaASTBuilder.js +17 -16
- package/dist/sqlite/abstractSqliteQuerier.d.ts +11 -28
- package/dist/sqlite/abstractSqliteQuerier.js +14 -33
- package/dist/sqlite/bunSqliteAdapter.bun.d.ts +5 -4
- package/dist/sqlite/bunSqliteAdapter.bun.js +1 -1
- package/dist/sqlite/hranaQuerier.d.ts +6 -4
- package/dist/sqlite/hranaQuerier.js +4 -13
- package/dist/sqlite/index.d.ts +0 -1
- package/dist/sqlite/index.js +0 -1
- package/dist/sqlite/localSqliteQuerierPool.d.ts +14 -5
- package/dist/sqlite/nodeSqliteAdapter.d.ts +3 -4
- package/dist/sqlite/nodeSqliteAdapter.js +3 -6
- package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -3
- package/dist/sqlite/nodeSqliteQuerierPool.js +3 -1
- package/dist/sqlite/sqliteDialect.d.ts +1 -1
- package/dist/sqlite/sqliteDialect.js +1 -1
- package/dist/sqlite/sqlitePragmas.d.ts +2 -11
- package/dist/sqlite/sqlitePragmas.js +1 -1
- package/dist/sqlite/sqliteQuerier.d.ts +29 -10
- package/dist/sqlite/sqliteQuerier.js +26 -4
- package/dist/sqlite/sqliteQuerierPool.d.ts +7 -3
- package/dist/sqlite/sqliteQuerierPool.js +12 -8
- package/dist/turso/index.d.ts +1 -0
- package/dist/turso/index.js +1 -0
- package/dist/turso/local.d.ts +1 -1
- package/dist/turso/local.js +1 -1
- package/dist/turso/tursoDialect.d.ts +4 -9
- package/dist/turso/tursoDialect.js +4 -12
- package/dist/turso/tursoLocalDialect.d.ts +10 -0
- package/dist/turso/tursoLocalDialect.js +13 -0
- package/dist/turso/tursoLocalQuerierPool.d.ts +8 -13
- package/dist/turso/tursoLocalQuerierPool.js +6 -5
- package/dist/turso/tursoQuerierPool.d.ts +15 -30
- package/dist/turso/tursoQuerierPool.js +13 -23
- package/dist/turso/tursoSessionQuerier.d.ts +57 -0
- package/dist/turso/tursoSessionQuerier.js +50 -0
- package/dist/type/dialect.d.ts +15 -6
- package/dist/type/entity.d.ts +108 -73
- package/dist/type/migration.d.ts +9 -2
- package/dist/type/query.d.ts +3 -3
- package/dist/type/queryLock.d.ts +7 -7
- package/dist/type/queryLock.js +8 -6
- package/dist/type/queryRaw.d.ts +30 -30
- package/dist/type/queryRaw.js +14 -9
- package/dist/util/ddlExpression.util.d.ts +8 -13
- package/dist/util/ddlExpression.util.js +14 -23
- package/dist/util/dialect.util.d.ts +1 -1
- package/dist/util/dialect.util.js +3 -4
- package/dist/util/field.util.d.ts +1 -1
- package/dist/util/raw.d.ts +24 -17
- package/dist/util/raw.js +46 -17
- package/dist/util/wideNumber.d.ts +2 -2
- package/dist/util/wideNumber.js +2 -2
- package/package.json +2 -2
- package/dist/sqlite/hranaQuerierPool.d.ts +0 -20
- package/dist/sqlite/hranaQuerierPool.js +0 -26
- package/dist/turso/tursoLocalQuerier.d.ts +0 -24
- 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,
|
|
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
|
|
35
|
-
|
|
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
|
|
54
|
-
...(references
|
|
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
|
-
|
|
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
|
|
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
|
|
95
|
+
const refs = memberRefs();
|
|
94
96
|
(meta.indexes ??= []).push({
|
|
95
97
|
...index,
|
|
96
98
|
unique: index.unique ?? false,
|
|
97
|
-
where:
|
|
98
|
-
columns: index.columns(
|
|
99
|
-
include: index.include?.(
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
504
|
-
target.hooks = {};
|
|
501
|
+
const hooks = (target.hooks ??= {});
|
|
505
502
|
for (const [event, sourceList] of definedEntries(source.hooks)) {
|
|
506
|
-
|
|
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 `
|
|
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 `
|
|
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
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
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
|
|
14
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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
|
|
25
|
-
*
|
|
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 (
|
|
33
|
+
if ('execute' in this.conf) {
|
|
29
34
|
return this.getQuerier();
|
|
30
35
|
}
|
|
31
|
-
const remote =
|
|
32
|
-
|
|
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
|
-
/**
|
|
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 {
|
|
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.
|
|
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 {
|
|
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:
|
|
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:
|
|
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,
|
|
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,
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
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;
|
|
@@ -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 {
|
|
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
|
|
7
|
-
* not generator methods:
|
|
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
|
|
16
|
-
* not generator methods:
|
|
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
|
|
266
|
+
if (q.$lock) {
|
|
267
267
|
throw new TypeError('$lock (row-level locking) is not supported on MongoDB');
|
|
268
268
|
}
|
|
269
269
|
}
|