@molecule/api-database-duckdb 0.0.0-stage → 1.1.1

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 (55) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +772 -2
  3. package/dist/browser-guard.d.ts +2 -0
  4. package/dist/browser-guard.d.ts.map +1 -0
  5. package/dist/browser-guard.js +19 -0
  6. package/dist/browser-guard.js.map +1 -0
  7. package/dist/capabilities.d.ts +30 -0
  8. package/dist/capabilities.d.ts.map +1 -0
  9. package/dist/capabilities.js +48 -0
  10. package/dist/capabilities.js.map +1 -0
  11. package/dist/index.d.ts +115 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +169 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/instances.d.ts +73 -0
  16. package/dist/instances.d.ts.map +1 -0
  17. package/dist/instances.js +117 -0
  18. package/dist/instances.js.map +1 -0
  19. package/dist/lifecycle.d.ts +22 -0
  20. package/dist/lifecycle.d.ts.map +1 -0
  21. package/dist/lifecycle.js +45 -0
  22. package/dist/lifecycle.js.map +1 -0
  23. package/dist/migrator.d.ts +74 -0
  24. package/dist/migrator.d.ts.map +1 -0
  25. package/dist/migrator.js +172 -0
  26. package/dist/migrator.js.map +1 -0
  27. package/dist/pool.d.ts +40 -0
  28. package/dist/pool.d.ts.map +1 -0
  29. package/dist/pool.js +273 -0
  30. package/dist/pool.js.map +1 -0
  31. package/dist/queue.d.ts +48 -0
  32. package/dist/queue.d.ts.map +1 -0
  33. package/dist/queue.js +98 -0
  34. package/dist/queue.js.map +1 -0
  35. package/dist/secrets.d.ts +16 -0
  36. package/dist/secrets.d.ts.map +1 -0
  37. package/dist/secrets.js +25 -0
  38. package/dist/secrets.js.map +1 -0
  39. package/dist/sql-dialect.d.ts +92 -0
  40. package/dist/sql-dialect.d.ts.map +1 -0
  41. package/dist/sql-dialect.js +309 -0
  42. package/dist/sql-dialect.js.map +1 -0
  43. package/dist/store.d.ts +18 -0
  44. package/dist/store.d.ts.map +1 -0
  45. package/dist/store.js +335 -0
  46. package/dist/store.js.map +1 -0
  47. package/dist/types.d.ts +57 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +7 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/utilities.d.ts +119 -0
  52. package/dist/utilities.d.ts.map +1 -0
  53. package/dist/utilities.js +246 -0
  54. package/dist/utilities.js.map +1 -0
  55. package/package.json +87 -4
