@technicity/data-service-generator 0.14.1 → 0.14.2

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 (34) hide show
  1. package/dist/generation/generate.d.ts +1 -0
  2. package/dist/generation/generate.js +916 -309
  3. package/dist/runtime/Cache.js +6 -3
  4. package/dist/runtime/IRuntime.d.ts +46 -17
  5. package/dist/runtime/RuntimeMSSQL.d.ts +7 -1
  6. package/dist/runtime/RuntimeMSSQL.js +4 -4
  7. package/dist/runtime/RuntimeMySQL.d.ts +3 -1
  8. package/dist/runtime/RuntimeMySQL.js +33 -7
  9. package/dist/runtime/RuntimeSQLite.d.ts +38 -0
  10. package/dist/runtime/RuntimeSQLite.js +135 -0
  11. package/dist/runtime/lib/MSSQL.d.ts +2 -1
  12. package/dist/runtime/lib/MSSQL.js +36 -8
  13. package/dist/runtime/lib/MySQL.d.ts +1 -1
  14. package/dist/runtime/lib/MySQL.js +15 -2
  15. package/dist/runtime/lib/addNullFallbacks.test.d.ts +1 -0
  16. package/dist/runtime/lib/addNullFallbacks.test.js +206 -0
  17. package/dist/runtime/lib/getSqlAst.js +158 -121
  18. package/dist/runtime/lib/shared.d.ts +1 -2
  19. package/dist/runtime/lib/shared.js +180 -71
  20. package/dist/runtime/lib/stringifyWhere.js +39 -12
  21. package/dist/runtime/lib/stringifyWhere.test.d.ts +1 -0
  22. package/dist/runtime/lib/stringifyWhere.test.js +236 -0
  23. package/dist/runtime/lib/typeCastMSSQL.js +24 -1
  24. package/dist/traverseFieldArgs.d.ts +2 -2
  25. package/dist/traverseFieldArgs.js +8 -3
  26. package/dist/traverseFieldArgs.test.d.ts +1 -0
  27. package/dist/traverseFieldArgs.test.js +56 -0
  28. package/package.json +1 -1
  29. package/dist/ksql.d.ts +0 -15
  30. package/dist/ksql.js +0 -55
  31. package/dist/runtime/RuntimeKSQL.d.ts +0 -19
  32. package/dist/runtime/RuntimeKSQL.js +0 -446
  33. package/dist/runtime/lib/runTransforms.d.ts +0 -2
  34. package/dist/runtime/lib/runTransforms.js +0 -36
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const globals_1 = require("@jest/globals");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const addNullFallbacks_1 = require("./addNullFallbacks");
9
+ (0, globals_1.describe)("addNullFallbacks", () => {
10
+ // The actual AST has other fields like `args` that
11
+ // aren't relevant to the function
12
+ const sqlAST = {
13
+ type: "table",
14
+ name: "Session",
15
+ as: "Session",
16
+ fieldName: "session",
17
+ grabMany: false,
18
+ children: [
19
+ {
20
+ type: "column",
21
+ name: "id",
22
+ fieldName: "id",
23
+ as: "a"
24
+ },
25
+ {
26
+ type: "table",
27
+ name: "SessionPlan",
28
+ as: "SessionPlan",
29
+ fieldName: "sessionPlan",
30
+ grabMany: false,
31
+ children: [
32
+ {
33
+ type: "column",
34
+ name: "id",
35
+ fieldName: "id",
36
+ as: "a"
37
+ },
38
+ {
39
+ type: "column",
40
+ name: "uuid",
41
+ fieldName: "uuid",
42
+ as: "c"
43
+ },
44
+ {
45
+ type: "column",
46
+ name: "id",
47
+ fieldName: "id",
48
+ as: "a"
49
+ }
50
+ ]
51
+ }
52
+ ]
53
+ };
54
+ (0, globals_1.test)("should work for object", () => {
55
+ const data = {
56
+ id: 1,
57
+ sessionPlanId: null,
58
+ sessionPlan: undefined
59
+ };
60
+ (0, addNullFallbacks_1.addNullFallbacks)(sqlAST, data);
61
+ strict_1.default.deepEqual(data, {
62
+ id: 1,
63
+ sessionPlanId: null,
64
+ sessionPlan: null
65
+ });
66
+ });
67
+ (0, globals_1.test)("should work for array", () => {
68
+ const data = [
69
+ {
70
+ id: 1,
71
+ sessionPlanId: null,
72
+ sessionPlan: undefined
73
+ },
74
+ {
75
+ id: 2,
76
+ sessionPlanId: null,
77
+ sessionPlan: undefined
78
+ }
79
+ ];
80
+ (0, addNullFallbacks_1.addNullFallbacks)(sqlAST, data);
81
+ strict_1.default.deepEqual(data, [
82
+ {
83
+ id: 1,
84
+ sessionPlanId: null,
85
+ sessionPlan: null
86
+ },
87
+ {
88
+ id: 2,
89
+ sessionPlanId: null,
90
+ sessionPlan: null
91
+ }
92
+ ]);
93
+ });
94
+ (0, globals_1.test)("should work for nested array", () => {
95
+ const sqlAST = {
96
+ type: "table",
97
+ name: "Session",
98
+ as: "Session",
99
+ fieldName: "session",
100
+ grabMany: false,
101
+ children: [
102
+ {
103
+ type: "column",
104
+ name: "id",
105
+ fieldName: "id",
106
+ as: "a"
107
+ },
108
+ {
109
+ type: "table",
110
+ name: "SessionPlan",
111
+ as: "SessionPlan",
112
+ fieldName: "sessionPlan",
113
+ grabMany: false,
114
+ children: [
115
+ {
116
+ type: "column",
117
+ name: "id",
118
+ fieldName: "id",
119
+ as: "a"
120
+ },
121
+ {
122
+ type: "column",
123
+ name: "uuid",
124
+ fieldName: "uuid",
125
+ as: "c"
126
+ },
127
+ {
128
+ type: "column",
129
+ name: "id",
130
+ fieldName: "id",
131
+ as: "a"
132
+ },
133
+ {
134
+ type: "table",
135
+ name: "SessionPlan",
136
+ as: "SessionPlan",
137
+ fieldName: "sessionPlan",
138
+ grabMany: false,
139
+ children: [
140
+ {
141
+ type: "column",
142
+ name: "id",
143
+ fieldName: "id",
144
+ as: "a"
145
+ },
146
+ {
147
+ type: "column",
148
+ name: "uuid",
149
+ fieldName: "uuid",
150
+ as: "c"
151
+ },
152
+ {
153
+ type: "column",
154
+ name: "id",
155
+ fieldName: "id",
156
+ as: "a"
157
+ }
158
+ ]
159
+ }
160
+ ]
161
+ }
162
+ ]
163
+ };
164
+ const data = [
165
+ {
166
+ id: 1,
167
+ sessionPlanId: 1,
168
+ sessionPlan: {
169
+ id: 1,
170
+ uuid: "stub",
171
+ sessionPlan: undefined
172
+ }
173
+ },
174
+ {
175
+ id: 2,
176
+ sessionPlanId: 2,
177
+ sessionPlan: {
178
+ id: 2,
179
+ uuid: "stub",
180
+ sessionPlan: undefined
181
+ }
182
+ }
183
+ ];
184
+ (0, addNullFallbacks_1.addNullFallbacks)(sqlAST, data);
185
+ strict_1.default.deepEqual(data, [
186
+ {
187
+ id: 1,
188
+ sessionPlanId: 1,
189
+ sessionPlan: {
190
+ id: 1,
191
+ uuid: "stub",
192
+ sessionPlan: null
193
+ }
194
+ },
195
+ {
196
+ id: 2,
197
+ sessionPlanId: 2,
198
+ sessionPlan: {
199
+ id: 2,
200
+ uuid: "stub",
201
+ sessionPlan: null
202
+ }
203
+ }
204
+ ]);
205
+ });
206
+ });
@@ -1,21 +1,47 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
2
28
  Object.defineProperty(exports, "__esModule", { value: true });
