@technicity/data-service-generator 0.8.4 → 0.10.0-next.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.
Files changed (43) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +4 -3
  3. package/dist/runtime/Cache.d.ts +18 -0
  4. package/dist/runtime/Cache.js +90 -0
  5. package/dist/runtime/Runtime.d.ts +23 -0
  6. package/dist/runtime/Runtime.js +29 -0
  7. package/dist/runtime/RuntimeKSQL.d.ts +1 -1
  8. package/dist/runtime/RuntimeKSQL.js +13 -11
  9. package/dist/runtime/RuntimeMSSQL.d.ts +18 -14
  10. package/dist/runtime/RuntimeMSSQL.js +48 -43
  11. package/dist/runtime/RuntimeMySQL.d.ts +11 -12
  12. package/dist/runtime/RuntimeMySQL.js +46 -79
  13. package/dist/runtime/lib/create.d.ts +12 -0
  14. package/dist/runtime/lib/create.js +175 -0
  15. package/dist/runtime/lib/delete.d.ts +5 -0
  16. package/dist/runtime/lib/delete.js +43 -0
  17. package/dist/runtime/lib/error.d.ts +9 -0
  18. package/dist/runtime/lib/error.js +22 -0
  19. package/dist/runtime/lib/getData.d.ts +4 -0
  20. package/dist/runtime/lib/getData.js +227 -0
  21. package/dist/runtime/lib/getSqlAst.js +2 -2
  22. package/dist/runtime/lib/getWhere.d.ts +17 -0
  23. package/dist/runtime/lib/getWhere.js +228 -4
  24. package/dist/runtime/lib/prepareWhere.d.ts +2 -0
  25. package/dist/runtime/lib/prepareWhere.js +158 -0
  26. package/dist/runtime/lib/resolve.d.ts +10 -0
  27. package/dist/runtime/lib/resolve.js +66 -0
  28. package/dist/runtime/lib/shared.d.ts +22 -12
  29. package/dist/runtime/lib/shared.js +16 -728
  30. package/dist/runtime/lib/typeCastMSSQL.js +1 -1
  31. package/dist/runtime/lib/update.d.ts +4 -0
  32. package/dist/runtime/lib/update.js +143 -0
  33. package/dist/runtime/lib/utility.d.ts +5 -0
  34. package/dist/runtime/lib/utility.js +15 -0
  35. package/package.json +8 -7
  36. package/dist/runtime/lib/MSSQL.d.ts +0 -13
  37. package/dist/runtime/lib/MSSQL.js +0 -73
  38. package/dist/runtime/lib/SDKNotFoundError.d.ts +0 -4
  39. package/dist/runtime/lib/SDKNotFoundError.js +0 -10
  40. package/dist/runtime/lib/getDateTimeStringMySQL.d.ts +0 -1
  41. package/dist/runtime/lib/getDateTimeStringMySQL.js +0 -8
  42. package/dist/runtime/lib/stringifyWhere.d.ts +0 -18
  43. package/dist/runtime/lib/stringifyWhere.js +0 -228
@@ -1,277 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._prepareWhere = exports.whereNeedsProcessing = exports.postProcess = exports.MiddlewareHandler = exports.resolve = void 0;
4
- // @ts-ignore
5
- // import * as queryAST from "join-monster/dist/query-ast-to-sql-ast";
6
- // @ts-ignore
7
- // import arrToConnection from "join-monster/dist/array-to-connection";
8
- // @ts-ignore
9
- const batch_planner_1 = require("join-monster/dist/batch-planner");
3
+ exports.postProcess = exports.mapMappedFields = exports.hasMappedFields = exports.getScalarFields = exports.getTotalCount = exports.wrapListPaginationCursor = exports.getDateTimeStringMySQL = exports.wrapListPaginationLimitOffset = void 0;
10
4
  // @ts-ignore
11
5
  const util_1 = require("join-monster/dist/util");
12
- const async_hooks_1 = require("async_hooks");
13
6
  const _ = require("lodash/fp");
14
- const uuid_1 = require("uuid");
15
- const getSqlAst_1 = require("./getSqlAst");
16
- const getWhere_1 = require("./getWhere");
17
- const getDateTimeStringMySQL_1 = require("./getDateTimeStringMySQL");
7
+ const error_1 = require("./error");
18
8
  const cursor_1 = require("./cursor");
19
9
  const runTransforms_1 = require("./runTransforms");
