@querypanel/node-sdk 1.0.25 → 1.0.26

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 (145) hide show
  1. package/README.md +23 -0
  2. package/dist/cjs/__tests__/ingest.test.d.ts +5 -0
  3. package/dist/cjs/__tests__/ingest.test.d.ts.map +1 -0
  4. package/dist/cjs/__tests__/ingest.test.js +95 -0
  5. package/dist/cjs/__tests__/ingest.test.js.map +1 -0
  6. package/dist/cjs/adapters/clickhouse.d.ts +48 -0
  7. package/dist/cjs/adapters/clickhouse.d.ts.map +1 -0
  8. package/dist/cjs/adapters/clickhouse.js +284 -0
  9. package/dist/cjs/adapters/clickhouse.js.map +1 -0
  10. package/dist/cjs/adapters/introspection.spec.d.ts +2 -0
  11. package/dist/cjs/adapters/introspection.spec.d.ts.map +1 -0
  12. package/dist/cjs/adapters/introspection.spec.js +192 -0
  13. package/dist/cjs/adapters/introspection.spec.js.map +1 -0
  14. package/dist/cjs/adapters/postgres.d.ts +46 -0
  15. package/dist/cjs/adapters/postgres.d.ts.map +1 -0
  16. package/dist/cjs/adapters/postgres.js +457 -0
  17. package/dist/cjs/adapters/postgres.js.map +1 -0
  18. package/dist/cjs/adapters/postgres.spec.d.ts +2 -0
  19. package/dist/cjs/adapters/postgres.spec.d.ts.map +1 -0
  20. package/dist/cjs/adapters/postgres.spec.js +37 -0
  21. package/dist/cjs/adapters/postgres.spec.js.map +1 -0
  22. package/dist/cjs/adapters/types.d.ts +38 -0
  23. package/dist/cjs/adapters/types.d.ts.map +1 -0
  24. package/dist/cjs/adapters/types.js +3 -0
  25. package/dist/cjs/adapters/types.js.map +1 -0
  26. package/dist/cjs/anonymize.spec.d.ts +2 -0
  27. package/dist/cjs/anonymize.spec.d.ts.map +1 -0
  28. package/dist/cjs/anonymize.spec.js +78 -0
  29. package/dist/cjs/anonymize.spec.js.map +1 -0
  30. package/dist/cjs/clickhouseClient.spec.d.ts +2 -0
  31. package/dist/cjs/clickhouseClient.spec.d.ts.map +1 -0
  32. package/dist/cjs/clickhouseClient.spec.js +286 -0
  33. package/dist/cjs/clickhouseClient.spec.js.map +1 -0
  34. package/dist/cjs/connectors/__tests__/clickhouse.introspect.test.d.ts +2 -0
  35. package/dist/cjs/connectors/__tests__/clickhouse.introspect.test.d.ts.map +1 -0
  36. package/dist/cjs/connectors/__tests__/clickhouse.introspect.test.js +119 -0
  37. package/dist/cjs/connectors/__tests__/clickhouse.introspect.test.js.map +1 -0
  38. package/dist/cjs/connectors/base.d.ts +13 -0
  39. package/dist/cjs/connectors/base.d.ts.map +1 -0
  40. package/dist/cjs/connectors/base.js +3 -0
  41. package/dist/cjs/connectors/base.js.map +1 -0
  42. package/dist/cjs/connectors/clickhouse.d.ts +53 -0
  43. package/dist/cjs/connectors/clickhouse.d.ts.map +1 -0
  44. package/dist/cjs/connectors/clickhouse.js +270 -0
  45. package/dist/cjs/connectors/clickhouse.js.map +1 -0
  46. package/dist/cjs/index.d.ts +490 -0
  47. package/dist/cjs/index.d.ts.map +1 -0
  48. package/dist/cjs/index.js +843 -0
  49. package/dist/cjs/index.js.map +1 -0
  50. package/dist/cjs/index.test.d.ts +2 -0
  51. package/dist/cjs/index.test.d.ts.map +1 -0
  52. package/dist/cjs/index.test.js +185 -0
  53. package/dist/cjs/index.test.js.map +1 -0
  54. package/dist/cjs/introspectV3.d.ts +45 -0
  55. package/dist/cjs/introspectV3.d.ts.map +1 -0
  56. package/dist/cjs/introspectV3.js +99 -0
  57. package/dist/cjs/introspectV3.js.map +1 -0
  58. package/dist/cjs/multidb.spec.d.ts +2 -0
  59. package/dist/cjs/multidb.spec.d.ts.map +1 -0
  60. package/dist/cjs/multidb.spec.js +76 -0
  61. package/dist/cjs/multidb.spec.js.map +1 -0
  62. package/dist/cjs/package.json +1 -0
  63. package/dist/cjs/schema/types.d.ts +73 -0
  64. package/dist/cjs/schema/types.d.ts.map +1 -0
  65. package/dist/cjs/schema/types.js +3 -0
  66. package/dist/cjs/schema/types.js.map +1 -0
  67. package/dist/cjs/tenant-isolation.spec.d.ts +2 -0
  68. package/dist/cjs/tenant-isolation.spec.d.ts.map +1 -0
  69. package/dist/cjs/tenant-isolation.spec.js +420 -0
  70. package/dist/cjs/tenant-isolation.spec.js.map +1 -0
  71. package/dist/cjs/utils/clickhouse.d.ts +9 -0
  72. package/dist/cjs/utils/clickhouse.d.ts.map +1 -0
  73. package/dist/cjs/utils/clickhouse.js +99 -0
  74. package/dist/cjs/utils/clickhouse.js.map +1 -0
  75. package/dist/esm/adapters/clickhouse.d.ts +48 -0
  76. package/dist/esm/adapters/clickhouse.d.ts.map +1 -0
  77. package/dist/esm/adapters/clickhouse.js +280 -0
  78. package/dist/esm/adapters/clickhouse.js.map +1 -0
  79. package/dist/esm/adapters/introspection.spec.d.ts +2 -0
  80. package/dist/esm/adapters/introspection.spec.d.ts.map +1 -0
  81. package/dist/esm/adapters/introspection.spec.js +190 -0
  82. package/dist/esm/adapters/introspection.spec.js.map +1 -0
  83. package/dist/esm/adapters/postgres.d.ts +46 -0
  84. package/dist/esm/adapters/postgres.d.ts.map +1 -0
  85. package/dist/esm/adapters/postgres.js +453 -0
  86. package/dist/esm/adapters/postgres.js.map +1 -0
  87. package/dist/esm/adapters/postgres.spec.d.ts +2 -0
  88. package/dist/esm/adapters/postgres.spec.d.ts.map +1 -0
  89. package/dist/esm/adapters/postgres.spec.js +35 -0
  90. package/dist/esm/adapters/postgres.spec.js.map +1 -0
  91. package/dist/esm/adapters/types.d.ts +38 -0
  92. package/dist/esm/adapters/types.d.ts.map +1 -0
  93. package/dist/esm/adapters/types.js +2 -0
  94. package/dist/esm/adapters/types.js.map +1 -0
  95. package/dist/esm/anonymize.spec.d.ts +2 -0
  96. package/dist/esm/anonymize.spec.d.ts.map +1 -0
  97. package/dist/esm/anonymize.spec.js +76 -0
  98. package/dist/esm/anonymize.spec.js.map +1 -0
  99. package/dist/esm/clickhouseClient.spec.d.ts +2 -0
  100. package/dist/esm/clickhouseClient.spec.d.ts.map +1 -0
  101. package/dist/esm/clickhouseClient.spec.js +281 -0
  102. package/dist/esm/clickhouseClient.spec.js.map +1 -0
  103. package/dist/esm/connectors/base.d.ts +14 -0
  104. package/dist/esm/connectors/base.d.ts.map +1 -0
  105. package/dist/esm/connectors/base.js +2 -0
  106. package/dist/esm/connectors/base.js.map +1 -0
  107. package/dist/esm/connectors/clickhouse.d.ts +35 -0
  108. package/dist/esm/connectors/clickhouse.d.ts.map +1 -0
  109. package/dist/esm/connectors/clickhouse.js +281 -0
  110. package/dist/esm/connectors/clickhouse.js.map +1 -0
  111. package/dist/esm/index.d.ts +490 -0
  112. package/dist/esm/index.d.ts.map +1 -0
  113. package/dist/esm/index.js +838 -0
  114. package/dist/esm/index.js.map +1 -0
  115. package/dist/esm/index.test.d.ts +2 -0
  116. package/dist/esm/index.test.d.ts.map +1 -0
  117. package/dist/esm/index.test.js +183 -0
  118. package/dist/esm/index.test.js.map +1 -0
  119. package/dist/esm/introspectV3.d.ts +45 -0
  120. package/dist/esm/introspectV3.d.ts.map +1 -0
  121. package/dist/esm/introspectV3.js +96 -0
  122. package/dist/esm/introspectV3.js.map +1 -0
  123. package/dist/esm/multidb.spec.d.ts +2 -0
  124. package/dist/esm/multidb.spec.d.ts.map +1 -0
  125. package/dist/esm/multidb.spec.js +74 -0
  126. package/dist/esm/multidb.spec.js.map +1 -0
  127. package/dist/esm/schema/types.d.ts +73 -0
  128. package/dist/esm/schema/types.d.ts.map +1 -0
  129. package/dist/esm/schema/types.js +2 -0
  130. package/dist/esm/schema/types.js.map +1 -0
  131. package/dist/esm/tenant-isolation.spec.d.ts +2 -0
  132. package/dist/esm/tenant-isolation.spec.d.ts.map +1 -0
  133. package/dist/esm/tenant-isolation.spec.js +418 -0
  134. package/dist/esm/tenant-isolation.spec.js.map +1 -0
  135. package/dist/esm/utils/clickhouse.d.ts +9 -0
  136. package/dist/esm/utils/clickhouse.d.ts.map +1 -0
  137. package/dist/esm/utils/clickhouse.js +92 -0
  138. package/dist/esm/utils/clickhouse.js.map +1 -0
  139. package/package.json +73 -53
  140. package/dist/index.cjs +0 -1471
  141. package/dist/index.cjs.map +0 -1
  142. package/dist/index.d.cts +0 -468
  143. package/dist/index.d.ts +0 -468
  144. package/dist/index.js +0 -1443
  145. package/dist/index.js.map +0 -1