3
29
  exports.getSqlAst = void 0;
4
- const SqlString = require("sqlstring");
30
+ const SqlString = __importStar(require("sqlstring"));
5
31
  // @ts-ignore
6
- const TSqlString = require("tsqlstring");
32
+ const TSqlString = __importStar(require("tsqlstring"));
7
33
  // @ts-ignore
8
- const alias_namespace_1 = require("join-monster/dist/alias-namespace");
9
- const _ = require("lodash/fp");
34
+ const alias_namespace_1 = __importDefault(require("join-monster/dist/alias-namespace"));
35
+ const _ = __importStar(require("lodash/fp"));
10
36
  const getOrderBy_1 = require("./getOrderBy");
11
37
  const namespace = new alias_namespace_1.default(true);
12
38
  function getSqlAst(input) {
13
- const { table, fieldName, fields, args, grabMany, sqlJoin, sqlBatch, junction, getWhere, artifacts, rowWithMatchingCursor, dialect, } = input;
39
+ const { table, fieldName, fields, args, grabMany, sqlJoin, sqlBatch, junction, getWhere, artifacts, rowWithMatchingCursor, dialect } = input;
14
40
  const tableArtifacts = artifacts[table];
15
41
  const primaryKey = tableArtifacts.primaryKey;
16
- const format = dialect === "mysql"
17
- ? SqlString.format.bind(SqlString)
18
- : TSqlString.format.bind(TSqlString);
42
+ const format = dialect === "mssql"
43
+ ? TSqlString.format.bind(TSqlString)
44
+ : SqlString.format.bind(SqlString);
19
45
  const orderBy = input.orderBy ?? (0, getOrderBy_1.getOrderBy)(args, primaryKey)?.orderBy;
20
46
  let where = input.where;
21
47
  if (input.where == null) {
@@ -60,127 +86,138 @@ function getSqlAst(input) {
60
86
  args,
61
87
  where,
62
88
  orderBy,
63
- children: children.concat(fields.map((x) => {
64
- if (typeof x === "string") {
65
- const mappedField = tableArtifacts.mappedFields?.[x];
66
- if (mappedField != null) {
67
- return {
68
- type: "expression",
69
- sqlExpr: (table) => {
70
- const referencedTableAlias = namespace.generate("table", mappedField.referencedTable);
71
- return format(`(SELECT ?? FROM ?? AS ?? WHERE ??.?? = ${table}.??)`, [
72
- mappedField.name,
73
- mappedField.referencedTable,
74
- referencedTableAlias,
75
- referencedTableAlias,
76
- mappedField.referencedKey,
77
- mappedField.foreignKey,
78
- ]);
89
+ children: children.concat(Object.entries(fields)
90
+ .filter(([_, v]) => v !== false)
91
+ .map(([k, v]) => {
92
+ const mappedField = tableArtifacts.mappedFields?.[k];
93
+ const relationField = tableArtifacts.relationFields?.[k];
94
+ if (mappedField != null) {
95
+ return {
96
+ type: "expression",
97
+ sqlExpr: (table) => {
98
+ const referencedTableAlias = namespace.generate("table", mappedField.referencedTable);
99
+ return format(`(SELECT ?? FROM ?? AS ?? WHERE ??.?? = ${table}.??)`, [
100
+ mappedField.name,
101
+ mappedField.referencedTable,
102
+ referencedTableAlias,
103
+ referencedTableAlias,
104
+ mappedField.referencedKey,
105
+ mappedField.foreignKey
106
+ ]);
107
+ },
108
+ name: k,
109
+ fieldName: k,
110
+ as: namespace.generate("column", k)
111
+ };
112
+ }
113
+ else if (relationField != null) {
114
+ const fields = typeof v === "object"
115
+ ? v.$fields ??
116
+ tableArtifacts.scalarFields.reduce((acc, x) => {
117
+ acc[x] = true;
118
+ return acc;
119
+ }, {})
120
+ : tableArtifacts.scalarFields.reduce((acc, x) => {
121
+ acc[x] = true;
122
+ return acc;
123
+ }, {});
124
+ const args = typeof v === "object" ? v : {};
125
+ if (relationField.type === "many-to-many") {
126
+ const asJunction = namespace.generate("table", relationField.junctionTable);
127
+ const uniqueKey = artifacts[relationField.junctionTable].primaryKey;
128
+ return getSqlAst({
129
+ table: relationField.table,
130
+ fieldName: k,
131
+ fields,
132
+ args,
133
+ grabMany: relationField.grabMany,
134
+ firstChild: {
135
+ ...keyToASTChild(uniqueKey, namespace, asJunction),
136
+ // There's either a bug in join-monster, or join-monster doesn't expect a junction table to have a primary key.
137
+ // Work around by ensuring a unique name, to avoid e.g. SELECT `UserRole`.`id` AS `b`, `Role`.`id` AS `b`
138
+ // Notice the duplicate names in the select. This results in missing rows because the
139
+ // shape definition passed into NestHydrationJS will only have 1 `id`.
140
+ fieldName: String(Date.now()),
141
+ as: String(Date.now())
79
142
  },
80
- name: x,
81
- fieldName: x,
82
- as: namespace.generate("column", x),
83
- };
143
+ junction: {
144
+ sqlTable: relationField.junctionTable,
145
+ as: asJunction,
146
+ uniqueKey,
147
+ where: (table, args) => {
148
+ if (typeof args?.$where !== "object" ||
149
+ typeof args?.$where == null ||
150
+ args.$where[relationField.junctionTable] == null) {
151
+ return undefined;
152
+ }
153
+ const argsMapped = _.cloneDeep(args);
154
+ argsMapped.$where =
155
+ argsMapped.$where[relationField.junctionTable];
156
+ const whereResult = getWhere(
157
+ // table is escaped already
158
+ table, argsMapped, dialect, orderBy, rowWithMatchingCursor);
159
+ if (whereResult == null) {
160
+ return undefined;
161
+ }
162
+ return whereResult;
163
+ },
164
+ // Because we used the where in sqlJoin
165
+ // where: () => undefined,
166
+ // TODO - where
167
+ // sqlJoins: [
168
+ // (t: string, junctionTable: string, args: any) =>
169
+ // `${t}.${relationField.relations[0].referencedKey} = ${junctionTable}.${relationField.relations[0].foreignKey}`,
170
+ // (junctionTable: string, t: string, args: any) =>
171
+ // `${junctionTable}.${relationField.relations[1].foreignKey} = ${t}.${relationField.relations[1].referencedKey}`,
172
+ // ],
173
+ // We have to use sqlBatch instead of sqlJoin because pagination is not
174
+ // supported with `mysql` dialect, and LIMITing the root list means
175
+ // sub lists are limited, too.
176
+ sqlBatch: {
177
+ thisKey: columnToASTChild(relationField.relations[0].foreignKey, namespace, asJunction),
178
+ parentKey: columnToASTChild(relationField.relations[0].referencedKey, namespace),
179
+ sqlJoin: (junctionTable, t, args) => `${junctionTable}.${relationField.relations[1].foreignKey} = ${t}.${relationField.relations[1].referencedKey}`
180
+ }
181
+ },
182
+ getWhere,
183
+ artifacts,
184
+ dialect
185
+ });
84
186
  }
85
- // TODO - validate in dev?
86
- return columnToASTChild(x, namespace);
87
- }
88
- const relationField = tableArtifacts.relationFields?.[x.name];
89
- if (relationField == null) {
90
- throw new Error("Invalid field: " + table + "." + x.name);
91
- }
92
- if (relationField.type === "many-to-many") {
93
- const asJunction = namespace.generate("table", relationField.junctionTable);
94
- const uniqueKey = artifacts[relationField.junctionTable].primaryKey;
95
187
  return getSqlAst({
96
188
  table: relationField.table,
97
- fieldName: x.as ?? x.name,
98
- fields: x.fields,
99
- args: x.args,
189
+ fieldName: k,
190
+ fields,
191
+ args,
100
192
  grabMany: relationField.grabMany,
101
- firstChild: {
102
- ...keyToASTChild(uniqueKey, namespace, asJunction),
103
- // There's either a bug in join-monster, or join-monster doesn't expect a junction table to have a primary key.
104
- // Work around by ensuring a unique name, to avoid e.g. SELECT `UserRole`.`id` AS `b`, `Role`.`id` AS `b`
105
- // Notice the duplicate names in the select. This results in missing rows because the
106
- // shape definition passed into NestHydrationJS will only have 1 `id`.
107
- fieldName: String(Date.now()),
108
- as: String(Date.now()),
109
- },
110
- junction: {
111
- sqlTable: relationField.junctionTable,
112
- as: asJunction,
113
- uniqueKey,
114
- where: (table, args) => {
115
- if (typeof args?.$where !== "object" ||
116
- typeof args?.$where == null ||
117
- args.$where[relationField.junctionTable] == null) {
118
- return undefined;
119
- }
120
- const argsMapped = _.cloneDeep(args);
121
- argsMapped.$where =
122
- argsMapped.$where[relationField.junctionTable];
123
- const whereResult = getWhere(
124
- // table is escaped already
125
- table, argsMapped, dialect, orderBy, rowWithMatchingCursor);
126
- if (whereResult == null) {
127
- return undefined;
128
- }
129
- return whereResult;
130
- },
131
- // Because we used the where in sqlJoin
132
- // where: () => undefined,
133
- // TODO - where
134
- // sqlJoins: [
135
- // (t: string, junctionTable: string, args: any) =>
136
- // `${t}.${relationField.relations[0].referencedKey} = ${junctionTable}.${relationField.relations[0].foreignKey}`,
137
- // (junctionTable: string, t: string, args: any) =>
138
- // `${junctionTable}.${relationField.relations[1].foreignKey} = ${t}.${relationField.relations[1].referencedKey}`,
139
- // ],
140
- // We have to use sqlBatch instead of sqlJoin because pagination is not
141
- // supported with `mysql` dialect, and LIMITing the root list means
142
- // sub lists are limited, too.
143
- sqlBatch: {
144
- thisKey: columnToASTChild(relationField.relations[0].foreignKey, namespace, asJunction),
145
- parentKey: columnToASTChild(relationField.relations[0].referencedKey, namespace),
146
- sqlJoin: (junctionTable, t, args) => `${junctionTable}.${relationField.relations[1].foreignKey} = ${t}.${relationField.relations[1].referencedKey}`,
147
- },
193
+ // Because we used the where in sqlJoin
194
+ // where: () => undefined,
195
+ // sqlJoin: (t1: string, t2: string, args: any) => {
196
+ // let sql = `${t1}.?? = ${t2}.??`;
197
+ // let values = [relationField.relation.foreignKey, relationField.relation.referencedKey];
198
+ // if (args?.$where != null) {
199
+ // const whereResult = getWhere(t2, args);
200
+ // sql += " and " + whereResult.sql;
201
+ // values.push(whereResult.values);
202
+ // }
203
+ // return s.format(sql, values);
204
+ // },
205
+ // We have to use sqlBatch instead of sqlJoin because pagination is not
206
+ // supported with `mysql` dialect, and LIMITing the root list means
207
+ // sub lists are limited, too.
208
+ sqlBatch: {
209
+ thisKey: columnToASTChild(relationField.relation.referencedKey, namespace),
210
+ parentKey: columnToASTChild(relationField.relation.foreignKey, namespace)
148
211
  },
149
212
  getWhere,
150
213
  artifacts,
151
- dialect,
214
+ dialect
152
215
  });
153
216
  }
154
- return getSqlAst({
155
- table: relationField.table,
156
- fieldName: x.as ?? x.name,
157
- fields: x.fields,
158
- args: x.args,
159
- grabMany: relationField.grabMany,
160
- // Because we used the where in sqlJoin
161
- // where: () => undefined,
162
- // sqlJoin: (t1: string, t2: string, args: any) => {
163
- // let sql = `${t1}.?? = ${t2}.??`;
164
- // let values = [relationField.relation.foreignKey, relationField.relation.referencedKey];
165
- // if (args?.$where != null) {
166
- // const whereResult = getWhere(t2, args);
167
- // sql += " and " + whereResult.sql;
168
- // values.push(whereResult.values);
169
- // }
170
- // return s.format(sql, values);
171
- // },
172
- // We have to use sqlBatch instead of sqlJoin because pagination is not
173
- // supported with `mysql` dialect, and LIMITing the root list means
174
- // sub lists are limited, too.
175
- sqlBatch: {
176
- thisKey: columnToASTChild(relationField.relation.referencedKey, namespace),
177
- parentKey: columnToASTChild(relationField.relation.foreignKey, namespace),
178
- },
179
- getWhere,
180
- artifacts,
181
- dialect,
182
- });
183
- })),
217
+ else {
218
+ return columnToASTChild(k, namespace);
219
+ }
220
+ }))
184
221
  };
185
222
  }
186
223
  exports.getSqlAst = getSqlAst;
@@ -192,7 +229,7 @@ function keyToASTChild(key, namespace, fromOtherTable) {
192
229
  name: key,
193
230
  fieldName: clumsyName,
194
231
  as: namespace.generate("column", clumsyName),
195
- fromOtherTable,
232
+ fromOtherTable
196
233
  };
197
234
  }
198
235
  return columnToASTChild(key, namespace, fromOtherTable);
@@ -203,7 +240,7 @@ function columnToASTChild(columnName, namespace, fromOtherTable) {
203
240
  name: columnName,
204
241
  fieldName: columnName,
205
242
  as: namespace.generate("column", columnName),
206
- fromOtherTable,
243
+ fromOtherTable
207
244
  };
208
245
  }
209
246
  function toClumsyName(keyArr) {
@@ -1,5 +1,4 @@
1
- import type { IGetSQLASTInput, IArtifacts, IDialect, TDbCall, TFormatQuery, TBeginTransaction, TContext } from "../IRuntime";
2
- import type { TMiddleware, TResolveParams } from "../IRuntime";
1
+ import type { IGetSQLASTInput, IArtifacts, IDialect, TDbCall, TFormatQuery, TBeginTransaction, TContext, TMiddleware, TResolveParams } from "../IRuntime";
3
2
  import Cache from "../Cache";
4
3
  export declare function resolve(input: TResolveParams, dbCall: TDbCall, formatQuery: TFormatQuery, beginTransaction: TBeginTransaction, dialect: IDialect, middlewareHandler: MiddlewareHandler<TMiddleware>, context: TContext, cache?: Cache): Promise<any>;
5
4
  export declare class MiddlewareHandler<M extends Function> {