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,4 +1,4 @@
|
|
|
1
|
-
import { type EntityData, type EntityMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryBuildFn, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryDialect, type QueryExclude, type QueryFilter, type QueryGroupMap, type QueryGroupOp, type QueryHavingMap, type QueryOptions, type QueryPager, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryTextSearchOptions, type QueryVectorNear, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereOptions, type RelationMeta, type SqlDialectName, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
|
|
1
|
+
import { type EntityData, type EntityMeta, type EntityWhereMeta, type FieldKey, type FieldOptions, type IsolationLevel, type JsonColumnType, type JsonUpdateOp, type Query, type QueryAggMap, type QueryAggregate, type QueryBuildFn, type QueryComparisonOptions, type QueryConflictPaths, type QueryContext, type QueryContextOptions, type QueryDialect, type QueryExclude, type QueryFilter, type QueryGroupMap, type QueryGroupOp, type QueryHavingMap, type QueryOptions, type QueryPager, QueryRaw, type QueryRawFnOptions, type QuerySearch, type QuerySelectValue, type QuerySizeComparisonOps, type QuerySortMap, type QueryTextSearchOptions, type QueryVectorNear, type QueryWhere, type QueryWhereArray, type QueryWhereFieldOperatorMap, type QueryWhereOptions, type RelationMeta, type SqlDialectName, type SqlQueryDialect, type Type, type UpdatePayload } from '../type/index.js';
|
|
2
2
|
import { type ColumnFamily } from '../util/field.util.js';
|
|
3
3
|
import type { HydrateKind } from './hydrateColumn.js';
|
|
4
4
|
import { type JsonAccessMode } from './jsonSql.js';
|
|
@@ -128,7 +128,7 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
128
128
|
*/
|
|
129
129
|
readonly maxFunctionArgs: number;
|
|
130
130
|
getBeginTransactionStatements(isolationLevel?: IsolationLevel): string[];
|
|
131
|
-
createContext(): QueryContext;
|
|
131
|
+
createContext(options?: QueryContextOptions): QueryContext;
|
|
132
132
|
/**
|
|
133
133
|
* Builds SQL text in isolation via `build`, so the caller can embed it inline (e.g.
|
|
134
134
|
* `"col" = <text>`) instead of appending it at the end of `ctx`. The fragment binds any value
|
|
@@ -139,8 +139,8 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
139
139
|
* shared for the same reason - see {@link SqlQueryContext}.
|
|
140
140
|
*/
|
|
141
141
|
protected buildFragment(ctx: QueryContext, build: QueryBuildFn): string;
|
|
142
|
-
/** A `raw()`
|
|
143
|
-
protected rawFragment(ctx: QueryContext, value: QueryRaw): string;
|
|
142
|
+
/** A `raw()` rendered in place, an operand or a projected term: bound, the driver would get the object. */
|
|
143
|
+
protected rawFragment(ctx: QueryContext, value: QueryRaw, prefix?: string, entity?: Type<unknown>): string;
|
|
144
144
|
/**
|
|
145
145
|
* Each operand rendered into its own fragment, keeping only those that emitted SQL.
|
|
146
146
|
*
|
|
@@ -150,7 +150,7 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
150
150
|
* the caller counts what comes back rather than what it passed in.
|
|
151
151
|
*/
|
|
152
152
|
protected renderOperands<T>(ctx: QueryContext, operands: readonly T[], render: (ctx: QueryContext, operand: T) => void): string[];
|
|
153
|
-
addValue(
|
|
153
|
+
addValue(ctx: QueryContext, value: unknown): string;
|
|
154
154
|
/**
|
|
155
155
|
* A parameter value as this engine's driver takes it: a boolean as the integer an engine with no
|
|
156
156
|
* boolean type stores, and everything else as it is - a `bigint` included, which every driver here
|
|
@@ -188,8 +188,6 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
188
188
|
selectTerms<E>(ctx: QueryContext, entity: Type<E>, select: QuerySelectValue<E> | undefined, opts?: SelectOptions, exclude?: QueryExclude<E>): SelectTerm[];
|
|
189
189
|
/** One field's column, or the expression an inlined one stands for, as the projection reads it. */
|
|
190
190
|
private fieldTerm;
|
|
191
|
-
/** A `raw()` rendered where it stands, without the alias a projection writes for it. */
|
|
192
|
-
private rawSql;
|
|
193
191
|
/**
|
|
194
192
|
* What follows `SELECT` before the projection. Empty everywhere but SQL Server, whose `FETCH` will
|
|
195
193
|
* not take a zero and which spells "no rows" as `TOP (0)` instead.
|
|
@@ -649,6 +647,13 @@ export declare abstract class AbstractSqlDialect extends VectorSqlDialect implem
|
|
|
649
647
|
protected abstract jsonPush(ctx: QueryContext, expr: string, push: Record<string, unknown>): string;
|
|
650
648
|
/** Remove object keys. */
|
|
651
649
|
protected abstract jsonUnset(ctx: QueryContext, expr: string, unset: readonly string[]): string;
|
|
650
|
+
/**
|
|
651
|
+
* The text of SQL a schema declares, as DDL carries it: values written as literals, and none left bound,
|
|
652
|
+
* since a `CREATE` statement has no placeholder to bind one into. An entity's SQL reads its fields, a
|
|
653
|
+
* predicate with no entity filter applied; a migration's is `raw` reading none.
|
|
654
|
+
*/
|
|
655
|
+
compileDdl(sql: QueryRaw): string;
|
|
656
|
+
compileDdl<E>(sql: EntityWhereMeta<E>, entity: Type<E>): string;
|
|
652
657
|
getRawValue(ctx: QueryContext, opts: QueryRawFnOptions & {
|
|
653
658
|
value: QueryRaw;
|
|
654
659
|
}): void;
|
|
@@ -83,8 +83,8 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
83
83
|
// 'set-before' - MySQL/MariaDB pattern
|
|
84
84
|
return [`SET TRANSACTION ISOLATION LEVEL ${level}`, this.beginTransactionCommand];
|
|
85
85
|
}
|
|
86
|
-
createContext() {
|
|
87
|
-
return new SqlQueryContext(this);
|
|
86
|
+
createContext(options = {}) {
|
|
87
|
+
return new SqlQueryContext(this, [], undefined, options.inlineValues);
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Builds SQL text in isolation via `build`, so the caller can embed it inline (e.g.
|
|
@@ -100,9 +100,9 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
100
100
|
build(fragmentCtx);
|
|
101
101
|
return fragmentCtx.sql;
|
|
102
102
|
}
|
|
103
|
-
/** A `raw()`
|
|
104
|
-
rawFragment(ctx, value) {
|
|
105
|
-
return this.buildFragment(ctx, (fragmentCtx) => this.getRawValue(fragmentCtx, { value }));
|
|
103
|
+
/** A `raw()` rendered in place, an operand or a projected term: bound, the driver would get the object. */
|
|
104
|
+
rawFragment(ctx, value, prefix, entity) {
|
|
105
|
+
return this.buildFragment(ctx, (fragmentCtx) => this.getRawValue(fragmentCtx, { value, prefix, entity }));
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
108
|
* Each operand rendered into its own fragment, keeping only those that emitted SQL.
|
|
@@ -117,9 +117,15 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
117
117
|
.map((operand) => this.buildFragment(ctx, (fragmentCtx) => render(fragmentCtx, operand)))
|
|
118
118
|
.filter((part) => part !== '');
|
|
119
119
|
}
|
|
120
|
-
addValue(
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
addValue(ctx, value) {
|
|
121
|
+
if (value instanceof QueryRaw) {
|
|
122
|
+
return this.rawFragment(ctx, value);
|
|
123
|
+
}
|
|
124
|
+
if (ctx.inlineValues) {
|
|
125
|
+
return this.escape(this.normalizeValue(value));
|
|
126
|
+
}
|
|
127
|
+
ctx.values.push(this.normalizeValue(value));
|
|
128
|
+
return this.placeholder(ctx.values.length);
|
|
123
129
|
}
|
|
124
130
|
/**
|
|
125
131
|
* A parameter value as this engine's driver takes it: a boolean as the integer an engine with no
|
|
@@ -196,7 +202,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
196
202
|
return [{ sql: `${this.escapeId(opts.prefix, true, true)}*`, bare: true }];
|
|
197
203
|
}
|
|
198
204
|
return keys.map((key) => key instanceof QueryRaw
|
|
199
|
-
? { sql: this.
|
|
205
|
+
? { sql: this.rawFragment(ctx, key, opts.prefix), key: key[RAW_ALIAS] }
|
|
200
206
|
: this.fieldTerm(ctx, meta, key, opts));
|
|
201
207
|
}
|
|
202
208
|
/** One field's column, or the expression an inlined one stands for, as the projection reads it. */
|
|
@@ -206,7 +212,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
206
212
|
// Qualified even when nothing else in this statement is: the expression is spliced in, and one
|
|
207
213
|
// that opens a correlated subquery has the inner table's columns in scope, so a bare `"id"`
|
|
208
214
|
// would bind to *that* table instead of this one.
|
|
209
|
-
const sql = this.
|
|
215
|
+
const sql = this.rawFragment(ctx, field.computed, opts.prefix ?? this.resolveTableAlias(meta), meta.entity);
|
|
210
216
|
return { sql: opts.json ? this.carried(`(${sql})`, field) : sql, key };
|
|
211
217
|
}
|
|
212
218
|
const columnName = this.resolveColumnName(key, field);
|
|
@@ -214,15 +220,6 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
214
220
|
const sql = opts.json ? this.carried(column, field) : this.selectFieldExpr(column, field);
|
|
215
221
|
return { sql, key, bare: sql === column && columnName === key };
|
|
216
222
|
}
|
|
217
|
-
/** A `raw()` rendered where it stands, without the alias a projection writes for it. */
|
|
218
|
-
rawSql(ctx, value, prefix) {
|
|
219
|
-
return this.buildFragment(ctx, (fragmentCtx) => value.render({
|
|
220
|
-
ctx: fragmentCtx,
|
|
221
|
-
dialect: this,
|
|
222
|
-
prefix: prefix ?? '',
|
|
223
|
-
escapedPrefix: this.escapeId(prefix, true, true),
|
|
224
|
-
}));
|
|
225
|
-
}
|
|
226
223
|
/**
|
|
227
224
|
* What follows `SELECT` before the projection. Empty everywhere but SQL Server, whose `FETCH` will
|
|
228
225
|
* not take a zero and which spells "no rows" as `TOP (0)` instead.
|
|
@@ -425,7 +422,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
425
422
|
}
|
|
426
423
|
this.getComparisonKey(ctx, entity, key, opts);
|
|
427
424
|
ctx.append(' = ');
|
|
428
|
-
this.getRawValue(ctx, { value: val });
|
|
425
|
+
this.getRawValue(ctx, { value: val, prefix: opts.prefix });
|
|
429
426
|
return;
|
|
430
427
|
}
|
|
431
428
|
if (key === '$text') {
|
|
@@ -479,7 +476,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
479
476
|
const childOperand = items.length > 1 || negate || opts.operand;
|
|
480
477
|
const parts = this.renderOperands(ctx, items, (fragmentCtx, entry) => {
|
|
481
478
|
if (entry instanceof QueryRaw) {
|
|
482
|
-
this.getRawValue(fragmentCtx, { value: entry });
|
|
479
|
+
this.getRawValue(fragmentCtx, { value: entry, prefix: opts.prefix });
|
|
483
480
|
}
|
|
484
481
|
else {
|
|
485
482
|
this.renderWhere(fragmentCtx, entity, entry, { prefix: opts.prefix, operand: childOperand, clause: false });
|
|
@@ -551,7 +548,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
551
548
|
}
|
|
552
549
|
const fold = like.insensitive && this.caseInsensitiveMatch === 'fold';
|
|
553
550
|
const value = String(val);
|
|
554
|
-
const ph = this.addValue(ctx
|
|
551
|
+
const ph = this.addValue(ctx, like.pattern(fold ? value.toLowerCase() : value));
|
|
555
552
|
const matchOp = like.insensitive && this.caseInsensitiveMatch === 'ilike' ? 'ILIKE' : this.likeFn;
|
|
556
553
|
return `${fold ? `LOWER(${operand})` : operand} ${matchOp} ${ph}`;
|
|
557
554
|
}
|
|
@@ -567,7 +564,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
567
564
|
resolveOperandField(ctx, entity, key, opts) {
|
|
568
565
|
const meta = getMeta(entity);
|
|
569
566
|
const field = meta.fields[key];
|
|
570
|
-
return (this.inlinedOperand(ctx, field, opts.prefix ?? this.resolveTableAlias(meta)) ??
|
|
567
|
+
return (this.inlinedOperand(ctx, field, opts.prefix ?? this.resolveTableAlias(meta), entity) ??
|
|
571
568
|
this.columnWithPrefix(key, field, opts.prefix));
|
|
572
569
|
}
|
|
573
570
|
/**
|
|
@@ -576,15 +573,9 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
576
573
|
* Every clause that names such a field needs the expression itself, never the output alias: an
|
|
577
574
|
* alias exists only when the field was also selected, which `$where` and `$sort` cannot assume.
|
|
578
575
|
*/
|
|
579
|
-
inlinedOperand(ctx, field, prefix) {
|
|
576
|
+
inlinedOperand(ctx, field, prefix, entity) {
|
|
580
577
|
const inlined = field && isInlinedExpression(field) ? field.computed : undefined;
|
|
581
|
-
return inlined
|
|
582
|
-
? this.buildFragment(ctx, (fragmentCtx) => this.getRawValue(fragmentCtx, {
|
|
583
|
-
value: inlined,
|
|
584
|
-
prefix,
|
|
585
|
-
escapedPrefix: this.escapeId(prefix, true, true),
|
|
586
|
-
}))
|
|
587
|
-
: undefined;
|
|
578
|
+
return inlined ? this.rawFragment(ctx, inlined, prefix, entity) : undefined;
|
|
588
579
|
}
|
|
589
580
|
compareFieldOperator(ctx, entity, key, op, val, opts = {}) {
|
|
590
581
|
const field = this.resolveOperandField(ctx, entity, key, opts);
|
|
@@ -629,7 +620,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
629
620
|
operatorCondition(ctx, operand, op, val) {
|
|
630
621
|
const compareOp = AbstractSqlDialect.COMPARE_OP_MAP.get(op);
|
|
631
622
|
if (compareOp) {
|
|
632
|
-
return `${operand}${compareOp}${this.addValue(ctx
|
|
623
|
+
return `${operand}${compareOp}${this.addValue(ctx, val)}`;
|
|
633
624
|
}
|
|
634
625
|
const like = this.likeCondition(ctx, operand, op, val);
|
|
635
626
|
if (like) {
|
|
@@ -637,17 +628,17 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
637
628
|
}
|
|
638
629
|
switch (op) {
|
|
639
630
|
case '$eq':
|
|
640
|
-
return val === null ? `${operand} IS NULL` : `${operand} = ${this.addValue(ctx
|
|
631
|
+
return val === null ? `${operand} IS NULL` : `${operand} = ${this.addValue(ctx, val)}`;
|
|
641
632
|
case '$ne':
|
|
642
|
-
return val === null ? `${operand} IS NOT NULL` : this.neExpr(operand, this.addValue(ctx
|
|
633
|
+
return val === null ? `${operand} IS NOT NULL` : this.neExpr(operand, this.addValue(ctx, val));
|
|
643
634
|
case '$regex':
|
|
644
|
-
return this.regexCondition(operand, this.addValue(ctx
|
|
635
|
+
return this.regexCondition(operand, this.addValue(ctx, val));
|
|
645
636
|
case '$in':
|
|
646
637
|
case '$nin':
|
|
647
638
|
return operand + this.formatIn(ctx, inOperands(op, val), op === '$nin');
|
|
648
639
|
case '$between': {
|
|
649
640
|
const [min, max] = val;
|
|
650
|
-
return `${operand} BETWEEN ${this.addValue(ctx
|
|
641
|
+
return `${operand} BETWEEN ${this.addValue(ctx, min)} AND ${this.addValue(ctx, max)}`;
|
|
651
642
|
}
|
|
652
643
|
case '$isNull':
|
|
653
644
|
return operand + (val ? ' IS NULL' : ' IS NOT NULL');
|
|
@@ -685,7 +676,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
685
676
|
// operator out of the same table a comparison against a column does.
|
|
686
677
|
const compareOp = AbstractSqlDialect.COMPARE_OP_MAP.get(op);
|
|
687
678
|
if (compareOp) {
|
|
688
|
-
return `${fieldAccessor(jsonPath, 'numeric')}${compareOp}${this.addValue(ctx
|
|
679
|
+
return `${fieldAccessor(jsonPath, 'numeric')}${compareOp}${this.addValue(ctx, value)}`;
|
|
689
680
|
}
|
|
690
681
|
switch (op) {
|
|
691
682
|
case '$eq':
|
|
@@ -697,7 +688,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
697
688
|
return `${jsonField} IS NOT NULL`;
|
|
698
689
|
return this.neExpr(comparand(value), this.jsonOperand(ctx, value, asJson));
|
|
699
690
|
case '$regex':
|
|
700
|
-
return this.regexCondition(jsonField, this.addValue(ctx
|
|
691
|
+
return this.regexCondition(jsonField, this.addValue(ctx, value));
|
|
701
692
|
case '$in':
|
|
702
693
|
case '$nin':
|
|
703
694
|
return this.jsonInNin(ctx, jsonField, comparand, op, value, asJson);
|
|
@@ -723,7 +714,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
723
714
|
}
|
|
724
715
|
/** The bound operand of a JSON comparison: JSON-encoded when comparing against the JSON value. */
|
|
725
716
|
jsonOperand(ctx, value, asJson) {
|
|
726
|
-
return asJson ? this.jsonScalarParam(ctx, value) : this.addValue(ctx
|
|
717
|
+
return asJson ? this.jsonScalarParam(ctx, value) : this.addValue(ctx, value);
|
|
727
718
|
}
|
|
728
719
|
/**
|
|
729
720
|
* Whether the dialect's array containment ({@link jsonAll}) matches an object element that merely
|
|
@@ -790,9 +781,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
790
781
|
if (value instanceof QueryRaw) {
|
|
791
782
|
return this.rawFragment(ctx, value);
|
|
792
783
|
}
|
|
793
|
-
|
|
794
|
-
// The placeholder for the value just pushed, so a named or numbered one is spelled correctly.
|
|
795
|
-
return this.jsonCast(this.placeholder(ctx.values.length));
|
|
784
|
+
return this.jsonCast(this.addValue(ctx, JSON.stringify(value)));
|
|
796
785
|
}
|
|
797
786
|
/** {@link resolveOperandField}, appended. */
|
|
798
787
|
getComparisonKey(ctx, entity, key, opts = {}) {
|
|
@@ -886,7 +875,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
886
875
|
sortColumn(ctx, meta, key, prefix) {
|
|
887
876
|
const field = meta.fields[key];
|
|
888
877
|
if (field) {
|
|
889
|
-
const expr = this.inlinedOperand(ctx, field, prefix ?? this.resolveTableAlias(meta)) ??
|
|
878
|
+
const expr = this.inlinedOperand(ctx, field, prefix ?? this.resolveTableAlias(meta), meta.entity) ??
|
|
890
879
|
this.columnWithPrefix(key, field, prefix);
|
|
891
880
|
return { expr, output: false };
|
|
892
881
|
}
|
|
@@ -1210,7 +1199,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1210
1199
|
if (value === undefined) {
|
|
1211
1200
|
this.appendDefaultInsertValue(ctx, fields[i]);
|
|
1212
1201
|
}
|
|
1213
|
-
else if (kinds[i] === 'plain'
|
|
1202
|
+
else if (kinds[i] === 'plain') {
|
|
1214
1203
|
// The overwhelmingly common case in a bulk insert, so it binds without a dispatch.
|
|
1215
1204
|
ctx.addValue(value);
|
|
1216
1205
|
}
|
|
@@ -1531,6 +1520,22 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1531
1520
|
jsonPull(ctx, expr, escapedCol, pull) {
|
|
1532
1521
|
return Object.entries(pull).reduce((acc, [key, value]) => this.jsonPullKey(ctx, acc, escapedCol, key, value), expr);
|
|
1533
1522
|
}
|
|
1523
|
+
compileDdl(sql, entity) {
|
|
1524
|
+
const ctx = this.createContext({ inlineValues: true });
|
|
1525
|
+
if (sql instanceof QueryRaw) {
|
|
1526
|
+
sql.render({ ctx, dialect: this, prefix: '', escapedPrefix: '', entity });
|
|
1527
|
+
}
|
|
1528
|
+
else if (entity) {
|
|
1529
|
+
this.renderWhere(ctx, entity, sql, { clause: false });
|
|
1530
|
+
}
|
|
1531
|
+
else {
|
|
1532
|
+
throw new TypeError('a predicate compiles against the entity it is written for, and none was given');
|
|
1533
|
+
}
|
|
1534
|
+
if (ctx.values.length) {
|
|
1535
|
+
throw new TypeError(`DDL has no placeholder to bind a value into, and this SQL left one bound: ${ctx.sql}`);
|
|
1536
|
+
}
|
|
1537
|
+
return ctx.sql;
|
|
1538
|
+
}
|
|
1534
1539
|
getRawValue(ctx, opts) {
|
|
1535
1540
|
const { value, prefix = '', escapedPrefix } = opts;
|
|
1536
1541
|
value.render({
|
|
@@ -1540,10 +1545,6 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1540
1545
|
prefix,
|
|
1541
1546
|
escapedPrefix: escapedPrefix ?? this.escapeId(prefix, true, true),
|
|
1542
1547
|
});
|
|
1543
|
-
const alias = value[RAW_ALIAS];
|
|
1544
|
-
if (alias) {
|
|
1545
|
-
ctx.append(' ' + this.escapeId(alias, true));
|
|
1546
|
-
}
|
|
1547
1548
|
}
|
|
1548
1549
|
/**
|
|
1549
1550
|
* Resolves a dot-notation key to its JSON field metadata.
|
|
@@ -1917,7 +1918,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1917
1918
|
// A COUNT is never NULL, so equality stays plain here instead of taking the shared renderer's
|
|
1918
1919
|
// null-safe `$ne` (`IS DISTINCT FROM` on Postgres, `IS NOT` on SQLite). Same rows, shorter SQL.
|
|
1919
1920
|
if (op === '$eq' || op === '$ne') {
|
|
1920
|
-
ctx.append(` ${op === '$eq' ? '=' : '<>'} ${this.addValue(ctx
|
|
1921
|
+
ctx.append(` ${op === '$eq' ? '=' : '<>'} ${this.addValue(ctx, val)}`);
|
|
1921
1922
|
return;
|
|
1922
1923
|
}
|
|
1923
1924
|
this.appendOperatorCondition(ctx, '', op, val);
|
|
@@ -1958,7 +1959,7 @@ export class AbstractSqlDialect extends VectorSqlDialect {
|
|
|
1958
1959
|
formatIn(ctx, values, negate) {
|
|
1959
1960
|
if (values.length === 0)
|
|
1960
1961
|
return negate ? ' NOT IN (NULL)' : ' IN (NULL)';
|
|
1961
|
-
const phs = values.map((v) => this.addValue(ctx
|
|
1962
|
+
const phs = values.map((v) => this.addValue(ctx, v)).join(', ');
|
|
1962
1963
|
return ` ${negate ? 'NOT IN' : 'IN'} (${phs})`;
|
|
1963
1964
|
}
|
|
1964
1965
|
toString() {
|
|
@@ -247,7 +247,7 @@ export class MysqlLikeSqlDialect extends AbstractSqlDialect {
|
|
|
247
247
|
return `${escapedColumn}->${jsonPath(jsonPathStr)}`;
|
|
248
248
|
}
|
|
249
249
|
jsonAll(ctx, jsonField, value) {
|
|
250
|
-
return `JSON_CONTAINS(${jsonField}, ${this.addValue(ctx
|
|
250
|
+
return `JSON_CONTAINS(${jsonField}, ${this.addValue(ctx, JSON.stringify(value))})`;
|
|
251
251
|
}
|
|
252
252
|
jsonSize(ctx, jsonField, value) {
|
|
253
253
|
return this.buildFragment(ctx, (fragmentCtx) => this.buildSizeComparison(fragmentCtx, () => fragmentCtx.append(`JSON_LENGTH(${jsonField})`), value));
|
|
@@ -80,6 +80,7 @@ export declare abstract class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
80
80
|
protected get regexpOp(): string;
|
|
81
81
|
protected readonly caseInsensitiveMatch = "ilike";
|
|
82
82
|
protected get neOp(): string;
|
|
83
|
+
/** One array parameter, which a context that inlines values has none of: it lists them instead. */
|
|
83
84
|
protected formatIn(ctx: QueryContext, values: unknown[], negate: boolean): string;
|
|
84
85
|
protected numericCast(expr: string): string;
|
|
85
86
|
protected appendJsonValue(ctx: QueryContext, value: unknown, type: JsonColumnType): void;
|
|
@@ -126,7 +126,7 @@ export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
126
126
|
.map((key) => this.escapeId(this.resolveColumnName(key, meta.fields[key])))
|
|
127
127
|
.join(` || ' ' || `);
|
|
128
128
|
// The config is bound once and its numbered placeholder reused by both calls.
|
|
129
|
-
const config = search.$config ? `${this.addValue(ctx
|
|
129
|
+
const config = search.$config ? `${this.addValue(ctx, search.$config)}::regconfig, ` : '';
|
|
130
130
|
ctx.append(`TO_TSVECTOR(${config}${fields}) @@ WEBSEARCH_TO_TSQUERY(${config}`);
|
|
131
131
|
ctx.addValue(search.$value);
|
|
132
132
|
ctx.append(')');
|
|
@@ -158,10 +158,11 @@ export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
158
158
|
get neOp() {
|
|
159
159
|
return 'IS DISTINCT FROM';
|
|
160
160
|
}
|
|
161
|
+
/** One array parameter, which a context that inlines values has none of: it lists them instead. */
|
|
161
162
|
formatIn(ctx, values, negate) {
|
|
162
|
-
if (values.length === 0)
|
|
163
|
-
return
|
|
164
|
-
const ph = this.addValue(ctx
|
|
163
|
+
if (values.length === 0 || ctx.inlineValues)
|
|
164
|
+
return super.formatIn(ctx, values, negate);
|
|
165
|
+
const ph = this.addValue(ctx, values);
|
|
165
166
|
return negate ? ` <> ALL(${ph})` : ` = ANY(${ph})`;
|
|
166
167
|
}
|
|
167
168
|
numericCast(expr) {
|
|
@@ -210,7 +211,7 @@ export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
210
211
|
}, expr);
|
|
211
212
|
}
|
|
212
213
|
jsonUnset(ctx, expr, unset) {
|
|
213
|
-
return `(${expr}) - ${this.addValue(ctx
|
|
214
|
+
return `(${expr}) - ${this.addValue(ctx, [...unset])}::text[]`;
|
|
214
215
|
}
|
|
215
216
|
/** Postgres binds JSON with a numbered placeholder and an explicit cast, per driver capability. */
|
|
216
217
|
jsonScalarParam(ctx, value) {
|
|
@@ -223,9 +224,9 @@ export class PgLikeSqlDialect extends AbstractSqlDialect {
|
|
|
223
224
|
if (value instanceof QueryRaw)
|
|
224
225
|
return this.rawFragment(ctx, value);
|
|
225
226
|
if (value == null)
|
|
226
|
-
return `${this.addValue(ctx
|
|
227
|
+
return `${this.addValue(ctx, null)}::${type}`;
|
|
227
228
|
const json = JSON.stringify(value);
|
|
228
|
-
const ph = this.addValue(ctx
|
|
229
|
+
const ph = this.addValue(ctx, json);
|
|
229
230
|
return this.features.explicitJsonCast ? `(${ph}::text)::${type}` : `${ph}::${type}`;
|
|
230
231
|
}
|
|
231
232
|
}
|
|
@@ -9,6 +9,7 @@ import type { QueryContext, QueryDialect } from '../type/index.js';
|
|
|
9
9
|
export declare class SqlQueryContext implements QueryContext {
|
|
10
10
|
readonly dialect: QueryDialect;
|
|
11
11
|
private readonly statement?;
|
|
12
|
+
readonly inlineValues: boolean;
|
|
12
13
|
private readonly sqlChunks;
|
|
13
14
|
private readonly params;
|
|
14
15
|
private readonly tableAliases;
|
|
@@ -20,8 +21,9 @@ export declare class SqlQueryContext implements QueryContext {
|
|
|
20
21
|
* than needing to be reconciled after the fact.
|
|
21
22
|
* @param statement The context this one renders a fragment of, which owns the claimed aliases: a
|
|
22
23
|
* fragment is part of one statement, so its aliases have to be unique across the whole of it.
|
|
24
|
+
* @param inlineValues See {@link QueryContext.inlineValues}; a fragment takes its statement's.
|
|
23
25
|
*/
|
|
24
|
-
constructor(dialect: QueryDialect, params?: unknown[], statement?: SqlQueryContext | undefined);
|
|
26
|
+
constructor(dialect: QueryDialect, params?: unknown[], statement?: SqlQueryContext | undefined, inlineValues?: boolean);
|
|
25
27
|
createFragment(): QueryContext;
|
|
26
28
|
/**
|
|
27
29
|
* Appends raw SQL string fragments to the query.
|
|
@@ -31,11 +33,8 @@ export declare class SqlQueryContext implements QueryContext {
|
|
|
31
33
|
*/
|
|
32
34
|
append(sql: string): this;
|
|
33
35
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* @param value The value to be parameterized.
|
|
38
|
-
* @returns The current context instance for method chaining.
|
|
36
|
+
* Appends the SQL the dialect writes for `value`: a placeholder for the value bound, or its literal
|
|
37
|
+
* where this context inlines values.
|
|
39
38
|
*/
|
|
40
39
|
addValue(value: unknown): this;
|
|
41
40
|
/**
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
export class SqlQueryContext {
|
|
9
9
|
dialect;
|
|
10
10
|
statement;
|
|
11
|
+
inlineValues;
|
|
11
12
|
sqlChunks = [];
|
|
12
13
|
params;
|
|
13
14
|
tableAliases = new Set();
|
|
@@ -19,14 +20,16 @@ export class SqlQueryContext {
|
|
|
19
20
|
* than needing to be reconciled after the fact.
|
|
20
21
|
* @param statement The context this one renders a fragment of, which owns the claimed aliases: a
|
|
21
22
|
* fragment is part of one statement, so its aliases have to be unique across the whole of it.
|
|
23
|
+
* @param inlineValues See {@link QueryContext.inlineValues}; a fragment takes its statement's.
|
|
22
24
|
*/
|
|
23
|
-
constructor(dialect, params = [], statement) {
|
|
25
|
+
constructor(dialect, params = [], statement, inlineValues = false) {
|
|
24
26
|
this.dialect = dialect;
|
|
25
27
|
this.statement = statement;
|
|
28
|
+
this.inlineValues = inlineValues;
|
|
26
29
|
this.params = params;
|
|
27
30
|
}
|
|
28
31
|
createFragment() {
|
|
29
|
-
return new SqlQueryContext(this.dialect, this.params, this.statement ?? this);
|
|
32
|
+
return new SqlQueryContext(this.dialect, this.params, this.statement ?? this, this.inlineValues);
|
|
30
33
|
}
|
|
31
34
|
/**
|
|
32
35
|
* Appends raw SQL string fragments to the query.
|
|
@@ -41,14 +44,11 @@ export class SqlQueryContext {
|
|
|
41
44
|
return this;
|
|
42
45
|
}
|
|
43
46
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* @param value The value to be parameterized.
|
|
48
|
-
* @returns The current context instance for method chaining.
|
|
47
|
+
* Appends the SQL the dialect writes for `value`: a placeholder for the value bound, or its literal
|
|
48
|
+
* where this context inlines values.
|
|
49
49
|
*/
|
|
50
50
|
addValue(value) {
|
|
51
|
-
this.sqlChunks.push(this.dialect.addValue(this
|
|
51
|
+
this.sqlChunks.push(this.dialect.addValue(this, value));
|
|
52
52
|
return this;
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EntityIndexOptions, EntityOptions,
|
|
1
|
+
import type { EntityIndexColumnInput, EntityIndexOptions, EntityOptions, FilterOptions, RefMap, Type } from '../../type/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Marks a class as an entity and finalizes its metadata.
|
|
4
4
|
*
|
|
@@ -12,16 +12,12 @@ export declare function Entity<E>(opts?: EntityOptions<E>): (entity: Type<E>, co
|
|
|
12
12
|
/**
|
|
13
13
|
* Registers a named `$where` filter, applied to every query unless bypassed via `QueryOptions.filters`.
|
|
14
14
|
*
|
|
15
|
-
* @example `@Filter('active', {
|
|
15
|
+
* @example `@Filter('active', { where: { status: 'active' }, default: false })`
|
|
16
16
|
*/
|
|
17
17
|
export declare function Filter<E>(name: string, opts: FilterOptions<E>): (entity: Type<E>) => void;
|
|
18
18
|
/**
|
|
19
|
-
* Declares a composite index, its columns read off the
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @example `@Index((user) => [user.lastName, user.firstName], { name: 'users_fullname_idx' })`
|
|
24
|
-
* @example `@Index((user) => [user.email], { unique: true })`
|
|
25
|
-
* @example `@Index((user) => [user.status], { where: "status = 'active'" })`
|
|
19
|
+
* Declares a composite index, its columns read off the entity's refs, so `@Index((user) => [user.nope])`
|
|
20
|
+
* does not compile and a rename reaches every column. Stacks, so several may sit above one class.
|
|
21
|
+
* @example `@Index((user) => [user.lastName, raw`lower(${user.email})`], { unique: true })`
|
|
26
22
|
*/
|
|
27
|
-
export declare function Index<E>(columns: (
|
|
23
|
+
export declare function Index<E>(columns: (refs: RefMap<E>) => readonly EntityIndexColumnInput<E>[], options?: EntityIndexOptions<E>): (entity: Type<E>) => void;
|
|
@@ -20,7 +20,7 @@ export function Entity(opts) {
|
|
|
20
20
|
/**
|
|
21
21
|
* Registers a named `$where` filter, applied to every query unless bypassed via `QueryOptions.filters`.
|
|
22
22
|
*
|
|
23
|
-
* @example `@Filter('active', {
|
|
23
|
+
* @example `@Filter('active', { where: { status: 'active' }, default: false })`
|
|
24
24
|
*/
|
|
25
25
|
export function Filter(name, opts) {
|
|
26
26
|
return (entity) => {
|
|
@@ -28,13 +28,9 @@ export function Filter(name, opts) {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Declares a composite index, its columns read off the
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* @example `@Index((user) => [user.lastName, user.firstName], { name: 'users_fullname_idx' })`
|
|
36
|
-
* @example `@Index((user) => [user.email], { unique: true })`
|
|
37
|
-
* @example `@Index((user) => [user.status], { where: "status = 'active'" })`
|
|
31
|
+
* Declares a composite index, its columns read off the entity's refs, so `@Index((user) => [user.nope])`
|
|
32
|
+
* does not compile and a rename reaches every column. Stacks, so several may sit above one class.
|
|
33
|
+
* @example `@Index((user) => [user.lastName, raw`lower(${user.email})`], { unique: true })`
|
|
38
34
|
*/
|
|
39
35
|
export function Index(columns, options = {}) {
|
|
40
36
|
return (entity) => {
|
|
@@ -40,12 +40,13 @@ type EnumValue<Members, Declared> = Declared extends Members ? {
|
|
|
40
40
|
*
|
|
41
41
|
* @example `@Field({ type: String }) name?: string;`
|
|
42
42
|
* @example `@Field({ references: () => User }) userId?: string;` (where `User.id` is a `uuid`)
|
|
43
|
+
* @example `@Field({ type: Number, computed: (line) => raw`${line.qty} * ${line.price}` }) total?: number;`
|
|
43
44
|
*/
|
|
44
|
-
export declare function Field<O extends FieldOptions<DeclaredValue<O
|
|
45
|
+
export declare function Field<This, O extends FieldOptions<DeclaredValue<O>, This> & ({
|
|
45
46
|
type: FieldType;
|
|
46
47
|
} | {
|
|
47
48
|
references: EntityGetter;
|
|
48
|
-
}) & RejectUnknown<O, FieldOptions> & RejectIncompatible<O>>(opts: O): MemberDecorator<DeclaredValue<O> | undefined>;
|
|
49
|
+
}) & RejectUnknown<O, FieldOptions> & RejectIncompatible<O>>(opts: O): MemberDecorator<DeclaredValue<O> | undefined, This>;
|
|
49
50
|
/**
|
|
50
51
|
* A key the type level cannot name, reported on each `@Id` that leaves it unnamed. Where no `idKey`
|
|
51
52
|
* brand and no conventional name applies, `IdKey` falls back to every field, and `IdValue`,
|
|
@@ -8,6 +8,7 @@ import { memberRegistrations } from './bag.js';
|
|
|
8
8
|
*
|
|
9
9
|
* @example `@Field({ type: String }) name?: string;`
|
|
10
10
|
* @example `@Field({ references: () => User }) userId?: string;` (where `User.id` is a `uuid`)
|
|
11
|
+
* @example `@Field({ type: Number, computed: (line) => raw`${line.qty} * ${line.price}` }) total?: number;`
|
|
11
12
|
*/
|
|
12
13
|
export function Field(opts) {
|
|
13
14
|
return (_value, context) => {
|
|
@@ -11,8 +11,8 @@ export declare function defineRelation<E, T extends object>(entity: Type<E>, key
|
|
|
11
11
|
export declare function relationRegistration<T extends object, O>({ mappedBy, references, ...opts }: RelationOptions<T, O>): RelationRegistration;
|
|
12
12
|
export declare function defineHook<E>(entity: Type<E>, methodName: string, event: HookEvent): EntityMeta<E>;
|
|
13
13
|
/**
|
|
14
|
-
* Declares a composite index, its columns read off the
|
|
15
|
-
* are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
|
|
14
|
+
* Declares a composite index, its columns read off the entity's refs. `unique` and the authored column
|
|
15
|
+
* sugar are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
|
|
16
16
|
*/
|
|
17
17
|
export declare function defineIndex<E>(entity: Type<E>, index: EntityIndexInput<E>): EntityMeta<E>;
|
|
18
18
|
export declare function defineFilter<E>(entity: Type<E>, name: string, opts: FilterOptions<E>): EntityMeta<E>;
|