@an5/orm 1.0.6 → 1.0.8
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/README.md +175 -147
- package/dist/an5Metadata.d.ts +10 -0
- package/dist/an5Metadata.js +29 -0
- package/dist/an5Orm.d.ts +4 -1
- package/dist/an5Orm.js +214 -409
- package/dist/config.d.ts +2 -0
- package/dist/config.js +24 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +16 -0
- package/dist/generator/src/code-generator.d.ts +13 -13
- package/dist/generator/src/code-generator.js +225 -225
- package/dist/generator/src/dotnet-generator.d.ts +11 -11
- package/dist/generator/src/dotnet-generator.js +546 -546
- package/dist/generator/src/index.d.ts +1 -1
- package/dist/generator/src/index.js +88 -88
- package/dist/generator/src/metadata-generator.d.ts +8 -8
- package/dist/generator/src/metadata-generator.js +90 -90
- package/dist/generator/src/parser.d.ts +11 -11
- package/dist/generator/src/parser.js +206 -206
- package/dist/generator/src/python-generator.d.ts +9 -9
- package/dist/generator/src/python-generator.js +105 -105
- package/dist/generator/src/types.d.ts +27 -27
- package/dist/generator/src/types.js +2 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5 -1
- package/dist/logger.d.ts +53 -0
- package/dist/logger.js +117 -0
- package/dist/metadata.d.ts +24 -0
- package/dist/metadata.js +15 -0
- package/dist/scripts/release-cli.d.ts +2 -2
- package/dist/scripts/release-cli.js +115 -115
- package/dist/sql-utils.d.ts +29 -0
- package/dist/sql-utils.js +220 -0
- package/generator/src/code-generator.ts +230 -234
- package/generator/src/dotnet-generator.ts +544 -544
- package/generator/src/index.ts +116 -95
- package/generator/src/metadata-generator.ts +101 -99
- package/generator/src/parser.ts +202 -202
- package/generator/src/python-generator.ts +114 -114
- package/generator/src/types.ts +29 -29
- package/package.json +5 -7
- package/dist/cleanup.d.ts +0 -2
- package/dist/cleanup.js +0 -120
- package/dist/cli.js +0 -64
- package/dist/migrate.d.ts +0 -11
- package/dist/migrate.js +0 -301
- package/dist/pull.d.ts +0 -2
- package/dist/pull.js +0 -339
- package/dist/push.d.ts +0 -2
- package/dist/push.js +0 -281
- package/dist/seed.d.ts +0 -2
- package/dist/seed.js +0 -401
package/dist/an5Orm.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.an5Orm = exports.An5ORM = void 0;
|
|
7
|
-
const
|
|
8
|
-
const an5_adapters_1 = require("@an5/adapters");
|
|
4
|
+
const adapters_1 = require("@an5/adapters");
|
|
9
5
|
const crypto_1 = require("crypto");
|
|
10
|
-
const logger_1 = require("
|
|
11
|
-
const
|
|
12
|
-
const
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
const errors_1 = require("./errors");
|
|
8
|
+
const metadata_1 = require("./metadata");
|
|
9
|
+
const sql_utils_1 = require("./sql-utils");
|
|
10
|
+
function aggSelect(fn, key) {
|
|
11
|
+
return `${fn}(${(0, sql_utils_1.quoteIdentifier)(key)}) as ${aggAlias(fn, key)}`;
|
|
12
|
+
}
|
|
13
|
+
function aggAlias(fn, key) {
|
|
14
|
+
return (0, sql_utils_1.sanitizeParamName)(`${fn}_${key}`);
|
|
15
|
+
}
|
|
13
16
|
let adapter = null;
|
|
14
17
|
async function getAdapter() {
|
|
15
18
|
if (!adapter) {
|
|
16
|
-
adapter = new
|
|
19
|
+
adapter = new adapters_1.An5Adapter({ connectionString: process.env.DATABASE_URL });
|
|
17
20
|
await adapter.$connect();
|
|
18
21
|
}
|
|
19
22
|
return adapter;
|
|
@@ -22,185 +25,6 @@ async function execQuery(queryText, params) {
|
|
|
22
25
|
const a = await getAdapter();
|
|
23
26
|
return a.exec(queryText, params);
|
|
24
27
|
}
|
|
25
|
-
function parseWhere(modelName, where, params, prefix = "") {
|
|
26
|
-
if (!where)
|
|
27
|
-
return "";
|
|
28
|
-
const conditions = [];
|
|
29
|
-
const cleanWhere = {};
|
|
30
|
-
for (const [key, value] of Object.entries(where)) {
|
|
31
|
-
if (key.includes("_") &&
|
|
32
|
-
value &&
|
|
33
|
-
typeof value === "object" &&
|
|
34
|
-
!(value instanceof Date) &&
|
|
35
|
-
!value.in &&
|
|
36
|
-
!value.contains &&
|
|
37
|
-
!value.not &&
|
|
38
|
-
!value.gte &&
|
|
39
|
-
!value.lte &&
|
|
40
|
-
!value.gt &&
|
|
41
|
-
!value.lt) {
|
|
42
|
-
Object.assign(cleanWhere, value);
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
cleanWhere[key] = value;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
for (const [key, value] of Object.entries(cleanWhere)) {
|
|
49
|
-
if (key === "OR" && Array.isArray(value)) {
|
|
50
|
-
const orConditions = value.map((subWhere, idx) => parseWhere(modelName, subWhere, params, `${prefix}or_${idx}_`));
|
|
51
|
-
const filtered = orConditions.filter(Boolean);
|
|
52
|
-
if (filtered.length > 0) {
|
|
53
|
-
conditions.push(`(${filtered.join(" OR ")})`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
else if (key === "AND" && Array.isArray(value)) {
|
|
57
|
-
const andConditions = value.map((subWhere, idx) => parseWhere(modelName, subWhere, params, `${prefix}and_${idx}_`));
|
|
58
|
-
const filtered = andConditions.filter(Boolean);
|
|
59
|
-
if (filtered.length > 0) {
|
|
60
|
-
conditions.push(`(${filtered.join(" AND ")})`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
const modelRelations = an5Metadata_1.relationMap[modelName];
|
|
65
|
-
const relation = modelRelations?.[key];
|
|
66
|
-
if (relation) {
|
|
67
|
-
// Relation subquery
|
|
68
|
-
const relationTable = an5Metadata_1.modelToTable[relation.modelName];
|
|
69
|
-
const subParams = {};
|
|
70
|
-
let subWhere = value;
|
|
71
|
-
let op = "some"; // default
|
|
72
|
-
if (value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
|
73
|
-
if (value.some) {
|
|
74
|
-
subWhere = value.some;
|
|
75
|
-
op = "some";
|
|
76
|
-
}
|
|
77
|
-
else if (value.none) {
|
|
78
|
-
subWhere = value.none;
|
|
79
|
-
op = "none";
|
|
80
|
-
}
|
|
81
|
-
else if (value.every) {
|
|
82
|
-
subWhere = value.every;
|
|
83
|
-
op = "every";
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
const subWhereSql = parseWhere(relation.modelName, subWhere, subParams, `${prefix}${key}_`);
|
|
87
|
-
Object.assign(params, subParams);
|
|
88
|
-
if (subWhereSql) {
|
|
89
|
-
if (relation.relationType === "one") {
|
|
90
|
-
if (op === "none") {
|
|
91
|
-
conditions.push(`${relation.foreignKey} NOT IN (SELECT ${relation.localKey} FROM ${relationTable} WITH (NOLOCK) WHERE ${subWhereSql})`);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
conditions.push(`${relation.foreignKey} IN (SELECT ${relation.localKey} FROM ${relationTable} WITH (NOLOCK) WHERE ${subWhereSql})`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
if (op === "none") {
|
|
99
|
-
conditions.push(`${relation.localKey} NOT IN (SELECT ${relation.foreignKey} FROM ${relationTable} WITH (NOLOCK) WHERE ${subWhereSql})`);
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
conditions.push(`${relation.localKey} IN (SELECT ${relation.foreignKey} FROM ${relationTable} WITH (NOLOCK) WHERE ${subWhereSql})`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
else {
|
|
108
|
-
const paramName = `${prefix}${key}`;
|
|
109
|
-
if (value && typeof value === "object" && !(value instanceof Date)) {
|
|
110
|
-
const ops = Object.entries(value);
|
|
111
|
-
for (const [op, opVal] of ops) {
|
|
112
|
-
if (op === "in" && Array.isArray(opVal)) {
|
|
113
|
-
if (opVal.length === 0) {
|
|
114
|
-
conditions.push("1 = 0");
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
const inParams = [];
|
|
118
|
-
opVal.forEach((item, idx) => {
|
|
119
|
-
const inParamName = `${paramName}_in_${idx}`;
|
|
120
|
-
inParams.push(`@${inParamName}`);
|
|
121
|
-
params[inParamName] = item;
|
|
122
|
-
});
|
|
123
|
-
conditions.push(`${key} IN (${inParams.join(", ")})`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
else if (op === "notIn" && Array.isArray(opVal)) {
|
|
127
|
-
if (opVal.length === 0) {
|
|
128
|
-
// NOT IN empty list is always true, but let's be safe
|
|
129
|
-
conditions.push("1 = 1");
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
const inParams = [];
|
|
133
|
-
opVal.forEach((item, idx) => {
|
|
134
|
-
const inParamName = `${paramName}_notin_${idx}`;
|
|
135
|
-
inParams.push(`@${inParamName}`);
|
|
136
|
-
params[inParamName] = item;
|
|
137
|
-
});
|
|
138
|
-
conditions.push(`${key} NOT IN (${inParams.join(", ")})`);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
else if (op === "contains") {
|
|
142
|
-
conditions.push(`${key} LIKE @${paramName}_contains`);
|
|
143
|
-
params[`${paramName}_contains`] = `%${opVal}%`;
|
|
144
|
-
}
|
|
145
|
-
else if (op === "startsWith") {
|
|
146
|
-
conditions.push(`${key} LIKE @${paramName}_startsWith`);
|
|
147
|
-
params[`${paramName}_startsWith`] = `${opVal}%`;
|
|
148
|
-
}
|
|
149
|
-
else if (op === "endsWith") {
|
|
150
|
-
conditions.push(`${key} LIKE @${paramName}_endsWith`);
|
|
151
|
-
params[`${paramName}_endsWith`] = `%${opVal}`;
|
|
152
|
-
}
|
|
153
|
-
else if (op === "not") {
|
|
154
|
-
conditions.push(`${key} <> @${paramName}_not`);
|
|
155
|
-
params[`${paramName}_not`] = opVal;
|
|
156
|
-
}
|
|
157
|
-
else if (op === "gte") {
|
|
158
|
-
conditions.push(`${key} >= @${paramName}_gte`);
|
|
159
|
-
params[`${paramName}_gte`] = opVal;
|
|
160
|
-
}
|
|
161
|
-
else if (op === "lte") {
|
|
162
|
-
conditions.push(`${key} <= @${paramName}_lte`);
|
|
163
|
-
params[`${paramName}_lte`] = opVal;
|
|
164
|
-
}
|
|
165
|
-
else if (op === "gt") {
|
|
166
|
-
conditions.push(`${key} > @${paramName}_gt`);
|
|
167
|
-
params[`${paramName}_gt`] = opVal;
|
|
168
|
-
}
|
|
169
|
-
else if (op === "lt") {
|
|
170
|
-
conditions.push(`${key} < @${paramName}_lt`);
|
|
171
|
-
params[`${paramName}_lt`] = opVal;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
if (value === null) {
|
|
177
|
-
conditions.push(`${key} IS NULL`);
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
conditions.push(`${key} = @${paramName}`);
|
|
181
|
-
params[paramName] = value;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return conditions.join(" AND ");
|
|
188
|
-
}
|
|
189
|
-
function buildOrderBy(orderBy) {
|
|
190
|
-
if (!orderBy)
|
|
191
|
-
return "";
|
|
192
|
-
const orderClauses = [];
|
|
193
|
-
const orderByArr = Array.isArray(orderBy) ? orderBy : [orderBy];
|
|
194
|
-
for (const orderObj of orderByArr) {
|
|
195
|
-
if (orderObj && typeof orderObj === "object") {
|
|
196
|
-
for (const [k, dir] of Object.entries(orderObj)) {
|
|
197
|
-
const dirStr = typeof dir === "string" ? dir.toUpperCase() : "ASC";
|
|
198
|
-
orderClauses.push(`${k} ${dirStr}`);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return orderClauses.length > 0 ? ` ORDER BY ` + orderClauses.join(", ") : "";
|
|
203
|
-
}
|
|
204
28
|
function projectFields(row, select) {
|
|
205
29
|
if (!row || !select)
|
|
206
30
|
return row;
|
|
@@ -216,10 +40,10 @@ function projectFields(row, select) {
|
|
|
216
40
|
return projected;
|
|
217
41
|
}
|
|
218
42
|
// Helper to batch-query and resolve relationships
|
|
219
|
-
async function resolveIncludes(modelName, rows, include, executor) {
|
|
43
|
+
async function resolveIncludes(modelName, rows, include, executor, metadata) {
|
|
220
44
|
if (!rows || rows.length === 0 || !include)
|
|
221
45
|
return;
|
|
222
|
-
const modelRelations =
|
|
46
|
+
const modelRelations = metadata.relationMap[modelName];
|
|
223
47
|
if (!modelRelations)
|
|
224
48
|
return;
|
|
225
49
|
for (const [key, value] of Object.entries(include)) {
|
|
@@ -232,17 +56,17 @@ async function resolveIncludes(modelName, rows, include, executor) {
|
|
|
232
56
|
for (const countField of countFields) {
|
|
233
57
|
const rel = modelRelations[countField];
|
|
234
58
|
if (rel) {
|
|
235
|
-
const relTable =
|
|
59
|
+
const relTable = metadata.modelToTable[rel.modelName];
|
|
236
60
|
const localKeys = rows.map(r => r[rel.localKey]).filter(Boolean);
|
|
237
61
|
if (localKeys.length === 0) {
|
|
238
62
|
rows.forEach(r => { r._count = { ...r._count, [countField]: 0 }; });
|
|
239
63
|
continue;
|
|
240
64
|
}
|
|
241
|
-
const sqlText = `
|
|
242
|
-
SELECT ${rel.foreignKey} as parentId, COUNT(*) as count
|
|
243
|
-
FROM ${relTable} WITH (NOLOCK)
|
|
244
|
-
WHERE ${rel.foreignKey} IN (${localKeys.map((_, i) => `@lk_${i}`).join(", ")})
|
|
245
|
-
GROUP BY ${rel.foreignKey}
|
|
65
|
+
const sqlText = `
|
|
66
|
+
SELECT ${(0, sql_utils_1.quoteIdentifier)(rel.foreignKey)} as parentId, COUNT(*) as count
|
|
67
|
+
FROM ${relTable} WITH (NOLOCK)
|
|
68
|
+
WHERE ${(0, sql_utils_1.quoteIdentifier)(rel.foreignKey)} IN (${localKeys.map((_, i) => `@lk_${i}`).join(", ")})
|
|
69
|
+
GROUP BY ${(0, sql_utils_1.quoteIdentifier)(rel.foreignKey)}
|
|
246
70
|
`;
|
|
247
71
|
const countParams = {};
|
|
248
72
|
localKeys.forEach((lk, i) => { countParams[`lk_${i}`] = lk; });
|
|
@@ -258,7 +82,7 @@ async function resolveIncludes(modelName, rows, include, executor) {
|
|
|
258
82
|
}
|
|
259
83
|
continue;
|
|
260
84
|
}
|
|
261
|
-
const relTable =
|
|
85
|
+
const relTable = metadata.modelToTable[relation.modelName];
|
|
262
86
|
const isMany = relation.relationType === "many";
|
|
263
87
|
const matchKey = relation.relationType === "one" ? relation.foreignKey : relation.localKey;
|
|
264
88
|
const searchKey = relation.relationType === "one" ? relation.localKey : relation.foreignKey;
|
|
@@ -271,24 +95,25 @@ async function resolveIncludes(modelName, rows, include, executor) {
|
|
|
271
95
|
let relCols = "*";
|
|
272
96
|
if (value && typeof value === "object" && value.select) {
|
|
273
97
|
const subSelect = value.select;
|
|
274
|
-
const subRelations =
|
|
98
|
+
const subRelations = metadata.relationMap[relation.modelName] || {};
|
|
275
99
|
const selectedSubCols = Object.keys(subSelect)
|
|
276
100
|
.filter(k => subSelect[k] && !subRelations[k])
|
|
277
|
-
.map(k =>
|
|
101
|
+
.map(k => (0, sql_utils_1.quoteIdentifier)(k));
|
|
278
102
|
if (selectedSubCols.length > 0) {
|
|
279
|
-
|
|
280
|
-
|
|
103
|
+
const quotedSearchKey = (0, sql_utils_1.quoteIdentifier)(searchKey);
|
|
104
|
+
if (!selectedSubCols.includes(quotedSearchKey)) {
|
|
105
|
+
selectedSubCols.push(quotedSearchKey);
|
|
281
106
|
}
|
|
282
107
|
relCols = selectedSubCols.join(", ");
|
|
283
108
|
}
|
|
284
109
|
}
|
|
285
|
-
let sqlText = `SELECT ${relCols} FROM ${relTable} WITH (NOLOCK) WHERE ${searchKey} IN (${uniqueKeys.map((_, i) => `@k_${i}`).join(", ")})`;
|
|
110
|
+
let sqlText = `SELECT ${relCols} FROM ${relTable} WITH (NOLOCK) WHERE ${(0, sql_utils_1.quoteIdentifier)(searchKey)} IN (${uniqueKeys.map((_, i) => `@k_${i}`).join(", ")})`;
|
|
286
111
|
const subParams = {};
|
|
287
112
|
uniqueKeys.forEach((k, i) => { subParams[`k_${i}`] = k; });
|
|
288
113
|
if (value && typeof value === "object") {
|
|
289
114
|
const subArgs = value;
|
|
290
115
|
if (subArgs.orderBy) {
|
|
291
|
-
sqlText += buildOrderBy(subArgs.orderBy);
|
|
116
|
+
sqlText += (0, sql_utils_1.buildOrderBy)(subArgs.orderBy);
|
|
292
117
|
}
|
|
293
118
|
}
|
|
294
119
|
const relatedRows = await executor(sqlText, subParams);
|
|
@@ -298,7 +123,7 @@ async function resolveIncludes(modelName, rows, include, executor) {
|
|
|
298
123
|
});
|
|
299
124
|
}
|
|
300
125
|
if (value && typeof value === "object" && value.include) {
|
|
301
|
-
await resolveIncludes(relation.modelName, relatedRows, value.include, executor);
|
|
126
|
+
await resolveIncludes(relation.modelName, relatedRows, value.include, executor, metadata);
|
|
302
127
|
}
|
|
303
128
|
const groupMap = new Map();
|
|
304
129
|
relatedRows.forEach((r) => {
|
|
@@ -333,35 +158,35 @@ class TableClient {
|
|
|
333
158
|
const hasSkip = finalArgs?.skip !== undefined && finalArgs?.skip !== null;
|
|
334
159
|
let cols = "*";
|
|
335
160
|
if (finalArgs?.select) {
|
|
336
|
-
const modelRelations =
|
|
161
|
+
const modelRelations = this.orm.metadata.relationMap[this.modelName] || {};
|
|
337
162
|
const selectedCols = Object.keys(finalArgs.select)
|
|
338
163
|
.filter(k => finalArgs.select[k] && !modelRelations[k])
|
|
339
|
-
.map(k =>
|
|
164
|
+
.map(k => (0, sql_utils_1.quoteIdentifier)(k));
|
|
340
165
|
if (selectedCols.length > 0) {
|
|
341
166
|
cols = selectedCols.join(", ");
|
|
342
167
|
}
|
|
343
168
|
}
|
|
344
169
|
let sqlText = "SELECT";
|
|
345
170
|
if (finalArgs?.take && !hasSkip) {
|
|
346
|
-
sqlText += ` TOP (${finalArgs.take})`;
|
|
171
|
+
sqlText += ` TOP (${(0, sql_utils_1.toNonNegativeInt)(finalArgs.take, 1)})`;
|
|
347
172
|
}
|
|
348
173
|
sqlText += ` ${cols} FROM ${this.tableName} WITH (NOLOCK)`;
|
|
349
174
|
const p = {};
|
|
350
|
-
const whereSql = parseWhere(this.modelName, finalArgs?.where, p);
|
|
175
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs?.where, p);
|
|
351
176
|
if (whereSql) {
|
|
352
177
|
sqlText += ` WHERE ${whereSql}`;
|
|
353
178
|
}
|
|
354
179
|
if (finalArgs?.orderBy) {
|
|
355
|
-
sqlText += buildOrderBy(finalArgs.orderBy);
|
|
180
|
+
sqlText += (0, sql_utils_1.buildOrderBy)(finalArgs.orderBy);
|
|
356
181
|
}
|
|
357
182
|
else if (hasSkip) {
|
|
358
183
|
// OFFSET requires an ORDER BY clause in SQL Server
|
|
359
184
|
sqlText += " ORDER BY (SELECT NULL)";
|
|
360
185
|
}
|
|
361
186
|
if (hasSkip) {
|
|
362
|
-
sqlText += ` OFFSET ${finalArgs.skip} ROWS`;
|
|
187
|
+
sqlText += ` OFFSET ${(0, sql_utils_1.toNonNegativeInt)(finalArgs.skip)} ROWS`;
|
|
363
188
|
if (finalArgs?.take) {
|
|
364
|
-
sqlText += ` FETCH NEXT ${finalArgs.take} ROWS ONLY`;
|
|
189
|
+
sqlText += ` FETCH NEXT ${(0, sql_utils_1.toNonNegativeInt)(finalArgs.take, 1)} ROWS ONLY`;
|
|
365
190
|
}
|
|
366
191
|
}
|
|
367
192
|
const rows = await this.executor(sqlText, p);
|
|
@@ -371,7 +196,7 @@ class TableClient {
|
|
|
371
196
|
});
|
|
372
197
|
}
|
|
373
198
|
if (finalArgs?.include) {
|
|
374
|
-
await resolveIncludes(this.modelName, rows, finalArgs.include, this.executor);
|
|
199
|
+
await resolveIncludes(this.modelName, rows, finalArgs.include, this.executor, this.orm.metadata);
|
|
375
200
|
}
|
|
376
201
|
return rows;
|
|
377
202
|
});
|
|
@@ -392,7 +217,7 @@ class TableClient {
|
|
|
392
217
|
const { args: finalArgs } = params;
|
|
393
218
|
let sqlText = `SELECT COUNT(*) as count FROM ${this.tableName} WITH (NOLOCK)`;
|
|
394
219
|
const p = {};
|
|
395
|
-
const whereSql = parseWhere(this.modelName, finalArgs?.where, p);
|
|
220
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs?.where, p);
|
|
396
221
|
if (whereSql) {
|
|
397
222
|
sqlText += ` WHERE ${whereSql}`;
|
|
398
223
|
}
|
|
@@ -401,7 +226,7 @@ class TableClient {
|
|
|
401
226
|
});
|
|
402
227
|
}
|
|
403
228
|
async handleNestedWrites(data, parentId) {
|
|
404
|
-
const modelRelations =
|
|
229
|
+
const modelRelations = this.orm.metadata.relationMap[this.modelName] || {};
|
|
405
230
|
for (const [key, value] of Object.entries(data)) {
|
|
406
231
|
const relation = modelRelations[key];
|
|
407
232
|
if (!relation || !value || typeof value !== "object" || (value instanceof Date))
|
|
@@ -447,20 +272,20 @@ class TableClient {
|
|
|
447
272
|
const data = { ...finalArgs.data };
|
|
448
273
|
// Extract nested writes
|
|
449
274
|
const nestedData = {};
|
|
450
|
-
const modelRelations =
|
|
275
|
+
const modelRelations = this.orm.metadata.relationMap[this.modelName] || {};
|
|
451
276
|
for (const key of Object.keys(data)) {
|
|
452
277
|
if (modelRelations[key]) {
|
|
453
278
|
nestedData[key] = data[key];
|
|
454
279
|
delete data[key];
|
|
455
280
|
}
|
|
456
281
|
}
|
|
457
|
-
if (!data.id &&
|
|
282
|
+
if (!data.id && this.orm.metadata.modelFields[this.modelName]?.id?.ts === "string") {
|
|
458
283
|
data.id = (0, crypto_1.randomUUID)();
|
|
459
284
|
}
|
|
460
285
|
const now = new Date();
|
|
461
|
-
if (!data.createdAt &&
|
|
286
|
+
if (!data.createdAt && this.orm.metadata.modelFields[this.modelName]?.createdAt)
|
|
462
287
|
data.createdAt = now;
|
|
463
|
-
if (!data.updatedAt &&
|
|
288
|
+
if (!data.updatedAt && this.orm.metadata.modelFields[this.modelName]?.updatedAt)
|
|
464
289
|
data.updatedAt = now;
|
|
465
290
|
// Handle one-relation connect where we hold the FK
|
|
466
291
|
for (const [key, value] of Object.entries(nestedData)) {
|
|
@@ -472,10 +297,13 @@ class TableClient {
|
|
|
472
297
|
}
|
|
473
298
|
}
|
|
474
299
|
const keys = Object.keys(data);
|
|
475
|
-
const columns = keys.map(k =>
|
|
476
|
-
const
|
|
300
|
+
const columns = keys.map(k => (0, sql_utils_1.quoteIdentifier)(k)).join(", ");
|
|
301
|
+
const safeKeys = keys.map(k => (0, sql_utils_1.sanitizeParamName)(k));
|
|
302
|
+
const placeholders = safeKeys.map(k => `@${k}`).join(", ");
|
|
303
|
+
const safeData = {};
|
|
304
|
+
keys.forEach((k, i) => { safeData[safeKeys[i]] = data[k]; });
|
|
477
305
|
const sqlText = `INSERT INTO ${this.tableName} (${columns}) OUTPUT inserted.* VALUES (${placeholders})`;
|
|
478
|
-
const rows = await this.executor(sqlText,
|
|
306
|
+
const rows = await this.executor(sqlText, safeData);
|
|
479
307
|
const createdRow = rows[0];
|
|
480
308
|
if (!createdRow) {
|
|
481
309
|
throw new Error("Failed to insert record and retrieve output");
|
|
@@ -500,19 +328,19 @@ class TableClient {
|
|
|
500
328
|
msg.includes('unique') ||
|
|
501
329
|
errNumber === 2627 ||
|
|
502
330
|
errNumber === 2601) {
|
|
503
|
-
throw new
|
|
331
|
+
throw new errors_1.An5ClientKnownRequestError("Unique constraint failed", {
|
|
504
332
|
code: "P2002",
|
|
505
333
|
clientVersion: "mock",
|
|
506
334
|
});
|
|
507
335
|
}
|
|
508
336
|
if (msg.includes('foreign key') || errNumber === 547) {
|
|
509
|
-
throw new
|
|
337
|
+
throw new errors_1.An5ClientKnownRequestError("Foreign key constraint failed", {
|
|
510
338
|
code: "P2003",
|
|
511
339
|
clientVersion: "mock",
|
|
512
340
|
});
|
|
513
341
|
}
|
|
514
342
|
if (msg.includes('not found') || errNumber === 404) {
|
|
515
|
-
throw new
|
|
343
|
+
throw new errors_1.An5ClientKnownRequestError("Record not found", {
|
|
516
344
|
code: "P2025",
|
|
517
345
|
clientVersion: "mock",
|
|
518
346
|
});
|
|
@@ -525,12 +353,12 @@ class TableClient {
|
|
|
525
353
|
return this.orm._executeMiddleware({ model: this.modelName, action: 'update', args }, async (params) => {
|
|
526
354
|
const { args: finalArgs } = params;
|
|
527
355
|
const data = { ...finalArgs.data };
|
|
528
|
-
if (
|
|
356
|
+
if (this.orm.metadata.modelFields[this.modelName]?.updatedAt) {
|
|
529
357
|
data.updatedAt = new Date();
|
|
530
358
|
}
|
|
531
359
|
// Extract nested writes
|
|
532
360
|
const nestedData = {};
|
|
533
|
-
const modelRelations =
|
|
361
|
+
const modelRelations = this.orm.metadata.relationMap[this.modelName] || {};
|
|
534
362
|
for (const key of Object.keys(data)) {
|
|
535
363
|
if (modelRelations[key]) {
|
|
536
364
|
nestedData[key] = data[key];
|
|
@@ -551,28 +379,30 @@ class TableClient {
|
|
|
551
379
|
const p = {};
|
|
552
380
|
for (const key of Object.keys(data)) {
|
|
553
381
|
const val = data[key];
|
|
382
|
+
const col = (0, sql_utils_1.quoteIdentifier)(key);
|
|
383
|
+
const safeKey = (0, sql_utils_1.sanitizeParamName)(key);
|
|
554
384
|
if (val && typeof val === "object" && !(val instanceof Date)) {
|
|
555
385
|
if (val.increment !== undefined) {
|
|
556
|
-
sets.push(
|
|
557
|
-
p[`${
|
|
386
|
+
sets.push(`${col} = ${col} + @${safeKey}_inc`);
|
|
387
|
+
p[`${safeKey}_inc`] = val.increment;
|
|
558
388
|
continue;
|
|
559
389
|
}
|
|
560
390
|
else if (val.decrement !== undefined) {
|
|
561
|
-
sets.push(
|
|
562
|
-
p[`${
|
|
391
|
+
sets.push(`${col} = ${col} - @${safeKey}_dec`);
|
|
392
|
+
p[`${safeKey}_dec`] = val.decrement;
|
|
563
393
|
continue;
|
|
564
394
|
}
|
|
565
395
|
else if (val.set !== undefined) {
|
|
566
|
-
sets.push(
|
|
567
|
-
p[`${
|
|
396
|
+
sets.push(`${col} = @${safeKey}_set`);
|
|
397
|
+
p[`${safeKey}_set`] = val.set;
|
|
568
398
|
continue;
|
|
569
399
|
}
|
|
570
400
|
}
|
|
571
|
-
sets.push(
|
|
572
|
-
p[
|
|
401
|
+
sets.push(`${col} = @${safeKey}`);
|
|
402
|
+
p[safeKey] = val;
|
|
573
403
|
}
|
|
574
404
|
const whereParams = {};
|
|
575
|
-
const whereSql = parseWhere(this.modelName, finalArgs.where, whereParams, "w_");
|
|
405
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs.where, whereParams, "w_");
|
|
576
406
|
Object.assign(p, whereParams);
|
|
577
407
|
const sqlText = `UPDATE ${this.tableName} SET ${sets.join(", ")} WHERE ${whereSql}`;
|
|
578
408
|
await this.executor(sqlText, p);
|
|
@@ -594,7 +424,7 @@ class TableClient {
|
|
|
594
424
|
return this.orm._executeMiddleware({ model: this.modelName, action: 'updateMany', args }, async (params) => {
|
|
595
425
|
const { args: finalArgs } = params;
|
|
596
426
|
const data = { ...finalArgs.data };
|
|
597
|
-
if (
|
|
427
|
+
if (this.orm.metadata.modelFields[this.modelName]?.updatedAt) {
|
|
598
428
|
data.updatedAt = new Date();
|
|
599
429
|
}
|
|
600
430
|
delete data.id;
|
|
@@ -602,39 +432,36 @@ class TableClient {
|
|
|
602
432
|
const p = {};
|
|
603
433
|
for (const key of Object.keys(data)) {
|
|
604
434
|
const val = data[key];
|
|
605
|
-
if (
|
|
435
|
+
if (this.orm.metadata.relationMap[this.modelName]?.[key])
|
|
606
436
|
continue;
|
|
437
|
+
const col = (0, sql_utils_1.quoteIdentifier)(key);
|
|
438
|
+
const safeKey = (0, sql_utils_1.sanitizeParamName)(key);
|
|
607
439
|
if (val && typeof val === "object" && !(val instanceof Date)) {
|
|
608
440
|
if (val.increment !== undefined) {
|
|
609
|
-
sets.push(
|
|
610
|
-
p[`${
|
|
441
|
+
sets.push(`${col} = ${col} + @${safeKey}_inc`);
|
|
442
|
+
p[`${safeKey}_inc`] = val.increment;
|
|
611
443
|
continue;
|
|
612
444
|
}
|
|
613
445
|
else if (val.decrement !== undefined) {
|
|
614
|
-
sets.push(
|
|
615
|
-
p[`${
|
|
446
|
+
sets.push(`${col} = ${col} - @${safeKey}_dec`);
|
|
447
|
+
p[`${safeKey}_dec`] = val.decrement;
|
|
616
448
|
continue;
|
|
617
449
|
}
|
|
618
450
|
else if (val.set !== undefined) {
|
|
619
|
-
sets.push(
|
|
620
|
-
p[`${
|
|
451
|
+
sets.push(`${col} = @${safeKey}_set`);
|
|
452
|
+
p[`${safeKey}_set`] = val.set;
|
|
621
453
|
continue;
|
|
622
454
|
}
|
|
623
455
|
}
|
|
624
|
-
sets.push(
|
|
625
|
-
p[
|
|
456
|
+
sets.push(`${col} = @${safeKey}`);
|
|
457
|
+
p[safeKey] = val;
|
|
626
458
|
}
|
|
627
459
|
const whereParams = {};
|
|
628
|
-
const whereSql = parseWhere(this.modelName, finalArgs.where, whereParams, "w_");
|
|
460
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs.where, whereParams, "w_");
|
|
629
461
|
Object.assign(p, whereParams);
|
|
630
462
|
const sqlText = `UPDATE ${this.tableName} SET ${sets.join(", ")} ${whereSql ? `WHERE ${whereSql}` : ""}`;
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
for (const [key, value] of Object.entries(p)) {
|
|
634
|
-
request.input(key, value);
|
|
635
|
-
}
|
|
636
|
-
const result = await request.query(sqlText);
|
|
637
|
-
return { count: result.rowsAffected?.[0] || 0 };
|
|
463
|
+
const count = await (await getAdapter())._executeRaw(sqlText, p);
|
|
464
|
+
return { count };
|
|
638
465
|
});
|
|
639
466
|
}
|
|
640
467
|
async delete(args) {
|
|
@@ -644,7 +471,7 @@ class TableClient {
|
|
|
644
471
|
if (!existing)
|
|
645
472
|
throw new Error("Record not found to delete");
|
|
646
473
|
const p = {};
|
|
647
|
-
const whereSql = parseWhere(this.modelName, finalArgs.where, p);
|
|
474
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs.where, p);
|
|
648
475
|
const sqlText = `DELETE FROM ${this.tableName} WHERE ${whereSql}`;
|
|
649
476
|
await this.executor(sqlText, p);
|
|
650
477
|
return existing;
|
|
@@ -654,39 +481,37 @@ class TableClient {
|
|
|
654
481
|
return this.orm._executeMiddleware({ model: this.modelName, action: 'deleteMany', args }, async (params) => {
|
|
655
482
|
const { args: finalArgs } = params;
|
|
656
483
|
const p = {};
|
|
657
|
-
const whereSql = parseWhere(this.modelName, finalArgs?.where, p);
|
|
484
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs?.where, p);
|
|
658
485
|
const sqlText = `DELETE FROM ${this.tableName} ${whereSql ? `WHERE ${whereSql}` : ""}`;
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
for (const [key, value] of Object.entries(p)) {
|
|
662
|
-
request.input(key, value);
|
|
663
|
-
}
|
|
664
|
-
const result = await request.query(sqlText);
|
|
665
|
-
return { count: result.rowsAffected?.[0] || 0 };
|
|
486
|
+
const count = await (await getAdapter())._executeRaw(sqlText, p);
|
|
487
|
+
return { count };
|
|
666
488
|
});
|
|
667
489
|
}
|
|
668
490
|
async vectorSearch(args) {
|
|
669
491
|
return this.orm._executeMiddleware({ model: this.modelName, action: 'vectorSearch', args }, async (params) => {
|
|
670
492
|
const { args: finalArgs } = params;
|
|
671
493
|
const field = finalArgs.vectorField || "embedding";
|
|
672
|
-
const
|
|
673
|
-
const
|
|
674
|
-
const
|
|
675
|
-
const
|
|
494
|
+
const METRICS = ["cosine", "euclidean", "dot"];
|
|
495
|
+
const ELEMENT_TYPES = ["float32", "float16", "uint8"];
|
|
496
|
+
const metric = METRICS.includes(finalArgs.distanceMetric) ? finalArgs.distanceMetric : "cosine";
|
|
497
|
+
const elementType = ELEMENT_TYPES.includes(finalArgs.vectorElementType) ? finalArgs.vectorElementType : "float32";
|
|
498
|
+
const take = (0, sql_utils_1.toNonNegativeInt)(finalArgs.take, 10);
|
|
499
|
+
const dim = Number(finalArgs.vector?.length) || 0;
|
|
676
500
|
const vectorJson = JSON.stringify(finalArgs.vector);
|
|
501
|
+
const col = (0, sql_utils_1.quoteIdentifier)(field);
|
|
677
502
|
try {
|
|
678
503
|
if (dim > 1998) {
|
|
679
504
|
throw new Error("Vector dimension exceeds SQL Server limit of 1998");
|
|
680
505
|
}
|
|
681
506
|
let sqlText = `SELECT TOP (${take}) *, `;
|
|
682
|
-
sqlText += `VECTOR_DISTANCE('${metric}', CAST(
|
|
507
|
+
sqlText += `VECTOR_DISTANCE('${metric}', CAST(${col} AS VECTOR(${dim}, ${elementType})), CAST(@query_vector AS VECTOR(${dim}, ${elementType}))) AS distance `;
|
|
683
508
|
sqlText += `FROM ${this.tableName} WITH (NOLOCK) `;
|
|
684
509
|
const p = {
|
|
685
510
|
query_vector: vectorJson
|
|
686
511
|
};
|
|
687
512
|
const whereClauses = [];
|
|
688
|
-
whereClauses.push(
|
|
689
|
-
const whereSql = parseWhere(this.modelName, finalArgs.where, p, "v_");
|
|
513
|
+
whereClauses.push(`${col} IS NOT NULL`);
|
|
514
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs.where, p, "v_");
|
|
690
515
|
if (whereSql) {
|
|
691
516
|
whereClauses.push(whereSql);
|
|
692
517
|
}
|
|
@@ -694,7 +519,7 @@ class TableClient {
|
|
|
694
519
|
sqlText += `ORDER BY distance ASC`;
|
|
695
520
|
const rows = await this.executor(sqlText, p);
|
|
696
521
|
if (finalArgs.include) {
|
|
697
|
-
await resolveIncludes(this.modelName, rows, finalArgs.include, this.executor);
|
|
522
|
+
await resolveIncludes(this.modelName, rows, finalArgs.include, this.executor, this.orm.metadata);
|
|
698
523
|
}
|
|
699
524
|
return rows;
|
|
700
525
|
}
|
|
@@ -716,8 +541,8 @@ class TableClient {
|
|
|
716
541
|
let fallbackSql = `SELECT * FROM ${this.tableName} WITH (NOLOCK) `;
|
|
717
542
|
const fallbackParams = {};
|
|
718
543
|
const fallbackWhereClauses = [];
|
|
719
|
-
fallbackWhereClauses.push(
|
|
720
|
-
const fallbackWhereSql = parseWhere(this.modelName, finalArgs.where, fallbackParams, "vf_");
|
|
544
|
+
fallbackWhereClauses.push(`${col} IS NOT NULL`);
|
|
545
|
+
const fallbackWhereSql = this.orm.parseWhere(this.modelName, finalArgs.where, fallbackParams, "vf_");
|
|
721
546
|
if (fallbackWhereSql) {
|
|
722
547
|
fallbackWhereClauses.push(fallbackWhereSql);
|
|
723
548
|
}
|
|
@@ -754,7 +579,7 @@ class TableClient {
|
|
|
754
579
|
.sort((a, b) => a.distance - b.distance)
|
|
755
580
|
.slice(0, take);
|
|
756
581
|
if (finalArgs.include && results.length > 0) {
|
|
757
|
-
await resolveIncludes(this.modelName, results, finalArgs.include, this.executor);
|
|
582
|
+
await resolveIncludes(this.modelName, results, finalArgs.include, this.executor, this.orm.metadata);
|
|
758
583
|
}
|
|
759
584
|
return results;
|
|
760
585
|
}
|
|
@@ -766,42 +591,10 @@ class TableClient {
|
|
|
766
591
|
if (!finalArgs.data || finalArgs.data.length === 0)
|
|
767
592
|
return { count: 0 };
|
|
768
593
|
try {
|
|
769
|
-
const
|
|
770
|
-
const table = new mssql_1.default.Table(this.tableName);
|
|
771
|
-
const fields = an5Metadata_1.modelFields[this.modelName] || {};
|
|
594
|
+
const fields = this.orm.metadata.modelFields[this.modelName] || {};
|
|
772
595
|
const fieldNames = Object.keys(fields);
|
|
773
|
-
for (const col of fieldNames) {
|
|
774
|
-
const fieldDef = fields[col];
|
|
775
|
-
const rawType = fieldDef?.ts || 'string';
|
|
776
|
-
const sqlType = fieldDef?.sql || 'NVARCHAR(MAX)';
|
|
777
|
-
const isNullable = rawType.endsWith('?');
|
|
778
|
-
const tsType = isNullable ? rawType.slice(0, -1) : rawType;
|
|
779
|
-
// Map SQL Server type to mssql package type
|
|
780
|
-
const sqlBase = sqlType.toUpperCase().split('(')[0];
|
|
781
|
-
if (sqlBase === 'INT' || sqlBase === 'SMALLINT' || sqlBase === 'TINYINT') {
|
|
782
|
-
table.columns.add(col, mssql_1.default.Int, { nullable: isNullable });
|
|
783
|
-
}
|
|
784
|
-
else if (sqlBase === 'BIGINT') {
|
|
785
|
-
table.columns.add(col, mssql_1.default.BigInt, { nullable: isNullable });
|
|
786
|
-
}
|
|
787
|
-
else if (sqlBase === 'FLOAT' || sqlBase === 'REAL' || sqlBase === 'DECIMAL' || sqlBase === 'NUMERIC' || sqlBase === 'MONEY' || sqlBase === 'SMALLMONEY') {
|
|
788
|
-
table.columns.add(col, mssql_1.default.Float, { nullable: isNullable });
|
|
789
|
-
}
|
|
790
|
-
else if (sqlBase === 'BIT') {
|
|
791
|
-
table.columns.add(col, mssql_1.default.Bit, { nullable: isNullable });
|
|
792
|
-
}
|
|
793
|
-
else if (sqlBase === 'DATETIME' || sqlBase === 'DATETIME2' || sqlBase === 'SMALLDATETIME' || sqlBase === 'DATE' || sqlBase === 'TIME') {
|
|
794
|
-
table.columns.add(col, mssql_1.default.DateTime, { nullable: isNullable });
|
|
795
|
-
}
|
|
796
|
-
else if (sqlBase === 'UNIQUEIDENTIFIER') {
|
|
797
|
-
table.columns.add(col, mssql_1.default.UniqueIdentifier, { nullable: isNullable });
|
|
798
|
-
}
|
|
799
|
-
else {
|
|
800
|
-
table.columns.add(col, mssql_1.default.NVarChar(mssql_1.default.MAX), { nullable: isNullable });
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
596
|
const now = new Date();
|
|
804
|
-
|
|
597
|
+
const rows = finalArgs.data.map((item) => {
|
|
805
598
|
const rowData = { ...item };
|
|
806
599
|
if (!rowData.id && fields.id?.ts === "string")
|
|
807
600
|
rowData.id = (0, crypto_1.randomUUID)();
|
|
@@ -809,17 +602,24 @@ class TableClient {
|
|
|
809
602
|
rowData.createdAt = now;
|
|
810
603
|
if (!rowData.updatedAt && fields.updatedAt)
|
|
811
604
|
rowData.updatedAt = now;
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
605
|
+
return rowData;
|
|
606
|
+
});
|
|
607
|
+
const cols = fieldNames.filter(col => rows.some((r) => r[col] !== undefined));
|
|
608
|
+
if (cols.length === 0)
|
|
609
|
+
throw new Error("No insertable columns");
|
|
610
|
+
const params = {};
|
|
611
|
+
const rowPlaceholders = [];
|
|
612
|
+
rows.forEach((row, rowIdx) => {
|
|
613
|
+
const vals = cols.map(col => {
|
|
614
|
+
const p = (0, sql_utils_1.sanitizeParamName)(`r${rowIdx}_${col}`);
|
|
615
|
+
params[p] = row[col] ?? null;
|
|
616
|
+
return `@${p}`;
|
|
817
617
|
});
|
|
818
|
-
|
|
819
|
-
}
|
|
820
|
-
const
|
|
821
|
-
await
|
|
822
|
-
return { count:
|
|
618
|
+
rowPlaceholders.push(`(${vals.join(", ")})`);
|
|
619
|
+
});
|
|
620
|
+
const sqlText = `INSERT INTO ${this.tableName} (${cols.map(sql_utils_1.quoteIdentifier).join(", ")}) VALUES ${rowPlaceholders.join(", ")}`;
|
|
621
|
+
await (await getAdapter())._executeRaw(sqlText, params);
|
|
622
|
+
return { count: rows.length };
|
|
823
623
|
}
|
|
824
624
|
catch (err) {
|
|
825
625
|
logger_1.logger.warn(`Bulk insert failed, falling back to sequential inserts: ${err.message}`);
|
|
@@ -847,25 +647,25 @@ class TableClient {
|
|
|
847
647
|
if (finalArgs._sum) {
|
|
848
648
|
resultObj._sum = {};
|
|
849
649
|
for (const key of Object.keys(finalArgs._sum)) {
|
|
850
|
-
selects.push(
|
|
650
|
+
selects.push(aggSelect("SUM", key));
|
|
851
651
|
}
|
|
852
652
|
}
|
|
853
653
|
if (finalArgs._avg) {
|
|
854
654
|
resultObj._avg = {};
|
|
855
655
|
for (const key of Object.keys(finalArgs._avg)) {
|
|
856
|
-
selects.push(
|
|
656
|
+
selects.push(aggSelect("AVG", key));
|
|
857
657
|
}
|
|
858
658
|
}
|
|
859
659
|
if (finalArgs._min) {
|
|
860
660
|
resultObj._min = {};
|
|
861
661
|
for (const key of Object.keys(finalArgs._min)) {
|
|
862
|
-
selects.push(
|
|
662
|
+
selects.push(aggSelect("MIN", key));
|
|
863
663
|
}
|
|
864
664
|
}
|
|
865
665
|
if (finalArgs._max) {
|
|
866
666
|
resultObj._max = {};
|
|
867
667
|
for (const key of Object.keys(finalArgs._max)) {
|
|
868
|
-
selects.push(
|
|
668
|
+
selects.push(aggSelect("MAX", key));
|
|
869
669
|
}
|
|
870
670
|
}
|
|
871
671
|
if (finalArgs._count) {
|
|
@@ -875,7 +675,7 @@ class TableClient {
|
|
|
875
675
|
}
|
|
876
676
|
else {
|
|
877
677
|
for (const key of Object.keys(finalArgs._count)) {
|
|
878
|
-
selects.push(
|
|
678
|
+
selects.push(aggSelect("COUNT", key));
|
|
879
679
|
}
|
|
880
680
|
}
|
|
881
681
|
}
|
|
@@ -884,7 +684,7 @@ class TableClient {
|
|
|
884
684
|
}
|
|
885
685
|
let sqlText = `SELECT ${selects.join(", ")} FROM ${this.tableName} WITH (NOLOCK)`;
|
|
886
686
|
const p = {};
|
|
887
|
-
const whereSql = parseWhere(this.modelName, finalArgs?.where, p);
|
|
687
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs?.where, p);
|
|
888
688
|
if (whereSql) {
|
|
889
689
|
sqlText += ` WHERE ${whereSql}`;
|
|
890
690
|
}
|
|
@@ -892,22 +692,22 @@ class TableClient {
|
|
|
892
692
|
const row = rows[0] || {};
|
|
893
693
|
if (finalArgs._sum) {
|
|
894
694
|
for (const key of Object.keys(finalArgs._sum)) {
|
|
895
|
-
resultObj._sum[key] = row[
|
|
695
|
+
resultObj._sum[key] = row[aggAlias("sum", key)] !== undefined ? row[aggAlias("sum", key)] : null;
|
|
896
696
|
}
|
|
897
697
|
}
|
|
898
698
|
if (finalArgs._avg) {
|
|
899
699
|
for (const key of Object.keys(finalArgs._avg)) {
|
|
900
|
-
resultObj._avg[key] = row[
|
|
700
|
+
resultObj._avg[key] = row[aggAlias("avg", key)] !== undefined ? row[aggAlias("avg", key)] : null;
|
|
901
701
|
}
|
|
902
702
|
}
|
|
903
703
|
if (finalArgs._min) {
|
|
904
704
|
for (const key of Object.keys(finalArgs._min)) {
|
|
905
|
-
resultObj._min[key] = row[
|
|
705
|
+
resultObj._min[key] = row[aggAlias("min", key)] !== undefined ? row[aggAlias("min", key)] : null;
|
|
906
706
|
}
|
|
907
707
|
}
|
|
908
708
|
if (finalArgs._max) {
|
|
909
709
|
for (const key of Object.keys(finalArgs._max)) {
|
|
910
|
-
resultObj._max[key] = row[
|
|
710
|
+
resultObj._max[key] = row[aggAlias("max", key)] !== undefined ? row[aggAlias("max", key)] : null;
|
|
911
711
|
}
|
|
912
712
|
}
|
|
913
713
|
if (finalArgs._count) {
|
|
@@ -916,7 +716,7 @@ class TableClient {
|
|
|
916
716
|
}
|
|
917
717
|
else {
|
|
918
718
|
for (const key of Object.keys(finalArgs._count)) {
|
|
919
|
-
resultObj._count[key] = row[
|
|
719
|
+
resultObj._count[key] = row[aggAlias("count", key)] || 0;
|
|
920
720
|
}
|
|
921
721
|
}
|
|
922
722
|
}
|
|
@@ -930,44 +730,44 @@ class TableClient {
|
|
|
930
730
|
if (byFields.length === 0) {
|
|
931
731
|
throw new Error("groupBy requires 'by' fields");
|
|
932
732
|
}
|
|
933
|
-
const selects =
|
|
733
|
+
const selects = byFields.map((f) => (0, sql_utils_1.quoteIdentifier)(f));
|
|
934
734
|
if (finalArgs._count) {
|
|
935
735
|
if (finalArgs._count === true || finalArgs._count._all) {
|
|
936
736
|
selects.push(`COUNT(*) as count_all`);
|
|
937
737
|
}
|
|
938
738
|
else {
|
|
939
739
|
for (const key of Object.keys(finalArgs._count)) {
|
|
940
|
-
selects.push(
|
|
740
|
+
selects.push(aggSelect("COUNT", key));
|
|
941
741
|
}
|
|
942
742
|
}
|
|
943
743
|
}
|
|
944
744
|
if (finalArgs._sum) {
|
|
945
745
|
for (const key of Object.keys(finalArgs._sum)) {
|
|
946
|
-
selects.push(
|
|
746
|
+
selects.push(aggSelect("SUM", key));
|
|
947
747
|
}
|
|
948
748
|
}
|
|
949
749
|
if (finalArgs._avg) {
|
|
950
750
|
for (const key of Object.keys(finalArgs._avg)) {
|
|
951
|
-
selects.push(
|
|
751
|
+
selects.push(aggSelect("AVG", key));
|
|
952
752
|
}
|
|
953
753
|
}
|
|
954
754
|
if (finalArgs._min) {
|
|
955
755
|
for (const key of Object.keys(finalArgs._min)) {
|
|
956
|
-
selects.push(
|
|
756
|
+
selects.push(aggSelect("MIN", key));
|
|
957
757
|
}
|
|
958
758
|
}
|
|
959
759
|
if (finalArgs._max) {
|
|
960
760
|
for (const key of Object.keys(finalArgs._max)) {
|
|
961
|
-
selects.push(
|
|
761
|
+
selects.push(aggSelect("MAX", key));
|
|
962
762
|
}
|
|
963
763
|
}
|
|
964
764
|
let sqlText = `SELECT ${selects.join(", ")} FROM ${this.tableName} WITH (NOLOCK)`;
|
|
965
765
|
const p = {};
|
|
966
|
-
const whereSql = parseWhere(this.modelName, finalArgs?.where, p);
|
|
766
|
+
const whereSql = this.orm.parseWhere(this.modelName, finalArgs?.where, p);
|
|
967
767
|
if (whereSql) {
|
|
968
768
|
sqlText += ` WHERE ${whereSql}`;
|
|
969
769
|
}
|
|
970
|
-
sqlText += ` GROUP BY ${byFields.join(", ")}`;
|
|
770
|
+
sqlText += ` GROUP BY ${byFields.map((f) => (0, sql_utils_1.quoteIdentifier)(f)).join(", ")}`;
|
|
971
771
|
const rows = await this.executor(sqlText, p);
|
|
972
772
|
return rows.map((row) => {
|
|
973
773
|
const item = {};
|
|
@@ -981,32 +781,32 @@ class TableClient {
|
|
|
981
781
|
}
|
|
982
782
|
else {
|
|
983
783
|
for (const key of Object.keys(finalArgs._count)) {
|
|
984
|
-
item._count[key] = row[
|
|
784
|
+
item._count[key] = row[aggAlias("count", key)] || 0;
|
|
985
785
|
}
|
|
986
786
|
}
|
|
987
787
|
}
|
|
988
788
|
if (finalArgs._sum) {
|
|
989
789
|
item._sum = {};
|
|
990
790
|
for (const key of Object.keys(finalArgs._sum)) {
|
|
991
|
-
item._sum[key] = row[
|
|
791
|
+
item._sum[key] = row[aggAlias("sum", key)] !== undefined ? row[aggAlias("sum", key)] : null;
|
|
992
792
|
}
|
|
993
793
|
}
|
|
994
794
|
if (finalArgs._avg) {
|
|
995
795
|
item._avg = {};
|
|
996
796
|
for (const key of Object.keys(finalArgs._avg)) {
|
|
997
|
-
item._avg[key] = row[
|
|
797
|
+
item._avg[key] = row[aggAlias("avg", key)] !== undefined ? row[aggAlias("avg", key)] : null;
|
|
998
798
|
}
|
|
999
799
|
}
|
|
1000
800
|
if (finalArgs._min) {
|
|
1001
801
|
item._min = {};
|
|
1002
802
|
for (const key of Object.keys(finalArgs._min)) {
|
|
1003
|
-
item._min[key] = row[
|
|
803
|
+
item._min[key] = row[aggAlias("min", key)] !== undefined ? row[aggAlias("min", key)] : null;
|
|
1004
804
|
}
|
|
1005
805
|
}
|
|
1006
806
|
if (finalArgs._max) {
|
|
1007
807
|
item._max = {};
|
|
1008
808
|
for (const key of Object.keys(finalArgs._max)) {
|
|
1009
|
-
item._max[key] = row[
|
|
809
|
+
item._max[key] = row[aggAlias("max", key)] !== undefined ? row[aggAlias("max", key)] : null;
|
|
1010
810
|
}
|
|
1011
811
|
}
|
|
1012
812
|
return item;
|
|
@@ -1021,39 +821,41 @@ class TableClient {
|
|
|
1021
821
|
const cleanCreate = { ...createData };
|
|
1022
822
|
const cleanUpdate = { ...updateData };
|
|
1023
823
|
for (const key of Object.keys(cleanCreate)) {
|
|
1024
|
-
if (
|
|
824
|
+
if (this.orm.metadata.relationMap[this.modelName]?.[key])
|
|
1025
825
|
delete cleanCreate[key];
|
|
1026
826
|
}
|
|
1027
827
|
for (const key of Object.keys(cleanUpdate)) {
|
|
1028
|
-
if (
|
|
828
|
+
if (this.orm.metadata.relationMap[this.modelName]?.[key])
|
|
1029
829
|
delete cleanUpdate[key];
|
|
1030
830
|
}
|
|
1031
|
-
if (!cleanCreate.id &&
|
|
831
|
+
if (!cleanCreate.id && this.orm.metadata.modelFields[this.modelName]?.id?.ts === "string") {
|
|
1032
832
|
cleanCreate.id = (0, crypto_1.randomUUID)();
|
|
1033
833
|
}
|
|
1034
834
|
const now = new Date();
|
|
1035
|
-
if (!cleanCreate.createdAt &&
|
|
835
|
+
if (!cleanCreate.createdAt && this.orm.metadata.modelFields[this.modelName]?.createdAt)
|
|
1036
836
|
cleanCreate.createdAt = now;
|
|
1037
|
-
if (!cleanCreate.updatedAt &&
|
|
837
|
+
if (!cleanCreate.updatedAt && this.orm.metadata.modelFields[this.modelName]?.updatedAt)
|
|
1038
838
|
cleanCreate.updatedAt = now;
|
|
1039
|
-
if (!cleanUpdate.updatedAt &&
|
|
839
|
+
if (!cleanUpdate.updatedAt && this.orm.metadata.modelFields[this.modelName]?.updatedAt)
|
|
1040
840
|
cleanUpdate.updatedAt = now;
|
|
1041
841
|
const p = {};
|
|
1042
|
-
const whereSql = parseWhere(this.modelName, where, p, "upw_");
|
|
842
|
+
const whereSql = this.orm.parseWhere(this.modelName, where, p, "upw_");
|
|
1043
843
|
const allKeys = Array.from(new Set([...Object.keys(cleanCreate), ...Object.keys(cleanUpdate)]));
|
|
844
|
+
const cParam = (k) => `c_${(0, sql_utils_1.sanitizeParamName)(k)}`;
|
|
845
|
+
const uParam = (k) => `u_${(0, sql_utils_1.sanitizeParamName)(k)}`;
|
|
1044
846
|
for (const k of allKeys) {
|
|
1045
847
|
if (cleanCreate[k] !== undefined)
|
|
1046
|
-
p[
|
|
848
|
+
p[cParam(k)] = cleanCreate[k];
|
|
1047
849
|
if (cleanUpdate[k] !== undefined)
|
|
1048
|
-
p[
|
|
850
|
+
p[uParam(k)] = cleanUpdate[k];
|
|
1049
851
|
}
|
|
1050
852
|
const sourceSelect = allKeys.map(k => {
|
|
1051
|
-
const val = cleanCreate[k] !== undefined ?
|
|
1052
|
-
return `${val} as
|
|
853
|
+
const val = cleanCreate[k] !== undefined ? `@${cParam(k)}` : (cleanUpdate[k] !== undefined ? `@${uParam(k)}` : "NULL");
|
|
854
|
+
return `${val} as ${(0, sql_utils_1.quoteIdentifier)(k)}`;
|
|
1053
855
|
}).join(", ");
|
|
1054
|
-
const updateSets = Object.keys(cleanUpdate).map(k => `target.
|
|
1055
|
-
const insertCols = Object.keys(cleanCreate).map(k =>
|
|
1056
|
-
const insertVals = Object.keys(cleanCreate).map(k => `source.
|
|
856
|
+
const updateSets = Object.keys(cleanUpdate).map(k => `target.${(0, sql_utils_1.quoteIdentifier)(k)} = source.${(0, sql_utils_1.quoteIdentifier)(k)}`).join(", ");
|
|
857
|
+
const insertCols = Object.keys(cleanCreate).map(k => (0, sql_utils_1.quoteIdentifier)(k)).join(", ");
|
|
858
|
+
const insertVals = Object.keys(cleanCreate).map(k => `source.${(0, sql_utils_1.quoteIdentifier)(k)}`).join(", ");
|
|
1057
859
|
// Note: This MERGE assumes the 'where' translates to a simple ON clause.
|
|
1058
860
|
// For complex 'where', parseWhere might return something not easily usable in ON.
|
|
1059
861
|
// We'll try to extract simple equality for ON if possible, or fallback to sequential.
|
|
@@ -1061,25 +863,25 @@ class TableClient {
|
|
|
1061
863
|
if (typeof where[k] === 'object' && where[k] !== null && !(where[k] instanceof Date)) {
|
|
1062
864
|
// Flatten unique object if needed
|
|
1063
865
|
const inner = where[k];
|
|
1064
|
-
return Object.keys(inner).map(ik => `target.
|
|
866
|
+
return Object.keys(inner).map(ik => `target.${(0, sql_utils_1.quoteIdentifier)(ik)} = @${(0, sql_utils_1.sanitizeParamName)(`upw_${k}_${ik}`)}`).join(" AND ");
|
|
1065
867
|
}
|
|
1066
|
-
return `target.
|
|
868
|
+
return `target.${(0, sql_utils_1.quoteIdentifier)(k)} = @${(0, sql_utils_1.sanitizeParamName)(`upw_${k}`)}`;
|
|
1067
869
|
}).join(" AND ");
|
|
1068
|
-
const sqlText = `
|
|
1069
|
-
MERGE INTO ${this.tableName} WITH (HOLDLOCK) AS target
|
|
1070
|
-
USING (SELECT ${sourceSelect}) AS source
|
|
1071
|
-
ON (${onClause})
|
|
1072
|
-
WHEN MATCHED THEN
|
|
1073
|
-
UPDATE SET ${updateSets}
|
|
1074
|
-
WHEN NOT MATCHED THEN
|
|
1075
|
-
INSERT (${insertCols}) VALUES (${insertVals})
|
|
1076
|
-
OUTPUT inserted.*;
|
|
870
|
+
const sqlText = `
|
|
871
|
+
MERGE INTO ${this.tableName} WITH (HOLDLOCK) AS target
|
|
872
|
+
USING (SELECT ${sourceSelect}) AS source
|
|
873
|
+
ON (${onClause})
|
|
874
|
+
WHEN MATCHED THEN
|
|
875
|
+
UPDATE SET ${updateSets}
|
|
876
|
+
WHEN NOT MATCHED THEN
|
|
877
|
+
INSERT (${insertCols}) VALUES (${insertVals})
|
|
878
|
+
OUTPUT inserted.*;
|
|
1077
879
|
`;
|
|
1078
880
|
try {
|
|
1079
881
|
const rows = await this.executor(sqlText, p);
|
|
1080
882
|
const result = rows[0];
|
|
1081
883
|
if (include && result) {
|
|
1082
|
-
await resolveIncludes(this.modelName, [result], include, this.executor);
|
|
884
|
+
await resolveIncludes(this.modelName, [result], include, this.executor, this.orm.metadata);
|
|
1083
885
|
}
|
|
1084
886
|
return result;
|
|
1085
887
|
}
|
|
@@ -1096,12 +898,12 @@ class TableClient {
|
|
|
1096
898
|
});
|
|
1097
899
|
}
|
|
1098
900
|
}
|
|
1099
|
-
function addNoLockToQuery(sql) {
|
|
901
|
+
function addNoLockToQuery(sql, metadata) {
|
|
1100
902
|
// If it's not a SELECT query, don't modify it
|
|
1101
903
|
if (!/^\s*SELECT/i.test(sql)) {
|
|
1102
904
|
return sql;
|
|
1103
905
|
}
|
|
1104
|
-
const tableNames = Object.values(
|
|
906
|
+
const tableNames = Object.values(metadata.modelToTable);
|
|
1105
907
|
let modifiedSql = sql;
|
|
1106
908
|
for (const table of tableNames) {
|
|
1107
909
|
const escapedTable = table.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
@@ -1130,11 +932,32 @@ function addNoLockToQuery(sql) {
|
|
|
1130
932
|
}
|
|
1131
933
|
return modifiedSql;
|
|
1132
934
|
}
|
|
935
|
+
// Lazy-load generated schema metadata from the ORM's own generated copy so
|
|
936
|
+
// `new An5ORM()` resolves schema models out of the box without the core ever
|
|
937
|
+
// importing from the generated client package (client is generated FROM the ORM).
|
|
938
|
+
let autoMetadata = null;
|
|
939
|
+
function loadAutoMetadata() {
|
|
940
|
+
if (autoMetadata)
|
|
941
|
+
return autoMetadata;
|
|
942
|
+
try {
|
|
943
|
+
const m = require("./an5Metadata");
|
|
944
|
+
autoMetadata = {
|
|
945
|
+
modelToTable: m.modelToTable || {},
|
|
946
|
+
relationMap: m.relationMap || {},
|
|
947
|
+
modelFields: m.modelFields || {},
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
catch {
|
|
951
|
+
autoMetadata = metadata_1.DEFAULT_METADATA;
|
|
952
|
+
}
|
|
953
|
+
return autoMetadata;
|
|
954
|
+
}
|
|
1133
955
|
// Proxied AN5 ORM client class
|
|
1134
956
|
class An5ORM {
|
|
1135
|
-
constructor(customExecutor) {
|
|
957
|
+
constructor(customExecutor, metadata) {
|
|
1136
958
|
this.customExecutor = customExecutor;
|
|
1137
959
|
this.middlewares = [];
|
|
960
|
+
this.metadata = metadata ?? loadAutoMetadata();
|
|
1138
961
|
// Add default logging middleware
|
|
1139
962
|
this.$use(async (params, next) => {
|
|
1140
963
|
const start = Date.now();
|
|
@@ -1180,7 +1003,7 @@ class An5ORM {
|
|
|
1180
1003
|
}
|
|
1181
1004
|
if (!(prop in target) && typeof prop === "string" && !prop.startsWith("_")) {
|
|
1182
1005
|
// Resolve modelName in camelCase and map to table name
|
|
1183
|
-
const tableName =
|
|
1006
|
+
const tableName = target.metadata.modelToTable[prop];
|
|
1184
1007
|
if (tableName) {
|
|
1185
1008
|
target[prop] = new TableClient(prop, tableName, target.customExecutor || execQuery, target // Pass ORM instance for middleware access
|
|
1186
1009
|
);
|
|
@@ -1193,6 +1016,12 @@ class An5ORM {
|
|
|
1193
1016
|
$use(middleware) {
|
|
1194
1017
|
this.middlewares.push(middleware);
|
|
1195
1018
|
}
|
|
1019
|
+
parseWhere(modelName, where, params, prefix = "") {
|
|
1020
|
+
return (0, sql_utils_1.parseWhere)(modelName, where, params, prefix, {
|
|
1021
|
+
relationMap: this.metadata.relationMap,
|
|
1022
|
+
modelToTable: this.metadata.modelToTable,
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1196
1025
|
async _executeMiddleware(params, finalAction) {
|
|
1197
1026
|
let index = -1;
|
|
1198
1027
|
const dispatch = async (i, currentParams) => {
|
|
@@ -1243,7 +1072,7 @@ class An5ORM {
|
|
|
1243
1072
|
else {
|
|
1244
1073
|
throw new Error("Invalid query format for $queryRaw");
|
|
1245
1074
|
}
|
|
1246
|
-
queryText = addNoLockToQuery(queryText);
|
|
1075
|
+
queryText = addNoLockToQuery(queryText, this.metadata);
|
|
1247
1076
|
return executor(queryText, params);
|
|
1248
1077
|
}
|
|
1249
1078
|
async $queryRawUnsafe(queryText, ...values) {
|
|
@@ -1255,7 +1084,7 @@ class An5ORM {
|
|
|
1255
1084
|
params[paramName] = val;
|
|
1256
1085
|
});
|
|
1257
1086
|
}
|
|
1258
|
-
const modifiedQueryText = addNoLockToQuery(queryText);
|
|
1087
|
+
const modifiedQueryText = addNoLockToQuery(queryText, this.metadata);
|
|
1259
1088
|
const result = await executor(modifiedQueryText, params);
|
|
1260
1089
|
return result;
|
|
1261
1090
|
}
|
|
@@ -1286,7 +1115,7 @@ class An5ORM {
|
|
|
1286
1115
|
else {
|
|
1287
1116
|
throw new Error("Invalid query format for $executeRaw");
|
|
1288
1117
|
}
|
|
1289
|
-
queryText = addNoLockToQuery(queryText);
|
|
1118
|
+
queryText = addNoLockToQuery(queryText, this.metadata);
|
|
1290
1119
|
const result = (await executor(queryText, params));
|
|
1291
1120
|
return result.rowsAffected?.[0] || 0;
|
|
1292
1121
|
}
|
|
@@ -1299,7 +1128,7 @@ class An5ORM {
|
|
|
1299
1128
|
params[paramName] = val;
|
|
1300
1129
|
});
|
|
1301
1130
|
}
|
|
1302
|
-
const modifiedQueryText = addNoLockToQuery(queryText);
|
|
1131
|
+
const modifiedQueryText = addNoLockToQuery(queryText, this.metadata);
|
|
1303
1132
|
const result = (await executor(modifiedQueryText, params));
|
|
1304
1133
|
return result.rowsAffected?.[0] || 0;
|
|
1305
1134
|
}
|
|
@@ -1307,42 +1136,18 @@ class An5ORM {
|
|
|
1307
1136
|
if (Array.isArray(fn)) {
|
|
1308
1137
|
return Promise.all(fn);
|
|
1309
1138
|
}
|
|
1310
|
-
const
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
const result = await request.query(queryText);
|
|
1322
|
-
const recordset = (result.recordset || []);
|
|
1323
|
-
recordset.rowsAffected = result.rowsAffected;
|
|
1324
|
-
return recordset;
|
|
1325
|
-
};
|
|
1326
|
-
const txClient = new An5ORM(txExecutor);
|
|
1327
|
-
try {
|
|
1328
|
-
const result = await fn(txClient);
|
|
1329
|
-
await transaction.commit();
|
|
1330
|
-
logger_1.logger.info("Database Transaction Committed Successfully");
|
|
1331
|
-
return result;
|
|
1332
|
-
}
|
|
1333
|
-
catch (err) {
|
|
1334
|
-
try {
|
|
1335
|
-
await transaction.rollback();
|
|
1336
|
-
logger_1.logger.warn("Database Transaction Rolled Back");
|
|
1337
|
-
}
|
|
1338
|
-
catch (rollbackErr) {
|
|
1339
|
-
logger_1.logger.error("Failed to rollback database transaction", rollbackErr);
|
|
1340
|
-
}
|
|
1341
|
-
throw err;
|
|
1342
|
-
}
|
|
1139
|
+
const a = await getAdapter();
|
|
1140
|
+
return a.$transaction(async (tx) => {
|
|
1141
|
+
const txExecutor = async (queryText, params) => {
|
|
1142
|
+
const rows = await tx.exec(queryText, params);
|
|
1143
|
+
return rows;
|
|
1144
|
+
};
|
|
1145
|
+
const txClient = new An5ORM(txExecutor, this.metadata);
|
|
1146
|
+
return fn(txClient);
|
|
1147
|
+
}, options);
|
|
1343
1148
|
}
|
|
1344
1149
|
}
|
|
1345
1150
|
exports.An5ORM = An5ORM;
|
|
1346
1151
|
exports.an5Orm = new An5ORM();
|
|
1347
1152
|
exports.default = exports.an5Orm;
|
|
1348
|
-
//# sourceMappingURL=an5Orm.js.map
|
|
1153
|
+
//# sourceMappingURL=an5Orm.js.map
|