@technicity/data-service-generator 0.14.0 → 0.14.1

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 +0 -1
  2. package/dist/generation/generate.js +309 -917
  3. package/dist/ksql.d.ts +15 -0
  4. package/dist/ksql.js +55 -0
  5. package/dist/runtime/Cache.js +3 -6
  6. package/dist/runtime/IRuntime.d.ts +17 -46
  7. package/dist/runtime/RuntimeKSQL.d.ts +19 -0
  8. package/dist/runtime/RuntimeKSQL.js +446 -0
  9. package/dist/runtime/RuntimeMSSQL.d.ts +1 -7
  10. package/dist/runtime/RuntimeMSSQL.js +4 -4
  11. package/dist/runtime/RuntimeMySQL.d.ts +1 -3
  12. package/dist/runtime/RuntimeMySQL.js +7 -33
  13. package/dist/runtime/lib/MSSQL.d.ts +1 -2
  14. package/dist/runtime/lib/MSSQL.js +8 -36
  15. package/dist/runtime/lib/MySQL.d.ts +1 -1
  16. package/dist/runtime/lib/MySQL.js +2 -15
  17. package/dist/runtime/lib/getSqlAst.js +121 -158
  18. package/dist/runtime/lib/runTransforms.d.ts +2 -0
  19. package/dist/runtime/lib/runTransforms.js +36 -0
  20. package/dist/runtime/lib/shared.d.ts +2 -1
  21. package/dist/runtime/lib/shared.js +71 -180
  22. package/dist/runtime/lib/stringifyWhere.js +12 -39
  23. package/dist/runtime/lib/typeCastMSSQL.js +1 -24
  24. package/dist/traverseFieldArgs.d.ts +2 -2
  25. package/dist/traverseFieldArgs.js +3 -8
  26. package/package.json +4 -1
  27. package/dist/runtime/RuntimeSQLite.d.ts +0 -38
  28. package/dist/runtime/RuntimeSQLite.js +0 -135
  29. package/dist/runtime/lib/addNullFallbacks.test.d.ts +0 -1
  30. package/dist/runtime/lib/addNullFallbacks.test.js +0 -206
  31. package/dist/runtime/lib/stringifyWhere.test.d.ts +0 -1
  32. package/dist/runtime/lib/stringifyWhere.test.js +0 -236
  33. package/dist/traverseFieldArgs.test.d.ts +0 -1
  34. package/dist/traverseFieldArgs.test.js +0 -56
@@ -13,13 +13,7 @@ export declare class RuntimeMSSQL implements IRuntime {
13
13
  $whereNeedsProcessing(where: any): boolean;
14
14
  $prepareWhere(artifacts: IArtifacts, table: string, data: any): Promise<{}>;
15
15
  $shutdown(): Promise<void>;
16
- $startTransaction(input?: {
17
- isolationLevel?: "READ UNCOMMITTED" | "READ COMMITTED" | "REPEATABLE READ" | "SERIALIZABLE";
18
- }): Promise<{
19
- commit: () => Promise<void>;
20
- rollback: () => Promise<void>;
21
- dbCall: (q: string) => Promise<any>;
22
- }>;
23
16
  private dbCall;
24
17
  private formatQuery;
18
+ private beginTransaction;
25
19
  }
@@ -27,7 +27,7 @@ class RuntimeMSSQL {
27
27
  __classPrivateFieldSet(this, _RuntimeMSSQL_middlewareHandler, new shared_1.MiddlewareHandler(), "f");
28
28
  }
29
29
  async resolve(input) {
30
- return (0, shared_1.resolve)(input, input.dbCall ?? this.dbCall.bind(this), this.formatQuery.bind(this), this.$startTransaction.bind(this), __classPrivateFieldGet(this, _RuntimeMSSQL_dialect, "f"), __classPrivateFieldGet(this, _RuntimeMSSQL_middlewareHandler, "f"), input.context ?? {});
30
+ return (0, shared_1.resolve)(input, this.dbCall.bind(this), this.formatQuery.bind(this), this.beginTransaction.bind(this), __classPrivateFieldGet(this, _RuntimeMSSQL_dialect, "f"), __classPrivateFieldGet(this, _RuntimeMSSQL_middlewareHandler, "f"), input.context ?? {});
31
31
  }
