@anthonyalayo/drizzle-kit 1.0.2 → 1.0.5

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 (172) hide show
  1. package/api.d.mts +2891 -0
  2. package/api.d.ts +2891 -0
  3. package/api.js +47534 -0
  4. package/api.mjs +47521 -0
  5. package/bin.cjs +80043 -0
  6. package/{src/index.ts → index-Z-1TKnbX.d.mts} +123 -141
  7. package/index-Z-1TKnbX.d.ts +308 -0
  8. package/index.d.mts +2 -0
  9. package/index.d.ts +2 -0
  10. package/index.js +32 -0
  11. package/index.mjs +7 -0
  12. package/package.json +2 -2
  13. package/utils.js +6056 -0
  14. package/utils.mjs +6032 -0
  15. package/.gitignore +0 -25
  16. package/build.dev.ts +0 -51
  17. package/build.ts +0 -112
  18. package/imports-checker/analyze.ts +0 -78
  19. package/imports-checker/checker.ts +0 -296
  20. package/imports-checker/grammar/grammar.ohm +0 -121
  21. package/imports-checker/grammar/grammar.ohm-bundle.d.ts +0 -164
  22. package/imports-checker/grammar/grammar.ohm-bundle.js +0 -753
  23. package/imports-checker/index.ts +0 -48
  24. package/patches/difflib@0.2.4.patch +0 -31
  25. package/src/@types/utils.ts +0 -58
  26. package/src/api.ts +0 -504
  27. package/src/cli/commands/_es5.ts +0 -2
  28. package/src/cli/commands/check.ts +0 -52
  29. package/src/cli/commands/drop.ts +0 -60
  30. package/src/cli/commands/introspect.ts +0 -772
  31. package/src/cli/commands/libSqlPushUtils.ts +0 -355
  32. package/src/cli/commands/migrate.ts +0 -1526
  33. package/src/cli/commands/mysqlIntrospect.ts +0 -53
  34. package/src/cli/commands/mysqlPushUtils.ts +0 -352
  35. package/src/cli/commands/mysqlUp.ts +0 -102
  36. package/src/cli/commands/pgIntrospect.ts +0 -55
  37. package/src/cli/commands/pgPushUtils.ts +0 -269
  38. package/src/cli/commands/pgUp.ts +0 -217
  39. package/src/cli/commands/push.ts +0 -637
  40. package/src/cli/commands/singlestoreIntrospect.ts +0 -53
  41. package/src/cli/commands/singlestorePushUtils.ts +0 -456
  42. package/src/cli/commands/singlestoreUp.ts +0 -1
  43. package/src/cli/commands/sqliteIntrospect.ts +0 -96
  44. package/src/cli/commands/sqlitePushUtils.ts +0 -322
  45. package/src/cli/commands/sqliteUp.ts +0 -52
  46. package/src/cli/commands/utils.ts +0 -858
  47. package/src/cli/connections.ts +0 -914
  48. package/src/cli/index.ts +0 -48
  49. package/src/cli/schema.ts +0 -794
  50. package/src/cli/selector-ui.ts +0 -38
  51. package/src/cli/utils.ts +0 -112
  52. package/src/cli/validations/cli.ts +0 -79
  53. package/src/cli/validations/common.ts +0 -193
  54. package/src/cli/validations/libsql.ts +0 -27
  55. package/src/cli/validations/mysql.ts +0 -61
  56. package/src/cli/validations/outputs.ts +0 -91
  57. package/src/cli/validations/postgres.ts +0 -83
  58. package/src/cli/validations/singlestore.ts +0 -61
  59. package/src/cli/validations/sqlite.ts +0 -104
  60. package/src/cli/validations/studio.ts +0 -24
  61. package/src/cli/views.ts +0 -658
  62. package/src/extensions/getTablesFilterByExtensions.ts +0 -16
  63. package/src/extensions/vector.ts +0 -10
  64. package/src/global.ts +0 -61
  65. package/src/introspect-mysql.ts +0 -1030
  66. package/src/introspect-pg.ts +0 -1435
  67. package/src/introspect-singlestore.ts +0 -913
  68. package/src/introspect-sqlite.ts +0 -533
  69. package/src/jsonDiffer.js +0 -882
  70. package/src/jsonStatements.ts +0 -3590
  71. package/src/loader.mjs +0 -57
  72. package/src/migrationPreparator.ts +0 -217
  73. package/src/schemaValidator.ts +0 -23
  74. package/src/serializer/index.ts +0 -142
  75. package/src/serializer/mysqlImports.ts +0 -38
  76. package/src/serializer/mysqlSchema.ts +0 -423
  77. package/src/serializer/mysqlSerializer.ts +0 -999
  78. package/src/serializer/pgImports.ts +0 -106
  79. package/src/serializer/pgSchema.ts +0 -937
  80. package/src/serializer/pgSerializer.ts +0 -2223
  81. package/src/serializer/singlestoreImports.ts +0 -38
  82. package/src/serializer/singlestoreSchema.ts +0 -257
  83. package/src/serializer/singlestoreSerializer.ts +0 -767
  84. package/src/serializer/sqliteImports.ts +0 -41
  85. package/src/serializer/sqliteSchema.ts +0 -352
  86. package/src/serializer/sqliteSerializer.ts +0 -931
  87. package/src/serializer/studio.ts +0 -694
  88. package/src/serializer/utils.ts +0 -45
  89. package/src/simulator.ts +0 -157
  90. package/src/snapshotsDiffer.ts +0 -4398
  91. package/src/sqlgenerator.ts +0 -4212
  92. package/src/statementCombiner.ts +0 -597
  93. package/src/utils/certs.ts +0 -44
  94. package/src/utils/words.ts +0 -1333
  95. package/src/utils.ts +0 -370
  96. package/tests/bin.test.ts +0 -58
  97. package/tests/cli/d1http.config.ts +0 -12
  98. package/tests/cli/drizzle.config.ts +0 -9
  99. package/tests/cli/durable-sqlite.config.ts +0 -7
  100. package/tests/cli/expo.config.ts +0 -7
  101. package/tests/cli/postgres.config.ts +0 -13
  102. package/tests/cli/postgres2.config.ts +0 -17
  103. package/tests/cli/schema.ts +0 -1
  104. package/tests/cli/turso.config.ts +0 -10
  105. package/tests/cli-export.test.ts +0 -79
  106. package/tests/cli-generate.test.ts +0 -259
  107. package/tests/cli-migrate.test.ts +0 -103
  108. package/tests/cli-push.test.ts +0 -126
  109. package/tests/common.ts +0 -15
  110. package/tests/indexes/common.ts +0 -21
  111. package/tests/indexes/pg.test.ts +0 -245
  112. package/tests/introspect/libsql.test.ts +0 -35
  113. package/tests/introspect/mysql.test.ts +0 -319
  114. package/tests/introspect/pg.test.ts +0 -894
  115. package/tests/introspect/singlestore.test.ts +0 -275
  116. package/tests/introspect/sqlite.test.ts +0 -122
  117. package/tests/libsql-checks.test.ts +0 -308
  118. package/tests/libsql-statements.test.ts +0 -989
  119. package/tests/libsql-views.test.ts +0 -218
  120. package/tests/migrate/libsq-schema.ts +0 -6
  121. package/tests/migrate/libsql-migrate.test.ts +0 -58
  122. package/tests/migrate/migrations/0000_little_blizzard.sql +0 -4
  123. package/tests/migrate/migrations/0001_nebulous_storm.sql +0 -10
  124. package/tests/migrate/migrations/meta/0000_snapshot.json +0 -40
  125. package/tests/migrate/migrations/meta/0001_snapshot.json +0 -40
  126. package/tests/migrate/migrations/meta/_journal.json +0 -20
  127. package/tests/mysql-checks.test.ts +0 -291
  128. package/tests/mysql-generated.test.ts +0 -1290
  129. package/tests/mysql-schemas.test.ts +0 -156
  130. package/tests/mysql-views.test.ts +0 -553
  131. package/tests/mysql.test.ts +0 -863
  132. package/tests/pg-array.test.ts +0 -368
  133. package/tests/pg-checks.test.ts +0 -329
  134. package/tests/pg-columns.test.ts +0 -484
  135. package/tests/pg-domains.test.ts +0 -306
  136. package/tests/pg-enums.test.ts +0 -751
  137. package/tests/pg-generated.test.ts +0 -529
  138. package/tests/pg-identity.test.ts +0 -447
  139. package/tests/pg-schemas.test.ts +0 -105
  140. package/tests/pg-sequences.test.ts +0 -298
  141. package/tests/pg-tables.test.ts +0 -1021
  142. package/tests/pg-views.test.ts +0 -1929
  143. package/tests/push/common.ts +0 -58
  144. package/tests/push/libsql.test.ts +0 -1400
  145. package/tests/push/mysql-push.test.ts +0 -345
  146. package/tests/push/mysql.test.ts +0 -788
  147. package/tests/push/pg.test.ts +0 -4341
  148. package/tests/push/singlestore-push.test.ts +0 -894
  149. package/tests/push/singlestore.test.ts +0 -444
  150. package/tests/push/sqlite.test.ts +0 -1613
  151. package/tests/rls/pg-policy.test.ts +0 -1656
  152. package/tests/rls/pg-role.test.ts +0 -234
  153. package/tests/schemaDiffer.ts +0 -2852
  154. package/tests/singlestore-generated.test.ts +0 -1290
  155. package/tests/singlestore-schemas.test.ts +0 -155
  156. package/tests/singlestore.test.ts +0 -978
  157. package/tests/sqlite-checks.test.ts +0 -308
  158. package/tests/sqlite-columns.test.ts +0 -1049
  159. package/tests/sqlite-generated.test.ts +0 -1726
  160. package/tests/sqlite-tables.test.ts +0 -637
  161. package/tests/sqlite-views.test.ts +0 -218
  162. package/tests/statements-combiner/libsql-statements-combiner.test.ts +0 -1812
  163. package/tests/statements-combiner/singlestore-statements-combiner.test.ts +0 -882
  164. package/tests/statements-combiner/sqlite-statements-combiner.test.ts +0 -1211
  165. package/tests/test/sqlite.test.ts +0 -39
  166. package/tests/testsinglestore.ts +0 -29
  167. package/tests/validations.test.ts +0 -869
  168. package/tests/wrap-param.test.ts +0 -16
  169. package/tsconfig.build.json +0 -4
  170. package/tsconfig.cli-types.json +0 -9
  171. package/tsconfig.json +0 -28
  172. package/vitest.config.ts +0 -34
