typeorm-extensions 2.1.0 → 2.2.0-rc.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/LICENSE +21 -0
- package/README.md +6 -3
- package/dist/decorators/calculated-column.decorator.d.ts +30 -0
- package/dist/decorators/calculated-column.decorator.js +82 -0
- package/dist/decorators/index.d.ts +1 -0
- package/dist/decorators/index.js +17 -0
- package/dist/extensions/calculated-column.extension.d.ts +33 -0
- package/dist/extensions/calculated-column.extension.js +33 -0
- package/dist/extensions/cursor-pagination.extension.d.ts +2 -1
- package/dist/extensions/cursor-pagination.extension.js +4 -3
- package/dist/extensions/get-many-with-totals.extension.d.ts +9 -1
- package/dist/extensions/get-many-with-totals.extension.js +159 -10
- package/dist/extensions/index.d.ts +7 -0
- package/dist/extensions/index.js +7 -0
- package/dist/extensions/join-lateral.extension.d.ts +19 -0
- package/dist/extensions/join-lateral.extension.js +50 -0
- package/dist/extensions/join-unnest.extension.d.ts +19 -0
- package/dist/extensions/join-unnest.extension.js +40 -0
- package/dist/extensions/order.extension.js +18 -7
- package/dist/extensions/query-returning.extension.d.ts +29 -0
- package/dist/extensions/query-returning.extension.js +50 -0
- package/dist/extensions/typed/index.d.ts +3 -0
- package/dist/extensions/typed/index.js +3 -2
- package/dist/extensions/typed/typed-distinct/typed-distinct.extension.d.ts +3 -2
- package/dist/extensions/typed/typed-group-by/typed-group-by.extension.d.ts +24 -0
- package/dist/extensions/typed/typed-group-by/typed-group-by.extension.js +31 -0
- package/dist/extensions/typed/typed-having/typed-having.extension.d.ts +36 -0
- package/dist/extensions/typed/typed-having/typed-having.extension.js +42 -0
- package/dist/extensions/typed/typed-joins/typed-joins.extension.d.ts +5 -4
- package/dist/extensions/typed/typed-order-by/typed-order-by-array-position.extension.d.ts +3 -2
- package/dist/extensions/typed/typed-order-by/typed-order-by-array-position.extension.js +10 -2
- package/dist/extensions/typed/typed-order-by/typed-order-by.extension.d.ts +3 -2
- package/dist/extensions/typed/typed-order-by/typed-order-by.extension.js +3 -2
- package/dist/extensions/typed/typed-root.extension.d.ts +25 -0
- package/dist/extensions/typed/typed-root.extension.js +13 -0
- package/dist/extensions/typed/typed-select/typed-select.extension.d.ts +5 -4
- package/dist/extensions/typed/typed-select/typed-select.extension.js +3 -2
- package/dist/extensions/typed/typed-where/typed-period-filter.extension.d.ts +2 -1
- package/dist/extensions/typed/typed-where/typed-where-array.extension.d.ts +10 -9
- package/dist/extensions/typed/typed-where/typed-where-array.extension.js +32 -0
- package/dist/extensions/typed/typed-where/typed-where-ilike.extension.d.ts +7 -6
- package/dist/extensions/typed/typed-where/typed-where-is-any.extension.d.ts +7 -6
- package/dist/extensions/typed/typed-where/typed-where-is-distinct-from.extension.d.ts +7 -6
- package/dist/extensions/typed/typed-where/typed-where-is-in.extension.d.ts +7 -6
- package/dist/extensions/typed/typed-where/typed-where-json.extension.d.ts +7 -6
- package/dist/extensions/typed/typed-where/typed-where-lower.extension.d.ts +7 -6
- package/dist/extensions/typed/typed-where/typed-where-similar.extension.d.ts +5 -4
- package/dist/extensions/typed/typed-where/typed-where.extension.d.ts +4 -3
- package/dist/extensions/union.extension.d.ts +22 -0
- package/dist/extensions/union.extension.js +52 -0
- package/dist/extensions/where-exists.extension.d.ts +50 -0
- package/dist/extensions/where-exists.extension.js +64 -0
- package/dist/extensions/where-relation-exists.extension.d.ts +38 -0
- package/dist/extensions/where-relation-exists.extension.js +95 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/types/extensions/cursor-pagination.types.d.ts +5 -0
- package/dist/types/extensions/get-many-with-totals.types.d.ts +19 -0
- package/dist/types/extensions/index.d.ts +5 -0
- package/dist/types/extensions/index.js +5 -0
- package/dist/types/extensions/join-lateral.types.d.ts +6 -0
- package/dist/types/extensions/join-lateral.types.js +2 -0
- package/dist/types/extensions/period.types.d.ts +8 -0
- package/dist/types/extensions/query-returning.types.d.ts +11 -0
- package/dist/types/extensions/query-returning.types.js +2 -0
- package/dist/types/extensions/typed-group-by.types.d.ts +8 -0
- package/dist/types/extensions/typed-group-by.types.js +2 -0
- package/dist/types/extensions/typed-having.types.d.ts +2 -0
- package/dist/types/extensions/typed-having.types.js +2 -0
- package/dist/types/extensions/union.types.d.ts +12 -0
- package/dist/types/extensions/union.types.js +2 -0
- package/dist/types/extensions/where.types.d.ts +1 -0
- package/dist/types/modules/typed-root.types.d.ts +17 -0
- package/dist/types/modules/typed-root.types.js +2 -0
- package/dist/utils/calculated-column.utils.d.ts +21 -0
- package/dist/utils/calculated-column.utils.js +63 -0
- package/dist/utils/parameter.utils.d.ts +7 -0
- package/dist/utils/parameter.utils.js +21 -0
- package/dist/utils/period.utils.js +7 -2
- package/dist/utils/prototype.utils.d.ts +5 -1
- package/dist/utils/prototype.utils.js +4 -1
- package/dist/utils/proxy-key.utils.d.ts +3 -3
- package/dist/utils/proxy-key.utils.js +7 -7
- package/dist/utils/query-builder.utils.d.ts +8 -0
- package/dist/utils/query-builder.utils.js +30 -2
- package/dist/utils/table.utils.d.ts +112 -2
- package/dist/utils/table.utils.js +206 -11
- package/dist/utils/time-zone.utils.d.ts +8 -0
- package/dist/utils/time-zone.utils.js +102 -0
- package/dist/utils/where.utils.d.ts +2 -2
- package/dist/utils/where.utils.js +23 -2
- package/package.json +3 -3
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.attachExists = void 0;
|
|
4
|
+
const typeorm_1 = require("typeorm");
|
|
5
|
+
const SoftDeleteQueryBuilder_1 = require("typeorm/query-builder/SoftDeleteQueryBuilder");
|
|
6
|
+
const prototype_utils_1 = require("../utils/prototype.utils");
|
|
7
|
+
const parameter_utils_1 = require("../utils/parameter.utils");
|
|
8
|
+
const existsMethods = {
|
|
9
|
+
prototype: {
|
|
10
|
+
whereExists(subQuery) {
|
|
11
|
+
return attachExists(this, 'where', subQuery, false);
|
|
12
|
+
},
|
|
13
|
+
andWhereExists(subQuery) {
|
|
14
|
+
return attachExists(this, 'andWhere', subQuery, false);
|
|
15
|
+
},
|
|
16
|
+
orWhereExists(subQuery) {
|
|
17
|
+
return attachExists(this, 'orWhere', subQuery, false);
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
const notExistsMethods = {
|
|
22
|
+
prototype: {
|
|
23
|
+
whereNotExists(subQuery) {
|
|
24
|
+
return attachExists(this, 'where', subQuery, true);
|
|
25
|
+
},
|
|
26
|
+
andWhereNotExists(subQuery) {
|
|
27
|
+
return attachExists(this, 'andWhere', subQuery, true);
|
|
28
|
+
},
|
|
29
|
+
orWhereNotExists(subQuery) {
|
|
30
|
+
return attachExists(this, 'orWhere', subQuery, true);
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
// only where the builder lacks them: SelectQueryBuilder keeps TypeORM's own whereExists /
|
|
35
|
+
// andWhereExists / orWhereExists, and a later TypeORM that adds any of these keeps its own
|
|
36
|
+
[typeorm_1.SelectQueryBuilder, typeorm_1.UpdateQueryBuilder, typeorm_1.DeleteQueryBuilder, SoftDeleteQueryBuilder_1.SoftDeleteQueryBuilder].forEach((builder) => {
|
|
37
|
+
(0, prototype_utils_1.patchPrototype)(builder, existsMethods, { onlyMissing: true });
|
|
38
|
+
(0, prototype_utils_1.patchPrototype)(builder, notExistsMethods, { onlyMissing: true });
|
|
39
|
+
});
|
|
40
|
+
// implementation
|
|
41
|
+
function attachExists(builder, method, subQuery, negate) {
|
|
42
|
+
const [condition, parameters] = (0, parameter_utils_1.withUniqueParameterNames)(...getExistsCondition(subQuery));
|
|
43
|
+
return builder[method](negate ? `NOT ${condition}` : condition, parameters);
|
|
44
|
+
}
|
|
45
|
+
exports.attachExists = attachExists;
|
|
46
|
+
/**
|
|
47
|
+
* TypeORM's EXISTS condition: the subquery selects 1, without ORDER BY, LIMIT and OFFSET. TypeORM also
|
|
48
|
+
* drops GROUP BY, which leaves a HAVING to aggregate the whole subquery: the GROUP BY stays with one.
|
|
49
|
+
*/
|
|
50
|
+
function getExistsCondition(subQuery) {
|
|
51
|
+
const query = subQuery
|
|
52
|
+
.clone()
|
|
53
|
+
.orderBy()
|
|
54
|
+
.offset(undefined)
|
|
55
|
+
.limit(undefined)
|
|
56
|
+
.skip(undefined)
|
|
57
|
+
.take(undefined)
|
|
58
|
+
.select('1')
|
|
59
|
+
.setOption('disable-global-order');
|
|
60
|
+
if (query.expressionMap.havings.length === 0) {
|
|
61
|
+
query.groupBy();
|
|
62
|
+
}
|
|
63
|
+
return [`EXISTS (${query.getQuery()})`, query.getParameters()];
|
|
64
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
|
2
|
+
import type { DeepUnwrapArray, KeyPathEnd } from '../types/modules/proxy-callback.types';
|
|
3
|
+
import type { TypedRoot } from '../types/modules/typed-root.types';
|
|
4
|
+
/**
|
|
5
|
+
* The relation to look in, selected by a typed callback: `user => user.images`. A relation of a joined alias
|
|
6
|
+
* (`joins => joins.owner.images`) ends the key path, so its entity type isn't known: pass it as `Related`.
|
|
7
|
+
*/
|
|
8
|
+
type RelationSelection<Type, Related> = (proxy: DeepUnwrapArray<Type>) => Related | KeyPathEnd | null | undefined;
|
|
9
|
+
/** Narrows the rows of the related entity: `images => images.andWhere('images.url IS NOT NULL')`. */
|
|
10
|
+
type RelatedCondition<Related extends ObjectLiteral> = (subQuery: SelectQueryBuilder<Related>) => unknown;
|
|
11
|
+
/**
|
|
12
|
+
* `EXISTS` / `NOT EXISTS` over a relation of an entity, with the join condition taken from the relation's
|
|
13
|
+
* metadata: `andWhereRelationExists(user => user.images, 'image', (images) => images.andWhere(…))` gives
|
|
14
|
+
* `EXISTS (SELECT 1 FROM "images" "image" WHERE … AND "image"."userId" = "user"."id")`. Works for
|
|
15
|
+
* one-to-many, many-to-one, one-to-one and many-to-many (through the junction table) relations.
|
|
16
|
+
*
|
|
17
|
+
* `alias` names the related entity in the subquery and must not be an alias of the outer query.
|
|
18
|
+
* The subquery's parameters get unique names, as in `whereNotExists`.
|
|
19
|
+
*/
|
|
20
|
+
export interface WhereRelationExistsMethods<Entity extends ObjectLiteral> {
|
|
21
|
+
/** Sets `WHERE EXISTS (…)` over the relation, replacing the WHERE conditions set before. */
|
|
22
|
+
whereRelationExists<Related extends ObjectLiteral, Type extends ObjectLiteral = TypedRoot<Entity>>(relation: RelationSelection<Type, Related>, alias: string, where?: RelatedCondition<Related>): this;
|
|
23
|
+
/** Adds `AND EXISTS (…)` over the relation. */
|
|
24
|
+
andWhereRelationExists<Related extends ObjectLiteral, Type extends ObjectLiteral = TypedRoot<Entity>>(relation: RelationSelection<Type, Related>, alias: string, where?: RelatedCondition<Related>): this;
|
|
25
|
+
/** Adds `OR EXISTS (…)` over the relation. */
|
|
26
|
+
orWhereRelationExists<Related extends ObjectLiteral, Type extends ObjectLiteral = TypedRoot<Entity>>(relation: RelationSelection<Type, Related>, alias: string, where?: RelatedCondition<Related>): this;
|
|
27
|
+
/** Sets `WHERE NOT EXISTS (…)` over the relation, replacing the WHERE conditions set before. */
|
|
28
|
+
whereRelationNotExists<Related extends ObjectLiteral, Type extends ObjectLiteral = TypedRoot<Entity>>(relation: RelationSelection<Type, Related>, alias: string, where?: RelatedCondition<Related>): this;
|
|
29
|
+
/** Adds `AND NOT EXISTS (…)` over the relation. */
|
|
30
|
+
andWhereRelationNotExists<Related extends ObjectLiteral, Type extends ObjectLiteral = TypedRoot<Entity>>(relation: RelationSelection<Type, Related>, alias: string, where?: RelatedCondition<Related>): this;
|
|
31
|
+
/** Adds `OR NOT EXISTS (…)` over the relation. */
|
|
32
|
+
orWhereRelationNotExists<Related extends ObjectLiteral, Type extends ObjectLiteral = TypedRoot<Entity>>(relation: RelationSelection<Type, Related>, alias: string, where?: RelatedCondition<Related>): this;
|
|
33
|
+
}
|
|
34
|
+
declare module 'typeorm/query-builder/SelectQueryBuilder' {
|
|
35
|
+
interface SelectQueryBuilder<Entity extends ObjectLiteral> extends WhereRelationExistsMethods<Entity> {
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const typeorm_1 = require("typeorm");
|
|
4
|
+
const where_exists_extension_1 = require("./where-exists.extension");
|
|
5
|
+
const prototype_utils_1 = require("../utils/prototype.utils");
|
|
6
|
+
const query_builder_utils_1 = require("../utils/query-builder.utils");
|
|
7
|
+
const where_utils_1 = require("../utils/where.utils");
|
|
8
|
+
const createMethod = (method, negate) => function (relation, alias, where) {
|
|
9
|
+
return attachRelationExists(this, method, negate, relation, alias, where);
|
|
10
|
+
};
|
|
11
|
+
const extension = {
|
|
12
|
+
prototype: {
|
|
13
|
+
whereRelationExists: createMethod('where', false),
|
|
14
|
+
andWhereRelationExists: createMethod('andWhere', false),
|
|
15
|
+
orWhereRelationExists: createMethod('orWhere', false),
|
|
16
|
+
whereRelationNotExists: createMethod('where', true),
|
|
17
|
+
andWhereRelationNotExists: createMethod('andWhere', true),
|
|
18
|
+
orWhereRelationNotExists: createMethod('orWhere', true),
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
(0, prototype_utils_1.patchPrototype)(typeorm_1.SelectQueryBuilder, extension);
|
|
22
|
+
// implementation
|
|
23
|
+
function attachRelationExists(builder, method, negate, relationSelection, alias, where) {
|
|
24
|
+
const methodName = `${method}Relation${negate ? 'Not' : ''}Exists`;
|
|
25
|
+
const key = (0, query_builder_utils_1.getTypedSelectionKey)(builder, relationSelection);
|
|
26
|
+
if (Array.isArray(key)) {
|
|
27
|
+
throw new TypeError(`${methodName} expects the callback to select one relation, got ${key.length}: ${key.join(', ')}`);
|
|
28
|
+
}
|
|
29
|
+
const dot = key.indexOf('.');
|
|
30
|
+
const ownerAlias = key.slice(0, dot);
|
|
31
|
+
const propertyPath = key.slice(dot + 1);
|
|
32
|
+
const aliases = queryAliases(builder);
|
|
33
|
+
const owner = aliases.find((candidate) => candidate.name === ownerAlias);
|
|
34
|
+
const relation = (owner === null || owner === void 0 ? void 0 : owner.hasMetadata) ? owner.metadata.findRelationWithPropertyPath(propertyPath) : undefined;
|
|
35
|
+
if (!relation) {
|
|
36
|
+
throw new TypeError(`${methodName}: ${key} is not a relation of an entity of the query`);
|
|
37
|
+
}
|
|
38
|
+
// in the subquery the alias would hide the outer one the join condition refers to; SQLite matches
|
|
39
|
+
// names without case, so 'USER' would hide 'user' there
|
|
40
|
+
if (aliases.some((candidate) => candidate.name.toLowerCase() === alias.toLowerCase())) {
|
|
41
|
+
throw new TypeError(`${methodName}: the alias "${alias}" is already used by the query, choose another one`);
|
|
42
|
+
}
|
|
43
|
+
const column = (aliasName, columnName) => `${builder.escape(aliasName)}.${builder.escape(columnName)}`;
|
|
44
|
+
const subQuery = builder.connection
|
|
45
|
+
.createQueryBuilder()
|
|
46
|
+
.select('1')
|
|
47
|
+
.from(relation.inverseEntityMetadata.target, alias);
|
|
48
|
+
const correlation = joinCondition(relation, ownerAlias, alias, column, subQuery);
|
|
49
|
+
where === null || where === void 0 ? void 0 : where(subQuery);
|
|
50
|
+
// after the caller's conditions, so a `where` or an `orWhere` of theirs can't drop or bypass it
|
|
51
|
+
(0, where_utils_1.andWhereNarrowing)(subQuery, correlation);
|
|
52
|
+
return (0, where_exists_extension_1.attachExists)(builder, method, subQuery, negate);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The aliases of the query and of the queries it is part of. Inside `Brackets` the builder has the outer
|
|
56
|
+
* query's main alias but none of its joins: those are on its parent.
|
|
57
|
+
*/
|
|
58
|
+
function queryAliases(builder) {
|
|
59
|
+
const aliases = [];
|
|
60
|
+
// parentQueryBuilder is protected in TypeORM's types
|
|
61
|
+
let query = builder;
|
|
62
|
+
for (; query; query = query.parentQueryBuilder) {
|
|
63
|
+
const { aliases: own, mainAlias } = query.expressionMap;
|
|
64
|
+
aliases.push(...own, ...(mainAlias ? [mainAlias] : []));
|
|
65
|
+
}
|
|
66
|
+
return aliases;
|
|
67
|
+
}
|
|
68
|
+
const equal = (left, right) => `${left} = ${right}`;
|
|
69
|
+
/** The condition between the related rows (`alias`) and the outer row (`ownerAlias`); joins the junction table of a many-to-many. */
|
|
70
|
+
function joinCondition(relation, ownerAlias, alias, column, subQuery) {
|
|
71
|
+
var _a;
|
|
72
|
+
const referenced = (joinColumn) => joinColumn.referencedColumn.databaseName;
|
|
73
|
+
if (relation.isManyToMany) {
|
|
74
|
+
const junctionAlias = `${alias}_junction`;
|
|
75
|
+
// the owning side defines the junction table; from the other side its columns swap roles
|
|
76
|
+
const inverse = relation.inverseRelation;
|
|
77
|
+
const [ownerColumns, relatedColumns] = relation.isOwning
|
|
78
|
+
? [relation.joinColumns, relation.inverseJoinColumns]
|
|
79
|
+
: [inverse.inverseJoinColumns, inverse.joinColumns];
|
|
80
|
+
subQuery.innerJoin(((_a = relation.junctionEntityMetadata) !== null && _a !== void 0 ? _a : inverse.junctionEntityMetadata).target, junctionAlias, relatedColumns.map((joinColumn) => equal(column(alias, referenced(joinColumn)), column(junctionAlias, joinColumn.databaseName))).join(' AND '));
|
|
81
|
+
return ownerColumns
|
|
82
|
+
.map((joinColumn) => equal(column(junctionAlias, joinColumn.databaseName), column(ownerAlias, referenced(joinColumn))))
|
|
83
|
+
.join(' AND ');
|
|
84
|
+
}
|
|
85
|
+
// the join columns are on the outer entity's table
|
|
86
|
+
if (relation.isManyToOne || relation.isOneToOneOwner) {
|
|
87
|
+
return relation.joinColumns
|
|
88
|
+
.map((joinColumn) => equal(column(alias, referenced(joinColumn)), column(ownerAlias, joinColumn.databaseName)))
|
|
89
|
+
.join(' AND ');
|
|
90
|
+
}
|
|
91
|
+
// one-to-many, or the inverse side of a one-to-one: the join columns are on the related table
|
|
92
|
+
return relation.inverseRelation.joinColumns
|
|
93
|
+
.map((joinColumn) => equal(column(alias, joinColumn.databaseName), column(ownerAlias, referenced(joinColumn))))
|
|
94
|
+
.join(' AND ');
|
|
95
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './extensions';
|
|
2
|
+
export * from './decorators';
|
|
2
3
|
export * from './types/interfaces';
|
|
3
4
|
export * from './types/extensions';
|
|
4
5
|
export type { Json } from './types/modules/proxy-callback.types';
|
|
6
|
+
export type { TypedRoot, WithTypedRoot } from './types/modules/typed-root.types';
|
|
5
7
|
export * from './utils/table.utils';
|
|
6
8
|
export { escapeLikePattern } from './utils/search.utils';
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.escapeLikePattern = void 0;
|
|
18
18
|
__exportStar(require("./extensions"), exports);
|
|
19
|
+
__exportStar(require("./decorators"), exports);
|
|
19
20
|
__exportStar(require("./types/interfaces"), exports);
|
|
20
21
|
__exportStar(require("./types/extensions"), exports);
|
|
21
22
|
__exportStar(require("./utils/table.utils"), exports);
|
|
@@ -13,4 +13,9 @@ export interface ListWithCursor<Entity> {
|
|
|
13
13
|
list: Entity[];
|
|
14
14
|
/** Cursor of the next page, `null` on the last page. */
|
|
15
15
|
nextCursor: string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Whether a next page follows. Always known, unlike the `hasMore` of `getManyWithTotals`: the
|
|
18
|
+
* keyset query loads `pageSize + 1` rows, so it needs no total. Equivalent to `nextCursor !== null`.
|
|
19
|
+
*/
|
|
20
|
+
hasMore: boolean;
|
|
16
21
|
}
|
|
@@ -1,12 +1,31 @@
|
|
|
1
|
+
import type { OrderType } from '../interfaces/ordering.interface';
|
|
1
2
|
import type { ApplyPaginationOptions } from './pagination.types';
|
|
2
3
|
/** Also takes the pagination options, e.g. `useTakeAndSkip` for queries with joined collections. */
|
|
3
4
|
export type GetManyWithTotalsOptions = ApplyPaginationOptions & {
|
|
4
5
|
disableTotalsCalculation?: boolean;
|
|
5
6
|
loadAll?: boolean;
|
|
6
7
|
};
|
|
8
|
+
/** Options of `getRawManyWithTotals`. Raw rows are paged with LIMIT / OFFSET, so there is no `useTakeAndSkip`. */
|
|
9
|
+
export type GetRawManyWithTotalsOptions = Omit<GetManyWithTotalsOptions, 'useTakeAndSkip'> & {
|
|
10
|
+
/**
|
|
11
|
+
* An expression that counts the rows of the query by itself, such as `COUNT(DISTINCT "order"."user_id")`
|
|
12
|
+
* for a query grouped by `"order"."user_id"`: cheaper than counting the query as a subquery.
|
|
13
|
+
* It replaces the select list, and GROUP BY, HAVING and DISTINCT are dropped: it can't count a query with HAVING,
|
|
14
|
+
* and counts a DISTINCT query only when it is a `COUNT(DISTINCT …)` itself.
|
|
15
|
+
*/
|
|
16
|
+
countExpression?: string;
|
|
17
|
+
};
|
|
7
18
|
export interface ListWithTotals<Entity> {
|
|
8
19
|
list: Entity[];
|
|
9
20
|
total: number | null;
|
|
10
21
|
limit: number | null;
|
|
11
22
|
offset: number | null;
|
|
23
|
+
/**
|
|
24
|
+
* Whether rows follow the page. `null` only with `loadAll`, where the page is every row.
|
|
25
|
+
* With `disableTotalsCalculation` it is still known: one row past the page is loaded and dropped,
|
|
26
|
+
* instead of counting.
|
|
27
|
+
*/
|
|
28
|
+
hasMore: boolean | null;
|
|
29
|
+
/** The ORDER BY clauses the query was built with, in the order they were applied. */
|
|
30
|
+
orderBy: OrderType[];
|
|
12
31
|
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export * from './pagination.types';
|
|
2
2
|
export * from './order.types';
|
|
3
3
|
export * from './typed-order-by.types';
|
|
4
|
+
export * from './typed-group-by.types';
|
|
4
5
|
export * from './get-many-with-totals.types';
|
|
5
6
|
export * from './where.types';
|
|
6
7
|
export * from './period.types';
|
|
7
8
|
export * from './cursor-pagination.types';
|
|
8
9
|
export * from './search.types';
|
|
10
|
+
export * from './typed-having.types';
|
|
11
|
+
export * from './union.types';
|
|
12
|
+
export * from './join-lateral.types';
|
|
13
|
+
export * from './query-returning.types';
|
|
@@ -17,8 +17,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./pagination.types"), exports);
|
|
18
18
|
__exportStar(require("./order.types"), exports);
|
|
19
19
|
__exportStar(require("./typed-order-by.types"), exports);
|
|
20
|
+
__exportStar(require("./typed-group-by.types"), exports);
|
|
20
21
|
__exportStar(require("./get-many-with-totals.types"), exports);
|
|
21
22
|
__exportStar(require("./where.types"), exports);
|
|
22
23
|
__exportStar(require("./period.types"), exports);
|
|
23
24
|
__exportStar(require("./cursor-pagination.types"), exports);
|
|
24
25
|
__exportStar(require("./search.types"), exports);
|
|
26
|
+
__exportStar(require("./typed-having.types"), exports);
|
|
27
|
+
__exportStar(require("./union.types"), exports);
|
|
28
|
+
__exportStar(require("./join-lateral.types"), exports);
|
|
29
|
+
__exportStar(require("./query-returning.types"), exports);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
|
2
|
+
/**
|
|
3
|
+
* The subquery of a LATERAL join: raw SQL (`SELECT … LIMIT 1`, without parentheses), a query
|
|
4
|
+
* builder, or a factory that builds it on the query builder it is given, as for TypeORM's joins.
|
|
5
|
+
*/
|
|
6
|
+
export type LateralSubQuery<SubEntity extends ObjectLiteral = ObjectLiteral> = string | SelectQueryBuilder<SubEntity> | ((qb: SelectQueryBuilder<ObjectLiteral>) => SelectQueryBuilder<SubEntity>);
|
|
@@ -12,4 +12,12 @@ export type ApplyPeriodOptions = {
|
|
|
12
12
|
* `{ periodFrom: '2024-01-01', periodTo: '2024-02-01' }`.
|
|
13
13
|
*/
|
|
14
14
|
includeTo?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* IANA time zone (`'America/New_York'`) in which a date (`'2024-01-31'`) and a date-time without an offset
|
|
17
|
+
* (`'2024-01-31 10:00'`) are read: `periodTo: '2024-01-31'` ends at midnight of February 1st in that zone.
|
|
18
|
+
* They become instants (`Date`), so it is for timestamp columns, not `date` ones. `Date`s and strings with
|
|
19
|
+
* an offset are instants already and stay as they are; other strings throw a `TypeError`, as does an
|
|
20
|
+
* unknown zone. Missing, `null` or `''`: the strings go to the database as they are.
|
|
21
|
+
*/
|
|
22
|
+
timeZone?: string | null;
|
|
15
23
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ObjectLiteral } from 'typeorm';
|
|
2
|
+
/** What `queryReturning` resolves to: the same shape for every statement and every driver. */
|
|
3
|
+
export interface QueryReturningResult<Row = ObjectLiteral> {
|
|
4
|
+
/** The rows the statement returned: those of a SELECT, or of a `RETURNING` clause. Empty when there are none. */
|
|
5
|
+
records: Row[];
|
|
6
|
+
/**
|
|
7
|
+
* The number of rows the driver reports for the statement, `null` when it reports none.
|
|
8
|
+
* SQLite reports none for a statement that returns rows, such as an UPDATE with `RETURNING`.
|
|
9
|
+
*/
|
|
10
|
+
affected: number | null;
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type TypedGroupByOptions = {
|
|
2
|
+
/**
|
|
3
|
+
* Group by the quoted database column (`"ticket"."ticket_status"`) instead of `ticket.status`,
|
|
4
|
+
* which TypeORM maps to the column itself. TypeORM maps only aliases with metadata, so a subquery
|
|
5
|
+
* in FROM needs it on PostgreSQL, where an unquoted `sub.firstName` is folded to `firstname`.
|
|
6
|
+
*/
|
|
7
|
+
useQuotes?: boolean;
|
|
8
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
|
2
|
+
/** A part of a UNION: a query builder, or raw SQL whose placeholders read the outer builder's parameters. */
|
|
3
|
+
export type UnionQuery = string | {
|
|
4
|
+
getQuery(): string;
|
|
5
|
+
getParameters(): ObjectLiteral;
|
|
6
|
+
};
|
|
7
|
+
export type UnionOptions = {
|
|
8
|
+
/** `UNION ALL`: keep duplicate rows. Defaults to `false`, `UNION`, which removes them. */
|
|
9
|
+
all?: boolean;
|
|
10
|
+
};
|
|
11
|
+
/** TypeORM's options of `addCommonTableExpression` (`materialized`, `columnNames`), and `all`. */
|
|
12
|
+
export type UnionCteOptions = UnionOptions & NonNullable<Parameters<SelectQueryBuilder<ObjectLiteral>['addCommonTableExpression']>[2]>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export type WhereMethods = 'where' | 'andWhere' | 'orWhere';
|
|
2
|
+
export type HavingMethods = 'having' | 'andHaving' | 'orHaving';
|
|
2
3
|
export type WhereInMethods = 'whereIsIn' | 'andWhereIsIn' | 'orWhereIsIn' | 'whereIsNotIn' | 'andWhereIsNotIn' | 'orWhereIsNotIn';
|
|
3
4
|
export type WhereAnyMethods = 'whereIsAny' | 'andWhereIsAny' | 'orWhereIsAny' | 'whereIsNotAny' | 'andWhereIsNotAny' | 'orWhereIsNotAny';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ObjectLiteral } from 'typeorm';
|
|
2
|
+
declare const typedRoot: unique symbol;
|
|
3
|
+
declare class TypedRootMark<Root> {
|
|
4
|
+
[typedRoot]?(): Root;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The entity type of a builder whose typed callbacks take another root, set with `typed<Root>()`: the entity
|
|
8
|
+
* with an optional symbol method that only types carry. Entities loaded with it are plain entities.
|
|
9
|
+
*/
|
|
10
|
+
export type WithTypedRoot<Entity, Root extends ObjectLiteral> = Entity & TypedRootMark<Root>;
|
|
11
|
+
/**
|
|
12
|
+
* The root of a builder's typed callbacks: the one set with `typed<Root>()`, or else its entity. The key check
|
|
13
|
+
* comes first: without `strictNullChecks` an entity with an index signature (`ObjectLiteral`) matches the
|
|
14
|
+
* optional mark too, and its root would be inferred as `unknown`.
|
|
15
|
+
*/
|
|
16
|
+
export type TypedRoot<Entity> = typeof typedRoot extends keyof Entity ? Entity extends TypedRootMark<infer Root> ? Root extends ObjectLiteral ? Root : Entity : Entity : Entity;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
|
2
|
+
type ResolvedCalculatedColumn = {
|
|
3
|
+
/** The key TypeORM reads the column's value from when it builds the entity. */
|
|
4
|
+
key: string;
|
|
5
|
+
/** `Entity.property`, for error messages. */
|
|
6
|
+
label: string;
|
|
7
|
+
};
|
|
8
|
+
/** Whether `property` of the entity of `aliasName` (the main alias by default) is a `@CalculatedColumn`. */
|
|
9
|
+
export declare function isCalculatedColumn<Entity extends ObjectLiteral>(builder: SelectQueryBuilder<Entity>, property: string, aliasName?: string): boolean;
|
|
10
|
+
/** The `@CalculatedColumn` `property` of the entity of `aliasName`; throws a `TypeError` for anything else. */
|
|
11
|
+
export declare function resolveCalculatedColumn<Entity extends ObjectLiteral>(builder: SelectQueryBuilder<Entity>, property: string, aliasName: string | undefined, methodName: string): ResolvedCalculatedColumn;
|
|
12
|
+
/**
|
|
13
|
+
* Selects the value of a `@CalculatedColumn`, already selected with `addSelectCalculated`, a second
|
|
14
|
+
* time under a generated lower-case alias, and returns the alias to order by.
|
|
15
|
+
*
|
|
16
|
+
* The alias the entity is built from can't be ordered by: PostgreSQL folds it unquoted
|
|
17
|
+
* (`user_imagesCount` → `user_imagescount`), and quoted it breaks the DISTINCT query TypeORM pages
|
|
18
|
+
* through with `take` / `skip` and joins, which takes only select aliases it knows unquoted.
|
|
19
|
+
*/
|
|
20
|
+
export declare function selectCalculatedForOrder<Entity extends ObjectLiteral>(builder: SelectQueryBuilder<Entity>, property: string, aliasName: string | undefined, methodName: string): string;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.selectCalculatedForOrder = exports.resolveCalculatedColumn = exports.isCalculatedColumn = void 0;
|
|
4
|
+
const DriverUtils_1 = require("typeorm/driver/DriverUtils");
|
|
5
|
+
const sql_utils_1 = require("./sql.utils");
|
|
6
|
+
function findCalculatedColumn(builder, property, aliasName) {
|
|
7
|
+
const { expressionMap } = builder;
|
|
8
|
+
const alias = aliasName === undefined
|
|
9
|
+
? expressionMap.mainAlias
|
|
10
|
+
: expressionMap.aliases.find((candidate) => candidate.name === aliasName);
|
|
11
|
+
if (!(alias === null || alias === void 0 ? void 0 : alias.hasMetadata)) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
aliasName: alias.name,
|
|
16
|
+
entityName: alias.metadata.name,
|
|
17
|
+
column: alias.metadata.findColumnWithPropertyPath(property),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
// @CalculatedColumn: a virtual property without the query of TypeORM's @VirtualColumn
|
|
21
|
+
const isCalculated = (column) => !!(column === null || column === void 0 ? void 0 : column.isVirtualProperty) && !column.query;
|
|
22
|
+
/** Whether `property` of the entity of `aliasName` (the main alias by default) is a `@CalculatedColumn`. */
|
|
23
|
+
function isCalculatedColumn(builder, property, aliasName) {
|
|
24
|
+
var _a;
|
|
25
|
+
return isCalculated((_a = findCalculatedColumn(builder, property, aliasName)) === null || _a === void 0 ? void 0 : _a.column);
|
|
26
|
+
}
|
|
27
|
+
exports.isCalculatedColumn = isCalculatedColumn;
|
|
28
|
+
/** The `@CalculatedColumn` `property` of the entity of `aliasName`; throws a `TypeError` for anything else. */
|
|
29
|
+
function resolveCalculatedColumn(builder, property, aliasName, methodName) {
|
|
30
|
+
var _a;
|
|
31
|
+
const found = findCalculatedColumn(builder, property, aliasName);
|
|
32
|
+
if (!found) {
|
|
33
|
+
throw new TypeError(`${methodName}: the alias "${aliasName !== null && aliasName !== void 0 ? aliasName : (_a = builder.expressionMap.mainAlias) === null || _a === void 0 ? void 0 : _a.name}" has no entity with "${property}"`);
|
|
34
|
+
}
|
|
35
|
+
const label = `${found.entityName}.${property}`;
|
|
36
|
+
if (!isCalculated(found.column)) {
|
|
37
|
+
throw new TypeError(`${methodName}: ${label} is not a @CalculatedColumn`);
|
|
38
|
+
}
|
|
39
|
+
// shortened past the driver's alias length limit, as TypeORM does it
|
|
40
|
+
const key = DriverUtils_1.DriverUtils.buildAlias(builder.connection.driver, {}, found.aliasName, found.column.databaseName);
|
|
41
|
+
return { key, label };
|
|
42
|
+
}
|
|
43
|
+
exports.resolveCalculatedColumn = resolveCalculatedColumn;
|
|
44
|
+
/**
|
|
45
|
+
* Selects the value of a `@CalculatedColumn`, already selected with `addSelectCalculated`, a second
|
|
46
|
+
* time under a generated lower-case alias, and returns the alias to order by.
|
|
47
|
+
*
|
|
48
|
+
* The alias the entity is built from can't be ordered by: PostgreSQL folds it unquoted
|
|
49
|
+
* (`user_imagesCount` → `user_imagescount`), and quoted it breaks the DISTINCT query TypeORM pages
|
|
50
|
+
* through with `take` / `skip` and joins, which takes only select aliases it knows unquoted.
|
|
51
|
+
*/
|
|
52
|
+
function selectCalculatedForOrder(builder, property, aliasName, methodName) {
|
|
53
|
+
const { key, label } = resolveCalculatedColumn(builder, property, aliasName, methodName);
|
|
54
|
+
const select = builder.expressionMap.selects.find((candidate) => candidate.aliasName === key);
|
|
55
|
+
if (!select) {
|
|
56
|
+
throw new TypeError(`${methodName}: ${label} isn't selected: select it with addSelectCalculated first`);
|
|
57
|
+
}
|
|
58
|
+
const orderAlias = (0, sql_utils_1.createUniqueParameterName)('calculated').toLowerCase();
|
|
59
|
+
// TypeORM keeps a subquery selection as its SQL, with its parameters already on the builder
|
|
60
|
+
builder.addSelect(select.selection, orderAlias);
|
|
61
|
+
return orderAlias;
|
|
62
|
+
}
|
|
63
|
+
exports.selectCalculatedForOrder = selectCalculatedForOrder;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ObjectLiteral } from 'typeorm';
|
|
2
|
+
/**
|
|
3
|
+
* Renames the parameters of a subquery to unique names, in its SQL and in its parameters. A query
|
|
4
|
+
* has one parameter namespace, so two subqueries with a `:status` each would otherwise both read
|
|
5
|
+
* whichever value was set last. Placeholders that aren't keys of `parameters` stay as they are.
|
|
6
|
+
*/
|
|
7
|
+
export declare function withUniqueParameterNames(sql: string, parameters: ObjectLiteral): [string, ObjectLiteral];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withUniqueParameterNames = void 0;
|
|
4
|
+
const sql_utils_1 = require("./sql.utils");
|
|
5
|
+
// TypeORM's placeholder syntax, `:name` and `:...name`, as its drivers match it
|
|
6
|
+
const PARAMETER_PLACEHOLDER = /:(\.\.\.)?([A-Za-z0-9_.]+)/g;
|
|
7
|
+
/**
|
|
8
|
+
* Renames the parameters of a subquery to unique names, in its SQL and in its parameters. A query
|
|
9
|
+
* has one parameter namespace, so two subqueries with a `:status` each would otherwise both read
|
|
10
|
+
* whichever value was set last. Placeholders that aren't keys of `parameters` stay as they are.
|
|
11
|
+
*/
|
|
12
|
+
function withUniqueParameterNames(sql, parameters) {
|
|
13
|
+
const names = new Map(Object.keys(parameters).map((name) => [name, (0, sql_utils_1.createUniqueParameterName)(name)]));
|
|
14
|
+
const renamedSql = sql.replace(PARAMETER_PLACEHOLDER, (placeholder, spread, name) => {
|
|
15
|
+
const unique = names.get(name);
|
|
16
|
+
return unique ? `:${spread !== null && spread !== void 0 ? spread : ''}${unique}` : placeholder;
|
|
17
|
+
});
|
|
18
|
+
const renamedParameters = Object.fromEntries(Object.entries(parameters).map(([name, value]) => [names.get(name), value]));
|
|
19
|
+
return [renamedSql, renamedParameters];
|
|
20
|
+
}
|
|
21
|
+
exports.withUniqueParameterNames = withUniqueParameterNames;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.attachPeriodFilter = void 0;
|
|
4
4
|
const sql_utils_1 = require("./sql.utils");
|
|
5
5
|
const where_utils_1 = require("./where.utils");
|
|
6
|
+
const time_zone_utils_1 = require("./time-zone.utils");
|
|
6
7
|
const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
7
8
|
/** `'2024-01-31'` as a UTC midnight Date, or a `TypeError` if it is not a calendar date (`'2024-02-30'`). */
|
|
8
9
|
function parseDateOnly(value, name) {
|
|
@@ -63,7 +64,10 @@ function getBoundCondition(boundary, name, include) {
|
|
|
63
64
|
* `(a OR b) AND column >= …`. `column` is already quoted.
|
|
64
65
|
*/
|
|
65
66
|
function attachPeriodFilter(builder, column, periodFilter, options) {
|
|
66
|
-
const { includeFrom = true, includeTo = true } = options !== null && options !== void 0 ? options : {};
|
|
67
|
+
const { includeFrom = true, includeTo = true, timeZone } = options !== null && options !== void 0 ? options : {};
|
|
68
|
+
if (timeZone) {
|
|
69
|
+
(0, time_zone_utils_1.assertTimeZone)(timeZone);
|
|
70
|
+
}
|
|
67
71
|
const bounds = [
|
|
68
72
|
{ name: 'periodFrom', include: includeFrom },
|
|
69
73
|
{ name: 'periodTo', include: includeTo },
|
|
@@ -75,7 +79,8 @@ function attachPeriodFilter(builder, column, periodFilter, options) {
|
|
|
75
79
|
}
|
|
76
80
|
const { operator, value } = getBoundCondition(boundary, name, include);
|
|
77
81
|
const paramName = (0, sql_utils_1.createUniqueParameterName)(name);
|
|
78
|
-
(0,
|
|
82
|
+
const bound = timeZone && typeof value === 'string' ? (0, time_zone_utils_1.readInTimeZone)(value, timeZone, name) : value;
|
|
83
|
+
(0, where_utils_1.andWhereNarrowing)(builder, `${column} ${operator} :${paramName}`, { [paramName]: bound });
|
|
79
84
|
}
|
|
80
85
|
return builder;
|
|
81
86
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
export type PatchPrototypeOptions = {
|
|
2
|
+
/** Leave a method the target already has, own or inherited: TypeORM's, or another library's. */
|
|
3
|
+
onlyMissing?: boolean;
|
|
4
|
+
};
|
|
1
5
|
export declare function patchPrototype<T extends {
|
|
2
6
|
prototype: any;
|
|
3
7
|
}, S extends {
|
|
4
8
|
prototype: any;
|
|
5
|
-
}>(target: T, source: S): void;
|
|
9
|
+
}>(target: T, source: S, options?: PatchPrototypeOptions): void;
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.patchPrototype = void 0;
|
|
5
|
-
function patchPrototype(target, source) {
|
|
5
|
+
function patchPrototype(target, source, options = {}) {
|
|
6
6
|
for (const method of Object.keys(source.prototype)) {
|
|
7
|
+
if (options.onlyMissing && method in target.prototype) {
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
7
10
|
target.prototype[method] = source.prototype[method];
|
|
8
11
|
}
|
|
9
12
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ObjectLiteral } from 'typeorm';
|
|
1
|
+
import { DatabaseType, ObjectLiteral } from 'typeorm';
|
|
2
2
|
import { KeyProxyCallback } from '../types/modules/proxy-callback.types';
|
|
3
3
|
export declare class KeyHolder {
|
|
4
4
|
private _keys;
|
|
5
5
|
constructor(_keys?: string[]);
|
|
6
|
-
toSql(length?: number, useQuotes?: boolean): string;
|
|
6
|
+
toSql(length?: number, useQuotes?: boolean, driver?: DatabaseType): string;
|
|
7
7
|
toString(length?: number): string;
|
|
8
8
|
valueOf(): string;
|
|
9
9
|
[Symbol.toPrimitive](): string;
|
|
@@ -37,4 +37,4 @@ export type KeyPrefix = string | (() => string | undefined);
|
|
|
37
37
|
* SQL key of a typed callback: `(u) => u.id` → `prefix.id`, `(u) => u.images.url` → `images.url`
|
|
38
38
|
* (an `alias.column` path keeps its own alias). Strings are returned as is.
|
|
39
39
|
*/
|
|
40
|
-
export declare const getSqlKeyFromProxyCallback: <Type extends ObjectLiteral>(callback: string | KeyHolder | KeyProxyCallback<Type>, addPrefix?: KeyPrefix, useQuotes?: boolean) => string | string[];
|
|
40
|
+
export declare const getSqlKeyFromProxyCallback: <Type extends ObjectLiteral>(callback: string | KeyHolder | KeyProxyCallback<Type>, addPrefix?: KeyPrefix, useQuotes?: boolean, driver?: DatabaseType) => string | string[];
|