32
32
  async $queryRaw(sql, values) {
33
33
  return this.dbCall(this.formatQuery(sql, values ?? []));
@@ -44,15 +44,15 @@ class RuntimeMSSQL {
44
44
  async $shutdown() {
45
45
  await __classPrivateFieldGet(this, _RuntimeMSSQL_mssqlClient, "f").closePool();
46
46
  }
47
- async $startTransaction(input) {
48
- return __classPrivateFieldGet(this, _RuntimeMSSQL_mssqlClient, "f").beginTransaction(input?.isolationLevel);
49
- }
50
47
  async dbCall(q) {
51
48
  return __classPrivateFieldGet(this, _RuntimeMSSQL_mssqlClient, "f").dbCall(q);
52
49
  }
53
50
  formatQuery(q, values) {
54
51
  return __classPrivateFieldGet(this, _RuntimeMSSQL_mssqlClient, "f").formatQuery(q, values);
55
52
  }
53
+ beginTransaction() {
54
+ return __classPrivateFieldGet(this, _RuntimeMSSQL_mssqlClient, "f").beginTransaction();
55
+ }
56
56
  }
57
57
  exports.RuntimeMSSQL = RuntimeMSSQL;
58
58
  _RuntimeMSSQL_dialect = new WeakMap(), _RuntimeMSSQL_mssqlClient = new WeakMap(), _RuntimeMSSQL_middlewareHandler = new WeakMap();
@@ -14,9 +14,7 @@ export declare class RuntimeMySQL implements IRuntime {
14
14
  $whereNeedsProcessing(where: any): boolean;
15
15
  $prepareWhere(artifacts: IArtifacts, table: string, data: any): Promise<{}>;
16
16
  $shutdown(): Promise<void>;
17
- $startTransaction(input?: {
18
- isolationLevel?: "READ UNCOMMITTED" | "READ COMMITTED" | "REPEATABLE READ" | "SERIALIZABLE";
19
- }): Promise<any>;
20
17
  private dbCall;
21
18
  private formatQuery;
19
+ private beginTransaction;
22
20
  }
@@ -1,27 +1,4 @@
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
2
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
26
3
  if (kind === "m") throw new TypeError("Private method is not writable");
27
4
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
@@ -33,17 +10,14 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
33
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
34
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
35
12
  };
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
13
  var _RuntimeMySQL_dialect, _RuntimeMySQL_mysqlClient, _RuntimeMySQL_clientCache, _RuntimeMySQL_middlewareHandler;
40
14
  Object.defineProperty(exports, "__esModule", { value: true });
41
15
  exports.RuntimeMySQL = void 0;
42
- const SqlString = __importStar(require("sqlstring"));
43
- const Cache_1 = __importDefault(require("./Cache"));
16
+ const SqlString = require("sqlstring");
17
+ const Cache_1 = require("./Cache");
44
18
  const MySQL_1 = require("./lib/MySQL");
45
19
  const shared_1 = require("./lib/shared");
46
- const loglevel_1 = __importDefault(require("loglevel"));
20
+ const loglevel_1 = require("loglevel");
47
21
  loglevel_1.default.setDefaultLevel("INFO");
