uql-orm 0.41.0 → 0.41.1
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/entity/decorator/members.d.ts +19 -1
- package/dist/entity/metadata/definition.js +6 -2
- package/dist/migrate/builder/migrationBuilder.js +2 -2
- package/dist/migrate/builder/tableBuilder.js +2 -2
- package/dist/migrate/schemaGenerator.js +9 -1
- package/dist/schema/schemaAST.js +1 -0
- package/dist/schema/schemaASTBuilder.js +2 -0
- package/dist/schema/types.d.ts +24 -0
- package/dist/type/entity.d.ts +28 -1
- package/dist/util/ddlExpression.util.d.ts +15 -0
- package/dist/util/ddlExpression.util.js +27 -0
- package/dist/util/index.d.ts +1 -1
- package/dist/util/index.js +1 -1
- package/dist/util/sql.util.d.ts +2 -0
- package/dist/util/sql.util.js +4 -0
- package/package.json +2 -2
- package/dist/util/indexColumn.util.d.ts +0 -8
- package/dist/util/indexColumn.util.js +0 -30
|
@@ -7,11 +7,29 @@ type MemberDecorator<V> = (value: undefined, context: ClassFieldDecoratorContext
|
|
|
7
7
|
* primary key's own type. Which is what makes `@Field({ references: () => User })` on a `number`, where
|
|
8
8
|
* `User.id` is a `uuid`, a compile error rather than a column that disagrees with its property.
|
|
9
9
|
*/
|
|
10
|
+
/**
|
|
11
|
+
* The value type the options declare, which the decorated property is then checked against.
|
|
12
|
+
*
|
|
13
|
+
* `enum` narrows it to its own values, so the property must spell out the same set. Only the values
|
|
14
|
+
* the declared `type` admits count, which is what keeps `enum: [2]` off a `String` field.
|
|
15
|
+
*/
|
|
10
16
|
type DeclaredValue<O> = O extends {
|
|
11
17
|
readonly type: infer T extends FieldType;
|
|
12
|
-
} ?
|
|
18
|
+
} ? O extends {
|
|
19
|
+
readonly enum: infer E extends readonly unknown[];
|
|
20
|
+
} ? EnumValue<Extract<E[number], TsTypeOf<T>>, TsTypeOf<T>> : TsTypeOf<T> : O extends {
|
|
13
21
|
readonly references: EntityGetter<infer E>;
|
|
14
22
|
} ? IdValue<E> : never;
|
|
23
|
+
/**
|
|
24
|
+
* The enum's members, or a named complaint when they widened.
|
|
25
|
+
*
|
|
26
|
+
* `['a', 'b']` without `as const` infers `string[]`, whose member type is the field's own type and
|
|
27
|
+
* so narrows nothing - the check would be silently off. Resolving to a type no property can hold
|
|
28
|
+
* makes that a compile error that says why, rather than a decoration.
|
|
29
|
+
*/
|
|
30
|
+
type EnumValue<Members, Declared> = Declared extends Members ? {
|
|
31
|
+
readonly __enumNeedsAsConst: true;
|
|
32
|
+
} : Members;
|
|
15
33
|
/**
|
|
16
34
|
* Declares a persisted field.
|
|
17
35
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SOFT_DELETE_FILTER } from '../../type/index.js';
|
|
2
|
-
import { getKeys, hasKeys, isToManyRelation, lowerFirst, normalizeIndexColumn,
|
|
2
|
+
import { getKeys, ddlText, hasKeys, isToManyRelation, lowerFirst, normalizeIndexColumn, upperFirst, } from '../../util/index.js';
|
|
3
3
|
import { ownRegistrations } from '../decorator/bag.js';
|
|
4
4
|
// Held on `globalThis` via the global symbol registry so a single metadata map survives multiple
|
|
5
5
|
// evaluations of this module (HMR, duplicated/federated bundles, ESM+CJS dual-loading). Version-suffixed
|
|
@@ -66,7 +66,7 @@ export function defineIndex(entity, index) {
|
|
|
66
66
|
meta.indexes.push({
|
|
67
67
|
...index,
|
|
68
68
|
unique: index.unique ?? false,
|
|
69
|
-
where:
|
|
69
|
+
where: ddlText(index.where, 'a partial-index predicate'),
|
|
70
70
|
columns: index.columns.map(normalizeIndexColumn),
|
|
71
71
|
});
|
|
72
72
|
return meta;
|
|
@@ -124,6 +124,10 @@ export function defineEntity(entity, opts = {}) {
|
|
|
124
124
|
// after class decorators return; draining empties the bag, so whichever runs second is a no-op.
|
|
125
125
|
applyMembers(entity, ownRegistrations(entity));
|
|
126
126
|
applyMembers(entity, opts);
|
|
127
|
+
// Unnamed checks are named by the generator, as unnamed indexes are.
|
|
128
|
+
for (const check of opts.checks ?? []) {
|
|
129
|
+
(meta.checks ??= []).push({ name: check.name, expression: ddlText(check.expression, 'a check constraint') });
|
|
130
|
+
}
|
|
127
131
|
for (const index of opts.indexes ?? []) {
|
|
128
132
|
defineIndex(entity, index);
|
|
129
133
|
}
|
|
@@ -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 { ddlText, 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';
|
|
@@ -29,7 +29,7 @@ function createIndexOperation(tableName, columns, options = {}) {
|
|
|
29
29
|
...index,
|
|
30
30
|
name: name ??
|
|
31
31
|
derivedIndexName(tableName, entries.map((entry) => entry.column)),
|
|
32
|
-
where:
|
|
32
|
+
where: ddlText(index.where, 'a partial-index predicate'),
|
|
33
33
|
entries,
|
|
34
34
|
unique: unique ?? false,
|
|
35
35
|
},
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Fluent API for defining tables in migrations.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { ddlText, normalizeIndexColumn } from '../../util/index.js';
|
|
7
7
|
import { derivedIndexName } from '../../util/sql.util.js';
|
|
8
8
|
import { ColumnBuilder } from './columnBuilder.js';
|
|
9
9
|
import { expr } from './expressions.js';
|
|
@@ -171,7 +171,7 @@ export class TableBuilder {
|
|
|
171
171
|
this._indexes.push({
|
|
172
172
|
...rest,
|
|
173
173
|
name: name ?? `${prefix}_${this._name}_${entries.map((entry) => entry.column).join('_')}`,
|
|
174
|
-
where:
|
|
174
|
+
where: ddlText(rest.where, 'a partial-index predicate'),
|
|
175
175
|
entries,
|
|
176
176
|
unique,
|
|
177
177
|
});
|
|
@@ -3,7 +3,7 @@ import { getMeta } from '../entity/index.js';
|
|
|
3
3
|
import { areTypesEqual, canonicalToSql, fieldOptionsToCanonical, isVectorCategory, sqlToCanonical, } from '../schema/canonicalType.js';
|
|
4
4
|
import { buildSchemaAST } from '../schema/schemaASTBuilder.js';
|
|
5
5
|
import { getKeys, isAutoIncrement, qualifyName } from '../util/index.js';
|
|
6
|
-
import { derivedForeignKeyName } from '../util/sql.util.js';
|
|
6
|
+
import { derivedCheckName, derivedForeignKeyName } from '../util/sql.util.js';
|
|
7
7
|
import { formatDefaultValue, SqlExpression } from './builder/expressions.js';
|
|
8
8
|
import { indexDdlFor } from './ddl/index.js';
|
|
9
9
|
import { fullColumnDefinitionToNode, tableDefinitionToNode } from './generator/definitionToNode.js';
|
|
@@ -247,6 +247,10 @@ export class SqlSchemaGenerator {
|
|
|
247
247
|
if (column.isUnique && !column.isPrimaryKey) {
|
|
248
248
|
def += ' UNIQUE';
|
|
249
249
|
}
|
|
250
|
+
if (column.enum?.length) {
|
|
251
|
+
const values = column.enum.map((value) => this.dialect.escape(value)).join(', ');
|
|
252
|
+
def += ` CHECK (${this.escapeId(column.name)} IN (${values}))`;
|
|
253
|
+
}
|
|
250
254
|
def += this.defaultClause(column);
|
|
251
255
|
if (column.comment) {
|
|
252
256
|
def += this.generateColumnComment(column.name, column.comment);
|
|
@@ -493,6 +497,10 @@ export class SqlSchemaGenerator {
|
|
|
493
497
|
const pkCols = table.primaryKey.map((c) => this.escapeId(c.name)).join(', ');
|
|
494
498
|
constraints.push(`PRIMARY KEY (${pkCols})`);
|
|
495
499
|
}
|
|
500
|
+
(table.checks ?? []).forEach((check, i) => {
|
|
501
|
+
const name = check.name ?? derivedCheckName(table.name, i + 1);
|
|
502
|
+
constraints.push(`CONSTRAINT ${this.escapeId(name)} CHECK (${check.expression})`);
|
|
503
|
+
});
|
|
496
504
|
for (const rel of table.outgoingRelations) {
|
|
497
505
|
if (rel.from.columns.length > 0) {
|
|
498
506
|
const fromCols = rel.from.columns.map((c) => this.escapeId(c.name)).join(', ');
|
package/dist/schema/schemaAST.js
CHANGED
|
@@ -71,6 +71,7 @@ function addTableFromEntity(ctx, meta) {
|
|
|
71
71
|
const tableName = ctx.resolveTableName(meta);
|
|
72
72
|
const table = createTableNode(tableName, ctx.resolveSchema(meta));
|
|
73
73
|
const { columns, primaryKey } = table;
|
|
74
|
+
table.checks?.push(...(meta.checks ?? []));
|
|
74
75
|
// Add columns from fields
|
|
75
76
|
const fields = meta.fields;
|
|
76
77
|
for (const key of Object.keys(fields)) {
|
|
@@ -94,6 +95,7 @@ function addTableFromEntity(ctx, meta) {
|
|
|
94
95
|
isAutoIncrement: field.autoIncrement ?? (isPrimaryKey && type.category === 'integer'),
|
|
95
96
|
isUnique: field.unique ?? false,
|
|
96
97
|
comment: field.comment,
|
|
98
|
+
enum: field.enum,
|
|
97
99
|
table,
|
|
98
100
|
referencedBy: [],
|
|
99
101
|
references: undefined,
|
package/dist/schema/types.d.ts
CHANGED
|
@@ -40,6 +40,26 @@ export interface CanonicalType {
|
|
|
40
40
|
* Actions for foreign key ON DELETE and ON UPDATE clauses.
|
|
41
41
|
*/
|
|
42
42
|
export type ForeignKeyAction = 'CASCADE' | 'SET NULL' | 'SET DEFAULT' | 'RESTRICT' | 'NO ACTION';
|
|
43
|
+
/**
|
|
44
|
+
* The values a column accepts, rendered as `CHECK (col IN (...))`.
|
|
45
|
+
*
|
|
46
|
+
* Strings and numbers only: those are what `IN (...)` can state, and each is escaped by the
|
|
47
|
+
* dialect's own literal rules, so a number stays bare where a string is quoted.
|
|
48
|
+
*/
|
|
49
|
+
export type EnumValues = readonly (string | number)[];
|
|
50
|
+
/**
|
|
51
|
+
* A `CHECK` constraint as the schema holds it, its expression already text. Declared here rather
|
|
52
|
+
* than beside the entity types because a table node also comes from introspection, where there is
|
|
53
|
+
* no entity to have authored one.
|
|
54
|
+
*
|
|
55
|
+
* Only ever compared by presence, never by content: a check is SQL text, and a database reprints
|
|
56
|
+
* text from its parse tree, so `CHECK ("balance" >= 0)` reads back as `CHECK ((balance >= (0)::numeric))`.
|
|
57
|
+
*/
|
|
58
|
+
export interface CheckSchema {
|
|
59
|
+
/** Absent when nothing named it, which the generator fills in with `derivedCheckName`. */
|
|
60
|
+
readonly name?: string;
|
|
61
|
+
readonly expression: string;
|
|
62
|
+
}
|
|
43
63
|
/**
|
|
44
64
|
* Default action for foreign key ON DELETE and ON UPDATE clauses.
|
|
45
65
|
*/
|
|
@@ -84,6 +104,8 @@ export interface ColumnNode {
|
|
|
84
104
|
readonly isAutoIncrement: boolean;
|
|
85
105
|
/** Whether this column has a unique constraint */
|
|
86
106
|
readonly isUnique: boolean;
|
|
107
|
+
/** The values the column accepts. See {@link EnumValues}. */
|
|
108
|
+
readonly enum?: EnumValues;
|
|
87
109
|
/** Column comment/description */
|
|
88
110
|
readonly comment?: string;
|
|
89
111
|
/** Reference to the parent table */
|
|
@@ -115,6 +137,8 @@ export interface TableNode {
|
|
|
115
137
|
readonly primaryKey: ColumnNode[];
|
|
116
138
|
/** Indexes on this table */
|
|
117
139
|
readonly indexes: IndexNode[];
|
|
140
|
+
/** `CHECK` constraints on this table. Optional: a node can be built without ever naming one. */
|
|
141
|
+
readonly checks?: CheckSchema[];
|
|
118
142
|
/** Optional table comment */
|
|
119
143
|
readonly comment?: string;
|
|
120
144
|
/** Relationships pointing TO this table (other tables referencing this one) */
|
package/dist/type/entity.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ForeignKeyAction, IndexType } from '../schema/types.js';
|
|
1
|
+
import type { CheckSchema, EnumValues, ForeignKeyAction, IndexType } from '../schema/types.js';
|
|
2
2
|
import type { FilterOptions } from './query.js';
|
|
3
3
|
import type { QueryRaw } from './queryRaw.js';
|
|
4
4
|
import type { Except, IsMany, Json, Scalar, Type, Unpacked } from './utility.js';
|
|
@@ -292,6 +292,20 @@ export type FieldOptions<V = TsTypeOf<FieldType>> = {
|
|
|
292
292
|
* @example `@Field({ references: () => Company, onDelete: 'CASCADE' }) companyId?: string;`
|
|
293
293
|
*/
|
|
294
294
|
readonly onDelete?: ForeignKeyAction;
|
|
295
|
+
/**
|
|
296
|
+
* The values the column accepts, enforced by the database as well as by TypeScript.
|
|
297
|
+
*
|
|
298
|
+
* Emitted as a column `CHECK (col IN (...))` on every SQL dialect rather than a native enum type:
|
|
299
|
+
* one code path, no separate schema object to order, and adding a value stays an ordinary column
|
|
300
|
+
* change instead of Postgres's irreversible `ALTER TYPE ... ADD VALUE`.
|
|
301
|
+
*
|
|
302
|
+
* Not constrained against the field's own type here: the decorator narrows the property to these
|
|
303
|
+
* values instead, which reports a mismatch where the mistake is rather than as an unrelated
|
|
304
|
+
* `never`. `as const` is what makes them literal, and so what makes any of it check.
|
|
305
|
+
*
|
|
306
|
+
* @example `@Field({ type: String, enum: ['draft', 'paid'] as const })`
|
|
307
|
+
*/
|
|
308
|
+
readonly enum?: EnumValues;
|
|
295
309
|
readonly virtual?: QueryRaw;
|
|
296
310
|
readonly updatable?: boolean;
|
|
297
311
|
readonly eager?: boolean;
|
|
@@ -699,6 +713,8 @@ export type EntityMeta<E> = {
|
|
|
699
713
|
};
|
|
700
714
|
/** Composite indexes defined via @Index decorator */
|
|
701
715
|
indexes?: EntityIndexMeta[];
|
|
716
|
+
/** `CHECK` constraints, their expressions already reduced to text. */
|
|
717
|
+
checks?: CheckSchema[];
|
|
702
718
|
/** Lifecycle hooks registered via @BeforeInsert, @AfterUpdate, etc. */
|
|
703
719
|
hooks?: Partial<Record<HookEvent, HookRegistration[]>>;
|
|
704
720
|
processed?: boolean;
|
|
@@ -709,6 +725,15 @@ export type EntityMeta<E> = {
|
|
|
709
725
|
* Optional `fields`, `relations`, `indexes`, and `hooks` register metadata in one call for
|
|
710
726
|
* decorator-free setups. Omit them when using `@Field` / `@ManyToOne` / etc.
|
|
711
727
|
*/
|
|
728
|
+
/**
|
|
729
|
+
* A table-level `CHECK`. The expression is `raw` with no interpolation, like an index expression:
|
|
730
|
+
* this is DDL, so there is no placeholder a bound value could go into.
|
|
731
|
+
*/
|
|
732
|
+
export type CheckOptions = {
|
|
733
|
+
/** Derived from the table and the constraint's position when absent. */
|
|
734
|
+
readonly name?: string;
|
|
735
|
+
readonly expression: QueryRaw;
|
|
736
|
+
};
|
|
712
737
|
export type EntityOptions<E = unknown> = {
|
|
713
738
|
readonly name?: string;
|
|
714
739
|
/**
|
|
@@ -726,6 +751,8 @@ export type EntityOptions<E = unknown> = {
|
|
|
726
751
|
readonly [K in RelationKey<E>]?: RelationOptionsFor<E[K]>;
|
|
727
752
|
};
|
|
728
753
|
readonly indexes?: readonly EntityIndexInput<FieldKey<E>, E>[];
|
|
754
|
+
/** Table-level `CHECK` constraints. See {@link CheckOptions}. */
|
|
755
|
+
readonly checks?: readonly CheckOptions[];
|
|
729
756
|
/** Map hook events to method names on the entity class. */
|
|
730
757
|
readonly hooks?: Partial<Record<HookEvent, readonly MethodKey<E>[]>>;
|
|
731
758
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type IndexColumnInput, type IndexColumnSchema, QueryRaw } from '../type/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* SQL bound for DDL, as the text a generator renders. `raw` with no interpolation, or a bare string
|
|
4
|
+
* where one is still accepted: DDL is evaluated once at creation time, so there is no query context
|
|
5
|
+
* for the callback form and no placeholder a `CREATE` statement could bind a value into.
|
|
6
|
+
*
|
|
7
|
+
* `what` names the thing being declared, so the error says which one the caller got wrong.
|
|
8
|
+
*/
|
|
9
|
+
export declare function ddlText(value: string | QueryRaw, what: string): string;
|
|
10
|
+
export declare function ddlText(value: string | QueryRaw | undefined, what: string): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Reduces an authored index entry to its normalized form, so the three shapes users write - a column
|
|
13
|
+
* name, an expression, or an options object - reach the dialects as one.
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeIndexColumn(entry: IndexColumnInput): IndexColumnSchema;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { QueryRaw, RAW_VALUE } from '../type/index.js';
|
|
2
|
+
export function ddlText(value, what) {
|
|
3
|
+
if (!(value instanceof QueryRaw)) {
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
const sql = value[RAW_VALUE];
|
|
7
|
+
if (typeof sql !== 'string') {
|
|
8
|
+
throw new TypeError(`${what} needs raw() with no interpolation, not a function or a bound value`);
|
|
9
|
+
}
|
|
10
|
+
return sql;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Reduces an authored index entry to its normalized form, so the three shapes users write - a column
|
|
14
|
+
* name, an expression, or an options object - reach the dialects as one.
|
|
15
|
+
*/
|
|
16
|
+
export function normalizeIndexColumn(entry) {
|
|
17
|
+
if (typeof entry === 'string') {
|
|
18
|
+
return { column: entry };
|
|
19
|
+
}
|
|
20
|
+
if (entry instanceof QueryRaw) {
|
|
21
|
+
return { column: ddlText(entry, 'an index expression'), expression: true };
|
|
22
|
+
}
|
|
23
|
+
const { column, ...rest } = entry;
|
|
24
|
+
return column instanceof QueryRaw
|
|
25
|
+
? { ...rest, column: ddlText(column, 'an index expression'), expression: true }
|
|
26
|
+
: { ...rest, column };
|
|
27
|
+
}
|
package/dist/util/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from './dialect.util.js';
|
|
|
2
2
|
export * from './field.util.js';
|
|
3
3
|
export * from './filters.util.js';
|
|
4
4
|
export * from './hook.util.js';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './ddlExpression.util.js';
|
|
6
6
|
export * from './logger.js';
|
|
7
7
|
export * from './object.util.js';
|
|
8
8
|
export * from './raw.js';
|
package/dist/util/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export * from './dialect.util.js';
|
|
|
2
2
|
export * from './field.util.js';
|
|
3
3
|
export * from './filters.util.js';
|
|
4
4
|
export * from './hook.util.js';
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './ddlExpression.util.js';
|
|
6
6
|
export * from './logger.js';
|
|
7
7
|
export * from './object.util.js';
|
|
8
8
|
export * from './raw.js';
|
package/dist/util/sql.util.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export declare function qualifyName(name: string, schema?: string): string;
|
|
|
24
24
|
* `table` is the table's own name, never qualified - the result is a single identifier.
|
|
25
25
|
*/
|
|
26
26
|
export declare function derivedIndexName(table: string, columns: readonly string[]): string;
|
|
27
|
+
/** The constraint name a check gets when nothing named it: `ck_Order_1`, by declaration order. */
|
|
28
|
+
export declare function derivedCheckName(table: string, position: number): string;
|
|
27
29
|
/** The constraint name a foreign key gets when nothing named it: `fk_Order_customerId`. */
|
|
28
30
|
export declare function derivedForeignKeyName(table: string, columns: readonly string[]): string;
|
|
29
31
|
/**
|
package/dist/util/sql.util.js
CHANGED
|
@@ -67,6 +67,10 @@ export function qualifyName(name, schema) {
|
|
|
67
67
|
export function derivedIndexName(table, columns) {
|
|
68
68
|
return `idx_${table}_${columns.join('_')}`;
|
|
69
69
|
}
|
|
70
|
+
/** The constraint name a check gets when nothing named it: `ck_Order_1`, by declaration order. */
|
|
71
|
+
export function derivedCheckName(table, position) {
|
|
72
|
+
return `ck_${table}_${position}`;
|
|
73
|
+
}
|
|
70
74
|
/** The constraint name a foreign key gets when nothing named it: `fk_Order_customerId`. */
|
|
71
75
|
export function derivedForeignKeyName(table, columns) {
|
|
72
76
|
return `fk_${table}_${columns.join('_')}`;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"homepage": "https://uql-orm.dev",
|
|
4
4
|
"description": "JSON-native ORM for Node.js, Bun and Deno. Supports PostgreSQL, PGlite, MySQL, MariaDB, SQLite, CockroachDB, Turso, Neon, Cloudflare D1 and MongoDB. Queries are plain JSON, typed to the leaf.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.41.
|
|
6
|
+
"version": "0.41.1",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=24"
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"README.md"
|
|
57
57
|
],
|
|
58
58
|
"scripts": {
|
|
59
|
-
"prepack": "bun run verify-dist.ts && cp ../../README.md .",
|
|
59
|
+
"prepack": "bun run build && bun run verify-dist.ts && cp ../../README.md .",
|
|
60
60
|
"postpack": "rm README.md && npm pkg delete gitHead",
|
|
61
61
|
"compile.browser": "bun build src/browser/index.ts --minify --sourcemap=linked --format=esm --target=browser --outdir=dist/browser --entry-naming 'uql-browser.min.[ext]'",
|
|
62
62
|
"build": "bun run clean && tsc -b tsconfig.build.json && bun run compile.browser && bun run verify-dist.ts",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type IndexColumnInput, type IndexColumnSchema, QueryRaw } from '../type/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Reduces an authored index entry to its normalized form, so the three shapes users write - a column
|
|
4
|
-
* name, `raw(expression)`, or an options object - reach the dialects as one.
|
|
5
|
-
*/
|
|
6
|
-
export declare function normalizeIndexColumn(entry: IndexColumnInput): IndexColumnSchema;
|
|
7
|
-
/** The partial-index predicate, as authored: `raw` for new code, a bare string for old. */
|
|
8
|
-
export declare function normalizeIndexWhere(where: string | QueryRaw | undefined): string | undefined;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { QueryRaw, RAW_VALUE } from '../type/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Reduces an authored index entry to its normalized form, so the three shapes users write - a column
|
|
4
|
-
* name, `raw(expression)`, or an options object - reach the dialects as one.
|
|
5
|
-
*/
|
|
6
|
-
export function normalizeIndexColumn(entry) {
|
|
7
|
-
if (typeof entry === 'string') {
|
|
8
|
-
return { column: entry };
|
|
9
|
-
}
|
|
10
|
-
if (entry instanceof QueryRaw) {
|
|
11
|
-
return { column: rawSql(entry), expression: true };
|
|
12
|
-
}
|
|
13
|
-
const { column, ...rest } = entry;
|
|
14
|
-
return column instanceof QueryRaw ? { ...rest, column: rawSql(column), expression: true } : { ...rest, column };
|
|
15
|
-
}
|
|
16
|
-
/** The partial-index predicate, as authored: `raw` for new code, a bare string for old. */
|
|
17
|
-
export function normalizeIndexWhere(where) {
|
|
18
|
-
return where instanceof QueryRaw ? rawSql(where, 'a partial-index predicate') : where;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Index DDL is evaluated once at creation time, so it cannot take the dialect-aware callback form of
|
|
22
|
-
* `raw()` - there is no query context to hand it, and no placeholder a `CREATE INDEX` could bind.
|
|
23
|
-
*/
|
|
24
|
-
function rawSql(value, what = 'an index expression') {
|
|
25
|
-
const sql = value[RAW_VALUE];
|
|
26
|
-
if (typeof sql !== 'string') {
|
|
27
|
-
throw new TypeError(`${what} needs raw() with no interpolation, not a function or a bound value`);
|
|
28
|
-
}
|
|
29
|
-
return sql;
|
|
30
|
-
}
|