@anthonyalayo/drizzle-kit 1.0.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 (161) hide show
  1. package/.gitignore +25 -0
  2. package/README.md +79 -0
  3. package/build.dev.ts +51 -0
  4. package/build.ts +112 -0
  5. package/imports-checker/analyze.ts +78 -0
  6. package/imports-checker/checker.ts +296 -0
  7. package/imports-checker/grammar/grammar.ohm +121 -0
  8. package/imports-checker/grammar/grammar.ohm-bundle.d.ts +164 -0
  9. package/imports-checker/grammar/grammar.ohm-bundle.js +753 -0
  10. package/imports-checker/index.ts +48 -0
  11. package/package.json +142 -0
  12. package/patches/difflib@0.2.4.patch +31 -0
  13. package/src/@types/utils.ts +58 -0
  14. package/src/api.ts +504 -0
  15. package/src/cli/commands/_es5.ts +2 -0
  16. package/src/cli/commands/check.ts +52 -0
  17. package/src/cli/commands/drop.ts +60 -0
  18. package/src/cli/commands/introspect.ts +772 -0
  19. package/src/cli/commands/libSqlPushUtils.ts +355 -0
  20. package/src/cli/commands/migrate.ts +1526 -0
  21. package/src/cli/commands/mysqlIntrospect.ts +53 -0
  22. package/src/cli/commands/mysqlPushUtils.ts +352 -0
  23. package/src/cli/commands/mysqlUp.ts +102 -0
  24. package/src/cli/commands/pgIntrospect.ts +55 -0
  25. package/src/cli/commands/pgPushUtils.ts +269 -0
  26. package/src/cli/commands/pgUp.ts +217 -0
  27. package/src/cli/commands/push.ts +637 -0
  28. package/src/cli/commands/singlestoreIntrospect.ts +53 -0
  29. package/src/cli/commands/singlestorePushUtils.ts +456 -0
  30. package/src/cli/commands/singlestoreUp.ts +1 -0
  31. package/src/cli/commands/sqliteIntrospect.ts +96 -0
  32. package/src/cli/commands/sqlitePushUtils.ts +322 -0
  33. package/src/cli/commands/sqliteUp.ts +52 -0
  34. package/src/cli/commands/utils.ts +858 -0
  35. package/src/cli/connections.ts +914 -0
  36. package/src/cli/index.ts +48 -0
  37. package/src/cli/schema.ts +794 -0
  38. package/src/cli/selector-ui.ts +38 -0
  39. package/src/cli/utils.ts +112 -0
  40. package/src/cli/validations/cli.ts +79 -0
  41. package/src/cli/validations/common.ts +193 -0
  42. package/src/cli/validations/libsql.ts +27 -0
  43. package/src/cli/validations/mysql.ts +61 -0
  44. package/src/cli/validations/outputs.ts +91 -0
  45. package/src/cli/validations/postgres.ts +83 -0
  46. package/src/cli/validations/singlestore.ts +61 -0
  47. package/src/cli/validations/sqlite.ts +104 -0
  48. package/src/cli/validations/studio.ts +24 -0
  49. package/src/cli/views.ts +658 -0
  50. package/src/extensions/getTablesFilterByExtensions.ts +16 -0
  51. package/src/extensions/vector.ts +10 -0
  52. package/src/global.ts +61 -0
  53. package/src/index.ts +326 -0
  54. package/src/introspect-mysql.ts +1030 -0
  55. package/src/introspect-pg.ts +1435 -0
  56. package/src/introspect-singlestore.ts +913 -0
  57. package/src/introspect-sqlite.ts +533 -0
  58. package/src/jsonDiffer.js +882 -0
  59. package/src/jsonStatements.ts +3590 -0
  60. package/src/loader.mjs +57 -0
  61. package/src/migrationPreparator.ts +217 -0
  62. package/src/schemaValidator.ts +23 -0
  63. package/src/serializer/index.ts +142 -0
  64. package/src/serializer/mysqlImports.ts +38 -0
  65. package/src/serializer/mysqlSchema.ts +423 -0
  66. package/src/serializer/mysqlSerializer.ts +999 -0
  67. package/src/serializer/pgImports.ts +106 -0
  68. package/src/serializer/pgSchema.ts +937 -0
  69. package/src/serializer/pgSerializer.ts +2223 -0
  70. package/src/serializer/singlestoreImports.ts +38 -0
  71. package/src/serializer/singlestoreSchema.ts +257 -0
  72. package/src/serializer/singlestoreSerializer.ts +767 -0
  73. package/src/serializer/sqliteImports.ts +41 -0
  74. package/src/serializer/sqliteSchema.ts +352 -0
  75. package/src/serializer/sqliteSerializer.ts +931 -0
  76. package/src/serializer/studio.ts +694 -0
  77. package/src/serializer/utils.ts +45 -0
  78. package/src/simulator.ts +157 -0
  79. package/src/snapshotsDiffer.ts +4398 -0
  80. package/src/sqlgenerator.ts +4212 -0
  81. package/src/statementCombiner.ts +597 -0
  82. package/src/utils/certs.ts +44 -0
  83. package/src/utils/words.ts +1333 -0
  84. package/src/utils.ts +370 -0
  85. package/tests/bin.test.ts +58 -0
  86. package/tests/cli/d1http.config.ts +12 -0
  87. package/tests/cli/drizzle.config.ts +9 -0
  88. package/tests/cli/durable-sqlite.config.ts +7 -0
  89. package/tests/cli/expo.config.ts +7 -0
  90. package/tests/cli/postgres.config.ts +13 -0
  91. package/tests/cli/postgres2.config.ts +17 -0
  92. package/tests/cli/schema.ts +1 -0
  93. package/tests/cli/turso.config.ts +10 -0
  94. package/tests/cli-export.test.ts +79 -0
  95. package/tests/cli-generate.test.ts +259 -0
  96. package/tests/cli-migrate.test.ts +103 -0
  97. package/tests/cli-push.test.ts +126 -0
  98. package/tests/common.ts +15 -0
  99. package/tests/indexes/common.ts +21 -0
  100. package/tests/indexes/pg.test.ts +245 -0
  101. package/tests/introspect/libsql.test.ts +35 -0
  102. package/tests/introspect/mysql.test.ts +319 -0
  103. package/tests/introspect/pg.test.ts +894 -0
  104. package/tests/introspect/singlestore.test.ts +275 -0
  105. package/tests/introspect/sqlite.test.ts +122 -0
  106. package/tests/libsql-checks.test.ts +308 -0
  107. package/tests/libsql-statements.test.ts +989 -0
  108. package/tests/libsql-views.test.ts +218 -0
  109. package/tests/migrate/libsq-schema.ts +6 -0
  110. package/tests/migrate/libsql-migrate.test.ts +58 -0
  111. package/tests/migrate/migrations/0000_little_blizzard.sql +4 -0
  112. package/tests/migrate/migrations/0001_nebulous_storm.sql +10 -0
  113. package/tests/migrate/migrations/meta/0000_snapshot.json +40 -0
  114. package/tests/migrate/migrations/meta/0001_snapshot.json +40 -0
  115. package/tests/migrate/migrations/meta/_journal.json +20 -0
  116. package/tests/mysql-checks.test.ts +291 -0
  117. package/tests/mysql-generated.test.ts +1290 -0
  118. package/tests/mysql-schemas.test.ts +156 -0
  119. package/tests/mysql-views.test.ts +553 -0
  120. package/tests/mysql.test.ts +863 -0
  121. package/tests/pg-array.test.ts +368 -0
  122. package/tests/pg-checks.test.ts +329 -0
  123. package/tests/pg-columns.test.ts +484 -0
  124. package/tests/pg-domains.test.ts +306 -0
  125. package/tests/pg-enums.test.ts +751 -0
  126. package/tests/pg-generated.test.ts +529 -0
  127. package/tests/pg-identity.test.ts +447 -0
  128. package/tests/pg-schemas.test.ts +105 -0
  129. package/tests/pg-sequences.test.ts +298 -0
  130. package/tests/pg-tables.test.ts +1021 -0
  131. package/tests/pg-views.test.ts +1929 -0
  132. package/tests/push/common.ts +58 -0
  133. package/tests/push/libsql.test.ts +1400 -0
  134. package/tests/push/mysql-push.test.ts +345 -0
  135. package/tests/push/mysql.test.ts +788 -0
  136. package/tests/push/pg.test.ts +4341 -0
  137. package/tests/push/singlestore-push.test.ts +894 -0
  138. package/tests/push/singlestore.test.ts +444 -0
  139. package/tests/push/sqlite.test.ts +1613 -0
  140. package/tests/rls/pg-policy.test.ts +1656 -0
  141. package/tests/rls/pg-role.test.ts +234 -0
  142. package/tests/schemaDiffer.ts +2852 -0
  143. package/tests/singlestore-generated.test.ts +1290 -0
  144. package/tests/singlestore-schemas.test.ts +155 -0
  145. package/tests/singlestore.test.ts +978 -0
  146. package/tests/sqlite-checks.test.ts +308 -0
  147. package/tests/sqlite-columns.test.ts +1049 -0
  148. package/tests/sqlite-generated.test.ts +1726 -0
  149. package/tests/sqlite-tables.test.ts +637 -0
  150. package/tests/sqlite-views.test.ts +218 -0
  151. package/tests/statements-combiner/libsql-statements-combiner.test.ts +1812 -0
  152. package/tests/statements-combiner/singlestore-statements-combiner.test.ts +882 -0
  153. package/tests/statements-combiner/sqlite-statements-combiner.test.ts +1211 -0
  154. package/tests/test/sqlite.test.ts +39 -0
  155. package/tests/testsinglestore.ts +29 -0
  156. package/tests/validations.test.ts +869 -0
  157. package/tests/wrap-param.test.ts +16 -0
  158. package/tsconfig.build.json +4 -0
  159. package/tsconfig.cli-types.json +9 -0
  160. package/tsconfig.json +28 -0
  161. package/vitest.config.ts +34 -0