package/dist/store.js ADDED
@@ -0,0 +1,335 @@
1
+ /**
2
+ * DuckDB DataStore implementation.
3
+ *
4
+ * Translates abstract DataStore CRUD methods to DuckDB SQL. DuckDB binds `?`
5
+ * and `$1` placeholders natively positionally, so the SQL built here needs no
6
+ * conversion on its way to the engine.
7
+ *
8
+ * @module
9
+ */
10
+ import { randomUUID } from 'node:crypto';
11
+ import { getLogger } from '@molecule/api-bond';
12
+ import { assertFindManyOptions, assertOptionalWhereConditions, assertWhereConditions, } from '@molecule/api-database/query-guards.js';
13
+ import { parseJsonColumns } from './utilities.js';
14
+ /**
15
+ * Validates that an identifier (table/column name) is safe for SQL interpolation.
16
+ * Hyphens are allowed: every interpolation site double-quotes the identifier, and
17
+ * inside a quoted identifier only `"` itself is dangerous (still rejected). Real
18
+ * consumers use hyphenated tables (e.g. `@molecule/api-resource-share`'s
19
+ * `"resource-share-links"`) — parity with the postgresql/sqlite bonds.
20
+ */
21
+ const SAFE_IDENTIFIER = /^[a-zA-Z_][a-zA-Z0-9_-]*$/;
22
+ /**
23
+ * Validates that a SQL identifier (table or column name) is safe for interpolation.
24
+ *
25
+ * Table/column names cannot be bound as parameters, so they are interpolated
26
+ * directly into the SQL string. Any value that reaches an interpolation point MUST be
27
+ * validated here — otherwise a caller passing a user-supplied identifier (e.g. a
28
+ * `sort_by` column from a query string) opens a SQL-injection hole. The whitelist of
29
+ * plain `[A-Za-z_][A-Za-z0-9_-]*` identifiers makes the `"..."` quoting unbreakable.
30
+ *
31
+ * @param name - The identifier string to validate.
32
+ */
33
+ function assertSafeIdentifier(name) {
34
+ if (!SAFE_IDENTIFIER.test(name)) {
35
+ throw new Error(`Invalid SQL identifier: ${name}`);
36
+ }
37
+ }
38
+ /**
39
+ * Builds a SQL WHERE clause from WhereCondition[] using ? placeholders.
40
+ *
41
+ * @param conditions - Array of WhereCondition objects to convert to SQL.
42
+ * @returns An object containing the SQL clause string and bound values array.
43
+ */
44
+ function buildWhere(conditions) {
45
+ if (conditions.length === 0) {
46
+ return { clause: '', values: [] };
47
+ }
48
+ const parts = [];
49
+ const values = [];
50
+ for (const cond of conditions) {
51
+ assertSafeIdentifier(cond.field);
52
+ switch (cond.operator) {
53
+ case '=':
54
+ case '!=':
55
+ case '>':
56
+ case '<':
57
+ case '>=':
58
+ case '<=':
59
+ // A list given to a one-value operator matches nothing on every store: say so, the way
60
+ // 'in' given a scalar does.
61
+ if (Array.isArray(cond.value)) {
62
+ throw new Error(`'${cond.operator}' operator takes one value, not a list (field "${cond.field}"); use 'in' for a list`);
63
+ }
64
+ parts.push(`"${cond.field}" ${cond.operator} ?`);
65
+ values.push(cond.value);
66
+ break;
67
+ case 'in': {
68
+ const arr = cond.value;
69
+ if (!Array.isArray(arr)) {
70
+ throw new Error(`'${cond.operator}' operator requires an array value (field "${cond.field}")`);
71
+ }
72
+ if (arr.length === 0) {
73
+ // `IN ()` is a syntax error; match Postgres `= ANY('{}')` semantics: no match.
74
+ parts.push('1 = 0');
75
+ break;
76
+ }
77
+ const placeholders = arr.map(() => '?').join(', ');
78
+ parts.push(`"${cond.field}" IN (${placeholders})`);
79
+ values.push(...arr);
80
+ break;
81
+ }
82
+ case 'not_in': {
83
+ const arr = cond.value;
84
+ if (!Array.isArray(arr)) {
85
+ throw new Error(`'${cond.operator}' operator requires an array value (field "${cond.field}")`);
86
+ }
87
+ if (arr.length === 0) {
88
+ // `NOT IN ()` is a syntax error; match Postgres `!= ALL('{}')`: everything matches.
89
+ parts.push('1 = 1');
90
+ break;
91
+ }
92
+ const placeholders = arr.map(() => '?').join(', ');
93
+ parts.push(`"${cond.field}" NOT IN (${placeholders})`);
94
+ values.push(...arr);
95
+ break;
96
+ }
97
+ case 'like':
98
+ // Case-insensitive RAW pattern match — the caller supplies the full SQL
99
+ // pattern (their own %/_ wildcards are honored, NOT escaped). LOWER()
100
+ // both sides for the documented core contract: `like` must be
101
+ // case-insensitive and IDENTICAL across every bond (DuckDB's own LIKE
102
+ // is case-sensitive; ILIKE exists but LIKE + LOWER() keeps the exact
103
+ // sqlite/mysql spelling of the contract). ESCAPE '\' pins backslash as
104
+ // THE escape character in the caller's pattern.
105
+ parts.push(`LOWER("${cond.field}") LIKE LOWER(?) ESCAPE '\\'`);
106
+ values.push(cond.value);
107
+ break;
108
+ case 'ilike':
109
+ // Case-insensitive CONTAINS on a literal substring — the documented core
110
+ // contract (`@molecule/api-database` WhereCondition): escape the value's
111
+ // LIKE metacharacters, wrap with `%…%`.
112
+ parts.push(`LOWER("${cond.field}") LIKE LOWER(?) ESCAPE '\\'`);
113
+ values.push(`%${String(cond.value).replace(/[%_\\]/g, '\\$&')}%`);
114
+ break;
115
+ case 'is_null':
116
+ parts.push(`"${cond.field}" IS NULL`);
117
+ break;
118
+ case 'is_not_null':
119
+ parts.push(`"${cond.field}" IS NOT NULL`);
120
+ break;
121
+ default:
122
+ // Parity with the postgres/sqlite bonds: an unknown operator must FAIL
123
+ // LOUDLY, not silently drop the condition (which would return unfiltered rows).
124
+ throw new Error(`Invalid SQL operator: ${String(cond.operator)}. The operators are lowercase: =, !=, >, <, >=, <=, in, not_in, like, ilike, is_null, is_not_null.`);
125
+ }
126
+ }
127
+ return { clause: `WHERE ${parts.join(' AND ')}`, values };
128
+ }
129
+ /**
130
+ * Builds an ORDER BY clause.
131
+ *
132
+ * @param orderBy - Array of field/direction pairs to sort by.
133
+ * @returns A SQL ORDER BY clause string, or an empty string if none provided.
134
+ */
135
+ function buildOrderBy(orderBy) {
136
+ if (!orderBy || orderBy.length === 0)
137
+ return '';
138
+ return `ORDER BY ${orderBy
139
+ .map((o) => {
140
+ assertSafeIdentifier(o.field);
141
+ // Whitelist the direction to exactly ASC/DESC — never interpolate an
142
+ // arbitrary `toUpperCase()` of caller input into the SQL string.
143
+ const dir = o.direction.toLowerCase() === 'desc' ? 'DESC' : 'ASC';
144
+ return `"${o.field}" ${dir}`;
145
+ })
146
+ .join(', ')}`;
147
+ }
148
+ /**
149
+ * Creates a DataStore backed by a DuckDB DatabasePool.
150
+ *
151
+ * @param pool - The DuckDB DatabasePool to use for queries.
152
+ * @returns A DataStore that translates CRUD operations to DuckDB-compatible SQL.
153
+ */
154
+ export function createStore(pool) {
155
+ // Cache of "this table's JSON-typed columns" so rows read back through the
156
+ // CRUD helpers carry parsed values, not JSON text.
157
+ const jsonColumnsCache = new Map();
158
+ /**
159
+ * The JSON-typed columns of a table, lower-cased (cached). DuckDB's `JSON`
160
+ * type is an alias over VARCHAR, so a JSON column reads as its JSON text and
161
+ * the column's type is visible ONLY in `information_schema.columns` — never
162
+ * in the result metadata. Without this, a `meta` JSON column round-trips as
163
+ * a string through `create()`/`findMany()` on this bond while the same row
164
+ * parses on the postgresql/sqlite bonds.
165
+ *
166
+ * @param table - The table name to introspect.
167
+ * @returns Its JSON-typed column names, lower-cased.
168
+ */
169
+ function jsonColumnsFor(table) {
170
+ const cached = jsonColumnsCache.get(table);
171
+ if (cached)
172
+ return cached;
173
+ const query = pool
174
+ .query("SELECT column_name FROM information_schema.columns WHERE table_name = ? AND data_type = 'JSON'", [table])
175
+ .then((result) => new Set(result.rows.map((row) => String(row.column_name).toLowerCase())))
176
+ .catch((error) => {
177
+ // A missing table has no JSON columns either; the caller's own query
178
+ // against it will name the real problem, so only log here.
179
+ getLogger().warn('DuckDB: could not list JSON columns', {
180
+ error,
181
+ table,
182
+ });
183
+ return new Set();
184
+ });
185
+ jsonColumnsCache.set(table, query);
186
+ return query;
187
+ }
188
+ /**
189
+ * Run a query for `table`, parsing its JSON columns back into values and
190
+ * naming the table in a column/table error (DuckDB's "does not exist" errors
191
+ * name neither — the same gap the sqlite store patches with `queryOn`).
192
+ *
193
+ * @param table - The table the statement is for.
194
+ * @param sql - The statement.
195
+ * @param values - Its parameters.
196
+ * @returns The query result with JSON columns parsed.
197
+ */
198
+ async function queryOn(table, sql, values) {
199
+ let result;
200
+ try {
201
+ result = await pool.query(sql, values);
202
+ }
203
+ catch (error) {
204
+ if (error instanceof Error &&
205
+ /does not exist|referenced table .* not found|no matching entry/i.test(error.message) &&
206
+ !error.message.includes(`(table "${table}")`)) {
207
+ error.message = `${error.message} (table "${table}")`;
208
+ }
209
+ throw error;
210
+ }
211
+ return {
212
+ rows: parseJsonColumns(result.rows, await jsonColumnsFor(table)),
213
+ rowCount: result.rowCount,
214
+ };
215
+ }
216
+ return {
217
+ async findById(table, id) {
218
+ assertSafeIdentifier(table);
219
+ const result = await queryOn(table, `SELECT * FROM "${table}" WHERE "id" = ? LIMIT 1`, [
220
+ id,
221
+ ]);
222
+ return result.rows[0] ?? null;
223
+ },
224
+ async findOne(table, where) {
225
+ assertSafeIdentifier(table);
226
+ assertWhereConditions(where, 'findOne');
227
+ const { clause, values } = buildWhere(where);
228
+ const result = await queryOn(table, `SELECT * FROM "${table}" ${clause} LIMIT 1`, values);
229
+ return result.rows[0] ?? null;
230
+ },
231
+ async findMany(table, options) {
232
+ assertSafeIdentifier(table);
233
+ assertFindManyOptions(options);
234
+ const { clause, values } = buildWhere(options?.where ?? []);
235
+ const selectFields = options?.select
236
+ ?.map((s) => {
237
+ assertSafeIdentifier(s);
238
+ return `"${s}"`;
239
+ })
240
+ .join(', ') ?? '*';
241
+ const orderBy = buildOrderBy(options?.orderBy);
242
+ // Safety cap: if caller doesn't specify a limit, apply a default to prevent
243
+ // unbounded queries from returning millions of rows and exhausting memory.
244
+ const MAX_DEFAULT_LIMIT = 10_000;
245
+ const effectiveLimit = Math.max(0, Math.min(Number(options?.limit ?? MAX_DEFAULT_LIMIT), MAX_DEFAULT_LIMIT));
246
+ const limit = `LIMIT ${effectiveLimit}`;
247
+ // Validate offset as a non-negative integer to prevent SQL injection.
248
+ const safeOffset = options?.offset != null ? Math.max(0, Math.floor(Number(options.offset))) : 0;
249
+ const offset = safeOffset > 0 ? `OFFSET ${safeOffset}` : '';
250
+ const sql = `SELECT ${selectFields} FROM "${table}" ${clause} ${orderBy} ${limit} ${offset}`.trim();
251
+ const result = await queryOn(table, sql, values);
252
+ return result.rows;
253
+ },
254
+ async count(table, where) {
255
+ assertSafeIdentifier(table);
256
+ assertOptionalWhereConditions(where);
257
+ const { clause, values } = buildWhere(where ?? []);
258
+ const result = await queryOn(table, `SELECT COUNT(*) AS "count" FROM "${table}" ${clause}`, values);
259
+ return Number(result.rows[0]?.count ?? 0);
260
+ },
261
+ async create(table, data) {
262
+ assertSafeIdentifier(table);
263
+ // The documented bare-create pattern — create('table', { ...fields }) with
264
+ // no explicit id — relies on the row getting an id. A hand-written
265
+ // migration may declare `id uuid NOT NULL` with no DEFAULT, so generate
266
+ // one when the caller omits it (no-op when supplied; composite-PK join
267
+ // tables without an id column are handled by the engine's own error).
268
+ if (data.id == null) {
269
+ data = { id: randomUUID(), ...data };
270
+ }
271
+ const keys = Object.keys(data);
272
+ for (const k of keys)
273
+ assertSafeIdentifier(k);
274
+ const columns = keys.map((k) => `"${k}"`).join(', ');
275
+ const placeholders = keys.map(() => '?').join(', ');
276
+ const values = keys.map((k) => data[k]);
277
+ const result = await queryOn(table, `INSERT INTO "${table}" (${columns}) VALUES (${placeholders}) RETURNING *`, values);
278
+ return { data: result.rows[0] ?? null, affected: result.rowCount ?? 0 };
279
+ },
280
+ async updateById(table, id, data) {
281
+ assertSafeIdentifier(table);
282
+ const keys = Object.keys(data);
283
+ // No-op when there are no fields to update — return the existing row
284
+ // so callers see `affected: 1` for known-id reads (parity with the
285
+ // postgres/sqlite bonds). Issuing an UPDATE with an empty SET clause is
286
+ // a SQL syntax error.
287
+ if (keys.length === 0) {
288
+ const existing = await queryOn(table, `SELECT * FROM "${table}" WHERE "id" = ? LIMIT 1`, [id]);
289
+ return { data: existing.rows[0] ?? null, affected: existing.rows.length };
290
+ }
291
+ for (const k of keys)
292
+ assertSafeIdentifier(k);
293
+ const setClauses = keys.map((k) => `"${k}" = ?`).join(', ');
294
+ const values = [...keys.map((k) => data[k]), id];
295
+ const result = await queryOn(table, `UPDATE "${table}" SET ${setClauses} WHERE "id" = ? RETURNING *`, values);
296
+ return { data: result.rows[0] ?? null, affected: result.rowCount ?? 0 };
297
+ },
298
+ async updateMany(table, where, data) {
299
+ assertWhereConditions(where, 'updateMany');
300
+ // Refuse an empty WHERE — parity with the postgres/sqlite bonds; an empty
301
+ // `where` would become an UNSCOPED full-table UPDATE.
302
+ if (where.length === 0) {
303
+ throw new Error('updateMany requires at least one WHERE condition to prevent accidental full-table updates');
304
+ }
305
+ assertSafeIdentifier(table);
306
+ const keys = Object.keys(data);
307
+ for (const k of keys)
308
+ assertSafeIdentifier(k);
309
+ const setClauses = keys.map((k) => `"${k}" = ?`).join(', ');
310
+ const setValues = keys.map((k) => data[k]);
311
+ const { clause, values: whereValues } = buildWhere(where);
312
+ const values = [...setValues, ...whereValues];
313
+ const result = await queryOn(table, `UPDATE "${table}" SET ${setClauses} ${clause}`, values);
314
+ return { data: null, affected: result.rowCount ?? 0 };
315
+ },
316
+ async deleteById(table, id) {
317
+ assertSafeIdentifier(table);
318
+ const result = await queryOn(table, `DELETE FROM "${table}" WHERE "id" = ?`, [id]);
319
+ return { data: null, affected: result.rowCount ?? 0 };
320
+ },
321
+ async deleteMany(table, where) {
322
+ assertWhereConditions(where, 'deleteMany');
323
+ // Refuse an empty WHERE — parity with the postgres/sqlite bonds (else an
324
+ // empty `where` becomes an UNSCOPED full-table DELETE).
325
+ if (where.length === 0) {
326
+ throw new Error('deleteMany requires at least one WHERE condition to prevent accidental full-table deletes');
327
+ }
328
+ assertSafeIdentifier(table);
329
+ const { clause, values } = buildWhere(where);
330
+ const result = await queryOn(table, `DELETE FROM "${table}" ${clause}`, values);
331
+ return { data: null, affected: result.rowCount ?? 0 };
332
+ },
333
+ };
334
+ }
335
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Type definitions for the DuckDB database provider.
3
+ *
4
+ * @module
5
+ */
6
+ /**
7
+ * Configuration for the DuckDB database provider.
8
+ */
9
+ export interface DuckdbConfig {
10
+ /**
11
+ * Path of the DuckDB database file — created on first open — or `':memory:'`
12
+ * for a database that lives only for the process's lifetime. Defaults to the
13
+ * `DUCKDB_PATH` env var, then `'./data/app.duckdb'`.
14
+ */
15
+ path?: string;
16
+ /**
17
+ * DuckDB `memory_limit` for the instance. DuckDB's own default is 80% of
18
+ * system RAM, which on a shared VM lets one query evict everything else, so
19
+ * this bond caps it at `'1GB'` by default. Accepts DuckDB size strings
20
+ * (`'512MB'`, `'2GB'`) or a plain byte count as a string. Also settable via
21
+ * the `DUCKDB_MEMORY_LIMIT` env var.
22
+ */
23
+ memoryLimit?: string;
24
+ /**
25
+ * DuckDB `threads` for the instance. DuckDB's own default is every CPU core,
26
+ * which oversubscribes a shared host, so this bond caps it at `4` by default.
27
+ * Also settable via the `DUCKDB_THREADS` env var.
28
+ */
29
+ threads?: number;
30
+ /**
31
+ * Open the database read-only (`access_mode = 'READ_ONLY'`). Multiple
32
+ * processes may read one file concurrently; only read-write mode is
33
+ * exclusive, so a read-only pool never fights an app holding the write lock.
34
+ */
35
+ readOnly?: boolean;
36
+ /**
37
+ * Extra DuckDB settings handed to `DuckDBInstance.fromCache(path, options)`
38
+ * as-is (a flat `Record<string, string>` of setting name → value). Entries
39
+ * here win over the `memoryLimit`/`threads`/`readOnly` fields.
40
+ */
41
+ config?: Record<string, string>;
42
+ /**
43
+ * How long (ms) a query, `connect()` or `transaction()` waits for the single
44
+ * connection before failing with an error that says who is holding it.
45
+ * Defaults to 30 000.
46
+ */
47
+ acquireTimeoutMillis?: number;
48
+ }
49
+ /**
50
+ * Environment variables consumed by the DuckDB database provider.
51
+ */
52
+ export interface ProcessEnv {
53
+ DUCKDB_PATH?: string;
54
+ DUCKDB_MEMORY_LIMIT?: string;
55
+ DUCKDB_THREADS?: string;
56
+ }
57
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Type definitions for the DuckDB database provider.
3
+ *
4
+ * @module
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Utility functions for DuckDB operations.
3
+ *
4
+ * @module
5
+ */
6
+ import { type DuckDBValue } from '@duckdb/node-api';
7
+ import type { SqlCompatibilityIssue, SqlFeature } from '@molecule/api-database/sql-compatibility.js';
8
+ /**
9
+ * Options for {@link translateDdlToDuckdb}.
10
+ */
11
+ export interface TranslateDdlOptions {
12
+ /** File name the SQL came from; copied into an unsupported-construct error. */
13
+ source?: string;
14
+ }
15
+ /**
16
+ * The error this bond's translator throws when a migration needs a construct
17
+ * DuckDB cannot honour. Named and typed so a caller can tell a genuine dialect
18
+ * limit apart from malformed SQL, and report it without a migration run.
19
+ *
20
+ * The diagnostic itself is described by the core TYPE contract
21
+ * ({@link SqlCompatibilityIssue}); this class is the bond's own error
22
+ * construction, next to the translation that raises it.
23
+ */
24
+ export declare class UnsupportedSqlFeatureError extends Error {
25
+ /** The construct's feature. */
26
+ readonly feature: SqlFeature;
27
+ /** The exact construct found in the migration. */
28
+ readonly detail: string;
29
+ /** Where the statement came from, when known. */
30
+ readonly source?: string;
31
+ /**
32
+ * Build the error from a compatibility diagnostic, copying its message and fields.
33
+ *
34
+ * @param issue - The diagnostic being refused.
35
+ */
36
+ constructor(issue: SqlCompatibilityIssue);
37
+ }
38
+ /**
39
+ * Translate PostgreSQL-dialect DDL to DuckDB-compatible DDL at migration time.
40
+ *
41
+ * Resource/template setup migrations are authored in PostgreSQL dialect. DuckDB
42
+ * 2.0 already speaks most of it natively — `uuid`/`timestamptz`/`bytea`/`text[]`
43
+ * type names, `gen_random_uuid()`, `now()`, `CURRENT_TIMESTAMP`, `::` casts,
44
+ * `ADD COLUMN IF NOT EXISTS`, `DROP COLUMN IF EXISTS`, `ON CONFLICT`, `ILIKE` —
45
+ * all verified against 2.0.0-r.1. The constructs it rejects are rewritten here,
46
+ * and only where the rewrite preserves behaviour:
47
+ *
48
+ * - `jsonb` → `json`, in both the column-type position and the `::jsonb` cast
49
+ * (DuckDB has a `JSON` type, stored as VARCHAR; there is no `jsonb`).
50
+ * - `USING <method>` on a `CREATE INDEX` (`gin`/`btree`/`hash`/`gist`) →
51
+ * removed: DuckDB indexes have no access method.
52
+ * - A partial index gets no `WHERE` support in DuckDB. A non-unique partial
53
+ * index becomes a full index on the same columns — the predicate only narrows
54
+ * which rows the index covers, never a query's result. A UNIQUE partial index
55
+ * becomes a UNIQUE index over `CASE WHEN <predicate> THEN <column> END` per
56
+ * column: rows outside the predicate get NULL keys (distinct in DuckDB), so
57
+ * uniqueness applies to exactly the rows PostgreSQL would constrain.
58
+ *
59
+ * What it does NOT rewrite is an `ON DELETE`/`ON UPDATE` referential action
60
+ * (`CASCADE`, `SET NULL`, `SET DEFAULT`): DuckDB rejects the clause at parse
61
+ * time and has no triggers, so dropping it would turn a cascading delete into a
62
+ * refusing one. Such SQL throws {@link UnsupportedSqlFeatureError}, naming the
63
+ * construct — see {@link sqlCapabilities}. The compatibility preflight in the
64
+ * generator rejects those resource/provider combinations before an app exists;
65
+ * this throw is the last line of defence for SQL that reaches the runner another
66
+ * way.
67
+ *
68
+ * Everything else passes through untouched — unlike the sqlite bond, no
69
+ * placeholder conversion or timestamp-default rewriting happens here.
70
+ *
71
+ * @param sql - Raw migration SQL, possibly in Postgres dialect.
72
+ * @param options - The source file name used in an unsupported-construct error.
73
+ * @returns DuckDB-compatible SQL.
74
+ * @throws {UnsupportedSqlFeatureError} When the SQL needs a construct DuckDB
75
+ * cannot reproduce without changing its behaviour.
76
+ */
77
+ export declare const translateDdlToDuckdb: (sql: string, options?: TranslateDdlOptions) => string;
78
+ /**
79
+ * Coerce a JS value into something `@duckdb/node-api` can bind. The client
80
+ * infers a parameter's type from the VALUE and only understands `null`,
81
+ * booleans, numbers, bigints and strings — anything else fails at bind time
82
+ * with `Cannot create values of type ANY. Specify a specific type.`, which
83
+ * would crash every `create()`/`update()` that passes a `Date`, a boolean-ish
84
+ * object or a jsonb value. Strings cast on the way in: DuckDB implicitly casts
85
+ * a bound VARCHAR to UUID/TIMESTAMPTZ/DECIMAL/JSON/LIST parameters, verified
86
+ * against 2.0.0-r.1.
87
+ *
88
+ * @param value - The value to bind.
89
+ * @returns A `@duckdb/node-api`-bindable value.
90
+ */
91
+ export declare const coerceDuckdbParam: (value: unknown) => DuckDBValue;
92
+ /**
93
+ * Normalize DuckDB result rows to the JS shapes the other database bonds hand
94
+ * back. DuckDB's JS conversion returns a `bigint` for every 64+-bit integer —
95
+ * `COUNT(*)`, `BIGINT` and `HUGEINT` columns — and `JSON.stringify` THROWS on a
96
+ * bigint, so a handler that serializes a row with `COUNT(*)` in it would 500.
97
+ * A bigint within `Number.MAX_SAFE_INTEGER` becomes a JS number (matching the
98
+ * sqlite bond); a larger one becomes its decimal string (matching node-postgres
99
+ * `int8AsString`). Mutates rows in place for speed.
100
+ *
101
+ * @param rows - Row objects from `result.getRowObjectsJS()`.
102
+ * @returns The normalized rows.
103
+ */
104
+ export declare const normalizeDuckdbRows: <T>(rows: Record<string, unknown>[]) => T[];
105
+ /**
106
+ * Parse the JSON-typed columns of a table's rows into values, matching what
107
+ * the postgresql/sqlite bonds hand back from a `json`/`jsonb` column. DuckDB's
108
+ * `JSON` type is an alias over VARCHAR, so a JSON column always READS as its
109
+ * JSON text — the column's type is only visible in
110
+ * `information_schema.columns.data_type`, never in the result metadata, which
111
+ * is why this runs in the DataStore (it knows the table) and not in the pool.
112
+ * A value that is not valid JSON text is left as the raw string.
113
+ *
114
+ * @param rows - Row objects.
115
+ * @param jsonColumns - The table's JSON-typed column names, lower-cased.
116
+ * @returns The rows with JSON columns parsed.
117
+ */
118
+ export declare const parseJsonColumns: <T>(rows: Record<string, unknown>[], jsonColumns: Set<string>) => T[];
119
+ //# sourceMappingURL=utilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,6CAA6C,CAAA;AAUpG;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;GAQG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,+BAA+B;IAC/B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,iDAAiD;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IAExB;;;;OAIG;gBACS,KAAK,EAAE,qBAAqB;CAOzC;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,oBAAoB,GAAI,KAAK,MAAM,EAAE,UAAS,mBAAwB,KAAG,MAarF,CAAA;AAqCD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,WAiBlD,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAG,CAAC,EAazE,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,EAChC,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,aAAa,GAAG,CAAC,MAAM,CAAC,KACvB,CAAC,EAgBH,CAAA"}