@@ -1,1435 +0,0 @@
1
- import { getTableName, is } from 'drizzle-orm';
2
- import { AnyPgTable } from 'drizzle-orm/pg-core';
3
- import {
4
- createTableRelationsHelpers,
5
- extractTablesRelationalConfig,
6
- Many,
7
- One,
8
- Relation,
9
- Relations,
10
- } from 'drizzle-orm/relations';
11
- import './@types/utils';
12
- import { toCamelCase } from 'drizzle-orm/casing';
13
- import { Casing } from './cli/validations/common';
14
- import { assertUnreachable } from './global';
15
- import {
16
- CheckConstraint,
17
- Column,
18
- ForeignKey,
19
- Index,
20
- PgKitInternals,
21
- PgSchemaInternal,
22
- Policy,
23
- PrimaryKey,
24
- UniqueConstraint,
25
- } from './serializer/pgSchema';
26
- import { indexName } from './serializer/pgSerializer';
27
- import { unescapeSingleQuotes } from './utils';
28
-
29
- const pgImportsList = new Set([
30
- 'pgTable',
31
- 'pgEnum',
32
- 'smallint',
33
- 'integer',
34
- 'bigint',
35
- 'boolean',
36
- 'text',
37
- 'varchar',
38
- 'char',
39
- 'serial',
40
- 'smallserial',
41
- 'bigserial',
42
- 'decimal',
43
- 'numeric',
44
- 'real',
45
- 'json',
46
- 'jsonb',
47
- 'time',
48
- 'timestamp',
49
- 'date',
50
- 'interval',
51
- 'cidr',
52
- 'inet',
53
- 'macaddr',
54
- 'macaddr8',
55
- 'bigint',
56
- 'doublePrecision',
57
- 'uuid',
58
- 'vector',
59
- 'point',
60
- 'line',
61
- 'geometry',
62
- ]);
63
-
64
- const objToStatement2 = (json: { [s: string]: unknown }) => {
65
- json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
66
-
67
- const keys = Object.keys(json);
68
- if (keys.length === 0) return;
69
-
70
- let statement = '{ ';
71
- statement += keys.map((it) => `${it}: "${json[it]}"`).join(', '); // no "" for keys
72
- statement += ' }';
73
- return statement;
74
- };
75
-
76
- const timeConfig = (json: { [s: string]: unknown }) => {
77
- json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
78
-
79
- const keys = Object.keys(json);
80
- if (keys.length === 0) return;
81
-
82
- let statement = '{ ';
83
- statement += keys.map((it) => `${it}: ${json[it]}`).join(', ');
84
- statement += ' }';
85
- return statement;
86
- };
87
-
88
- const possibleIntervals = [
89
- 'year',
90
- 'month',
91
- 'day',
92
- 'hour',
93
- 'minute',
94
- 'second',
95
- 'year to month',
96
- 'day to hour',
97
- 'day to minute',
98
- 'day to second',
99
- 'hour to minute',
100
- 'hour to second',
101
- 'minute to second',
102
- ];
103
-
104
- const intervalStrToObj = (str: string) => {
105
- if (str.startsWith('interval(')) {
106
- return {
107
- precision: Number(str.substring('interval('.length, str.length - 1)),
108
- };
109
- }
110
- const splitted = str.split(' ');
111
- if (splitted.length === 1) {
112
- return {};
113
- }
114
- const rest = splitted.slice(1, splitted.length).join(' ');
115
- if (possibleIntervals.includes(rest)) {
116
- return { fields: `"${rest}"` };
117
- }
118
-
119
- for (const s of possibleIntervals) {
120
- if (rest.startsWith(`${s}(`)) {
121
- return {
122
- fields: `"${s}"`,
123
- precision: Number(rest.substring(s.length + 1, rest.length - 1)),
124
- };
125
- }
126
- }
127
- return {};
128
- };
129
-
130
- const intervalConfig = (str: string) => {
131
- const json = intervalStrToObj(str);
132
- // json = Object.fromEntries(Object.entries(json).filter((it) => it[1]));
133
-
134
- const keys = Object.keys(json);
135
- if (keys.length === 0) return;
136
-
137
- let statement = '{ ';
138
- statement += keys.map((it: keyof typeof json) => `${it}: ${json[it]}`).join(', ');
139
- statement += ' }';
140
- return statement;
141
- };
142
-
143
- const mapColumnDefault = (defaultValue: any, isExpression?: boolean) => {
144
- if (isExpression) {
145
- return `sql\`${defaultValue}\``;
146
- }
147
-
148
- return defaultValue;
149
- };
150
-
151
- const importsPatch = {
152
- 'double precision': 'doublePrecision',
153
- 'timestamp without time zone': 'timestamp',
154
- 'timestamp with time zone': 'timestamp',
155
- 'time without time zone': 'time',
156
- 'time with time zone': 'time',
157
- } as Record<string, string>;
158
-
159
- const relations = new Set<string>();
160
-
161
- const escapeColumnKey = (value: string) => {
162
- if (/^(?![a-zA-Z_$][a-zA-Z0-9_$]*$).+$/.test(value)) {
163
- return `"${value}"`;
164
- }
165
- return value;
166
- };
167
-
168
- const withCasing = (value: string, casing: Casing) => {
169
- if (casing === 'preserve') {
170
- return escapeColumnKey(value);
171
- }
172
- if (casing === 'camel') {
173
- return escapeColumnKey(value.camelCase());
174
- }
175
-
176
- assertUnreachable(casing);
177
- };
178
-
179
- const dbColumnName = ({ name, casing, withMode = false }: { name: string; casing: Casing; withMode?: boolean }) => {
180
- if (casing === 'preserve') {
181
- return '';
182
- }
183
- if (casing === 'camel') {
184
- return toCamelCase(name) === name ? '' : withMode ? `"${name}", ` : `"${name}"`;
185
- }
186
-
187
- assertUnreachable(casing);
188
- };
189
-
190
- export const relationsToTypeScriptForStudio = (
191
- schema: Record<string, Record<string, AnyPgTable<{}>>>,
192
- relations: Record<string, Relations<string, Record<string, Relation<string>>>>,
193
- ) => {
194
- const relationalSchema: Record<string, unknown> = {
195
- ...Object.fromEntries(
196
- Object.entries(schema)
197
- .map(([key, val]) => {
198
- // have unique keys across schemas
199
- const mappedTableEntries = Object.entries(val).map((tableEntry) => {
200
- return [`__${key}__.${tableEntry[0]}`, tableEntry[1]];
201
- });
202
-
203
- return mappedTableEntries;
204
- })
205
- .flat(),
206
- ),
207
- ...relations,
208
- };
209
-
210
- const relationsConfig = extractTablesRelationalConfig(relationalSchema, createTableRelationsHelpers);
211
-
212
- let result = '';
213
-
214
- function findColumnKey(table: AnyPgTable, columnName: string) {
215
- for (const tableEntry of Object.entries(table)) {
216
- const key = tableEntry[0];
217
- const value = tableEntry[1];
218
-
219
- if (value.name === columnName) {
220
- return key;
221
- }
222
- }
223
- }
224
-
225
- Object.values(relationsConfig.tables).forEach((table) => {
226
- const tableName = table.tsName.split('.')[1];
227
- const relations = table.relations;
228
- let hasRelations = false;
229
- let relationsObjAsStr = '';
230
- let hasOne = false;
231
- let hasMany = false;
232
-
233
- Object.values(relations).forEach((relation) => {
234
- hasRelations = true;
235
-
236
- if (is(relation, Many)) {
237
- hasMany = true;
238
- relationsObjAsStr += `\t\t${relation.fieldName}: many(${
239
- relationsConfig.tableNamesMap[relation.referencedTableName].split('.')[1]
240
- }${typeof relation.relationName !== 'undefined' ? `, { relationName: "${relation.relationName}"}` : ''}),`;
241
- }
242
-
243
- if (is(relation, One)) {
244
- hasOne = true;
245
- relationsObjAsStr += `\t\t${relation.fieldName}: one(${
246
- relationsConfig.tableNamesMap[relation.referencedTableName].split('.')[1]
247
- }, { fields: [${
248
- relation.config?.fields.map(
249
- (c) =>
250
- `${relationsConfig.tableNamesMap[getTableName(relation.sourceTable)].split('.')[1]}.${
251
- findColumnKey(relation.sourceTable, c.name)
252
- }`,
253
- )
254
- }], references: [${
255
- relation.config?.references.map(
256
- (c) =>
257
- `${relationsConfig.tableNamesMap[getTableName(relation.referencedTable)].split('.')[1]}.${
258
- findColumnKey(relation.referencedTable, c.name)
259
- }`,
260
- )
261
- }]${typeof relation.relationName !== 'undefined' ? `, relationName: "${relation.relationName}"` : ''}}),`;
262
- }
263
- });
264
-
265
- if (hasRelations) {
266
- result += `export const ${tableName}Relation = relations(${tableName}, ({${hasOne ? 'one' : ''}${
267
- hasOne && hasMany ? ', ' : ''
268
- }${hasMany ? 'many' : ''}}) => ({
269
- ${relationsObjAsStr}
270
- }));\n`;
271
- }
272
- });
273
-
274
- return result;
275
- };
276
-
277
- function generateIdentityParams(identity: Column['identity']) {
278
- let paramsObj = `{ name: "${identity!.name}"`;
279
- if (identity?.startWith) {
280
- paramsObj += `, startWith: ${identity.startWith}`;
281
- }
282
- if (identity?.increment) {
283
- paramsObj += `, increment: ${identity.increment}`;
284
- }
285
- if (identity?.minValue) {
286
- paramsObj += `, minValue: ${identity.minValue}`;
287
- }
288
- if (identity?.maxValue) {
289
- paramsObj += `, maxValue: ${identity.maxValue}`;
290
- }
291
- if (identity?.cache) {
292
- paramsObj += `, cache: ${identity.cache}`;
293
- }
294
- if (identity?.cycle) {
295
- paramsObj += `, cycle: true`;
296
- }
297
- paramsObj += ' }';
298
- if (identity?.type === 'always') {
299
- return `.generatedAlwaysAsIdentity(${paramsObj})`;
300
- }
301
- return `.generatedByDefaultAsIdentity(${paramsObj})`;
302
- }
303
-
304
- export const paramNameFor = (name: string, schema?: string) => {
305
- const schemaSuffix = schema && schema !== 'public' ? `In${schema.capitalise()}` : '';
306
- return `${name}${schemaSuffix}`;
307
- };
308
-
309
- export const schemaToTypeScript = (schema: PgSchemaInternal, casing: Casing) => {
310
- // collectFKs
311
- Object.values(schema.tables).forEach((table) => {
312
- Object.values(table.foreignKeys).forEach((fk) => {
313
- const relation = `${fk.tableFrom}-${fk.tableTo}`;
314
- relations.add(relation);
315
- });
316
- });
317
-
318
- const schemas = Object.fromEntries(
319
- Object.entries(schema.schemas).map((it) => {
320
- return [it[0], withCasing(it[1], casing)];
321
- }),
322
- );
323
-
324
- const domainTypes = Object.values(schema.domains).reduce((acc, cur) => {
325
- acc.add(`${cur.schema}.${cur.name}`);
326
- return acc;
327
- }, new Set<string>());
328
-
329
- const enumTypes = Object.values(schema.enums).reduce((acc, cur) => {
330
- acc.add(`${cur.schema}.${cur.name}`);
331
- return acc;
332
- }, new Set<string>());
333
-
334
- const imports = Object.values(schema.tables).reduce(
335
- (res, it) => {
336
- const idxImports = Object.values(it.indexes).map((idx) => (idx.isUnique ? 'uniqueIndex' : 'index'));
337
- const fkImpots = Object.values(it.foreignKeys).map((it) => 'foreignKey');
338
- if (Object.values(it.foreignKeys).some((it) => isCyclic(it) && !isSelf(it))) {
339
- res.pg.push('type AnyPgColumn');
340
- }
341
- const pkImports = Object.values(it.compositePrimaryKeys).map((it) => 'primaryKey');
342
- const uniqueImports = Object.values(it.uniqueConstraints).map((it) => 'unique');
343
-
344
- const checkImports = Object.values(it.checkConstraints).map(
345
- (it) => 'check',
346
- );
347
-
348
- const policiesImports = Object.values(it.policies).map(
349
- (it) => 'pgPolicy',
350
- );
351
-
352
- if (it.schema && it.schema !== 'public' && it.schema !== '') {
353
- res.pg.push('pgSchema');
354
- }
355
-
356
- res.pg.push(...idxImports);
357
- res.pg.push(...fkImpots);
358
- res.pg.push(...pkImports);
359
- res.pg.push(...uniqueImports);
360
- res.pg.push(...policiesImports);
361
- res.pg.push(...checkImports);
362
-
363
- const columnImports = Object.values(it.columns)
364
- .map((col) => {
365
- let patched: string = (importsPatch[col.type] || col.type).replace('[]', '');
366
- patched = patched === 'double precision' ? 'doublePrecision' : patched;
367
- patched = patched.startsWith('varchar(') ? 'varchar' : patched;
368
- patched = patched.startsWith('char(') ? 'char' : patched;
369
- patched = patched.startsWith('numeric(') ? 'numeric' : patched;
370
- patched = patched.startsWith('time(') ? 'time' : patched;
371
- patched = patched.startsWith('timestamp(') ? 'timestamp' : patched;
372
- patched = patched.startsWith('vector(') ? 'vector' : patched;
373
- patched = patched.startsWith('geometry(') ? 'geometry' : patched;
374
- return patched;
375
- })
376
- .filter((type) => {
377
- return pgImportsList.has(type);
378
- });
379
-
380
- res.pg.push(...columnImports);
381
- return res;
382
- },
383
- { pg: [] as string[] },
384
- );
385
-
386
- Object.values(schema.views).forEach((it) => {
387
- if (it.schema && it.schema !== 'public' && it.schema !== '') {
388
- imports.pg.push('pgSchema');
389
- } else if (it.schema === 'public') {
390
- it.materialized ? imports.pg.push('pgMaterializedView') : imports.pg.push('pgView');
391
- }
392
-
393
- Object.values(it.columns).forEach(() => {
394
- const columnImports = Object.values(it.columns)
395
- .map((col) => {
396
- let patched: string = (importsPatch[col.type] || col.type).replace('[]', '');
397
- patched = patched === 'double precision' ? 'doublePrecision' : patched;
398
- patched = patched.startsWith('varchar(') ? 'varchar' : patched;
399
- patched = patched.startsWith('char(') ? 'char' : patched;
400
- patched = patched.startsWith('numeric(') ? 'numeric' : patched;
401
- patched = patched.startsWith('time(') ? 'time' : patched;
402
- patched = patched.startsWith('timestamp(') ? 'timestamp' : patched;
403
- patched = patched.startsWith('vector(') ? 'vector' : patched;
404
- patched = patched.startsWith('geometry(') ? 'geometry' : patched;
405
- return patched;
406
- })
407
- .filter((type) => {
408
- return pgImportsList.has(type);
409
- });
410
-
411
- imports.pg.push(...columnImports);
412
- });
413
- });
414
-
415
- Object.values(schema.sequences).forEach((it) => {
416
- if (it.schema && it.schema !== 'public' && it.schema !== '') {
417
- imports.pg.push('pgSchema');
418
- } else if (it.schema === 'public') {
419
- imports.pg.push('pgSequence');
420
- }
421
- });
422
-
423
- Object.values(schema.domains).forEach((it) => {
424
- if (it.schema && it.schema !== 'public' && it.schema !== '') {
425
- imports.pg.push('pgSchema');
426
- } else if (it.schema === 'public') {
427
- imports.pg.push('pgDomain');
428
- }
429
- });
430
-
431
- Object.values(schema.enums).forEach((it) => {
432
- if (it.schema && it.schema !== 'public' && it.schema !== '') {
433
- imports.pg.push('pgSchema');
434
- } else if (it.schema === 'public') {
435
- imports.pg.push('pgEnum');
436
- }
437
- });
438
-
439
- if (Object.keys(schema.roles).length > 0) {
440
- imports.pg.push('pgRole');
441
- }
442
-
443
- const domainStatements = Object.values(schema.domains)
444
- .map((it) => {
445
- const domainSchema = schemas[it.schema];
446
- const paramName = paramNameFor(it.name, domainSchema);
447
- const func = domainSchema ? `${domainSchema}.domain` : 'pgDomain';
448
-
449
- // TODO handle all logic by porting from column() function below
450
- let type = it.baseType;
451
- if (type.startsWith('varchar(') && type.length > 7) {
452
- type = `varchar({ length: ${type.substring(8, type.length - 1)}})`;
453
- } else {
454
- type += '()';
455
- }
456
-
457
- // Start with base type function
458
- let domainChain = `${func}("${it.name}", ${type}`;
459
-
460
- // Apply chained methods based on properties
461
- if (it.notNull) {
462
- domainChain += '.notNull()';
463
- }
464
- if (it.defaultValue) {
465
- domainChain += `.default(${it.defaultValue})`;
466
- }
467
- if (it.checkConstraints && Object.keys(it.checkConstraints).length > 0) {
468
- const checkStmts = Object.entries(it.checkConstraints)
469
- .map(([, check]) => {
470
- return `\n\t.checkConstraint('${check.name}', sql\`${check.value}\`)`;
471
- }).join('');
472
- domainChain += checkStmts;
473
- }
474
-
475
- // Close function chain
476
- domainChain += ')';
477
-
478
- return `export const ${withCasing(paramName, casing)} = ${domainChain};\n`;
479
- })
480
- .join('\n')
481
- .concat('\n');
482
-
483
- const enumStatements = Object.values(schema.enums)
484
- .map((it) => {
485
- const enumSchema = schemas[it.schema];
486
- // const func = schema || schema === "public" ? "pgTable" : schema;
487
- const paramName = paramNameFor(it.name, enumSchema);
488
-
489
- const func = enumSchema ? `${enumSchema}.enum` : 'pgEnum';
490
-
491
- const values = Object.values(it.values)
492
- .map((it) => `'${unescapeSingleQuotes(it, false)}'`)
493
- .join(', ');
494
- return `export const ${withCasing(paramName, casing)} = ${func}("${it.name}", [${values}])\n`;
495
- })
496
- .join('')
497
- .concat('\n');
498
-
499
- const sequencesStatements = Object.values(schema.sequences)
500
- .map((it) => {
501
- const seqSchema = schemas[it.schema];
502
- const paramName = paramNameFor(it.name, seqSchema);
503
-
504
- const func = seqSchema ? `${seqSchema}.sequence` : 'pgSequence';
505
-
506
- let params = '';
507
-
508
- if (it.startWith) {
509
- params += `, startWith: "${it.startWith}"`;
510
- }
511
- if (it.increment) {
512
- params += `, increment: "${it.increment}"`;
513
- }
514
- if (it.minValue) {
515
- params += `, minValue: "${it.minValue}"`;
516
- }
517
- if (it.maxValue) {
518
- params += `, maxValue: "${it.maxValue}"`;
519
- }
520
- if (it.cache) {
521
- params += `, cache: "${it.cache}"`;
522
- }
523
- if (it.cycle) {
524
- params += `, cycle: true`;
525
- } else {
526
- params += `, cycle: false`;
527
- }
528
-
529
- return `export const ${withCasing(paramName, casing)} = ${func}("${it.name}"${
530
- params ? `, { ${params.trimChar(',')} }` : ''
531
- })\n`;
532
- })
533
- .join('')
534
- .concat('');
535
-
536
- const schemaStatements = Object.entries(schemas)
537
- // .filter((it) => it[0] !== "public")
538
- .map((it) => {
539
- return `export const ${it[1]} = pgSchema("${it[0]}");\n`;
540
- })
541
- .join('');
542
-
543
- const rolesNameToTsKey: Record<string, string> = {};
544
-
545
- const rolesStatements = Object.entries(schema.roles)
546
- .map((it) => {
547
- const fields = it[1];
548
- rolesNameToTsKey[fields.name] = it[0];
549
- return `export const ${withCasing(it[0], casing)} = pgRole("${fields.name}", ${
550
- !fields.createDb && !fields.createRole && fields.inherit
551
- ? ''
552
- : `${
553
- `, { ${fields.createDb ? `createDb: true,` : ''}${fields.createRole ? ` createRole: true,` : ''}${
554
- !fields.inherit ? ` inherit: false ` : ''
555
- }`.trimChar(',')
556
- }}`
557
- } );\n`;
558
- })
559
- .join('');
560
-
561
- const tableStatements = Object.values(schema.tables).map((table) => {
562
- const tableSchema = schemas[table.schema];
563
- const paramName = paramNameFor(table.name, tableSchema);
564
-
565
- const func = tableSchema ? `${tableSchema}.table` : 'pgTable';
566
- let statement = `export const ${withCasing(paramName, casing)} = ${func}("${table.name}", {\n`;
567
- statement += createTableColumns(
568
- table.name,
569
- Object.values(table.columns),
570
- Object.values(table.foreignKeys),
571
- domainTypes,
572
- enumTypes,
573
- schemas,
574
- casing,
575
- schema.internal,
576
- );
577
- statement += '}';
578
-
579
- // more than 2 fields or self reference or cyclic
580
- // Andrii: I switched this one off until we will get custom names in .references()
581
- // const filteredFKs = Object.values(table.foreignKeys).filter((it) => {
582
- // return it.columnsFrom.length > 1 || isSelf(it);
583
- // });
584
-
585
- if (
586
- Object.keys(table.indexes).length > 0
587
- || Object.values(table.foreignKeys).length > 0
588
- || Object.values(table.policies).length > 0
589
- || Object.keys(table.compositePrimaryKeys).length > 0
590
- || Object.keys(table.uniqueConstraints).length > 0
591
- || Object.keys(table.checkConstraints).length > 0
592
- ) {
593
- statement += ', ';
594
- statement += '(table) => [';
595
- statement += createTableIndexes(table.name, Object.values(table.indexes), casing);
596
- statement += createTableFKs(Object.values(table.foreignKeys), schemas, casing);
597
- statement += createTablePKs(
598
- Object.values(table.compositePrimaryKeys),
599
- casing,
600
- );
601
- statement += createTableUniques(
602
- Object.values(table.uniqueConstraints),
603
- casing,
604
- );
605
- statement += createTablePolicies(
606
- Object.values(table.policies),
607
- casing,
608
- rolesNameToTsKey,
609
- );
610
- statement += createTableChecks(
611
- Object.values(table.checkConstraints),
612
- casing,
613
- );
614
- statement += '\n]';
615
- }
616
-
617
- statement += ');';
618
- return statement;
619
- });
620
-
621
- const viewsStatements = Object.values(schema.views)
622
- .map((it) => {
623
- const viewSchema = schemas[it.schema];
624
-
625
- const paramName = paramNameFor(it.name, viewSchema);
626
-
627
- const func = viewSchema
628
- ? (it.materialized ? `${viewSchema}.materializedView` : `${viewSchema}.view`)
629
- : it.materialized
630
- ? 'pgMaterializedView'
631
- : 'pgView';
632
-
633
- const withOption = it.with ?? '';
634
-
635
- const as = `sql\`${it.definition}\``;
636
-
637
- const tablespace = it.tablespace ?? '';
638
-
639
- const columns = createTableColumns(
640
- '',
641
- Object.values(it.columns),
642
- [],
643
- domainTypes,
644
- enumTypes,
645
- schemas,
646
- casing,
647
- schema.internal,
648
- );
649
-
650
- let statement = `export const ${withCasing(paramName, casing)} = ${func}("${it.name}", {${columns}})`;
651
- statement += tablespace ? `.tablespace("${tablespace}")` : '';
652
- statement += withOption ? `.with(${JSON.stringify(withOption)})` : '';
653
- statement += `.as(${as});`;
654
-
655
- return statement;
656
- })
657
- .join('\n\n');
658
-
659
- const uniquePgImports = ['pgTable', ...new Set(imports.pg)];
660
-
661
- const importsTs = `import { ${
662
- uniquePgImports.join(
663
- ', ',
664
- )
665
- } } from "drizzle-orm/pg-core"
666
- import { sql } from "drizzle-orm"\n\n`;
667
-
668
- let decalrations = schemaStatements;
669
- decalrations += rolesStatements;
670
- decalrations += domainStatements;
671
- decalrations += enumStatements;
672
- decalrations += sequencesStatements;
673
- decalrations += '\n';
674
- decalrations += tableStatements.join('\n\n');
675
- decalrations += '\n';
676
- decalrations += viewsStatements;
677
-
678
- const file = importsTs + decalrations;
679
-
680
- // for drizzle studio query runner
681
- const schemaEntry = `
682
- {
683
- ${
684
- Object.values(schema.tables)
685
- .map((it) => withCasing(it.name, casing))
686
- .join(',\n')
687
- }
688
- }
689
- `;
690
-
691
- return { file, imports: importsTs, decalrations, schemaEntry };
692
- };
693
-
694
- const isCyclic = (fk: ForeignKey) => {
695
- const key = `${fk.tableFrom}-${fk.tableTo}`;
696
- const reverse = `${fk.tableTo}-${fk.tableFrom}`;
697
- return relations.has(key) && relations.has(reverse);
698
- };
699
-
700
- const isSelf = (fk: ForeignKey) => {
701
- return fk.tableFrom === fk.tableTo;
702
- };
703
-
704
- const buildArrayDefault = (defaultValue: string, typeName: string): string => {
705
- if (typeof defaultValue === 'string' && !(defaultValue.startsWith('{') || defaultValue.startsWith("'{"))) {
706
- return `sql\`${defaultValue}\``;
707
- }
708
- defaultValue = defaultValue.substring(2, defaultValue.length - 2);
709
- return `[${
710
- defaultValue
711
- .split(/\s*,\s*/g)
712
- .map((value) => {
713
- // if (['integer', 'smallint', 'bigint', 'double precision', 'real'].includes(typeName)) {
714
- // return value;
715
- // } else if (typeName === 'interval') {
716
- // return value.replaceAll('"', "'");
717
- // } else if (typeName === 'boolean') {
718
- // return value === 't' ? 'true' : 'false';
719
- if (typeName === 'json' || typeName === 'jsonb') {
720
- return value.substring(1, value.length - 1).replaceAll('\\', '');
721
- }
722
- return value;
723
- // }
724
- })
725
- .join(', ')
726
- }]`;
727
- };
728
-
729
- const mapDefault = (
730
- tableName: string,
731
- type: string,
732
- name: string,
733
- enumTypes: Set<string>,
734
- typeSchema: string,
735
- defaultValue?: any,
736
- internals?: PgKitInternals,
737
- ) => {
738
- const isExpression = internals?.tables[tableName]?.columns[name]?.isDefaultAnExpression ?? false;
739
- const isArray = internals?.tables[tableName]?.columns[name]?.isArray ?? false;
740
- const lowered = type.toLowerCase().replace('[]', '');
741
-
742
- if (isArray) {
743
- return typeof defaultValue !== 'undefined' ? `.default(${buildArrayDefault(defaultValue, lowered)})` : '';
744
- }
745
-
746
- if (enumTypes.has(`${typeSchema}.${type.replace('[]', '')}`)) {
747
- return typeof defaultValue !== 'undefined'
748
- ? `.default(${mapColumnDefault(unescapeSingleQuotes(defaultValue, true), isExpression)})`
749
- : '';
750
- }
751
-
752
- if (lowered.startsWith('integer')) {
753
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
754
- }
755
-
756
- if (lowered.startsWith('smallint')) {
757
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
758
- }
759
-
760
- if (lowered.startsWith('bigint')) {
761
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
762
- }
763
-
764
- if (lowered.startsWith('boolean')) {
765
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
766
- }
767
-
768
- if (lowered.startsWith('double precision')) {
769
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
770
- }
771
-
772
- if (lowered.startsWith('real')) {
773
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
774
- }
775
-
776
- if (lowered.startsWith('uuid')) {
777
- return defaultValue === 'gen_random_uuid()'
778
- ? '.defaultRandom()'
779
- : defaultValue
780
- ? `.default(sql\`${defaultValue}\`)`
781
- : '';
782
- }
783
-
784
- if (lowered.startsWith('numeric')) {
785
- defaultValue = defaultValue
786
- ? (defaultValue.startsWith(`'`) && defaultValue.endsWith(`'`)
787
- ? defaultValue.substring(1, defaultValue.length - 1)
788
- : defaultValue)
789
- : undefined;
790
- return defaultValue ? `.default('${mapColumnDefault(defaultValue, isExpression)}')` : '';
791
- }
792
-
793
- if (lowered.startsWith('timestamp')) {
794
- return defaultValue === 'now()'
795
- ? '.defaultNow()'
796
- : /^'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?([+-]\d{2}(:\d{2})?)?'$/.test(defaultValue) // Matches 'YYYY-MM-DD HH:MI:SS', 'YYYY-MM-DD HH:MI:SS.FFFFFF', 'YYYY-MM-DD HH:MI:SS+TZ', 'YYYY-MM-DD HH:MI:SS.FFFFFF+TZ' and 'YYYY-MM-DD HH:MI:SS+HH:MI'
797
- ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
798
- : defaultValue
799
- ? `.default(sql\`${defaultValue}\`)`
800
- : '';
801
- }
802
-
803
- if (lowered.startsWith('time')) {
804
- return defaultValue === 'now()'
805
- ? '.defaultNow()'
806
- : /^'\d{2}:\d{2}(:\d{2})?(\.\d+)?'$/.test(defaultValue) // Matches 'HH:MI', 'HH:MI:SS' and 'HH:MI:SS.FFFFFF'
807
- ? `.default(${mapColumnDefault(defaultValue, isExpression)})`
808
- : defaultValue
809
- ? `.default(sql\`${defaultValue}\`)`
810
- : '';
811
- }
812
-
813
- if (lowered.startsWith('interval')) {
814
- return defaultValue ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
815
- }
816
-
817
- if (lowered === 'date') {
818
- return defaultValue === 'now()'
819
- ? '.defaultNow()'
820
- : /^'\d{4}-\d{2}-\d{2}'$/.test(defaultValue) // Matches 'YYYY-MM-DD'
821
- ? `.default(${defaultValue})`
822
- : defaultValue
823
- ? `.default(sql\`${defaultValue}\`)`
824
- : '';
825
- }
826
-
827
- if (lowered.startsWith('text')) {
828
- return typeof defaultValue !== 'undefined'
829
- ? `.default(${mapColumnDefault(unescapeSingleQuotes(defaultValue, true), isExpression)})`
830
- : '';
831
- }
832
-
833
- if (lowered.startsWith('jsonb')) {
834
- const def = typeof defaultValue !== 'undefined'
835
- ? defaultValue.replace(/::(.*?)(?<![^\w"])(?=$)/, '').slice(1, -1)
836
- : null;
837
-
838
- return defaultValue ? `.default(${def})` : '';
839
- }
840
-
841
- if (lowered.startsWith('json')) {
842
- const def = defaultValue ? defaultValue.replace(/::(.*?)(?<![^\w"])(?=$)/, '').slice(1, -1) : null;
843
-
844
- return typeof defaultValue !== 'undefined' ? `.default(${def})` : '';
845
- }
846
-
847
- if (lowered.startsWith('inet')) {
848
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
849
- }
850
-
851
- if (lowered.startsWith('cidr')) {
852
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
853
- }
854
-
855
- if (lowered.startsWith('macaddr8')) {
856
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
857
- }
858
-
859
- if (lowered.startsWith('macaddr')) {
860
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
861
- }
862
-
863
- if (lowered.startsWith('varchar')) {
864
- return typeof defaultValue !== 'undefined'
865
- ? `.default(${mapColumnDefault(unescapeSingleQuotes(defaultValue, true), isExpression)})`
866
- : '';
867
- }
868
-
869
- if (lowered.startsWith('point')) {
870
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
871
- }
872
-
873
- if (lowered.startsWith('line')) {
874
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
875
- }
876
-
877
- if (lowered.startsWith('geometry')) {
878
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
879
- }
880
-
881
- if (lowered.startsWith('vector')) {
882
- return typeof defaultValue !== 'undefined' ? `.default(${mapColumnDefault(defaultValue, isExpression)})` : '';
883
- }
884
-
885
- if (lowered.startsWith('char')) {
886
- return typeof defaultValue !== 'undefined'
887
- ? `.default(${mapColumnDefault(unescapeSingleQuotes(defaultValue, true), isExpression)})`
888
- : '';
889
- }
890
-
891
- return '';
892
- };
893
-
894
- const column = (
895
- tableName: string,
896
- type: string,
897
- name: string,
898
- domainTypes: Set<string>,
899
- enumTypes: Set<string>,
900
- domainTypeSchema: string,
901
- typeSchema: string,
902
- casing: Casing,
903
- defaultValue?: any,
904
- internals?: PgKitInternals,
905
- ) => {
906
- const isExpression = internals?.tables[tableName]?.columns[name]?.isDefaultAnExpression ?? false;
907
- const lowered = type.toLowerCase().replace('[]', '');
908
-
909
- if (enumTypes.has(`${typeSchema}.${type.replace('[]', '')}`)) {
910
- let out = `${withCasing(name, casing)}: ${withCasing(paramNameFor(type.replace('[]', ''), typeSchema), casing)}(${
911
- dbColumnName({ name, casing })
912
- })`;
913
- return out;
914
- }
915
-
916
- if (domainTypes.has(`${domainTypeSchema}.${type}`)) {
917
- return `${withCasing(name, casing)}: ${withCasing(type, casing)}(${dbColumnName({ name, casing })})`;
918
- }
919
-
920
- // TODO move all of the below into a function so that it can be used for domain serialization
921
- if (lowered.startsWith('serial')) {
922
- return `${withCasing(name, casing)}: serial(${dbColumnName({ name, casing })})`;
923
- }
924
-
925
- if (lowered.startsWith('smallserial')) {
926
- return `${withCasing(name, casing)}: smallserial(${dbColumnName({ name, casing })})`;
927
- }
928
-
929
- if (lowered.startsWith('bigserial')) {
930
- return `${withCasing(name, casing)}: bigserial(${
931
- dbColumnName({ name, casing, withMode: true })
932
- }{ mode: "bigint" })`;
933
- }
934
-
935
- if (lowered.startsWith('integer')) {
936
- let out = `${withCasing(name, casing)}: integer(${dbColumnName({ name, casing })})`;
937
- return out;
938
- }
939
-
940
- if (lowered.startsWith('smallint')) {
941
- let out = `${withCasing(name, casing)}: smallint(${dbColumnName({ name, casing })})`;
942
- return out;
943
- }
944
-
945
- if (lowered.startsWith('bigint')) {
946
- let out = `// You can use { mode: "bigint" } if numbers are exceeding js number limitations\n\t`;
947
- out += `${withCasing(name, casing)}: bigint(${dbColumnName({ name, casing, withMode: true })}{ mode: "number" })`;
948
- return out;
949
- }
950
-
951
- if (lowered.startsWith('boolean')) {
952
- let out = `${withCasing(name, casing)}: boolean(${dbColumnName({ name, casing })})`;
953
- return out;
954
- }
955
-
956
- if (lowered.startsWith('double precision')) {
957
- let out = `${withCasing(name, casing)}: doublePrecision(${dbColumnName({ name, casing })})`;
958
- return out;
959
- }
960
-
961
- if (lowered.startsWith('real')) {
962
- let out = `${withCasing(name, casing)}: real(${dbColumnName({ name, casing })})`;
963
- return out;
964
- }
965
-
966
- if (lowered.startsWith('uuid')) {
967
- let out = `${withCasing(name, casing)}: uuid(${dbColumnName({ name, casing })})`;
968
-
969
- return out;
970
- }
971
-
972
- if (lowered.startsWith('numeric')) {
973
- let params: { precision: string | undefined; scale: string | undefined } | undefined;
974
-
975
- if (lowered.length > 7) {
976
- const [precision, scale] = lowered.slice(8, lowered.length - 1).split(',');
977
- params = { precision, scale };
978
- }
979
-
980
- let out = params
981
- ? `${withCasing(name, casing)}: numeric(${dbColumnName({ name, casing, withMode: true })}${timeConfig(params)})`
982
- : `${withCasing(name, casing)}: numeric(${dbColumnName({ name, casing })})`;
983
-
984
- return out;
985
- }
986
-
987
- if (lowered.startsWith('timestamp')) {
988
- const withTimezone = lowered.includes('with time zone');
989
- // const split = lowered.split(" ");
990
- let precision = lowered.startsWith('timestamp(')
991
- ? Number(lowered.split(' ')[0].substring('timestamp('.length, lowered.split(' ')[0].length - 1))
992
- : null;
993
- precision = precision ? precision : null;
994
-
995
- const params = timeConfig({
996
- precision,
997
- withTimezone,
998
- mode: "'string'",
999
- });
1000
-
1001
- let out = params
1002
- ? `${withCasing(name, casing)}: timestamp(${dbColumnName({ name, casing, withMode: true })}${params})`
1003
- : `${withCasing(name, casing)}: timestamp(${dbColumnName({ name, casing })})`;
1004
-
1005
- return out;
1006
- }
1007
-
1008
- if (lowered.startsWith('time')) {
1009
- const withTimezone = lowered.includes('with time zone');
1010
-
1011
- let precision = lowered.startsWith('time(')
1012
- ? Number(lowered.split(' ')[0].substring('time('.length, lowered.split(' ')[0].length - 1))
1013
- : null;
1014
- precision = precision ? precision : null;
1015
-
1016
- const params = timeConfig({ precision, withTimezone });
1017
-
1018
- let out = params
1019
- ? `${withCasing(name, casing)}: time(${dbColumnName({ name, casing, withMode: true })}${params})`
1020
- : `${withCasing(name, casing)}: time(${dbColumnName({ name, casing })})`;
1021
-
1022
- return out;
1023
- }
1024
-
1025
- if (lowered.startsWith('interval')) {
1026
- // const withTimezone = lowered.includes("with time zone");
1027
- // const split = lowered.split(" ");
1028
- // let precision = split.length >= 2 ? Number(split[1].substring(1, 2)) : null;
1029
- // precision = precision ? precision : null;
1030
-
1031
- const params = intervalConfig(lowered);
1032
-
1033
- let out = params
1034
- ? `${withCasing(name, casing)}: interval(${dbColumnName({ name, casing, withMode: true })}${params})`
1035
- : `${withCasing(name, casing)}: interval(${dbColumnName({ name, casing })})`;
1036
-
1037
- return out;
1038
- }
1039
-
1040
- if (lowered === 'date') {
1041
- let out = `${withCasing(name, casing)}: date(${dbColumnName({ name, casing })})`;
1042
-
1043
- return out;
1044
- }
1045
-
1046
- if (lowered.startsWith('text')) {
1047
- let out = `${withCasing(name, casing)}: text(${dbColumnName({ name, casing })})`;
1048
- return out;
1049
- }
1050
-
1051
- if (lowered.startsWith('jsonb')) {
1052
- let out = `${withCasing(name, casing)}: jsonb(${dbColumnName({ name, casing })})`;
1053
- return out;
1054
- }
1055
-
1056
- if (lowered.startsWith('json')) {
1057
- let out = `${withCasing(name, casing)}: json(${dbColumnName({ name, casing })})`;
1058
- return out;
1059
- }
1060
-
1061
- if (lowered.startsWith('inet')) {
1062
- let out = `${withCasing(name, casing)}: inet(${dbColumnName({ name, casing })})`;
1063
- return out;
1064
- }
1065
-
1066
- if (lowered.startsWith('cidr')) {
1067
- let out = `${withCasing(name, casing)}: cidr(${dbColumnName({ name, casing })})`;
1068
- return out;
1069
- }
1070
-
1071
- if (lowered.startsWith('macaddr8')) {
1072
- let out = `${withCasing(name, casing)}: macaddr8(${dbColumnName({ name, casing })})`;
1073
- return out;
1074
- }
1075
-
1076
- if (lowered.startsWith('macaddr')) {
1077
- let out = `${withCasing(name, casing)}: macaddr(${dbColumnName({ name, casing })})`;
1078
- return out;
1079
- }
1080
-
1081
- if (lowered.startsWith('varchar')) {
1082
- let out: string;
1083
- if (lowered.length !== 7) {
1084
- out = `${withCasing(name, casing)}: varchar(${dbColumnName({ name, casing, withMode: true })}{ length: ${
1085
- lowered.substring(8, lowered.length - 1)
1086
- } })`;
1087
- } else {
1088
- out = `${withCasing(name, casing)}: varchar(${dbColumnName({ name, casing })})`;
1089
- }
1090
-
1091
- return out;
1092
- }
1093
-
1094
- if (lowered.startsWith('point')) {
1095
- let out: string = `${withCasing(name, casing)}: point(${dbColumnName({ name, casing })})`;
1096
- return out;
1097
- }
1098
-
1099
- if (lowered.startsWith('line')) {
1100
- let out: string = `${withCasing(name, casing)}: point(${dbColumnName({ name, casing })})`;
1101
- return out;
1102
- }
1103
-
1104
- if (lowered.startsWith('geometry')) {
1105
- let out: string = '';
1106
-
1107
- let isGeoUnknown = false;
1108
-
1109
- if (lowered.length !== 8) {
1110
- const geometryOptions = lowered.slice(9, -1).split(',');
1111
- if (geometryOptions.length === 1 && geometryOptions[0] !== '') {
1112
- out = `${withCasing(name, casing)}: geometry(${dbColumnName({ name, casing, withMode: true })}{ type: "${
1113
- geometryOptions[0]
1114
- }" })`;
1115
- } else if (geometryOptions.length === 2) {
1116
- out = `${withCasing(name, casing)}: geometry(${dbColumnName({ name, casing, withMode: true })}{ type: "${
1117
- geometryOptions[0]
1118
- }", srid: ${geometryOptions[1]} })`;
1119
- } else {
1120
- isGeoUnknown = true;
1121
- }
1122
- } else {
1123
- out = `${withCasing(name, casing)}: geometry(${dbColumnName({ name, casing })})`;
1124
- }
1125
-
1126
- if (isGeoUnknown) {
1127
- let unknown =
1128
- `// TODO: failed to parse geometry type because found more than 2 options inside geometry function '${type}'\n// Introspect is currently supporting only type and srid options\n`;
1129
- unknown += `\t${withCasing(name, casing)}: unknown("${name}")`;
1130
- return unknown;
1131
- }
1132
- return out;
1133
- }
1134
-
1135
- if (lowered.startsWith('vector')) {
1136
- let out: string;
1137
- if (lowered.length !== 6) {
1138
- out = `${withCasing(name, casing)}: vector(${dbColumnName({ name, casing, withMode: true })}{ dimensions: ${
1139
- lowered.substring(7, lowered.length - 1)
1140
- } })`;
1141
- } else {
1142
- out = `${withCasing(name, casing)}: vector(${dbColumnName({ name, casing })})`;
1143
- }
1144
-
1145
- return out;
1146
- }
1147
-
1148
- if (lowered.startsWith('char')) {
1149
- let out: string;
1150
- if (lowered.length !== 4) {
1151
- out = `${withCasing(name, casing)}: char(${dbColumnName({ name, casing, withMode: true })}{ length: ${
1152
- lowered.substring(5, lowered.length - 1)
1153
- } })`;
1154
- } else {
1155
- out = `${withCasing(name, casing)}: char(${dbColumnName({ name, casing })})`;
1156
- }
1157
-
1158
- return out;
1159
- }
1160
-
1161
- let unknown = `// TODO: failed to parse database type '${type}'\n`;
1162
- unknown += `\t${withCasing(name, casing)}: unknown("${name}")`;
1163
- return unknown;
1164
- };
1165
-
1166
- const dimensionsInArray = (size?: number): string => {
1167
- let res = '';
1168
- if (typeof size === 'undefined') return res;
1169
- for (let i = 0; i < size; i++) {
1170
- res += '.array()';
1171
- }
1172
- return res;
1173
- };
1174
-
1175
- const createTableColumns = (
1176
- tableName: string,
1177
- columns: Column[],
1178
- fks: ForeignKey[],
1179
- domainTypes: Set<string>,
1180
- enumTypes: Set<string>,
1181
- schemas: Record<string, string>,
1182
- casing: Casing,
1183
- internals: PgKitInternals,
1184
- ): string => {
1185
- let statement = '';
1186
-
1187
- // no self refs and no cyclic
1188
- const oneColumnsFKs = Object.values(fks)
1189
- .filter((it) => {
1190
- return !isSelf(it);
1191
- })
1192
- .filter((it) => it.columnsFrom.length === 1);
1193
-
1194
- const fkByColumnName = oneColumnsFKs.reduce((res, it) => {
1195
- const arr = res[it.columnsFrom[0]] || [];
1196
- arr.push(it);
1197
- res[it.columnsFrom[0]] = arr;
1198
- return res;
1199
- }, {} as Record<string, ForeignKey[]>);
1200
-
1201
- columns.forEach((it) => {
1202
- const columnStatement = column(
1203
- tableName,
1204
- it.type,
1205
- it.name,
1206
- domainTypes,
1207
- enumTypes,
1208
- it.domainTypeSchema ?? 'public',
1209
- it.typeSchema ?? 'public',
1210
- casing,
1211
- it.default,
1212
- internals,
1213
- );
1214
- statement += '\t';
1215
- statement += columnStatement;
1216
- // Provide just this in column function
1217
- if (internals?.tables[tableName]?.columns[it.name]?.isArray) {
1218
- statement += dimensionsInArray(internals?.tables[tableName]?.columns[it.name]?.dimensions);
1219
- }
1220
- statement += mapDefault(tableName, it.type, it.name, enumTypes, it.typeSchema ?? 'public', it.default, internals);
1221
- statement += it.primaryKey ? '.primaryKey()' : '';
1222
- statement += it.notNull && !it.identity ? '.notNull()' : '';
1223
-
1224
- statement += it.identity ? generateIdentityParams(it.identity) : '';
1225
-
1226
- statement += it.generated ? `.generatedAlwaysAs(sql\`${it.generated.as}\`)` : '';
1227
-
1228
- // const fks = fkByColumnName[it.name];
1229
- // Andrii: I switched it off until we will get a custom naem setting in references
1230
- // if (fks) {
1231
- // const fksStatement = fks
1232
- // .map((it) => {
1233
- // const onDelete = it.onDelete && it.onDelete !== 'no action' ? it.onDelete : null;
1234
- // const onUpdate = it.onUpdate && it.onUpdate !== 'no action' ? it.onUpdate : null;
1235
- // const params = { onDelete, onUpdate };
1236
-
1237
- // const typeSuffix = isCyclic(it) ? ': AnyPgColumn' : '';
1238
-
1239
- // const paramsStr = objToStatement2(params);
1240
- // const tableSchema = schemas[it.schemaTo || ''];
1241
- // const paramName = paramNameFor(it.tableTo, tableSchema);
1242
- // if (paramsStr) {
1243
- // return `.references(()${typeSuffix} => ${
1244
- // withCasing(
1245
- // paramName,
1246
- // casing,
1247
- // )
1248
- // }.${withCasing(it.columnsTo[0], casing)}, ${paramsStr} )`;
1249
- // }
1250
- // return `.references(()${typeSuffix} => ${
1251
- // withCasing(
1252
- // paramName,
1253
- // casing,
1254
- // )
1255
- // }.${withCasing(it.columnsTo[0], casing)})`;
1256
- // })
1257
- // .join('');
1258
- // statement += fksStatement;
1259
- // }
1260
-
1261
- statement += ',\n';
1262
- });
1263
-
1264
- return statement;
1265
- };
1266
-
1267
- const createTableIndexes = (tableName: string, idxs: Index[], casing: Casing): string => {
1268
- let statement = '';
1269
-
1270
- idxs.forEach((it) => {
1271
- // we have issue when index is called as table called
1272
- let idxKey = it.name.startsWith(tableName) && it.name !== tableName ? it.name.slice(tableName.length + 1) : it.name;
1273
- idxKey = idxKey.endsWith('_index') ? idxKey.slice(0, -'_index'.length) + '_idx' : idxKey;
1274
-
1275
- idxKey = withCasing(idxKey, casing);
1276
-
1277
- const indexGeneratedName = indexName(
1278
- tableName,
1279
- it.columns.map((it) => it.expression),
1280
- );
1281
- const escapedIndexName = indexGeneratedName === it.name ? '' : `"${it.name}"`;
1282
-
1283
- statement += `\n\t`;
1284
- statement += it.isUnique ? 'uniqueIndex(' : 'index(';
1285
- statement += `${escapedIndexName})`;
1286
- statement += `${it.concurrently ? `.concurrently()` : ''}`;
1287
-
1288
- statement += `.using("${it.method}", ${
1289
- it.columns
1290
- .map((it) => {
1291
- if (it.isExpression) {
1292
- return `sql\`${it.expression}\``;
1293
- } else {
1294
- return `table.${withCasing(it.expression, casing)}${it.asc ? '.asc()' : '.desc()'}${
1295
- it.nulls === 'first' ? '.nullsFirst()' : '.nullsLast()'
1296
- }${
1297
- it.opclass
1298
- ? `.op("${it.opclass}")`
1299
- : ''
1300
- }`;
1301
- }
1302
- })
1303
- .join(', ')
1304
- })`;
1305
- statement += it.where ? `.where(sql\`${it.where}\`)` : '';
1306
-
1307
- function reverseLogic(mappedWith: Record<string, string>): string {
1308
- let reversedString = '{';
1309
- for (const key in mappedWith) {
1310
- if (mappedWith.hasOwnProperty(key)) {
1311
- reversedString += `${key}: "${mappedWith[key]}",`;
1312
- }
1313
- }
1314
- reversedString = reversedString.length > 1 ? reversedString.slice(0, reversedString.length - 1) : reversedString;
1315
- return `${reversedString}}`;
1316
- }
1317
-
1318
- statement += it.with && Object.keys(it.with).length > 0 ? `.with(${reverseLogic(it.with)})` : '';
1319
- statement += `,`;
1320
- });
1321
-
1322
- return statement;
1323
- };
1324
-
1325
- const createTablePKs = (pks: PrimaryKey[], casing: Casing): string => {
1326
- let statement = '';
1327
-
1328
- pks.forEach((it) => {
1329
- statement += `\n\t`;
1330
- statement += 'primaryKey({ columns: [';
1331
- statement += `${
1332
- it.columns
1333
- .map((c) => {
1334
- return `table.${withCasing(c, casing)}`;
1335
- })
1336
- .join(', ')
1337
- }]${it.name ? `, name: "${it.name}"` : ''}}`;
1338
- statement += ')';
1339
- statement += `,`;
1340
- });
1341
-
1342
- return statement;
1343
- };
1344
-
1345
- // get a map of db role name to ts key
1346
- // if to by key is in this map - no quotes, otherwise - quotes
1347
-
1348
- const createTablePolicies = (
1349
- policies: Policy[],
1350
- casing: Casing,
1351
- rolesNameToTsKey: Record<string, string> = {},
1352
- ): string => {
1353
- let statement = '';
1354
-
1355
- policies.forEach((it) => {
1356
- const idxKey = withCasing(it.name, casing);
1357
-
1358
- const mappedItTo = it.to?.map((v) => {
1359
- return rolesNameToTsKey[v] ? withCasing(rolesNameToTsKey[v], casing) : `"${v}"`;
1360
- });
1361
-
1362
- statement += `\n\t`;
1363
- statement += 'pgPolicy(';
1364
- statement += `"${it.name}", { `;
1365
- statement += `as: "${it.as?.toLowerCase()}", for: "${it.for?.toLowerCase()}", to: [${mappedItTo?.join(', ')}]${
1366
- it.using ? `, using: sql\`${it.using}\`` : ''
1367
- }${it.withCheck ? `, withCheck: sql\`${it.withCheck}\` ` : ''}`;
1368
- statement += ` }),`;
1369
- });
1370
-
1371
- return statement;
1372
- };
1373
-
1374
- const createTableUniques = (
1375
- unqs: UniqueConstraint[],
1376
- casing: Casing,
1377
- ): string => {
1378
- let statement = '';
1379
-
1380
- unqs.forEach((it) => {
1381
- statement += `\n\t`;
1382
- statement += 'unique(';
1383
- statement += `"${it.name}")`;
1384
- statement += `.on(${it.columns.map((it) => `table.${withCasing(it, casing)}`).join(', ')})`;
1385
- statement += it.nullsNotDistinct ? `.nullsNotDistinct()` : '';
1386
- statement += `,`;
1387
- });
1388
-
1389
- return statement;
1390
- };
1391
-
1392
- const createTableChecks = (
1393
- checkConstraints: CheckConstraint[],
1394
- casing: Casing,
1395
- ) => {
1396
- let statement = '';
1397
-
1398
- checkConstraints.forEach((it) => {
1399
- statement += `\n\t`;
1400
- statement += 'check(';
1401
- statement += `"${it.name}", `;
1402
- statement += `sql\`${it.value}\`)`;
1403
- statement += `,`;
1404
- });
1405
-
1406
- return statement;
1407
- };
1408
-
1409
- const createTableFKs = (fks: ForeignKey[], schemas: Record<string, string>, casing: Casing): string => {
1410
- let statement = '';
1411
-
1412
- fks.forEach((it) => {
1413
- const tableSchema = schemas[it.schemaTo || ''];
1414
- const paramName = paramNameFor(it.tableTo, tableSchema);
1415
-
1416
- const isSelf = it.tableTo === it.tableFrom;
1417
- const tableTo = isSelf ? 'table' : `${withCasing(paramName, casing)}`;
1418
- statement += `\n\t`;
1419
- statement += `foreignKey({\n`;
1420
- statement += `\t\t\tcolumns: [${it.columnsFrom.map((i) => `table.${withCasing(i, casing)}`).join(', ')}],\n`;
1421
- statement += `\t\t\tforeignColumns: [${
1422
- it.columnsTo.map((i) => `${tableTo}.${withCasing(i, casing)}`).join(', ')
1423
- }],\n`;
1424
- statement += `\t\t\tname: "${it.name}"\n`;
1425
- statement += `\t\t})`;
1426
-
1427
- statement += it.onUpdate && it.onUpdate !== 'no action' ? `.onUpdate("${it.onUpdate}")` : '';
1428
-
1429
- statement += it.onDelete && it.onDelete !== 'no action' ? `.onDelete("${it.onDelete}")` : '';
1430
-
1431
- statement += `,`;
1432
- });
1433
-
1434
- return statement;
1435
- };