@@ -0,0 +1,913 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ import { toCamelCase } from 'drizzle-orm/casing';
3
+ import './@types/utils';
4
+ import type { Casing } from './cli/validations/common';
5
+ import { assertUnreachable } from './global';
6
+ import {
7
+ Column,
8
+ Index,
9
+ PrimaryKey,
10
+ SingleStoreSchema,
11
+ SingleStoreSchemaInternal,
12
+ UniqueConstraint,
13
+ } from './serializer/singlestoreSchema';
14
+ import { indexName } from './serializer/singlestoreSerializer';
15
+
16
+ // time precision to fsp
17
+ // {mode: "string"} for timestamp by default
18
+
19
+ const singlestoreImportsList = new Set([
20
+ 'singlestoreTable',
21
+ 'singlestoreEnum',
22
+ 'bigint',
23
+ 'binary',
24
+ 'boolean',
25
+ 'char',
26
+ 'date',
27
+ 'datetime',
28
+ 'decimal',
29
+ 'double',
30
+ 'float',
31
+ 'int',
32
+ 'json',
33
+ // TODO: add new type BSON
34
+ // TODO: add new type Blob
35
+ // TODO: add new type UUID
36
+ // TODO: add new type GUID
37
+ // TODO: add new type Vector
38
+ // TODO: add new type GeoPoint
39
+ 'mediumint',
40
+ 'real',
41
+ 'serial',
42
+ 'smallint',
43
+ 'text',
44
+ 'tinytext',
45
+ 'mediumtext',
46
+ 'longtext',
47
+ 'time',
48
+ 'timestamp',
49
+ 'tinyint',
50
+ 'varbinary',
51
+ 'varchar',
52
+ 'vector',
53
+ 'year',
54
+ 'enum',
55
+ ]);
56
+
57
+ const objToStatement = (json: any) => {
58
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
59
+
60
+ const keys = Object.keys(json);
61
+ if (keys.length === 0) return;
62
+
63
+ let statement = '{ ';
64
+ statement += keys.map((it) => `"${it}": "${json[it]}"`).join(', ');
65
+ statement += ' }';
66
+ return statement;
67
+ };
68
+
69
+ const objToStatement2 = (json: any) => {
70
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
71
+
72
+ const keys = Object.keys(json);
73
+ if (keys.length === 0) return;
74
+
75
+ let statement = '{ ';
76
+ statement += keys.map((it) => `${it}: "${json[it]}"`).join(', '); // no "" for keys
77
+ statement += ' }';
78
+ return statement;
79
+ };
80
+
81
+ const timeConfig = (json: any) => {
82
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
83
+
84
+ const keys = Object.keys(json);
85
+ if (keys.length === 0) return;
86
+
87
+ let statement = '{ ';
88
+ statement += keys.map((it) => `${it}: ${json[it]}`).join(', ');
89
+ statement += ' }';
90
+ return statement;
91
+ };
92
+
93
+ const binaryConfig = (json: any) => {
94
+ json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
95
+
96
+ const keys = Object.keys(json);
97
+ if (keys.length === 0) return;
98
+
99
+ let statement = '{ ';
100
+ statement += keys.map((it) => `${it}: ${json[it]}`).join(', ');
101
+ statement += ' }';
102
+ return statement;
103
+ };
104
+
105
+ const importsPatch = {
106
+ 'double precision': 'doublePrecision',
107
+ 'timestamp without time zone': 'timestamp',
108
+ } as Record<string, string>;
109
+
110
+ const escapeColumnKey = (value: string) => {
111
+ if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) {
112
+ return `"${value}"`;
113
+ }
114
+ return value;
115
+ };
116
+
117
+ const prepareCasing = (casing?: Casing) => (value: string) => {
118
+ if (casing === 'preserve') {
119
+ return escapeColumnKey(value);
120
+ }
121
+ if (casing === 'camel') {
122
+ return escapeColumnKey(value.camelCase());
123
+ }
124
+
125
+ assertUnreachable(casing);
126
+ };
127
+
128
+ const dbColumnName = ({ name, casing, withMode = false }: { name: string; casing: Casing; withMode?: boolean }) => {
129
+ if (casing === 'preserve') {
130
+ return '';
131
+ }
132
+ if (casing === 'camel') {
133
+ return toCamelCase(name) === name ? '' : withMode ? `"${name}", ` : `"${name}"`;
134
+ }
135
+
136
+ assertUnreachable(casing);
137
+ };
138
+
139
+ export const schemaToTypeScript = (
140
+ schema: SingleStoreSchemaInternal,
141
+ casing: Casing,
142
+ ) => {
143
+ const withCasing = prepareCasing(casing);
144
+
145
+ const imports = Object.values(schema.tables).reduce(
146
+ (res, it) => {
147
+ const idxImports = Object.values(it.indexes).map((idx) => idx.isUnique ? 'uniqueIndex' : 'index');
148
+ const pkImports = Object.values(it.compositePrimaryKeys).map(
149
+ (it) => 'primaryKey',
150
+ );
151
+ const uniqueImports = Object.values(it.uniqueConstraints).map(
152
+ (it) => 'unique',
153
+ );
154
+
155
+ res.singlestore.push(...idxImports);
156
+ res.singlestore.push(...pkImports);
157
+ res.singlestore.push(...uniqueImports);
158
+
159
+ const columnImports = Object.values(it.columns)
160
+ .map((col) => {
161
+ let patched = importsPatch[col.type] ?? col.type;
162
+ patched = patched.startsWith('varchar(') ? 'varchar' : patched;
163
+ patched = patched.startsWith('char(') ? 'char' : patched;
164
+ patched = patched.startsWith('binary(') ? 'binary' : patched;
165
+ patched = patched.startsWith('decimal(') ? 'decimal' : patched;
166
+ patched = patched.startsWith('smallint(') ? 'smallint' : patched;
167
+ patched = patched.startsWith('enum(') ? 'singlestoreEnum' : patched;
168
+ patched = patched.startsWith('datetime(') ? 'datetime' : patched;
169
+ patched = patched.startsWith('varbinary(') ? 'varbinary' : patched;
170
+ patched = patched.startsWith('int(') ? 'int' : patched;
171
+ patched = patched.startsWith('double(') ? 'double' : patched;
172
+ patched = patched.startsWith('float(') ? 'float' : patched;
173
+ patched = patched.startsWith('int unsigned') ? 'int' : patched;
174
+ patched = patched.startsWith('tinyint(') ? 'tinyint' : patched;
175
+ patched = patched.startsWith('mediumint(') ? 'mediumint' : patched;
176
+ patched = patched.startsWith('bigint(') ? 'bigint' : patched;
177
+ patched = patched.startsWith('tinyint unsigned') ? 'tinyint' : patched;
178
+ patched = patched.startsWith('smallint unsigned') ? 'smallint' : patched;
179
+ patched = patched.startsWith('mediumint unsigned') ? 'mediumint' : patched;
180
+ patched = patched.startsWith('bigint unsigned') ? 'bigint' : patched;
181
+ return patched;
182
+ })
183
+ .filter((type) => {
184
+ return singlestoreImportsList.has(type);
185
+ });
186
+
187
+ res.singlestore.push(...columnImports);
188
+ return res;
189
+ },
190
+ { singlestore: [] as string[] },
191
+ );
192
+
193
+ /* Object.values(schema.views).forEach((it) => {
194
+ imports.singlestore.push('singlestoreView');
195
+
196
+ const columnImports = Object.values(it.columns)
197
+ .map((col) => {
198
+ let patched = importsPatch[col.type] ?? col.type;
199
+ patched = patched.startsWith('varchar(') ? 'varchar' : patched;
200
+ patched = patched.startsWith('char(') ? 'char' : patched;
201
+ patched = patched.startsWith('binary(') ? 'binary' : patched;
202
+ patched = patched.startsWith('decimal(') ? 'decimal' : patched;
203
+ patched = patched.startsWith('smallint(') ? 'smallint' : patched;
204
+ patched = patched.startsWith('enum(') ? 'singlestoreEnum' : patched;
205
+ patched = patched.startsWith('datetime(') ? 'datetime' : patched;
206
+ patched = patched.startsWith('varbinary(') ? 'varbinary' : patched;
207
+ patched = patched.startsWith('int(') ? 'int' : patched;
208
+ patched = patched.startsWith('double(') ? 'double' : patched;
209
+ patched = patched.startsWith('float(') ? 'float' : patched;
210
+ patched = patched.startsWith('int unsigned') ? 'int' : patched;
211
+ patched = patched.startsWith('tinyint(') ? 'tinyint' : patched;
212
+ patched = patched.startsWith('mediumint(') ? 'mediumint' : patched;
213
+ patched = patched.startsWith('bigint(') ? 'bigint' : patched;
214
+ patched = patched.startsWith('tinyint unsigned') ? 'tinyint' : patched;
215
+ patched = patched.startsWith('smallint unsigned') ? 'smallint' : patched;
216
+ patched = patched.startsWith('mediumint unsigned') ? 'mediumint' : patched;
217
+ patched = patched.startsWith('bigint unsigned') ? 'bigint' : patched;
218
+ return patched;
219
+ })
220
+ .filter((type) => {
221
+ return singlestoreImportsList.has(type);
222
+ });
223
+
224
+ imports.singlestore.push(...columnImports);
225
+ }); */
226
+
227
+ const tableStatements = Object.values(schema.tables).map((table) => {
228
+ const func = 'singlestoreTable';
229
+ let statement = '';
230
+ if (imports.singlestore.includes(withCasing(table.name))) {
231
+ statement = `// Table name is in conflict with ${
232
+ withCasing(
233
+ table.name,
234
+ )
235
+ } import.\n// Please change to any other name, that is not in imports list\n`;
236
+ }
237
+ statement += `export const ${withCasing(table.name)} = ${func}("${table.name}", {\n`;
238
+ statement += createTableColumns(
239
+ Object.values(table.columns),
240
+ withCasing,
241
+ casing,
242
+ table.name,
243
+ schema,
244
+ );
245
+ statement += '}';
246
+
247
+ if (
248
+ Object.keys(table.indexes).length > 0
249
+ || Object.keys(table.compositePrimaryKeys).length > 0
250
+ || Object.keys(table.uniqueConstraints).length > 0
251
+ ) {
252
+ statement += ',\n';
253
+ statement += '(table) => [';
254
+ statement += createTableIndexes(
255
+ table.name,
256
+ Object.values(table.indexes),
257
+ withCasing,
258
+ );
259
+ statement += createTablePKs(
260
+ Object.values(table.compositePrimaryKeys),
261
+ withCasing,
262
+ );
263
+ statement += createTableUniques(
264
+ Object.values(table.uniqueConstraints),
265
+ withCasing,
266
+ );
267
+ statement += '\n]';
268
+ }
269
+
270
+ statement += ');';
271
+ return statement;
272
+ });
273
+
274
+ /* const viewsStatements = Object.values(schema.views).map((view) => {
275
+ const { columns, name, algorithm, definition, sqlSecurity, withCheckOption } = view;
276
+ const func = 'singlestoreView';
277
+ let statement = '';
278
+
279
+ if (imports.singlestore.includes(withCasing(name))) {
280
+ statement = `// Table name is in conflict with ${
281
+ withCasing(
282
+ view.name,
283
+ )
284
+ } import.\n// Please change to any other name, that is not in imports list\n`;
285
+ }
286
+ statement += `export const ${withCasing(name)} = ${func}("${name}", {\n`;
287
+ statement += createTableColumns(
288
+ Object.values(columns),
289
+ withCasing,
290
+ casing,
291
+ name,
292
+ schema,
293
+ );
294
+ statement += '})';
295
+
296
+ statement += algorithm ? `.algorithm("${algorithm}")` : '';
297
+ statement += sqlSecurity ? `.sqlSecurity("${sqlSecurity}")` : '';
298
+ statement += withCheckOption ? `.withCheckOption("${withCheckOption}")` : '';
299
+ statement += `.as(sql\`${definition?.replaceAll('`', '\\`')}\`);`;
300
+
301
+ return statement;
302
+ }); */
303
+
304
+ const uniqueSingleStoreImports = [
305
+ 'singlestoreTable',
306
+ 'singlestoreSchema',
307
+ 'AnySingleStoreColumn',
308
+ ...new Set(imports.singlestore),
309
+ ];
310
+ const importsTs = `import { ${
311
+ uniqueSingleStoreImports.join(
312
+ ', ',
313
+ )
314
+ } } from "drizzle-orm/singlestore-core"\nimport { sql } from "drizzle-orm"\n\n`;
315
+
316
+ let decalrations = '';
317
+ decalrations += tableStatements.join('\n\n');
318
+ decalrations += '\n';
319
+ /* decalrations += viewsStatements.join('\n\n'); */
320
+
321
+ const file = importsTs + decalrations;
322
+
323
+ const schemaEntry = `
324
+ {
325
+ ${
326
+ Object.values(schema.tables)
327
+ .map((it) => withCasing(it.name))
328
+ .join(',')
329
+ }
330
+ }
331
+ `;
332
+
333
+ return {
334
+ file, // backward compatible, print to file
335
+ imports: importsTs,
336
+ decalrations,
337
+ schemaEntry,
338
+ };
339
+ };
340
+
341
+ const mapColumnDefault = (defaultValue: any, isExpression?: boolean) => {
342
+ if (isExpression) {
343
+ return `sql\`${defaultValue}\``;
344
+ }
345
+
346
+ return defaultValue;
347
+ };
348
+
349
+ const mapColumnDefaultForJson = (defaultValue: any) => {
350
+ if (
351
+ typeof defaultValue === 'string'
352
+ && defaultValue.startsWith("('")
353
+ && defaultValue.endsWith("')")
354
+ ) {
355
+ return defaultValue.substring(2, defaultValue.length - 2);
356
+ }
357
+
358
+ return defaultValue;
359
+ };
360
+
361
+ const column = (
362
+ type: string,
363
+ name: string,
364
+ casing: (value: string) => string,
365
+ rawCasing: Casing,
366
+ defaultValue?: any,
367
+ autoincrement?: boolean,
368
+ onUpdate?: boolean,
369
+ isExpression?: boolean,
370
+ ) => {
371
+ let lowered = type;
372
+ if (!type.startsWith('enum(')) {
373
+ lowered = type.toLowerCase();
374
+ }
375
+
376
+ if (lowered === 'serial') {
377
+ return `${casing(name)}: serial(${dbColumnName({ name, casing: rawCasing })})`;
378
+ }
379
+
380
+ if (lowered.startsWith('int')) {
381
+ const isUnsigned = lowered.includes('unsigned');
382
+ const columnName = dbColumnName({ name, casing: rawCasing, withMode: isUnsigned });
383
+ let out = `${casing(name)}: int(${columnName}${isUnsigned ? '{ unsigned: true }' : ''})`;
384
+ out += autoincrement ? `.autoincrement()` : '';
385
+ out += typeof defaultValue !== 'undefined'
386
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
387
+ : '';
388
+ return out;
389
+ }
390
+
391
+ if (lowered.startsWith('tinyint')) {
392
+ const isUnsigned = lowered.includes('unsigned');
393
+ const columnName = dbColumnName({ name, casing: rawCasing, withMode: isUnsigned });
394
+ let out: string = `${casing(name)}: tinyint(${columnName}${isUnsigned ? '{ unsigned: true }' : ''})`;
395
+ out += autoincrement ? `.autoincrement()` : '';
396
+ out += typeof defaultValue !== 'undefined'
397
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
398
+ : '';
399
+ return out;
400
+ }
401
+
402
+ if (lowered.startsWith('smallint')) {
403
+ const isUnsigned = lowered.includes('unsigned');
404
+ const columnName = dbColumnName({ name, casing: rawCasing, withMode: isUnsigned });
405
+ let out = `${casing(name)}: smallint(${columnName}${isUnsigned ? '{ unsigned: true }' : ''})`;
406
+ out += autoincrement ? `.autoincrement()` : '';
407
+ out += defaultValue
408
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
409
+ : '';
410
+ return out;
411
+ }
412
+
413
+ if (lowered.startsWith('mediumint')) {
414
+ const isUnsigned = lowered.includes('unsigned');
415
+ const columnName = dbColumnName({ name, casing: rawCasing, withMode: isUnsigned });
416
+ let out = `${casing(name)}: mediumint(${columnName}${isUnsigned ? '{ unsigned: true }' : ''})`;
417
+ out += autoincrement ? `.autoincrement()` : '';
418
+ out += defaultValue
419
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
420
+ : '';
421
+ return out;
422
+ }
423
+
424
+ if (lowered.startsWith('bigint')) {
425
+ const isUnsigned = lowered.includes('unsigned');
426
+ let out = `${casing(name)}: bigint(${dbColumnName({ name, casing: rawCasing, withMode: true })}{ mode: "number"${
427
+ isUnsigned ? ', unsigned: true' : ''
428
+ } })`;
429
+ out += autoincrement ? `.autoincrement()` : '';
430
+ out += defaultValue
431
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
432
+ : '';
433
+ return out;
434
+ }
435
+
436
+ if (lowered === 'boolean') {
437
+ let out = `${casing(name)}: boolean(${dbColumnName({ name, casing: rawCasing })})`;
438
+ out += defaultValue
439
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
440
+ : '';
441
+ return out;
442
+ }
443
+
444
+ if (lowered.startsWith('double')) {
445
+ let params:
446
+ | { precision?: string; scale?: string; unsigned?: boolean }
447
+ | undefined;
448
+
449
+ if (lowered.length > (lowered.includes('unsigned') ? 15 : 6)) {
450
+ const [precision, scale] = lowered
451
+ .slice(7, lowered.length - (1 + (lowered.includes('unsigned') ? 9 : 0)))
452
+ .split(',');
453
+ params = { precision, scale };
454
+ }
455
+
456
+ if (lowered.includes('unsigned')) {
457
+ params = { ...(params ?? {}), unsigned: true };
458
+ }
459
+
460
+ const timeConfigParams = params ? timeConfig(params) : undefined;
461
+
462
+ let out = params
463
+ ? `${casing(name)}: double(${
464
+ dbColumnName({ name, casing: rawCasing, withMode: timeConfigParams !== undefined })
465
+ }${timeConfig(params)})`
466
+ : `${casing(name)}: double(${dbColumnName({ name, casing: rawCasing })})`;
467
+
468
+ // let out = `${name.camelCase()}: double("${name}")`;
469
+ out += defaultValue
470
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
471
+ : '';
472
+ return out;
473
+ }
474
+
475
+ if (lowered.startsWith('float')) {
476
+ let params:
477
+ | { precision?: string; scale?: string; unsigned?: boolean }
478
+ | undefined;
479
+
480
+ if (lowered.length > (lowered.includes('unsigned') ? 14 : 5)) {
481
+ const [precision, scale] = lowered
482
+ .slice(6, lowered.length - (1 + (lowered.includes('unsigned') ? 9 : 0)))
483
+ .split(',');
484
+ params = { precision, scale };
485
+ }
486
+
487
+ if (lowered.includes('unsigned')) {
488
+ params = { ...(params ?? {}), unsigned: true };
489
+ }
490
+
491
+ let out = `${casing(name)}: float(${dbColumnName({ name, casing: rawCasing })}${params ? timeConfig(params) : ''})`;
492
+ out += defaultValue
493
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
494
+ : '';
495
+ return out;
496
+ }
497
+
498
+ if (lowered === 'real') {
499
+ let out = `${casing(name)}: real(${dbColumnName({ name, casing: rawCasing })})`;
500
+ out += defaultValue
501
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
502
+ : '';
503
+ return out;
504
+ }
505
+
506
+ if (lowered.startsWith('timestamp')) {
507
+ const keyLength = 'timestamp'.length + 1;
508
+ let fsp = lowered.length > keyLength
509
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
510
+ : null;
511
+ fsp = fsp ? fsp : null;
512
+
513
+ const params = timeConfig({ fsp, mode: "'string'" });
514
+
515
+ let out = params
516
+ ? `${casing(name)}: timestamp(${
517
+ dbColumnName({ name, casing: rawCasing, withMode: params !== undefined })
518
+ }${params})`
519
+ : `${casing(name)}: timestamp(${dbColumnName({ name, casing: rawCasing })})`;
520
+
521
+ // singlestore has only CURRENT_TIMESTAMP, as I found from docs. But will leave now() for just a case
522
+ defaultValue = defaultValue === 'now()' || defaultValue === 'CURRENT_TIMESTAMP'
523
+ ? '.defaultNow()'
524
+ : defaultValue
525
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
526
+ : '';
527
+
528
+ out += defaultValue;
529
+
530
+ let onUpdateNow = onUpdate ? '.onUpdateNow()' : '';
531
+ out += onUpdateNow;
532
+
533
+ return out;
534
+ }
535
+
536
+ if (lowered.startsWith('time')) {
537
+ const keyLength = 'time'.length + 1;
538
+ let fsp = lowered.length > keyLength
539
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
540
+ : null;
541
+ fsp = fsp ? fsp : null;
542
+
543
+ const params = timeConfig({ fsp });
544
+
545
+ let out = params
546
+ ? `${casing(name)}: time(${dbColumnName({ name, casing: rawCasing, withMode: params !== undefined })}${params})`
547
+ : `${casing(name)}: time(${dbColumnName({ name, casing: rawCasing })})`;
548
+
549
+ defaultValue = defaultValue === 'now()'
550
+ ? '.defaultNow()'
551
+ : defaultValue
552
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
553
+ : '';
554
+
555
+ out += defaultValue;
556
+ return out;
557
+ }
558
+
559
+ if (lowered === 'date') {
560
+ let out = `// you can use { mode: 'date' }, if you want to have Date as type for this column\n\t${
561
+ casing(
562
+ name,
563
+ )
564
+ }: date(${dbColumnName({ name, casing: rawCasing, withMode: true })}{ mode: 'string' })`;
565
+
566
+ defaultValue = defaultValue === 'now()'
567
+ ? '.defaultNow()'
568
+ : defaultValue
569
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
570
+ : '';
571
+
572
+ out += defaultValue;
573
+ return out;
574
+ }
575
+
576
+ // in singlestore text can't have default value. Will leave it in case smth ;)
577
+ if (lowered === 'text') {
578
+ let out = `${casing(name)}: text(${dbColumnName({ name, casing: rawCasing })})`;
579
+ out += defaultValue
580
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
581
+ : '';
582
+ return out;
583
+ }
584
+
585
+ // in singlestore text can't have default value. Will leave it in case smth ;)
586
+ if (lowered === 'tinytext') {
587
+ let out = `${casing(name)}: tinytext(${dbColumnName({ name, casing: rawCasing })})`;
588
+ out += defaultValue
589
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
590
+ : '';
591
+ return out;
592
+ }
593
+
594
+ // in singlestore text can't have default value. Will leave it in case smth ;)
595
+ if (lowered === 'mediumtext') {
596
+ let out = `${casing(name)}: mediumtext(${dbColumnName({ name, casing: rawCasing })})`;
597
+ out += defaultValue
598
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
599
+ : '';
600
+ return out;
601
+ }
602
+
603
+ // in singlestore text can't have default value. Will leave it in case smth ;)
604
+ if (lowered === 'longtext') {
605
+ let out = `${casing(name)}: longtext(${dbColumnName({ name, casing: rawCasing })})`;
606
+ out += defaultValue
607
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
608
+ : '';
609
+ return out;
610
+ }
611
+
612
+ if (lowered === 'year') {
613
+ let out = `${casing(name)}: year(${dbColumnName({ name, casing: rawCasing })})`;
614
+ out += defaultValue
615
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
616
+ : '';
617
+ return out;
618
+ }
619
+
620
+ // in singlestore json can't have default value. Will leave it in case smth ;)
621
+ if (lowered === 'json') {
622
+ let out = `${casing(name)}: json(${dbColumnName({ name, casing: rawCasing })})`;
623
+
624
+ out += defaultValue
625
+ ? `.default(${mapColumnDefaultForJson(defaultValue)})`
626
+ : '';
627
+
628
+ return out;
629
+ }
630
+
631
+ if (lowered.startsWith('varchar')) {
632
+ let out: string = `${
633
+ casing(
634
+ name,
635
+ )
636
+ }: varchar(${dbColumnName({ name, casing: rawCasing, withMode: true })}{ length: ${
637
+ lowered.substring(
638
+ 'varchar'.length + 1,
639
+ lowered.length - 1,
640
+ )
641
+ } })`;
642
+
643
+ out += defaultValue
644
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
645
+ : '';
646
+ return out;
647
+ }
648
+
649
+ if (lowered.startsWith('char')) {
650
+ let out: string = `${
651
+ casing(
652
+ name,
653
+ )
654
+ }: char(${dbColumnName({ name, casing: rawCasing, withMode: true })}{ length: ${
655
+ lowered.substring(
656
+ 'char'.length + 1,
657
+ lowered.length - 1,
658
+ )
659
+ } })`;
660
+
661
+ out += defaultValue
662
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
663
+ : '';
664
+ return out;
665
+ }
666
+
667
+ if (lowered.startsWith('datetime')) {
668
+ let out = `// you can use { mode: 'date' }, if you want to have Date as type for this column\n\t`;
669
+
670
+ const fsp = lowered.startsWith('datetime(')
671
+ ? lowered.substring('datetime'.length + 1, lowered.length - 1)
672
+ : undefined;
673
+
674
+ out = fsp
675
+ ? `${
676
+ casing(
677
+ name,
678
+ )
679
+ }: datetime(${dbColumnName({ name, casing: rawCasing, withMode: true })}{ mode: 'string', fsp: ${
680
+ lowered.substring(
681
+ 'datetime'.length + 1,
682
+ lowered.length - 1,
683
+ )
684
+ } })`
685
+ : `${casing(name)}: datetime(${dbColumnName({ name, casing: rawCasing, withMode: true })}{ mode: 'string'})`;
686
+
687
+ defaultValue = defaultValue === 'now()'
688
+ ? '.defaultNow()'
689
+ : defaultValue
690
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
691
+ : '';
692
+
693
+ out += defaultValue;
694
+ return out;
695
+ }
696
+
697
+ if (lowered.startsWith('decimal')) {
698
+ let params:
699
+ | { precision?: string; scale?: string; unsigned?: boolean }
700
+ | undefined;
701
+
702
+ if (lowered.length > (lowered.includes('unsigned') ? 16 : 7)) {
703
+ const [precision, scale] = lowered
704
+ .slice(8, lowered.length - (1 + (lowered.includes('unsigned') ? 9 : 0)))
705
+ .split(',');
706
+ params = { precision, scale };
707
+ }
708
+
709
+ if (lowered.includes('unsigned')) {
710
+ params = { ...(params ?? {}), unsigned: true };
711
+ }
712
+
713
+ const timeConfigParams = params ? timeConfig(params) : undefined;
714
+
715
+ let out = params
716
+ ? `${casing(name)}: decimal(${
717
+ dbColumnName({ name, casing: rawCasing, withMode: timeConfigParams !== undefined })
718
+ }${timeConfigParams})`
719
+ : `${casing(name)}: decimal(${dbColumnName({ name, casing: rawCasing })})`;
720
+
721
+ defaultValue = typeof defaultValue !== 'undefined'
722
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
723
+ : '';
724
+
725
+ out += defaultValue;
726
+ return out;
727
+ }
728
+
729
+ if (lowered.startsWith('binary')) {
730
+ const keyLength = 'binary'.length + 1;
731
+ let length = lowered.length > keyLength
732
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
733
+ : null;
734
+ length = length ? length : null;
735
+
736
+ const params = binaryConfig({ length });
737
+
738
+ let out = params
739
+ ? `${casing(name)}: binary(${dbColumnName({ name, casing: rawCasing, withMode: params !== undefined })}${params})`
740
+ : `${casing(name)}: binary(${dbColumnName({ name, casing: rawCasing })})`;
741
+
742
+ defaultValue = defaultValue
743
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
744
+ : '';
745
+
746
+ out += defaultValue;
747
+ return out;
748
+ }
749
+
750
+ if (lowered.startsWith('enum')) {
751
+ const values = lowered.substring('enum'.length + 1, lowered.length - 1);
752
+ let out = `${casing(name)}: singlestoreEnum(${
753
+ dbColumnName({ name, casing: rawCasing, withMode: true })
754
+ }[${values}])`;
755
+ out += defaultValue
756
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
757
+ : '';
758
+ return out;
759
+ }
760
+
761
+ if (lowered.startsWith('varbinary')) {
762
+ const keyLength = 'varbinary'.length + 1;
763
+ let length = lowered.length > keyLength
764
+ ? Number(lowered.substring(keyLength, lowered.length - 1))
765
+ : null;
766
+ length = length ? length : null;
767
+
768
+ const params = binaryConfig({ length });
769
+
770
+ let out = params
771
+ ? `${casing(name)}: varbinary(${
772
+ dbColumnName({ name, casing: rawCasing, withMode: params !== undefined })
773
+ }${params})`
774
+ : `${casing(name)}: varbinary(${dbColumnName({ name, casing: rawCasing })})`;
775
+
776
+ defaultValue = defaultValue
777
+ ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
778
+ : '';
779
+
780
+ out += defaultValue;
781
+ return out;
782
+ }
783
+
784
+ if (lowered.startsWith('vector')) {
785
+ const [dimensions, elementType] = lowered.substring('vector'.length + 1, lowered.length - 1).split(',');
786
+ let out = `${casing(name)}: vector(${
787
+ dbColumnName({ name, casing: rawCasing, withMode: true })
788
+ }{ dimensions: ${dimensions}, elementType: ${elementType} })`;
789
+
790
+ out += defaultValue ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
791
+ return out;
792
+ }
793
+
794
+ console.log('uknown', type);
795
+ return `// Warning: Can't parse ${type} from database\n\t// ${type}Type: ${type}("${name}")`;
796
+ };
797
+
798
+ const createTableColumns = (
799
+ columns: Column[],
800
+ casing: (val: string) => string,
801
+ rawCasing: Casing,
802
+ tableName: string,
803
+ schema: SingleStoreSchemaInternal,
804
+ ): string => {
805
+ let statement = '';
806
+
807
+ columns.forEach((it) => {
808
+ statement += '\t';
809
+ statement += column(
810
+ it.type,
811
+ it.name,
812
+ casing,
813
+ rawCasing,
814
+ it.default,
815
+ it.autoincrement,
816
+ it.onUpdate,
817
+ schema.internal?.tables![tableName]?.columns[it.name]
818
+ ?.isDefaultAnExpression ?? false,
819
+ );
820
+ statement += it.primaryKey ? '.primaryKey()' : '';
821
+ statement += it.notNull ? '.notNull()' : '';
822
+
823
+ statement += it.generated
824
+ ? `.generatedAlwaysAs(sql\`${
825
+ it.generated.as.replace(
826
+ /`/g,
827
+ '\\`',
828
+ )
829
+ }\`, { mode: "${it.generated.type}" })`
830
+ : '';
831
+
832
+ statement += ',\n';
833
+ });
834
+
835
+ return statement;
836
+ };
837
+
838
+ const createTableIndexes = (
839
+ tableName: string,
840
+ idxs: Index[],
841
+ casing: (value: string) => string,
842
+ ): string => {
843
+ let statement = '';
844
+
845
+ idxs.forEach((it) => {
846
+ let idxKey = it.name.startsWith(tableName) && it.name !== tableName
847
+ ? it.name.slice(tableName.length + 1)
848
+ : it.name;
849
+ idxKey = idxKey.endsWith('_index')
850
+ ? idxKey.slice(0, -'_index'.length) + '_idx'
851
+ : idxKey;
852
+
853
+ idxKey = casing(idxKey);
854
+
855
+ const indexGeneratedName = indexName(tableName, it.columns);
856
+ const escapedIndexName = indexGeneratedName === it.name ? '' : `"${it.name}"`;
857
+
858
+ statement += `\n\t`;
859
+ statement += it.isUnique ? 'uniqueIndex(' : 'index(';
860
+ statement += `${escapedIndexName})`;
861
+ statement += `.on(${
862
+ it.columns
863
+ .map((it) => `table.${casing(it)}`)
864
+ .join(', ')
865
+ }),`;
866
+ });
867
+
868
+ return statement;
869
+ };
870
+
871
+ const createTableUniques = (
872
+ unqs: UniqueConstraint[],
873
+ casing: (value: string) => string,
874
+ ): string => {
875
+ let statement = '';
876
+
877
+ unqs.forEach((it) => {
878
+ statement += `\n\t`;
879
+ statement += 'unique(';
880
+ statement += `"${it.name}")`;
881
+ statement += `.on(${
882
+ it.columns
883
+ .map((it) => `table.${casing(it)}`)
884
+ .join(', ')
885
+ }),`;
886
+ });
887
+
888
+ return statement;
889
+ };
890
+
891
+ const createTablePKs = (
892
+ pks: PrimaryKey[],
893
+ casing: (value: string) => string,
894
+ ): string => {
895
+ let statement = '';
896
+
897
+ pks.forEach((it) => {
898
+ let idxKey = casing(it.name);
899
+
900
+ statement += `\n\t`;
901
+ statement += 'primaryKey({ columns: [';
902
+ statement += `${
903
+ it.columns
904
+ .map((c) => {
905
+ return `table.${casing(c)}`;
906
+ })
907
+ .join(', ')
908
+ }]${it.name ? `, name: "${it.name}"` : ''}}`;
909
+ statement += '),';
910
+ });
911
+
912
+ return statement;
913
+ };