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
@@ -478,7 +478,7 @@ function generateSchemaCode(table, options) {
478
478
  modifiers.push('.unique()');
479
479
  }
480
480
  if (col.default !== undefined) {
481
- const defaultVal = formatDefaultValue(col.default);
481
+ const defaultVal = formatDefaultValue(col.default, col.type);
482
482
  modifiers.push(`.default(${defaultVal})`);
483
483
  }
484
484
  if (col.references) {
@@ -583,7 +583,7 @@ function toPascalCase(str) {
583
583
  function escapeString(str) {
584
584
  return str.replace(/'/g, "\\'").replace(/\\/g, '\\\\');
585
585
  }
586
- function formatDefaultValue(value) {
586
+ function formatDefaultValue(value, colType) {
587
587
  const upper = value.toUpperCase().trim();
588
588
  if (upper === 'NOW()' || upper === 'CURRENT_TIMESTAMP' ||
589
589
  upper === 'CURRENT_DATE' || upper === 'CURRENT_TIME') {
@@ -598,7 +598,11 @@ function formatDefaultValue(value) {
598
598
  if (upper === 'NULL') {
599
599
  return 'null';
600
600
  }
601
- if (/^-?\d+(\.\d+)?$/.test(value)) {
601
+ const isBigint = colType?.toLowerCase().startsWith('bigint');
602
+ if (/^-?\d+$/.test(value)) {
603
+ return isBigint ? `${value}n` : value;
604
+ }
605
+ if (/^-?\d+\.\d+$/.test(value)) {
602
606
  return value;
603
607
  }
604
608
  if (value.includes('(')) {
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pgRelations = pgRelations;
4
+ exports.defineRelations = defineRelations;
5
+ exports.actionCodeToString = actionCodeToString;
6
+ exports.stringToActionCode = stringToActionCode;
7
+ exports.matchCodeToString = matchCodeToString;
8
+ exports.generateReferencesSQL = generateReferencesSQL;
9
+ function createColumnRef(tableName, columnName, schemaKey) {
10
+ return {
11
+ $table: tableName,
12
+ $column: columnName,
13
+ $schemaKey: schemaKey,
14
+ };
15
+ }
16
+ function createTargetColumnRefs(schemaKey, table) {
17
+ const refs = {};
18
+ const actualTableName = table.$name;
19
+ for (const colName of Object.keys(table.$columns)) {
20
+ const colDef = table.$columns[colName];
21
+ const actualColName = colDef.$sqlName || colName;
22
+ refs[colName] = createColumnRef(actualTableName, actualColName, colName);
23
+ }
24
+ return refs;
25
+ }
26
+ function createReferenceToBuilder(schema, currentTableKey) {
27
+ return new Proxy({}, {
28
+ get(_, targetTableKey) {
29
+ const targetTable = schema[targetTableKey];
30
+ if (!targetTable) {
31
+ throw new Error(`Unknown table: ${targetTableKey}`);
32
+ }
33
+ return (callback) => {
34
+ const targetColRefs = createTargetColumnRefs(targetTableKey, targetTable);
35
+ const options = callback(targetColRefs);
36
+ const currentTable = schema[currentTableKey];
37
+ const currentTableName = currentTable?.$name || currentTableKey;
38
+ if ('columns' in options && Array.isArray(options.columns)) {
39
+ const compositeOpts = options;
40
+ return {
41
+ $type: 'foreignKey',
42
+ $targetTable: targetTable.$name,
43
+ $columns: compositeOpts.columns.map(c => ({
44
+ table: c.$table,
45
+ column: c.$column,
46
+ })),
47
+ $references: compositeOpts.references.map(r => ({
48
+ table: r.$table,
49
+ column: r.$column,
50
+ })),
51
+ $onDelete: compositeOpts.onDelete,
52
+ $onUpdate: compositeOpts.onUpdate,
53
+ $match: compositeOpts.match,
54
+ $deferrable: compositeOpts.deferrable,
55
+ $initiallyDeferred: compositeOpts.initiallyDeferred,
56
+ };
57
+ }
58
+ const singleOpts = options;
59
+ const referencesCol = singleOpts.references;
60
+ return {
61
+ $type: 'foreignKey',
62
+ $targetTable: targetTable.$name,
63
+ $columns: [],
64
+ $references: referencesCol ? [{
65
+ table: referencesCol.$table,
66
+ column: referencesCol.$column,
67
+ }] : undefined,
68
+ $onDelete: singleOpts.onDelete,
69
+ $onUpdate: singleOpts.onUpdate,
70
+ $match: singleOpts.match,
71
+ $deferrable: singleOpts.deferrable,
72
+ $initiallyDeferred: singleOpts.initiallyDeferred,
73
+ };
74
+ };
75
+ },
76
+ });
77
+ }
78
+ function createSourceColumnRefs(schemaKey, table) {
79
+ const refs = {};
80
+ const actualTableName = table.$name;
81
+ for (const colName of Object.keys(table.$columns)) {
82
+ const colDef = table.$columns[colName];
83
+ const actualColName = colDef.$sqlName || colName;
84
+ refs[colName] = createColumnRef(actualTableName, actualColName, colName);
85
+ }
86
+ return refs;
87
+ }
88
+ function createFullBuilder(schema, currentTableKey) {
89
+ const builder = {
90
+ referenceTo: createReferenceToBuilder(schema, currentTableKey),
91
+ };
92
+ for (const [tableName, table] of Object.entries(schema)) {
93
+ builder[tableName] = createSourceColumnRefs(tableName, table);
94
+ }
95
+ return builder;
96
+ }
97
+ function pgRelations(schema, builder) {
98
+ const tables = {};
99
+ for (const tableKey of Object.keys(schema)) {
100
+ tables[tableKey] = (defineRelations) => {
101
+ const fullBuilder = createFullBuilder(schema, tableKey);
102
+ return defineRelations(fullBuilder);
103
+ };
104
+ }
105
+ return builder(tables);
106
+ }
107
+ function defineRelations(schema, relationDefs) {
108
+ const result = {};
109
+ for (const [tableKey, defFn] of Object.entries(relationDefs)) {
110
+ if (typeof defFn === 'function') {
111
+ const fullBuilder = createFullBuilder(schema, tableKey);
112
+ result[tableKey] = defFn(fullBuilder);
113
+ }
114
+ }
115
+ return result;
116
+ }
117
+ function actionCodeToString(code) {
118
+ switch (code) {
119
+ case 'a': return 'NO ACTION';
120
+ case 'r': return 'RESTRICT';
121
+ case 'c': return 'CASCADE';
122
+ case 'n': return 'SET NULL';
123
+ case 'd': return 'SET DEFAULT';
124
+ default: return 'NO ACTION';
125
+ }
126
+ }
127
+ function stringToActionCode(action) {
128
+ switch (action) {
129
+ case 'NO ACTION': return 'a';
130
+ case 'RESTRICT': return 'r';
131
+ case 'CASCADE': return 'c';
132
+ case 'SET NULL': return 'n';
133
+ case 'SET DEFAULT': return 'd';
134
+ default: return 'a';
135
+ }
136
+ }
137
+ function matchCodeToString(code) {
138
+ switch (code) {
139
+ case 'f': return 'FULL';
140
+ case 's':
141
+ default: return 'SIMPLE';
142
+ }
143
+ }
144
+ function generateReferencesSQL(relation, columnName, columnType = 'uuid') {
145
+ const parts = [`${columnName} ${columnType}`];
146
+ if (relation.$references && relation.$references.length > 0) {
147
+ const refCols = relation.$references.map(r => r.column).join(', ');
148
+ parts.push(`REFERENCES ${relation.$targetTable}(${refCols})`);
149
+ }
150
+ else {
151
+ parts.push(`REFERENCES ${relation.$targetTable}`);
152
+ }
153
+ if (relation.$onDelete && relation.$onDelete !== 'NO ACTION') {
154
+ parts.push(`ON DELETE ${relation.$onDelete}`);
155
+ }
156
+ if (relation.$onUpdate && relation.$onUpdate !== 'NO ACTION') {
157
+ parts.push(`ON UPDATE ${relation.$onUpdate}`);
158
+ }
159
+ if (relation.$match && relation.$match !== 'SIMPLE') {
160
+ parts.push(`MATCH ${relation.$match}`);
161
+ }
162
+ if (relation.$deferrable) {
163
+ parts.push('DEFERRABLE');
164
+ if (relation.$initiallyDeferred) {
165
+ parts.push('INITIALLY DEFERRED');
166
+ }
167
+ }
168
+ return parts.join(' ');
169
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pgView = pgView;
4
+ exports.pgMaterializedView = pgMaterializedView;
5
+ exports.viewToSQL = viewToSQL;
6
+ exports.materializedViewToSQL = materializedViewToSQL;
7
+ function pgView(name, definition) {
8
+ return {
9
+ _type: 'view',
10
+ name,
11
+ definition: definition.trim(),
12
+ isMaterialized: false,
13
+ };
14
+ }
15
+ function pgMaterializedView(name, definition, options) {
16
+ return {
17
+ _type: 'materialized_view',
18
+ name,
19
+ definition: definition.trim(),
20
+ isMaterialized: true,
21
+ withData: options?.withData,
22
+ };
23
+ }
24
+ function viewToSQL(view) {
25
+ return `CREATE OR REPLACE VIEW "${view.name}" AS\n${view.definition};`;
26
+ }
27
+ function materializedViewToSQL(view) {
28
+ const withData = view.withData !== false ? ' WITH DATA' : ' WITH NO DATA';
29
+ return `CREATE MATERIALIZED VIEW IF NOT EXISTS "${view.name}" AS\n${view.definition}${withData};`;
30
+ }
@@ -43,6 +43,9 @@ function createColumnExpr(colName) {
43
43
  neq(value) {
44
44
  return whereCondition(`${this.$sql} != ${formatWhereValue(value)}`);
45
45
  },
46
+ ne(value) {
47
+ return whereCondition(`${this.$sql} <> ${formatWhereValue(value)}`);
48
+ },
46
49
  gt(value) {
47
50
  return whereCondition(`${this.$sql} > ${formatWhereValue(value)}`);
48
51
  },
@@ -177,6 +180,9 @@ function createCheckExpr(sql) {
177
180
  neq(value) {
178
181
  return createCheckWhereCondition(`${this.$sql} != ${formatVal(value)}`);
179
182
  },
183
+ ne(value) {
184
+ return createCheckWhereCondition(`${this.$sql} <> ${formatVal(value)}`);
185
+ },
180
186
  isNull() {
181
187
  return createCheckWhereCondition(`${this.$sql} IS NULL`);
182
188
  },
@@ -261,6 +267,53 @@ function createCheckConstraintBuilder() {
261
267
  constraint(name, condition) {
262
268
  return { name, expression: condition.$sql };
263
269
  },
270
+ raw(expression) {
271
+ return createCheckWhereCondition(expression);
272
+ },
273
+ };
274
+ }
275
+ function createConstraintBuilder() {
276
+ return {
277
+ primaryKey(...args) {
278
+ if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && 'columns' in args[0]) {
279
+ const opts = args[0];
280
+ return {
281
+ $type: 'PRIMARY KEY',
282
+ $name: opts.name || '',
283
+ $columns: opts.columns.map(c => String(c)),
284
+ };
285
+ }
286
+ const columns = args;
287
+ return {
288
+ $type: 'PRIMARY KEY',
289
+ $name: '',
290
+ $columns: columns.map(c => String(c)),
291
+ };
292
+ },
293
+ unique(...args) {
294
+ if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && 'columns' in args[0]) {
295
+ const opts = args[0];
296
+ return {
297
+ $type: 'UNIQUE',
298
+ $name: opts.name || '',
299
+ $columns: opts.columns.map(c => String(c)),
300
+ };
301
+ }
302
+ const columns = args;
303
+ return {
304
+ $type: 'UNIQUE',
305
+ $name: '',
306
+ $columns: columns.map(c => String(c)),
307
+ };
308
+ },
309
+ exclude(name, expression) {
310
+ return {
311
+ $type: 'EXCLUDE',
312
+ $name: name,
313
+ $columns: [],
314
+ $expression: expression,
315
+ };
316
+ },
264
317
  };
265
318
  }
266
319
  function createColumnRefs(columns) {
@@ -272,6 +325,15 @@ function createColumnRefs(columns) {
272
325
  }
273
326
  return refs;
274
327
  }
328
+ function createIndexTableRefs(columns) {
329
+ const refs = {};
330
+ for (const key of Object.keys(columns)) {
331
+ const col = columns[key];
332
+ const colName = col.$columnName || key;
333
+ refs[key] = createColumnExpr(colName);
334
+ }
335
+ return refs;
336
+ }
275
337
  function createIndexFactory() {
276
338
  const factory = (name) => {
277
339
  const def = {
@@ -331,6 +393,22 @@ function createIndexFactory() {
331
393
  def._opclass = opclass;
332
394
  return Object.assign(this, { _opclass: opclass });
333
395
  },
396
+ ifNotExists() {
397
+ def.ifNotExists = true;
398
+ return Object.assign(this, { ifNotExists: true });
399
+ },
400
+ tableOnly() {
401
+ def.tableOnly = true;
402
+ return Object.assign(this, { tableOnly: true });
403
+ },
404
+ comment(text) {
405
+ def.comment = text;
406
+ return Object.assign(this, { comment: text });
407
+ },
408
+ $id(trackingId) {
409
+ def.trackingId = trackingId;
410
+ return Object.assign(this, { trackingId: trackingId });
411
+ },
334
412
  };
335
413
  return {
336
414
  on(...columns) {
@@ -354,10 +432,11 @@ function createIndexFactory() {
354
432
  const indexFactory = createIndexFactory();
355
433
  function defineTable(name, columns, options) {
356
434
  const columnRefs = createColumnRefs(columns);
435
+ const indexTableRefs = createIndexTableRefs(columns);
357
436
  let resolvedIndexes;
358
437
  if (options?.indexes) {
359
438
  if (typeof options.indexes === 'function') {
360
- const rawIndexes = options.indexes(columnRefs, indexFactory, sql_expressions_1.sqlFunctions);
439
+ const rawIndexes = options.indexes(indexTableRefs, indexFactory, sql_expressions_1.sqlFunctions);
361
440
  resolvedIndexes = rawIndexes.map(normalizeIndexDef);
362
441
  }
363
442
  else {
@@ -375,6 +454,11 @@ function defineTable(name, columns, options) {
375
454
  const constraints = options.checkConstraints(checkTableRefs, checkBuilder);
376
455
  resolvedCheckConstraints = constraints.map(c => ({ expression: c.expression, name: c.name }));
377
456
  }
457
+ let resolvedConstraints;
458
+ if (options?.constraints) {
459
+ const constraintBuilder = createConstraintBuilder();
460
+ resolvedConstraints = options.constraints(columnRefs, constraintBuilder);
461
+ }
378
462
  const definition = {
379
463
  $name: name,
380
464
  $schema: options?.schema,
@@ -382,12 +466,14 @@ function defineTable(name, columns, options) {
382
466
  $primaryKey: options?.primaryKey,
383
467
  $uniqueConstraints: options?.uniqueConstraints,
384
468
  $checkConstraints: resolvedCheckConstraints,
469
+ $constraints: resolvedConstraints,
385
470
  $foreignKeys: options?.foreignKeys,
386
471
  $indexes: resolvedIndexes,
387
472
  $inherits: options?.inherits,
388
473
  $partitionBy: resolvedPartitionBy,
389
474
  $tablespace: options?.tablespace,
390
475
  $withOptions: options?.withOptions,
476
+ $ifNotExists: options?.ifNotExists,
391
477
  $inferSelect: {},
392
478
  $inferInsert: {},
393
479
  toSQL() {
@@ -416,13 +502,16 @@ function normalizeIndexDef(idx) {
416
502
  nulls: idx.nulls,
417
503
  order: idx.order,
418
504
  include: idx.include,
505
+ ifNotExists: idx.ifNotExists,
506
+ tableOnly: idx.tableOnly,
419
507
  };
420
508
  }
421
509
  function generateCreateTableSQL(def) {
422
510
  const tableName = def.$schema
423
511
  ? `${pg_format_1.default.ident(def.$schema)}.${pg_format_1.default.ident(def.$name)}`
424
512
  : pg_format_1.default.ident(def.$name);
425
- const parts = [`CREATE TABLE ${tableName} (`];
513
+ const ifNotExistsClause = def.$ifNotExists ? 'IF NOT EXISTS ' : '';
514
+ const parts = [`CREATE TABLE ${ifNotExistsClause}${tableName} (`];
426
515
  const columnDefs = [];
427
516
  const constraints = [];
428
517
  for (const [colName, colConfig] of Object.entries(def.$columns)) {
@@ -456,6 +545,12 @@ function generateCreateTableSQL(def) {
456
545
  }
457
546
  }
458
547
  }
548
+ if (def.$constraints) {
549
+ for (const c of def.$constraints) {
550
+ const cols = c.$columns.map(col => pg_format_1.default.ident(col)).join(', ');
551
+ constraints.push(`CONSTRAINT ${pg_format_1.default.ident(c.$name)} ${c.$type} (${cols})`);
552
+ }
553
+ }
459
554
  if (def.$foreignKeys) {
460
555
  for (const fk of def.$foreignKeys) {
461
556
  const cols = fk.columns.map(c => pg_format_1.default.ident(c)).join(', ');
@@ -517,7 +612,10 @@ function generateColumnSQL(name, config) {
517
612
  const defaultVal = typeof config.$default === 'function'
518
613
  ? config.$default()
519
614
  : config.$default;
520
- if (typeof defaultVal === 'symbol') {
615
+ if (typeof defaultVal === 'object' && defaultVal !== null && '$isDefault' in defaultVal && '$sql' in defaultVal) {
616
+ parts.push(`DEFAULT ${defaultVal.$sql}`);
617
+ }
618
+ else if (typeof defaultVal === 'symbol') {
521
619
  const symDesc = defaultVal.description || String(defaultVal);
522
620
  if (symDesc.includes('emptyObject')) {
523
621
  parts.push(`DEFAULT '{}'::jsonb`);
@@ -593,7 +691,15 @@ function generateIndexSQL(def) {
593
691
  if (idx.unique) {
594
692
  sql += ' UNIQUE';
595
693
  }
596
- sql += ` INDEX ${pg_format_1.default.ident(indexName)} ON ${tableName}`;
694
+ sql += ' INDEX';
695
+ if (idx.ifNotExists) {
696
+ sql += ' IF NOT EXISTS';
697
+ }
698
+ sql += ` ${pg_format_1.default.ident(indexName)} ON`;
699
+ if (idx.tableOnly) {
700
+ sql += ' ONLY';
701
+ }
702
+ sql += ` ${tableName}`;
597
703
  if (idx.using) {
598
704
  sql += ` USING ${idx.using}`;
599
705
  }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isPoolingEnabled = isPoolingEnabled;
4
4
  exports.toPoolConfig = toPoolConfig;
5
+ exports.isAwsDsqlConfig = isAwsDsqlConfig;
5
6
  const pool_defaults_1 = require("../utils/pool-defaults.cjs");
6
7
  function isPoolingEnabled(config) {
7
8
  return config.pooling !== false;
@@ -10,18 +11,23 @@ function toPoolConfig(config) {
10
11
  const smartDefaults = config.disableSmartDefaults
11
12
  ? { min: 0, max: 10, idleTimeoutMillis: 30000, connectionTimeoutMillis: 0 }
12
13
  : (0, pool_defaults_1.mergeWithDefaults)(config.pool);
14
+ const isAws = !!config.aws;
15
+ const host = isAws ? config.aws.hostname : (config.host || 'localhost');
16
+ const port = config.aws?.port ?? config.port ?? 5432;
17
+ const user = config.aws?.user ?? config.user ?? (isAws ? 'admin' : undefined);
18
+ const ssl = isAws ? (config.aws.ssl ?? true) : config.ssl;
13
19
  const poolConfig = {
14
- host: config.host || 'localhost',
15
- port: config.port || 5432,
20
+ host,
21
+ port,
16
22
  database: config.database,
17
- user: config.user,
23
+ user,
18
24
  password: config.password,
19
25
  min: config.pool?.min ?? smartDefaults.min,
20
26
  max: config.pool?.max ?? smartDefaults.max,
21
27
  idleTimeoutMillis: config.pool?.idleTimeoutMillis ?? smartDefaults.idleTimeoutMillis,
22
28
  connectionTimeoutMillis: config.pool?.connectionTimeoutMillis ?? smartDefaults.connectionTimeoutMillis,
23
29
  application_name: config.pool?.application_name,
24
- ssl: config.pool?.ssl,
30
+ ssl: config.pool?.ssl ?? ssl,
25
31
  allowExitOnIdle: true
26
32
  };
27
33
  if (config.connectionString) {
@@ -38,3 +44,6 @@ function toPoolConfig(config) {
38
44
  }
39
45
  return poolConfig;
40
46
  }
47
+ function isAwsDsqlConfig(config) {
48
+ return !!config.aws?.hostname && !!config.aws?.region;
49
+ }
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getAwsDsqlToken = getAwsDsqlToken;
37
+ exports.clearAwsDsqlToken = clearAwsDsqlToken;
38
+ exports.isAwsDsql = isAwsDsql;
39
+ const node_fs_1 = require("node:fs");
40
+ const node_path_1 = require("node:path");
41
+ const node_os_1 = require("node:os");
42
+ const node_crypto_1 = require("node:crypto");
43
+ const node_constants_1 = require("node:constants");
44
+ const relq_errors_1 = require("../errors/relq-errors.cjs");
45
+ const tokenCache = new Map();
46
+ function getCacheKey(config) {
47
+ const hash = (0, node_crypto_1.createHash)('md5')
48
+ .update(`${config.secretAccessKey ?? ''}-${config.accessKeyId ?? ''}-${config.region}-${config.hostname}`)
49
+ .digest('hex');
50
+ return hash;
51
+ }
52
+ function getTempFolder() {
53
+ return (0, node_path_1.join)((0, node_os_1.tmpdir)(), '.dsql_');
54
+ }
55
+ function isTempFolderAvailable() {
56
+ const tempFolder = getTempFolder();
57
+ try {
58
+ (0, node_fs_1.mkdirSync)(tempFolder, { recursive: true });
59
+ (0, node_fs_1.accessSync)(tempFolder, node_constants_1.F_OK | node_constants_1.R_OK | node_constants_1.W_OK);
60
+ return true;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ function getFromCache(cacheKey) {
67
+ const memoryToken = tokenCache.get(cacheKey);
68
+ if (memoryToken && memoryToken.expiresAt > Date.now()) {
69
+ return memoryToken;
70
+ }
71
+ const envName = `DSQL_TOKEN_${cacheKey}`;
72
+ const envToken = process.env[envName];
73
+ if (envToken) {
74
+ try {
75
+ const parsed = JSON.parse(envToken);
76
+ if (parsed.expiresAt > Date.now()) {
77
+ tokenCache.set(cacheKey, parsed);
78
+ return parsed;
79
+ }
80
+ }
81
+ catch { }
82
+ }
83
+ if (isTempFolderAvailable()) {
84
+ const tokenFile = (0, node_path_1.join)(getTempFolder(), `${cacheKey}.json`);
85
+ if ((0, node_fs_1.existsSync)(tokenFile)) {
86
+ try {
87
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(tokenFile, 'utf8'));
88
+ if (parsed.expiresAt > Date.now()) {
89
+ tokenCache.set(cacheKey, parsed);
90
+ process.env[envName] = JSON.stringify(parsed);
91
+ return parsed;
92
+ }
93
+ }
94
+ catch { }
95
+ }
96
+ }
97
+ return null;
98
+ }
99
+ function saveToCache(cacheKey, token) {
100
+ tokenCache.set(cacheKey, token);
101
+ const envName = `DSQL_TOKEN_${cacheKey}`;
102
+ process.env[envName] = JSON.stringify(token);
103
+ if (isTempFolderAvailable()) {
104
+ const tokenFile = (0, node_path_1.join)(getTempFolder(), `${cacheKey}.json`);
105
+ try {
106
+ (0, node_fs_1.writeFileSync)(tokenFile, JSON.stringify(token));
107
+ }
108
+ catch { }
109
+ }
110
+ }
111
+ let DsqlSigner = null;
112
+ async function loadAwsSdk() {
113
+ if (!DsqlSigner) {
114
+ try {
115
+ const sdk = await Promise.resolve().then(() => __importStar(require('@aws-sdk/dsql-signer')));
116
+ DsqlSigner = sdk.DsqlSigner;
117
+ }
118
+ catch (error) {
119
+ throw new relq_errors_1.RelqConfigError('AWS DSQL requires @aws-sdk/dsql-signer package.\n\n' +
120
+ 'Install it with:\n' +
121
+ ' npm install @aws-sdk/dsql-signer\n' +
122
+ ' # or\n' +
123
+ ' bun add @aws-sdk/dsql-signer', { field: '@aws-sdk/dsql-signer', value: 'not installed' });
124
+ }
125
+ }
126
+ return DsqlSigner;
127
+ }
128
+ async function getAwsDsqlToken(config) {
129
+ const cacheKey = getCacheKey(config);
130
+ const cached = getFromCache(cacheKey);
131
+ if (cached) {
132
+ return cached.token;
133
+ }
134
+ if (!config.useDefaultCredentials && (!config.accessKeyId || !config.secretAccessKey)) {
135
+ throw new relq_errors_1.RelqConfigError('AWS DSQL requires credentials. Either provide accessKeyId + secretAccessKey, ' +
136
+ 'or set useDefaultCredentials: true to use AWS credential chain.', { field: 'aws.credentials', value: 'missing' });
137
+ }
138
+ const SignerClass = await loadAwsSdk();
139
+ const expiresIn = config.tokenExpiresIn ?? 604800;
140
+ const signerConfig = {
141
+ hostname: config.hostname,
142
+ region: config.region,
143
+ expiresIn,
144
+ };
145
+ if (!config.useDefaultCredentials) {
146
+ signerConfig.credentials = {
147
+ accessKeyId: config.accessKeyId,
148
+ secretAccessKey: config.secretAccessKey,
149
+ };
150
+ }
151
+ const signer = new SignerClass(signerConfig);
152
+ const token = await signer.getDbConnectAdminAuthToken();
153
+ const cachedToken = {
154
+ token,
155
+ expiresAt: Date.now() + ((expiresIn - 30) * 1000)
156
+ };
157
+ saveToCache(cacheKey, cachedToken);
158
+ return token;
159
+ }
160
+ function clearAwsDsqlToken(config) {
161
+ const cacheKey = getCacheKey(config);
162
+ tokenCache.delete(cacheKey);
163
+ const envName = `DSQL_TOKEN_${cacheKey}`;
164
+ delete process.env[envName];
165
+ if (isTempFolderAvailable()) {
166
+ const tokenFile = (0, node_path_1.join)(getTempFolder(), `${cacheKey}.json`);
167
+ try {
168
+ if ((0, node_fs_1.existsSync)(tokenFile)) {
169
+ (0, node_fs_1.writeFileSync)(tokenFile, '');
170
+ }
171
+ }
172
+ catch { }
173
+ }
174
+ }
175
+ function isAwsDsql(config) {
176
+ return !!config.aws?.hostname && !!config.aws?.region;
177
+ }