@@ -0,0 +1,280 @@
1
+ import { extractFixedStringLength, extractPrecisionScale, isNullableType, parseKeyExpression, unwrapTypeModifiers, } from "../utils/clickhouse.js";
2
+ export class ClickHouseAdapter {
3
+ constructor(clientFn, options = {}) {
4
+ this.clientFn = clientFn;
5
+ console.log({ options });
6
+ this.databaseName = options.database ?? "default";
7
+ this.defaultFormat = options.defaultFormat ?? "JSONEachRow";
8
+ this.kind = options.kind ?? "clickhouse";
9
+ if (options.allowedTables) {
10
+ this.allowedTables = normalizeTableFilter(options.allowedTables);
11
+ }
12
+ }
13
+ async execute(sql, params) {
14
+ // Validate query against allowed tables if restrictions are in place
15
+ if (this.allowedTables) {
16
+ this.validateQueryTables(sql);
17
+ }
18
+ const queryOptions = {
19
+ format: this.defaultFormat,
20
+ };
21
+ if (params) {
22
+ queryOptions.params = params;
23
+ }
24
+ const rows = await this.query(sql, queryOptions);
25
+ const fields = rows.length > 0 ? Object.keys(rows[0] ?? {}) : [];
26
+ return { fields, rows };
27
+ }
28
+ async validate(sql, params) {
29
+ const queryOptions = {
30
+ format: this.defaultFormat,
31
+ };
32
+ if (params) {
33
+ queryOptions.params = params;
34
+ }
35
+ await this.query(`EXPLAIN ${sql}`, queryOptions);
36
+ }
37
+ getDialect() {
38
+ return "clickhouse";
39
+ }
40
+ async introspect(options) {
41
+ // Use adapter-level allowedTables if no specific tables provided in options
42
+ const tablesToIntrospect = options?.tables
43
+ ? normalizeTableFilter(options.tables)
44
+ : this.allowedTables;
45
+ const allowTables = tablesToIntrospect ?? [];
46
+ const hasFilter = allowTables.length > 0;
47
+ const queryParams = {
48
+ db: this.databaseName,
49
+ };
50
+ if (hasFilter) {
51
+ queryParams.tables = allowTables;
52
+ }
53
+ const filterClause = hasFilter ? " AND name IN {tables:Array(String)}" : "";
54
+ const tables = await this.query(`SELECT name, engine, comment, total_rows, total_bytes, primary_key, sorting_key
55
+ FROM system.tables
56
+ WHERE database = {db:String}${filterClause}
57
+ ORDER BY name`, { params: queryParams });
58
+ const columnFilterClause = hasFilter
59
+ ? " AND table IN {tables:Array(String)}"
60
+ : "";
61
+ const columns = await this.query(`SELECT table, name, type, position, default_kind, default_expression, comment, is_in_primary_key
62
+ FROM system.columns
63
+ WHERE database = {db:String}${columnFilterClause}
64
+ ORDER BY table, position`, { params: queryParams });
65
+ const columnsByTable = new Map();
66
+ for (const rawColumn of columns) {
67
+ const list = columnsByTable.get(rawColumn.table) ?? [];
68
+ list.push(transformColumnRow(rawColumn));
69
+ columnsByTable.set(rawColumn.table, list);
70
+ }
71
+ const tableSchemas = tables.map((table) => {
72
+ const tableColumns = columnsByTable.get(table.name) ?? [];
73
+ const primaryKeyColumns = parseKeyExpression(table.primary_key);
74
+ const totalRows = toNumber(table.total_rows);
75
+ const totalBytes = toNumber(table.total_bytes);
76
+ for (const column of tableColumns) {
77
+ column.isPrimaryKey =
78
+ column.isPrimaryKey || primaryKeyColumns.includes(column.name);
79
+ }
80
+ const indexes = primaryKeyColumns.length
81
+ ? [
82
+ {
83
+ name: "primary_key",
84
+ columns: primaryKeyColumns,
85
+ unique: true,
86
+ type: "PRIMARY KEY",
87
+ ...(table.primary_key ? { definition: table.primary_key } : {}),
88
+ },
89
+ ]
90
+ : [];
91
+ const constraints = primaryKeyColumns.length
92
+ ? [
93
+ {
94
+ name: "primary_key",
95
+ type: "PRIMARY KEY",
96
+ columns: primaryKeyColumns,
97
+ },
98
+ ]
99
+ : [];
100
+ const base = {
101
+ name: table.name,
102
+ schema: this.databaseName,
103
+ type: asTableType(table.engine),
104
+ engine: table.engine,
105
+ columns: tableColumns,
106
+ indexes,
107
+ constraints,
108
+ };
109
+ const comment = sanitize(table.comment);
110
+ if (comment !== undefined) {
111
+ base.comment = comment;
112
+ }
113
+ const statistics = buildTableStatistics(totalRows, totalBytes);
114
+ if (statistics) {
115
+ base.statistics = statistics;
116
+ }
117
+ return base;
118
+ });
119
+ return {
120
+ db: {
121
+ kind: this.kind,
122
+ name: this.databaseName,
123
+ },
124
+ tables: tableSchemas,
125
+ introspectedAt: new Date().toISOString(),
126
+ };
127
+ }
128
+ /**
129
+ * Validate that the SQL query only references allowed tables.
130
+ * This is a basic validation that extracts table-like patterns from the query.
131
+ */
132
+ validateQueryTables(sql) {
133
+ if (!this.allowedTables || this.allowedTables.length === 0) {
134
+ return;
135
+ }
136
+ const allowedSet = new Set(this.allowedTables);
137
+ // Extract potential table references from SQL
138
+ // This regex looks for identifiers after FROM/JOIN keywords
139
+ // ClickHouse may use database.table notation
140
+ const tablePattern = /(?:FROM|JOIN)\s+(?:FINAL\s+)?(?:(?:[a-zA-Z_][a-zA-Z0-9_]*)\.)?(["'`]?[a-zA-Z_][a-zA-Z0-9_]*["'`]?)/gi;
141
+ const matches = sql.matchAll(tablePattern);
142
+ for (const match of matches) {
143
+ const table = match[1]?.replace(/["'`]/g, "");
144
+ if (table) {
145
+ if (!allowedSet.has(table)) {
146
+ throw new Error(`Query references table "${table}" which is not in the allowed tables list`);
147
+ }
148
+ }
149
+ }
150
+ }
151
+ async close() {
152
+ // No-op: lifecycle of the underlying client is controlled by the caller.
153
+ }
154
+ async query(sql, options) {
155
+ const params = {
156
+ query: sql,
157
+ };
158
+ const format = options?.format ?? this.defaultFormat;
159
+ if (format !== undefined) {
160
+ params.format = format;
161
+ }
162
+ if (options?.params) {
163
+ params.query_params = options.params;
164
+ }
165
+ if (options?.settings) {
166
+ params.clickhouse_settings = options.settings;
167
+ }
168
+ const result = await this.clientFn(params);
169
+ return this.extractRows(result);
170
+ }
171
+ async extractRows(result) {
172
+ if (Array.isArray(result)) {
173
+ return result;
174
+ }
175
+ if (result &&
176
+ typeof result.json === "function") {
177
+ const payload = await result.json();
178
+ return normalizePayload(payload);
179
+ }
180
+ return [];
181
+ }
182
+ }
183
+ function normalizePayload(payload) {
184
+ if (Array.isArray(payload)) {
185
+ return payload;
186
+ }
187
+ if (payload && typeof payload === "object") {
188
+ const maybeData = payload.data;
189
+ if (Array.isArray(maybeData)) {
190
+ return maybeData;
191
+ }
192
+ }
193
+ return [];
194
+ }
195
+ function normalizeTableFilter(tables) {
196
+ if (!tables?.length)
197
+ return [];
198
+ const seen = new Set();
199
+ const normalized = [];
200
+ for (const table of tables) {
201
+ if (!table)
202
+ continue;
203
+ const trimmed = table.trim();
204
+ if (!trimmed)
205
+ continue;
206
+ const parts = trimmed.split(".");
207
+ const tableName = parts[parts.length - 1];
208
+ if (!tableName || seen.has(tableName))
209
+ continue;
210
+ seen.add(tableName);
211
+ normalized.push(tableName);
212
+ }
213
+ return normalized;
214
+ }
215
+ function transformColumnRow(row) {
216
+ const nullable = isNullableType(row.type);
217
+ const unwrappedType = unwrapTypeModifiers(row.type);
218
+ const { precision, scale } = extractPrecisionScale(row.type);
219
+ const maxLength = extractFixedStringLength(row.type);
220
+ const column = {
221
+ name: row.name,
222
+ type: unwrappedType,
223
+ rawType: row.type,
224
+ nullable,
225
+ isPrimaryKey: Boolean(toNumber(row.is_in_primary_key)),
226
+ isForeignKey: false,
227
+ };
228
+ const defaultKind = sanitize(row.default_kind);
229
+ if (defaultKind !== undefined)
230
+ column.defaultKind = defaultKind;
231
+ const defaultExpression = sanitize(row.default_expression);
232
+ if (defaultExpression !== undefined) {
233
+ column.defaultExpression = defaultExpression;
234
+ }
235
+ const comment = sanitize(row.comment);
236
+ if (comment !== undefined)
237
+ column.comment = comment;
238
+ if (maxLength !== undefined)
239
+ column.maxLength = maxLength;
240
+ if (precision !== undefined)
241
+ column.precision = precision;
242
+ if (scale !== undefined)
243
+ column.scale = scale;
244
+ return column;
245
+ }
246
+ function asTableType(engine) {
247
+ if (typeof engine === "string") {
248
+ const normalized = engine.toLowerCase();
249
+ // ClickHouse view engines: View, MaterializedView, LiveView
250
+ if (normalized.includes("view")) {
251
+ return "view";
252
+ }
253
+ }
254
+ return "table";
255
+ }
256
+ function buildTableStatistics(totalRows, totalBytes) {
257
+ if (totalRows === undefined && totalBytes === undefined)
258
+ return undefined;
259
+ const stats = {};
260
+ if (totalRows !== undefined)
261
+ stats.totalRows = totalRows;
262
+ if (totalBytes !== undefined)
263
+ stats.totalBytes = totalBytes;
264
+ return stats;
265
+ }
266
+ function sanitize(value) {
267
+ if (value === null || value === undefined)
268
+ return undefined;
269
+ const trimmed = String(value).trim();
270
+ return trimmed.length ? trimmed : undefined;
271
+ }
272
+ function toNumber(value) {
273
+ if (value === null || value === undefined)
274
+ return undefined;
275
+ if (typeof value === "number")
276
+ return value;
277
+ const parsed = Number.parseFloat(String(value));
278
+ return Number.isNaN(parsed) ? undefined : parsed;
279
+ }
280
+ //# sourceMappingURL=clickhouse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../../src/adapters/clickhouse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=introspection.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspection.spec.d.ts","sourceRoot":"","sources":["../../../src/adapters/introspection.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,190 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { ClickHouseAdapter } from "./clickhouse.js";
3
+ import { PostgresAdapter } from "./postgres.js";
4
+ function createClickHouseResponse(rows) {
5
+ return {
6
+ json: async () => rows,
7
+ };
8
+ }
9
+ describe("Database adapter introspection", () => {
10
+ it("introspects ClickHouse tables", async () => {
11
+ const clientFn = vi.fn(async ({ query }) => {
12
+ if (query.includes("FROM system.tables")) {
13
+ return createClickHouseResponse([
14
+ {
15
+ name: "events",
16
+ engine: "MergeTree",
17
+ comment: "Main events table",
18
+ total_rows: "1000",
19
+ total_bytes: "2048",
20
+ primary_key: "(id)",
21
+ sorting_key: null,
22
+ },
23
+ ]);
24
+ }
25
+ if (query.includes("FROM system.columns")) {
26
+ return createClickHouseResponse([
27
+ {
28
+ table: "events",
29
+ name: "id",
30
+ type: "UInt64",
31
+ position: 1,
32
+ default_kind: null,
33
+ default_expression: null,
34
+ comment: "Primary identifier",
35
+ is_in_primary_key: "1",
36
+ },
37
+ {
38
+ table: "events",
39
+ name: "name",
40
+ type: "Nullable(String)",
41
+ position: 2,
42
+ default_kind: null,
43
+ default_expression: null,
44
+ comment: null,
45
+ is_in_primary_key: "0",
46
+ },
47
+ ]);
48
+ }
49
+ return createClickHouseResponse([]);
50
+ });
51
+ const adapter = new ClickHouseAdapter(clientFn, {
52
+ database: "analytics",
53
+ });
54
+ const result = await adapter.introspect();
55
+ expect(result.db.name).toBe("analytics");
56
+ expect(result.tables).toHaveLength(1);
57
+ const table = result.tables[0];
58
+ if (!table)
59
+ throw new Error("missing table");
60
+ expect(table.columns.map((c) => c.name)).toEqual(["id", "name"]);
61
+ const idColumn = table.columns.find((c) => c.name === "id");
62
+ expect(idColumn?.isPrimaryKey).toBe(true);
63
+ expect(table.indexes[0]?.name).toBe("primary_key");
64
+ });
65
+ it("introspects Postgres tables", async () => {
66
+ const responses = new Map();
67
+ responses.set("tables", () => ({
68
+ rows: [
69
+ {
70
+ table_name: "users",
71
+ schema_name: "public",
72
+ table_type: "BASE TABLE",
73
+ comment: "application users",
74
+ total_rows: 200,
75
+ total_bytes: 4096,
76
+ },
77
+ ],
78
+ fields: [],
79
+ }));
80
+ responses.set("columns", () => ({
81
+ rows: [
82
+ {
83
+ table_name: "users",
84
+ table_schema: "public",
85
+ column_name: "id",
86
+ data_type: "integer",
87
+ udt_name: "int4",
88
+ is_nullable: "NO",
89
+ column_default: "nextval('users_id_seq'::regclass)",
90
+ character_maximum_length: null,
91
+ numeric_precision: 32,
92
+ numeric_scale: 0,
93
+ ordinal_position: 1,
94
+ description: "primary key",
95
+ },
96
+ {
97
+ table_name: "users",
98
+ table_schema: "public",
99
+ column_name: "role_id",
100
+ data_type: "integer",
101
+ udt_name: "int4",
102
+ is_nullable: "YES",
103
+ column_default: null,
104
+ character_maximum_length: null,
105
+ numeric_precision: 32,
106
+ numeric_scale: 0,
107
+ ordinal_position: 2,
108
+ description: null,
109
+ },
110
+ ],
111
+ fields: [],
112
+ }));
113
+ responses.set("constraints", () => ({
114
+ rows: [
115
+ {
116
+ table_schema: "public",
117
+ table_name: "users",
118
+ constraint_name: "users_pkey",
119
+ constraint_type: "PRIMARY KEY",
120
+ column_name: "id",
121
+ foreign_table_schema: null,
122
+ foreign_table_name: null,
123
+ foreign_column_name: null,
124
+ },
125
+ {
126
+ table_schema: "public",
127
+ table_name: "users",
128
+ constraint_name: "users_role_id_fkey",
129
+ constraint_type: "FOREIGN KEY",
130
+ column_name: "role_id",
131
+ foreign_table_schema: "public",
132
+ foreign_table_name: "roles",
133
+ foreign_column_name: "id",
134
+ },
135
+ ],
136
+ fields: [],
137
+ }));
138
+ responses.set("indexes", () => ({
139
+ rows: [
140
+ {
141
+ schema_name: "public",
142
+ table_name: "users",
143
+ index_name: "users_pkey",
144
+ indisunique: true,
145
+ column_names: ["id"],
146
+ definition: "CREATE UNIQUE INDEX users_pkey ON public.users USING btree (id)",
147
+ },
148
+ ],
149
+ fields: [],
150
+ }));
151
+ let indexQuerySql = null;
152
+ let lastSql = null;
153
+ const clientFn = vi.fn(async (sql) => {
154
+ lastSql = sql;
155
+ if (/pg_index\s+idx/.test(sql)) {
156
+ indexQuerySql = sql;
157
+ return responses.get("indexes")?.() ?? { rows: [], fields: [] };
158
+ }
159
+ if (sql.includes("FROM pg_class c")) {
160
+ return responses.get("tables")?.() ?? { rows: [], fields: [] };
161
+ }
162
+ if (sql.includes("information_schema.columns")) {
163
+ return responses.get("columns")?.() ?? { rows: [], fields: [] };
164
+ }
165
+ if (sql.includes("table_constraints")) {
166
+ return responses.get("constraints")?.() ?? { rows: [], fields: [] };
167
+ }
168
+ return { rows: [], fields: [] };
169
+ });
170
+ const adapter = new PostgresAdapter(clientFn, {
171
+ database: "app",
172
+ defaultSchema: "public",
173
+ });
174
+ const result = await adapter.introspect();
175
+ if (!indexQuerySql) {
176
+ throw new Error(`index query not executed. last sql: ${lastSql}`);
177
+ }
178
+ expect(result.db.name).toBe("app");
179
+ const table = result.tables[0];
180
+ if (!table)
181
+ throw new Error("expected table");
182
+ expect(table.constraints).toHaveLength(2);
183
+ const fk = table.constraints.find((c) => c.type === "FOREIGN KEY");
184
+ expect(fk?.referencedTable).toBe("public.roles");
185
+ const roleColumn = table.columns.find((c) => c.name === "role_id");
186
+ expect(roleColumn?.isForeignKey).toBe(true);
187
+ expect(table.indexes[0]?.columns).toEqual(["id"]);
188
+ });
189
+ });
190
+ //# sourceMappingURL=introspection.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspection.spec.js","sourceRoot":"","sources":["../../../src/adapters/introspection.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { IntrospectOptions, SchemaIntrospection } from "../schema/types.js";
2
+ import type { DatabaseAdapter, DatabaseExecutionResult } from "./types.js";
3
+ export interface PostgresQueryResult {
4
+ rows: Array<Record<string, unknown>>;
5
+ fields: Array<{
6
+ name: string;
7
+ }>;
8
+ }
9
+ export type PostgresClientFn = (sql: string, params?: unknown[]) => Promise<PostgresQueryResult>;
10
+ export interface PostgresAdapterOptions {
11
+ /** Logical database name used in introspection metadata. */
12
+ database?: string;
13
+ /** Schema to assume when a table is provided without qualification. */
14
+ defaultSchema?: string;
15
+ /** Optional database kind label. Defaults to "postgres". */
16
+ kind?: SchemaIntrospection["db"]["kind"];
17
+ /**
18
+ * Optional allow-list of table names (schema-qualified or bare).
19
+ * When specified, introspection and queries are restricted to these tables only.
20
+ */
21
+ allowedTables?: string[];
22
+ }
23
+ export declare class PostgresAdapter implements DatabaseAdapter {
24
+ private readonly clientFn;
25
+ private readonly databaseName;
26
+ private readonly defaultSchema;
27
+ private readonly kind;
28
+ private readonly allowedTables?;
29
+ constructor(clientFn: PostgresClientFn, options?: PostgresAdapterOptions);
30
+ execute(sql: string, params?: Record<string, string | number | boolean | string[] | number[]>): Promise<DatabaseExecutionResult>;
31
+ /**
32
+ * Validate that the SQL query only references allowed tables.
33
+ * This is a basic validation that extracts table-like patterns from the query.
34
+ */
35
+ private validateQueryTables;
36
+ /**
37
+ * Convert named params to positional array for PostgreSQL
38
+ * PostgreSQL expects $1, $2, $3 in SQL and an array of values [val1, val2, val3]
39
+ * The LLM should generate params like: { '1': 'value1', '2': 'value2' }
40
+ */
41
+ private convertNamedToPositionalParams;
42
+ validate(sql: string, params?: Record<string, string | number | boolean | string[] | number[]>): Promise<void>;
43
+ getDialect(): "postgres";
44
+ introspect(options?: IntrospectOptions): Promise<SchemaIntrospection>;
45
+ }
46
+ //# sourceMappingURL=postgres.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../../src/adapters/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAIV,iBAAiB,EACjB,mBAAmB,EAEpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE3E,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjC;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC7B,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,KACf,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAElC,MAAM,WAAW,sBAAsB;IACrC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAmDD,qBAAa,eAAgB,YAAW,eAAe;IAOnD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAN3B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAoB;gBAGhC,QAAQ,EAAE,gBAAgB,EAC3C,OAAO,GAAE,sBAA2B;IAahC,OAAO,CACX,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,GACvE,OAAO,CAAC,uBAAuB,CAAC;IAiBnC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA6B3B;;;;OAIG;IACH,OAAO,CAAC,8BAA8B;IA8BhC,QAAQ,CACZ,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,GACvE,OAAO,CAAC,IAAI,CAAC;IAUhB,UAAU,IACD,UAAU;IAGb,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAiL5E"}