relq 1.0.4 → 1.0.6

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 (84) hide show
  1. package/dist/cjs/cli/commands/add.cjs +252 -12
  2. package/dist/cjs/cli/commands/commit.cjs +12 -1
  3. package/dist/cjs/cli/commands/export.cjs +25 -19
  4. package/dist/cjs/cli/commands/import.cjs +219 -100
  5. package/dist/cjs/cli/commands/init.cjs +86 -14
  6. package/dist/cjs/cli/commands/pull.cjs +104 -23
  7. package/dist/cjs/cli/commands/push.cjs +38 -3
  8. package/dist/cjs/cli/index.cjs +9 -1
  9. package/dist/cjs/cli/utils/ast/codegen/builder.cjs +297 -0
  10. package/dist/cjs/cli/utils/ast/codegen/constraints.cjs +185 -0
  11. package/dist/cjs/cli/utils/ast/codegen/defaults.cjs +311 -0
  12. package/dist/cjs/cli/utils/ast/codegen/index.cjs +24 -0
  13. package/dist/cjs/cli/utils/ast/codegen/type-map.cjs +116 -0
  14. package/dist/cjs/cli/utils/ast/codegen/utils.cjs +69 -0
  15. package/dist/cjs/cli/utils/ast/index.cjs +19 -0
  16. package/dist/cjs/cli/utils/ast/transformer/helpers.cjs +154 -0
  17. package/dist/cjs/cli/utils/ast/transformer/index.cjs +25 -0
  18. package/dist/cjs/cli/utils/ast/types.cjs +2 -0
  19. package/dist/cjs/cli/utils/ast-codegen.cjs +949 -0
  20. package/dist/cjs/cli/utils/ast-transformer.cjs +916 -0
  21. package/dist/cjs/cli/utils/change-tracker.cjs +50 -1
  22. package/dist/cjs/cli/utils/cli-utils.cjs +151 -0
  23. package/dist/cjs/cli/utils/fast-introspect.cjs +149 -23
  24. package/dist/cjs/cli/utils/pg-parser.cjs +1 -0
  25. package/dist/cjs/cli/utils/repo-manager.cjs +121 -4
  26. package/dist/cjs/cli/utils/schema-comparator.cjs +98 -14
  27. package/dist/cjs/cli/utils/schema-introspect.cjs +56 -19
  28. package/dist/cjs/cli/utils/snapshot-manager.cjs +0 -1
  29. package/dist/cjs/cli/utils/sql-generator.cjs +353 -64
  30. package/dist/cjs/cli/utils/type-generator.cjs +114 -15
  31. package/dist/cjs/core/relq-client.cjs +22 -6
  32. package/dist/cjs/schema-definition/column-types.cjs +150 -13
  33. package/dist/cjs/schema-definition/defaults.cjs +72 -0
  34. package/dist/cjs/schema-definition/index.cjs +15 -1
  35. package/dist/cjs/schema-definition/introspection.cjs +7 -3
  36. package/dist/cjs/schema-definition/pg-relations.cjs +169 -0
  37. package/dist/cjs/schema-definition/pg-view.cjs +30 -0
  38. package/dist/cjs/schema-definition/table-definition.cjs +110 -4
  39. package/dist/cjs/types/config-types.cjs +13 -4
  40. package/dist/cjs/utils/aws-dsql.cjs +177 -0
  41. package/dist/config.d.ts +146 -1
  42. package/dist/esm/cli/commands/add.js +250 -13
  43. package/dist/esm/cli/commands/commit.js +12 -1
  44. package/dist/esm/cli/commands/export.js +25 -19
  45. package/dist/esm/cli/commands/import.js +221 -102
  46. package/dist/esm/cli/commands/init.js +86 -14
  47. package/dist/esm/cli/commands/pull.js +106 -25
  48. package/dist/esm/cli/commands/push.js +39 -4
  49. package/dist/esm/cli/index.js +9 -1
  50. package/dist/esm/cli/utils/ast/codegen/builder.js +291 -0
  51. package/dist/esm/cli/utils/ast/codegen/constraints.js +176 -0
  52. package/dist/esm/cli/utils/ast/codegen/defaults.js +305 -0
  53. package/dist/esm/cli/utils/ast/codegen/index.js +6 -0
  54. package/dist/esm/cli/utils/ast/codegen/type-map.js +111 -0
  55. package/dist/esm/cli/utils/ast/codegen/utils.js +60 -0
  56. package/dist/esm/cli/utils/ast/index.js +3 -0
  57. package/dist/esm/cli/utils/ast/transformer/helpers.js +141 -0
  58. package/dist/esm/cli/utils/ast/transformer/index.js +2 -0
  59. package/dist/esm/cli/utils/ast/types.js +1 -0
  60. package/dist/esm/cli/utils/ast-codegen.js +945 -0
  61. package/dist/esm/cli/utils/ast-transformer.js +907 -0
  62. package/dist/esm/cli/utils/change-tracker.js +50 -1
  63. package/dist/esm/cli/utils/cli-utils.js +147 -0
  64. package/dist/esm/cli/utils/fast-introspect.js +149 -23
  65. package/dist/esm/cli/utils/pg-parser.js +1 -0
  66. package/dist/esm/cli/utils/repo-manager.js +114 -4
  67. package/dist/esm/cli/utils/schema-comparator.js +98 -14
  68. package/dist/esm/cli/utils/schema-introspect.js +56 -19
  69. package/dist/esm/cli/utils/snapshot-manager.js +0 -1
  70. package/dist/esm/cli/utils/sql-generator.js +353 -64
  71. package/dist/esm/cli/utils/type-generator.js +114 -15
  72. package/dist/esm/core/relq-client.js +23 -7
  73. package/dist/esm/schema-definition/column-types.js +147 -12
  74. package/dist/esm/schema-definition/defaults.js +69 -0
  75. package/dist/esm/schema-definition/index.js +3 -0
  76. package/dist/esm/schema-definition/introspection.js +7 -3
  77. package/dist/esm/schema-definition/pg-relations.js +161 -0
  78. package/dist/esm/schema-definition/pg-view.js +24 -0
  79. package/dist/esm/schema-definition/table-definition.js +110 -4
  80. package/dist/esm/types/config-types.js +12 -4
  81. package/dist/esm/utils/aws-dsql.js +139 -0
  82. package/dist/index.d.ts +159 -1
  83. package/dist/schema-builder.d.ts +1314 -32
  84. package/package.json +1 -1