20
- const addNullFallbacks_1 = require("./addNullFallbacks");
21
- const SDKNotFoundError_1 = require("./SDKNotFoundError");
22
- const stringifyWhere_1 = require("./stringifyWhere");
23
- const getOrderBy_1 = require("./getOrderBy");
24
- async function resolve(input, dbCall, formatQuery, beginTransaction, dialect, middlewareHandler, context) {
25
- // https://github.com/prisma/prisma/blob/822198e5ba21535364d20c86901b8c3778ebf6a3/packages/client/src/runtime/getPrismaClient.ts#L1087
26
- let index = -1;
27
- if (middlewareHandler.length() > 0) {
28
- const resource = new async_hooks_1.AsyncResource("sdk-request");
29
- const params = input;
30
- const consumer = (paramsMaybeMutated) => {
31
- const nextMiddleware = middlewareHandler.get(++index);
32
- if (nextMiddleware != null) {
33
- return nextMiddleware(paramsMaybeMutated, consumer);
34
- }
35
- const paramsChanged = { ...input, ...params };
36
- return _resolve(paramsChanged, dbCall, formatQuery, beginTransaction, dialect, context);
37
- };
38
- return resource.runInAsyncScope(() => consumer(params));
39
- }
40
- return _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context);
41
- }
42
- exports.resolve = resolve;
43
- function _resolve(input, dbCall, formatQuery, beginTransaction, dialect, context) {
44
- if (input.action === "findUnique") {
45
- return getData(input, dbCall, formatQuery, dialect);
46
- }
47
- if (input.action === "findMany") {
48
- return getData(input, dbCall, formatQuery, dialect);
49
- }
50
- if (input.action === "findManyPaginated") {
51
- return getData(input, dbCall, formatQuery, dialect);
52
- }
53
- if (input.action === "create") {
54
- return create(input, dbCall, formatQuery, beginTransaction, dialect, context);
55
- }
56
- if (input.action === "update") {
57
- return update(input, dbCall, formatQuery, dialect);
58
- }
59
- if (input.action === "updateMany") {
60
- return updateMany(input, dbCall, formatQuery, dialect);
61
- }
62
- if (input.action === "delete") {
63
- return del(input, dbCall, formatQuery, dialect);
64
- }
65
- if (input.action === "deleteMany") {
66
- return deleteMany(input, dbCall, formatQuery, dialect);
67
- }
68
- throw new Error("Invalid action: " + input.action);
69
- }
70
- class MiddlewareHandler {
71
- constructor() {
72
- this._middlewares = [];
73
- }
74
- register(middleware) {
75
- this._middlewares.push(middleware);
76
- }
77
- get(id) {
78
- return this._middlewares[id];
79
- }
80
- has(id) {
81
- return !!this._middlewares[id];
82
- }
83
- length() {
84
- return this._middlewares.length;
85
- }
86
- }
87
- exports.MiddlewareHandler = MiddlewareHandler;
88
- async function getData(input, dbCall, formatQuery, dialect) {
89
- const context = {};
90
- const action = input.action;
91
- const primaryKey = input.artifacts[input.resource].primaryKey;
92
- let paginationType;
93
- let limit = undefined;
94
- let offset = undefined;
95
- let rowWithMatchingCursor = undefined;
96
- if (action === "findManyPaginated") {
97
- if (input.args?.$paginate == null) {
98
- throw new Error("$paginate required but not supplied");
99
- }
100
- if (typeof input?.args?.$paginate?.limit === "number") {
101
- paginationType = "limit-offset";
102
- limit = input.args.$paginate.limit;
103
- offset = input.args.$paginate.offset;
104
- }
105
- else if (typeof input?.args?.$paginate?.first === "number" ||
106
- typeof input?.args?.$paginate?.last === "number") {
107
- paginationType = "cursor";
108
- limit = (typeof input?.args?.$paginate?.first === "number"
109
- ? input?.args?.$paginate?.first
110
- : input?.args?.$paginate?.last);
111
- // + 1 to peek if there is more data
112
- limit += 1;
113
- if (input.args.$paginate.after != null ||
114
- input.args.$paginate.before != null) {
115
- const cursor = input.args.$paginate.after != null
116
- ? input.args.$paginate.after
117
- : input.args.$paginate.before;
118
- rowWithMatchingCursor = await dbCall(formatQuery("SELECT * FROM ?? WHERE ?? = ?", [
119
- input.resource,
120
- primaryKey,
121
- (0, cursor_1.decodeCursor)(cursor),
122
- ])).then((xs) => xs[0]);
123
- if (rowWithMatchingCursor == null) {
124
- throw new Error(`Invalid cursor: ${cursor}`);
125
- }
126
- }
127
- }
128
- else {
129
- throw new Error(`Invalid $paginate: ${input?.args?.$paginate}`);
130
- }
131
- }
132
- else if (action === "findMany") {
133
- if (typeof input?.args?.$limit === "number") {
134
- limit = input?.args?.$limit;
135
- }
136
- }
137
- // we need to read the query AST and build a new "SQL AST" from which the SQL and
138
- // const sqlAST = queryAST.queryASTToSqlAST(resolveInfo, options, context);
139
- const fields = input.fields ?? getScalarFields(input.resource, input.artifacts);
140
- const orderByListPaginatedRootResult =
141
- // MSSQL's OFFSET and FETCH requires ORDER BY, so we need to provide a fallback
142
- dialect === "mssql" && paginationType === "limit-offset"
143
- ? {
144
- orderBy: (0, getOrderBy_1.getOrderBy)(input.args, primaryKey)?.orderBy ?? [
145
- { column: primaryKey, direction: "asc" },
146
- ],
147
- flip: false,
148
- }
149
- : action === "findManyPaginated"
150
- ? (0, getOrderBy_1.getOrderBy)(input.args, primaryKey)
151
- : undefined;
152
- const grabMany = action === "findMany" ||
153
- action === "findManyPaginated" ||
154
- action === "updateMany" ||
155
- action === "deleteMany";
156
- const sqlAST = (0, getSqlAst_1.getSqlAst)({
157
- ...input,
158
- table: input.resource,
159
- fieldName: "data",
160
- fields,
161
- getWhere: getWhere_1.getWhere,
162
- orderBy: orderByListPaginatedRootResult?.orderBy,
163
- rowWithMatchingCursor,
164
- dialect,
165
- grabMany,
166
- });
167
- const options = { dialect };
168
- let { sql, shapeDefinition } = await (0, util_1.compileSqlAST)(sqlAST, context, options);
169
- if (!sql) {
170
- // return {};
171
- throw new Error("No SQL");
172
- }
173
- // TODO - remove if limit support added for mysql dialect
174
- if (action === "findMany" || action === "findManyPaginated") {
175
- if (typeof limit === "number") {
176
- const escape = (0, stringifyWhere_1.getEscape)(dialect);
177
- if (dialect === "mssql") {
178
- if (typeof offset === "number") {
179
- sql += ` OFFSET ${escape(offset)} ROWS FETCH NEXT ${escape(limit)} ROWS ONLY`;
180
- }
181
- else {
182
- sql = sql.replace("SELECT", `SELECT TOP ${escape(limit)}`);
183
- }
184
- }
185
- else {
186
- sql += ` LIMIT ${escape(limit)}`;
187
- if (typeof offset === "number") {
188
- sql += ` OFFSET ${escape(offset)}`;
189
- }
190
- }
191
- }
192
- }
193
- // call their function for querying the DB, handle the different cases, do some validation, return a promise of the object
194
- let data = await (0, util_1.handleUserDbCall)(dbCall, sql, sqlAST, shapeDefinition);
195
- // if they are paginating, we'll get back an array which is essentially a "slice" of the whole data.
196
- // this function goes through the data tree and converts the arrays to Connection Objects
197
- // data = arrToConnection(data, sqlAST);
198
- // so far we handled the first "batch". up until now, additional batches were ignored
199
- // this function recursively scanss the sqlAST and runs remaining batches
200
- await (0, batch_planner_1.default)(sqlAST, data, dbCall, context, options);
201
- (0, addNullFallbacks_1.addNullFallbacks)(sqlAST, data);
202
- // We only need to remove extra keys if input.fields isn't
203
- // specified, since otherwise there wouldn't be extra keys
204
- const shouldRemoveExtraKeys = input.fields != null;
205
- if (action !== "findManyPaginated") {
206
- // Remove additional keys that are added for batches and joins
207
- // Do later for `listPaginated`, since the `id` is needed for
208
- // creating the cursor
209
- postProcess(data, fields, shouldRemoveExtraKeys);
210
- }
211
- // check for batch data
212
- if (Array.isArray(data)) {
213
- // TODO - not sure why this code exists in original
214
- // source code of join-monster; doesn't make sense to me.
215
- // const childrenToCheck = sqlAST.children.filter(
216
- // (child: any) => child.sqlBatch
217
- // );
218
- // data = data.filter((d) => {
219
- // for (const child of childrenToCheck) {
220
- // if (d[child.fieldName] == null) {
221
- // return false;
222
- // }
223
- // }
224
- // return true;
225
- // });
226
- if (action === "findManyPaginated") {
227
- const argsTotalCount = input.args && _.cloneDeep(input.args);
228
- if (argsTotalCount != null) {
229
- if (argsTotalCount.$paginate != null) {
230
- // We don't want the where clause to include cursor-related stuff
231
- delete argsTotalCount.$paginate.after;
232
- delete argsTotalCount.$paginate.before;
233
- // We don't need offset
234
- delete argsTotalCount.$paginate.offset;
235
- }
236
- }
237
- const sqlASTTotalCount = (0, getSqlAst_1.getSqlAst)({
238
- ...input,
239
- table: input.resource,
240
- fieldName: "data",
241
- args: argsTotalCount,
242
- // Because we're going to manually set children anyway
243
- fields: [],
244
- getWhere: getWhere_1.getWhere,
245
- // We don't want the where clause to include cursor-related stuff
246
- rowWithMatchingCursor: null,
247
- dialect,
248
- grabMany: true,
249
- });
250
- // Because orderBy doesn't matter for total count.
251
- // getOrderBy adds an element if paginating, so deleting args.$orderBy
252
- // isn't sufficient.
253
- delete sqlASTTotalCount.orderBy;
254
- const totalCount = await getTotalCount(sqlASTTotalCount, dbCall, context, options);
255
- if (paginationType === "cursor") {
256
- data = wrapListPaginationCursor(data, input.args, orderByListPaginatedRootResult.flip, (xs) => {
257
- postProcess(xs, fields, shouldRemoveExtraKeys);
258
- }, input.artifacts[input.resource].primaryKey, totalCount);
259
- }
260
- else {
261
- postProcess(data, fields, shouldRemoveExtraKeys);
262
- data = wrapListPaginationLimitOffset(data, totalCount);
263
- }
264
- }
265
- return data;
266
- }
267
- if (data == null && !grabMany) {
268
- throw new SDKNotFoundError_1.SDKNotFoundError();
269
- }
270
- return data;
271
- }
272
10
  function wrapListPaginationLimitOffset(data, totalCount) {
273
11
  return { paginationInfo: { totalCount }, results: data };
274
12
  }
