eslint-plugin-slonik 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +368 -0
  3. package/dist/config.cjs +61 -0
  4. package/dist/config.cjs.map +1 -0
  5. package/dist/config.d.cts +192 -0
  6. package/dist/config.d.mts +192 -0
  7. package/dist/config.d.ts +192 -0
  8. package/dist/config.mjs +59 -0
  9. package/dist/config.mjs.map +1 -0
  10. package/dist/index.cjs +27 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.cts +319 -0
  13. package/dist/index.d.mts +319 -0
  14. package/dist/index.d.ts +319 -0
  15. package/dist/index.mjs +20 -0
  16. package/dist/index.mjs.map +1 -0
  17. package/dist/shared/eslint-plugin-slonik.1m1xlVmw.d.cts +611 -0
  18. package/dist/shared/eslint-plugin-slonik.1m1xlVmw.d.mts +611 -0
  19. package/dist/shared/eslint-plugin-slonik.1m1xlVmw.d.ts +611 -0
  20. package/dist/shared/eslint-plugin-slonik.BxexVlk1.cjs +1539 -0
  21. package/dist/shared/eslint-plugin-slonik.BxexVlk1.cjs.map +1 -0
  22. package/dist/shared/eslint-plugin-slonik.C0xTyWZ2.mjs +2866 -0
  23. package/dist/shared/eslint-plugin-slonik.C0xTyWZ2.mjs.map +1 -0
  24. package/dist/shared/eslint-plugin-slonik.DbzoLz5_.mjs +1514 -0
  25. package/dist/shared/eslint-plugin-slonik.DbzoLz5_.mjs.map +1 -0
  26. package/dist/shared/eslint-plugin-slonik.rlOTrCdf.cjs +2929 -0
  27. package/dist/shared/eslint-plugin-slonik.rlOTrCdf.cjs.map +1 -0
  28. package/dist/workers/check-sql.worker.cjs +2436 -0
  29. package/dist/workers/check-sql.worker.cjs.map +1 -0
  30. package/dist/workers/check-sql.worker.d.cts +171 -0
  31. package/dist/workers/check-sql.worker.d.mts +171 -0
  32. package/dist/workers/check-sql.worker.d.ts +171 -0
  33. package/dist/workers/check-sql.worker.mjs +2412 -0
  34. package/dist/workers/check-sql.worker.mjs.map +1 -0
  35. package/package.json +103 -0
