typesql-cli 0.19.2 → 0.21.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 (123) hide show
  1. package/README.md +5 -0
  2. package/cli.js +51 -64
  3. package/cli.js.map +1 -1
  4. package/code-generator.d.ts +1 -1
  5. package/code-generator.d.ts.map +1 -1
  6. package/code-generator.js +4 -3
  7. package/code-generator.js.map +1 -1
  8. package/code-generator2.d.ts.map +1 -1
  9. package/code-generator2.js +151 -115
  10. package/code-generator2.js.map +1 -1
  11. package/codegen/code-generator.d.ts +13 -0
  12. package/codegen/code-generator.d.ts.map +1 -0
  13. package/codegen/code-generator.js +106 -0
  14. package/codegen/code-generator.js.map +1 -0
  15. package/codegen/code-generator2.d.ts +10 -0
  16. package/codegen/code-generator2.d.ts.map +1 -0
  17. package/codegen/code-generator2.js +917 -0
  18. package/codegen/code-generator2.js.map +1 -0
  19. package/codegen/codegen-util.d.ts +1 -0
  20. package/codegen/codegen-util.d.ts.map +1 -0
  21. package/codegen/codegen-util.js +2 -0
  22. package/codegen/codegen-util.js.map +1 -0
  23. package/codegen/generic/codegen-util.d.ts +8 -0
  24. package/codegen/generic/codegen-util.d.ts.map +1 -0
  25. package/codegen/generic/codegen-util.js +89 -0
  26. package/codegen/generic/codegen-util.js.map +1 -0
  27. package/codegen/mysql2.d.ts +40 -0
  28. package/codegen/mysql2.d.ts.map +1 -0
  29. package/codegen/mysql2.js +667 -0
  30. package/codegen/mysql2.js.map +1 -0
  31. package/codegen/pg.d.ts +9 -0
  32. package/codegen/pg.d.ts.map +1 -0
  33. package/codegen/pg.js +760 -0
  34. package/codegen/pg.js.map +1 -0
  35. package/codegen/postgres-pg.d.ts +10 -0
  36. package/codegen/postgres-pg.d.ts.map +1 -0
  37. package/codegen/postgres-pg.js +917 -0
  38. package/codegen/postgres-pg.js.map +1 -0
  39. package/codegen/shared/codegen-util.d.ts +28 -0
  40. package/codegen/shared/codegen-util.d.ts.map +1 -0
  41. package/codegen/shared/codegen-util.js +303 -0
  42. package/codegen/shared/codegen-util.js.map +1 -0
  43. package/codegen/sqlite-code-generator.d.ts +15 -0
  44. package/codegen/sqlite-code-generator.d.ts.map +1 -0
  45. package/codegen/sqlite-code-generator.js +1049 -0
  46. package/codegen/sqlite-code-generator.js.map +1 -0
  47. package/codegen/sqlite.d.ts +13 -0
  48. package/codegen/sqlite.d.ts.map +1 -0
  49. package/codegen/sqlite.js +893 -0
  50. package/codegen/sqlite.js.map +1 -0
  51. package/describe-query.d.ts.map +1 -1
  52. package/describe-query.js +45 -32
  53. package/describe-query.js.map +1 -1
  54. package/dialects/postgres.d.ts +4 -1
  55. package/dialects/postgres.d.ts.map +1 -1
  56. package/dialects/postgres.js +4 -2
  57. package/dialects/postgres.js.map +1 -1
  58. package/drivers/sqlite.d.ts +4 -1
  59. package/drivers/sqlite.d.ts.map +1 -1
  60. package/drivers/sqlite.js +4 -1
  61. package/drivers/sqlite.js.map +1 -1
  62. package/drivers/types.d.ts +3 -1
  63. package/drivers/types.d.ts.map +1 -1
  64. package/generic/codegen-util.d.ts +8 -0
  65. package/generic/codegen-util.d.ts.map +1 -0
  66. package/generic/codegen-util.js +89 -0
  67. package/generic/codegen-util.js.map +1 -0
  68. package/load-config.d.ts +6 -0
  69. package/load-config.d.ts.map +1 -1
  70. package/load-config.js +65 -1
  71. package/load-config.js.map +1 -1
  72. package/mysql-mapping.d.ts +4 -1
  73. package/mysql-mapping.d.ts.map +1 -1
  74. package/mysql-mapping.js +5 -3
  75. package/mysql-mapping.js.map +1 -1
  76. package/mysql-query-analyzer/infer-column-nullability.js +1 -1
  77. package/mysql-query-analyzer/infer-column-nullability.js.map +1 -1
  78. package/mysql-query-analyzer/parse.d.ts.map +1 -1
  79. package/mysql-query-analyzer/parse.js +3 -2
  80. package/mysql-query-analyzer/parse.js.map +1 -1
  81. package/package.json +2 -1
  82. package/postgres-pg.d.ts +10 -0
  83. package/postgres-pg.d.ts.map +1 -0
  84. package/postgres-pg.js +917 -0
  85. package/postgres-pg.js.map +1 -0
  86. package/postgres-query-analyzer/describe.d.ts +1 -1
  87. package/postgres-query-analyzer/describe.d.ts.map +1 -1
  88. package/postgres-query-analyzer/describe.js +77 -48
  89. package/postgres-query-analyzer/describe.js.map +1 -1
  90. package/postgres-query-analyzer/traverse.d.ts +1 -0
  91. package/postgres-query-analyzer/traverse.d.ts.map +1 -1
  92. package/postgres-query-analyzer/traverse.js +90 -28
  93. package/postgres-query-analyzer/traverse.js.map +1 -1
  94. package/postgres-query-analyzer/util.d.ts +9 -0
  95. package/postgres-query-analyzer/util.d.ts.map +1 -0
  96. package/postgres-query-analyzer/util.js +58 -0
  97. package/postgres-query-analyzer/util.js.map +1 -0
  98. package/rescript.d.ts +1 -0
  99. package/rescript.d.ts.map +1 -0
  100. package/rescript.js +2 -0
  101. package/rescript.js.map +1 -0
  102. package/sqlite-query-analyzer/parser.js +3 -3
  103. package/sqlite-query-analyzer/parser.js.map +1 -1
  104. package/sqlite-query-analyzer/replace-list-params.d.ts.map +1 -1
  105. package/sqlite-query-analyzer/replace-list-params.js.map +1 -1
  106. package/sqlite-query-analyzer/sqlite-code-generator.d.ts +15 -0
  107. package/sqlite-query-analyzer/sqlite-code-generator.d.ts.map +1 -0
  108. package/sqlite-query-analyzer/sqlite-code-generator.js +1049 -0
  109. package/sqlite-query-analyzer/sqlite-code-generator.js.map +1 -0
  110. package/sqlite-query-analyzer/traverse.js +1 -1
  111. package/sqlite-query-analyzer/traverse.js.map +1 -1
  112. package/sqlite.d.ts +43 -0
  113. package/sqlite.d.ts.map +1 -0
  114. package/sqlite.js +755 -0
  115. package/sqlite.js.map +1 -0
  116. package/ts-dynamic-query-descriptor.d.ts.map +1 -1
  117. package/ts-dynamic-query-descriptor.js +2 -1
  118. package/ts-dynamic-query-descriptor.js.map +1 -1
  119. package/ts-nested-descriptor.d.ts.map +1 -1
  120. package/ts-nested-descriptor.js +1 -1
  121. package/ts-nested-descriptor.js.map +1 -1
  122. package/types.d.ts +9 -1
  123. package/types.d.ts.map +1 -1
