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