13
+ exports.wrapListPaginationLimitOffset = wrapListPaginationLimitOffset;
14
+ function getDateTimeStringMySQL(dateTimeString) {
15
+ return dateTimeString.replace("T", " ").slice(0, 19);
16
+ }
17
+ exports.getDateTimeStringMySQL = getDateTimeStringMySQL;
275
18
  // Not recursive at the moment; only supported at the root.
276
19
  // TODO - remove if support for pagination for mysql dialect
277
20
  // is added (I doubt it)
@@ -303,6 +46,7 @@ function wrapListPaginationCursor(data, args, flip, cb, primaryKey, totalCount)
303
46
  results: data,
304
47
  };
305
48
  }
49
+ exports.wrapListPaginationCursor = wrapListPaginationCursor;
306
50
  async function getTotalCount(sqlASTTotalCount, dbCall, context, options) {
307
51
  // Replace field selection with `COUNT(*)`
308
52
  const fieldNameTotalCount = "totalCount";
@@ -318,332 +62,13 @@ async function getTotalCount(sqlASTTotalCount, dbCall, context, options) {
318
62
  const totalCount = await dbCall(sqlTotalCount).then((xs) => xs[0][fieldNameTotalCount]);
319
63
  return totalCount;
320
64
  }
321
- const runCreateTreeMySQL = async (table, referencedKey, referencedKeyValue, columns, values, dbCall, formatQuery) => {
322
- let allColumns = columns;
323
- if (typeof referencedKey === "string") {
324
- allColumns = allColumns.slice().map((xs) => xs.concat(referencedKey));
325
- }
326
- let allValues = values;
327
- if (referencedKeyValue != null) {
328
- allValues = allValues.slice().map((xs) => xs.concat(referencedKeyValue));
329
- }
330
- return Promise.all(allColumns.map((cs, i) => dbCall(formatQuery(`INSERT INTO ?? (??) VALUES (?)`, [table, cs, allValues[i]])).then((x) => x.insertId)));
331
- };
332
- // This doesn't use bulk inserts because:
333
- // 1. columns aren't necessarily uniform
334
- // 2. We don't want to do backflips to get all the inserted IDs
335
- const runCreateTreeMSSQL = async (table, referencedKey, referencedKeyValue, columns, values, dbCall, formatQuery) => {
336
- let allColumns = columns;
337
- if (typeof referencedKey === "string") {
338
- allColumns = allColumns.slice().map((xs) => xs.concat(referencedKey));
339
- }
340
- let allValues = values;
341
- if (referencedKeyValue != null) {
342
- allValues = allValues.slice().map((xs) => xs.concat(referencedKeyValue));
343
- }
344
- // https://github.com/tediousjs/node-mssql/issues/302
345
- // return Promise.all(
346
- // allColumns.map((cs, i) =>
347
- // dbCall(
348
- // formatQuery(
349
- // `INSERT INTO ?? (??) VALUES (?) SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]`,
350
- // [table, cs, allValues[i]]
351
- // )
352
- // ).then((xs) => xs[0]["SCOPE_IDENTITY"])
353
- // )
354
- // );
355
- let out = [];
356
- let i = 0;
357
- for (let cs of allColumns) {
358
- out.push(await dbCall(formatQuery(`INSERT INTO ?? (??) VALUES (?) SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]`, [table, cs, allValues[i]])).then((xs) => xs[0]["SCOPE_IDENTITY"]));
359
- i += 1;
360
- }
361
- return out;
362
- };
363
- async function create(input, dbCall, formatQuery, beginTransaction, dialect, context) {
364
- async function _create() {
365
- // Shallow clone, as we're going to mutate later
366
- let data = { ...input.data };
367
- const tableArtifacts = input.artifacts[input.resource];
368
- // Top-level only
369
- if (hasMappedFields(input.artifacts, input.resource, data)) {
370
- await mapMappedFields(tableArtifacts, data, dbCall, formatQuery);
371
- }
372
- const hasChildren = Object.keys(data).some((k) => {
373
- const oneToManyRelation = tableArtifacts.relationFields[k];
374
- if (oneToManyRelation == null) {
375
- return false;
376
- }
377
- if (oneToManyRelation.type === "one-to-many__many-to-one" &&
378
- oneToManyRelation.kind === "one-to-many") {
379
- return true;
380
- }
381
- });
382
- if (hasChildren) {
383
- const { dbCall: dbCallTransaction, commit } = await beginTransaction();
384
- const id = await runCreateTree(getCreateTree([data], input.resource, null, context?.specialCaseUuidColumn, dialect, input.artifacts), null, dialect === "mssql" ? runCreateTreeMSSQL : runCreateTreeMySQL, dbCallTransaction, formatQuery, dialect).then((xs) => xs[0]);
385
- await commit();
386
- return id;
387
- }
388
- else {
389
- data = processCreateData(data, tableArtifacts, dialect, context?.specialCaseUuidColumn);
390
- if (dialect === "mysql") {
391
- const inserted = await dbCall(formatQuery("INSERT INTO ?? SET ?", [input.resource, data]));
392
- return inserted.insertId;
393
- }
394
- else {
395
- const columns = Object.keys(data);
396
- const values = Object.values(data);
397
- const inserted = await dbCall(formatQuery(`INSERT INTO ?? (??) VALUES (?) SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY]`, [input.resource, columns, values]));
398
- return inserted[0]["SCOPE_IDENTITY"];
399
- }
400
- }
401
- }
402
- const id = await _create();
403
- return getData({ ...input, args: { $where: { id } } }, dbCall, formatQuery, dialect);
404
- }
405
- function processCreateData(data, tableArtifacts, dialect, specialCaseUuidColumn) {
406
- let out = { ...data };
407
- if (dialect === "mysql" && tableArtifacts.dateTimeFieldsCount > 0) {
408
- for (let k in tableArtifacts.dateTimeFields) {
409
- if (out[k] != null) {
410
- out[k] = (0, getDateTimeStringMySQL_1.getDateTimeStringMySQL)(out[k]);
411
- }
412
- }
413
- }
414
- // Delete keys with value of undefined
415
- for (let k in out) {
416
- if (out[k] === void 0) {
417
- delete out[k];
418
- }
419
- }
420
- const scalarFieldSet = new Set(tableArtifacts.scalarFields);
421
- if (specialCaseUuidColumn &&
422
- scalarFieldSet.has("uuid") &&
423
- !Object.prototype.hasOwnProperty.call(out, "uuid")) {
424
- out["uuid"] = (0, uuid_1.v4)();
425
- }
426
- return out;
427
- }
428
- async function runCreateTree(tree, referencedKeyValue, runCreateTreeSQL, dbCall, formatQuery, dialect) {
429
- const ids = await runCreateTreeSQL(tree.table, tree.referencedKey, referencedKeyValue, tree.columns, tree.values, dbCall, formatQuery);
430
- if (tree.children?.length > 0) {
431
- // https://github.com/tediousjs/node-mssql/issues/302
432
- if (dialect === "mssql") {
433
- const idIndexes = Array(ids.length)
434
- .fill(null)
435
- .map((_, i) => i);
436
- for (let i of idIndexes) {
437
- for (let c of tree.children[i]) {
438
- await runCreateTree(c, ids[i], runCreateTreeSQL, dbCall, formatQuery, dialect);
439
- }
440
- }
441
- }
442
- else {
443
- await Promise.all(ids.flatMap((id, i) => tree.children[i].map((c) => runCreateTree(c, id, runCreateTreeSQL, dbCall, formatQuery, dialect))));
444
- }
445
- }
446
- return ids;
447
- }
448
- function getCreateTree(data, table, referencedKey, specialCaseUuidColumn, dialect, artifacts) {
449
- const tableArtifacts = artifacts[table];
450
- const scalarFieldSet = new Set(tableArtifacts.scalarFields);
451
- let out = {
452
- table,
453
- referencedKey,
454
- columns: [],
455
- values: [],
456
- children: [],
457
- };
458
- for (let i = 0; i < data.length; i++) {
459
- let d = data[i];
460
- if (Object.keys(d).length === 0) {
461
- continue;
462
- }
463
- d = processCreateData(d, tableArtifacts, dialect, specialCaseUuidColumn);
464
- out.columns[i] = [];
465
- out.values[i] = [];
466
- out.children[i] = [];
467
- for (let k in d) {
468
- if (scalarFieldSet.has(k)) {
469
- out.columns[i].push(k);
470
- const v = d[k];
471
- out.values[i].push(v);
472
- continue;
473
- }
474
- const oneToManyRelation = tableArtifacts.relationFields[k];
475
- if (oneToManyRelation == null ||
476
- oneToManyRelation.type !== "one-to-many__many-to-one" ||
477
- oneToManyRelation.kind !== "one-to-many") {
478
- continue;
479
- }
480
- if (!Array.isArray(d[k]?.$create)) {
481
- throw new Error("Invalid data: " + k);
482
- }
483
- out.children[i].push(getCreateTree(d[k].$create, oneToManyRelation.table, oneToManyRelation.relation.referencedKey, specialCaseUuidColumn, dialect, artifacts));
484
- }
485
- }
486
- return out;
487
- }
488
- async function update(input, dbCall, formatQuery, dialect) {
489
- async function _update() {
490
- const escapeId = (0, stringifyWhere_1.getEscapeId)(dialect);
491
- const tableArtifacts = input.artifacts[input.resource];
492
- const where = (0, getWhere_1.getWhere)(escapeId(input.resource), input.args, dialect);
493
- if (where == null) {
494
- throw new Error("Null where");
495
- }
496
- const current = await dbCall(formatQuery("SELECT * FROM ?? WHERE " + where, [input.resource])).then((xs) => xs[0]);
497
- if (current == null) {
498
- throw new SDKNotFoundError_1.SDKNotFoundError();
499
- }
500
- // Shallow clone, as we're going to mutate later
501
- const data = { ...input.data };
502
- if (hasMappedFields(input.artifacts, input.resource, data)) {
503
- await mapMappedFields(tableArtifacts, data, dbCall, formatQuery);
504
- }
505
- if (dialect === "mysql" && tableArtifacts.dateTimeFieldsCount > 0) {
506
- for (let k in tableArtifacts.dateTimeFields) {
507
- if (data[k] != null) {
508
- data[k] = (0, getDateTimeStringMySQL_1.getDateTimeStringMySQL)(data[k]);
509
- }
510
- }
511
- }
512
- // Delete keys with value of undefined
513
- for (let k in data) {
514
- if (data[k] === void 0) {
515
- delete data[k];
516
- }
517
- }
518
- // Nothing to update
519
- if (Object.keys(data).length === 0) {
520
- return true;
521
- }
522
- await dbCall(getUpdateQuery(input.resource, data, where, dialect, formatQuery));
523
- return true;
524
- }
525
- await _update();
526
- return getData(input, dbCall, formatQuery, dialect);
527
- }
528
- function getUpdateQuery(table, data, where, dialect, formatQuery) {
529
- // Assumes `data` is not empty
530
- const escapeId = (0, stringifyWhere_1.getEscapeId)(dialect);
531
- const escape = (0, stringifyWhere_1.getEscape)(dialect);
532
- let q = "UPDATE ?? ";
533
- let values = [table];
534
- let opsStrs = [];
535
- let dataRegular = {};
536
- for (let k in data) {
537
- const v = data[k];
538
- if (typeof v === "object" && v != null && Object.keys(v).length === 1) {
539
- const _entries = Object.entries(v)?.[0];
540
- const op = _entries?.[0];
541
- const vv = _entries?.[1];
542
- if (op === "$prepend") {
543
- opsStrs.push(`${table}.${escapeId(k)} = CASE WHEN ${table}.${escapeId(k)} IS NULL THEN NULL ELSE CONCAT(${escape(vv)}, ${table}.${escapeId(k)}) END`);
544
- continue;
545
- }
546
- if (op === "$append") {
547
- opsStrs.push(`${table}.${escapeId(k)} = CASE WHEN ${table}.${escapeId(k)} IS NULL THEN NULL ELSE CONCAT(${table}.${escapeId(k)}, ${escape(vv)}) END`);
548
- continue;
549
- }
550
- if (op === "$increment") {
551
- opsStrs.push(`${table}.${escapeId(k)} = ${table}.${escapeId(k)} + ${escape(vv)}`);
552
- continue;
553
- }
554
- if (op === "$decrement") {
555
- opsStrs.push(`${table}.${escapeId(k)} = ${table}.${escapeId(k)} - ${escape(vv)}`);
556
- continue;
557
- }
558
- dataRegular[k] = v;
559
- }
560
- dataRegular[k] = v;
561
- }
562
- if (opsStrs.length > 0) {
563
- q += `SET ${opsStrs.join(", ")}`;
564
- }
565
- if (Object.keys(dataRegular).length > 0) {
566
- if (opsStrs.length > 0) {
567
- q += ", ?";
568
- }
569
- else {
570
- q += "SET ?";
571
- }
572
- values.push(dataRegular);
573
- }
574
- q += ` WHERE ${where}`;
575
- return formatQuery(q, values);
576
- }
577
- async function updateMany(input, dbCall, formatQuery, dialect) {
578
- async function _updateMany() {
579
- const escapeId = (0, stringifyWhere_1.getEscapeId)(dialect);
580
- const tableArtifacts = input.artifacts[input.resource];
581
- const where = (0, getWhere_1.getWhere)(escapeId(input.resource), input.args, dialect);
582
- if (where == null) {
583
- throw new Error("Null where");
584
- }
585
- // Shallow clone, as we're going to mutate later
586
- const data = { ...input.data };
587
- if (hasMappedFields(input.artifacts, input.resource, data)) {
588
- await mapMappedFields(tableArtifacts, data, dbCall, formatQuery);
589
- }
590
- if (dialect === "mysql" && tableArtifacts.dateTimeFieldsCount > 0) {
591
- for (let k in tableArtifacts.dateTimeFields) {
592
- if (data[k] != null) {
593
- data[k] = (0, getDateTimeStringMySQL_1.getDateTimeStringMySQL)(data[k]);
594
- }
595
- }
596
- }
597
- // Delete keys with value of undefined
598
- for (let k in data) {
599
- if (data[k] === void 0) {
600
- delete data[k];
601
- }
602
- }
603
- // Nothing to update
604
- if (Object.keys(data).length === 0) {
605
- return [];
606
- }
607
- await dbCall(getUpdateQuery(input.resource, data, where, dialect, formatQuery));
608
- return true;
609
- }
610
- await _updateMany();
611
- return getData(input, dbCall, formatQuery, dialect);
612
- }
613
- async function del(input, dbCall, formatQuery, dialect) {
614
- const _findOne = Object.entries(input.args.$where)[0];
615
- const findOne = { key: _findOne[0], value: _findOne[1] };
616
- const current = await dbCall(formatQuery("SELECT * FROM ?? WHERE ?? = ?", [
617
- input.resource,
618
- findOne.key,
619
- findOne.value,
620
- ])).then((xs) => xs[0]);
621
- if (current == null) {
622
- throw new SDKNotFoundError_1.SDKNotFoundError();
623
- }
624
- await dbCall(formatQuery("DELETE FROM ?? WHERE ?? = ?", [
625
- input.resource,
626
- findOne.key,
627
- findOne.value,
628
- ]));
629
- return true;
630
- }
631
- async function deleteMany(input, dbCall, formatQuery, dialect) {
632
- const escapeId = (0, stringifyWhere_1.getEscapeId)(dialect);
633
- const where = (0, getWhere_1.getWhere)(escapeId(input.resource), input.args, dialect);
634
- if (where == null) {
635
- throw new Error("Null where");
636
- }
637
- const sql = "DELETE FROM ?? WHERE " + where;
638
- const values = [input.resource];
639
- await dbCall(formatQuery(sql, values));
640
- return true;
641
- }
65
+ exports.getTotalCount = getTotalCount;
642
66
  function getScalarFields(table, artifacts) {
643
67
  return artifacts[table].scalarFields;
644
68
  }
69
+ exports.getScalarFields = getScalarFields;
645
70
  function hasMappedFields(artifacts, table, data) {
646
- const mappedFields = artifacts[table].mappedFields;
71
+ const { mappedFields } = artifacts[table];
647
72
  if (mappedFields == null) {
648
73
  return false;
649
74
  }
@@ -651,6 +76,7 @@ function hasMappedFields(artifacts, table, data) {
651
76
  const dataKeys = Object.keys(data);
652
77
  return dataKeys.some((k) => keys.has(k));
653
78
  }
79
+ exports.hasMappedFields = hasMappedFields;
654
80
  async function mapMappedFields(artifactsForTable, data, dbCall, formatQuery) {
655
81
  for (let k in data) {
656
82
  const v = data[k];
@@ -680,7 +106,7 @@ async function mapMappedFields(artifactsForTable, data, dbCall, formatQuery) {
680
106
  w,
681
107
  ])).then((xs) => xs[0]?.[mappedField.referencedKey]);
682
108
  if (result == null) {
683
- throw new SDKNotFoundError_1.SDKNotFoundError();
109
+ throw new error_1.SDKNotFoundError();
684
110
  }
685
111
  return result;
686
112
  }));