@@ -0,0 +1,305 @@
1
+ import { escapeString } from "./utils.js";
2
+ let needsDefaultImport = false;
3
+ let needsSqlImport = false;
4
+ export function resetDefaultImportFlags() {
5
+ needsDefaultImport = false;
6
+ needsSqlImport = false;
7
+ }
8
+ export function getDefaultImportNeeded() {
9
+ return needsDefaultImport;
10
+ }
11
+ export function getDefaultSqlImportNeeded() {
12
+ return needsSqlImport;
13
+ }
14
+ export function formatDefaultValue(value, columnType) {
15
+ if (!value)
16
+ return "''";
17
+ const trimmed = value.trim();
18
+ const upper = trimmed.toUpperCase();
19
+ if (upper === 'TRUE')
20
+ return 'true';
21
+ if (upper === 'FALSE')
22
+ return 'false';
23
+ if (upper === 'NULL')
24
+ return 'null';
25
+ if (upper === 'GEN_RANDOM_UUID()' || upper.includes('GEN_RANDOM_UUID')) {
26
+ needsDefaultImport = true;
27
+ return 'DEFAULT.genRandomUuid()';
28
+ }
29
+ if (upper === 'UUID_GENERATE_V4()' || upper.includes('UUID_GENERATE_V4')) {
30
+ needsDefaultImport = true;
31
+ return 'DEFAULT.uuidGenerateV4()';
32
+ }
33
+ if (upper === 'UUID_GENERATE_V1()' || upper.includes('UUID_GENERATE_V1()')) {
34
+ needsDefaultImport = true;
35
+ return 'DEFAULT.uuidGenerateV1()';
36
+ }
37
+ if (upper === 'UUID_GENERATE_V1MC()') {
38
+ needsDefaultImport = true;
39
+ return 'DEFAULT.uuidGenerateV1mc()';
40
+ }
41
+ if (upper === 'UUID_NIL()') {
42
+ needsDefaultImport = true;
43
+ return 'DEFAULT.uuidNil()';
44
+ }
45
+ if (upper === 'NOW()' || upper === 'NOW') {
46
+ needsDefaultImport = true;
47
+ return 'DEFAULT.now()';
48
+ }
49
+ if (upper === 'CURRENT_TIMESTAMP' || upper === 'CURRENT_TIMESTAMP()') {
50
+ needsDefaultImport = true;
51
+ return 'DEFAULT.currentTimestamp()';
52
+ }
53
+ if (upper === 'CURRENT_DATE' || upper === 'CURRENT_DATE()') {
54
+ needsDefaultImport = true;
55
+ return 'DEFAULT.currentDate()';
56
+ }
57
+ if (upper === 'CURRENT_TIME' || upper === 'CURRENT_TIME()') {
58
+ needsDefaultImport = true;
59
+ return 'DEFAULT.currentTime()';
60
+ }
61
+ if (upper === 'LOCALTIMESTAMP' || upper === 'LOCALTIMESTAMP()') {
62
+ needsDefaultImport = true;
63
+ return 'DEFAULT.localTimestamp()';
64
+ }
65
+ if (upper === 'LOCALTIME' || upper === 'LOCALTIME()') {
66
+ needsDefaultImport = true;
67
+ return 'DEFAULT.localTime()';
68
+ }
69
+ if (upper === 'TRANSACTION_TIMESTAMP()') {
70
+ needsDefaultImport = true;
71
+ return 'DEFAULT.transactionTimestamp()';
72
+ }
73
+ if (upper === 'STATEMENT_TIMESTAMP()') {
74
+ needsDefaultImport = true;
75
+ return 'DEFAULT.statementTimestamp()';
76
+ }
77
+ if (upper === 'CLOCK_TIMESTAMP()') {
78
+ needsDefaultImport = true;
79
+ return 'DEFAULT.clockTimestamp()';
80
+ }
81
+ if (upper === 'TIMEOFDAY()') {
82
+ needsDefaultImport = true;
83
+ return 'DEFAULT.timeofday()';
84
+ }
85
+ const intervalMatch = trimmed.match(/^'([^']+)'::interval$/i);
86
+ if (intervalMatch) {
87
+ needsDefaultImport = true;
88
+ return `DEFAULT.interval('${intervalMatch[1]}')`;
89
+ }
90
+ if (upper === 'CURRENT_USER' || upper === 'CURRENT_USER()') {
91
+ needsDefaultImport = true;
92
+ return 'DEFAULT.currentUser()';
93
+ }
94
+ if (upper === 'SESSION_USER' || upper === 'SESSION_USER()') {
95
+ needsDefaultImport = true;
96
+ return 'DEFAULT.sessionUser()';
97
+ }
98
+ if (upper === 'USER' || upper === 'USER()') {
99
+ needsDefaultImport = true;
100
+ return 'DEFAULT.user()';
101
+ }
102
+ if (upper === 'CURRENT_SCHEMA()' || upper === 'CURRENT_SCHEMA') {
103
+ needsDefaultImport = true;
104
+ return 'DEFAULT.currentSchema()';
105
+ }
106
+ if (upper === 'CURRENT_DATABASE()') {
107
+ needsDefaultImport = true;
108
+ return 'DEFAULT.currentDatabase()';
109
+ }
110
+ if (upper === 'CURRENT_CATALOG' || upper === 'CURRENT_CATALOG()') {
111
+ needsDefaultImport = true;
112
+ return 'DEFAULT.currentCatalog()';
113
+ }
114
+ if (upper === 'INET_CLIENT_ADDR()') {
115
+ needsDefaultImport = true;
116
+ return 'DEFAULT.inetClientAddr()';
117
+ }
118
+ if (upper === 'INET_SERVER_ADDR()') {
119
+ needsDefaultImport = true;
120
+ return 'DEFAULT.inetServerAddr()';
121
+ }
122
+ if (upper === 'PG_BACKEND_PID()') {
123
+ needsDefaultImport = true;
124
+ return 'DEFAULT.pgBackendPid()';
125
+ }
126
+ const nextvalMatch = trimmed.match(/^nextval\('([^']+)'(?:::regclass)?\)$/i);
127
+ if (nextvalMatch) {
128
+ needsDefaultImport = true;
129
+ return `DEFAULT.nextval('${nextvalMatch[1]}')`;
130
+ }
131
+ const currvalMatch = trimmed.match(/^currval\('([^']+)'(?:::regclass)?\)$/i);
132
+ if (currvalMatch) {
133
+ needsDefaultImport = true;
134
+ return `DEFAULT.currval('${currvalMatch[1]}')`;
135
+ }
136
+ if (upper === 'LASTVAL()') {
137
+ needsDefaultImport = true;
138
+ return 'DEFAULT.lastval()';
139
+ }
140
+ if (upper === 'RANDOM()') {
141
+ needsDefaultImport = true;
142
+ return 'DEFAULT.random()';
143
+ }
144
+ if (upper === 'PI()') {
145
+ needsDefaultImport = true;
146
+ return 'DEFAULT.pi()';
147
+ }
148
+ if (trimmed === "''" || trimmed === '""') {
149
+ needsDefaultImport = true;
150
+ return 'DEFAULT.emptyString()';
151
+ }
152
+ if (trimmed === "'{}'::jsonb" || upper === "'{}'::JSONB") {
153
+ needsDefaultImport = true;
154
+ return 'DEFAULT.emptyJsonb()';
155
+ }
156
+ if (trimmed === "'{}'::json" || upper === "'{}'::JSON") {
157
+ needsDefaultImport = true;
158
+ return 'DEFAULT.emptyJson()';
159
+ }
160
+ if (trimmed === "'{}'" || trimmed === "'{}'") {
161
+ needsDefaultImport = true;
162
+ return 'DEFAULT.emptyObject()';
163
+ }
164
+ if (trimmed === "'[]'::jsonb" || upper === "'[]'::JSONB" || trimmed === "'[]'::json" || upper === "'[]'::JSON") {
165
+ needsDefaultImport = true;
166
+ return 'DEFAULT.emptyArray()';
167
+ }
168
+ const emptyArrayMatch = trimmed.match(/^ARRAY\[\]::(\w+)\[\]$/i);
169
+ if (emptyArrayMatch) {
170
+ needsDefaultImport = true;
171
+ return 'DEFAULT.emptyArray()';
172
+ }
173
+ const emptyArrayLiteralMatch = trimmed.match(/^'\{\}'::(\w+)\[\]$/i);
174
+ if (emptyArrayLiteralMatch) {
175
+ needsDefaultImport = true;
176
+ return 'DEFAULT.emptyArray()';
177
+ }
178
+ if (upper === "'EMPTY'::INT4RANGE") {
179
+ needsDefaultImport = true;
180
+ return 'DEFAULT.emptyInt4range()';
181
+ }
182
+ if (upper === "'EMPTY'::INT8RANGE") {
183
+ needsDefaultImport = true;
184
+ return 'DEFAULT.emptyInt8range()';
185
+ }
186
+ if (upper === "'EMPTY'::NUMRANGE") {
187
+ needsDefaultImport = true;
188
+ return 'DEFAULT.emptyNumrange()';
189
+ }
190
+ if (upper === "'EMPTY'::TSRANGE") {
191
+ needsDefaultImport = true;
192
+ return 'DEFAULT.emptyTsrange()';
193
+ }
194
+ if (upper === "'EMPTY'::TSTZRANGE") {
195
+ needsDefaultImport = true;
196
+ return 'DEFAULT.emptyTstzrange()';
197
+ }
198
+ if (upper === "'EMPTY'::DATERANGE") {
199
+ needsDefaultImport = true;
200
+ return 'DEFAULT.emptyDaterange()';
201
+ }
202
+ if (upper === "''::TSVECTOR") {
203
+ needsDefaultImport = true;
204
+ return 'DEFAULT.emptyTsvector()';
205
+ }
206
+ if (upper === "''::HSTORE") {
207
+ needsDefaultImport = true;
208
+ return 'DEFAULT.emptyHstore()';
209
+ }
210
+ if (trimmed === "'\\x'::bytea" || upper === "'\\X'::BYTEA") {
211
+ needsDefaultImport = true;
212
+ return 'DEFAULT.emptyBytea()';
213
+ }
214
+ const moneyMatch = trimmed.match(/^'([^']+)'::money$/i);
215
+ if (moneyMatch) {
216
+ needsDefaultImport = true;
217
+ if (moneyMatch[1] === '0' || moneyMatch[1] === '0.00') {
218
+ return 'DEFAULT.zeroMoney()';
219
+ }
220
+ return `DEFAULT.money('${moneyMatch[1]}')`;
221
+ }
222
+ const inetMatch = trimmed.match(/^'([^']+)'::inet$/i);
223
+ if (inetMatch) {
224
+ needsDefaultImport = true;
225
+ return `DEFAULT.inet('${inetMatch[1]}')`;
226
+ }
227
+ const cidrMatch = trimmed.match(/^'([^']+)'::cidr$/i);
228
+ if (cidrMatch) {
229
+ needsDefaultImport = true;
230
+ return `DEFAULT.cidr('${cidrMatch[1]}')`;
231
+ }
232
+ const macaddrMatch = trimmed.match(/^'([^']+)'::macaddr$/i);
233
+ if (macaddrMatch) {
234
+ needsDefaultImport = true;
235
+ return `DEFAULT.macaddr('${macaddrMatch[1]}')`;
236
+ }
237
+ const pointMatch = trimmed.match(/^point\(([^,]+),\s*([^)]+)\)$/i);
238
+ if (pointMatch) {
239
+ needsDefaultImport = true;
240
+ return `DEFAULT.point(${pointMatch[1]}, ${pointMatch[2]})`;
241
+ }
242
+ const castMatch = trimmed.match(/^'([^']*)'::(.+)$/i);
243
+ if (castMatch) {
244
+ const castValue = castMatch[1];
245
+ const castType = castMatch[2].toLowerCase().trim();
246
+ if ((castType === 'jsonb' || castType === 'json') && castValue.startsWith('[')) {
247
+ try {
248
+ const parsed = JSON.parse(castValue);
249
+ return JSON.stringify(parsed);
250
+ }
251
+ catch {
252
+ }
253
+ }
254
+ if ((castType === 'jsonb' || castType === 'json') && castValue.startsWith('{')) {
255
+ try {
256
+ const parsed = JSON.parse(castValue);
257
+ return JSON.stringify(parsed);
258
+ }
259
+ catch {
260
+ }
261
+ }
262
+ if (['varchar', 'text', 'char', 'bpchar', 'character', 'character varying'].includes(castType)) {
263
+ return `'${castValue.replace(/'/g, "\\'")}'`;
264
+ }
265
+ if (['int', 'int2', 'int4', 'int8', 'integer', 'smallint', 'bigint'].includes(castType)) {
266
+ const num = parseInt(castValue, 10);
267
+ if (!isNaN(num)) {
268
+ if (castType === 'int8' || castType === 'bigint') {
269
+ return `${num}n`;
270
+ }
271
+ return String(num);
272
+ }
273
+ }
274
+ if (castType === 'boolean' || castType === 'bool') {
275
+ return castValue.toLowerCase() === 'true' ? 'true' : 'false';
276
+ }
277
+ if (['numeric', 'decimal', 'real', 'float', 'float4', 'float8', 'double precision'].includes(castType)) {
278
+ const num = parseFloat(castValue);
279
+ if (!isNaN(num)) {
280
+ return String(num);
281
+ }
282
+ }
283
+ return `'${castValue.replace(/'/g, "\\'")}'`;
284
+ }
285
+ const normalizedColType = columnType?.toLowerCase().trim();
286
+ const isBigintColumn = normalizedColType === 'int8' || normalizedColType === 'bigint';
287
+ if (/^-?\d+$/.test(trimmed)) {
288
+ if (isBigintColumn) {
289
+ return `${trimmed}n`;
290
+ }
291
+ return trimmed;
292
+ }
293
+ if (/^-?\d+\.\d+$/.test(trimmed)) {
294
+ return trimmed;
295
+ }
296
+ if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
297
+ const inner = trimmed.slice(1, -1);
298
+ return `'${inner.replace(/'/g, "\\'")}'`;
299
+ }
300
+ if (/^CAST\s*\(\s*(?:'?\{\}'?|ARRAY\s*\[\s*\])\s+AS\s+\w+\s*\[\s*\]\s*\)$/i.test(trimmed)) {
301
+ return '[]';
302
+ }
303
+ needsSqlImport = true;
304
+ return `sql\`${escapeString(trimmed)}\``;
305
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./utils.js";
2
+ export * from "./builder.js";
3
+ export * from "./type-map.js";
4
+ export * from "./defaults.js";
5
+ export * from "./constraints.js";
6
+ export { generateTypeScriptFromAST } from "../../ast-codegen.js";
@@ -0,0 +1,111 @@
1
+ export const TYPE_MAP = {
2
+ 'int2': 'smallint',
3
+ 'int4': 'integer',
4
+ 'int8': 'bigint',
5
+ 'smallint': 'smallint',
6
+ 'integer': 'integer',
7
+ 'bigint': 'bigint',
8
+ 'serial': 'serial',
9
+ 'smallserial': 'smallserial',
10
+ 'bigserial': 'bigserial',
11
+ 'float4': 'real',
12
+ 'float8': 'doublePrecision',
13
+ 'real': 'real',
14
+ 'double precision': 'doublePrecision',
15
+ 'numeric': 'numeric',
16
+ 'decimal': 'numeric',
17
+ 'money': 'money',
18
+ 'text': 'text',
19
+ 'varchar': 'varchar',
20
+ 'character varying': 'varchar',
21
+ 'char': 'char',
22
+ 'character': 'char',
23
+ 'bpchar': 'char',
24
+ 'citext': 'citext',
25
+ 'name': 'name',
26
+ 'bytea': 'bytea',
27
+ 'bool': 'boolean',
28
+ 'boolean': 'boolean',
29
+ 'date': 'date',
30
+ 'time': 'time',
31
+ 'timetz': 'timetz',
32
+ 'timestamp': 'timestamp',
33
+ 'timestamptz': 'timestamptz',
34
+ 'interval': 'interval',
35
+ 'uuid': 'uuid',
36
+ 'json': 'json',
37
+ 'jsonb': 'jsonb',
38
+ 'inet': 'inet',
39
+ 'cidr': 'cidr',
40
+ 'macaddr': 'macaddr',
41
+ 'macaddr8': 'macaddr8',
42
+ 'point': 'point',
43
+ 'line': 'line',
44
+ 'lseg': 'lseg',
45
+ 'box': 'box',
46
+ 'path': 'path',
47
+ 'polygon': 'polygon',
48
+ 'circle': 'circle',
49
+ 'int4range': 'int4range',
50
+ 'int8range': 'int8range',
51
+ 'numrange': 'numrange',
52
+ 'tsrange': 'tsrange',
53
+ 'tstzrange': 'tstzrange',
54
+ 'daterange': 'daterange',
55
+ 'tsvector': 'tsvector',
56
+ 'tsquery': 'tsquery',
57
+ 'xml': 'xml',
58
+ 'bit': 'bit',
59
+ 'varbit': 'varbit',
60
+ 'ltree': 'ltree',
61
+ 'cube': 'cube',
62
+ 'hstore': 'hstore',
63
+ };
64
+ export function getColumnBuilder(type, params) {
65
+ const result = getColumnBuilderWithInfo(type, params);
66
+ if (result.length != null) {
67
+ return `${result.builderName}(${result.length})`;
68
+ }
69
+ return result.builder;
70
+ }
71
+ export function getColumnBuilderWithInfo(type, params) {
72
+ const normalizedType = type.toLowerCase().trim();
73
+ const builderName = TYPE_MAP[normalizedType] || 'text';
74
+ let builder = `${builderName}()`;
75
+ let length;
76
+ if (params) {
77
+ if ((builderName === 'varchar' || builderName === 'char') && params.length) {
78
+ length = params.length;
79
+ }
80
+ else if (builderName === 'numeric' && params.precision != null) {
81
+ if (params.scale != null && params.scale > 0) {
82
+ builder = `numeric(${params.precision}, ${params.scale})`;
83
+ }
84
+ else {
85
+ builder = `numeric(${params.precision})`;
86
+ }
87
+ }
88
+ else if (builderName === 'bit' && params.length) {
89
+ builder = `bit(${params.length})`;
90
+ }
91
+ else if (builderName === 'varbit' && params.length) {
92
+ builder = `varbit(${params.length})`;
93
+ }
94
+ else if (builderName === 'time' && params.precision != null) {
95
+ builder = `time(${params.precision})`;
96
+ }
97
+ else if (builderName === 'timetz' && params.precision != null) {
98
+ builder = `timetz(${params.precision})`;
99
+ }
100
+ else if (builderName === 'timestamp' && params.precision != null) {
101
+ builder = `timestamp(${params.precision})`;
102
+ }
103
+ else if (builderName === 'timestamptz' && params.precision != null) {
104
+ builder = `timestamptz(${params.precision})`;
105
+ }
106
+ else if (builderName === 'interval' && params.precision != null) {
107
+ builder = `interval(${params.precision})`;
108
+ }
109
+ }
110
+ return { builder, builderName, length };
111
+ }
@@ -0,0 +1,60 @@
1
+ export function toCamelCase(str) {
2
+ if (!str)
3
+ return 'unknown';
4
+ const cleaned = str.replace(/^[_0-9]+/, '');
5
+ return cleaned
6
+ .split('_')
7
+ .map((word, i) => i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
8
+ .join('');
9
+ }
10
+ export function toPascalCase(str) {
11
+ if (!str)
12
+ return 'Unknown';
13
+ const cleaned = str.replace(/^[_0-9]+/, '');
14
+ return cleaned
15
+ .split('_')
16
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
17
+ .join('');
18
+ }
19
+ export function escapeString(str) {
20
+ return str.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
21
+ }
22
+ export function escapeJsDocString(str) {
23
+ return str.replace(/\*\//g, '*\\/').replace(/\n/g, '\n * ');
24
+ }
25
+ export function pluralize(word) {
26
+ if (!word)
27
+ return word;
28
+ if (word.endsWith('s') || word.endsWith('x') || word.endsWith('z') ||
29
+ word.endsWith('ch') || word.endsWith('sh')) {
30
+ return word + 'es';
31
+ }
32
+ if (word.endsWith('y') && !['a', 'e', 'i', 'o', 'u'].includes(word[word.length - 2])) {
33
+ return word.slice(0, -1) + 'ies';
34
+ }
35
+ return word + 's';
36
+ }
37
+ export function isBalanced(str) {
38
+ let count = 0;
39
+ for (const char of str) {
40
+ if (char === '(')
41
+ count++;
42
+ if (char === ')')
43
+ count--;
44
+ if (count < 0)
45
+ return false;
46
+ }
47
+ return count === 0;
48
+ }
49
+ export function getComparisonMethod(op) {
50
+ switch (op) {
51
+ case '>': return 'gt';
52
+ case '>=': return 'gte';
53
+ case '<': return 'lt';
54
+ case '<=': return 'lte';
55
+ case '=': return 'eq';
56
+ case '<>':
57
+ case '!=': return 'neq';
58
+ default: return 'eq';
59
+ }
60
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./codegen/index.js";
3
+ export * from "./transformer/index.js";
@@ -0,0 +1,141 @@
1
+ import { deparse } from 'pgsql-deparser';
2
+ export function extractTypeName(typeName) {
3
+ if (!typeName)
4
+ return { name: 'text', isArray: false };
5
+ const names = typeName.names?.map((n) => n.String?.sval).filter(Boolean) || [];
6
+ let name = names.length > 1 ? names[names.length - 1] : names[0] || 'text';
7
+ if (names[0] === 'pg_catalog') {
8
+ name = names[1] || 'text';
9
+ }
10
+ const isArray = (typeName.arrayBounds?.length ?? 0) > 0;
11
+ const arrayDims = typeName.arrayBounds?.length;
12
+ let params;
13
+ if (typeName.typmods && typeName.typmods.length > 0) {
14
+ const mods = typeName.typmods.map((m) => {
15
+ if (m.A_Const?.ival?.ival !== undefined)
16
+ return m.A_Const.ival.ival;
17
+ if (m.A_Const?.sval?.sval !== undefined)
18
+ return m.A_Const.sval.sval;
19
+ return undefined;
20
+ }).filter((v) => v !== undefined);
21
+ if (mods.length === 1) {
22
+ if (['varchar', 'character varying', 'char', 'character', 'bit', 'varbit'].includes(name.toLowerCase())) {
23
+ params = { length: mods[0] };
24
+ }
25
+ else {
26
+ params = { precision: mods[0] };
27
+ }
28
+ }
29
+ else if (mods.length === 2) {
30
+ params = { precision: mods[0], scale: mods[1] };
31
+ }
32
+ }
33
+ return { name, params, isArray, arrayDims };
34
+ }
35
+ export function extractConstraintType(contype) {
36
+ const types = {
37
+ 0: 'NULL',
38
+ 1: 'NOT NULL',
39
+ 2: 'DEFAULT',
40
+ 3: 'IDENTITY',
41
+ 4: 'GENERATED',
42
+ 5: 'CHECK',
43
+ 6: 'PRIMARY KEY',
44
+ 7: 'UNIQUE',
45
+ 8: 'EXCLUSION',
46
+ 9: 'FOREIGN KEY',
47
+ };
48
+ return types[contype] || 'UNKNOWN';
49
+ }
50
+ export function extractFkAction(action) {
51
+ if (!action)
52
+ return undefined;
53
+ const actions = {
54
+ 'a': 'NO ACTION',
55
+ 'r': 'RESTRICT',
56
+ 'c': 'CASCADE',
57
+ 'n': 'SET NULL',
58
+ 'd': 'SET DEFAULT',
59
+ };
60
+ return actions[action];
61
+ }
62
+ export function extractFkMatch(matchType) {
63
+ if (!matchType)
64
+ return undefined;
65
+ const matches = {
66
+ 's': 'SIMPLE',
67
+ 'f': 'FULL',
68
+ };
69
+ return matches[matchType];
70
+ }
71
+ export async function deparseNode(node) {
72
+ try {
73
+ const result = await deparse([node]);
74
+ return result.trim();
75
+ }
76
+ catch {
77
+ return '';
78
+ }
79
+ }
80
+ export function normalizeTypeName(dataType, udtName) {
81
+ if (dataType === 'ARRAY' && udtName) {
82
+ const baseType = udtName.replace(/^_/, '');
83
+ return baseType;
84
+ }
85
+ const typeMap = {
86
+ 'integer': 'int4',
87
+ 'smallint': 'int2',
88
+ 'bigint': 'int8',
89
+ 'real': 'float4',
90
+ 'double precision': 'float8',
91
+ 'character varying': 'varchar',
92
+ 'character': 'char',
93
+ 'boolean': 'bool',
94
+ 'timestamp without time zone': 'timestamp',
95
+ 'timestamp with time zone': 'timestamptz',
96
+ 'time without time zone': 'time',
97
+ 'time with time zone': 'timetz',
98
+ };
99
+ const lower = dataType.toLowerCase();
100
+ return typeMap[lower] || udtName || lower;
101
+ }
102
+ export function extractTypeParams(col) {
103
+ if (col.characterMaxLength) {
104
+ return { length: col.characterMaxLength };
105
+ }
106
+ if (col.numericPrecision != null) {
107
+ if (col.numericScale != null && col.numericScale > 0) {
108
+ return { precision: col.numericPrecision, scale: col.numericScale };
109
+ }
110
+ return { precision: col.numericPrecision };
111
+ }
112
+ return undefined;
113
+ }
114
+ export function extractColumnsFromDefinition(definition) {
115
+ const match = definition.match(/\(([^)]+)\)/);
116
+ if (!match)
117
+ return [];
118
+ return match[1].split(',').map(s => s.trim().replace(/"/g, ''));
119
+ }
120
+ export function extractCheckExpression(definition) {
121
+ const match = definition.match(/CHECK\s*\((.+)\)/is);
122
+ return match ? match[1].trim() : definition;
123
+ }
124
+ export function extractExcludeExpression(definition) {
125
+ const match = definition.match(/EXCLUDE\s+USING\s+\w+\s*\((.+)\)/is);
126
+ return match ? match[1].trim() : definition;
127
+ }
128
+ export function parseArgTypes(argTypes) {
129
+ if (!argTypes)
130
+ return [];
131
+ if (Array.isArray(argTypes)) {
132
+ return argTypes.map(t => ({ type: t }));
133
+ }
134
+ return argTypes.split(',').map(arg => {
135
+ const parts = arg.trim().split(/\s+/);
136
+ if (parts.length > 1) {
137
+ return { name: parts[0], type: parts.slice(1).join(' ') };
138
+ }
139
+ return { type: parts[0] };
140
+ }).filter(a => a.type);
141
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./helpers.js";
2
+ export { parseSQL, deparseSchema, introspectedToParsedSchema, normalizedToParsedSchema, parse, deparse, } from "../../ast-transformer.js";
@@ -0,0 +1 @@
1
+ export {};