sqlstack 3.0.0 → 3.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/dist/cjs/decorators/query.d.ts.map +1 -1
- package/dist/cjs/decorators/query.js +258 -240
- package/dist/cjs/decorators/query.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/run.d.ts +29 -0
- package/dist/cjs/run.d.ts.map +1 -0
- package/dist/cjs/run.js +38 -0
- package/dist/cjs/run.js.map +1 -0
- package/dist/cjs/testing/index.d.ts +4 -0
- package/dist/cjs/testing/index.d.ts.map +1 -1
- package/dist/cjs/testing/index.js +5 -1
- package/dist/cjs/testing/index.js.map +1 -1
- package/dist/cjs/testing/schema/ddl.d.ts +1 -10
- package/dist/cjs/testing/schema/ddl.d.ts.map +1 -1
- package/dist/cjs/testing/schema/ddl.js +29 -13
- package/dist/cjs/testing/schema/ddl.js.map +1 -1
- package/dist/cjs/testing/schema/normalize.js +3 -3
- package/dist/cjs/testing/schema/normalize.js.map +1 -1
- package/dist/cjs/testing/schema/types.d.ts +1 -20
- package/dist/cjs/testing/schema/types.d.ts.map +1 -1
- package/dist/cjs/testing/schema/types.js +0 -4
- package/dist/cjs/testing/schema/types.js.map +1 -1
- package/dist/cjs/testing/sqlite/builder.d.ts +24 -0
- package/dist/cjs/testing/sqlite/builder.d.ts.map +1 -0
- package/dist/cjs/testing/sqlite/builder.js +134 -0
- package/dist/cjs/testing/sqlite/builder.js.map +1 -0
- package/dist/cjs/testing/sqlite/database.d.ts +18 -0
- package/dist/cjs/testing/sqlite/database.d.ts.map +1 -0
- package/dist/cjs/testing/sqlite/database.js +123 -0
- package/dist/cjs/testing/sqlite/database.js.map +1 -0
- package/dist/cjs/testing/sqlite/loadData.d.ts +7 -0
- package/dist/cjs/testing/sqlite/loadData.d.ts.map +1 -0
- package/dist/cjs/testing/sqlite/loadData.js +55 -0
- package/dist/cjs/testing/sqlite/loadData.js.map +1 -0
- package/dist/esm/decorators/query.js +258 -240
- package/dist/esm/decorators/query.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/run.js +34 -0
- package/dist/esm/run.js.map +1 -0
- package/dist/esm/testing/index.js +2 -0
- package/dist/esm/testing/index.js.map +1 -1
- package/dist/esm/testing/schema/ddl.js +29 -13
- package/dist/esm/testing/schema/ddl.js.map +1 -1
- package/dist/esm/testing/schema/normalize.js +3 -3
- package/dist/esm/testing/schema/normalize.js.map +1 -1
- package/dist/esm/testing/schema/types.js +0 -4
- package/dist/esm/testing/schema/types.js.map +1 -1
- package/dist/esm/testing/sqlite/builder.js +98 -0
- package/dist/esm/testing/sqlite/builder.js.map +1 -0
- package/dist/esm/testing/sqlite/database.js +85 -0
- package/dist/esm/testing/sqlite/database.js.map +1 -0
- package/dist/esm/testing/sqlite/loadData.js +48 -0
- package/dist/esm/testing/sqlite/loadData.js.map +1 -0
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/decorators/query.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../../src/decorators/query.ts"],"names":[],"mappings":"AAYA,KAAK,YAAY,GAAG;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;CAC3C,CAAC;AAEF,wBAAgB,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,YAAY,IAC9B,SAAS,GAAG,EAAE,MAAM,MAAM,GAAG,MAAM,EAAE,MAAM,kBAAkB,wBA2S/E"}
|
|
@@ -11,6 +11,7 @@ const resolver_1 = require("../core/resolver");
|
|
|
11
11
|
const sourceScanResolver_1 = require("../core/sourceScanResolver");
|
|
12
12
|
const transactions_1 = require("../transactions");
|
|
13
13
|
const sql_1 = require("../sql");
|
|
14
|
+
const run_1 = require("../run");
|
|
14
15
|
function Query(arg) {
|
|
15
16
|
return function (_target, prop, desc) {
|
|
16
17
|
const options = typeof arg === 'string' ? undefined : arg;
|
|
@@ -47,281 +48,298 @@ function Query(arg) {
|
|
|
47
48
|
desc.value = async function (...callArgs) {
|
|
48
49
|
const labels = (0, metadata_1.getMethodLabels)(this, prop);
|
|
49
50
|
const classLabels = (0, metadata_1.getClassLabels)(this);
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
fragmentResult = undefined;
|
|
58
|
-
}
|
|
59
|
-
if (fragmentResult instanceof sql_1.SqlFragment) {
|
|
60
|
-
const { sql: boundSql, params } = fragmentResult.toSQL();
|
|
51
|
+
// The full file/inline pipeline (resolve source, bind, execute,
|
|
52
|
+
// shape/transform/validate). Invoked either by run() from inside the
|
|
53
|
+
// method body, or directly as the legacy fallback when the body throws.
|
|
54
|
+
const pipeline = async () => {
|
|
55
|
+
// 1) prepare args with defaults
|
|
56
|
+
const rawInput = callArgs.length === 1 ? callArgs[0] : callArgs; // object or positional array
|
|
57
|
+
// 2) choose database and dialect via the active environment
|
|
61
58
|
const dbName = labels.db ?? options?.db ?? classLabels?.db;
|
|
62
|
-
const { entry } = await (0, runtime_1.resolveExecution)(dbName);
|
|
59
|
+
const { entry, resolver: activeResolver } = await (0, runtime_1.resolveExecution)(dbName);
|
|
63
60
|
const db = entry.db;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
if (Array.isArray(out)) {
|
|
73
|
-
const shaped = applyShape(out, labels.shape);
|
|
74
|
-
const transformed = labels.transform ? labels.transform(shaped) : shaped;
|
|
75
|
-
if (labels.validateSchema && !(0, validator_1.isValidationDisabled)()) {
|
|
76
|
-
if (Array.isArray(transformed)) {
|
|
77
|
-
for (const row of transformed)
|
|
78
|
-
(0, validator_1.validateOutput)(labels.validateSchema, row);
|
|
79
|
-
}
|
|
80
|
-
else if (transformed !== null && transformed !== undefined) {
|
|
81
|
-
(0, validator_1.validateOutput)(labels.validateSchema, transformed);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return transformed;
|
|
85
|
-
}
|
|
86
|
-
return out;
|
|
87
|
-
}
|
|
88
|
-
// 1) prepare args with defaults
|
|
89
|
-
const rawInput = callArgs.length === 1 ? callArgs[0] : callArgs; // object or positional array
|
|
90
|
-
// 2) choose database and dialect via the active environment
|
|
91
|
-
const dbName = labels.db ?? options?.db ?? classLabels?.db;
|
|
92
|
-
const { entry, resolver: activeResolver } = await (0, runtime_1.resolveExecution)(dbName);
|
|
93
|
-
const db = entry.db;
|
|
94
|
-
const dialect = options?.dialect ?? db.dialect ?? 'sqlite';
|
|
95
|
-
// 3) load SQL source (inline, environment resolver, v1 fs fallback,
|
|
96
|
-
// or the zero-config source scan — bare @Query() with nothing installed)
|
|
97
|
-
const sql = labels?.source?.kind === 'inline'
|
|
98
|
-
? labels.source.sql
|
|
99
|
-
: activeResolver
|
|
100
|
-
? activeResolver.resolve({
|
|
101
|
-
className: this?.constructor?.name ?? '<anonymous>',
|
|
102
|
-
methodName: String(prop),
|
|
103
|
-
dialect,
|
|
104
|
-
rootDir: labels?.source?.kind === 'fs' ? labels.source.rootDir : undefined,
|
|
105
|
-
})
|
|
106
|
-
: labels?.source?.kind === 'fs'
|
|
107
|
-
? (0, fileResolution_1.resolveSqlFromFs)(labels.source.rootDir, String(prop), dialect).sql
|
|
108
|
-
: (0, sourceScanResolver_1.defaultSourceScanResolver)()?.resolve({
|
|
61
|
+
const dialect = options?.dialect ?? db.dialect ?? 'sqlite';
|
|
62
|
+
// 3) load SQL source (inline, environment resolver, v1 fs fallback,
|
|
63
|
+
// or the zero-config source scan — bare @Query() with nothing installed)
|
|
64
|
+
const sql = labels?.source?.kind === 'inline'
|
|
65
|
+
? labels.source.sql
|
|
66
|
+
: activeResolver
|
|
67
|
+
? activeResolver.resolve({
|
|
109
68
|
className: this?.constructor?.name ?? '<anonymous>',
|
|
110
69
|
methodName: String(prop),
|
|
111
70
|
dialect,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const pageCfg = labels.page;
|
|
131
|
-
if (pageCfg) {
|
|
132
|
-
const { size, zeroBase } = pageCfg;
|
|
133
|
-
const base = zeroBase ? 0 : 1;
|
|
134
|
-
// Extract page number from input (object) or a trailing options object in positional mode
|
|
135
|
-
const pageFromObject = (val) => {
|
|
136
|
-
if (val && typeof val === 'object' && !Array.isArray(val) && typeof val.page !== 'undefined') {
|
|
137
|
-
const p = val.page;
|
|
138
|
-
if (typeof p === 'number' && isFinite(p))
|
|
139
|
-
return p;
|
|
140
|
-
}
|
|
141
|
-
return undefined;
|
|
142
|
-
};
|
|
143
|
-
let pageNum;
|
|
71
|
+
rootDir: labels?.source?.kind === 'fs' ? labels.source.rootDir : undefined,
|
|
72
|
+
})
|
|
73
|
+
: labels?.source?.kind === 'fs'
|
|
74
|
+
? (0, fileResolution_1.resolveSqlFromFs)(labels.source.rootDir, String(prop), dialect).sql
|
|
75
|
+
: (0, sourceScanResolver_1.defaultSourceScanResolver)()?.resolve({
|
|
76
|
+
className: this?.constructor?.name ?? '<anonymous>',
|
|
77
|
+
methodName: String(prop),
|
|
78
|
+
dialect,
|
|
79
|
+
});
|
|
80
|
+
if (!sql) {
|
|
81
|
+
throw new errors_1.SqlStackError(`No SQL source provided for method ${String(prop)}. Use @Query() with a file/folder path or inline sql.`);
|
|
82
|
+
}
|
|
83
|
+
// 4) bind placeholders
|
|
84
|
+
// Decide argument mode: positional if SQL contains :argN
|
|
85
|
+
let workingSql = sql;
|
|
86
|
+
const hasPositional = /:arg[1-9][0-9]*/.test(workingSql);
|
|
87
|
+
// Prepare args for binder
|
|
88
|
+
let args;
|
|
144
89
|
if (hasPositional) {
|
|
145
|
-
|
|
146
|
-
if (callArgs.length > 0) {
|
|
147
|
-
const last = callArgs[callArgs.length - 1];
|
|
148
|
-
pageNum = pageFromObject(last);
|
|
149
|
-
}
|
|
90
|
+
args = callArgs;
|
|
150
91
|
}
|
|
151
92
|
else {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
93
|
+
const namedBase = callArgs.length > 0 ? callArgs[0] : undefined;
|
|
94
|
+
args = applyDefaults(labels.defaults, namedBase ?? {});
|
|
95
|
+
}
|
|
96
|
+
// Compute paging and inject :offset/:limit (named mode) or rewrite to positional
|
|
97
|
+
const pageCfg = labels.page;
|
|
98
|
+
if (pageCfg) {
|
|
99
|
+
const { size, zeroBase } = pageCfg;
|
|
100
|
+
const base = zeroBase ? 0 : 1;
|
|
101
|
+
// Extract page number from input (object) or a trailing options object in positional mode
|
|
102
|
+
const pageFromObject = (val) => {
|
|
103
|
+
if (val && typeof val === 'object' && !Array.isArray(val) && typeof val.page !== 'undefined') {
|
|
104
|
+
const p = val.page;
|
|
105
|
+
if (typeof p === 'number' && isFinite(p))
|
|
106
|
+
return p;
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
109
|
+
};
|
|
110
|
+
let pageNum;
|
|
111
|
+
if (hasPositional) {
|
|
112
|
+
// Variadic-style: only the LAST argument may carry `{ page }`
|
|
113
|
+
if (callArgs.length > 0) {
|
|
114
|
+
const last = callArgs[callArgs.length - 1];
|
|
115
|
+
pageNum = pageFromObject(last);
|
|
116
|
+
}
|
|
156
117
|
}
|
|
157
|
-
|
|
158
|
-
|
|
118
|
+
else {
|
|
119
|
+
// Prefer last-arg options if provided; otherwise read from named object
|
|
120
|
+
if (callArgs.length > 1) {
|
|
121
|
+
const last = callArgs[callArgs.length - 1];
|
|
122
|
+
pageNum = pageFromObject(last);
|
|
123
|
+
}
|
|
124
|
+
if (pageNum === undefined) {
|
|
125
|
+
pageNum = pageFromObject(args);
|
|
126
|
+
}
|
|
159
127
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
inLC = false;
|
|
181
|
-
i++;
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
if (inBC) {
|
|
185
|
-
out.push(ch);
|
|
186
|
-
if (ch === '*' && next === '/') {
|
|
187
|
-
out.push(next);
|
|
128
|
+
const effectivePage = typeof pageNum === 'number' ? pageNum : base;
|
|
129
|
+
const offset = (effectivePage - base) * size;
|
|
130
|
+
const limit = size;
|
|
131
|
+
if (hasPositional) {
|
|
132
|
+
// Replace occurrences of :offset and :limit with new :argN tokens appended to args
|
|
133
|
+
const baseIndex = callArgs.length; // start numbering after user args
|
|
134
|
+
let nextIndex = baseIndex + 1;
|
|
135
|
+
const additions = [];
|
|
136
|
+
const rewrite = (sqlText) => {
|
|
137
|
+
const out = [];
|
|
138
|
+
let i = 0;
|
|
139
|
+
let inSQ = false, inDQ = false, inLC = false, inBC = false;
|
|
140
|
+
const len = sqlText.length;
|
|
141
|
+
while (i < len) {
|
|
142
|
+
const ch = sqlText[i];
|
|
143
|
+
const next = i + 1 < len ? sqlText[i + 1] : '';
|
|
144
|
+
if (inLC) {
|
|
145
|
+
out.push(ch);
|
|
146
|
+
if (ch === '\n')
|
|
147
|
+
inLC = false;
|
|
188
148
|
i++;
|
|
189
|
-
|
|
149
|
+
continue;
|
|
190
150
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
151
|
+
if (inBC) {
|
|
152
|
+
out.push(ch);
|
|
153
|
+
if (ch === '*' && next === '/') {
|
|
154
|
+
out.push(next);
|
|
155
|
+
i++;
|
|
156
|
+
inBC = false;
|
|
157
|
+
}
|
|
158
|
+
i++;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (inSQ) {
|
|
162
|
+
out.push(ch);
|
|
163
|
+
if (ch === "'" && next === "'") {
|
|
164
|
+
out.push(next);
|
|
165
|
+
i += 2;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (ch === "'")
|
|
169
|
+
inSQ = false;
|
|
170
|
+
i++;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (inDQ) {
|
|
174
|
+
out.push(ch);
|
|
175
|
+
if (ch === '"' && next === '"') {
|
|
176
|
+
out.push(next);
|
|
177
|
+
i += 2;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (ch === '"')
|
|
181
|
+
inDQ = false;
|
|
182
|
+
i++;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (ch === '-' && next === '-') {
|
|
186
|
+
out.push(ch, next);
|
|
198
187
|
i += 2;
|
|
188
|
+
inLC = true;
|
|
199
189
|
continue;
|
|
200
190
|
}
|
|
201
|
-
if (ch ===
|
|
202
|
-
|
|
203
|
-
i++;
|
|
204
|
-
continue;
|
|
205
|
-
}
|
|
206
|
-
if (inDQ) {
|
|
207
|
-
out.push(ch);
|
|
208
|
-
if (ch === '"' && next === '"') {
|
|
209
|
-
out.push(next);
|
|
191
|
+
if (ch === '/' && next === '*') {
|
|
192
|
+
out.push(ch, next);
|
|
210
193
|
i += 2;
|
|
194
|
+
inBC = true;
|
|
211
195
|
continue;
|
|
212
196
|
}
|
|
213
|
-
if (ch === '"')
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (ch === '-' && next === '-') {
|
|
219
|
-
out.push(ch, next);
|
|
220
|
-
i += 2;
|
|
221
|
-
inLC = true;
|
|
222
|
-
continue;
|
|
223
|
-
}
|
|
224
|
-
if (ch === '/' && next === '*') {
|
|
225
|
-
out.push(ch, next);
|
|
226
|
-
i += 2;
|
|
227
|
-
inBC = true;
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
if (ch === '"') {
|
|
231
|
-
out.push(ch);
|
|
232
|
-
inDQ = true;
|
|
233
|
-
i++;
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
if (ch === "'") {
|
|
237
|
-
out.push(ch);
|
|
238
|
-
inSQ = true;
|
|
239
|
-
i++;
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
if (ch === ':' && next === ':') {
|
|
243
|
-
out.push('::');
|
|
244
|
-
i += 2;
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
247
|
-
if (ch === ':') {
|
|
248
|
-
// parse token
|
|
249
|
-
let j = i + 1;
|
|
250
|
-
const start = j;
|
|
251
|
-
while (j < len) {
|
|
252
|
-
const c = sqlText[j];
|
|
253
|
-
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c === '_')
|
|
254
|
-
j++;
|
|
255
|
-
else
|
|
256
|
-
break;
|
|
197
|
+
if (ch === '"') {
|
|
198
|
+
out.push(ch);
|
|
199
|
+
inDQ = true;
|
|
200
|
+
i++;
|
|
201
|
+
continue;
|
|
257
202
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
additions.push(offset);
|
|
263
|
-
i = j;
|
|
203
|
+
if (ch === "'") {
|
|
204
|
+
out.push(ch);
|
|
205
|
+
inSQ = true;
|
|
206
|
+
i++;
|
|
264
207
|
continue;
|
|
265
208
|
}
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
209
|
+
if (ch === ':' && next === ':') {
|
|
210
|
+
out.push('::');
|
|
211
|
+
i += 2;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (ch === ':') {
|
|
215
|
+
// parse token
|
|
216
|
+
let j = i + 1;
|
|
217
|
+
const start = j;
|
|
218
|
+
while (j < len) {
|
|
219
|
+
const c = sqlText[j];
|
|
220
|
+
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c === '_')
|
|
221
|
+
j++;
|
|
222
|
+
else
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
const name = sqlText.slice(start, j);
|
|
226
|
+
if (name === 'offset') {
|
|
227
|
+
const token = `:arg${nextIndex++}`;
|
|
228
|
+
out.push(token);
|
|
229
|
+
additions.push(offset);
|
|
230
|
+
i = j;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (name === 'limit') {
|
|
234
|
+
const token = `:arg${nextIndex++}`;
|
|
235
|
+
out.push(token);
|
|
236
|
+
additions.push(limit);
|
|
237
|
+
i = j;
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
// otherwise leave untouched
|
|
241
|
+
out.push(':');
|
|
242
|
+
i++;
|
|
271
243
|
continue;
|
|
272
244
|
}
|
|
273
|
-
|
|
274
|
-
out.push(':');
|
|
245
|
+
out.push(ch);
|
|
275
246
|
i++;
|
|
276
|
-
continue;
|
|
277
247
|
}
|
|
278
|
-
out.
|
|
279
|
-
|
|
248
|
+
return out.join('');
|
|
249
|
+
};
|
|
250
|
+
const rewritten = rewrite(workingSql);
|
|
251
|
+
if (rewritten !== workingSql) {
|
|
252
|
+
workingSql = rewritten;
|
|
253
|
+
// append values so :argK map correctly
|
|
254
|
+
args.push(...additions);
|
|
280
255
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
workingSql = rewritten;
|
|
286
|
-
// append values so :argK map correctly
|
|
287
|
-
args.push(...additions);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// Named-mode: attach computed values (override any provided)
|
|
259
|
+
args = { ...args, offset, limit };
|
|
288
260
|
}
|
|
289
261
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
262
|
+
const binder = dialect === 'postgres' ? (0, sqlBinder_1.createPostgresBinder)() : dialect === 'mysql' ? (0, sqlBinder_1.createMysqlBinder)() : (0, sqlBinder_1.createSqliteBinder)();
|
|
263
|
+
const { sql: boundSql, params } = binder.bind(workingSql, args);
|
|
264
|
+
// 5) execute query via registry DB
|
|
265
|
+
let out;
|
|
266
|
+
try {
|
|
267
|
+
const tx = (0, transactions_1.getActiveTransaction)(entry);
|
|
268
|
+
out = tx ? await tx.query(boundSql, params) : await db.query(boundSql, params);
|
|
293
269
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
270
|
+
catch (dbError) {
|
|
271
|
+
// Attach SQL query (with placeholders) to error for debugging
|
|
272
|
+
throw new errors_1.DatabaseError(dbError?.message || String(dbError), boundSql, dbError instanceof Error ? dbError : undefined);
|
|
273
|
+
}
|
|
274
|
+
// 6) If rows were returned (SELECT/CTE), shape + transform + validate
|
|
275
|
+
if (Array.isArray(out)) {
|
|
276
|
+
const shaped = applyShape(out, labels.shape);
|
|
277
|
+
const transformed = labels.transform ? labels.transform(shaped) : shaped;
|
|
278
|
+
// 7) validate result via JSON Schema, if provided
|
|
279
|
+
if (labels.validateSchema && !(0, validator_1.isValidationDisabled)()) {
|
|
280
|
+
if (Array.isArray(transformed)) {
|
|
281
|
+
for (const row of transformed)
|
|
282
|
+
(0, validator_1.validateOutput)(labels.validateSchema, row);
|
|
283
|
+
}
|
|
284
|
+
else if (transformed !== null && transformed !== undefined) {
|
|
285
|
+
(0, validator_1.validateOutput)(labels.validateSchema, transformed);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return transformed;
|
|
289
|
+
}
|
|
290
|
+
// Non-SELECT: return the write result as-is
|
|
291
|
+
return out;
|
|
292
|
+
};
|
|
293
|
+
// 0) Invoke the method body inside a run() context. Three outcomes:
|
|
294
|
+
// - body calls run(): the pipeline executed inside the body; return
|
|
295
|
+
// the body's result verbatim (it may have caught/transformed it).
|
|
296
|
+
// - body returns a SqlFragment (template literal path): execute it.
|
|
297
|
+
// - body throws without calling run() (legacy placeholder throw):
|
|
298
|
+
// fall through to the pipeline.
|
|
299
|
+
const runCtx = { ran: false, execute: pipeline };
|
|
300
|
+
let fragmentResult;
|
|
299
301
|
try {
|
|
300
|
-
|
|
301
|
-
out = tx ? await tx.query(boundSql, params) : await db.query(boundSql, params);
|
|
302
|
+
fragmentResult = await run_1.runStorage.run(runCtx, () => original.apply(this, callArgs));
|
|
302
303
|
}
|
|
303
|
-
catch (
|
|
304
|
-
//
|
|
305
|
-
|
|
304
|
+
catch (bodyError) {
|
|
305
|
+
// A body that invoked run() is real logic — its errors propagate.
|
|
306
|
+
if (runCtx.ran)
|
|
307
|
+
throw bodyError;
|
|
308
|
+
// Method body threw (e.g. placeholder `throw new Error('replaced')`) — fall through to file/inline SQL
|
|
309
|
+
fragmentResult = undefined;
|
|
306
310
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
311
|
+
if (runCtx.ran)
|
|
312
|
+
return fragmentResult;
|
|
313
|
+
if (fragmentResult instanceof sql_1.SqlFragment) {
|
|
314
|
+
const { sql: boundSql, params } = fragmentResult.toSQL();
|
|
315
|
+
const dbName = labels.db ?? options?.db ?? classLabels?.db;
|
|
316
|
+
const { entry } = await (0, runtime_1.resolveExecution)(dbName);
|
|
317
|
+
const db = entry.db;
|
|
318
|
+
let out;
|
|
319
|
+
try {
|
|
320
|
+
const tx = (0, transactions_1.getActiveTransaction)(entry);
|
|
321
|
+
out = tx ? await tx.query(boundSql, params) : await db.query(boundSql, params);
|
|
322
|
+
}
|
|
323
|
+
catch (dbError) {
|
|
324
|
+
throw new errors_1.DatabaseError(dbError?.message || String(dbError), boundSql, dbError instanceof Error ? dbError : undefined);
|
|
325
|
+
}
|
|
326
|
+
if (Array.isArray(out)) {
|
|
327
|
+
const shaped = applyShape(out, labels.shape);
|
|
328
|
+
const transformed = labels.transform ? labels.transform(shaped) : shaped;
|
|
329
|
+
if (labels.validateSchema && !(0, validator_1.isValidationDisabled)()) {
|
|
330
|
+
if (Array.isArray(transformed)) {
|
|
331
|
+
for (const row of transformed)
|
|
332
|
+
(0, validator_1.validateOutput)(labels.validateSchema, row);
|
|
333
|
+
}
|
|
334
|
+
else if (transformed !== null && transformed !== undefined) {
|
|
335
|
+
(0, validator_1.validateOutput)(labels.validateSchema, transformed);
|
|
336
|
+
}
|
|
319
337
|
}
|
|
338
|
+
return transformed;
|
|
320
339
|
}
|
|
321
|
-
return
|
|
340
|
+
return out;
|
|
322
341
|
}
|
|
323
|
-
|
|
324
|
-
return out;
|
|
342
|
+
return pipeline();
|
|
325
343
|
};
|
|
326
344
|
return desc;
|
|
327
345
|
};
|