uql-orm 0.53.0 → 0.54.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/cockroachdb/cockroachDialect.d.ts +2 -5
- package/dist/cockroachdb/cockroachDialect.js +2 -5
- package/dist/dialect/abstractSqlDialect.d.ts +6 -0
- package/dist/dialect/abstractSqlDialect.js +9 -3
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +0 -3
- package/dist/dialect/mysqlLikeSqlDialect.js +0 -3
- package/dist/entity/decorator/members.d.ts +3 -10
- package/dist/entity/metadata/definition.js +0 -4
- package/dist/migrate/builder/migrationBuilder.js +0 -4
- package/dist/migrate/migrator.d.ts +3 -7
- package/dist/migrate/migrator.js +3 -7
- package/dist/migrate/schemaGenerator.d.ts +0 -13
- package/dist/migrate/schemaGenerator.js +0 -13
- package/dist/migrate/storage/databaseStorage.d.ts +2 -2
- package/dist/migrate/storage/databaseStorage.js +2 -2
- package/dist/mongo/mongodbQuerier.d.ts +3 -5
- package/dist/mongo/mongodbQuerier.js +18 -19
- package/dist/mssql/mssqlDialect.d.ts +2 -0
- package/dist/mssql/mssqlDialect.js +2 -0
- package/dist/querier/abstractQuerier.d.ts +17 -22
- package/dist/querier/abstractQuerier.js +80 -57
- package/dist/querier/abstractSqlQuerier.d.ts +9 -9
- package/dist/querier/abstractSqlQuerier.js +68 -84
- package/dist/schema/schemaASTBuilder.js +7 -7
- package/dist/type/entity.d.ts +6 -11
- package/dist/type/migration.d.ts +0 -3
- package/dist/type/query.d.ts +12 -12
- package/dist/type/query.js +0 -6
- package/dist/type/universalQuerier.d.ts +3 -3
- package/dist/util/dialect.util.d.ts +3 -2
- package/dist/util/dialect.util.js +1 -0
- package/dist/util/field.util.d.ts +4 -16
- package/dist/util/field.util.js +6 -19
- package/dist/util/fieldOption.util.d.ts +1 -4
- package/dist/util/fieldOption.util.js +0 -2
- package/dist/util/logger.d.ts +3 -3
- package/dist/util/logger.js +3 -0
- package/dist/util/raw.d.ts +3 -10
- package/dist/util/sql.util.js +2 -2
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { getMeta, soleIdOf } from '../entity/metadata/definition.js';
|
|
9
9
|
import { ddlText } from '../util/ddlExpression.util.js';
|
|
10
|
-
import {
|
|
10
|
+
import { isInlinedExpression } from '../util/field.util.js';
|
|
11
11
|
import { isSoleIdField } from '../util/field.util.js';
|
|
12
12
|
import { isAutoIncrement } from '../util/field.util.js';
|
|
13
13
|
import { derivedForeignKeyName, derivedIndexName, qualifyName } from '../util/sql.util.js';
|
|
@@ -101,7 +101,7 @@ function addTableFromEntity(ctx, meta) {
|
|
|
101
101
|
isPrimaryKey,
|
|
102
102
|
isAutoIncrement: isAutoIncrement(field, isSoleKey),
|
|
103
103
|
isUnique: field.unique ?? false,
|
|
104
|
-
generatedAs: ddlText(
|
|
104
|
+
generatedAs: ddlText(field.computed, `the computed column '${columnName}'`),
|
|
105
105
|
comment: field.comment,
|
|
106
106
|
enum: field.enum,
|
|
107
107
|
table,
|
|
@@ -202,16 +202,16 @@ function addIndexesFromEntity(ctx, meta) {
|
|
|
202
202
|
addCompositeIndex(ctx, table, meta, idxMeta);
|
|
203
203
|
}
|
|
204
204
|
}
|
|
205
|
-
/**
|
|
206
|
-
* One `@Index([...])`. Its entries keep the authored form (expression, prefix length, order) with
|
|
207
|
-
* names resolved, so the generator renders exactly what was declared; `columns` is the resolvable
|
|
208
|
-
* subset, which is what diffing and introspection compare.
|
|
209
|
-
*/
|
|
210
205
|
/** An `include` column is named like any other, so a naming strategy has to reach it too. */
|
|
211
206
|
function resolveIncludeColumn(ctx, meta, column) {
|
|
212
207
|
const field = meta.fields[column];
|
|
213
208
|
return field ? ctx.resolveColumnName(column, field) : column;
|
|
214
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* One `@Index([...])`. Its entries keep the authored form (expression, prefix length, order) with
|
|
212
|
+
* names resolved, so the generator renders exactly what was declared; `columns` is the resolvable
|
|
213
|
+
* subset, which is what diffing and introspection compare.
|
|
214
|
+
*/
|
|
215
215
|
function addCompositeIndex(ctx, table, meta, idxMeta) {
|
|
216
216
|
// An entry survives if it is an expression (nothing to resolve) or names a column that exists;
|
|
217
217
|
// an index left with none is dropped, the same as one naming only unknown columns always was.
|
package/dist/type/entity.d.ts
CHANGED
|
@@ -359,11 +359,6 @@ export type FieldOptions<V = TsTypeOf<FieldType>> = {
|
|
|
359
359
|
* @example `@Field({ type: String, enum: ['draft', 'paid'] as const })`
|
|
360
360
|
*/
|
|
361
361
|
readonly enum?: EnumValues;
|
|
362
|
-
/**
|
|
363
|
-
* @deprecated Renamed to {@link FieldOptions.computed}, which also takes `stored`. `npx uql-codemod`
|
|
364
|
-
* rewrites it. Giving both throws.
|
|
365
|
-
*/
|
|
366
|
-
readonly virtual?: QueryRaw;
|
|
367
362
|
/**
|
|
368
363
|
* An expression the database computes, rather than a value the caller writes. Never part of an
|
|
369
364
|
* insert or update either way.
|
|
@@ -818,12 +813,6 @@ export type EntityMeta<E> = {
|
|
|
818
813
|
/** The revision `getMeta` last finalized, which is what makes finalizing idempotent and re-entrant. */
|
|
819
814
|
processedAt?: number;
|
|
820
815
|
};
|
|
821
|
-
/**
|
|
822
|
-
* Configurable options for an entity (`@Entity()` / `defineEntity`).
|
|
823
|
-
*
|
|
824
|
-
* Optional `fields`, `relations`, `indexes`, and `hooks` register metadata in one call for
|
|
825
|
-
* decorator-free setups. Omit them when using `@Field` / `@ManyToOne` / etc.
|
|
826
|
-
*/
|
|
827
816
|
/**
|
|
828
817
|
* A table-level `CHECK`. The expression is `raw` with no interpolation, like an index expression:
|
|
829
818
|
* this is DDL, so there is no placeholder a bound value could go into.
|
|
@@ -843,6 +832,12 @@ export type EntityMembers = {
|
|
|
843
832
|
readonly relations?: Readonly<Record<string, RelationOptions | undefined>>;
|
|
844
833
|
readonly hooks?: Readonly<Partial<Record<HookEvent, readonly string[]>>>;
|
|
845
834
|
};
|
|
835
|
+
/**
|
|
836
|
+
* Configurable options for an entity (`@Entity()` / `defineEntity`).
|
|
837
|
+
*
|
|
838
|
+
* Optional `fields`, `relations`, `indexes`, and `hooks` register metadata in one call for
|
|
839
|
+
* decorator-free setups. Omit them when using `@Field` / `@ManyToOne` / etc.
|
|
840
|
+
*/
|
|
846
841
|
export type EntityOptions<E = unknown> = {
|
|
847
842
|
readonly name?: string;
|
|
848
843
|
/**
|
package/dist/type/migration.d.ts
CHANGED
|
@@ -372,9 +372,6 @@ export interface SchemaIntrospector {
|
|
|
372
372
|
* the database side never reports it, and no migration can close the gap.
|
|
373
373
|
*/
|
|
374
374
|
readonly indexFacets: ReadonlySet<IndexFacet>;
|
|
375
|
-
/**
|
|
376
|
-
* Introspect entire database schema and return SchemaAST.
|
|
377
|
-
*/
|
|
378
375
|
/** The whole database, or just the tables named. Names nothing matches are left out. */
|
|
379
376
|
introspect(tables?: readonly string[]): Promise<SchemaAST>;
|
|
380
377
|
/**
|
package/dist/type/query.d.ts
CHANGED
|
@@ -59,17 +59,17 @@ export type QueryExclude<E> = QuerySelect<E>;
|
|
|
59
59
|
export type QueryPopulate<E> = {
|
|
60
60
|
[K in RelationKey<E>]?: BooleanLike | QueryPopulateRelationOptions<E[K]>;
|
|
61
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* The key a read carries its relation tallies under. One spelling for the type and the runtime that
|
|
64
|
+
* fills it: they sit in different modules, so a drift would type-check and answer `undefined`.
|
|
65
|
+
*/
|
|
66
|
+
export declare const COUNT_RESULT_KEY = "_count";
|
|
62
67
|
/**
|
|
63
68
|
* How many rows each named relation holds per parent, `true` for all of them or a filter to narrow
|
|
64
69
|
* which ones count. One statement per relation named here, batched over every parent at once, so it
|
|
65
70
|
* stays flat however many rows the read returned. Comes back under `_count`, which keeps it clear of
|
|
66
71
|
* a relation of the same name that `$populate` filled with rows.
|
|
67
72
|
*/
|
|
68
|
-
/**
|
|
69
|
-
* The key a read carries its relation tallies under. One spelling for the type and the runtime that
|
|
70
|
-
* fills it: they sit in different modules, so a drift would type-check and answer `undefined`.
|
|
71
|
-
*/
|
|
72
|
-
export declare const COUNT_RESULT_KEY = "_count";
|
|
73
73
|
export type QueryCount<E> = {
|
|
74
74
|
[K in ToManyRelationKey<E>]?: BooleanLike | QueryFilter<RelationTarget<E[K]>>;
|
|
75
75
|
};
|
|
@@ -141,6 +141,13 @@ type ToOneRelationKey<E> = {
|
|
|
141
141
|
}[RelationKey<E>];
|
|
142
142
|
/** The relation names a parent holds many rows of, which a populated query fills with a list. */
|
|
143
143
|
type ToManyRelationKey<E> = Exclude<RelationKey<E>, ToOneRelationKey<E>>;
|
|
144
|
+
/**
|
|
145
|
+
* Ordering parents by how many rows a to-many relation holds - "the ten users with the most posts".
|
|
146
|
+
* The tally is computed per parent as a correlated count, never by loading the rows.
|
|
147
|
+
*/
|
|
148
|
+
export type QuerySortByCount = {
|
|
149
|
+
$count: QuerySortDirection;
|
|
150
|
+
};
|
|
144
151
|
/**
|
|
145
152
|
* sort by map - supports field keys, JSON dot-notation paths (restricted to real JSON fields,
|
|
146
153
|
* like `QueryWhere`), relation sort via nested objects, and vector similarity search on
|
|
@@ -153,13 +160,6 @@ type ToManyRelationKey<E> = Exclude<RelationKey<E>, ToOneRelationKey<E>>;
|
|
|
153
160
|
* against an intersection is repeated per constituent, which made this the single most expensive
|
|
154
161
|
* type in the package to check.
|
|
155
162
|
*/
|
|
156
|
-
/**
|
|
157
|
-
* Ordering parents by how many rows a to-many relation holds - "the ten users with the most posts".
|
|
158
|
-
* The tally is computed per parent as a correlated count, never by loading the rows.
|
|
159
|
-
*/
|
|
160
|
-
export type QuerySortByCount = {
|
|
161
|
-
$count: QuerySortDirection;
|
|
162
|
-
};
|
|
163
163
|
export type QuerySortMap<E, Vector extends boolean = true> = {
|
|
164
164
|
[K in FieldKey<E> | JsonFieldPaths<E> | RelationKey<E>]?: K extends RelationKey<E> ? IsMany<E[K]> extends true ? QuerySortByCount : QuerySortMap<RelationTarget<E[K]>, false> : K extends FieldKey<E> ? Vector extends true ? NonNullable<E[K]> extends readonly number[] ? QuerySortValue : QuerySortDirection : QuerySortDirection : QuerySortDirection;
|
|
165
165
|
};
|
package/dist/type/query.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* How many rows each named relation holds per parent, `true` for all of them or a filter to narrow
|
|
3
|
-
* which ones count. One statement per relation named here, batched over every parent at once, so it
|
|
4
|
-
* stays flat however many rows the read returned. Comes back under `_count`, which keeps it clear of
|
|
5
|
-
* a relation of the same name that `$populate` filled with rows.
|
|
6
|
-
*/
|
|
7
1
|
/**
|
|
8
2
|
* The key a read carries its relation tallies under. One spelling for the type and the runtime that
|
|
9
3
|
* fills it: they sit in different modules, so a drift would type-check and answer `undefined`.
|
|
@@ -126,7 +126,7 @@ export interface UniversalQuerier extends SharedQuerier<'server', QueryOptions>
|
|
|
126
126
|
* on MySQL/SQLite they are inferred from the driver header, which is only reliable for
|
|
127
127
|
* auto-increment keys in batches without explicit IDs - otherwise those entries are
|
|
128
128
|
* `undefined` rather than potentially wrong values. A composite key is never one the statement
|
|
129
|
-
* reports, so those rows are named
|
|
129
|
+
* reports, so those rows are named as written, `onInsert` columns included.
|
|
130
130
|
* @param entity the entity to persist on
|
|
131
131
|
* @param payload the data to be persisted
|
|
132
132
|
* @return the IDs
|
|
@@ -137,7 +137,7 @@ export interface UniversalQuerier extends SharedQuerier<'server', QueryOptions>
|
|
|
137
137
|
* @param entity the entity to persist on
|
|
138
138
|
* @param conflictPaths the keys to use for the unique search
|
|
139
139
|
* @param payload the data to be persisted
|
|
140
|
-
* @return
|
|
140
|
+
* @return the id and whether it was created; see {@link QueryUpsertOneResult}
|
|
141
141
|
*/
|
|
142
142
|
upsertOne<E extends object>(entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: EntityData<E>): Promise<QueryUpsertOneResult<E>>;
|
|
143
143
|
/**
|
|
@@ -145,7 +145,7 @@ export interface UniversalQuerier extends SharedQuerier<'server', QueryOptions>
|
|
|
145
145
|
* @param entity the entity to persist on
|
|
146
146
|
* @param conflictPaths the keys to use for the unique search
|
|
147
147
|
* @param payload the data to be persisted
|
|
148
|
-
* @return
|
|
148
|
+
* @return the ids, in payload order; see {@link QueryUpsertManyResult}
|
|
149
149
|
*/
|
|
150
150
|
upsertMany<E extends object>(entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: EntityData<E>[]): Promise<QueryUpsertManyResult<E>>;
|
|
151
151
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CascadeType, type EntityData, type EntityId, type EntityIndexMeta, type EntityMeta, type FieldKey, type FieldOptions, type JsonUpdateOp, type OnFieldCallback, type Query, type QueryAggMap, type QueryAggregateOp, type QueryExclude, type QueryGroupMap, type QueryOptions, QueryRaw, type QuerySearch, type QuerySelect, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryVectorSearch, type QueryWhere, type RelationKey } from '../type/index.js';
|
|
1
|
+
import { type CascadeType, type EntityData, type EntityId, type EntityIndexMeta, type EntityMeta, type FieldKey, type FieldOptions, type JsonUpdateOp, type OnFieldCallback, type Query, type QueryAggMap, type QueryAggregateOp, type QueryExclude, type QueryGroupMap, type QueryOptions, QueryRaw, type QuerySearch, type QuerySelect, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryVectorSearch, type QueryWhere, type RelationKey, type UpdatePayload } from '../type/index.js';
|
|
2
2
|
export type CallbackKey = keyof Pick<FieldOptions, 'onInsert' | 'onUpdate'>;
|
|
3
3
|
export declare function filterFieldKeys<E>(meta: EntityMeta<E>, payload: EntityData<E>, callbackKey: CallbackKey): FieldKey<E>[];
|
|
4
4
|
/** Appends `record`'s not-yet-`seen` insertable keys (real, caller-written, defined value) to `keys`. */
|
|
@@ -35,7 +35,8 @@ export declare function getSoftDeleteValue(field: FieldOptions): string | number
|
|
|
35
35
|
}[] | readonly number[] | Uint8Array<ArrayBufferLike> | {
|
|
36
36
|
readonly __json?: never;
|
|
37
37
|
};
|
|
38
|
-
|
|
38
|
+
/** Fills each field `callbackKey` generates on `payload` in place, where the caller left it unset. */
|
|
39
|
+
export declare function fillOnFields<E, R extends EntityData<E> | UpdatePayload<E>>(meta: EntityMeta<E>, payload: R | R[], callbackKey: CallbackKey): R[];
|
|
39
40
|
/**
|
|
40
41
|
* The relation keys present in `payload` whose cascade configuration allows `action`. Only
|
|
41
42
|
* `payload`'s keys are read, so any keys-bearing object works (an entity, an update payload,
|
|
@@ -73,6 +73,7 @@ export function getFieldCallbackValue(val) {
|
|
|
73
73
|
export function getSoftDeleteValue(field) {
|
|
74
74
|
return field.softDelete === true ? new Date() : getFieldCallbackValue(field.softDelete);
|
|
75
75
|
}
|
|
76
|
+
/** Fills each field `callbackKey` generates on `payload` in place, where the caller left it unset. */
|
|
76
77
|
export function fillOnFields(meta, payload, callbackKey) {
|
|
77
78
|
const payloads = Array.isArray(payload) ? payload : [payload];
|
|
78
79
|
const keys = getKeys(meta.fields).filter((key) => meta.fields[key][callbackKey]);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { EntityMeta, FieldOptions } from '../type/index.js';
|
|
2
|
-
import type { QueryRaw } from '../type/queryRaw.js';
|
|
3
2
|
/**
|
|
4
3
|
* The kind of column a field lands on, which is what decides whether an option means anything on it:
|
|
5
4
|
* `length` is a string's, `precision` a number's, `dimensions` a vector's. Named in the words an
|
|
@@ -23,26 +22,15 @@ export declare const COLUMN_TYPES_BY_FAMILY: {
|
|
|
23
22
|
};
|
|
24
23
|
/** The family of a logical field type, or `undefined` where it names none. */
|
|
25
24
|
export declare function columnFamily(type: unknown): ColumnFamily | undefined;
|
|
26
|
-
/**
|
|
27
|
-
* The expression the database computes for this field, whichever key declared it.
|
|
28
|
-
*
|
|
29
|
-
* `virtual` is `computed` under its old name and is read here so both spell one behaviour. Giving
|
|
30
|
-
* both is refused at registration rather than resolved, since only the author knows which was meant.
|
|
31
|
-
*/
|
|
32
|
-
export declare function computedExpression(field: FieldOptions): QueryRaw | undefined;
|
|
33
25
|
/**
|
|
34
26
|
* Whether the field's expression is spliced into each statement that reads it, rather than stored.
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* the projection, the `$where` operand, the `ORDER BY` operand - because an inlined field has no
|
|
38
|
-
* column to name, while a stored one is read exactly like any other.
|
|
27
|
+
* Every read site asks this - the DDL skip, the projection, the `$where` and `ORDER BY` operands -
|
|
28
|
+
* because an inlined field has no column to name, while a stored one is read like any other.
|
|
39
29
|
*/
|
|
40
30
|
export declare function isInlinedExpression(field: FieldOptions): boolean;
|
|
41
31
|
/**
|
|
42
|
-
* Whether the database supplies this field's value, so no insert or update may write it
|
|
43
|
-
*
|
|
44
|
-
* The other question, and the one that makes `stored` more than a rename: a stored computed column
|
|
45
|
-
* *is* a real column, so it is read like one - but writing to it is an error on every engine.
|
|
32
|
+
* Whether the database supplies this field's value, so no insert or update may write it: a stored
|
|
33
|
+
* computed column *is* a real column, read like one, but writing to it is an error on every engine.
|
|
46
34
|
*/
|
|
47
35
|
export declare function isDatabaseWritten(field: FieldOptions): boolean;
|
|
48
36
|
/**
|
package/dist/util/field.util.js
CHANGED
|
@@ -46,33 +46,20 @@ for (const family of getKeys(COLUMN_TYPES_BY_FAMILY)) {
|
|
|
46
46
|
export function columnFamily(type) {
|
|
47
47
|
return FAMILY_OF.get(typeof type === 'string' ? type.toLowerCase() : type);
|
|
48
48
|
}
|
|
49
|
-
/**
|
|
50
|
-
* The expression the database computes for this field, whichever key declared it.
|
|
51
|
-
*
|
|
52
|
-
* `virtual` is `computed` under its old name and is read here so both spell one behaviour. Giving
|
|
53
|
-
* both is refused at registration rather than resolved, since only the author knows which was meant.
|
|
54
|
-
*/
|
|
55
|
-
export function computedExpression(field) {
|
|
56
|
-
return field.computed ?? field.virtual;
|
|
57
|
-
}
|
|
58
49
|
/**
|
|
59
50
|
* Whether the field's expression is spliced into each statement that reads it, rather than stored.
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* the projection, the `$where` operand, the `ORDER BY` operand - because an inlined field has no
|
|
63
|
-
* column to name, while a stored one is read exactly like any other.
|
|
51
|
+
* Every read site asks this - the DDL skip, the projection, the `$where` and `ORDER BY` operands -
|
|
52
|
+
* because an inlined field has no column to name, while a stored one is read like any other.
|
|
64
53
|
*/
|
|
65
54
|
export function isInlinedExpression(field) {
|
|
66
|
-
return
|
|
55
|
+
return field.computed !== undefined && field.stored !== true;
|
|
67
56
|
}
|
|
68
57
|
/**
|
|
69
|
-
* Whether the database supplies this field's value, so no insert or update may write it
|
|
70
|
-
*
|
|
71
|
-
* The other question, and the one that makes `stored` more than a rename: a stored computed column
|
|
72
|
-
* *is* a real column, so it is read like one - but writing to it is an error on every engine.
|
|
58
|
+
* Whether the database supplies this field's value, so no insert or update may write it: a stored
|
|
59
|
+
* computed column *is* a real column, read like one, but writing to it is an error on every engine.
|
|
73
60
|
*/
|
|
74
61
|
export function isDatabaseWritten(field) {
|
|
75
|
-
return
|
|
62
|
+
return field.computed !== undefined;
|
|
76
63
|
}
|
|
77
64
|
/**
|
|
78
65
|
* Whether the field is the entity's *whole* primary key - the only kind a serial can stand in for,
|
|
@@ -14,7 +14,6 @@ declare const FIELD_OPTION_FAMILY: {
|
|
|
14
14
|
readonly references: '*';
|
|
15
15
|
readonly onDelete: '*';
|
|
16
16
|
readonly enum: '*';
|
|
17
|
-
readonly virtual: '*';
|
|
18
17
|
readonly computed: '*';
|
|
19
18
|
readonly stored: '*';
|
|
20
19
|
readonly updatable: '*';
|
|
@@ -39,7 +38,7 @@ declare const FIELD_OPTION_FAMILY: {
|
|
|
39
38
|
* rather than on each option that dies, because it is one fact rather than nineteen - and because an
|
|
40
39
|
* option added without a thought then lands on the safe side of it.
|
|
41
40
|
*/
|
|
42
|
-
declare const INLINE_READS: readonly ["type", "
|
|
41
|
+
declare const INLINE_READS: readonly ["type", "computed", "stored", "enum", "eager", "distance"];
|
|
43
42
|
type InlineRead = (typeof INLINE_READS)[number];
|
|
44
43
|
/**
|
|
45
44
|
* What a column the *database* writes cannot use. A stored computed column is a real column - it has
|
|
@@ -66,8 +65,6 @@ type FamilyOfType<T> = T extends NumericColumnType | NumberConstructor | BigIntC
|
|
|
66
65
|
type DeadOptions<O> = (O extends {
|
|
67
66
|
readonly stored: true;
|
|
68
67
|
} ? GeneratedWrite : O extends {
|
|
69
|
-
readonly virtual: QueryRaw;
|
|
70
|
-
} | {
|
|
71
68
|
readonly computed: QueryRaw;
|
|
72
69
|
} ? Exclude<keyof FieldOptions, InlineRead> : never) | (O extends {
|
|
73
70
|
readonly isId: true;
|
|
@@ -14,7 +14,6 @@ const FIELD_OPTION_FAMILY = {
|
|
|
14
14
|
references: '*',
|
|
15
15
|
onDelete: '*',
|
|
16
16
|
enum: '*',
|
|
17
|
-
virtual: '*',
|
|
18
17
|
computed: '*',
|
|
19
18
|
stored: '*',
|
|
20
19
|
updatable: '*',
|
|
@@ -41,7 +40,6 @@ const FIELD_OPTION_FAMILY = {
|
|
|
41
40
|
*/
|
|
42
41
|
const INLINE_READS = [
|
|
43
42
|
'type',
|
|
44
|
-
'virtual',
|
|
45
43
|
'computed',
|
|
46
44
|
'stored',
|
|
47
45
|
'enum',
|
package/dist/util/logger.d.ts
CHANGED
|
@@ -12,9 +12,6 @@ export declare class DefaultLogger implements Logger {
|
|
|
12
12
|
logMigration(message: string): void;
|
|
13
13
|
logSkippedMigration(message: string): void;
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
16
|
-
* A wrapper class that implements the Logger interface and handles different logging options.
|
|
17
|
-
*/
|
|
18
15
|
/**
|
|
19
16
|
* Secondary {@link LoggerWrapper} settings, alongside the primary `options: LoggingOptions`
|
|
20
17
|
* constructor argument.
|
|
@@ -28,6 +25,9 @@ export interface LoggerWrapperConfig {
|
|
|
28
25
|
/** Threshold in milliseconds - queries exceeding this are logged as slow. */
|
|
29
26
|
slowQuery?: number;
|
|
30
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* A wrapper class that implements the Logger interface and handles different logging options.
|
|
30
|
+
*/
|
|
31
31
|
export declare class LoggerWrapper implements Logger {
|
|
32
32
|
private readonly levels;
|
|
33
33
|
private readonly logger?;
|
package/dist/util/logger.js
CHANGED
|
@@ -40,6 +40,9 @@ export class DefaultLogger {
|
|
|
40
40
|
console.info(`\x1b[33mskipped migration:\x1b[0m ${message}`);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* A wrapper class that implements the Logger interface and handles different logging options.
|
|
45
|
+
*/
|
|
43
46
|
export class LoggerWrapper {
|
|
44
47
|
levels;
|
|
45
48
|
logger;
|
package/dist/util/raw.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { QueryRaw, type QueryRawFn
|
|
1
|
+
import { QueryRaw, type QueryRawFn } from '../type/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Create a raw SQL expression.
|
|
4
4
|
*
|
|
@@ -19,18 +19,11 @@ import { QueryRaw, type QueryRawFn, type Scalar } from '../type/index.js';
|
|
|
19
19
|
* The callback form remains for SQL a template cannot express, such as a sub-query generated through
|
|
20
20
|
* `dialect.find(...)`. See {@link col} for a context-aware column reference.
|
|
21
21
|
*
|
|
22
|
-
* **⚠️ Security:** the tag is safe because it binds;
|
|
23
|
-
*
|
|
24
|
-
* Inside a callback, bind with `ctx.addValue()`.
|
|
22
|
+
* **⚠️ Security:** the tag is safe because it binds; a callback is not, since it emits whatever it
|
|
23
|
+
* writes, so never build one from user input. Inside a callback, bind with `ctx.addValue()`.
|
|
25
24
|
*/
|
|
26
25
|
export declare function raw(strings: TemplateStringsArray, ...values: readonly unknown[]): QueryRaw;
|
|
27
26
|
export declare function raw(value: QueryRawFn, alias?: string): QueryRaw;
|
|
28
|
-
/**
|
|
29
|
-
* @deprecated Emits its argument verbatim, so it cannot bind a value. Use the tagged template:
|
|
30
|
-
* `raw('"a" > 1')` becomes `` raw`"a" > 1` ``, and `raw('LOG10(x)', 'score')` becomes
|
|
31
|
-
* `` raw`LOG10(x)`.as('score') ``. `npx uql-codemod` rewrites both.
|
|
32
|
-
*/
|
|
33
|
-
export declare function raw(value: Scalar, alias?: string): QueryRaw;
|
|
34
27
|
/**
|
|
35
28
|
* A column of the entity being queried, alias-qualified and escaped for the dialect. This is what a
|
|
36
29
|
* template cannot know on its own: the alias is decided while the statement is built, not where the
|
package/dist/util/sql.util.js
CHANGED
|
@@ -200,8 +200,8 @@ export function buildUpdateResult(payload) {
|
|
|
200
200
|
// UPDATE` convention makes `changes` a per-row weighted sum (1=insert, 2=update, 0=no-op), so a
|
|
201
201
|
// batch mixing an insert and an update would fabricate ids for rows that were never touched. This
|
|
202
202
|
// function has no way to tell the two call sites apart (`internalRun` reports the same header
|
|
203
|
-
// shape either way), so `AbstractSqlQuerier
|
|
204
|
-
//
|
|
203
|
+
// shape either way), so `AbstractSqlQuerier`'s `runUpsert` discards them for a multi-row `firstId`
|
|
204
|
+
// upsert and reads the ids back by the conflict columns instead.
|
|
205
205
|
let ids = [];
|
|
206
206
|
if (rows?.length) {
|
|
207
207
|
ids = rows.map((r) => r['id']);
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"homepage": "https://uql-orm.dev",
|
|
4
4
|
"description": "The JSON-native TypeScript ORM for Bun, Browsers, Edge, Deno, Node, Workers. Supports PostgreSQL, PGlite, MySQL, MariaDB, SQLite, CockroachDB, SQL Server, Turso, Neon, Cloudflare D1 and MongoDB. Queries are plain JSON, typed to the leaf.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.54.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=24"
|