48
22
  class RuntimeMySQL {
49
23
  constructor(clientOpts, otherOpts, artifacts) {
@@ -96,7 +70,7 @@ class RuntimeMySQL {
96
70
  __classPrivateFieldSet(this, _RuntimeMySQL_mysqlClient, new MySQL_1.MySQL(clientOpts), "f");
97
71
  }
98
72
  async resolve(input) {
99
- return (0, shared_1.resolve)(input, input.dbCall ?? this.dbCall.bind(this), this.formatQuery.bind(this), this.$startTransaction.bind(this), __classPrivateFieldGet(this, _RuntimeMySQL_dialect, "f"), __classPrivateFieldGet(this, _RuntimeMySQL_middlewareHandler, "f"), input.context ?? {}, __classPrivateFieldGet(this, _RuntimeMySQL_clientCache, "f"));
73
+ return (0, shared_1.resolve)(input, this.dbCall.bind(this), this.formatQuery.bind(this), this.beginTransaction.bind(this), __classPrivateFieldGet(this, _RuntimeMySQL_dialect, "f"), __classPrivateFieldGet(this, _RuntimeMySQL_middlewareHandler, "f"), input.context ?? {}, __classPrivateFieldGet(this, _RuntimeMySQL_clientCache, "f"));
100
74
  }
101
75
  async $queryRaw(sql, values) {
102
76
  return this.dbCall(this.formatQuery(sql, values ?? []));
@@ -116,15 +90,15 @@ class RuntimeMySQL {
116
90
  }
117
91
  await __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").endPool();
118
92
  }
119
- async $startTransaction(input) {
120
- return __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").beginTransaction(input?.isolationLevel);
121
- }
122
93
  dbCall(q) {
123
94
  return __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").query(q);
124
95
  }
125
96
  formatQuery(q, values) {
126
97
  return SqlString.format(q, values);
127
98
  }
99
+ beginTransaction() {
100
+ return __classPrivateFieldGet(this, _RuntimeMySQL_mysqlClient, "f").beginTransaction();
101
+ }
128
102
  }
129
103
  exports.RuntimeMySQL = RuntimeMySQL;
130
104
  _RuntimeMySQL_dialect = new WeakMap(), _RuntimeMySQL_mysqlClient = new WeakMap(), _RuntimeMySQL_clientCache = new WeakMap(), _RuntimeMySQL_middlewareHandler = new WeakMap();
@@ -5,9 +5,8 @@ export declare class MSSQL {
5
5
  dbCall(q: string): Promise<any>;
6
6
  private mapResult;
7
7
  formatQuery(q: string, values: any[]): any;
8
- beginTransaction(isolationLevel?: "READ UNCOMMITTED" | "READ COMMITTED" | "REPEATABLE READ" | "SERIALIZABLE"): Promise<{
8
+ beginTransaction(): Promise<{
9
9
  commit: () => Promise<void>;
10
- rollback: () => Promise<void>;
11
10
  dbCall: (q: string) => Promise<any>;
12
11
  }>;
13
12
  closePool(): Promise<void>;
@@ -1,27 +1,4 @@
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
2
  var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
26
3
  if (kind === "m") throw new TypeError("Private method is not writable");
27
4
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
@@ -36,9 +13,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
36
13
  var _MSSQL_pool, _MSSQL_poolConnect, _MSSQL_typeCast;
37
14
  Object.defineProperty(exports, "__esModule", { value: true });
38
15
  exports.MSSQL = void 0;
39
- const mssql = __importStar(require("mssql"));
16
+ const mssql = require("mssql");
40
17
  // @ts-ignore
41
- const TSqlString = __importStar(require("tsqlstring"));
18
+ const TSqlString = require("tsqlstring");
42
19
  class MSSQL {
43
20
  constructor(clientOpts, typeCast) {
44
21
  _MSSQL_pool.set(this, void 0);
@@ -65,7 +42,7 @@ class MSSQL {
65
42
  formatQuery(q, values) {
66
43
  return TSqlString.format(q, values);
67
44
  }
68
- async beginTransaction(isolationLevel) {
45
+ async beginTransaction() {
69
46
  const transaction = new mssql.Transaction(__classPrivateFieldGet(this, _MSSQL_pool, "f"));
70
47
  let rolledBack = false;
71
48
  transaction.on("rollback", (aborted) => {
@@ -79,18 +56,13 @@ class MSSQL {
79
56
  throw err;
80
57
  }
81
58
  const mapResult = this.mapResult.bind(this);
82
- let isolationLevelNumber;
83
- if (isolationLevel) {
84
- isolationLevelNumber = mssql.ISOLATION_LEVEL[isolationLevel.replace(" ", "_")];
85
- if (isolationLevelNumber == null) {
86
- throw new Error(`Invalid isolationLevel: ${isolationLevel}`);
87
- }
88
- }
89
- await transaction.begin(isolationLevelNumber);
59
+ await transaction.begin();
90
60
  return {
91
61
  commit: () => transaction.commit().catch(handleError),
92
- rollback: () => transaction.rollback(),
93
- dbCall: (q) => new mssql.Request(transaction).query(q).then(mapResult).catch(handleError)
62
+ dbCall: (q) => new mssql.Request(transaction)
63
+ .query(q)
64
+ .then(mapResult)
65
+ .catch(handleError),
94
66
  };
95
67
  }
96
68
  async closePool() {
@@ -2,7 +2,7 @@ export declare class MySQL {
2
2
  pool: any;
3
3
  constructor(opts: any);
4
4
  query(...args: any[]): any;
5
- beginTransaction(isolationLevel?: "READ UNCOMMITTED" | "READ COMMITTED" | "REPEATABLE READ" | "SERIALIZABLE"): Promise<any>;
5
+ beginTransaction(): Promise<any>;
6
6
  getConnection(): Promise<any>;
7
7
  endPool(): Promise<void>;
8
8
  }
@@ -13,29 +13,16 @@ class MySQL {
13
13
  query(...args) {
14
14
  return P.using(this.getConnection(), (connection) => connection.queryAsync(...args));
15
15
  }
16
- async beginTransaction(isolationLevel) {
16
+ async beginTransaction() {
17
17
  return P.using(this.getConnection(), async (connection) => {
18
18
  async function handleError(err) {
19
19
  await connection.rollbackAsync();
20
20
  throw err;
21
21
  }
22
- // https://dev.mysql.com/doc/refman/8.0/en/set-transaction.html#set-transaction-isolation-level
23
- // Without any SESSION or GLOBAL keyword:
24
- // The statement applies only to the next single transaction performed within the session.
25
- if (isolationLevel != null) {
26
- if (isolationLevel !== "READ UNCOMMITTED" &&
27
- isolationLevel !== "READ COMMITTED" &&
28
- isolationLevel !== "REPEATABLE READ" &&
29
- isolationLevel !== "SERIALIZABLE") {
30
- throw new Error(`Invalid isolationLevel: ${isolationLevel}`);
31
- }
32
- await connection.queryAsync(`SET TRANSACTION ISOLATION LEVEL ${isolationLevel};`);
33
- }
34
22
  await connection.beginTransactionAsync();
35
23
  return {
36
24
  commit: () => connection.commitAsync().catch(handleError),
37
- rollback: () => connection.rollbackAsync(),
38
- dbCall: (q) => connection.queryAsync(q).catch(handleError)
25
+ dbCall: (q) => connection.queryAsync(q).catch(handleError),
39
26
  };
40
27
  });
41
28
  }
@@ -1,47 +1,21 @@
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
- };
28
2
  Object.defineProperty(exports, "__esModule", { value: true });
29
3
  exports.getSqlAst = void 0;
30
- const SqlString = __importStar(require("sqlstring"));
4
+ const SqlString = require("sqlstring");
31
5
  // @ts-ignore
32
- const TSqlString = __importStar(require("tsqlstring"));
6
+ const TSqlString = require("tsqlstring");
33
7
  // @ts-ignore
34
- const alias_namespace_1 = __importDefault(require("join-monster/dist/alias-namespace"));
35
- const _ = __importStar(require("lodash/fp"));
8
+ const alias_namespace_1 = require("join-monster/dist/alias-namespace");
9
+ const _ = require("lodash/fp");
36
10
  const getOrderBy_1 = require("./getOrderBy");
37
11
  const namespace = new alias_namespace_1.default(true);
38
12
  function getSqlAst(input) {
39
- const { table, fieldName, fields, args, grabMany, sqlJoin, sqlBatch, junction, getWhere, artifacts, rowWithMatchingCursor, dialect } = input;
13
+ const { table, fieldName, fields, args, grabMany, sqlJoin, sqlBatch, junction, getWhere, artifacts, rowWithMatchingCursor, dialect, } = input;
40
14
  const tableArtifacts = artifacts[table];
41
15
  const primaryKey = tableArtifacts.primaryKey;
42
- const format = dialect === "mssql"
43
- ? TSqlString.format.bind(TSqlString)
44
- : SqlString.format.bind(SqlString);
16
+ const format = dialect === "mysql"
17
+ ? SqlString.format.bind(SqlString)
18
+ : TSqlString.format.bind(TSqlString);
45
19
  const orderBy = input.orderBy ?? (0, getOrderBy_1.getOrderBy)(args, primaryKey)?.orderBy;
46
20
  let where = input.where;
47
21
  if (input.where == null) {
@@ -86,138 +60,127 @@ function getSqlAst(input) {
86
60
  args,
87
61
  where,
88
62
  orderBy,
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())
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
+ ]);
142
79
  },
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
- });
80
+ name: x,
81
+ fieldName: x,
82
+ as: namespace.generate("column", x),
83
+ };
186
84
  }
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;
187
95
  return getSqlAst({
188
96
  table: relationField.table,
189
- fieldName: k,
190
- fields,
191
- args,
97
+ fieldName: x.as ?? x.name,
98
+ fields: x.fields,
99
+ args: x.args,
192
100
  grabMany: relationField.grabMany,
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)
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
+ },
211
148
  },
212
149
  getWhere,
213
150
  artifacts,
214
- dialect
151
+ dialect,
215
152
  });
216
153
  }
217
- else {
218
- return columnToASTChild(k, namespace);
219
- }
220
- }))
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
+ })),
221
184
  };