@@ -0,0 +1,2412 @@
1
+ import { g as getOrSetFromMapWithEnabled, D as DuplicateColumnsError, i as isPostgresError, P as PostgresError, d as defaultTypesMap, a as groupBy, t as toCase, f as fmap, b as assertNever, n as normalizeIndent, c as getConnectionStrategyByRuleOptionConnection, p as parseConnection, m as mapConnectionOptionsToString, e as getMigrationDatabaseMetadata, h as getDatabaseName, j as DEFAULT_CONNECTION_URL, k as isWatchMigrationsDirEnabled, l as initDatabase, r as runMigrations, I as InternalError } from '../shared/eslint-plugin-slonik.C0xTyWZ2.mjs';
2
+ import { either } from 'fp-ts';
3
+ import * as parser from 'libpg-query';
4
+ import path from 'path';
5
+ import { runAsWorker } from 'synckit';
6
+ import { match } from 'ts-pattern';
7
+ import postgres from 'postgres';
8
+ import 'fp-ts/lib/Either.js';
9
+ import { pipe } from 'fp-ts/lib/function.js';
10
+ import * as O from 'fp-ts/lib/Option.js';
11
+ import * as TE from 'fp-ts/lib/TaskEither.js';
12
+ import * as J from 'fp-ts/lib/Json.js';
13
+ import chokidar from 'chokidar';
14
+ import 'crypto';
15
+ import 'fs';
16
+ import '@typescript-eslint/utils';
17
+ import 'pg-connection-string';
18
+
19
+ var AExprKind = /* @__PURE__ */ ((AExprKind2) => {
20
+ AExprKind2["A_EXPR_KIND_UNDEFINED"] = "A_EXPR_KIND_UNDEFINED";
21
+ AExprKind2["AEXPR_OP"] = "AEXPR_OP";
22
+ AExprKind2["AEXPR_OP_ANY"] = "AEXPR_OP_ANY";
23
+ AExprKind2["AEXPR_OP_ALL"] = "AEXPR_OP_ALL";
24
+ AExprKind2["AEXPR_DISTINCT"] = "AEXPR_DISTINCT";
25
+ AExprKind2["AEXPR_NOT_DISTINCT"] = "AEXPR_NOT_DISTINCT";
26
+ AExprKind2["AEXPR_NULLIF"] = "AEXPR_NULLIF";
27
+ AExprKind2["AEXPR_IN"] = "AEXPR_IN";
28
+ AExprKind2["AEXPR_LIKE"] = "AEXPR_LIKE";
29
+ AExprKind2["AEXPR_ILIKE"] = "AEXPR_ILIKE";
30
+ AExprKind2["AEXPR_SIMILAR"] = "AEXPR_SIMILAR";
31
+ AExprKind2["AEXPR_BETWEEN"] = "AEXPR_BETWEEN";
32
+ AExprKind2["AEXPR_NOT_BETWEEN"] = "AEXPR_NOT_BETWEEN";
33
+ AExprKind2["AEXPR_BETWEEN_SYM"] = "AEXPR_BETWEEN_SYM";
34
+ AExprKind2["AEXPR_NOT_BETWEEN_SYM"] = "AEXPR_NOT_BETWEEN_SYM";
35
+ AExprKind2["UNRECOGNIZED"] = "UNRECOGNIZED";
36
+ return AExprKind2;
37
+ })(AExprKind || {});
38
+ var BoolExprType = /* @__PURE__ */ ((BoolExprType2) => {
39
+ BoolExprType2["BOOL_EXPR_TYPE_UNDEFINED"] = "BOOL_EXPR_TYPE_UNDEFINED";
40
+ BoolExprType2["AND_EXPR"] = "AND_EXPR";
41
+ BoolExprType2["OR_EXPR"] = "OR_EXPR";
42
+ BoolExprType2["NOT_EXPR"] = "NOT_EXPR";
43
+ BoolExprType2["UNRECOGNIZED"] = "UNRECOGNIZED";
44
+ return BoolExprType2;
45
+ })(BoolExprType || {});
46
+ var SubLinkType = /* @__PURE__ */ ((SubLinkType2) => {
47
+ SubLinkType2["SUB_LINK_TYPE_UNDEFINED"] = "SUB_LINK_TYPE_UNDEFINED";
48
+ SubLinkType2["EXISTS_SUBLINK"] = "EXISTS_SUBLINK";
49
+ SubLinkType2["ALL_SUBLINK"] = "ALL_SUBLINK";
50
+ SubLinkType2["ANY_SUBLINK"] = "ANY_SUBLINK";
51
+ SubLinkType2["ROWCOMPARE_SUBLINK"] = "ROWCOMPARE_SUBLINK";
52
+ SubLinkType2["EXPR_SUBLINK"] = "EXPR_SUBLINK";
53
+ SubLinkType2["MULTIEXPR_SUBLINK"] = "MULTIEXPR_SUBLINK";
54
+ SubLinkType2["ARRAY_SUBLINK"] = "ARRAY_SUBLINK";
55
+ SubLinkType2["CTE_SUBLINK"] = "CTE_SUBLINK";
56
+ SubLinkType2["UNRECOGNIZED"] = "UNRECOGNIZED";
57
+ return SubLinkType2;
58
+ })(SubLinkType || {});
59
+ var NullTestType = /* @__PURE__ */ ((NullTestType2) => {
60
+ NullTestType2["NULL_TEST_TYPE_UNDEFINED"] = "NULL_TEST_TYPE_UNDEFINED";
61
+ NullTestType2["IS_NULL"] = "IS_NULL";
62
+ NullTestType2["IS_NOT_NULL"] = "IS_NOT_NULL";
63
+ NullTestType2["UNRECOGNIZED"] = "UNRECOGNIZED";
64
+ return NullTestType2;
65
+ })(NullTestType || {});
66
+ var JoinType = /* @__PURE__ */ ((JoinType2) => {
67
+ JoinType2["JOIN_TYPE_UNDEFINED"] = "JOIN_TYPE_UNDEFINED";
68
+ JoinType2["JOIN_INNER"] = "JOIN_INNER";
69
+ JoinType2["JOIN_LEFT"] = "JOIN_LEFT";
70
+ JoinType2["JOIN_FULL"] = "JOIN_FULL";
71
+ JoinType2["JOIN_RIGHT"] = "JOIN_RIGHT";
72
+ JoinType2["JOIN_SEMI"] = "JOIN_SEMI";
73
+ JoinType2["JOIN_ANTI"] = "JOIN_ANTI";
74
+ JoinType2["JOIN_UNIQUE_OUTER"] = "JOIN_UNIQUE_OUTER";
75
+ JoinType2["JOIN_UNIQUE_INNER"] = "JOIN_UNIQUE_INNER";
76
+ JoinType2["UNRECOGNIZED"] = "UNRECOGNIZED";
77
+ return JoinType2;
78
+ })(JoinType || {});
79
+
80
+ function isColumnStarRef(fields) {
81
+ return isSingleCell(fields) && fields[0]?.A_Star !== void 0;
82
+ }
83
+ function isColumnTableStarRef(fields) {
84
+ return isTuple(fields) && fields[0].String !== void 0 && fields[1].A_Star !== void 0;
85
+ }
86
+ function isColumnUnknownRef(fields) {
87
+ return isSingleCell(fields) && fields[0].String !== void 0;
88
+ }
89
+ function isColumnTableColumnRef(fields) {
90
+ return isTuple(fields) && fields[0].String !== void 0 && fields[1].String !== void 0;
91
+ }
92
+ function isSingleCell(arr) {
93
+ return arr.length === 1;
94
+ }
95
+ function isTuple(arr) {
96
+ return arr.length === 2;
97
+ }
98
+
99
+ function getSources({
100
+ select,
101
+ prevSources,
102
+ nonNullableColumns,
103
+ pgColsBySchemaAndTableName,
104
+ relations
105
+ }) {
106
+ const relationsByAlias = /* @__PURE__ */ new Map();
107
+ const relationsByRelName = /* @__PURE__ */ new Map();
108
+ for (const rel of relations) {
109
+ const key = rel.alias ?? rel.joinRelName;
110
+ if (key) {
111
+ relationsByAlias.set(key, rel);
112
+ }
113
+ if (!relationsByRelName.has(rel.relName)) {
114
+ relationsByRelName.set(rel.relName, []);
115
+ }
116
+ relationsByRelName.get(rel.relName).push(rel);
117
+ }
118
+ const tableToSchema = /* @__PURE__ */ new Map();
119
+ const publicCols = pgColsBySchemaAndTableName.get("public");
120
+ if (publicCols) {
121
+ for (const tableName of publicCols.keys()) {
122
+ tableToSchema.set(tableName, "public");
123
+ }
124
+ }
125
+ for (const [schemaName, cols] of pgColsBySchemaAndTableName) {
126
+ if (schemaName === "public") break;
127
+ for (const tableName of cols.keys()) {
128
+ if (!tableToSchema.has(tableName)) {
129
+ tableToSchema.set(tableName, schemaName);
130
+ }
131
+ }
132
+ }
133
+ function getColumnCTEs(ctes2) {
134
+ const map = /* @__PURE__ */ new Map();
135
+ for (const cte of ctes2) {
136
+ if (cte.CommonTableExpr?.ctequery?.SelectStmt === void 0) continue;
137
+ if (cte.CommonTableExpr?.ctename === void 0) continue;
138
+ const resolver = getSources({
139
+ pgColsBySchemaAndTableName,
140
+ prevSources,
141
+ nonNullableColumns,
142
+ relations,
143
+ select: cte.CommonTableExpr.ctequery.SelectStmt
144
+ });
145
+ map.set(cte.CommonTableExpr.ctename, resolver);
146
+ }
147
+ return map;
148
+ }
149
+ const ctes = getColumnCTEs(select.withClause?.ctes ?? []);
150
+ function resolveRangeVarSchema(node) {
151
+ switch (true) {
152
+ case node.schemaname !== void 0:
153
+ return node.schemaname;
154
+ case pgColsBySchemaAndTableName.get("public")?.has(node.relname):
155
+ return "public";
156
+ default:
157
+ for (const [schemaName, cols] of pgColsBySchemaAndTableName) {
158
+ if (cols.has(node.relname)) {
159
+ return schemaName;
160
+ }
161
+ }
162
+ return "public";
163
+ }
164
+ }
165
+ function getNodeColumnAndSources(node) {
166
+ if (node.RangeVar !== void 0) {
167
+ const cteResolver = ctes.get(node.RangeVar.relname);
168
+ if (cteResolver !== void 0) {
169
+ return [{ kind: "cte", name: node.RangeVar.relname, sources: cteResolver }];
170
+ }
171
+ const schemaName = resolveRangeVarSchema(node.RangeVar);
172
+ const realTableName = node.RangeVar.relname;
173
+ const tableName = node.RangeVar.alias?.aliasname ?? realTableName;
174
+ const tableColsArray = pgColsBySchemaAndTableName.get(schemaName)?.get(realTableName) ?? [];
175
+ const tableSource = {
176
+ kind: "table",
177
+ schemaName,
178
+ original: realTableName,
179
+ name: tableName,
180
+ alias: node.RangeVar.alias?.aliasname,
181
+ columns: /* @__PURE__ */ new Map()
182
+ };
183
+ for (const col of tableColsArray) {
184
+ tableSource.columns.set(col.colName, resolveColumn(col, tableSource));
185
+ }
186
+ return [tableSource];
187
+ }
188
+ const sourcesArr = [];
189
+ if (node.JoinExpr?.larg !== void 0) {
190
+ sourcesArr.push(...getNodeColumnAndSources(node.JoinExpr.larg));
191
+ }
192
+ if (node.JoinExpr?.rarg !== void 0) {
193
+ sourcesArr.push(...getNodeColumnAndSources(node.JoinExpr.rarg));
194
+ }
195
+ if (node.RangeSubselect?.subquery?.SelectStmt?.fromClause !== void 0) {
196
+ const combinedPrevSources = new Map([
197
+ ...prevSources?.entries() ?? [],
198
+ ...sourcesArr.map((x) => [x.name, x])
199
+ ]);
200
+ sourcesArr.push({
201
+ kind: "subselect",
202
+ name: node.RangeSubselect.alias?.aliasname ?? "subselect",
203
+ sources: getSources({
204
+ nonNullableColumns,
205
+ pgColsBySchemaAndTableName,
206
+ relations,
207
+ prevSources: combinedPrevSources,
208
+ select: node.RangeSubselect.subquery.SelectStmt
209
+ })
210
+ });
211
+ }
212
+ return sourcesArr;
213
+ }
214
+ function getColumnSources(stmt) {
215
+ const fromClauseSources = [];
216
+ for (const node of stmt.fromClause ?? []) {
217
+ const nodes = getNodeColumnAndSources(node);
218
+ for (const nodeSource of nodes) {
219
+ fromClauseSources.push([nodeSource.name, nodeSource]);
220
+ }
221
+ }
222
+ return new Map(fromClauseSources);
223
+ }
224
+ const sources = new Map([
225
+ ...prevSources?.entries() ?? [],
226
+ ...getColumnSources(select).entries()
227
+ ]);
228
+ const cachedColumnsMap = /* @__PURE__ */ new WeakMap();
229
+ function getSourceColumns(source) {
230
+ if (cachedColumnsMap.has(source)) {
231
+ return cachedColumnsMap.get(source);
232
+ }
233
+ let result = [];
234
+ switch (source.kind) {
235
+ case "table":
236
+ result = Array.from(source.columns.values()).map((col) => ({
237
+ column: col,
238
+ source
239
+ }));
240
+ break;
241
+ case "cte":
242
+ case "subselect":
243
+ result = [];
244
+ break;
245
+ }
246
+ cachedColumnsMap.set(source, result);
247
+ return result;
248
+ }
249
+ function getAllResolvedColumns() {
250
+ const all = [];
251
+ for (const source of sources.values()) {
252
+ all.push(...getSourceColumns(source));
253
+ }
254
+ return all;
255
+ }
256
+ const allResolved = getAllResolvedColumns();
257
+ const columnIndex = /* @__PURE__ */ new Map();
258
+ const unknownColumnIndex = /* @__PURE__ */ new Map();
259
+ for (const entry of allResolved) {
260
+ const key = `${entry.source.name}.${entry.column.column.colName}`;
261
+ columnIndex.set(key, entry);
262
+ const unknownKey = entry.column.column.colName;
263
+ if (!unknownColumnIndex.has(unknownKey)) {
264
+ unknownColumnIndex.set(unknownKey, []);
265
+ }
266
+ unknownColumnIndex.get(unknownKey).push(entry);
267
+ }
268
+ function getColumnByTableAndColumnName(p) {
269
+ const source = sources.get(p.table);
270
+ if (!source) return null;
271
+ switch (source.kind) {
272
+ case "table":
273
+ return source.columns.get(p.column) || null;
274
+ default:
275
+ return null;
276
+ }
277
+ }
278
+ function getResolvedColumnsInTable(sourceName) {
279
+ const source = sources.get(sourceName);
280
+ if (!source) return [];
281
+ return getSourceColumns(source).map((x) => x.column);
282
+ }
283
+ function getNestedResolvedTargetField(field) {
284
+ switch (field.kind) {
285
+ case "column": {
286
+ const key = `${field.table}.${field.column}`;
287
+ if (columnIndex.has(key)) {
288
+ return columnIndex.get(key)?.column ?? null;
289
+ }
290
+ break;
291
+ }
292
+ case "unknown": {
293
+ if (unknownColumnIndex.has(field.field)) {
294
+ const candidates = unknownColumnIndex.get(field.field);
295
+ if (candidates.length > 0) return candidates[0]?.column ?? null;
296
+ }
297
+ break;
298
+ }
299
+ }
300
+ for (const source of sources.values()) {
301
+ switch (source.kind) {
302
+ case "cte":
303
+ case "subselect": {
304
+ const nested = source.sources.getNestedResolvedTargetField(field);
305
+ if (nested) {
306
+ return {
307
+ ...nested,
308
+ isNotNull: nested.isNotNull && !checkIsNullableDueToRelation(source.name)
309
+ };
310
+ }
311
+ break;
312
+ }
313
+ case "table": {
314
+ const key = field.kind === "column" ? field.column : field.field;
315
+ const column = source.columns.get(key);
316
+ if (column) return column;
317
+ break;
318
+ }
319
+ }
320
+ }
321
+ return null;
322
+ }
323
+ function getColumnsByTargetField(field) {
324
+ switch (field.kind) {
325
+ case "column": {
326
+ const result = getColumnByTableAndColumnName(field);
327
+ if (result !== null) {
328
+ return [result];
329
+ }
330
+ for (const source of sources.values()) {
331
+ switch (source.kind) {
332
+ case "subselect": {
333
+ const column = source.sources.getNestedResolvedTargetField(field);
334
+ if (column) {
335
+ const isNullableDueToRelation = checkIsNullableDueToRelation(source.name);
336
+ if (isNullableDueToRelation && column.isNotNull) {
337
+ return [{ ...column, isNotNull: false }];
338
+ }
339
+ return [column];
340
+ }
341
+ break;
342
+ }
343
+ }
344
+ }
345
+ return null;
346
+ }
347
+ case "unknown": {
348
+ const source = sources.get(field.field);
349
+ if (source !== void 0) {
350
+ return getSourceColumns(source).map((x) => x.column);
351
+ }
352
+ const foundColumn = getNestedResolvedTargetField(field);
353
+ if (foundColumn) {
354
+ return [foundColumn];
355
+ }
356
+ for (const source2 of sources.values()) {
357
+ switch (source2.kind) {
358
+ case "subselect": {
359
+ const columns = source2.sources.getColumnsByTargetField(field);
360
+ if (columns) {
361
+ const isNullableDueToRelation = checkIsNullableDueToRelation(source2.name);
362
+ if (isNullableDueToRelation) {
363
+ return columns.map((col) => col.isNotNull ? { ...col, isNotNull: false } : col);
364
+ }
365
+ return columns;
366
+ }
367
+ break;
368
+ }
369
+ }
370
+ }
371
+ return null;
372
+ }
373
+ }
374
+ }
375
+ function checkIsNullableDueToRelation(key) {
376
+ const rel = relationsByAlias.get(key);
377
+ if (rel !== void 0) {
378
+ switch (rel.joinType) {
379
+ case JoinType.JOIN_LEFT:
380
+ case JoinType.JOIN_FULL:
381
+ return true;
382
+ case JoinType.JOIN_TYPE_UNDEFINED:
383
+ case JoinType.JOIN_INNER:
384
+ case JoinType.JOIN_RIGHT:
385
+ case JoinType.JOIN_SEMI:
386
+ case JoinType.JOIN_ANTI:
387
+ case JoinType.JOIN_UNIQUE_OUTER:
388
+ case JoinType.JOIN_UNIQUE_INNER:
389
+ case JoinType.UNRECOGNIZED:
390
+ return false;
391
+ default:
392
+ return assertNever(rel.joinType);
393
+ }
394
+ }
395
+ for (const relation of relationsByRelName.get(key) ?? []) {
396
+ switch (relation.joinType) {
397
+ case JoinType.JOIN_RIGHT:
398
+ case JoinType.JOIN_FULL:
399
+ return true;
400
+ case JoinType.JOIN_TYPE_UNDEFINED:
401
+ case JoinType.JOIN_INNER:
402
+ case JoinType.JOIN_LEFT:
403
+ case JoinType.JOIN_SEMI:
404
+ case JoinType.JOIN_ANTI:
405
+ case JoinType.JOIN_UNIQUE_OUTER:
406
+ case JoinType.JOIN_UNIQUE_INNER:
407
+ case JoinType.UNRECOGNIZED:
408
+ return false;
409
+ default:
410
+ return assertNever(relation.joinType);
411
+ }
412
+ }
413
+ return false;
414
+ }
415
+ function resolveColumn(col, source) {
416
+ const keyForNullability = source.alias ? source.alias : source.original;
417
+ const isNullableDueToRelation = checkIsNullableDueToRelation(keyForNullability);
418
+ const isNotNullBasedOnAST = nonNullableColumns.has(col.colName) || nonNullableColumns.has(`${source.name}.${col.colName}`);
419
+ const isNotNullInTable = col.colNotNull;
420
+ const isNonNullable = isNotNullBasedOnAST || isNotNullInTable && !isNullableDueToRelation;
421
+ return { column: col, isNotNull: isNonNullable };
422
+ }
423
+ return {
424
+ getNodeColumnAndSources,
425
+ getResolvedColumnsInTable,
426
+ getAllResolvedColumns,
427
+ getColumnsByTargetField,
428
+ getNestedResolvedTargetField,
429
+ sources
430
+ };
431
+ }
432
+
433
+ const nonNullFunctions = /* @__PURE__ */ new Set([
434
+ "count",
435
+ "now",
436
+ "abs",
437
+ "ceil",
438
+ "floor",
439
+ "round",
440
+ "sqrt",
441
+ "cbrt",
442
+ "exp",
443
+ "log",
444
+ "log10",
445
+ "sin",
446
+ "cos",
447
+ "tan",
448
+ "asin",
449
+ "acos",
450
+ "atan",
451
+ "radians",
452
+ "degrees",
453
+ "length",
454
+ "trim",
455
+ "lower",
456
+ "upper",
457
+ "ascii",
458
+ "concat",
459
+ "concat_ws",
460
+ "lpad",
461
+ "rpad",
462
+ "initcap",
463
+ "left",
464
+ "right",
465
+ "cdat",
466
+ "chr",
467
+ "strpos",
468
+ "substr",
469
+ "translate",
470
+ "current_date",
471
+ "current_time",
472
+ "current_timestamp",
473
+ "localtime",
474
+ "localtimestamp",
475
+ "uuid_generate_v1",
476
+ "uuid_generate_v4",
477
+ "pi",
478
+ "random",
479
+ "exists",
480
+ "row_number",
481
+ "current_schema",
482
+ "current_schemas",
483
+ "inet_server_addr",
484
+ "inet_server_port",
485
+ "isfinite",
486
+ "isnan",
487
+ "pg_backend_pid",
488
+ "pg_blocking_pids",
489
+ "pg_cancel_backend",
490
+ "pg_is_in_recovery",
491
+ "pg_postmaster_start_time",
492
+ "pg_relation_size",
493
+ "pg_total_relation_size",
494
+ "timeofday",
495
+ "similar_to_escape"
496
+ ]);
497
+ function concatStringNodes$1(nodes) {
498
+ return nodes?.map((x) => x.String?.sval).filter(Boolean).join(".") ?? "";
499
+ }
500
+ function isColumnNonNullable(val, root) {
501
+ if (val === void 0) {
502
+ return false;
503
+ }
504
+ if (val.NullTest) {
505
+ return true;
506
+ }
507
+ if (val.BoolExpr?.boolop === BoolExprType.NOT_EXPR) {
508
+ return true;
509
+ }
510
+ if (val.A_Const) {
511
+ return val.A_Const.isnull !== true;
512
+ }
513
+ if (val.FuncCall) {
514
+ const functionName = concatStringNodes$1(val.FuncCall.funcname);
515
+ return nonNullFunctions.has(functionName.toLowerCase());
516
+ }
517
+ if (val.TypeCast?.arg) {
518
+ return isColumnNonNullable(val.TypeCast.arg, root);
519
+ }
520
+ if (val.SubLink) {
521
+ switch (val.SubLink.subLinkType) {
522
+ case SubLinkType.EXISTS_SUBLINK:
523
+ return true;
524
+ case SubLinkType.ARRAY_SUBLINK:
525
+ return true;
526
+ // while the array itself can be non-nullable, the elements can be nullable
527
+ case SubLinkType.ALL_SUBLINK:
528
+ case SubLinkType.ANY_SUBLINK:
529
+ case SubLinkType.ROWCOMPARE_SUBLINK:
530
+ case SubLinkType.EXPR_SUBLINK:
531
+ case SubLinkType.MULTIEXPR_SUBLINK:
532
+ case SubLinkType.CTE_SUBLINK:
533
+ return isColumnNonNullable(val.SubLink.subselect, root);
534
+ case SubLinkType.SUB_LINK_TYPE_UNDEFINED:
535
+ case SubLinkType.UNRECOGNIZED:
536
+ return false;
537
+ default:
538
+ assertNever(val.SubLink.subLinkType);
539
+ }
540
+ }
541
+ if (val.A_Expr?.kind === AExprKind.AEXPR_SIMILAR) {
542
+ return true;
543
+ }
544
+ if (val.A_Expr?.kind === AExprKind.AEXPR_LIKE) {
545
+ return true;
546
+ }
547
+ if (val.A_Expr?.kind === AExprKind.AEXPR_OP) {
548
+ return isColumnNonNullable(val.A_Expr.lexpr, root) && isColumnNonNullable(val.A_Expr.rexpr, root);
549
+ }
550
+ if (val.CaseExpr) {
551
+ for (const when of val.CaseExpr.args) {
552
+ if (!isColumnNonNullable(when.CaseWhen?.result, root)) {
553
+ return false;
554
+ }
555
+ }
556
+ if (val.CaseExpr.defresult && !isColumnNonNullable(val.CaseExpr.defresult, root)) {
557
+ return false;
558
+ }
559
+ return true;
560
+ }
561
+ if (val.ColumnRef) {
562
+ const refColumnName = concatStringNodes$1(val.ColumnRef.fields);
563
+ for (const stmt of root.stmts) {
564
+ if (stmt?.stmt?.SelectStmt?.whereClause) {
565
+ const whereClause = stmt.stmt.SelectStmt.whereClause;
566
+ const whereClauseColumnName = concatStringNodes$1(
567
+ whereClause.NullTest?.arg?.ColumnRef?.fields
568
+ );
569
+ if (whereClause.NullTest?.nulltesttype === NullTestType.IS_NOT_NULL && whereClauseColumnName === refColumnName) {
570
+ return true;
571
+ }
572
+ }
573
+ }
574
+ }
575
+ if (val.CoalesceExpr) {
576
+ for (const arg of val.CoalesceExpr.args) {
577
+ if (isColumnNonNullable(arg, root)) {
578
+ return true;
579
+ }
580
+ }
581
+ }
582
+ if (val.A_ArrayExpr) {
583
+ return true;
584
+ }
585
+ if (val.SelectStmt) {
586
+ const nonNullableColumnsInSubStmt = getNonNullableColumnsInSelectStmt(val.SelectStmt, root);
587
+ return Array.from(nonNullableColumnsInSubStmt.values()).some(Boolean);
588
+ }
589
+ return false;
590
+ }
591
+ function getNodeName(node) {
592
+ if (node?.ColumnRef !== void 0) {
593
+ return concatStringNodes$1(node.ColumnRef.fields);
594
+ }
595
+ if (node?.NullTest) {
596
+ return getNodeName(node.NullTest.arg);
597
+ }
598
+ if (node?.A_Const?.boolval !== void 0) {
599
+ return "bool";
600
+ }
601
+ if (node?.TypeCast !== void 0) {
602
+ const typeName = concatStringNodes$1(node.TypeCast.typeName?.names);
603
+ if (typeName === "pg_catalog.interval") {
604
+ return "interval";
605
+ }
606
+ if (node.TypeCast.arg) {
607
+ return getNodeName(node.TypeCast.arg);
608
+ }
609
+ return typeName.replace(/^pg_catalog\./, "");
610
+ }
611
+ if (node?.FuncCall?.funcname !== void 0) {
612
+ return concatStringNodes$1(node.FuncCall.funcname);
613
+ }
614
+ if (node?.SubLink?.subLinkType === SubLinkType.EXISTS_SUBLINK) {
615
+ return "exists";
616
+ }
617
+ if (node?.SubLink?.subLinkType === SubLinkType.ARRAY_SUBLINK) {
618
+ return "array";
619
+ }
620
+ if (node?.SubLink?.subselect?.SelectStmt?.targetList !== void 0) {
621
+ const subSelectTargetList = node.SubLink.subselect.SelectStmt.targetList;
622
+ if (subSelectTargetList?.[0].ResTarget !== void 0) {
623
+ return getTargetName(subSelectTargetList[0].ResTarget);
624
+ }
625
+ }
626
+ if (node?.A_ArrayExpr !== void 0) {
627
+ return "array";
628
+ }
629
+ if (node?.CaseExpr !== void 0) {
630
+ return "case";
631
+ }
632
+ if (node?.CoalesceExpr !== void 0) {
633
+ return "coalesce";
634
+ }
635
+ return "?column?";
636
+ }
637
+ function getTargetName(target) {
638
+ return target.name ?? getNodeName(target.val);
639
+ }
640
+ function getNonNullableColumnsInSelectStmt(stmt, root) {
641
+ const nonNullableColumns = /* @__PURE__ */ new Set();
642
+ const targetList = [
643
+ ...stmt.targetList ?? [],
644
+ ...stmt.larg?.targetList ?? [],
645
+ ...stmt.rarg?.targetList ?? []
646
+ ];
647
+ const targetNames = /* @__PURE__ */ new Set();
648
+ for (const target of targetList) {
649
+ if (target.ResTarget) {
650
+ targetNames.add(getTargetName(target.ResTarget));
651
+ }
652
+ if (target.ResTarget && isColumnNonNullable(target.ResTarget.val, root)) {
653
+ nonNullableColumns.add(getTargetName(target.ResTarget));
654
+ }
655
+ }
656
+ if (stmt.whereClause) {
657
+ if (stmt.whereClause.NullTest?.nulltesttype === NullTestType.IS_NOT_NULL) {
658
+ const colRef = stmt.whereClause.NullTest.arg?.ColumnRef;
659
+ const whereClauseName = concatStringNodes$1(colRef?.fields);
660
+ switch (true) {
661
+ case targetNames.has(whereClauseName):
662
+ nonNullableColumns.add(whereClauseName);
663
+ break;
664
+ case targetNames.has(colRef?.fields?.at(-1)?.String?.sval ?? ""):
665
+ nonNullableColumns.add(colRef?.fields?.at(-1)?.String?.sval ?? "");
666
+ break;
667
+ default:
668
+ nonNullableColumns.add(whereClauseName);
669
+ break;
670
+ }
671
+ }
672
+ if (stmt.whereClause.BoolExpr?.boolop === BoolExprType.AND_EXPR) {
673
+ for (const arg of stmt.whereClause.BoolExpr.args) {
674
+ if (arg.NullTest?.nulltesttype === NullTestType.IS_NOT_NULL && arg.NullTest.arg?.ColumnRef?.fields) {
675
+ nonNullableColumns.add(concatStringNodes$1(arg.NullTest.arg.ColumnRef.fields));
676
+ }
677
+ }
678
+ }
679
+ }
680
+ return nonNullableColumns;
681
+ }
682
+ function getNonNullableColumns(root) {
683
+ for (const stmt of root.stmts) {
684
+ if (stmt.stmt?.SelectStmt) {
685
+ return getNonNullableColumnsInSelectStmt(stmt.stmt.SelectStmt, root);
686
+ }
687
+ }
688
+ return /* @__PURE__ */ new Set();
689
+ }
690
+
691
+ function getRelationsWithJoins(parsed) {
692
+ const results = /* @__PURE__ */ new Map();
693
+ const stmt = parsed.stmts[0];
694
+ if (stmt === void 0 || stmt?.stmt?.SelectStmt?.fromClause === void 0) {
695
+ return results;
696
+ }
697
+ for (const fromClause of stmt.stmt.SelectStmt.fromClause) {
698
+ if (fromClause.JoinExpr !== void 0) {
699
+ const { relName, joins } = recursiveTraverseJoins([], fromClause.JoinExpr);
700
+ results.set(relName, joins);
701
+ }
702
+ }
703
+ return results;
704
+ }
705
+ function recursiveGetJoinName(joinExpr) {
706
+ if (joinExpr.rarg?.JoinExpr !== void 0) {
707
+ return recursiveGetJoinName(joinExpr.rarg.JoinExpr);
708
+ }
709
+ return joinExpr.rarg?.RangeVar?.relname ?? joinExpr.rarg?.RangeSubselect?.alias?.aliasname;
710
+ }
711
+ function recursiveTraverseJoins(joins, joinExpr) {
712
+ const joinName = recursiveGetJoinName(joinExpr);
713
+ const aliasName = joinExpr.rarg?.RangeVar?.alias?.aliasname;
714
+ if (joinName === void 0) {
715
+ throw new Error("joinName is undefined");
716
+ }
717
+ const join = { type: joinExpr.jointype, name: joinName, alias: aliasName };
718
+ if (joinExpr.larg?.JoinExpr !== void 0) {
719
+ return recursiveTraverseJoins([join, ...joins], joinExpr.larg?.JoinExpr);
720
+ }
721
+ if (joinExpr.rarg?.JoinExpr !== void 0) {
722
+ return recursiveTraverseJoins([join, ...joins], joinExpr.rarg?.JoinExpr);
723
+ }
724
+ const relName = joinExpr.larg?.RangeVar?.relname ?? joinExpr.larg?.RangeFunction?.alias?.aliasname ?? joinExpr.rarg?.RangeVar?.relname ?? joinExpr.rarg?.RangeFunction?.alias?.aliasname;
725
+ if (relName === void 0) {
726
+ throw new Error("relName is undefined");
727
+ }
728
+ return { relName, joins: [join, ...joins] };
729
+ }
730
+ function flattenRelationsWithJoinsMap(relationsWithJoinsMap) {
731
+ const result = [];
732
+ relationsWithJoinsMap.forEach((joins, relName) => {
733
+ joins.forEach((join) => {
734
+ result.push({ relName, joinType: join.type, joinRelName: join.name, alias: join.alias });
735
+ });
736
+ });
737
+ return result;
738
+ }
739
+
740
+ function getASTDescription(params) {
741
+ const select = params.parsed.stmts[0]?.stmt?.SelectStmt;
742
+ if (select === void 0) {
743
+ return {
744
+ map: /* @__PURE__ */ new Map(),
745
+ meta: {
746
+ relations: [],
747
+ nonNullableColumns: /* @__PURE__ */ new Set()
748
+ }
749
+ };
750
+ }
751
+ const nonNullableColumns = getNonNullableColumns(params.parsed);
752
+ const relations = flattenRelationsWithJoinsMap(getRelationsWithJoins(params.parsed));
753
+ function getTypeByOid(oid) {
754
+ const name = params.pgTypes.get(oid)?.name;
755
+ if (name === void 0) {
756
+ return { isArray: false, override: false, value: "unknown" };
757
+ }
758
+ const { isArray, typeName } = name.startsWith("_") ? { isArray: true, typeName: name.slice(1) } : { isArray: false, typeName: name };
759
+ const resolvedTypeName = params.typesMap.get(typeName) ?? { override: false, value: "unknown" };
760
+ return {
761
+ isArray,
762
+ override: resolvedTypeName.override,
763
+ value: resolvedTypeName.value
764
+ };
765
+ }
766
+ const context = {
767
+ ...params,
768
+ nonNullableColumns,
769
+ relations,
770
+ resolver: getSources({
771
+ relations,
772
+ select,
773
+ nonNullableColumns,
774
+ pgColsBySchemaAndTableName: params.pgColsBySchemaAndTableName
775
+ }),
776
+ select,
777
+ resolved: /* @__PURE__ */ new WeakMap(),
778
+ toTypeScriptType: (p) => {
779
+ if ("name" in p) {
780
+ return {
781
+ kind: "type",
782
+ value: params.typesMap.get(p.name)?.value ?? "unknown",
783
+ type: p.name
784
+ };
785
+ }
786
+ const pgType = params.pgTypes.get(p.oid);
787
+ const typeByOid = getTypeByOid(p.oid);
788
+ if (typeByOid.override) {
789
+ const baseType = {
790
+ kind: "type",
791
+ value: typeByOid.value,
792
+ type: pgType?.name ?? "unknown"
793
+ };
794
+ return typeByOid.isArray ? { kind: "array", value: baseType } : baseType;
795
+ }
796
+ const typeByBaseOid = fmap(p.baseOid, getTypeByOid);
797
+ if (typeByBaseOid?.override === true) {
798
+ const baseType = {
799
+ kind: "type",
800
+ value: typeByBaseOid.value,
801
+ type: params.pgTypes.get(p.baseOid)?.name ?? "unknown"
802
+ };
803
+ return typeByBaseOid.isArray ? { kind: "array", value: baseType } : baseType;
804
+ }
805
+ const getEnumByOid = (oid) => {
806
+ const pgEnum = params.pgEnums.get(oid);
807
+ if (pgEnum === void 0) {
808
+ return void 0;
809
+ }
810
+ return {
811
+ kind: "union",
812
+ value: pgEnum.values.map((value2) => ({
813
+ kind: "type",
814
+ value: `'${value2}'`,
815
+ type: pgEnum.name
816
+ }))
817
+ };
818
+ };
819
+ const valueAsEnum = (() => {
820
+ const enumType = getEnumByOid(p.oid);
821
+ if (enumType !== void 0) {
822
+ return enumType;
823
+ }
824
+ if (pgType?.typelem !== void 0 && pgType.typelem !== 0) {
825
+ const arrayEnumValue = getEnumByOid(pgType.typelem);
826
+ if (arrayEnumValue !== void 0) {
827
+ return {
828
+ kind: "array",
829
+ value: arrayEnumValue
830
+ };
831
+ }
832
+ }
833
+ return void 0;
834
+ })();
835
+ if (valueAsEnum !== void 0) {
836
+ return valueAsEnum;
837
+ }
838
+ const { isArray, value } = typeByBaseOid ?? typeByOid;
839
+ const type = {
840
+ kind: "type",
841
+ value,
842
+ type: pgType?.name ?? "unknown"
843
+ };
844
+ if (p.baseOid !== null) {
845
+ type.base = params.pgTypes.get(p.baseOid)?.name;
846
+ }
847
+ return isArray ? { kind: "array", value: type } : type;
848
+ }
849
+ };
850
+ const targetLists = [select.targetList, select.larg?.targetList, select.rarg?.targetList].filter(
851
+ (x) => x !== void 0
852
+ );
853
+ const resolvedColumnsList = [];
854
+ for (const [targetListIdx, targetList] of targetLists.entries()) {
855
+ resolvedColumnsList[targetListIdx] = targetList.map((target) => {
856
+ const described = getDescribedNode({
857
+ alias: void 0,
858
+ node: target,
859
+ context
860
+ });
861
+ if (described.length === 0) {
862
+ return [void 0];
863
+ }
864
+ return described;
865
+ }).flat();
866
+ }
867
+ const columnsLength = resolvedColumnsList.reduce((acc, x) => Math.max(acc, x.length), 0);
868
+ const final = /* @__PURE__ */ new Map();
869
+ for (let i = 0; i < columnsLength; i++) {
870
+ const result = mergeColumns(resolvedColumnsList.map((x) => x[i]));
871
+ final.set(i, result);
872
+ }
873
+ return {
874
+ map: final,
875
+ meta: {
876
+ relations,
877
+ nonNullableColumns
878
+ }
879
+ };
880
+ }
881
+ function mergeColumns(columns) {
882
+ const definedColumns = columns.filter((x) => x !== void 0);
883
+ if (definedColumns.length === 0) {
884
+ return void 0;
885
+ }
886
+ const name = definedColumns[0].name;
887
+ const type = mergeDescribedColumnTypes(definedColumns.map((x) => x.type));
888
+ return { name, type };
889
+ }
890
+ function getDescribedNode(params) {
891
+ const { alias, node, context } = params;
892
+ if (node.ResTarget !== void 0) {
893
+ return getDescribedResTarget({ node: node.ResTarget, context });
894
+ }
895
+ if (node.A_Const !== void 0) {
896
+ return getDescribedAConst({ alias, node: node.A_Const, context });
897
+ }
898
+ if (node.ColumnRef !== void 0) {
899
+ return getDescribedColumnRef({ alias, node: node.ColumnRef, context });
900
+ }
901
+ if (node.FuncCall !== void 0) {
902
+ return getDescribedFuncCall({ alias, node: node.FuncCall, context });
903
+ }
904
+ if (node.TypeCast !== void 0) {
905
+ return getDescribedTypeCast({ alias, node: node.TypeCast, context });
906
+ }
907
+ if (node.A_ArrayExpr !== void 0) {
908
+ return getDescribedArrayExpr({ alias, node: node.A_ArrayExpr, context });
909
+ }
910
+ if (node.CoalesceExpr !== void 0) {
911
+ return getDescribedCoalesceExpr({ alias, node: node.CoalesceExpr, context });
912
+ }
913
+ if (node.SubLink !== void 0) {
914
+ return getDescribedSubLink({ alias, node: node.SubLink, context });
915
+ }
916
+ if (node.BoolExpr !== void 0) {
917
+ return getDescribedBoolExpr({ alias, node: node.BoolExpr, context });
918
+ }
919
+ if (node.CaseExpr !== void 0) {
920
+ return getDescribedCaseExpr({ alias, node: node.CaseExpr, context });
921
+ }
922
+ if (node.NullTest !== void 0) {
923
+ return getDescribedNullTest({ alias, node: node.NullTest, context });
924
+ }
925
+ if (node.A_Expr !== void 0) {
926
+ return getDescribedAExpr({ alias, node: node.A_Expr, context });
927
+ }
928
+ if (node.SelectStmt !== void 0) {
929
+ return getDescribedSelectStmt({ alias, node: node.SelectStmt, context });
930
+ }
931
+ return [];
932
+ }
933
+ function getDescribedAExpr({
934
+ alias,
935
+ node,
936
+ context
937
+ }) {
938
+ const name = alias ?? "?column?";
939
+ if (node.lexpr === void 0 && node.rexpr !== void 0) {
940
+ const described = getDescribedNode({ alias, node: node.rexpr, context }).at(0);
941
+ const type2 = fmap(described, (x) => getBaseType(x.type));
942
+ if (type2 === null) return [];
943
+ return [{ name, type: type2 }];
944
+ }
945
+ if (node.lexpr === void 0 || node.rexpr === void 0) {
946
+ return [];
947
+ }
948
+ const getResolvedNullableValueOrNull = (node2) => {
949
+ const column = getDescribedNode({ alias: void 0, node: node2, context }).at(0);
950
+ if (column === void 0) return null;
951
+ const getFromType = (type2) => {
952
+ switch (true) {
953
+ case type2.kind === "type":
954
+ return { value: type2.base ?? type2.type, array: false, nullable: false };
955
+ case (type2.kind === "literal" && type2.base.kind === "type"):
956
+ return { value: type2.base.type, array: false, nullable: false };
957
+ case (type2.kind === "union" && type2.value.every((x) => x.kind === "literal")): {
958
+ const resolved = getFromType(type2.value[0].base);
959
+ if (resolved === null) return null;
960
+ return { value: resolved.value, nullable: false, array: false };
961
+ }
962
+ case (type2.kind === "union" && isTuple(type2.value)): {
963
+ let nullable = false;
964
+ let value = void 0;
965
+ for (const valueType of type2.value) {
966
+ if (valueType.kind !== "type") return null;
967
+ if (valueType.value === "null") nullable = true;
968
+ if (valueType.value !== "null") value = valueType.type;
969
+ }
970
+ if (value === void 0) return null;
971
+ return { value, nullable, array: false };
972
+ }
973
+ case type2.kind === "object":
974
+ return { value: "jsonb", array: false, nullable: false };
975
+ default:
976
+ return null;
977
+ }
978
+ };
979
+ if (column.type.kind === "array") {
980
+ const resolved = getFromType(column.type.value);
981
+ if (!resolved) return null;
982
+ return { value: resolved.value, nullable: resolved.nullable, array: true };
983
+ }
984
+ return getFromType(column.type);
985
+ };
986
+ const lnode = getResolvedNullableValueOrNull(node.lexpr);
987
+ const rnode = getResolvedNullableValueOrNull(node.rexpr);
988
+ const operator = concatStringNodes(node.name);
989
+ if (lnode === null || rnode === null) {
990
+ return [];
991
+ }
992
+ const downcast = () => {
993
+ const left = lnode.array ? `_${lnode.value}` : lnode.value;
994
+ const right = rnode.array ? `_${rnode.value}` : rnode.value;
995
+ const overrides = {
996
+ "int4 ^ int4": ["float8", "^", "float8"]
997
+ };
998
+ if (overrides[`${left} ${operator} ${right}`]) {
999
+ return overrides[`${left} ${operator} ${right}`];
1000
+ }
1001
+ const adjust = (value) => value === "varchar" ? "text" : value;
1002
+ return [adjust(left), operator, adjust(right)];
1003
+ };
1004
+ const getNullable = () => {
1005
+ if (context.nonNullableColumns.has(name)) {
1006
+ return false;
1007
+ }
1008
+ if (lnode.nullable || rnode.nullable) {
1009
+ return true;
1010
+ }
1011
+ const operatorForcesNullable = ["->>", "#>>"].includes(operator) && hasColumnReference(node.lexpr);
1012
+ return operatorForcesNullable;
1013
+ };
1014
+ const getType = () => {
1015
+ const nullable = getNullable();
1016
+ const [dleft, doperator, dright] = downcast();
1017
+ const type2 = context.typeExprMap.get(dleft)?.get(doperator)?.get(dright) ?? context.typeExprMap.get("anycompatiblearray")?.get(operator)?.get("anycompatiblearray") ?? context.typeExprMap.get("anyarray")?.get(operator)?.get("anyarray") ?? context.typeExprMap.get(lnode.value)?.get(operator)?.values().next().value;
1018
+ if (type2 === void 0) {
1019
+ return;
1020
+ }
1021
+ if (type2 === "anycompatiblearray") {
1022
+ return {
1023
+ kind: "array",
1024
+ value: resolveType({
1025
+ context,
1026
+ nullable,
1027
+ type: context.toTypeScriptType({ name: lnode.value })
1028
+ })
1029
+ };
1030
+ }
1031
+ return resolveType({
1032
+ context,
1033
+ nullable,
1034
+ type: context.toTypeScriptType({ name: type2 })
1035
+ });
1036
+ };
1037
+ const type = getType();
1038
+ if (type === void 0) {
1039
+ return [];
1040
+ }
1041
+ return [{ name, type }];
1042
+ }
1043
+ function getDescribedNullTest({
1044
+ alias,
1045
+ context
1046
+ }) {
1047
+ return [
1048
+ {
1049
+ name: alias ?? "?column?",
1050
+ type: resolveType({
1051
+ context,
1052
+ nullable: false,
1053
+ type: context.toTypeScriptType({ name: "bool" })
1054
+ })
1055
+ }
1056
+ ];
1057
+ }
1058
+ function getDescribedCaseExpr({
1059
+ alias,
1060
+ node,
1061
+ context
1062
+ }) {
1063
+ const results = [];
1064
+ for (const arg of node.args) {
1065
+ if (arg.CaseWhen?.result !== void 0) {
1066
+ results.push(getDescribedNode({ alias: void 0, node: arg.CaseWhen.result, context }));
1067
+ }
1068
+ }
1069
+ results.push(
1070
+ node.defresult !== void 0 ? getDescribedNode({ alias: void 0, node: node.defresult, context }) : [{ name: "?column?", type: context.toTypeScriptType({ name: "null" }) }]
1071
+ );
1072
+ const types = results.flat().map((x) => x.type);
1073
+ const literalsOnly = types.some((x) => x.kind !== "literal" && x.value !== "null");
1074
+ const value = mergeDescribedColumnTypes(literalsOnly ? types.map(getBaseType) : types);
1075
+ return [
1076
+ {
1077
+ name: alias ?? "case",
1078
+ type: value
1079
+ }
1080
+ ];
1081
+ }
1082
+ function getBaseType(type) {
1083
+ switch (type.kind) {
1084
+ case "object":
1085
+ case "union":
1086
+ case "array":
1087
+ case "type":
1088
+ return type;
1089
+ case "literal":
1090
+ return type.base;
1091
+ }
1092
+ }
1093
+ function getDescribedBoolExpr({
1094
+ alias,
1095
+ context
1096
+ }) {
1097
+ return [
1098
+ {
1099
+ name: alias ?? "?column?",
1100
+ type: resolveType({
1101
+ context,
1102
+ nullable: false,
1103
+ type: context.toTypeScriptType({ name: "bool" })
1104
+ })
1105
+ }
1106
+ ];
1107
+ }
1108
+ function getDescribedSubLink({
1109
+ alias,
1110
+ context,
1111
+ node
1112
+ }) {
1113
+ const getSubLinkType = () => {
1114
+ if (node.subLinkType === SubLinkType.EXISTS_SUBLINK) {
1115
+ return context.toTypeScriptType({ name: "bool" });
1116
+ }
1117
+ if (node.subLinkType === SubLinkType.EXPR_SUBLINK) {
1118
+ const described = node.subselect?.SelectStmt ? getDescribedNode({
1119
+ alias: void 0,
1120
+ node: { SelectStmt: node.subselect.SelectStmt },
1121
+ context
1122
+ }) : [];
1123
+ return described.length > 0 ? described[0].type : context.toTypeScriptType({ name: "unknown" });
1124
+ }
1125
+ return context.toTypeScriptType({ name: "unknown" });
1126
+ };
1127
+ return [
1128
+ {
1129
+ name: alias ?? "exists",
1130
+ type: resolveType({
1131
+ context,
1132
+ nullable: false,
1133
+ type: getSubLinkType()
1134
+ })
1135
+ }
1136
+ ];
1137
+ }
1138
+ function getDescribedSelectStmt({
1139
+ alias,
1140
+ context,
1141
+ node
1142
+ }) {
1143
+ const subParsed = {
1144
+ version: 0,
1145
+ stmts: [{ stmt: { SelectStmt: node }, stmtLocation: 0, stmtLen: 0 }]
1146
+ };
1147
+ const subDescription = getASTDescription({
1148
+ parsed: subParsed,
1149
+ typesMap: context.typesMap,
1150
+ typeExprMap: context.typeExprMap,
1151
+ overridenColumnTypesMap: context.overridenColumnTypesMap,
1152
+ pgColsBySchemaAndTableName: context.pgColsBySchemaAndTableName,
1153
+ pgTypes: context.pgTypes,
1154
+ pgEnums: context.pgEnums,
1155
+ pgFns: context.pgFns,
1156
+ fieldTransform: context.fieldTransform
1157
+ });
1158
+ const firstColumn = subDescription.map.get(0);
1159
+ if (firstColumn) {
1160
+ return [
1161
+ {
1162
+ name: alias ?? firstColumn.name,
1163
+ type: firstColumn.type
1164
+ }
1165
+ ];
1166
+ }
1167
+ return [];
1168
+ }
1169
+ function getDescribedCoalesceExpr({
1170
+ alias,
1171
+ context,
1172
+ node
1173
+ }) {
1174
+ const firstArg = node.args.at(0);
1175
+ const unknownCoalesce = {
1176
+ name: alias ?? "coalesce",
1177
+ type: context.toTypeScriptType({ name: "unknown" })
1178
+ };
1179
+ if (firstArg === void 0) {
1180
+ return [unknownCoalesce];
1181
+ }
1182
+ const type = getDescribedNode({ alias: void 0, node: firstArg, context }).map((x) => asNonNullableType(x.type)).at(0);
1183
+ if (type === void 0) {
1184
+ return [];
1185
+ }
1186
+ return [
1187
+ {
1188
+ name: alias ?? "coalesce",
1189
+ type
1190
+ }
1191
+ ];
1192
+ }
1193
+ function getDescribedArrayExpr({
1194
+ alias,
1195
+ context,
1196
+ node
1197
+ }) {
1198
+ const types = mergeDescribedColumnTypes(
1199
+ node.elements.flatMap((node2) => getDescribedNode({ alias: void 0, node: node2, context })).map((x) => x.type)
1200
+ );
1201
+ return [
1202
+ {
1203
+ name: alias ?? "?column?",
1204
+ type: {
1205
+ kind: "array",
1206
+ value: types
1207
+ }
1208
+ }
1209
+ ];
1210
+ }
1211
+ function mergeDescribedColumnTypes(types) {
1212
+ const result = [];
1213
+ const seenSymbols = /* @__PURE__ */ new Set();
1214
+ function processType(type) {
1215
+ switch (type.kind) {
1216
+ case "union":
1217
+ type.value.forEach((subtype) => processType(subtype));
1218
+ break;
1219
+ case "type":
1220
+ case "literal":
1221
+ if (!seenSymbols.has(type.value)) {
1222
+ seenSymbols.add(type.value);
1223
+ result.push(type);
1224
+ }
1225
+ break;
1226
+ case "object":
1227
+ case "array":
1228
+ result.push(type);
1229
+ break;
1230
+ }
1231
+ }
1232
+ for (const t of types) {
1233
+ processType(t);
1234
+ }
1235
+ if (!seenSymbols.has("boolean") && seenSymbols.has("true") && seenSymbols.has("false")) {
1236
+ seenSymbols.add("boolean");
1237
+ result.push({ kind: "type", value: "boolean", type: "bool" });
1238
+ }
1239
+ if (seenSymbols.has("boolean") && (seenSymbols.has("true") || seenSymbols.has("false"))) {
1240
+ const filtered = result.filter(
1241
+ (t) => !(t.kind === "literal" && (t.value === "true" || t.value === "false"))
1242
+ );
1243
+ return isSingleCell(filtered) ? filtered[0] : { kind: "union", value: filtered };
1244
+ }
1245
+ return isSingleCell(result) ? result[0] : { kind: "union", value: result };
1246
+ }
1247
+ function getDescribedTypeCast({
1248
+ alias,
1249
+ context,
1250
+ node
1251
+ }) {
1252
+ let typeName = node.typeName?.names.at(-1)?.String?.sval;
1253
+ if (typeName === "int") {
1254
+ typeName = "int4";
1255
+ }
1256
+ if (typeName === void 0 || node.arg === void 0) {
1257
+ return [];
1258
+ }
1259
+ const type = context.toTypeScriptType({ name: typeName });
1260
+ const innerDescribed = getDescribedNode({ alias, node: node.arg, context }).at(0);
1261
+ const nullable = fmap(innerDescribed, (x) => isDescribedColumnNullable(x.type)) ?? true;
1262
+ switch (true) {
1263
+ case node.arg.FuncCall !== void 0: {
1264
+ return [
1265
+ {
1266
+ name: alias ?? node.arg.FuncCall?.funcname.at(-1)?.String?.sval ?? "?column?",
1267
+ type: resolveType({ context, nullable, type })
1268
+ }
1269
+ ];
1270
+ }
1271
+ case node.arg.ColumnRef !== void 0: {
1272
+ return [
1273
+ {
1274
+ name: alias ?? concatStringNodes(node.arg.ColumnRef.fields),
1275
+ type: resolveType({ context, nullable, type })
1276
+ }
1277
+ ];
1278
+ }
1279
+ default: {
1280
+ return [
1281
+ {
1282
+ name: alias ?? typeName ?? "?column?",
1283
+ type: resolveType({ context, nullable, type })
1284
+ }
1285
+ ];
1286
+ }
1287
+ }
1288
+ }
1289
+ function getDescribedResTarget(params) {
1290
+ const { node, context } = params;
1291
+ if (node.val === void 0) {
1292
+ return [];
1293
+ }
1294
+ return getDescribedNode({
1295
+ alias: node.name,
1296
+ context,
1297
+ node: node.val
1298
+ });
1299
+ }
1300
+ function getDescribedFuncCall(params) {
1301
+ const functionName = params.node.funcname.at(-1)?.String?.sval;
1302
+ if (functionName === void 0) {
1303
+ return [];
1304
+ }
1305
+ switch (true) {
1306
+ case functionName === "json_build_object":
1307
+ case functionName === "jsonb_build_object":
1308
+ return getDescribedJsonBuildObjectFunCall(params);
1309
+ case functionName === "json_agg":
1310
+ case functionName === "jsonb_agg":
1311
+ return getDescribedJsonAggFunCall(params);
1312
+ case functionName === "array_agg":
1313
+ return getDescribedArrayAggFunCall(params);
1314
+ case functionName === "unnest":
1315
+ return getDescribedUnnestFunCall(params);
1316
+ default:
1317
+ return getDescribedFuncCallByPgFn(params);
1318
+ }
1319
+ }
1320
+ function getDescribedUnnestFunCall({
1321
+ alias,
1322
+ context,
1323
+ node
1324
+ }) {
1325
+ const functionName = node.funcname.at(-1)?.String?.sval ?? "";
1326
+ const name = alias ?? functionName;
1327
+ const firstArg = node.args?.at(0);
1328
+ if (firstArg === void 0) {
1329
+ return [{ name, type: context.toTypeScriptType({ name: "unknown" }) }];
1330
+ }
1331
+ const described = getDescribedNode({ alias: void 0, node: firstArg, context }).at(0);
1332
+ if (described === void 0) {
1333
+ return [{ name, type: context.toTypeScriptType({ name: "unknown" }) }];
1334
+ }
1335
+ function unwrap(type) {
1336
+ if (type.kind === "array") {
1337
+ return unwrap(type.value);
1338
+ }
1339
+ if (type.kind === "union") {
1340
+ const hasArray = type.value.some((t) => t.kind === "array");
1341
+ const unwrapped = type.value.filter((t) => !hasArray || !(t.kind === "type" && t.value === "null")).map(unwrap);
1342
+ return mergeDescribedColumnTypes(unwrapped);
1343
+ }
1344
+ if (type.kind === "type" && type.type.startsWith("_")) {
1345
+ return { ...type, type: type.type.slice(1) };
1346
+ }
1347
+ return type;
1348
+ }
1349
+ return [{ name, type: unwrap(described.type) }];
1350
+ }
1351
+ function getDescribedFuncCallByPgFn({
1352
+ alias,
1353
+ context,
1354
+ node
1355
+ }) {
1356
+ const functionName = node.funcname.at(-1)?.String?.sval;
1357
+ const name = alias ?? functionName ?? "?column?";
1358
+ const args = (node.args ?? []).flatMap((node2) => {
1359
+ const described = getDescribedNode({ alias: void 0, node: node2, context }).at(0);
1360
+ if (described?.type.kind === "type") {
1361
+ return [described.type.value];
1362
+ }
1363
+ return [];
1364
+ });
1365
+ if (functionName === void 0) {
1366
+ return [{ name, type: context.toTypeScriptType({ name: "unknown" }) }];
1367
+ }
1368
+ const pgFnValue = args.length === 0 ? context.pgFns.get(functionName) ?? context.pgFns.get(`${functionName}(string)`) : context.pgFns.get(`${functionName}(${args.join(", ")})`) ?? context.pgFns.get(`${functionName}(any)`) ?? context.pgFns.get(`${functionName}(unknown)`);
1369
+ const type = resolveType({
1370
+ context,
1371
+ nullable: !context.nonNullableColumns.has(name),
1372
+ type: { kind: "type", value: pgFnValue?.ts ?? "unknown", type: pgFnValue?.pg ?? "unknown" }
1373
+ });
1374
+ return [{ name, type }];
1375
+ }
1376
+ function getDescribedArrayAggFunCall({
1377
+ alias,
1378
+ context,
1379
+ node
1380
+ }) {
1381
+ const name = alias ?? concatStringNodes(node.funcname);
1382
+ const firstArg = fmap(node.args?.at(0), (node2) => {
1383
+ return {
1384
+ node: node2,
1385
+ described: getDescribedNode({ alias: void 0, node: node2, context })
1386
+ };
1387
+ });
1388
+ if (firstArg === null) {
1389
+ return [
1390
+ {
1391
+ name,
1392
+ type: context.toTypeScriptType({ name: "unknown" })
1393
+ }
1394
+ ];
1395
+ }
1396
+ const isSourceRef = context.resolver.sources.get(concatStringNodes(firstArg.node.ColumnRef?.fields)) !== void 0;
1397
+ const type = resolveType({
1398
+ context,
1399
+ nullable: !context.nonNullableColumns.has(name),
1400
+ type: {
1401
+ kind: "array",
1402
+ value: isSourceRef || firstArg.described.length > 1 ? {
1403
+ kind: "object",
1404
+ value: firstArg.described.map((x) => [x.name, x.type])
1405
+ } : firstArg.described[0].type
1406
+ }
1407
+ });
1408
+ return [{ name, type }];
1409
+ }
1410
+ function getDescribedJsonAggFunCall({
1411
+ alias,
1412
+ context,
1413
+ node
1414
+ }) {
1415
+ const name = alias ?? concatStringNodes(node.funcname);
1416
+ if (node.args === void 0 || !isSingleCell(node.args)) {
1417
+ return [];
1418
+ }
1419
+ const argNode = node.args[0];
1420
+ const cellType = getDescribedNode({ alias: void 0, node: argNode, context });
1421
+ if (cellType.length === 0) {
1422
+ return [];
1423
+ }
1424
+ const isSourceRef = context.resolver.sources.get(concatStringNodes(argNode.ColumnRef?.fields)) !== void 0;
1425
+ const type = resolveType({
1426
+ context,
1427
+ nullable: !context.nonNullableColumns.has(name),
1428
+ type: {
1429
+ kind: "array",
1430
+ value: isSourceRef || cellType.length > 1 ? {
1431
+ kind: "object",
1432
+ value: cellType.map((x) => [x.name, x.type])
1433
+ } : cellType[0].type
1434
+ }
1435
+ });
1436
+ return [{ name, type }];
1437
+ }
1438
+ function getDescribedJsonBuildObjectFunCall({
1439
+ alias,
1440
+ context,
1441
+ node
1442
+ }) {
1443
+ const functionName = node.funcname.at(-1)?.String?.sval ?? "";
1444
+ const name = alias ?? functionName;
1445
+ const unknownDescribedColumn = {
1446
+ name,
1447
+ type: context.toTypeScriptType({ name: "unknown" })
1448
+ };
1449
+ if (node.args === void 0) {
1450
+ return [unknownDescribedColumn];
1451
+ }
1452
+ const describedColumn = { kind: "object", value: [] };
1453
+ for (const [idx, arg] of node.args.entries()) {
1454
+ if (idx % 2 === 1) {
1455
+ continue;
1456
+ }
1457
+ const valueNode = node.args.at(idx + 1);
1458
+ if (valueNode === void 0) {
1459
+ throw new Error(normalizeIndent`
1460
+ argument list must have even number of elements
1461
+ Hint: The arguments of ${functionName}() must consist of alternating keys and values.
1462
+ `);
1463
+ }
1464
+ const alias2 = arg.A_Const?.sval?.sval;
1465
+ const type = fmap(node.args[idx + 1], (node2) => {
1466
+ return getDescribedNode({ alias: alias2, node: node2, context }).at(0)?.type ?? null;
1467
+ });
1468
+ if (alias2 === void 0 || type === null) {
1469
+ return [unknownDescribedColumn];
1470
+ }
1471
+ const transformedKey = toCase(alias2, context.fieldTransform);
1472
+ describedColumn.value.push([transformedKey, resolveType({ context, nullable: false, type })]);
1473
+ }
1474
+ return [
1475
+ {
1476
+ name,
1477
+ type: describedColumn
1478
+ }
1479
+ ];
1480
+ }
1481
+ function getColumnRefOrigins({
1482
+ context,
1483
+ node
1484
+ }) {
1485
+ if (isColumnTableStarRef(node.fields)) {
1486
+ const source = node.fields[0].String.sval;
1487
+ return (
1488
+ // lookup in cte
1489
+ context.select.withClause?.ctes.find((cte) => cte.CommonTableExpr?.ctename === source)?.CommonTableExpr?.ctequery?.SelectStmt?.targetList ?? // lookup in subselect
1490
+ context.select.fromClause?.map((from) => from.RangeSubselect).find((subselect) => subselect?.alias?.aliasname === source)?.subquery?.SelectStmt?.targetList
1491
+ );
1492
+ }
1493
+ if (isColumnTableColumnRef(node.fields)) {
1494
+ const source = node.fields[0].String.sval;
1495
+ const column = node.fields[1].String.sval;
1496
+ const origin = (
1497
+ // lookup in cte
1498
+ context.select.withClause?.ctes.find((cte) => cte.CommonTableExpr?.ctename === source)?.CommonTableExpr?.ctequery?.SelectStmt?.targetList?.find(
1499
+ (x) => x.ResTarget?.name === column
1500
+ ) ?? // lookup in subselect
1501
+ context.select.fromClause?.map((from) => from.RangeSubselect).find((subselect) => subselect?.alias?.aliasname === source)?.subquery?.SelectStmt?.targetList?.find((x) => x.ResTarget?.name === column)
1502
+ );
1503
+ if (!origin) return void 0;
1504
+ return [origin];
1505
+ }
1506
+ }
1507
+ function getContextForColumnRef(context, node) {
1508
+ if (isColumnTableColumnRef(node.fields) || isColumnTableStarRef(node.fields)) {
1509
+ const sourceName = node.fields[0].String.sval;
1510
+ const source = context.resolver.sources.get(sourceName);
1511
+ if (source?.kind === "cte") {
1512
+ return { ...context, resolver: source.sources };
1513
+ }
1514
+ }
1515
+ return context;
1516
+ }
1517
+ function getDescribedColumnRef({
1518
+ alias,
1519
+ context,
1520
+ node
1521
+ }) {
1522
+ const definitionNodes = getColumnRefOrigins({ context, node });
1523
+ if (definitionNodes) {
1524
+ const defContext = getContextForColumnRef(context, node);
1525
+ return definitionNodes.flatMap(
1526
+ (node2) => getDescribedNode({ alias, node: node2, context: defContext })
1527
+ );
1528
+ }
1529
+ return getDescribedColumnRefFromSchema({ alias, context, node });
1530
+ }
1531
+ function getDescribedColumnRefFromSchema({
1532
+ alias,
1533
+ context,
1534
+ node
1535
+ }) {
1536
+ if (isColumnStarRef(node.fields)) {
1537
+ return getDescribedColumnByResolvedColumns({
1538
+ alias,
1539
+ context,
1540
+ resolved: context.resolver.getAllResolvedColumns().map((x) => x.column)
1541
+ });
1542
+ }
1543
+ if (isColumnTableStarRef(node.fields)) {
1544
+ return getDescribedColumnByResolvedColumns({
1545
+ alias,
1546
+ context,
1547
+ resolved: context.resolver.getResolvedColumnsInTable(node.fields[0].String.sval)
1548
+ });
1549
+ }
1550
+ if (isColumnUnknownRef(node.fields)) {
1551
+ const resolved = context.resolver.getColumnsByTargetField({
1552
+ kind: "unknown",
1553
+ field: node.fields[0].String.sval
1554
+ });
1555
+ return getDescribedColumnByResolvedColumns({
1556
+ alias,
1557
+ context,
1558
+ resolved: resolved ?? []
1559
+ });
1560
+ }
1561
+ if (isColumnTableColumnRef(node.fields)) {
1562
+ const resolved = context.resolver.getNestedResolvedTargetField({
1563
+ kind: "column",
1564
+ table: node.fields[0].String.sval,
1565
+ column: node.fields[1].String.sval
1566
+ });
1567
+ return getDescribedColumnByResolvedColumns({
1568
+ alias,
1569
+ context,
1570
+ resolved: fmap(resolved, (x) => [x]) ?? []
1571
+ });
1572
+ }
1573
+ return [];
1574
+ }
1575
+ function getDescribedColumnByResolvedColumns(params) {
1576
+ return params.resolved.map(({ column, isNotNull }) => {
1577
+ const getType = () => {
1578
+ const overridenType = params.context.overridenColumnTypesMap.get(column.tableName)?.get(column.colName);
1579
+ if (overridenType !== void 0) {
1580
+ return {
1581
+ kind: "type",
1582
+ value: overridenType,
1583
+ type: params.context.pgTypes.get(column.colTypeOid)?.name ?? "unknown"
1584
+ };
1585
+ }
1586
+ return params.context.toTypeScriptType({
1587
+ oid: column.colTypeOid,
1588
+ baseOid: column.colBaseTypeOid
1589
+ });
1590
+ };
1591
+ return {
1592
+ name: params.alias ?? column.colName,
1593
+ type: resolveType({
1594
+ context: params.context,
1595
+ nullable: !isNotNull,
1596
+ type: getType()
1597
+ })
1598
+ };
1599
+ });
1600
+ }
1601
+ function getDescribedAConst({
1602
+ alias,
1603
+ context,
1604
+ node
1605
+ }) {
1606
+ const type = (() => {
1607
+ switch (true) {
1608
+ case node.boolval !== void 0:
1609
+ return {
1610
+ kind: "literal",
1611
+ value: node.boolval.boolval ? "true" : "false",
1612
+ base: context.toTypeScriptType({ name: "bool" })
1613
+ };
1614
+ case node.bsval !== void 0:
1615
+ return context.toTypeScriptType({ name: "bytea" });
1616
+ case node.fval !== void 0:
1617
+ return {
1618
+ kind: "literal",
1619
+ value: node.fval.toString(),
1620
+ base: context.toTypeScriptType({ name: "float8" })
1621
+ };
1622
+ case node.isnull !== void 0:
1623
+ return context.toTypeScriptType({ name: "null" });
1624
+ case node.ival !== void 0:
1625
+ return {
1626
+ kind: "literal",
1627
+ value: (node.ival.ival ?? 0).toString(),
1628
+ base: context.toTypeScriptType({ name: "int4" })
1629
+ };
1630
+ case node.sval !== void 0:
1631
+ return {
1632
+ kind: "literal",
1633
+ value: `'${node.sval.sval}'`,
1634
+ base: context.toTypeScriptType({ name: "text" })
1635
+ };
1636
+ default:
1637
+ return context.toTypeScriptType({ name: "unknown" });
1638
+ }
1639
+ })();
1640
+ return [
1641
+ {
1642
+ name: alias ?? "?column?",
1643
+ type: resolveType({ context, nullable: node.isnull === true, type })
1644
+ }
1645
+ ];
1646
+ }
1647
+ function asNonNullableType(type) {
1648
+ switch (type.kind) {
1649
+ case "object":
1650
+ case "array":
1651
+ case "literal":
1652
+ return type;
1653
+ case "union": {
1654
+ const filtered = type.value.filter(
1655
+ (described) => described.kind !== "type" || described.value !== "null"
1656
+ );
1657
+ if (filtered.length === 0) {
1658
+ return { kind: "type", value: "unknown", type: "unknown" };
1659
+ }
1660
+ if (filtered.length === 1) {
1661
+ return filtered[0];
1662
+ }
1663
+ return { kind: "union", value: filtered };
1664
+ }
1665
+ case "type":
1666
+ return type.value === "null" ? { kind: "type", value: "unknown", type: "unknown" } : type;
1667
+ }
1668
+ }
1669
+ function isDescribedColumnNullable(type) {
1670
+ return type.kind === "union" && type.value.some((x) => x.kind === "type" && x.value === "null");
1671
+ }
1672
+ function resolveType(params) {
1673
+ if (params.nullable && params.type.value !== "null") {
1674
+ return {
1675
+ kind: "union",
1676
+ value: [params.type, params.context.toTypeScriptType({ name: "null" })]
1677
+ };
1678
+ }
1679
+ return params.type;
1680
+ }
1681
+ function concatStringNodes(nodes) {
1682
+ return nodes?.map((x) => x.String?.sval).filter(Boolean).join(".") ?? "";
1683
+ }
1684
+ function hasColumnReference(node) {
1685
+ if (node === void 0) {
1686
+ return false;
1687
+ }
1688
+ if (node.ColumnRef !== void 0) {
1689
+ return true;
1690
+ }
1691
+ if (node.A_Const !== void 0) {
1692
+ return false;
1693
+ }
1694
+ if (node.TypeCast !== void 0) {
1695
+ return hasColumnReference(node.TypeCast.arg);
1696
+ }
1697
+ if (node.A_Expr !== void 0) {
1698
+ return hasColumnReference(node.A_Expr.lexpr) || hasColumnReference(node.A_Expr.rexpr);
1699
+ }
1700
+ if (node.BoolExpr !== void 0) {
1701
+ return (node.BoolExpr.args ?? []).some(hasColumnReference);
1702
+ }
1703
+ if (node.FuncCall !== void 0) {
1704
+ return (node.FuncCall.args ?? []).some(hasColumnReference);
1705
+ }
1706
+ if (node.CoalesceExpr !== void 0) {
1707
+ return node.CoalesceExpr.args.some(hasColumnReference);
1708
+ }
1709
+ if (node.CaseExpr !== void 0) {
1710
+ if (node.CaseExpr.arg && hasColumnReference(node.CaseExpr.arg)) {
1711
+ return true;
1712
+ }
1713
+ if (node.CaseExpr.defresult && hasColumnReference(node.CaseExpr.defresult)) {
1714
+ return true;
1715
+ }
1716
+ return node.CaseExpr.args.some((caseWhen) => {
1717
+ if (caseWhen.CaseWhen === void 0) {
1718
+ return false;
1719
+ }
1720
+ return hasColumnReference(caseWhen.CaseWhen.expr) || hasColumnReference(caseWhen.CaseWhen.result);
1721
+ });
1722
+ }
1723
+ if (node.A_ArrayExpr !== void 0) {
1724
+ return (node.A_ArrayExpr.elements ?? []).some(hasColumnReference);
1725
+ }
1726
+ if (node.SubLink !== void 0) {
1727
+ return true;
1728
+ }
1729
+ return false;
1730
+ }
1731
+
1732
+ function isParsedInsertResult(parsed) {
1733
+ return parsed.stmts[0]?.stmt?.InsertStmt !== void 0;
1734
+ }
1735
+ function validateInsertResult(parsed, pgColsBySchemaAndTableName, query) {
1736
+ const insertStmt = parsed.stmts[0].stmt.InsertStmt;
1737
+ if (insertStmt.relation === void 0) {
1738
+ return;
1739
+ }
1740
+ const schemaName = insertStmt.relation.schemaname ?? "public";
1741
+ const tableName = insertStmt.relation.relname;
1742
+ const tableCols = pgColsBySchemaAndTableName.get(schemaName)?.get(tableName);
1743
+ if (tableCols === void 0) {
1744
+ return;
1745
+ }
1746
+ const insertCols = getInsertColumns(insertStmt, tableCols);
1747
+ const missing = tableCols.filter(
1748
+ (c) => c.colNotNull && !c.colHasDef && c.colIdentity === "" && !insertCols.includes(c.colName)
1749
+ );
1750
+ if (missing.length === 0) {
1751
+ return;
1752
+ }
1753
+ const position = (parsed.stmts[0]?.stmtLocation ?? 0) + 1;
1754
+ const columnsStr = missing.map((c) => `"${c.colName}"`).join(", ");
1755
+ const message = missing.length === 1 ? [
1756
+ `null value in column ${columnsStr} violates not-null constraint`,
1757
+ `Hint: Column ${columnsStr} is not nullable and has no default value.`
1758
+ ].join("\n") : [
1759
+ `null value in columns ${columnsStr} violates not-null constraint`,
1760
+ `Hint: Columns ${columnsStr} are not nullable and have no default value.`
1761
+ ].join("\n");
1762
+ throw PostgresError.of({
1763
+ queryText: query.text,
1764
+ message,
1765
+ line: "1",
1766
+ position,
1767
+ sourcemaps: query.sourcemaps
1768
+ });
1769
+ }
1770
+ function getInsertColumns(stmt, tableCols) {
1771
+ if (stmt.cols) {
1772
+ return stmt.cols.map((col) => col.ResTarget?.name).filter((name) => Boolean(name));
1773
+ }
1774
+ if (stmt.selectStmt === void 0) {
1775
+ return [];
1776
+ }
1777
+ const valuesFromSelect = stmt.selectStmt.SelectStmt?.valuesLists?.at(0)?.List?.items;
1778
+ if (valuesFromSelect !== void 0) {
1779
+ return tableCols.slice(0, valuesFromSelect.length).map((c) => c.colName);
1780
+ }
1781
+ return tableCols.map((c) => c.colName);
1782
+ }
1783
+
1784
+ function createEmptyCache() {
1785
+ return {
1786
+ base: /* @__PURE__ */ new Map(),
1787
+ overrides: {
1788
+ types: /* @__PURE__ */ new Map(),
1789
+ columns: /* @__PURE__ */ new Map()
1790
+ },
1791
+ functions: /* @__PURE__ */ new Map()
1792
+ };
1793
+ }
1794
+ function createGenerator() {
1795
+ const cache = createEmptyCache();
1796
+ return {
1797
+ generate: (params) => generate(params, cache),
1798
+ dropCacheKey: (cacheKey) => cache.base.delete(cacheKey),
1799
+ clearCache: () => {
1800
+ cache.base.clear();
1801
+ cache.overrides.types.clear();
1802
+ cache.overrides.columns.clear();
1803
+ cache.functions.clear();
1804
+ }
1805
+ };
1806
+ }
1807
+ async function generate(params, cache) {
1808
+ const { sql, query, cacheKey, cacheMetadata = true } = params;
1809
+ const {
1810
+ pgColsByTableOidCache,
1811
+ pgColsBySchemaAndTableName,
1812
+ pgTypes,
1813
+ pgEnums,
1814
+ pgFnsByName,
1815
+ pgTypeExprMap
1816
+ } = await getOrSetFromMapWithEnabled({
1817
+ shouldCache: cacheMetadata,
1818
+ map: cache.base,
1819
+ key: cacheKey,
1820
+ value: () => getDatabaseMetadata(sql)
1821
+ });
1822
+ const typesMap = await getOrSetFromMapWithEnabled({
1823
+ shouldCache: cacheMetadata,
1824
+ map: cache.overrides.types,
1825
+ key: JSON.stringify(params.overrides?.types),
1826
+ value: () => {
1827
+ const map = /* @__PURE__ */ new Map([["array", { override: false, value: "array" }]]);
1828
+ for (const [key, value] of defaultTypesMap.entries()) {
1829
+ map.set(key, { override: false, value });
1830
+ }
1831
+ for (const [k, v] of Object.entries(params.overrides?.types ?? {})) {
1832
+ map.set(k, { override: true, value: typeof v === "string" ? v : v.return });
1833
+ }
1834
+ return map;
1835
+ }
1836
+ });
1837
+ const overridenColumnTypesMap = await getOrSetFromMapWithEnabled({
1838
+ shouldCache: cacheMetadata,
1839
+ map: cache.overrides.columns,
1840
+ key: JSON.stringify(params.overrides?.columns),
1841
+ value: () => {
1842
+ const map = /* @__PURE__ */ new Map();
1843
+ for (const [colPath, type] of Object.entries(params.overrides?.columns ?? {})) {
1844
+ const [table, column] = colPath.split(".");
1845
+ if (table === void 0 || column === void 0) {
1846
+ throw new Error(`Invalid override column key: ${colPath}. Expected format: table.column`);
1847
+ }
1848
+ map.has(table) ? map.get(table)?.set(column, type) : map.set(table, /* @__PURE__ */ new Map([[column, type]]));
1849
+ }
1850
+ return map;
1851
+ }
1852
+ });
1853
+ function byReturnType(a, b) {
1854
+ const priority = ["numeric", "int8"];
1855
+ return priority.indexOf(a.returnType) - priority.indexOf(b.returnType);
1856
+ }
1857
+ const functionsMap = await getOrSetFromMapWithEnabled({
1858
+ shouldCache: cacheMetadata,
1859
+ map: cache.functions,
1860
+ key: JSON.stringify(params.overrides?.types),
1861
+ value: () => {
1862
+ const map = /* @__PURE__ */ new Map();
1863
+ for (const [functionName, signatures] of pgFnsByName.entries()) {
1864
+ for (const signature of signatures.sort(byReturnType)) {
1865
+ const tsArgs = signature.arguments.map((arg) => {
1866
+ return typesMap.get(arg)?.value ?? "unknown";
1867
+ });
1868
+ const tsReturnType = typesMap.get(signature.returnType)?.value ?? signature.returnType;
1869
+ const key = tsArgs.length === 0 ? functionName : `${functionName}(${tsArgs.join(", ")})`;
1870
+ map.set(key, { ts: tsReturnType, pg: signature.returnType });
1871
+ }
1872
+ }
1873
+ return map;
1874
+ }
1875
+ });
1876
+ try {
1877
+ const result = await sql.unsafe(query.text, [], { prepare: true }).describe();
1878
+ const parsed = await parser.parse(query.text);
1879
+ if (isParsedInsertResult(parsed)) {
1880
+ validateInsertResult(parsed, pgColsBySchemaAndTableName, query);
1881
+ }
1882
+ if (result.columns === void 0 || result.columns === null || result.columns.length === 0) {
1883
+ return either.right({ output: null, unknownColumns: [], stmt: result, query });
1884
+ }
1885
+ const duplicateCols = result.columns.filter(
1886
+ (col, index) => result.columns.find((c, i) => c.name === col.name && i != index)
1887
+ );
1888
+ if (duplicateCols.length > 0) {
1889
+ const dupes = duplicateCols.map((col) => {
1890
+ const tableCols = pgColsByTableOidCache.get(col.table);
1891
+ const tableCol = col.number !== 0 ? tableCols?.at(col.number - 1) : tableCols?.find((c) => c.colName === col.name);
1892
+ return {
1893
+ table: tableCol?.tableName,
1894
+ column: col.name,
1895
+ originalColumn: tableCol?.colName
1896
+ };
1897
+ });
1898
+ const dupePosition = (() => {
1899
+ const match = query.text.search(new RegExp(`\\b${duplicateCols[0].name}\\b`));
1900
+ return (match > -1 ? match : query.text.search(/SELECT/i)) + 1;
1901
+ })();
1902
+ return either.left(
1903
+ DuplicateColumnsError.of({
1904
+ queryText: query.text,
1905
+ sourcemaps: query.sourcemaps,
1906
+ position: dupePosition,
1907
+ columns: dupes.map((x) => {
1908
+ return x.column !== x.originalColumn ? `${x.table}.${x.originalColumn} (alias: ${x.column})` : `${x.table}.${x.column}`;
1909
+ })
1910
+ })
1911
+ );
1912
+ }
1913
+ const astQueryDescription = getASTDescription({
1914
+ parsed,
1915
+ typesMap,
1916
+ overridenColumnTypesMap,
1917
+ pgColsBySchemaAndTableName,
1918
+ pgTypes,
1919
+ pgEnums,
1920
+ pgFns: functionsMap,
1921
+ typeExprMap: pgTypeExprMap,
1922
+ fieldTransform: params.fieldTransform
1923
+ });
1924
+ const columns = result.columns.map((col, position) => {
1925
+ const introspected = pgColsByTableOidCache.get(col.table)?.find((x) => x.colNum === col.number);
1926
+ const astDescribed = astQueryDescription.map.get(position);
1927
+ return {
1928
+ described: col,
1929
+ astDescribed,
1930
+ introspected,
1931
+ isNonNullableBasedOnAST: astQueryDescription.meta.nonNullableColumns.has(col.name)
1932
+ };
1933
+ });
1934
+ const context = {
1935
+ columns,
1936
+ pgTypes,
1937
+ pgEnums,
1938
+ relationsWithJoins: astQueryDescription.meta.relations,
1939
+ overrides: {
1940
+ types: typesMap,
1941
+ columns: overridenColumnTypesMap
1942
+ },
1943
+ pgColsBySchemaAndTableName,
1944
+ fieldTransform: params.fieldTransform
1945
+ };
1946
+ return either.right({
1947
+ output: getTypedColumnEntries({ context }),
1948
+ unknownColumns: columns.filter((x) => x.astDescribed === void 0).map((x) => x.described.name),
1949
+ stmt: result,
1950
+ query
1951
+ });
1952
+ } catch (e) {
1953
+ if (isPostgresError(e)) {
1954
+ return either.left(
1955
+ PostgresError.of({
1956
+ queryText: query.text,
1957
+ sourcemaps: query.sourcemaps,
1958
+ message: e.message,
1959
+ line: e.line,
1960
+ position: e.position
1961
+ })
1962
+ );
1963
+ }
1964
+ throw e;
1965
+ }
1966
+ }
1967
+ async function getDatabaseMetadata(sql) {
1968
+ const pgTypes = await getPgTypes(sql);
1969
+ const pgCols = await getPgCols(sql);
1970
+ const pgEnums = await getPgEnums(sql);
1971
+ const pgFns = await getPgFunctions(sql);
1972
+ const pgColsByTableOidCache = groupBy(pgCols, "tableOid");
1973
+ const pgColsBySchemaAndTableName = groupBy(pgCols, "schemaName", "tableName");
1974
+ const pgFnsByName = groupBy(pgFns, "name");
1975
+ const pgTypeExprMap = await getPgTypeExprMap(sql);
1976
+ return {
1977
+ pgTypes,
1978
+ pgCols,
1979
+ pgEnums,
1980
+ pgColsByTableOidCache,
1981
+ pgColsBySchemaAndTableName,
1982
+ pgFnsByName,
1983
+ pgTypeExprMap
1984
+ };
1985
+ }
1986
+ function getTypedColumnEntries(params) {
1987
+ const value = params.context.columns.map(
1988
+ (col) => getResolvedTargetEntry({ col, context: params.context })
1989
+ );
1990
+ return { kind: "object", value };
1991
+ }
1992
+ function isNullableResolvedTarget(target) {
1993
+ switch (target.kind) {
1994
+ case "type":
1995
+ return ["any", "null"].includes(target.value) === false;
1996
+ case "union":
1997
+ return target.value.some(isNullableResolvedTarget);
1998
+ case "array":
1999
+ return isNullableResolvedTarget(target.value);
2000
+ case "object":
2001
+ return target.value.some(([, value]) => isNullableResolvedTarget(value));
2002
+ case "literal":
2003
+ return false;
2004
+ }
2005
+ }
2006
+ function buildInterfacePropertyValue(params) {
2007
+ const isNullable = params.isNullable && isNullableResolvedTarget(params.value);
2008
+ return [
2009
+ params.key,
2010
+ isNullable ? { kind: "union", value: [params.value, { kind: "type", value: "null", type: "null" }] } : params.value
2011
+ ];
2012
+ }
2013
+ function checkIsNullableDueToRelation(params) {
2014
+ const { col, relationsWithJoins } = params;
2015
+ const findByJoin = relationsWithJoins.find((x) => x.joinRelName === col.tableName);
2016
+ if (findByJoin !== void 0) {
2017
+ switch (findByJoin.joinType) {
2018
+ case JoinType.JOIN_LEFT:
2019
+ case JoinType.JOIN_FULL:
2020
+ return true;
2021
+ case JoinType.JOIN_TYPE_UNDEFINED:
2022
+ case JoinType.JOIN_INNER:
2023
+ case JoinType.JOIN_RIGHT:
2024
+ case JoinType.JOIN_SEMI:
2025
+ case JoinType.JOIN_ANTI:
2026
+ case JoinType.JOIN_UNIQUE_OUTER:
2027
+ case JoinType.JOIN_UNIQUE_INNER:
2028
+ case JoinType.UNRECOGNIZED:
2029
+ return false;
2030
+ default:
2031
+ assertNever(findByJoin.joinType);
2032
+ }
2033
+ }
2034
+ const findByRel = relationsWithJoins.filter((x) => x.relName === col.tableName);
2035
+ for (const rel of findByRel) {
2036
+ switch (rel.joinType) {
2037
+ case JoinType.JOIN_RIGHT:
2038
+ case JoinType.JOIN_FULL:
2039
+ return true;
2040
+ case JoinType.JOIN_TYPE_UNDEFINED:
2041
+ case JoinType.JOIN_INNER:
2042
+ case JoinType.JOIN_LEFT:
2043
+ case JoinType.JOIN_SEMI:
2044
+ case JoinType.JOIN_ANTI:
2045
+ case JoinType.JOIN_UNIQUE_OUTER:
2046
+ case JoinType.JOIN_UNIQUE_INNER:
2047
+ case JoinType.UNRECOGNIZED:
2048
+ return false;
2049
+ default:
2050
+ assertNever(rel.joinType);
2051
+ }
2052
+ }
2053
+ return false;
2054
+ }
2055
+ function getResolvedTargetEntry(params) {
2056
+ if (params.col.astDescribed !== void 0) {
2057
+ return [
2058
+ toCase(params.col.described.name, params.context.fieldTransform),
2059
+ params.col.astDescribed.type
2060
+ ];
2061
+ }
2062
+ const pgTypeOid = params.col.introspected?.colBaseTypeOid ?? params.col.described.type;
2063
+ const pgType = params.context.pgTypes.get(pgTypeOid);
2064
+ const getEnumByOid = (oid) => {
2065
+ const pgEnum = params.context.pgEnums.get(oid);
2066
+ if (pgEnum === void 0) {
2067
+ return void 0;
2068
+ }
2069
+ return {
2070
+ kind: "union",
2071
+ value: pgEnum.values.map(
2072
+ (value2) => ({
2073
+ kind: "type",
2074
+ value: `'${value2}'`,
2075
+ type: pgEnum.name
2076
+ })
2077
+ )
2078
+ };
2079
+ };
2080
+ const valueAsEnum = (() => {
2081
+ const enumTarget = getEnumByOid(pgTypeOid);
2082
+ if (enumTarget !== void 0) {
2083
+ return enumTarget;
2084
+ }
2085
+ if (pgType?.typelem !== void 0 && pgType.typelem !== 0) {
2086
+ const elemEnumTarget = getEnumByOid(pgType.typelem);
2087
+ if (elemEnumTarget !== void 0) {
2088
+ return { kind: "array", value: elemEnumTarget };
2089
+ }
2090
+ }
2091
+ return void 0;
2092
+ })();
2093
+ const valueAsType = getTsTypeFromPgTypeOid({
2094
+ pgTypeOid,
2095
+ pgTypes: params.context.pgTypes
2096
+ });
2097
+ const valueAsOverride = (() => {
2098
+ const pgType2 = params.context.pgTypes.get(
2099
+ params.col.introspected?.colTypeOid ?? params.col.described.type
2100
+ );
2101
+ if (!pgType2) return void 0;
2102
+ const columnOverride = params?.context?.overrides?.columns.get(params.col.introspected?.tableName ?? "")?.get(params.col.introspected?.colName ?? params.col.described.name);
2103
+ if (columnOverride !== void 0) {
2104
+ return { kind: "type", value: columnOverride, type: pgType2.name };
2105
+ }
2106
+ const typeOverride = params?.context?.overrides?.types.get(pgType2.name);
2107
+ if (typeOverride !== void 0) {
2108
+ return {
2109
+ kind: "type",
2110
+ value: typeOverride.value,
2111
+ type: pgType2.name
2112
+ };
2113
+ }
2114
+ return void 0;
2115
+ })();
2116
+ const value = valueAsOverride ?? valueAsEnum ?? valueAsType;
2117
+ const key = params.col.described.name ?? params.col.introspected?.colName;
2118
+ let isNonNullable = params.col.isNonNullableBasedOnAST;
2119
+ if (!isNonNullable && params.col.introspected !== void 0) {
2120
+ isNonNullable = params.col.introspected.colNotNull;
2121
+ if (checkIsNullableDueToRelation({
2122
+ col: params.col.introspected,
2123
+ relationsWithJoins: params.context.relationsWithJoins
2124
+ })) {
2125
+ isNonNullable = false;
2126
+ }
2127
+ }
2128
+ return buildInterfacePropertyValue({
2129
+ key: toCase(key, params.context.fieldTransform),
2130
+ value,
2131
+ isNullable: !isNonNullable
2132
+ });
2133
+ }
2134
+ function getTsTypeFromPgTypeOid(params) {
2135
+ const pgType = params.pgTypes.get(params.pgTypeOid);
2136
+ if (pgType === void 0) {
2137
+ return { kind: "type", value: "unknown", type: "unknown" };
2138
+ }
2139
+ return getTsTypeFromPgType({ pgTypeName: pgType.name });
2140
+ }
2141
+ function getTsTypeFromPgType(params) {
2142
+ const { isArray, pgType } = parsePgType(params.pgTypeName);
2143
+ const tsType = defaultTypesMap.get(pgType) ?? "any";
2144
+ const property = { kind: "type", value: tsType, type: pgType };
2145
+ return isArray ? { kind: "array", value: property } : property;
2146
+ }
2147
+ function isPgTypeArray(pgType) {
2148
+ return pgType.startsWith("_");
2149
+ }
2150
+ function parsePgType(pgType) {
2151
+ const isArray = isPgTypeArray(pgType);
2152
+ return {
2153
+ isArray,
2154
+ pgType: isArray ? pgType.slice(1) : pgType
2155
+ };
2156
+ }
2157
+ async function getPgEnums(sql) {
2158
+ const rows = await sql`
2159
+ SELECT pg_type.oid, pg_type.typname, pg_enum.enumlabel
2160
+ FROM pg_type
2161
+ JOIN pg_enum ON pg_enum.enumtypid = pg_type.oid
2162
+ WHERE pg_type.typtype = 'e'
2163
+ ORDER BY pg_type.typname, pg_enum.enumsortorder
2164
+ `;
2165
+ const map = /* @__PURE__ */ new Map();
2166
+ for (const row of rows) {
2167
+ const existing = map.get(row.oid);
2168
+ if (existing === void 0) {
2169
+ map.set(row.oid, {
2170
+ name: row.typname,
2171
+ values: [row.enumlabel]
2172
+ });
2173
+ continue;
2174
+ }
2175
+ existing.values.push(row.enumlabel);
2176
+ }
2177
+ return map;
2178
+ }
2179
+ async function getPgTypes(sql) {
2180
+ const rows = await sql`
2181
+ SELECT oid, typname as name, typelem FROM pg_type
2182
+ `;
2183
+ const map = /* @__PURE__ */ new Map();
2184
+ for (const row of rows) {
2185
+ map.set(row.oid, row);
2186
+ }
2187
+ return map;
2188
+ }
2189
+ async function getPgCols(sql) {
2190
+ const rows = await sql`
2191
+ SELECT
2192
+ pg_class.oid AS "tableOid",
2193
+ pg_namespace.nspname AS "schemaName",
2194
+ pg_class.relname AS "tableName",
2195
+ pg_attribute.attname AS "colName",
2196
+ pg_type.oid AS "colTypeOid",
2197
+ CASE
2198
+ WHEN pg_type.typtype = 'd' THEN
2199
+ (SELECT pt.oid FROM pg_type pt WHERE pt.oid = pg_type.typbasetype)
2200
+ ELSE
2201
+ NULL
2202
+ END AS "colBaseTypeOid",
2203
+ pg_attribute.attnum AS "colNum",
2204
+ pg_attribute.atthasdef "colHasDef",
2205
+ pg_attribute.attnotnull "colNotNull",
2206
+ pg_attribute.attidentity "colIdentity"
2207
+ FROM
2208
+ pg_attribute,
2209
+ pg_class,
2210
+ pg_type,
2211
+ pg_namespace
2212
+ WHERE TRUE
2213
+ AND pg_attribute.attrelid = pg_class.oid
2214
+ AND pg_attribute.atttypid = pg_type.oid
2215
+ AND pg_class.relnamespace = pg_namespace.oid
2216
+ AND pg_attribute.attnum >= 1
2217
+ ORDER BY
2218
+ pg_class.relname,
2219
+ pg_attribute.attnum
2220
+ `;
2221
+ return rows;
2222
+ }
2223
+ async function getPgFunctions(sql) {
2224
+ const rows = await sql`
2225
+ SELECT
2226
+ pg_proc.proname AS "name",
2227
+ pg_catalog.pg_get_function_arguments(pg_proc.oid) AS "argumentsString",
2228
+ pg_type.typname AS "returnType"
2229
+ FROM
2230
+ pg_catalog.pg_proc
2231
+ JOIN
2232
+ pg_catalog.pg_type ON pg_proc.prorettype = pg_type.oid
2233
+ WHERE
2234
+ pg_proc.pronamespace::regnamespace = 'pg_catalog'::regnamespace
2235
+ `;
2236
+ return rows.map((row) => ({
2237
+ name: row.name,
2238
+ arguments: row.argumentsString.replace(/"/, "").split(", ").filter((x) => x !== ""),
2239
+ returnType: row.returnType
2240
+ }));
2241
+ }
2242
+ async function getPgTypeExprMap(sql) {
2243
+ const rows = await sql`
2244
+ SELECT
2245
+ l.typname as left,
2246
+ o.oprname as operator,
2247
+ r.typname as right,
2248
+ ret.typname AS result
2249
+ FROM pg_operator o
2250
+ JOIN pg_type l ON l.oid = o.oprleft
2251
+ JOIN pg_type r ON r.oid = o.oprright
2252
+ JOIN pg_type ret ON ret.oid = o.oprresult
2253
+ WHERE o.oprleft <> 0 AND o.oprright <> 0
2254
+ `;
2255
+ const map = /* @__PURE__ */ new Map();
2256
+ for (const row of rows) {
2257
+ const leftMap = map.get(row.left) ?? /* @__PURE__ */ new Map();
2258
+ const rightMap = leftMap.get(row.operator) ?? /* @__PURE__ */ new Map();
2259
+ rightMap.set(row.right, row.result);
2260
+ leftMap.set(row.operator, rightMap);
2261
+ map.set(row.left, leftMap);
2262
+ }
2263
+ return map;
2264
+ }
2265
+
2266
+ function createConnectionManager() {
2267
+ const connectionMap = /* @__PURE__ */ new Map();
2268
+ return {
2269
+ getOrCreate: (databaseUrl, options) => getOrCreateConnection(databaseUrl, connectionMap, options),
2270
+ close: (params) => closeConnection(params, connectionMap)
2271
+ };
2272
+ }
2273
+ function getOrCreateConnection(databaseUrl, connectionMap, options) {
2274
+ return pipe(
2275
+ O.fromNullable(connectionMap.get(databaseUrl)),
2276
+ O.foldW(
2277
+ () => {
2278
+ const sql = postgres(databaseUrl, options);
2279
+ connectionMap.set(databaseUrl, sql);
2280
+ return { sql, databaseUrl, isFirst: true };
2281
+ },
2282
+ (sql) => ({ sql, databaseUrl, isFirst: false })
2283
+ )
2284
+ );
2285
+ }
2286
+ function closeConnection(params, connectionMap) {
2287
+ const { connection, projectDir } = params;
2288
+ const strategy = getConnectionStrategyByRuleOptionConnection({ connection, projectDir });
2289
+ match(strategy).with({ type: "databaseUrl" }, ({ databaseUrl }) => {
2290
+ const sql = connectionMap.get(databaseUrl);
2291
+ if (sql) {
2292
+ sql.end();
2293
+ connectionMap.delete(databaseUrl);
2294
+ }
2295
+ }).with({ type: "migrations" }, ({ connectionUrl, databaseName }) => {
2296
+ const connectionOptions = { ...parseConnection(connectionUrl), database: databaseName };
2297
+ const databaseUrl = mapConnectionOptionsToString(connectionOptions);
2298
+ const sql = connectionMap.get(databaseUrl);
2299
+ const migrationSql = connectionMap.get(connectionUrl);
2300
+ if (sql) {
2301
+ sql.end();
2302
+ connectionMap.delete(databaseUrl);
2303
+ }
2304
+ if (migrationSql) {
2305
+ migrationSql.end();
2306
+ connectionMap.delete(connectionUrl);
2307
+ }
2308
+ }).exhaustive();
2309
+ }
2310
+
2311
+ function createWatchManager() {
2312
+ const migrationPaths = /* @__PURE__ */ new Map();
2313
+ const watcher = chokidar.watch([], { ignoreInitial: true }).on("all", (_, filePath) => {
2314
+ for (const [path2, { onChange }] of migrationPaths.entries()) {
2315
+ if (filePath.startsWith(path2)) {
2316
+ return onChange();
2317
+ }
2318
+ }
2319
+ });
2320
+ const watchMigrationsDir = (params) => {
2321
+ const migrationPath = path.join(params.projectDir, params.connection.migrationsDir);
2322
+ if (migrationPaths.has(migrationPath)) {
2323
+ return;
2324
+ }
2325
+ migrationPaths.set(migrationPath, {
2326
+ onChange: () => {
2327
+ const { databaseUrl } = getMigrationDatabaseMetadata({
2328
+ connectionUrl: params.connection.connectionUrl ?? DEFAULT_CONNECTION_URL,
2329
+ databaseName: getDatabaseName({
2330
+ databaseName: params.connection.databaseName,
2331
+ migrationsDir: params.connection.migrationsDir,
2332
+ projectDir: params.projectDir
2333
+ })
2334
+ });
2335
+ params.dropCacheKeyFn(databaseUrl);
2336
+ params.closeConnectionFn({ connection: params.connection, projectDir: params.projectDir });
2337
+ }
2338
+ });
2339
+ watcher.add(migrationPath);
2340
+ };
2341
+ return {
2342
+ watchMigrationsDir
2343
+ };
2344
+ }
2345
+
2346
+ const generator = createGenerator();
2347
+ const connections = createConnectionManager();
2348
+ const watchers = createWatchManager();
2349
+ async function handler(params) {
2350
+ if (isWatchMigrationsDirEnabled(params.connection)) {
2351
+ watchers.watchMigrationsDir({
2352
+ connection: params.connection,
2353
+ projectDir: params.projectDir,
2354
+ dropCacheKeyFn: generator.dropCacheKey,
2355
+ closeConnectionFn: connections.close
2356
+ });
2357
+ }
2358
+ const result = await pipe(
2359
+ TE.Do,
2360
+ TE.chain(() => workerHandler(params))
2361
+ )();
2362
+ if (params.connection.keepAlive === false) {
2363
+ connections.close({ connection: params.connection, projectDir: params.projectDir });
2364
+ }
2365
+ return J.stringify(result);
2366
+ }
2367
+ runAsWorker(handler);
2368
+ function workerHandler(params) {
2369
+ const strategy = getConnectionStrategyByRuleOptionConnection(params);
2370
+ const connectionPayload = match(strategy).with(
2371
+ { type: "databaseUrl" },
2372
+ ({ databaseUrl }) => TE.right(connections.getOrCreate(databaseUrl))
2373
+ ).with({ type: "migrations" }, ({ migrationsDir, databaseName, connectionUrl }) => {
2374
+ const { connectionOptions, databaseUrl } = getMigrationDatabaseMetadata({
2375
+ connectionUrl,
2376
+ databaseName
2377
+ });
2378
+ const { sql, isFirst } = connections.getOrCreate(databaseUrl);
2379
+ const { sql: migrationSql } = connections.getOrCreate(connectionUrl, {
2380
+ onnotice: () => {
2381
+ }
2382
+ });
2383
+ const connectionPayload2 = { sql, isFirst, databaseUrl };
2384
+ if (isFirst) {
2385
+ const migrationsPath = path.join(params.projectDir, migrationsDir);
2386
+ return pipe(
2387
+ TE.Do,
2388
+ TE.chainW(() => initDatabase(migrationSql, connectionOptions.database)),
2389
+ TE.chainW(() => runMigrations({ migrationsPath, sql })),
2390
+ TE.map(() => connectionPayload2)
2391
+ );
2392
+ }
2393
+ return TE.right(connectionPayload2);
2394
+ }).exhaustive();
2395
+ const generateTask = (params2) => {
2396
+ return TE.tryCatch(() => generator.generate(params2), InternalError.to);
2397
+ };
2398
+ return pipe(
2399
+ connectionPayload,
2400
+ TE.chainW(({ sql, databaseUrl }) => {
2401
+ return generateTask({
2402
+ sql,
2403
+ query: params.query,
2404
+ cacheKey: databaseUrl,
2405
+ overrides: params.connection.overrides,
2406
+ fieldTransform: params.target.fieldTransform
2407
+ });
2408
+ }),
2409
+ TE.chainW(TE.fromEither)
2410
+ );
2411
+ }
2412
+ //# sourceMappingURL=check-sql.worker.mjs.map