@relq/orm 0.1.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/LICENSE +21 -0
- package/README.md +236 -0
- package/dist/cjs/__test-types.cjs +17 -0
- package/dist/cjs/addon/cursor.cjs +1473 -0
- package/dist/cjs/addon/pg.cjs +4969 -0
- package/dist/cjs/cache/index.cjs +9 -0
- package/dist/cjs/cache/query-cache.cjs +311 -0
- package/dist/cjs/condition/array-condition-builder.cjs +527 -0
- package/dist/cjs/condition/array-numeric-condition-builder.cjs +186 -0
- package/dist/cjs/condition/array-specialized-condition-builder.cjs +206 -0
- package/dist/cjs/condition/array-string-condition-builder.cjs +146 -0
- package/dist/cjs/condition/base-condition-builder.cjs +2 -0
- package/dist/cjs/condition/condition-collector.cjs +461 -0
- package/dist/cjs/condition/fulltext-condition-builder.cjs +61 -0
- package/dist/cjs/condition/geometric-condition-builder.cjs +228 -0
- package/dist/cjs/condition/index.cjs +29 -0
- package/dist/cjs/condition/jsonb-condition-builder.cjs +448 -0
- package/dist/cjs/condition/network-condition-builder.cjs +237 -0
- package/dist/cjs/condition/postgis-condition-builder.cjs +188 -0
- package/dist/cjs/condition/range-condition-builder.cjs +98 -0
- package/dist/cjs/core/helpers/ConnectedAggregateBuilder.cjs +132 -0
- package/dist/cjs/core/helpers/ConnectedCTEBuilder.cjs +53 -0
- package/dist/cjs/core/helpers/ConnectedCountBuilder.cjs +73 -0
- package/dist/cjs/core/helpers/ConnectedDeleteBuilder.cjs +65 -0
- package/dist/cjs/core/helpers/ConnectedInsertBuilder.cjs +112 -0
- package/dist/cjs/core/helpers/ConnectedInsertFromSelectBuilder.cjs +66 -0
- package/dist/cjs/core/helpers/ConnectedQueryBuilder.cjs +146 -0
- package/dist/cjs/core/helpers/ConnectedRawQueryBuilder.cjs +46 -0
- package/dist/cjs/core/helpers/ConnectedSelectBuilder.cjs +331 -0
- package/dist/cjs/core/helpers/ConnectedTransactionBuilder.cjs +105 -0
- package/dist/cjs/core/helpers/ConnectedUpdateBuilder.cjs +79 -0
- package/dist/cjs/core/helpers/PaginateBuilder.cjs +178 -0
- package/dist/cjs/core/helpers/ReturningExecutor.cjs +70 -0
- package/dist/cjs/core/helpers/capability-guard.cjs +10 -0
- package/dist/cjs/core/helpers/index.cjs +31 -0
- package/dist/cjs/core/helpers/methods.cjs +10 -0
- package/dist/cjs/core/helpers/query-convenience.cjs +238 -0
- package/dist/cjs/core/helpers/select-joins.cjs +251 -0
- package/dist/cjs/core/helpers/select-pagination.cjs +233 -0
- package/dist/cjs/core/helpers/select-types.cjs +2 -0
- package/dist/cjs/core/pg-family/cockroachdb-client/capabilities.cjs +31 -0
- package/dist/cjs/core/pg-family/cockroachdb-client/index.cjs +7 -0
- package/dist/cjs/core/pg-family/cockroachdb-client/relq-cockroach.cjs +16 -0
- package/dist/cjs/core/pg-family/dsql-client/capabilities.cjs +31 -0
- package/dist/cjs/core/pg-family/dsql-client/index.cjs +7 -0
- package/dist/cjs/core/pg-family/dsql-client/relq-dsql.cjs +16 -0
- package/dist/cjs/core/pg-family/index.cjs +19 -0
- package/dist/cjs/core/pg-family/nile-client/capabilities.cjs +31 -0
- package/dist/cjs/core/pg-family/nile-client/index.cjs +7 -0
- package/dist/cjs/core/pg-family/nile-client/relq-nile.cjs +36 -0
- package/dist/cjs/core/pg-family/nile-client/tenant-context.cjs +44 -0
- package/dist/cjs/core/pg-family/pg-client/capabilities.cjs +31 -0
- package/dist/cjs/core/pg-family/pg-client/index.cjs +7 -0
- package/dist/cjs/core/pg-family/pg-client/relq-postgres.cjs +43 -0
- package/dist/cjs/core/pg-family/shared/pg-base.cjs +385 -0
- package/dist/cjs/core/pg-family/shared/pg-dialect.cjs +67 -0
- package/dist/cjs/core/pg-family/shared/pg-error-parser.cjs +34 -0
- package/dist/cjs/core/pg-family/shared/pg-type-coercion.cjs +14 -0
- package/dist/cjs/core/relq-base.cjs +307 -0
- package/dist/cjs/core/relq-client.cjs +56 -0
- package/dist/cjs/core/shared/cleanup.cjs +36 -0
- package/dist/cjs/core/shared/column-mapping.cjs +97 -0
- package/dist/cjs/core/shared/errors.cjs +17 -0
- package/dist/cjs/core/shared/index.cjs +24 -0
- package/dist/cjs/core/shared/table-accessor.cjs +22 -0
- package/dist/cjs/core/shared/transform.cjs +35 -0
- package/dist/cjs/core/shared/types.cjs +2 -0
- package/dist/cjs/core/shared/validation.cjs +140 -0
- package/dist/cjs/core/types/core.types.cjs +2 -0
- package/dist/cjs/count/count-builder.cjs +88 -0
- package/dist/cjs/count/index.cjs +5 -0
- package/dist/cjs/delete/delete-builder.cjs +176 -0
- package/dist/cjs/delete/index.cjs +5 -0
- package/dist/cjs/explain/explain-builder.cjs +99 -0
- package/dist/cjs/explain/index.cjs +5 -0
- package/dist/cjs/index.cjs +26 -0
- package/dist/cjs/insert/conflict-builder.cjs +213 -0
- package/dist/cjs/insert/index.cjs +5 -0
- package/dist/cjs/insert/insert-builder.cjs +320 -0
- package/dist/cjs/insert/insert-from-select-builder.cjs +86 -0
- package/dist/cjs/pubsub/index.cjs +7 -0
- package/dist/cjs/pubsub/listen-notify-builder.cjs +57 -0
- package/dist/cjs/pubsub/listener-connection.cjs +180 -0
- package/dist/cjs/raw/index.cjs +8 -0
- package/dist/cjs/raw/raw-query-builder.cjs +27 -0
- package/dist/cjs/raw/sql-template.cjs +73 -0
- package/dist/cjs/select/aggregate-builder.cjs +179 -0
- package/dist/cjs/select/index.cjs +16 -0
- package/dist/cjs/select/join-builder.cjs +192 -0
- package/dist/cjs/select/join-condition-builder.cjs +189 -0
- package/dist/cjs/select/join-internals.cjs +5 -0
- package/dist/cjs/select/join-many-condition-builder.cjs +159 -0
- package/dist/cjs/select/scalar-query-builder.cjs +134 -0
- package/dist/cjs/select/scalar-select-builder.cjs +78 -0
- package/dist/cjs/select/select-builder.cjs +426 -0
- package/dist/cjs/select/sql-expression.cjs +38 -0
- package/dist/cjs/select/table-proxy.cjs +99 -0
- package/dist/cjs/shared/aws-dsql.cjs +181 -0
- package/dist/cjs/shared/errors/relq-errors.cjs +361 -0
- package/dist/cjs/shared/pg-format.cjs +383 -0
- package/dist/cjs/shared/types/config-types.cjs +51 -0
- package/dist/cjs/transaction/index.cjs +6 -0
- package/dist/cjs/transaction/transaction-builder.cjs +78 -0
- package/dist/cjs/types/aggregate-types.cjs +2 -0
- package/dist/cjs/types/inference-types.cjs +18 -0
- package/dist/cjs/types/pagination-types.cjs +7 -0
- package/dist/cjs/types/result-types.cjs +2 -0
- package/dist/cjs/types/scalar-types.cjs +2 -0
- package/dist/cjs/types/schema-types.cjs +2 -0
- package/dist/cjs/types/subscription-types.cjs +2 -0
- package/dist/cjs/types.cjs +2 -0
- package/dist/cjs/update/array-update-builder.cjs +232 -0
- package/dist/cjs/update/index.cjs +16 -0
- package/dist/cjs/update/jsonb-update-builder.cjs +219 -0
- package/dist/cjs/update/update-builder.cjs +274 -0
- package/dist/cjs/utils/addon/pg/cursor.cjs +8 -0
- package/dist/cjs/utils/addon/pg/pg.cjs +23 -0
- package/dist/cjs/utils/case-converter.cjs +58 -0
- package/dist/cjs/utils/env-resolver.cjs +226 -0
- package/dist/cjs/utils/environment-detection.cjs +124 -0
- package/dist/cjs/utils/fk-resolver.cjs +186 -0
- package/dist/cjs/utils/index.cjs +25 -0
- package/dist/cjs/utils/pool-defaults.cjs +91 -0
- package/dist/cjs/utils/type-coercion.cjs +120 -0
- package/dist/cjs/window/index.cjs +5 -0
- package/dist/cjs/window/window-builder.cjs +80 -0
- package/dist/esm/__test-types.js +15 -0
- package/dist/esm/addon/cursor.js +1440 -0
- package/dist/esm/addon/pg.js +4931 -0
- package/dist/esm/cache/index.js +1 -0
- package/dist/esm/cache/query-cache.js +303 -0
- package/dist/esm/condition/array-condition-builder.js +519 -0
- package/dist/esm/condition/array-numeric-condition-builder.js +182 -0
- package/dist/esm/condition/array-specialized-condition-builder.js +200 -0
- package/dist/esm/condition/array-string-condition-builder.js +142 -0
- package/dist/esm/condition/base-condition-builder.js +1 -0
- package/dist/esm/condition/condition-collector.js +452 -0
- package/dist/esm/condition/fulltext-condition-builder.js +53 -0
- package/dist/esm/condition/geometric-condition-builder.js +220 -0
- package/dist/esm/condition/index.js +8 -0
- package/dist/esm/condition/jsonb-condition-builder.js +439 -0
- package/dist/esm/condition/network-condition-builder.js +229 -0
- package/dist/esm/condition/postgis-condition-builder.js +180 -0
- package/dist/esm/condition/range-condition-builder.js +90 -0
- package/dist/esm/core/helpers/ConnectedAggregateBuilder.js +128 -0
- package/dist/esm/core/helpers/ConnectedCTEBuilder.js +49 -0
- package/dist/esm/core/helpers/ConnectedCountBuilder.js +69 -0
- package/dist/esm/core/helpers/ConnectedDeleteBuilder.js +61 -0
- package/dist/esm/core/helpers/ConnectedInsertBuilder.js +108 -0
- package/dist/esm/core/helpers/ConnectedInsertFromSelectBuilder.js +62 -0
- package/dist/esm/core/helpers/ConnectedQueryBuilder.js +142 -0
- package/dist/esm/core/helpers/ConnectedRawQueryBuilder.js +42 -0
- package/dist/esm/core/helpers/ConnectedSelectBuilder.js +327 -0
- package/dist/esm/core/helpers/ConnectedTransactionBuilder.js +100 -0
- package/dist/esm/core/helpers/ConnectedUpdateBuilder.js +75 -0
- package/dist/esm/core/helpers/PaginateBuilder.js +174 -0
- package/dist/esm/core/helpers/ReturningExecutor.js +66 -0
- package/dist/esm/core/helpers/capability-guard.js +7 -0
- package/dist/esm/core/helpers/index.js +13 -0
- package/dist/esm/core/helpers/methods.js +6 -0
- package/dist/esm/core/helpers/query-convenience.js +194 -0
- package/dist/esm/core/helpers/select-joins.js +246 -0
- package/dist/esm/core/helpers/select-pagination.js +226 -0
- package/dist/esm/core/helpers/select-types.js +1 -0
- package/dist/esm/core/pg-family/cockroachdb-client/capabilities.js +28 -0
- package/dist/esm/core/pg-family/cockroachdb-client/index.js +2 -0
- package/dist/esm/core/pg-family/cockroachdb-client/relq-cockroach.js +12 -0
- package/dist/esm/core/pg-family/dsql-client/capabilities.js +28 -0
- package/dist/esm/core/pg-family/dsql-client/index.js +2 -0
- package/dist/esm/core/pg-family/dsql-client/relq-dsql.js +12 -0
- package/dist/esm/core/pg-family/index.js +6 -0
- package/dist/esm/core/pg-family/nile-client/capabilities.js +28 -0
- package/dist/esm/core/pg-family/nile-client/index.js +2 -0
- package/dist/esm/core/pg-family/nile-client/relq-nile.js +32 -0
- package/dist/esm/core/pg-family/nile-client/tenant-context.js +40 -0
- package/dist/esm/core/pg-family/pg-client/capabilities.js +28 -0
- package/dist/esm/core/pg-family/pg-client/index.js +2 -0
- package/dist/esm/core/pg-family/pg-client/relq-postgres.js +39 -0
- package/dist/esm/core/pg-family/shared/pg-base.js +347 -0
- package/dist/esm/core/pg-family/shared/pg-dialect.js +63 -0
- package/dist/esm/core/pg-family/shared/pg-error-parser.js +29 -0
- package/dist/esm/core/pg-family/shared/pg-type-coercion.js +6 -0
- package/dist/esm/core/relq-base.js +270 -0
- package/dist/esm/core/relq-client.js +48 -0
- package/dist/esm/core/shared/cleanup.js +27 -0
- package/dist/esm/core/shared/column-mapping.js +90 -0
- package/dist/esm/core/shared/errors.js +13 -0
- package/dist/esm/core/shared/index.js +6 -0
- package/dist/esm/core/shared/table-accessor.js +19 -0
- package/dist/esm/core/shared/transform.js +30 -0
- package/dist/esm/core/shared/types.js +1 -0
- package/dist/esm/core/shared/validation.js +136 -0
- package/dist/esm/core/types/core.types.js +1 -0
- package/dist/esm/count/count-builder.js +81 -0
- package/dist/esm/count/index.js +1 -0
- package/dist/esm/delete/delete-builder.js +169 -0
- package/dist/esm/delete/index.js +1 -0
- package/dist/esm/explain/explain-builder.js +95 -0
- package/dist/esm/explain/index.js +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/insert/conflict-builder.js +202 -0
- package/dist/esm/insert/index.js +1 -0
- package/dist/esm/insert/insert-builder.js +313 -0
- package/dist/esm/insert/insert-from-select-builder.js +79 -0
- package/dist/esm/pubsub/index.js +1 -0
- package/dist/esm/pubsub/listen-notify-builder.js +48 -0
- package/dist/esm/pubsub/listener-connection.js +173 -0
- package/dist/esm/raw/index.js +2 -0
- package/dist/esm/raw/raw-query-builder.js +20 -0
- package/dist/esm/raw/sql-template.js +66 -0
- package/dist/esm/select/aggregate-builder.js +172 -0
- package/dist/esm/select/index.js +4 -0
- package/dist/esm/select/join-builder.js +184 -0
- package/dist/esm/select/join-condition-builder.js +181 -0
- package/dist/esm/select/join-internals.js +2 -0
- package/dist/esm/select/join-many-condition-builder.js +151 -0
- package/dist/esm/select/scalar-query-builder.js +126 -0
- package/dist/esm/select/scalar-select-builder.js +70 -0
- package/dist/esm/select/select-builder.js +419 -0
- package/dist/esm/select/sql-expression.js +33 -0
- package/dist/esm/select/table-proxy.js +91 -0
- package/dist/esm/shared/aws-dsql.js +140 -0
- package/dist/esm/shared/errors/relq-errors.js +339 -0
- package/dist/esm/shared/pg-format.js +375 -0
- package/dist/esm/shared/types/config-types.js +46 -0
- package/dist/esm/transaction/index.js +1 -0
- package/dist/esm/transaction/transaction-builder.js +70 -0
- package/dist/esm/types/aggregate-types.js +1 -0
- package/dist/esm/types/inference-types.js +12 -0
- package/dist/esm/types/pagination-types.js +4 -0
- package/dist/esm/types/result-types.js +1 -0
- package/dist/esm/types/scalar-types.js +1 -0
- package/dist/esm/types/schema-types.js +1 -0
- package/dist/esm/types/subscription-types.js +1 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/update/array-update-builder.js +219 -0
- package/dist/esm/update/index.js +3 -0
- package/dist/esm/update/jsonb-update-builder.js +211 -0
- package/dist/esm/update/update-builder.js +267 -0
- package/dist/esm/utils/addon/pg/cursor.js +1 -0
- package/dist/esm/utils/addon/pg/pg.js +2 -0
- package/dist/esm/utils/case-converter.js +55 -0
- package/dist/esm/utils/env-resolver.js +213 -0
- package/dist/esm/utils/environment-detection.js +114 -0
- package/dist/esm/utils/fk-resolver.js +178 -0
- package/dist/esm/utils/index.js +4 -0
- package/dist/esm/utils/pool-defaults.js +85 -0
- package/dist/esm/utils/type-coercion.js +112 -0
- package/dist/esm/window/index.js +1 -0
- package/dist/esm/window/window-builder.js +73 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +7281 -0
- package/dist/index.js +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConnectedSelectBuilder = void 0;
|
|
4
|
+
const methods_1 = require("./methods.cjs");
|
|
5
|
+
const select_joins_1 = require("./select-joins.cjs");
|
|
6
|
+
const select_pagination_1 = require("./select-pagination.cjs");
|
|
7
|
+
const capability_guard_1 = require("./capability-guard.cjs");
|
|
8
|
+
const table_accessor_1 = require("../shared/table-accessor.cjs");
|
|
9
|
+
const sql_expression_1 = require("../../select/sql-expression.cjs");
|
|
10
|
+
const table_proxy_1 = require("../../select/table-proxy.cjs");
|
|
11
|
+
const fk_resolver_1 = require("../../utils/fk-resolver.cjs");
|
|
12
|
+
class ConnectedSelectBuilder {
|
|
13
|
+
builder;
|
|
14
|
+
relq;
|
|
15
|
+
tableName;
|
|
16
|
+
columns;
|
|
17
|
+
schemaKey;
|
|
18
|
+
constructor(builder, relq, tableName, columns, schemaKey) {
|
|
19
|
+
this.builder = builder;
|
|
20
|
+
this.relq = relq;
|
|
21
|
+
this.tableName = tableName;
|
|
22
|
+
this.columns = columns;
|
|
23
|
+
this.schemaKey = schemaKey;
|
|
24
|
+
this.setupColumnResolver();
|
|
25
|
+
}
|
|
26
|
+
get joinCtx() {
|
|
27
|
+
return { relq: this.relq, builder: this.builder, tableName: this.tableName, schemaKey: this.schemaKey };
|
|
28
|
+
}
|
|
29
|
+
get paginationCtx() {
|
|
30
|
+
return { relq: this.relq, builder: this.builder, tableName: this.tableName };
|
|
31
|
+
}
|
|
32
|
+
setupColumnResolver() {
|
|
33
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
34
|
+
const tableKey = this.schemaKey || this.tableName;
|
|
35
|
+
const tableDef = internal.getTableDef(tableKey);
|
|
36
|
+
if (!tableDef) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
40
|
+
this.builder.setColumnResolver((column) => {
|
|
41
|
+
const columnDef = tableColumns[column];
|
|
42
|
+
if (columnDef) {
|
|
43
|
+
return columnDef.$columnName || column;
|
|
44
|
+
}
|
|
45
|
+
return column;
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
transformJoinResults(rows) {
|
|
49
|
+
const joins = this.builder.getStructuredJoins();
|
|
50
|
+
if (joins.length === 0) {
|
|
51
|
+
return rows;
|
|
52
|
+
}
|
|
53
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
54
|
+
return rows.map(row => {
|
|
55
|
+
if (!row || typeof row !== 'object')
|
|
56
|
+
return row;
|
|
57
|
+
const transformed = { ...row };
|
|
58
|
+
for (const join of joins) {
|
|
59
|
+
const alias = join.alias;
|
|
60
|
+
const nestedData = transformed[alias];
|
|
61
|
+
if (nestedData === null || nestedData === undefined) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const joinedTableDef = internal.getTableDef(join.schemaKey || alias) || internal.getTableDef(join.table);
|
|
65
|
+
if (!joinedTableDef) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const tableColumns = joinedTableDef.$columns || joinedTableDef;
|
|
69
|
+
const dbToProp = new Map();
|
|
70
|
+
const propTypes = new Map();
|
|
71
|
+
for (const [propName, colDef] of Object.entries(tableColumns)) {
|
|
72
|
+
const dbColName = colDef?.$columnName ?? propName;
|
|
73
|
+
dbToProp.set(dbColName, propName);
|
|
74
|
+
const snakeCase = propName.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
75
|
+
if (snakeCase !== propName && !dbToProp.has(snakeCase)) {
|
|
76
|
+
dbToProp.set(snakeCase, propName);
|
|
77
|
+
}
|
|
78
|
+
const sqlType = colDef?.$sqlType || (typeof colDef?.$type === 'string' ? colDef.$type : undefined);
|
|
79
|
+
if (sqlType) {
|
|
80
|
+
propTypes.set(propName, sqlType.toLowerCase());
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (Array.isArray(nestedData)) {
|
|
84
|
+
transformed[alias] = nestedData.map((item) => this.transformNestedObject(item, dbToProp, propTypes));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
transformed[alias] = this.transformNestedObject(nestedData, dbToProp, propTypes);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return transformed;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
transformNestedObject(obj, dbToProp, propTypes) {
|
|
94
|
+
if (!obj || typeof obj !== 'object')
|
|
95
|
+
return obj;
|
|
96
|
+
const result = {};
|
|
97
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
98
|
+
const propName = dbToProp.get(key) ?? key;
|
|
99
|
+
result[propName] = propTypes ? this.coerceValue(value, propTypes.get(propName)) : value;
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
coerceValue(value, sqlType) {
|
|
104
|
+
if (value === null || value === undefined || !sqlType)
|
|
105
|
+
return value;
|
|
106
|
+
switch (sqlType) {
|
|
107
|
+
case 'timestamp':
|
|
108
|
+
case 'timestamptz':
|
|
109
|
+
case 'timestamp without time zone':
|
|
110
|
+
case 'timestamp with time zone':
|
|
111
|
+
return typeof value === 'string' ? new Date(value) : value;
|
|
112
|
+
case 'bigint':
|
|
113
|
+
case 'int8':
|
|
114
|
+
return typeof value === 'number' ? BigInt(value) : typeof value === 'string' ? BigInt(value) : value;
|
|
115
|
+
default:
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
where(callback) {
|
|
120
|
+
this.builder.where((q) => {
|
|
121
|
+
q._tables = (0, table_accessor_1.createTableAccessor)(this.relq, this.relq.schema);
|
|
122
|
+
return callback(q);
|
|
123
|
+
});
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
orderBy(column, direction) {
|
|
127
|
+
const dbColumn = this.relq[methods_1.INTERNAL].hasColumnMapping()
|
|
128
|
+
? Object.keys(this.relq[methods_1.INTERNAL].transformToDbColumns(this.tableName, { [column]: true }))[0]
|
|
129
|
+
: column;
|
|
130
|
+
this.builder.orderBy(dbColumn, direction);
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
orderByNulls(column, direction, nulls) {
|
|
134
|
+
const dbColumn = this.relq[methods_1.INTERNAL].hasColumnMapping()
|
|
135
|
+
? Object.keys(this.relq[methods_1.INTERNAL].transformToDbColumns(this.tableName, { [column]: true }))[0]
|
|
136
|
+
: column;
|
|
137
|
+
this.builder.orderByNulls(dbColumn, direction, nulls);
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
limit(count) {
|
|
141
|
+
this.builder.limit(count);
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
offset(count) {
|
|
145
|
+
this.builder.offset(count);
|
|
146
|
+
return this;
|
|
147
|
+
}
|
|
148
|
+
groupBy(...columns) {
|
|
149
|
+
const dbColumns = this.relq[methods_1.INTERNAL].hasColumnMapping()
|
|
150
|
+
? columns.map(col => Object.keys(this.relq[methods_1.INTERNAL].transformToDbColumns(this.tableName, { [col]: true }))[0])
|
|
151
|
+
: columns;
|
|
152
|
+
this.builder.groupBy(...dbColumns);
|
|
153
|
+
return this;
|
|
154
|
+
}
|
|
155
|
+
having(callback) {
|
|
156
|
+
this.builder.having(callback);
|
|
157
|
+
return this;
|
|
158
|
+
}
|
|
159
|
+
include(callback) {
|
|
160
|
+
const agg = new sql_expression_1.AggregateFunctions();
|
|
161
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
162
|
+
const schema = internal.getSchema() || {};
|
|
163
|
+
const sourceSchemaKey = this.schemaKey || this.tableName;
|
|
164
|
+
const sourceAlias = this.builder.getTableIdentifier();
|
|
165
|
+
const tableProxies = new Proxy({}, {
|
|
166
|
+
get(_, tableKey) {
|
|
167
|
+
if (typeof tableKey === 'symbol')
|
|
168
|
+
return undefined;
|
|
169
|
+
const tableDef = schema[tableKey];
|
|
170
|
+
const tableName = tableDef?.$name || tableKey;
|
|
171
|
+
const alias = tableKey === sourceSchemaKey ? sourceAlias : tableKey;
|
|
172
|
+
return (0, table_proxy_1.createTableProxy)(tableName, alias, tableDef);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
const expressions = callback(agg, tableProxies);
|
|
176
|
+
for (const [alias, expr] of Object.entries(expressions)) {
|
|
177
|
+
this.builder.addIncludeExpression(alias, expr.sql);
|
|
178
|
+
}
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
join(tableOrAlias, callback) {
|
|
182
|
+
(0, select_joins_1.executeTypeSafeJoin)(this.joinCtx, 'JOIN', tableOrAlias, callback);
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
leftJoin(tableOrAlias, callback) {
|
|
186
|
+
(0, select_joins_1.executeTypeSafeJoin)(this.joinCtx, 'LEFT JOIN', tableOrAlias, callback);
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
rightJoin(tableOrAlias, callback) {
|
|
190
|
+
(0, select_joins_1.executeTypeSafeJoin)(this.joinCtx, 'RIGHT JOIN', tableOrAlias, callback);
|
|
191
|
+
return this;
|
|
192
|
+
}
|
|
193
|
+
innerJoin(tableOrAlias, callback) {
|
|
194
|
+
(0, select_joins_1.executeTypeSafeJoin)(this.joinCtx, 'INNER JOIN', tableOrAlias, callback);
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
197
|
+
joinSubquery(alias, subquery, onClause) {
|
|
198
|
+
const subquerySQL = typeof subquery === 'string' ? subquery : subquery.toString();
|
|
199
|
+
this.builder.addRawJoin(`JOIN (${subquerySQL}) AS "${alias}" ON ${onClause}`);
|
|
200
|
+
return this;
|
|
201
|
+
}
|
|
202
|
+
leftJoinSubquery(alias, subquery, onClause) {
|
|
203
|
+
const subquerySQL = typeof subquery === 'string' ? subquery : subquery.toString();
|
|
204
|
+
this.builder.addRawJoin(`LEFT JOIN (${subquerySQL}) AS "${alias}" ON ${onClause}`);
|
|
205
|
+
return this;
|
|
206
|
+
}
|
|
207
|
+
joinMany(tableOrAlias, callbackOrOptions, throughCallback) {
|
|
208
|
+
(0, capability_guard_1.requireCapability)(this.relq, 'lateral', 'LATERAL JOIN (joinMany)', 'Use separate queries for one-to-many relationships');
|
|
209
|
+
if (callbackOrOptions && typeof callbackOrOptions === 'object' && 'through' in callbackOrOptions) {
|
|
210
|
+
(0, select_joins_1.executeTypeSafeJoinManyThrough)(this.joinCtx, 'JOIN', tableOrAlias, callbackOrOptions.through, throughCallback);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
(0, select_joins_1.executeTypeSafeJoinMany)(this.joinCtx, 'JOIN', tableOrAlias, callbackOrOptions);
|
|
214
|
+
}
|
|
215
|
+
return this;
|
|
216
|
+
}
|
|
217
|
+
leftJoinMany(tableOrAlias, callbackOrOptions, throughCallback) {
|
|
218
|
+
(0, capability_guard_1.requireCapability)(this.relq, 'lateral', 'LATERAL JOIN (leftJoinMany)', 'Use separate queries for one-to-many relationships');
|
|
219
|
+
if (callbackOrOptions && typeof callbackOrOptions === 'object' && 'through' in callbackOrOptions) {
|
|
220
|
+
(0, select_joins_1.executeTypeSafeJoinManyThrough)(this.joinCtx, 'LEFT JOIN', tableOrAlias, callbackOrOptions.through, throughCallback);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
(0, select_joins_1.executeTypeSafeJoinMany)(this.joinCtx, 'LEFT JOIN', tableOrAlias, callbackOrOptions);
|
|
224
|
+
}
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
227
|
+
with(table) {
|
|
228
|
+
(0, select_joins_1.executeTypeSafeJoin)(this.joinCtx, 'LEFT JOIN', table);
|
|
229
|
+
return this;
|
|
230
|
+
}
|
|
231
|
+
withMany(table, options) {
|
|
232
|
+
(0, capability_guard_1.requireCapability)(this.relq, 'lateral', 'LATERAL JOIN (withMany)', 'Use separate queries for one-to-many relationships');
|
|
233
|
+
if (options && 'through' in options) {
|
|
234
|
+
(0, select_joins_1.executeTypeSafeJoinManyThrough)(this.joinCtx, 'LEFT JOIN', table, options.through);
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
238
|
+
const schema = internal.getSchema();
|
|
239
|
+
const relations = internal.getRelations();
|
|
240
|
+
if (!schema || !relations) {
|
|
241
|
+
throw new Error(`Cannot use .withMany('${table}') without schema and relations config. ` +
|
|
242
|
+
`Use .leftJoinMany() with an explicit callback instead.`);
|
|
243
|
+
}
|
|
244
|
+
const sourceKey = this.schemaKey || this.tableName;
|
|
245
|
+
const fk = (0, fk_resolver_1.resolveForeignKey)(relations, schema, sourceKey, table);
|
|
246
|
+
if (!fk) {
|
|
247
|
+
throw new Error(`No FK relationship found between "${sourceKey}" and "${table}". ` +
|
|
248
|
+
`Use .leftJoinMany() with explicit join conditions instead.`);
|
|
249
|
+
}
|
|
250
|
+
(0, select_joins_1.executeTypeSafeJoinMany)(this.joinCtx, 'LEFT JOIN', table, (on, right, left) => {
|
|
251
|
+
const rightCol = right[fk.toColumn];
|
|
252
|
+
const leftCol = left[fk.fromColumn];
|
|
253
|
+
return on.equal(rightCol, leftCol);
|
|
254
|
+
});
|
|
255
|
+
return this;
|
|
256
|
+
}
|
|
257
|
+
distinct() {
|
|
258
|
+
this.builder.distinct();
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
distinctOn(...columns) {
|
|
262
|
+
(0, capability_guard_1.requireCapability)(this.relq, 'distinctOn', 'DISTINCT ON', 'Use GROUP BY with appropriate aggregation instead');
|
|
263
|
+
this.builder.distinctOn(...columns);
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
union(query) {
|
|
267
|
+
this.builder.union(typeof query === 'string' ? query : query.toString());
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
270
|
+
unionAll(query) {
|
|
271
|
+
this.builder.unionAll(typeof query === 'string' ? query : query.toString());
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
274
|
+
intersect(query) {
|
|
275
|
+
this.builder.intersect(typeof query === 'string' ? query : query.toString());
|
|
276
|
+
return this;
|
|
277
|
+
}
|
|
278
|
+
except(query) {
|
|
279
|
+
this.builder.except(typeof query === 'string' ? query : query.toString());
|
|
280
|
+
return this;
|
|
281
|
+
}
|
|
282
|
+
forUpdate() {
|
|
283
|
+
this.builder.forUpdate();
|
|
284
|
+
return this;
|
|
285
|
+
}
|
|
286
|
+
forUpdateSkipLocked() {
|
|
287
|
+
(0, capability_guard_1.requireCapability)(this.relq, 'forUpdateSkipLocked', 'FOR UPDATE SKIP LOCKED', 'Use FOR UPDATE without SKIP LOCKED');
|
|
288
|
+
this.builder.forUpdateSkipLocked();
|
|
289
|
+
return this;
|
|
290
|
+
}
|
|
291
|
+
forShare() {
|
|
292
|
+
this.builder.forShare();
|
|
293
|
+
return this;
|
|
294
|
+
}
|
|
295
|
+
toString() {
|
|
296
|
+
return this.builder.toString();
|
|
297
|
+
}
|
|
298
|
+
async all(withMetadata, _asRequired) {
|
|
299
|
+
const sql = this.builder.toString();
|
|
300
|
+
const result = await this.relq[methods_1.INTERNAL].executeSelect(sql, this.tableName);
|
|
301
|
+
const transformedData = this.transformJoinResults(result.data);
|
|
302
|
+
if (withMetadata) {
|
|
303
|
+
return { data: transformedData, metadata: result.metadata };
|
|
304
|
+
}
|
|
305
|
+
return transformedData;
|
|
306
|
+
}
|
|
307
|
+
async get(withMetadata, _asRequired) {
|
|
308
|
+
this.builder.limit(1);
|
|
309
|
+
const sql = this.builder.toString();
|
|
310
|
+
const result = await this.relq[methods_1.INTERNAL].executeSelectOne(sql, this.tableName);
|
|
311
|
+
const transformedData = result.data ? this.transformJoinResults([result.data])[0] : null;
|
|
312
|
+
if (withMetadata) {
|
|
313
|
+
return { data: transformedData, metadata: result.metadata };
|
|
314
|
+
}
|
|
315
|
+
return transformedData;
|
|
316
|
+
}
|
|
317
|
+
async value(column) {
|
|
318
|
+
this.builder.limit(1);
|
|
319
|
+
const sql = this.builder.toString();
|
|
320
|
+
const result = await this.relq[methods_1.INTERNAL].executeSelectOne(sql, this.tableName);
|
|
321
|
+
return result.data?.[column] ?? null;
|
|
322
|
+
}
|
|
323
|
+
async each(callback, options = {}) {
|
|
324
|
+
(0, capability_guard_1.requireCapability)(this.relq, 'cursors', 'Cursor-based iteration (each)', 'Use pagination() instead of each() for row-by-row processing');
|
|
325
|
+
return (0, select_pagination_1.executeCursorEach)(this.paginationCtx, callback, options);
|
|
326
|
+
}
|
|
327
|
+
async pagination(options) {
|
|
328
|
+
return (0, select_pagination_1.executePagination)(this.paginationCtx, options, (opts) => this.pagination(opts));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
exports.ConnectedSelectBuilder = ConnectedSelectBuilder;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransactionClient = void 0;
|
|
4
|
+
exports.executeTransaction = executeTransaction;
|
|
5
|
+
const ConnectedRawQueryBuilder_1 = require("./ConnectedRawQueryBuilder.cjs");
|
|
6
|
+
const table_accessor_1 = require("../shared/table-accessor.cjs");
|
|
7
|
+
const methods_1 = require("./methods.cjs");
|
|
8
|
+
class TransactionClient {
|
|
9
|
+
client;
|
|
10
|
+
relq;
|
|
11
|
+
schema;
|
|
12
|
+
constructor(client, relq) {
|
|
13
|
+
this.client = client;
|
|
14
|
+
this.relq = relq;
|
|
15
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
16
|
+
this.schema = internal.getSchema?.() ?? this.relq.schema;
|
|
17
|
+
}
|
|
18
|
+
get dialect() { return this.relq.dialect; }
|
|
19
|
+
get capabilities() { return this.relq.capabilities; }
|
|
20
|
+
get table() {
|
|
21
|
+
return (0, table_accessor_1.createTableAccessor)(this, this.schema);
|
|
22
|
+
}
|
|
23
|
+
raw(query, ...params) {
|
|
24
|
+
return new ConnectedRawQueryBuilder_1.ConnectedRawQueryBuilder(query, params, this);
|
|
25
|
+
}
|
|
26
|
+
get [methods_1.INTERNAL]() {
|
|
27
|
+
const parentInternal = this.relq[methods_1.INTERNAL];
|
|
28
|
+
const queryViaClient = async (sql) => {
|
|
29
|
+
const start = performance.now();
|
|
30
|
+
const pgResult = await this.client.query(sql);
|
|
31
|
+
return {
|
|
32
|
+
result: {
|
|
33
|
+
rows: pgResult.rows,
|
|
34
|
+
rowCount: pgResult.rowCount,
|
|
35
|
+
command: pgResult.command,
|
|
36
|
+
fields: pgResult.fields?.map((f) => ({ name: f.name, dataTypeID: f.dataTypeID })) ?? [],
|
|
37
|
+
},
|
|
38
|
+
duration: performance.now() - start,
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
const buildMetadata = (result, duration) => ({
|
|
42
|
+
rowCount: result.rowCount,
|
|
43
|
+
command: result.command,
|
|
44
|
+
duration,
|
|
45
|
+
fields: result.fields,
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
executeQuery: queryViaClient,
|
|
49
|
+
async executeSelect(sql, tableName) {
|
|
50
|
+
const { result, duration } = await queryViaClient(sql);
|
|
51
|
+
const rows = tableName
|
|
52
|
+
? parentInternal.transformResultsFromDb(tableName, result.rows)
|
|
53
|
+
: result.rows;
|
|
54
|
+
return { data: rows, metadata: buildMetadata(result, duration) };
|
|
55
|
+
},
|
|
56
|
+
async executeSelectOne(sql, tableName) {
|
|
57
|
+
const { result, duration } = await queryViaClient(sql);
|
|
58
|
+
const row = result.rows[0]
|
|
59
|
+
? (tableName ? parentInternal.transformFromDbColumns(tableName, result.rows[0]) : result.rows[0])
|
|
60
|
+
: null;
|
|
61
|
+
return { data: row, metadata: buildMetadata(result, duration) };
|
|
62
|
+
},
|
|
63
|
+
async executeCount(sql) {
|
|
64
|
+
const { result, duration } = await queryViaClient(sql);
|
|
65
|
+
const count = result.rows[0]?.count ? parseInt(result.rows[0].count, 10) : 0;
|
|
66
|
+
return { count, metadata: buildMetadata(result, duration) };
|
|
67
|
+
},
|
|
68
|
+
async executeRun(sql) {
|
|
69
|
+
const { result, duration } = await queryViaClient(sql);
|
|
70
|
+
return { success: true, metadata: buildMetadata(result, duration) };
|
|
71
|
+
},
|
|
72
|
+
transformToDbColumns: parentInternal.transformToDbColumns,
|
|
73
|
+
transformFromDbColumns: parentInternal.transformFromDbColumns,
|
|
74
|
+
transformResultsFromDb: parentInternal.transformResultsFromDb,
|
|
75
|
+
hasColumnMapping: parentInternal.hasColumnMapping,
|
|
76
|
+
validateData: parentInternal.validateData,
|
|
77
|
+
getSchema: parentInternal.getSchema,
|
|
78
|
+
getRelations: parentInternal.getRelations,
|
|
79
|
+
getTableDef: parentInternal.getTableDef,
|
|
80
|
+
getClientForCursor: async () => ({ client: this.client, release: () => { } }),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.TransactionClient = TransactionClient;
|
|
85
|
+
async function executeTransaction(relq, callback) {
|
|
86
|
+
await relq.ensureInitialized();
|
|
87
|
+
const { client, release } = await relq[methods_1.INTERNAL].getClientForCursor();
|
|
88
|
+
try {
|
|
89
|
+
await client.query('BEGIN');
|
|
90
|
+
const tx = new TransactionClient(client, relq);
|
|
91
|
+
const result = await callback(tx);
|
|
92
|
+
await client.query('COMMIT');
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
try {
|
|
97
|
+
await client.query('ROLLBACK');
|
|
98
|
+
}
|
|
99
|
+
catch { }
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
release();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConnectedUpdateBuilder = void 0;
|
|
4
|
+
const methods_1 = require("./methods.cjs");
|
|
5
|
+
const ReturningExecutor_1 = require("./ReturningExecutor.cjs");
|
|
6
|
+
const capability_guard_1 = require("./capability-guard.cjs");
|
|
7
|
+
const table_accessor_1 = require("../shared/table-accessor.cjs");
|
|
8
|
+
class ConnectedUpdateBuilder {
|
|
9
|
+
builder;
|
|
10
|
+
relq;
|
|
11
|
+
tableName;
|
|
12
|
+
schemaKey;
|
|
13
|
+
constructor(builder, relq, tableName, schemaKey) {
|
|
14
|
+
this.builder = builder;
|
|
15
|
+
this.relq = relq;
|
|
16
|
+
this.tableName = tableName;
|
|
17
|
+
this.schemaKey = schemaKey;
|
|
18
|
+
this.setupColumnResolver();
|
|
19
|
+
}
|
|
20
|
+
setupColumnResolver() {
|
|
21
|
+
if (!this.tableName && !this.schemaKey) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const internal = this.relq[methods_1.INTERNAL];
|
|
25
|
+
const tableDef = internal.getTableDef(this.schemaKey || this.tableName);
|
|
26
|
+
if (!tableDef) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const tableColumns = tableDef.$columns || tableDef;
|
|
30
|
+
this.builder.setColumnResolver((column) => {
|
|
31
|
+
const columnDef = tableColumns[column];
|
|
32
|
+
if (columnDef) {
|
|
33
|
+
return columnDef.$columnName || column;
|
|
34
|
+
}
|
|
35
|
+
return column;
|
|
36
|
+
});
|
|
37
|
+
this.builder.setColumnTypeResolver((column) => {
|
|
38
|
+
const columnDef = tableColumns[column];
|
|
39
|
+
if (!columnDef) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
const type = columnDef.$type;
|
|
43
|
+
if (typeof type !== 'string') {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const isArray = columnDef.$array === true;
|
|
47
|
+
const baseType = type.replace(/\[\]$/, '').toLowerCase();
|
|
48
|
+
return { type: baseType, isArray };
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
where(callback) {
|
|
52
|
+
this.builder.where((q) => {
|
|
53
|
+
q._tables = (0, table_accessor_1.createTableAccessor)(this.relq, this.relq.schema);
|
|
54
|
+
return callback(q);
|
|
55
|
+
});
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
toString() {
|
|
59
|
+
return this.builder.toString();
|
|
60
|
+
}
|
|
61
|
+
async run(withMetadata) {
|
|
62
|
+
this.relq[methods_1.INTERNAL].validateData(this.builder.tableName, this.builder.updateData, 'update');
|
|
63
|
+
const sql = this.builder.toString();
|
|
64
|
+
const result = await this.relq[methods_1.INTERNAL].executeRun(sql);
|
|
65
|
+
if (withMetadata) {
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
return result.metadata.rowCount ?? 0;
|
|
69
|
+
}
|
|
70
|
+
returning(columns) {
|
|
71
|
+
if (columns === null) {
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
(0, capability_guard_1.requireCapability)(this.relq, 'returning', 'RETURNING clause', 'Use a SELECT query after the UPDATE to retrieve modified data');
|
|
75
|
+
this.builder.returning(columns);
|
|
76
|
+
return new ReturningExecutor_1.ReturningExecutor(this.builder, this.relq, this.tableName, this.schemaKey);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.ConnectedUpdateBuilder = ConnectedUpdateBuilder;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PaginateBuilder = void 0;
|
|
4
|
+
const count_builder_1 = require("../../count/count-builder.cjs");
|
|
5
|
+
const relq_errors_1 = require("../../../shared/errors/relq-errors.cjs");
|
|
6
|
+
const select_builder_1 = require("../../select/select-builder.cjs");
|
|
7
|
+
const methods_1 = require("./methods.cjs");
|
|
8
|
+
class PaginateBuilder {
|
|
9
|
+
relq;
|
|
10
|
+
tableName;
|
|
11
|
+
columns;
|
|
12
|
+
whereClause;
|
|
13
|
+
orderByClause;
|
|
14
|
+
constructor(relq, tableName, columns, whereClause, orderByClause) {
|
|
15
|
+
this.relq = relq;
|
|
16
|
+
this.tableName = tableName;
|
|
17
|
+
this.columns = columns;
|
|
18
|
+
this.whereClause = whereClause;
|
|
19
|
+
this.orderByClause = orderByClause;
|
|
20
|
+
}
|
|
21
|
+
async paging(options) {
|
|
22
|
+
const page = options.page ?? 1;
|
|
23
|
+
const perPage = options.perPage;
|
|
24
|
+
const shouldCount = options.count ?? true;
|
|
25
|
+
if (page < 1) {
|
|
26
|
+
throw new relq_errors_1.RelqQueryError('page must be >= 1', { hint: 'Page numbers are 1-indexed' });
|
|
27
|
+
}
|
|
28
|
+
if (perPage < 1) {
|
|
29
|
+
throw new relq_errors_1.RelqQueryError('perPage must be >= 1');
|
|
30
|
+
}
|
|
31
|
+
const columnsToSelect = this.columns && this.columns.length > 0 ? this.columns : ['*'];
|
|
32
|
+
const orderByArr = this.orderByClause
|
|
33
|
+
? (Array.isArray(this.orderByClause[0]) ? this.orderByClause : [this.orderByClause])
|
|
34
|
+
: [];
|
|
35
|
+
const selectBuilder = new select_builder_1.SelectBuilder(this.tableName, columnsToSelect);
|
|
36
|
+
if (this.whereClause) {
|
|
37
|
+
selectBuilder.where(this.whereClause);
|
|
38
|
+
}
|
|
39
|
+
for (const [column, direction] of orderByArr) {
|
|
40
|
+
const dbColumn = this.relq[methods_1.INTERNAL].transformToDbColumns(this.tableName, { [column]: true });
|
|
41
|
+
selectBuilder.orderBy(Object.keys(dbColumn)[0] || column, direction);
|
|
42
|
+
}
|
|
43
|
+
let total = 0;
|
|
44
|
+
if (shouldCount) {
|
|
45
|
+
const countBuilder = new count_builder_1.CountBuilder(this.tableName);
|
|
46
|
+
if (this.whereClause) {
|
|
47
|
+
countBuilder.where(this.whereClause);
|
|
48
|
+
}
|
|
49
|
+
const countResult = await this.relq[methods_1.INTERNAL].executeCount(countBuilder.toString());
|
|
50
|
+
total = countResult.count;
|
|
51
|
+
}
|
|
52
|
+
const offset = (page - 1) * perPage;
|
|
53
|
+
selectBuilder.limit(perPage);
|
|
54
|
+
selectBuilder.offset(offset);
|
|
55
|
+
const result = await this.relq[methods_1.INTERNAL].executeSelect(selectBuilder.toString(), this.tableName);
|
|
56
|
+
const totalPages = Math.ceil(total / perPage);
|
|
57
|
+
const hasNext = page < totalPages;
|
|
58
|
+
const hasPrev = page > 1;
|
|
59
|
+
const pagination = {
|
|
60
|
+
page,
|
|
61
|
+
perPage,
|
|
62
|
+
total,
|
|
63
|
+
totalPages,
|
|
64
|
+
};
|
|
65
|
+
if (hasNext) {
|
|
66
|
+
pagination.hasNext = true;
|
|
67
|
+
pagination.nextPage = page + 1;
|
|
68
|
+
Object.defineProperty(pagination, 'loadNext', {
|
|
69
|
+
value: () => this.paging({ ...options, page: page + 1 }),
|
|
70
|
+
enumerable: false
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
pagination.hasNext = false;
|
|
75
|
+
}
|
|
76
|
+
if (hasPrev) {
|
|
77
|
+
pagination.hasPrev = true;
|
|
78
|
+
pagination.prevPage = page - 1;
|
|
79
|
+
Object.defineProperty(pagination, 'loadPrev', {
|
|
80
|
+
value: () => this.paging({ ...options, page: page - 1 }),
|
|
81
|
+
enumerable: false
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
pagination.hasPrev = false;
|
|
86
|
+
}
|
|
87
|
+
Object.defineProperty(pagination, 'toJSON', {
|
|
88
|
+
value: () => ({ page, perPage, total, totalPages, hasNext: pagination.hasNext, hasPrev: pagination.hasPrev, nextPage: pagination.nextPage, prevPage: pagination.prevPage }),
|
|
89
|
+
enumerable: false
|
|
90
|
+
});
|
|
91
|
+
return { data: result.data, pagination };
|
|
92
|
+
}
|
|
93
|
+
async offset(options) {
|
|
94
|
+
const position = options.position ?? 0;
|
|
95
|
+
const shouldCount = options.count ?? false;
|
|
96
|
+
if (position < 0) {
|
|
97
|
+
throw new relq_errors_1.RelqQueryError('position must be >= 0');
|
|
98
|
+
}
|
|
99
|
+
let limit;
|
|
100
|
+
if (options.shuffleLimit) {
|
|
101
|
+
const [min, max] = options.shuffleLimit;
|
|
102
|
+
if (min < 1 || max < 1) {
|
|
103
|
+
throw new relq_errors_1.RelqQueryError('shuffleLimit values must be >= 1', { hint: 'Use [min, max] where both are >= 1' });
|
|
104
|
+
}
|
|
105
|
+
if (min > max) {
|
|
106
|
+
throw new relq_errors_1.RelqQueryError('shuffleLimit[0] must be <= shuffleLimit[1]', { hint: 'Use [min, max] format where min <= max' });
|
|
107
|
+
}
|
|
108
|
+
limit = Math.floor(Math.random() * (max - min + 1)) + min;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const limitValue = options.limit;
|
|
112
|
+
if (limitValue !== undefined && limitValue < 1) {
|
|
113
|
+
throw new relq_errors_1.RelqQueryError('limit must be >= 1');
|
|
114
|
+
}
|
|
115
|
+
limit = limitValue ?? 50;
|
|
116
|
+
}
|
|
117
|
+
const columnsToSelect = this.columns && this.columns.length > 0 ? this.columns : ['*'];
|
|
118
|
+
const orderByArr = this.orderByClause
|
|
119
|
+
? (Array.isArray(this.orderByClause[0]) ? this.orderByClause : [this.orderByClause])
|
|
120
|
+
: [];
|
|
121
|
+
const selectBuilder = new select_builder_1.SelectBuilder(this.tableName, columnsToSelect);
|
|
122
|
+
if (this.whereClause) {
|
|
123
|
+
selectBuilder.where(this.whereClause);
|
|
124
|
+
}
|
|
125
|
+
for (const [column, direction] of orderByArr) {
|
|
126
|
+
const dbColumn = this.relq[methods_1.INTERNAL].transformToDbColumns(this.tableName, { [column]: true });
|
|
127
|
+
selectBuilder.orderBy(Object.keys(dbColumn)[0] || column, direction);
|
|
128
|
+
}
|
|
129
|
+
let total = 0;
|
|
130
|
+
if (shouldCount) {
|
|
131
|
+
const countBuilder = new count_builder_1.CountBuilder(this.tableName);
|
|
132
|
+
if (this.whereClause) {
|
|
133
|
+
countBuilder.where(this.whereClause);
|
|
134
|
+
}
|
|
135
|
+
const countResult = await this.relq[methods_1.INTERNAL].executeCount(countBuilder.toString());
|
|
136
|
+
total = countResult.count;
|
|
137
|
+
}
|
|
138
|
+
selectBuilder.limit(limit + 1);
|
|
139
|
+
selectBuilder.offset(position);
|
|
140
|
+
const result = await this.relq[methods_1.INTERNAL].executeSelect(selectBuilder.toString(), this.tableName);
|
|
141
|
+
const hasMore = result.data.length > limit;
|
|
142
|
+
const data = hasMore ? result.data.slice(0, limit) : result.data;
|
|
143
|
+
const hasPrev = position > 0;
|
|
144
|
+
const pagination = {
|
|
145
|
+
position,
|
|
146
|
+
limit,
|
|
147
|
+
total,
|
|
148
|
+
};
|
|
149
|
+
if (hasMore) {
|
|
150
|
+
pagination.hasMore = true;
|
|
151
|
+
pagination.nextPos = position + limit;
|
|
152
|
+
Object.defineProperty(pagination, 'loadNext', {
|
|
153
|
+
value: () => this.offset({ ...options, position: position + limit }),
|
|
154
|
+
enumerable: false
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
pagination.hasMore = false;
|
|
159
|
+
}
|
|
160
|
+
if (hasPrev) {
|
|
161
|
+
pagination.hasPrev = true;
|
|
162
|
+
pagination.prevPos = Math.max(0, position - limit);
|
|
163
|
+
Object.defineProperty(pagination, 'loadPrev', {
|
|
164
|
+
value: () => this.offset({ ...options, position: Math.max(0, position - limit) }),
|
|
165
|
+
enumerable: false
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
pagination.hasPrev = false;
|
|
170
|
+
}
|
|
171
|
+
Object.defineProperty(pagination, 'toJSON', {
|
|
172
|
+
value: () => ({ position, limit, total, hasMore: pagination.hasMore, hasPrev: pagination.hasPrev, nextPos: pagination.nextPos, prevPos: pagination.prevPos }),
|
|
173
|
+
enumerable: false
|
|
174
|
+
});
|
|
175
|
+
return { data, pagination };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.PaginateBuilder = PaginateBuilder;
|