@@ -0,0 +1,667 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.generateTsCodeForMySQL = generateTsCodeForMySQL;
16
+ exports.getOperator = getOperator;
17
+ exports.generateRelationType = generateRelationType;
18
+ exports.writeTypeBlock = writeTypeBlock;
19
+ exports.generateTsDescriptor = generateTsDescriptor;
20
+ exports.removeDuplicatedParameters = removeDuplicatedParameters;
21
+ exports.removeDuplicatedParameters2 = removeDuplicatedParameters2;
22
+ exports.renameInvalidNames = renameInvalidNames;
23
+ exports.escapeInvalidTsField = escapeInvalidTsField;
24
+ exports.hasStringColumn = hasStringColumn;
25
+ exports.hasDateColumn = hasDateColumn;
26
+ exports.replaceOrderByParam = replaceOrderByParam;
27
+ exports.capitalize = capitalize;
28
+ exports.convertToCamelCaseName = convertToCamelCaseName;
29
+ exports.generateTsFileFromContent = generateTsFileFromContent;
30
+ const camelcase_1 = __importDefault(require("camelcase"));
31
+ const Either_1 = require("fp-ts/lib/Either");
32
+ const mysql_mapping_1 = require("../mysql-mapping");
33
+ const describe_query_1 = require("../describe-query");
34
+ const code_block_writer_1 = __importDefault(require("code-block-writer"));
35
+ const ts_nested_descriptor_1 = require("../ts-nested-descriptor");
36
+ const ts_dynamic_query_descriptor_1 = require("../ts-dynamic-query-descriptor");
37
+ const node_os_1 = require("node:os");
38
+ function generateTsCodeForMySQL(tsDescriptor, fileName, crud = false) {
39
+ var _a;
40
+ const writer = new code_block_writer_1.default();
41
+ const camelCaseName = convertToCamelCaseName(fileName);
42
+ const capitalizedName = capitalize(camelCaseName);
43
+ const dataTypeName = `${capitalizedName}Data`;
44
+ const paramsTypeName = `${capitalizedName}Params`;
45
+ const resultTypeName = `${capitalizedName}Result`;
46
+ const dynamicParamsTypeName = `${capitalizedName}DynamicParams`;
47
+ const selectColumnsTypeName = `${capitalizedName}Select`;
48
+ const whereTypeName = `${capitalizedName}Where`;
49
+ const orderByTypeName = `${capitalizedName}OrderBy`;
50
+ const generateOrderBy = tsDescriptor.orderByColumns != null && tsDescriptor.orderByColumns.length > 0;
51
+ // Import declarations
52
+ writer.writeLine(`import type { Connection } from 'mysql2/promise';`);
53
+ if (tsDescriptor.dynamicQuery != null) {
54
+ writer.writeLine(`import { EOL } from 'os';`);
55
+ }
56
+ writer.blankLine();
57
+ if (tsDescriptor.data) {
58
+ //update
59
+ writeTypeBlock(writer, tsDescriptor.data, dataTypeName, crud);
60
+ }
61
+ const orderByField = generateOrderBy ? `orderBy: [${orderByTypeName}, ...${orderByTypeName}[]]` : undefined;
62
+ const paramsTypes = tsDescriptor.dynamicQuery == null ? tsDescriptor.parameters : (0, ts_dynamic_query_descriptor_1.mapToDynamicParams)(tsDescriptor.parameters);
63
+ if (tsDescriptor.dynamicQuery != null) {
64
+ writer.write(`export type ${dynamicParamsTypeName} = `).block(() => {
65
+ writer.writeLine(`select?: ${selectColumnsTypeName};`);
66
+ if (paramsTypes.length > 0) {
67
+ writer.writeLine(`params?: ${paramsTypeName};`);
68
+ }
69
+ writer.writeLine(`where?: ${whereTypeName}[];`);
70
+ if (orderByField) {
71
+ writer.writeLine(`${orderByField};`);
72
+ }
73
+ });
74
+ writer.blankLine();
75
+ }
76
+ writeTypeBlock(writer, paramsTypes, paramsTypeName, false, tsDescriptor.dynamicQuery ? undefined : orderByField);
77
+ const resultTypes = tsDescriptor.dynamicQuery == null ? tsDescriptor.columns : (0, ts_dynamic_query_descriptor_1.mapToDynamicResultColumns)(tsDescriptor.columns);
78
+ writeTypeBlock(writer, resultTypes, resultTypeName, false);
79
+ if (tsDescriptor.dynamicQuery) {
80
+ const selectFields = (0, ts_dynamic_query_descriptor_1.mapToDynamicSelectColumns)(tsDescriptor.columns);
81
+ writeTypeBlock(writer, selectFields, selectColumnsTypeName, false);
82
+ writer.write('const selectFragments = ').inlineBlock(() => {
83
+ var _a;
84
+ (_a = tsDescriptor.dynamicQuery) === null || _a === void 0 ? void 0 : _a.select.forEach((fragment, index) => {
85
+ const field = tsDescriptor.columns[index].name;
86
+ writer.writeLine(`${field}: \`${fragment.fragmentWitoutAlias}\`,`);
87
+ });
88
+ });
89
+ writer.write(' as const;');
90
+ if (orderByField != null) {
91
+ writer.blankLine();
92
+ writer.write('const orderByFragments = ').inlineBlock(() => {
93
+ for (const col of tsDescriptor.orderByColumns || []) {
94
+ writer.writeLine(`'${col}': \`${col}\`,`);
95
+ }
96
+ });
97
+ writer.write(' as const;');
98
+ }
99
+ writer.blankLine();
100
+ writer.writeLine(`const NumericOperatorList = ['=', '<>', '>', '<', '>=', '<='] as const;`);
101
+ writer.writeLine('type NumericOperator = typeof NumericOperatorList[number];');
102
+ if (hasStringColumn(tsDescriptor.columns)) {
103
+ writer.writeLine(`type StringOperator = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'LIKE';`);
104
+ }
105
+ writer.writeLine(`type SetOperator = 'IN' | 'NOT IN';`);
106
+ writer.writeLine(`type BetweenOperator = 'BETWEEN';`);
107
+ writer.blankLine();
108
+ writer.write(`export type ${whereTypeName} =`).indent(() => {
109
+ for (const col of tsDescriptor.columns) {
110
+ writer.writeLine(`| ['${col.name}', ${getOperator(col.tsType)}, ${col.tsType} | null]`);
111
+ writer.writeLine(`| ['${col.name}', SetOperator, ${col.tsType}[]]`);
112
+ writer.writeLine(`| ['${col.name}', BetweenOperator, ${col.tsType} | null, ${col.tsType} | null]`);
113
+ }
114
+ });
115
+ writer.blankLine();
116
+ }
117
+ let functionReturnType = resultTypeName;
118
+ functionReturnType += tsDescriptor.multipleRowsResult ? '[]' : tsDescriptor.queryType === 'Select' ? ' | null' : '';
119
+ let functionArguments = 'connection: Connection';
120
+ functionArguments += tsDescriptor.data && tsDescriptor.data.length > 0 ? `, data: ${dataTypeName}` : '';
121
+ if (tsDescriptor.dynamicQuery == null) {
122
+ functionArguments += tsDescriptor.parameters.length > 0 || generateOrderBy ? `, params: ${paramsTypeName}` : '';
123
+ }
124
+ else {
125
+ functionArguments += `, ${orderByField ? 'params' : 'params?'}: ${dynamicParamsTypeName}`;
126
+ }
127
+ const allParameters = tsDescriptor.data
128
+ ? tsDescriptor.data.map((field, index) => {
129
+ //:nameIsSet, :name, :valueIsSet, :value....
130
+ if (crud && index % 2 === 0) {
131
+ const nextField = tsDescriptor.data[index + 1];
132
+ return `data.${nextField.name} !== undefined`;
133
+ }
134
+ return `data.${field.name}`;
135
+ })
136
+ : [];
137
+ allParameters.push(...tsDescriptor.parameterNames.map((paramName) => generateParam(paramName)));
138
+ const queryParams = allParameters.length > 0 ? `, [${allParameters.join(', ')}]` : '';
139
+ const escapedBackstick = scapeBackStick(tsDescriptor.sql);
140
+ const processedSql = replaceOrderByParam(escapedBackstick);
141
+ const sqlSplit = processedSql.split('\n');
142
+ writer.write(`export async function ${camelCaseName}(${functionArguments}): Promise<${functionReturnType}>`).block(() => {
143
+ if (tsDescriptor.dynamicQuery == null) {
144
+ writer.writeLine('const sql = `');
145
+ sqlSplit.forEach((sqlLine) => {
146
+ writer.indent().write(sqlLine);
147
+ writer.newLine();
148
+ });
149
+ writer.indent().write('`');
150
+ writer.blankLine();
151
+ }
152
+ else {
153
+ writer.writeLine('const where = whereConditionsToObject(params?.where);');
154
+ if (orderByField != null) {
155
+ writer.writeLine('const orderBy = orderByToObject(params.orderBy);');
156
+ }
157
+ writer.writeLine('const paramsValues: any = [];');
158
+ if (tsDescriptor.dynamicQuery.with) {
159
+ writer.writeLine(`let withClause = '';`);
160
+ tsDescriptor.dynamicQuery.with.forEach((withFragment) => {
161
+ generateDynamicQueryFrom(writer, 'withClause', withFragment, tsDescriptor.columns);
162
+ });
163
+ }
164
+ writer.writeLine(`let sql = 'SELECT';`);
165
+ tsDescriptor.dynamicQuery.select.forEach((fragment) => {
166
+ writer
167
+ .write(`if (params?.select == null || ${fragment.dependOnFields.map((fieldIndex) => `params.select.${tsDescriptor.columns[fieldIndex].name}`).join('&&')})`)
168
+ .block(() => {
169
+ writer.write(`sql = appendSelect(sql, \`${fragment.fragment}\`);`);
170
+ });
171
+ });
172
+ tsDescriptor.dynamicQuery.from.forEach((fragment) => {
173
+ generateDynamicQueryFrom(writer, 'sql', fragment, tsDescriptor.columns, tsDescriptor.orderByColumns != null);
174
+ });
175
+ writer.writeLine('sql += EOL + `WHERE 1 = 1`;');
176
+ tsDescriptor.dynamicQuery.where.forEach((fragment) => {
177
+ const ifParamConditions = fragment.dependOnParams.map((param) => `params?.params?.${param} != null`);
178
+ const paramValues = fragment.parameters.map((param) => `params.params.${param}`);
179
+ if (ifParamConditions.length > 0) {
180
+ writer.write(`if (${ifParamConditions.join(' || ')})`).block(() => {
181
+ writer.writeLine(`sql += EOL + \`${fragment.fragment}\`;`);
182
+ paramValues.forEach((paramValues) => {
183
+ writer.writeLine(`paramsValues.push(${paramValues});`);
184
+ });
185
+ });
186
+ }
187
+ else {
188
+ writer.writeLine(`sql += EOL + '${fragment.fragment}';`);
189
+ }
190
+ });
191
+ if (tsDescriptor.dynamicQuery.with) {
192
+ writer.write(`if (withClause != '') `).block(() => {
193
+ writer.writeLine(`sql = 'WITH ' + withClause + EOL + sql;`);
194
+ });
195
+ }
196
+ writer.write('params?.where?.forEach(condition => ').inlineBlock(() => {
197
+ writer.writeLine('const where = whereCondition(condition);');
198
+ writer.write('if (where?.hasValue)').block(() => {
199
+ writer.writeLine(`sql += EOL + 'AND ' + where.sql;`);
200
+ writer.write('paramsValues.push(...where.values);');
201
+ });
202
+ });
203
+ writer.write(');');
204
+ if (tsDescriptor.orderByColumns) {
205
+ writer.writeLine('sql += EOL + `ORDER BY ${buildOrderBy(params.orderBy)}`;');
206
+ }
207
+ }
208
+ const singleRowSelect = tsDescriptor.queryType === 'Select' && tsDescriptor.multipleRowsResult === false;
209
+ if (tsDescriptor.queryType === 'Select') {
210
+ if (tsDescriptor.dynamicQuery == null) {
211
+ writer.writeLine(`return connection.query({sql, rowsAsArray: true}${queryParams})`);
212
+ writer.indent().write('.then(res => res[0] as any[])');
213
+ writer.newLine().indent().write(`.then(res => res.map(data => mapArrayTo${resultTypeName}(data)))`);
214
+ }
215
+ else {
216
+ writer.writeLine('return connection.query({ sql, rowsAsArray: true }, paramsValues)');
217
+ writer.indent().write('.then(res => res[0] as any[])');
218
+ writer.newLine().indent().write(`.then(res => res.map(data => mapArrayTo${resultTypeName}(data, params?.select)))`);
219
+ }
220
+ }
221
+ else {
222
+ writer.writeLine(`return connection.query(sql${queryParams})`);
223
+ writer.indent().write(`.then(res => res[0] as ${resultTypeName})`);
224
+ }
225
+ if (tsDescriptor.queryType === 'Select' && tsDescriptor.multipleRowsResult === false) {
226
+ writer.newLine().indent().write('.then(res => res[0]);');
227
+ }
228
+ else {
229
+ writer.write(';');
230
+ }
231
+ });
232
+ if (tsDescriptor.queryType === 'Select') {
233
+ writer.blankLine();
234
+ if (tsDescriptor.dynamicQuery == null) {
235
+ writer.write(`function mapArrayTo${resultTypeName}(data: any)`).block(() => {
236
+ writer.write(`const result: ${resultTypeName} =`).block(() => {
237
+ tsDescriptor.columns.forEach((tsField, index) => {
238
+ writer.writeLine(`${tsField.name}: data[${index}]${commaSeparator(tsDescriptor.columns.length, index)}`);
239
+ });
240
+ });
241
+ writer.write('return result;');
242
+ });
243
+ }
244
+ else {
245
+ writer.write(`function mapArrayTo${resultTypeName}(data: any, select?: ${selectColumnsTypeName})`).block(() => {
246
+ writer.writeLine(`const result = {} as ${resultTypeName};`);
247
+ writer.writeLine('let rowIndex = 0;');
248
+ tsDescriptor.columns.forEach((tsField) => {
249
+ writer.write(`if (select == null || select.${tsField.name})`).block(() => {
250
+ writer.writeLine(`result.${tsField.name} = data[rowIndex++];`);
251
+ });
252
+ });
253
+ writer.write('return result;');
254
+ });
255
+ writer.blankLine();
256
+ writer.write('function appendSelect(sql: string, selectField: string)').block(() => {
257
+ writer.write(`if (sql == 'SELECT')`).block(() => {
258
+ writer.writeLine('return sql + EOL + selectField;');
259
+ });
260
+ writer.write('else').block(() => {
261
+ writer.writeLine(`return sql + ', ' + EOL + selectField;`);
262
+ });
263
+ });
264
+ writer.blankLine();
265
+ writer.write(`function whereConditionsToObject(whereConditions?: ${whereTypeName}[])`).block(() => {
266
+ writer.writeLine('const obj = {} as any;');
267
+ writer.write('whereConditions?.forEach(condition => ').inlineBlock(() => {
268
+ writer.writeLine('const where = whereCondition(condition);');
269
+ writer.write('if (where?.hasValue) ').block(() => {
270
+ writer.writeLine('obj[condition[0]] = true;');
271
+ });
272
+ });
273
+ writer.write(');');
274
+ writer.writeLine('return obj;');
275
+ });
276
+ if (orderByField != null) {
277
+ writer.blankLine();
278
+ writer.write(`function orderByToObject(${orderByField})`).block(() => {
279
+ writer.writeLine('const obj = {} as any;');
280
+ writer.write('orderBy?.forEach(order => ').inlineBlock(() => {
281
+ writer.writeLine('obj[order.column] = true;');
282
+ });
283
+ writer.write(');');
284
+ writer.writeLine('return obj;');
285
+ });
286
+ }
287
+ writer.blankLine();
288
+ writer.write('type WhereConditionResult = ').block(() => {
289
+ writer.writeLine('sql: string;');
290
+ writer.writeLine('hasValue: boolean;');
291
+ writer.writeLine('values: any[];');
292
+ });
293
+ writer.blankLine();
294
+ writer.write(`function whereCondition(condition: ${whereTypeName}): WhereConditionResult | undefined `).block(() => {
295
+ writer.blankLine();
296
+ writer.writeLine('const selectFragment = selectFragments[condition[0]];');
297
+ writer.writeLine('const operator = condition[1];');
298
+ writer.blankLine();
299
+ if (hasStringColumn(tsDescriptor.columns)) {
300
+ writer.write(`if (operator == 'LIKE') `).block(() => {
301
+ writer.write('return ').block(() => {
302
+ writer.writeLine("sql: `${selectFragment} LIKE concat('%', ?, '%')`,");
303
+ writer.writeLine('hasValue: condition[2] != null,');
304
+ writer.writeLine('values: [condition[2]]');
305
+ });
306
+ });
307
+ }
308
+ writer.write(`if (operator == 'BETWEEN') `).block(() => {
309
+ writer.write('return ').block(() => {
310
+ writer.writeLine('sql: `${selectFragment} BETWEEN ? AND ?`,');
311
+ writer.writeLine('hasValue: condition[2] != null && condition[3] != null,');
312
+ writer.writeLine('values: [condition[2], condition[3]]');
313
+ });
314
+ });
315
+ writer.write(`if (operator == 'IN' || operator == 'NOT IN') `).block(() => {
316
+ writer.write('return ').block(() => {
317
+ writer.writeLine('sql: `${selectFragment} ${operator} (?)`,');
318
+ writer.writeLine('hasValue: condition[2] != null && condition[2].length > 0,');
319
+ writer.writeLine('values: [condition[2]]');
320
+ });
321
+ });
322
+ writer.write('if (NumericOperatorList.includes(operator)) ').block(() => {
323
+ writer.write('return ').block(() => {
324
+ writer.writeLine('sql: `${selectFragment} ${operator} ?`,');
325
+ writer.writeLine('hasValue: condition[2] != null,');
326
+ writer.writeLine('values: [condition[2]]');
327
+ });
328
+ });
329
+ });
330
+ }
331
+ }
332
+ if (generateOrderBy) {
333
+ const orderByColumnsType = (_a = tsDescriptor.orderByColumns) === null || _a === void 0 ? void 0 : _a.map((col) => `'${col}'`).join(' | ');
334
+ writer.blankLine();
335
+ writer.write(`export type ${orderByTypeName} = `).block(() => {
336
+ if (tsDescriptor.dynamicQuery == null) {
337
+ writer.writeLine(`column: ${orderByColumnsType};`);
338
+ }
339
+ else {
340
+ writer.writeLine('column: keyof typeof orderByFragments;');
341
+ }
342
+ writer.writeLine(`direction: 'asc' | 'desc';`);
343
+ });
344
+ writer.blankLine();
345
+ writer.write(`function buildOrderBy(orderBy: ${orderByTypeName}[]): string`).block(() => {
346
+ if (tsDescriptor.dynamicQuery == null) {
347
+ writer.writeLine(`return orderBy.map(order => \`\\\`\${order.column}\\\` \${order.direction == 'desc' ? 'desc' : 'asc' }\`).join(', ');`);
348
+ }
349
+ else {
350
+ writer.writeLine(`return orderBy.map(order => \`\${orderByFragments[order.column]} \${order.direction == 'desc' ? 'desc' : 'asc'}\`).join(', ');`);
351
+ }
352
+ });
353
+ }
354
+ if (tsDescriptor.nestedDescriptor) {
355
+ const relations = tsDescriptor.nestedDescriptor.relations;
356
+ relations.forEach((relation) => {
357
+ const relationType = generateRelationType(capitalizedName, relation.name);
358
+ writer.blankLine();
359
+ writer.write(`export type ${relationType} = `).block(() => {
360
+ const uniqueNameFields = renameInvalidNames(relation.fields.map((f) => f.name));
361
+ relation.fields.forEach((field, index) => {
362
+ if (field.type === 'field') {
363
+ writer.writeLine(`${uniqueNameFields[index]}: ${field.tsType};`);
364
+ }
365
+ if (field.type === 'relation') {
366
+ const nestedRelationType = generateRelationType(capitalizedName, field.tsType);
367
+ const nullableOperator = field.notNull ? '' : '?';
368
+ writer.writeLine(`${field.name}${nullableOperator}: ${nestedRelationType};`);
369
+ }
370
+ });
371
+ });
372
+ });
373
+ relations.forEach((relation, index) => {
374
+ const relationType = generateRelationType(capitalizedName, relation.name);
375
+ if (index === 0) {
376
+ //first
377
+ writer.blankLine();
378
+ writer.write(`export async function ${camelCaseName}Nested(${functionArguments}): Promise<${relationType}[]>`).block(() => {
379
+ const params = tsDescriptor.parameters.length > 0 ? ', params' : '';
380
+ writer.writeLine(`const selectResult = await ${camelCaseName}(connection${params});`);
381
+ writer.write('if (selectResult.length == 0)').block(() => {
382
+ writer.writeLine('return [];');
383
+ });
384
+ writer.writeLine(`return collect${relationType}(selectResult);`);
385
+ });
386
+ }
387
+ const collectFunctionName = `collect${relationType}`;
388
+ const mapFunctionName = `mapTo${relationType}`;
389
+ writer.blankLine();
390
+ writer.write(`function ${collectFunctionName}(selectResult: ${resultTypeName}[]): ${relationType}[]`).block(() => {
391
+ const groupKey = tsDescriptor.columns[relation.groupKeyIndex].name;
392
+ writer.writeLine(`const grouped = groupBy(selectResult.filter(r => r.${groupKey} != null), r => r.${groupKey});`);
393
+ writer.writeLine(`return [...grouped.values()].map(r => ${mapFunctionName}(r))`);
394
+ });
395
+ writer.blankLine();
396
+ writer.write(`function ${mapFunctionName}(selectResult: ${resultTypeName}[]): ${relationType}`).block(() => {
397
+ writer.writeLine('const firstRow = selectResult[0];');
398
+ writer.write(`const result: ${relationType} = `).block(() => {
399
+ const uniqueNameFields = renameInvalidNames(relation.fields.map((f) => f.name));
400
+ relation.fields.forEach((field, index) => {
401
+ const separator = commaSeparator(relation.fields.length, index);
402
+ if (field.type === 'field') {
403
+ const fieldName = tsDescriptor.columns[field.index].name;
404
+ writer.writeLine(`${uniqueNameFields[index]}: firstRow.${fieldName}!${separator}`);
405
+ }
406
+ if (field.type === 'relation') {
407
+ const nestedRelationType = generateRelationType(capitalizedName, field.name);
408
+ const cardinality = field.list ? '' : '[0]';
409
+ writer.writeLine(`${field.name}: collect${nestedRelationType}(selectResult)${cardinality}${separator}`);
410
+ }
411
+ });
412
+ });
413
+ writer.writeLine('return result;');
414
+ });
415
+ });
416
+ writer.blankLine();
417
+ writer.write('const groupBy = <T, Q>(array: T[], predicate: (value: T, index: number, array: T[]) => Q) =>').block(() => {
418
+ writer
419
+ .write('return array.reduce((map, value, index, array) => ')
420
+ .inlineBlock(() => {
421
+ writer.writeLine('const key = predicate(value, index, array);');
422
+ writer.writeLine('map.get(key)?.push(value) ?? map.set(key, [value]);');
423
+ writer.writeLine('return map;');
424
+ })
425
+ .write(', new Map<Q, T[]>());');
426
+ });
427
+ }
428
+ return writer.toString();
429
+ }
430
+ function generateDynamicQueryFrom(writer, sqlVar, fragment, columns, includeOrderBy = false) {
431
+ var _a;
432
+ const selectConditions = fragment.dependOnFields.map((fieldIndex) => `params.select.${columns[fieldIndex].name}`);
433
+ if (selectConditions.length > 0) {
434
+ selectConditions.unshift('params?.select == null');
435
+ }
436
+ const paramConditions = fragment.dependOnParams.map((param) => `params.params?.${param} != null`);
437
+ const whereConditions = fragment.dependOnFields.map((fieldIndex) => `where.${columns[fieldIndex].name} != null`);
438
+ const orderByConditions = includeOrderBy ? ((_a = fragment.dependOnOrderBy) === null || _a === void 0 ? void 0 : _a.map((orderBy) => `orderBy['${orderBy}'] != null`)) || [] : [];
439
+ const allConditions = [...selectConditions, ...paramConditions, ...whereConditions, ...orderByConditions];
440
+ const paramValues = fragment.parameters.map((param) => `params?.params?.${param}`);
441
+ if (allConditions.length > 0) {
442
+ writer.write(`if (${allConditions.join(`${node_os_1.EOL} || `)})`).block(() => {
443
+ writer.write(`${sqlVar} += EOL + \`${fragment.fragment}\`;`);
444
+ for (const paramValue of paramValues) {
445
+ writer.writeLine(`paramsValues.push(${paramValue});`);
446
+ }
447
+ });
448
+ }
449
+ else {
450
+ writer.writeLine(`${sqlVar} += EOL + \`${fragment.fragment}\`;`);
451
+ for (const paramValue of paramValues) {
452
+ writer.writeLine(`paramsValues.push(${paramValue});`);
453
+ }
454
+ }
455
+ }
456
+ function getOperator(type) {
457
+ if (type === 'number' || type === 'Date') {
458
+ return 'NumericOperator';
459
+ }
460
+ return 'StringOperator';
461
+ }
462
+ function generateParam(param) {
463
+ if (param.isList) {
464
+ return `params.${param.name}.length == 0? null : params.${param.name}`;
465
+ }
466
+ return `params.${param.name}`;
467
+ }
468
+ function generateRelationType(functionName, relationName) {
469
+ return `${capitalizeStr(functionName)}Nested${capitalizeStr(relationName)}`;
470
+ }
471
+ function writeTypeBlock(writer, fields, typeName, updateCrud, extraField) {
472
+ const writeBlockCond = fields.length > 0 || extraField != null;
473
+ if (writeBlockCond) {
474
+ writer.write(`export type ${typeName} =`).block(() => {
475
+ fields.forEach((tsField, index) => {
476
+ // :nameSet, :name, valueSet, :value...
477
+ if (updateCrud && index % 2 !== 0) {
478
+ //only odd fields (:name, :value)
479
+ writer.writeLine(`${tsFieldToStr(tsField, true)};`);
480
+ }
481
+ else if (!updateCrud) {
482
+ writer.writeLine(`${tsFieldToStr(tsField, false)};`);
483
+ }
484
+ });
485
+ if (extraField) {
486
+ writer.write(`${extraField};`);
487
+ }
488
+ });
489
+ writer.blankLine();
490
+ }
491
+ }
492
+ function tsFieldToStr(tsField, isCrudUpdate) {
493
+ if (isCrudUpdate) {
494
+ //all fields are optionals
495
+ return `${tsField.name}?: ${tsField.tsType}${tsField.notNull === false ? ' | null' : ''}`;
496
+ }
497
+ return tsField.name + (tsField.notNull ? ': ' : '?: ') + tsField.tsType;
498
+ }
499
+ function generateTsDescriptor(queryInfo) {
500
+ var _a;
501
+ const escapedColumnsNames = renameInvalidNames(queryInfo.columns.map((col) => col.name));
502
+ const columns = queryInfo.columns.map((col, columnIndex) => {
503
+ const tsDesc = {
504
+ name: escapedColumnsNames[columnIndex],
505
+ tsType: mapColumnType(col.type),
506
+ notNull: col.notNull ? col.notNull : false
507
+ };
508
+ return tsDesc;
509
+ });
510
+ const parameterNames = queryInfo.parameters.map((p) => {
511
+ const paramInfo = {
512
+ name: p.name,
513
+ isList: !!p.columnType.endsWith('[]')
514
+ };
515
+ return paramInfo;
516
+ });
517
+ const uniqueParams = removeDuplicatedParameters(queryInfo.parameters);
518
+ const escapedParametersNames = renameInvalidNames(uniqueParams.map((col) => col.name));
519
+ const parameters = uniqueParams.map((col, paramIndex) => {
520
+ const arraySymbol = col.list ? '[]' : '';
521
+ const tsDesc = {
522
+ name: escapedParametersNames[paramIndex],
523
+ tsType: mapColumnType(col.columnType) + arraySymbol,
524
+ notNull: col.notNull ? col.notNull : false,
525
+ toDriver: col.name,
526
+ isArray: false
527
+ };
528
+ return tsDesc;
529
+ });
530
+ const escapedDataNames = queryInfo.data ? renameInvalidNames(queryInfo.data.map((col) => col.name)) : [];
531
+ const data = (_a = queryInfo.data) === null || _a === void 0 ? void 0 : _a.map((col, dataIndex) => {
532
+ const tsDesc = {
533
+ name: escapedDataNames[dataIndex],
534
+ tsType: mapColumnType(col.columnType),
535
+ notNull: col.notNull ? col.notNull : false,
536
+ toDriver: col.name,
537
+ isArray: false
538
+ };
539
+ return tsDesc;
540
+ });
541
+ const result = {
542
+ sql: queryInfo.sql,
543
+ queryType: queryInfo.queryType,
544
+ multipleRowsResult: queryInfo.multipleRowsResult,
545
+ columns,
546
+ orderByColumns: queryInfo.orderByColumns,
547
+ parameterNames,
548
+ parameters,
549
+ data
550
+ };
551
+ if (queryInfo.nestedResultInfo) {
552
+ const nestedDescriptor = (0, ts_nested_descriptor_1.createNestedTsDescriptor)(queryInfo.columns, queryInfo.nestedResultInfo);
553
+ result.nestedDescriptor = nestedDescriptor;
554
+ }
555
+ if (queryInfo.dynamicSqlQuery) {
556
+ const dynamicQueryDescriptor = queryInfo.dynamicSqlQuery;
557
+ result.dynamicQuery = dynamicQueryDescriptor;
558
+ }
559
+ if (queryInfo.returning) {
560
+ result.returning = queryInfo.returning;
561
+ }
562
+ return result;
563
+ }
564
+ function removeDuplicatedParameters(parameters) {
565
+ const columnsCount = new Map();
566
+ parameters.forEach((param) => {
567
+ const dupParam = columnsCount.get(param.name);
568
+ if (dupParam != null) {
569
+ //duplicated - two parameter null and notNull, resturn the null param (notNull == false)
570
+ if (param.notNull === false) {
571
+ columnsCount.set(param.name, param);
572
+ }
573
+ // return param;
574
+ }
575
+ else {
576
+ columnsCount.set(param.name, param);
577
+ }
578
+ });
579
+ return [...columnsCount.values()];
580
+ }
581
+ //TODO - remove duplicated code
582
+ function removeDuplicatedParameters2(parameters) {
583
+ const columnsCount = new Map();
584
+ parameters.forEach((param) => {
585
+ const dupParam = columnsCount.get(param.name);
586
+ if (dupParam != null) {
587
+ //duplicated - two parameter null and notNull, resturn the null param (notNull == false)
588
+ if (param.notNull === false) {
589
+ columnsCount.set(param.name, param);
590
+ }
591
+ // return param;
592
+ }
593
+ else {
594
+ columnsCount.set(param.name, param);
595
+ }
596
+ });
597
+ return [...columnsCount.values()];
598
+ }
599
+ function renameInvalidNames(columnNames) {
600
+ const columnsCount = new Map();
601
+ return columnNames.map((columnName) => {
602
+ if (columnsCount.has(columnName)) {
603
+ const count = columnsCount.get(columnName) + 1;
604
+ columnsCount.set(columnName, count);
605
+ const newName = `${columnName}_${count}`;
606
+ return escapeInvalidTsField(newName);
607
+ }
608
+ columnsCount.set(columnName, 1);
609
+ return escapeInvalidTsField(columnName);
610
+ });
611
+ }
612
+ function scapeBackStick(sql) {
613
+ const pattern = /`/g;
614
+ return sql.replace(pattern, '\\`');
615
+ }
616
+ function escapeInvalidTsField(columnName) {
617
+ const validPattern = /^[a-zA-Z0-9_$]+$/g;
618
+ if (!validPattern.test(columnName)) {
619
+ return `"${columnName}"`;
620
+ }
621
+ return columnName;
622
+ }
623
+ function mapColumnType(columnType) {
624
+ if (columnType === 'any')
625
+ return 'any';
626
+ const types = [].concat(columnType);
627
+ const mappedTypes = types.map((type) => mysql_mapping_1.mapper.convertToTsType(type));
628
+ return mappedTypes.join(' | '); // number | string
629
+ }
630
+ function hasStringColumn(columns) {
631
+ return columns.some((c) => c.tsType === 'string');
632
+ }
633
+ function hasDateColumn(columns) {
634
+ return columns.some((c) => c.tsType === 'Date');
635
+ }
636
+ function replaceOrderByParam(sql) {
637
+ const patern = /(.*order\s+by\s*)(\?)(.\n$)*/i;
638
+ const newSql = sql.replace(patern, '$1${buildOrderBy(params.orderBy)}$3');
639
+ return newSql;
640
+ }
641
+ function capitalize(name) {
642
+ return capitalizeStr(name);
643
+ }
644
+ function capitalizeStr(name) {
645
+ if (name.length === 0)
646
+ return name;
647
+ return name.charAt(0).toUpperCase() + name.slice(1);
648
+ }
649
+ function convertToCamelCaseName(name) {
650
+ const camelCaseStr = (0, camelcase_1.default)(name);
651
+ return camelCaseStr;
652
+ }
653
+ function generateTsFileFromContent(client_1, queryName_1, sqlContent_1) {
654
+ return __awaiter(this, arguments, void 0, function* (client, queryName, sqlContent, crud = false) {
655
+ const queryInfoResult = yield (0, describe_query_1.parseSql)(client, sqlContent);
656
+ if ((0, Either_1.isLeft)(queryInfoResult)) {
657
+ return queryInfoResult;
658
+ }
659
+ const tsDescriptor = generateTsDescriptor(queryInfoResult.right);
660
+ const tsContent = generateTsCodeForMySQL(tsDescriptor, queryName, crud);
661
+ return (0, Either_1.right)(tsContent);
662
+ });
663
+ }
664
+ function commaSeparator(length, index) {
665
+ return length > 1 && index !== length - 1 ? ',' : '';
666
+ }
667
+ //# sourceMappingURL=mysql2.js.map