@@ -694,13 +120,14 @@ async function mapMappedFields(artifactsForTable, data, dbCall, formatQuery) {
694
120
  v,
695
121
  ])).then((xs) => xs[0]?.[mappedField.referencedKey]);
696
122
  if (result == null) {
697
- throw new SDKNotFoundError_1.SDKNotFoundError();
123
+ throw new error_1.SDKNotFoundError();
698
124
  }
699
125
  data[mappedField.foreignKey] = result;
700
126
  delete data[k];
701
127
  }
702
128
  }
703
129
  }
130
+ exports.mapMappedFields = mapMappedFields;
704
131
  // 1. Remove additional keys added to data for batches and joins
705
132
  // 2. Execute `transform` functions if they exist
706
133
  function postProcess(data, fields, shouldRemoveExtraKeys) {
@@ -714,7 +141,7 @@ function removeExtraKeys(data, fields) {
714
141
  if (data == null || (Array.isArray(data) && data[0] == null)) {
715
142
  return;
716
143
  }
717
- let fieldKeys = [];
144
+ const fieldKeys = [];
718
145
  for (let x of fields) {
719
146
  if (typeof x === "string") {
720
147
  fieldKeys.push(x);
@@ -751,142 +178,3 @@ function removeExtraKeys(data, fields) {
751
178
  }
752
179
  }
753
180
  }
754
- function whereNeedsProcessing(where) {
755
- return JSON.stringify(where).includes("Uuid");
756
- }
757
- exports.whereNeedsProcessing = whereNeedsProcessing;
758
- async function _prepareWhere(artifacts, table, data, dbCall, formatQuery) {
759
- const mappedFields = artifacts[table].mappedFields;
760
- let out = {};
761
- await traverseWhere(data, async (where, ptr, parentPtr, root) => {
762
- const path = ptr.split("/").slice(1);
763
- const opIndex = path.length - 1;
764
- if (ops.includes(path[opIndex])) {
765
- const newPath = path.slice();
766
- const index = newPath.length - 2;
767
- const key = newPath[index];
768
- const mappedField = mappedFields?.[key];
769
- if (mappedField != null) {
770
- newPath[index] = mappedField.foreignKey;
771
- if (Array.isArray(where)) {
772
- const newVal = await Promise.all(where.map((v) => dbCall(formatQuery("SELECT ?? FROM ?? WHERE ?? = ?", [
773
- mappedField.referencedKey,
774
- mappedField.referencedTable,
775
- mappedField.name,
776
- v,
777
- ])).then((xs) => xs[0]?.[mappedField.referencedKey])));
778
- if (newVal.some((x) => x == null)) {
779
- throw new SDKNotFoundError_1.SDKNotFoundError();
780
- }
781
- out = _.set(newPath, newVal, out);
782
- }
783
- else {
784
- const newVal = await dbCall(formatQuery("SELECT ?? FROM ?? WHERE ?? = ?", [
785
- mappedField.referencedKey,
786
- mappedField.referencedTable,
787
- mappedField.name,
788
- where,
789
- ])).then((xs) => xs[0]?.[mappedField.referencedKey]);
790
- if (newVal == null) {
791
- throw new SDKNotFoundError_1.SDKNotFoundError();
792
- }
793
- out = _.set(newPath, newVal, out);
794
- }
795
- out = _.unset(path.slice(0, path.length - 1), out);
796
- return;
797
- }
798
- }
799
- else {
800
- const key = path[path.length - 1];
801
- const mappedField = mappedFields?.[key];
802
- if (mappedField != null) {
803
- const newPath = path
804
- .slice(0, path.length - 1)
805
- .concat(mappedField.foreignKey);
806
- if (Array.isArray(where)) {
807
- const newVal = await Promise.all(where.map((v) => dbCall(formatQuery("SELECT ?? FROM ?? WHERE ?? = ?", [
808
- mappedField.referencedKey,
809
- mappedField.referencedTable,
810
- mappedField.name,
811
- v,
812
- ])).then((xs) => xs[0]?.[mappedField.referencedKey])));
813
- if (newVal.some((x) => x == null)) {
814
- throw new SDKNotFoundError_1.SDKNotFoundError();
815
- }
816
- out = _.set(newPath, newVal, out);
817
- }
818
- else {
819
- const newVal = await dbCall(formatQuery("SELECT ?? FROM ?? WHERE ?? = ?", [
820
- mappedField.referencedKey,
821
- mappedField.referencedTable,
822
- mappedField.name,
823
- where,
824
- ])).then((xs) => xs[0]?.[mappedField.referencedKey]);
825
- if (newVal == null) {
826
- throw new SDKNotFoundError_1.SDKNotFoundError();
827
- }
828
- out = _.set(newPath, newVal, out);
829
- }
830
- out = _.unset(path, out);
831
- }
832
- else {
833
- out = path.length > 0 ? _.set(path, where, out) : where;
834
- }
835
- }
836
- });
837
- return out;
838
- }
839
- exports._prepareWhere = _prepareWhere;
840
- const ops = [
841
- "$eq",
842
- "$neq",
843
- "$gt",
844
- "$gte",
845
- "$lt",
846
- "$lte",
847
- "$in",
848
- "$nin",
849
- "$like",
850
- "$nlike",
851
- "$btwn",
852
- "$nbtwn",
853
- ];
854
- async function traverseWhere(where, cb) {
855
- return await _traverseWhere(cb, where, "", where);
856
- }
857
- const _traverseWhere = async function (cb, where, ptr, root, parentPtr) {
858
- await cb(where, ptr, parentPtr, root);
859
- if (where && typeof where == "object" && !Array.isArray(where)) {
860
- for (let key in where) {
861
- const sch = where[key];
862
- if (key === "$and" || key == "$or") {
863
- await Promise.all(sch.map(async (s, i) => {
864
- await _traverseWhere(cb, s, ptr + "/" + key + "/" + i, root, ptr
865
- // key,
866
- // where,
867
- // parentPtr,
868
- // i
869
- );
870
- }));
871
- }
872
- else if (typeof sch === "object") {
873
- for (let prop in sch) {
874
- await _traverseWhere(cb, sch[prop], ptr + "/" + key + "/" + escapePtr(prop), root, ptr
875
- // key,
876
- // where,
877
- // prop
878
- );
879
- }
880
- }
881
- else {
882
- await _traverseWhere(cb, sch, ptr + "/" + key, root, ptr
883
- // key,
884
- // where
885
- );
886
- }
887
- }
888
- }
889
- };
890
- function escapePtr(str) {
891
- return str.replace(/~/g, "~0").replace(/\//g, "~1");
892
- }