222
185
  }
223
186
  exports.getSqlAst = getSqlAst;
@@ -229,7 +192,7 @@ function keyToASTChild(key, namespace, fromOtherTable) {
229
192
  name: key,
230
193
  fieldName: clumsyName,
231
194
  as: namespace.generate("column", clumsyName),
232
- fromOtherTable
195
+ fromOtherTable,
233
196
  };
234
197
  }
235
198
  return columnToASTChild(key, namespace, fromOtherTable);
@@ -240,7 +203,7 @@ function columnToASTChild(columnName, namespace, fromOtherTable) {
240
203
  name: columnName,
241
204
  fieldName: columnName,
242
205
  as: namespace.generate("column", columnName),
243
- fromOtherTable
206
+ fromOtherTable,
244
207
  };
245
208
  }
246
209
  function toClumsyName(keyArr) {
@@ -0,0 +1,2 @@
1
+ import type { IGetSQLASTInput } from "../IRuntime";
2
+ export declare function runTransforms(data: any, fields: IGetSQLASTInput["fields"]): void;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runTransforms = void 0;
4
+ function runTransforms(data, fields) {
5
+ if (data == null) {
6
+ return;
7
+ }
8
+ for (let x of fields) {
9
+ if (typeof x === "object") {
10
+ const k = x.as ?? x.name;
11
+ if (Array.isArray(data)) {
12
+ for (let d of data) {
13
+ if (d != null) {
14
+ runTransforms(d[k], x.fields);
15
+ }
16
+ }
17
+ }
18
+ else {
19
+ runTransforms(data[k], x.fields);
20
+ }
21
+ if (typeof x.transform === "function") {
22
+ if (Array.isArray(data)) {
23
+ for (let d of data) {
24
+ if (d != null) {
25
+ d[k] = x.transform(d[k]);
26
+ }
27
+ }
28
+ }
29
+ else {
30
+ data[k] = x.transform(data[k]);
31
+ }
32
+ }
33
+ }
34
+ }
35
+ }
36
+ exports.runTransforms = runTransforms;
@@ -1,4 +1,5 @@
1
- import type { IGetSQLASTInput, IArtifacts, IDialect, TDbCall, TFormatQuery, TBeginTransaction, TContext, TMiddleware, TResolveParams } from "../IRuntime";
1
+ import type { IGetSQLASTInput, IArtifacts, IDialect, TDbCall, TFormatQuery, TBeginTransaction, TContext } from "../IRuntime";
2
+ import type { TMiddleware, TResolveParams } from "../IRuntime";
2
3
  import Cache from "../Cache";
3
4
  export declare function resolve(input: TResolveParams, dbCall: TDbCall, formatQuery: TFormatQuery, beginTransaction: TBeginTransaction, dialect: IDialect, middlewareHandler: MiddlewareHandler<TMiddleware>, context: TContext, cache?: Cache): Promise<any>;
4
5
  export declare class MiddlewareHandler<M extends Function> {