@sqlrooms/duckdb-core 0.26.1-rc.5

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.md +9 -0
  2. package/README.md +387 -0
  3. package/dist/BaseDuckDbConnector.d.ts +20 -0
  4. package/dist/BaseDuckDbConnector.d.ts.map +1 -0
  5. package/dist/BaseDuckDbConnector.js +122 -0
  6. package/dist/BaseDuckDbConnector.js.map +1 -0
  7. package/dist/DuckDbConnector.d.ts +312 -0
  8. package/dist/DuckDbConnector.d.ts.map +1 -0
  9. package/dist/DuckDbConnector.js +2 -0
  10. package/dist/DuckDbConnector.js.map +1 -0
  11. package/dist/arrow-utils.d.ts +8 -0
  12. package/dist/arrow-utils.d.ts.map +1 -0
  13. package/dist/arrow-utils.js +28 -0
  14. package/dist/arrow-utils.js.map +1 -0
  15. package/dist/duckdb-utils.d.ts +140 -0
  16. package/dist/duckdb-utils.d.ts.map +1 -0
  17. package/dist/duckdb-utils.js +290 -0
  18. package/dist/duckdb-utils.js.map +1 -0
  19. package/dist/index.d.ts +12 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +8 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/load/create.d.ts +33 -0
  24. package/dist/load/create.d.ts.map +1 -0
  25. package/dist/load/create.js +33 -0
  26. package/dist/load/create.js.map +1 -0
  27. package/dist/load/load.d.ts +57 -0
  28. package/dist/load/load.d.ts.map +1 -0
  29. package/dist/load/load.js +153 -0
  30. package/dist/load/load.js.map +1 -0
  31. package/dist/load/sql-from.d.ts +18 -0
  32. package/dist/load/sql-from.d.ts.map +1 -0
  33. package/dist/load/sql-from.js +69 -0
  34. package/dist/load/sql-from.js.map +1 -0
  35. package/dist/schema-tree/schemaTree.d.ts +9 -0
  36. package/dist/schema-tree/schemaTree.d.ts.map +1 -0
  37. package/dist/schema-tree/schemaTree.js +75 -0
  38. package/dist/schema-tree/schemaTree.js.map +1 -0
  39. package/dist/schema-tree/typeCategories.d.ts +16 -0
  40. package/dist/schema-tree/typeCategories.d.ts.map +1 -0
  41. package/dist/schema-tree/typeCategories.js +72 -0
  42. package/dist/schema-tree/typeCategories.js.map +1 -0
  43. package/dist/schema-tree/types.d.ts +28 -0
  44. package/dist/schema-tree/types.d.ts.map +1 -0
  45. package/dist/schema-tree/types.js +2 -0
  46. package/dist/schema-tree/types.js.map +1 -0
  47. package/dist/typedRowAccessor.d.ts +19 -0
  48. package/dist/typedRowAccessor.d.ts.map +1 -0
  49. package/dist/typedRowAccessor.js +45 -0
  50. package/dist/typedRowAccessor.js.map +1 -0
  51. package/dist/types.d.ts +21 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/package.json +42 -0
@@ -0,0 +1,312 @@
1
+ import { LoadFileOptions, StandardLoadOptions } from '@sqlrooms/room-config';
2
+ import * as arrow from 'apache-arrow';
3
+ import { TypeMap } from 'apache-arrow';
4
+ /**
5
+ * Options for query execution
6
+ */
7
+ export interface QueryOptions {
8
+ /**
9
+ * Optional external abort signal for coordinated cancellation.
10
+ * When provided, the query will be cancelled if this signal is aborted.
11
+ * This enables powerful composition patterns like cancelling multiple
12
+ * queries together or integrating with other cancellable operations.
13
+ */
14
+ signal?: AbortSignal;
15
+ }
16
+ /**
17
+ * Handle for managing query execution and cancellation.
18
+ *
19
+ * It is **Promise-like**, so you can either:
20
+ *
21
+ * • `await handle` – the most ergonomic form, or
22
+ * • `await handle.result` – kept for backwards-compatibility.
23
+ *
24
+ * Additional capabilities:
25
+ * • Standard Promise API: `.then()`, `.catch()`, `.finally()`
26
+ * • `handle.cancel()` – cancel the running query.
27
+ * • `handle.signal` – `AbortSignal` that fires when the query is cancelled.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Simple usage
32
+ * const handle = connector.query('SELECT * FROM table');
33
+ * const table = await handle; // no .result needed
34
+ *
35
+ * // With cancellation
36
+ * const controller = new AbortController();
37
+ * const handle = connector.query('SELECT * FROM large_table', { signal: controller.signal });
38
+ * setTimeout(() => controller.abort(), 5000);
39
+ *
40
+ * // Manual cancel via the handle
41
+ * const h = connector.query('SELECT * FROM table');
42
+ * await someCondition;
43
+ * await h.cancel();
44
+ *
45
+ * // Composable cancellation (multiple queries, one controller)
46
+ * const controller = new AbortController();
47
+ * const h1 = connector.query('SELECT * FROM table1', { signal: controller.signal });
48
+ * const h2 = connector.query('SELECT * FROM table2', { signal: controller.signal });
49
+ * // Later...
50
+ * controller.abort(); // Cancels h1 and h2 together
51
+ *
52
+ * // Using Promise utilities
53
+ * const [t1, t2] = await Promise.all([
54
+ * connector.query('select 1'),
55
+ * connector.query('select 2')
56
+ * ]);
57
+ * ```
58
+ */
59
+ export type QueryHandle<T = any> = PromiseLike<T> & {
60
+ /** Promise that resolves with query results */
61
+ result: Promise<T>;
62
+ /**
63
+ * Method to cancel the query with optional cleanup.
64
+ * This provides a clean abstraction over the underlying cancellation mechanism.
65
+ */
66
+ cancel: () => Promise<void>;
67
+ /**
68
+ * Read-only access to the abort signal for composability.
69
+ *
70
+ * Key benefits:
71
+ * - **Event-driven**: Listen for abort events to update UI or perform cleanup
72
+ * - **Integration**: Use with other Web APIs like fetch() that accept AbortSignal
73
+ * - **Status checking**: Check if query is already cancelled with signal.aborted
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * // Listen for cancellation events
78
+ * handle.signal.addEventListener('abort', () => {
79
+ * console.log('Query cancelled');
80
+ * updateUI('Operation cancelled');
81
+ * });
82
+ *
83
+ * // Check cancellation status
84
+ * if (handle.signal.aborted) {
85
+ * console.log('Query was already cancelled');
86
+ * }
87
+ *
88
+ * // Use with other APIs
89
+ * const response = await fetch('/api/data', { signal: handle.signal });
90
+ * ```
91
+ */
92
+ signal: AbortSignal;
93
+ /** Attach a callback for only the rejection of the Promise */
94
+ catch: Promise<T>['catch'];
95
+ /** Attach a callback that's invoked when the Promise is settled (fulfilled or rejected) */
96
+ finally: Promise<T>['finally'];
97
+ };
98
+ /**
99
+ * DuckDB connector interface with advanced query cancellation support
100
+ *
101
+ * This interface provides a hybrid approach that combines the simplicity of method-based
102
+ * cancellation with the composability of Web Standards (AbortController/AbortSignal).
103
+ *
104
+ * ## Key Benefits of This Design
105
+ *
106
+ * ### 🔗 Composability
107
+ * Cancel multiple queries with a single controller:
108
+ * ```typescript
109
+ * const controller = new AbortController();
110
+ * const query1 = connector.query('SELECT * FROM table1', { signal: controller.signal });
111
+ * const query2 = connector.query('SELECT * FROM table2', { signal: controller.signal });
112
+ * controller.abort(); // Cancels both queries
113
+ * ```
114
+ *
115
+ * ### 🌐 Integration with Web APIs
116
+ * Use the same signal for queries and HTTP requests:
117
+ * ```typescript
118
+ * const controller = new AbortController();
119
+ * const queryHandle = connector.query('SELECT * FROM table', { signal: controller.signal });
120
+ * const response = await fetch('/api/data', { signal: controller.signal });
121
+ * // controller.abort() cancels both the query and the HTTP request
122
+ * ```
123
+ *
124
+ * ### 🎛️ Flexibility
125
+ * Simple usage when you don't need external control, advanced when you do:
126
+ * ```typescript
127
+ * // Simple - internal cancellation management
128
+ * const handle = connector.query('SELECT * FROM table');
129
+ * handle.cancel();
130
+ *
131
+ * // Advanced - external cancellation control
132
+ * const controller = new AbortController();
133
+ * const handle = connector.query('SELECT * FROM table', { signal: controller.signal });
134
+ * controller.abort();
135
+ * ```
136
+ *
137
+ * ### 📡 Event-Driven
138
+ * React to cancellation events for better UX:
139
+ * ```typescript
140
+ * handle.signal.addEventListener('abort', () => {
141
+ * showNotification('Query cancelled');
142
+ * hideLoadingSpinner();
143
+ * });
144
+ * ```
145
+ *
146
+ * ### ⏱️ Timeout Support
147
+ * Built-in timeout capability with manual override:
148
+ * ```typescript
149
+ * const timeoutController = new AbortController();
150
+ * setTimeout(() => timeoutController.abort(), 30000); // 30s timeout
151
+ *
152
+ * const handle = connector.query('SELECT * FROM large_table', {
153
+ * signal: timeoutController.signal
154
+ * });
155
+ *
156
+ * // User can still cancel manually
157
+ * cancelButton.onclick = () => timeoutController.abort();
158
+ * ```
159
+ *
160
+ * ### 🏗️ Signal Composition
161
+ * Combine multiple cancellation sources:
162
+ * ```typescript
163
+ * function combineSignals(...signals: AbortSignal[]): AbortSignal {
164
+ * const controller = new AbortController();
165
+ * signals.forEach(signal => {
166
+ * if (signal.aborted) controller.abort();
167
+ * else signal.addEventListener('abort', () => controller.abort());
168
+ * });
169
+ * return controller.signal;
170
+ * }
171
+ *
172
+ * const userSignal = userController.signal;
173
+ * const timeoutSignal = createTimeoutSignal(30000);
174
+ * const combinedSignal = combineSignals(userSignal, timeoutSignal);
175
+ *
176
+ * const handle = connector.query('SELECT * FROM table', { signal: combinedSignal });
177
+ * ```
178
+ */
179
+ export interface DuckDbConnector {
180
+ /**
181
+ * Initialize the connector.
182
+ * The function returns a promise that resolves when the connector is initialized.
183
+ * Calling the initialize() function multiple times should not restart the initialization.
184
+ * See BaseDuckDbConnector for an implementation example.
185
+ */
186
+ initialize(): Promise<void>;
187
+ /**
188
+ * Destroy the connector and clean up resources
189
+ */
190
+ destroy(): Promise<void>;
191
+ /**
192
+ * Execute a SQL query without returning a result
193
+ *
194
+ * @param sql SQL query to execute
195
+ * @param options Optional query options including abort signal for coordinated cancellation
196
+ * @returns QueryHandle containing:
197
+ * - result: Promise that resolves when execution completes
198
+ * - cancel: Method to cancel the query with cleanup
199
+ * - signal: AbortSignal for composability with other cancellable operations
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * // Simple execution
204
+ * const handle = connector.execute('CREATE TABLE test AS SELECT * FROM source');
205
+ * await handle.result;
206
+ *
207
+ * // With external cancellation control
208
+ * const controller = new AbortController();
209
+ * const handle = connector.execute('DROP TABLE large_table', {
210
+ * signal: controller.signal
211
+ * });
212
+ *
213
+ * // Cancel if it takes too long
214
+ * setTimeout(() => controller.abort(), 5000);
215
+ * ```
216
+ */
217
+ execute(sql: string, options?: QueryOptions): QueryHandle;
218
+ /**
219
+ * Execute a SQL query and return the result as an Arrow table
220
+ *
221
+ * @param query SQL query to execute
222
+ * @param options Optional query options including abort signal for coordinated cancellation
223
+ * @returns QueryHandle containing:
224
+ * - result: Promise that resolves with Arrow table
225
+ * - cancel: Method to cancel the query with cleanup
226
+ * - signal: AbortSignal for composability with other cancellable operations
227
+ *
228
+ * @example
229
+ * ```typescript
230
+ * // Basic query
231
+ * const handle = await connector.query('SELECT * FROM users WHERE active = true');
232
+ * console.log(`Found ${table.numRows} active users`);
233
+ *
234
+ * // Query with timeout
235
+ * const controller = new AbortController();
236
+ * setTimeout(() => controller.abort(), 30000); // 30s timeout
237
+ *
238
+ * const handle = connector.query('SELECT * FROM very_large_table', {
239
+ * signal: controller.signal
240
+ * });
241
+ *
242
+ * try {
243
+ * const result = await handle;
244
+ * console.log('Query completed within timeout');
245
+ * } catch (error) {
246
+ * if (error.name === 'AbortError') {
247
+ * console.log('Query timed out');
248
+ * }
249
+ * }
250
+ * ```
251
+ */
252
+ query<T extends TypeMap = any>(query: string, options?: QueryOptions): QueryHandle<arrow.Table<T>>;
253
+ /**
254
+ * Execute a SQL query and return the result as a JSON object
255
+ *
256
+ * @param query SQL query to execute
257
+ * @param options Optional query options including abort signal for coordinated cancellation
258
+ * @returns QueryHandle containing:
259
+ * - result: Promise that resolves with iterable of JSON objects
260
+ * - cancel: Method to cancel the query with cleanup
261
+ * - signal: AbortSignal for composability with other cancellable operations
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * // Simple JSON query
266
+ * const users = await connector.queryJson('SELECT name, email FROM users LIMIT 10');
267
+ * for (const user of users) {
268
+ * console.log(`${user.name}: ${user.email}`);
269
+ * }
270
+ *
271
+ * // Coordinated cancellation with multiple operations
272
+ * const operationController = new AbortController();
273
+ *
274
+ * const usersHandle = connector.queryJson('SELECT * FROM users', {
275
+ * signal: operationController.signal
276
+ * });
277
+ *
278
+ * const ordersHandle = connector.queryJson('SELECT * FROM orders', {
279
+ * signal: operationController.signal
280
+ * });
281
+ *
282
+ * // Cancel both queries if user navigates away
283
+ * window.addEventListener('beforeunload', () => {
284
+ * operationController.abort();
285
+ * });
286
+ * ```
287
+ */
288
+ queryJson<T = Record<string, any>>(query: string, options?: QueryOptions): QueryHandle<Iterable<T>>;
289
+ /**
290
+ * Load a file into DuckDB and create a table
291
+ * @param fileName - Path to the file to load
292
+ * @param tableName - Name of the table to create
293
+ * @param opts - Load options
294
+ */
295
+ loadFile(fileName: string | File, tableName: string, opts?: LoadFileOptions): Promise<void>;
296
+ /**
297
+ * Load an arrow table or an arrow IPC stream into DuckDB
298
+ * @param table - Arrow table or arrow IPC stream to load
299
+ * @param tableName - Name of the table to create
300
+ */
301
+ loadArrow(table: arrow.Table | Uint8Array, tableName: string, opts?: {
302
+ schema?: string;
303
+ }): Promise<void>;
304
+ /**
305
+ * Load JavaScript objects into DuckDB
306
+ * @param data - Array of objects to load
307
+ * @param tableName - Name of the table to create
308
+ * @param opts - Load options
309
+ */
310
+ loadObjects(data: Record<string, unknown>[], tableName: string, opts?: StandardLoadOptions): Promise<void>;
311
+ }
312
+ //# sourceMappingURL=DuckDbConnector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DuckDbConnector.d.ts","sourceRoot":"","sources":["../src/DuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAE,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IAClD,+CAA+C;IAC/C,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAEnB;;;OAGG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,EAAE,WAAW,CAAC;IAEpB,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAE3B,2FAA2F;IAC3F,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;IAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,KAAK,CAAC,CAAC,SAAS,OAAO,GAAG,GAAG,EAC3B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACH,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5B;;;;;OAKG;IACH,QAAQ,CACN,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;OAIG;IACH,SAAS,CACP,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,EAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;OAKG;IACH,WAAW,CACT,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=DuckDbConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DuckDbConnector.js","sourceRoot":"","sources":["../src/DuckDbConnector.ts"],"names":[],"mappings":"","sourcesContent":["import {LoadFileOptions, StandardLoadOptions} from '@sqlrooms/room-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\n\n/**\n * Options for query execution\n */\nexport interface QueryOptions {\n /**\n * Optional external abort signal for coordinated cancellation.\n * When provided, the query will be cancelled if this signal is aborted.\n * This enables powerful composition patterns like cancelling multiple\n * queries together or integrating with other cancellable operations.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Handle for managing query execution and cancellation.\n *\n * It is **Promise-like**, so you can either:\n *\n * • `await handle` – the most ergonomic form, or\n * • `await handle.result` – kept for backwards-compatibility.\n *\n * Additional capabilities:\n * • Standard Promise API: `.then()`, `.catch()`, `.finally()`\n * • `handle.cancel()` – cancel the running query.\n * • `handle.signal` – `AbortSignal` that fires when the query is cancelled.\n *\n * @example\n * ```typescript\n * // Simple usage\n * const handle = connector.query('SELECT * FROM table');\n * const table = await handle; // no .result needed\n *\n * // With cancellation\n * const controller = new AbortController();\n * const handle = connector.query('SELECT * FROM large_table', { signal: controller.signal });\n * setTimeout(() => controller.abort(), 5000);\n *\n * // Manual cancel via the handle\n * const h = connector.query('SELECT * FROM table');\n * await someCondition;\n * await h.cancel();\n *\n * // Composable cancellation (multiple queries, one controller)\n * const controller = new AbortController();\n * const h1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const h2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * // Later...\n * controller.abort(); // Cancels h1 and h2 together\n *\n * // Using Promise utilities\n * const [t1, t2] = await Promise.all([\n * connector.query('select 1'),\n * connector.query('select 2')\n * ]);\n * ```\n */\nexport type QueryHandle<T = any> = PromiseLike<T> & {\n /** Promise that resolves with query results */\n result: Promise<T>;\n\n /**\n * Method to cancel the query with optional cleanup.\n * This provides a clean abstraction over the underlying cancellation mechanism.\n */\n cancel: () => Promise<void>;\n\n /**\n * Read-only access to the abort signal for composability.\n *\n * Key benefits:\n * - **Event-driven**: Listen for abort events to update UI or perform cleanup\n * - **Integration**: Use with other Web APIs like fetch() that accept AbortSignal\n * - **Status checking**: Check if query is already cancelled with signal.aborted\n *\n * @example\n * ```typescript\n * // Listen for cancellation events\n * handle.signal.addEventListener('abort', () => {\n * console.log('Query cancelled');\n * updateUI('Operation cancelled');\n * });\n *\n * // Check cancellation status\n * if (handle.signal.aborted) {\n * console.log('Query was already cancelled');\n * }\n *\n * // Use with other APIs\n * const response = await fetch('/api/data', { signal: handle.signal });\n * ```\n */\n signal: AbortSignal;\n\n /** Attach a callback for only the rejection of the Promise */\n catch: Promise<T>['catch'];\n\n /** Attach a callback that's invoked when the Promise is settled (fulfilled or rejected) */\n finally: Promise<T>['finally'];\n};\n\n/**\n * DuckDB connector interface with advanced query cancellation support\n *\n * This interface provides a hybrid approach that combines the simplicity of method-based\n * cancellation with the composability of Web Standards (AbortController/AbortSignal).\n *\n * ## Key Benefits of This Design\n *\n * ### 🔗 Composability\n * Cancel multiple queries with a single controller:\n * ```typescript\n * const controller = new AbortController();\n * const query1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const query2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * controller.abort(); // Cancels both queries\n * ```\n *\n * ### 🌐 Integration with Web APIs\n * Use the same signal for queries and HTTP requests:\n * ```typescript\n * const controller = new AbortController();\n * const queryHandle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * const response = await fetch('/api/data', { signal: controller.signal });\n * // controller.abort() cancels both the query and the HTTP request\n * ```\n *\n * ### 🎛️ Flexibility\n * Simple usage when you don't need external control, advanced when you do:\n * ```typescript\n * // Simple - internal cancellation management\n * const handle = connector.query('SELECT * FROM table');\n * handle.cancel();\n *\n * // Advanced - external cancellation control\n * const controller = new AbortController();\n * const handle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * controller.abort();\n * ```\n *\n * ### 📡 Event-Driven\n * React to cancellation events for better UX:\n * ```typescript\n * handle.signal.addEventListener('abort', () => {\n * showNotification('Query cancelled');\n * hideLoadingSpinner();\n * });\n * ```\n *\n * ### ⏱️ Timeout Support\n * Built-in timeout capability with manual override:\n * ```typescript\n * const timeoutController = new AbortController();\n * setTimeout(() => timeoutController.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM large_table', {\n * signal: timeoutController.signal\n * });\n *\n * // User can still cancel manually\n * cancelButton.onclick = () => timeoutController.abort();\n * ```\n *\n * ### 🏗️ Signal Composition\n * Combine multiple cancellation sources:\n * ```typescript\n * function combineSignals(...signals: AbortSignal[]): AbortSignal {\n * const controller = new AbortController();\n * signals.forEach(signal => {\n * if (signal.aborted) controller.abort();\n * else signal.addEventListener('abort', () => controller.abort());\n * });\n * return controller.signal;\n * }\n *\n * const userSignal = userController.signal;\n * const timeoutSignal = createTimeoutSignal(30000);\n * const combinedSignal = combineSignals(userSignal, timeoutSignal);\n *\n * const handle = connector.query('SELECT * FROM table', { signal: combinedSignal });\n * ```\n */\nexport interface DuckDbConnector {\n /**\n * Initialize the connector.\n * The function returns a promise that resolves when the connector is initialized.\n * Calling the initialize() function multiple times should not restart the initialization.\n * See BaseDuckDbConnector for an implementation example.\n */\n initialize(): Promise<void>;\n\n /**\n * Destroy the connector and clean up resources\n */\n destroy(): Promise<void>;\n\n /**\n * Execute a SQL query without returning a result\n *\n * @param sql SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves when execution completes\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple execution\n * const handle = connector.execute('CREATE TABLE test AS SELECT * FROM source');\n * await handle.result;\n *\n * // With external cancellation control\n * const controller = new AbortController();\n * const handle = connector.execute('DROP TABLE large_table', {\n * signal: controller.signal\n * });\n *\n * // Cancel if it takes too long\n * setTimeout(() => controller.abort(), 5000);\n * ```\n */\n execute(sql: string, options?: QueryOptions): QueryHandle;\n\n /**\n * Execute a SQL query and return the result as an Arrow table\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with Arrow table\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Basic query\n * const handle = await connector.query('SELECT * FROM users WHERE active = true');\n * console.log(`Found ${table.numRows} active users`);\n *\n * // Query with timeout\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM very_large_table', {\n * signal: controller.signal\n * });\n *\n * try {\n * const result = await handle;\n * console.log('Query completed within timeout');\n * } catch (error) {\n * if (error.name === 'AbortError') {\n * console.log('Query timed out');\n * }\n * }\n * ```\n */\n query<T extends TypeMap = any>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>>;\n\n /**\n * Execute a SQL query and return the result as a JSON object\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with iterable of JSON objects\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple JSON query\n * const users = await connector.queryJson('SELECT name, email FROM users LIMIT 10');\n * for (const user of users) {\n * console.log(`${user.name}: ${user.email}`);\n * }\n *\n * // Coordinated cancellation with multiple operations\n * const operationController = new AbortController();\n *\n * const usersHandle = connector.queryJson('SELECT * FROM users', {\n * signal: operationController.signal\n * });\n *\n * const ordersHandle = connector.queryJson('SELECT * FROM orders', {\n * signal: operationController.signal\n * });\n *\n * // Cancel both queries if user navigates away\n * window.addEventListener('beforeunload', () => {\n * operationController.abort();\n * });\n * ```\n */\n queryJson<T = Record<string, any>>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>>;\n\n /**\n * Load a file into DuckDB and create a table\n * @param fileName - Path to the file to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadFile(\n fileName: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void>;\n\n /**\n * Load an arrow table or an arrow IPC stream into DuckDB\n * @param table - Arrow table or arrow IPC stream to load\n * @param tableName - Name of the table to create\n */\n loadArrow(\n table: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void>;\n\n /**\n * Load JavaScript objects into DuckDB\n * @param data - Array of objects to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadObjects(\n data: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void>;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import * as arrow from 'apache-arrow';
2
+ /**
3
+ * Converts an Arrow table to a JSON-compatible array of objects
4
+ * @see https://duckdb.org/docs/api/wasm/query.html#arrow-table-to-json
5
+ * @see https://github.com/apache/arrow/issues/37856
6
+ */
7
+ export declare function arrowTableToJson(table: arrow.Table): Record<string, unknown>[];
8
+ //# sourceMappingURL=arrow-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arrow-utils.d.ts","sourceRoot":"","sources":["../src/arrow-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,CAAC,KAAK,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAQ3B"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Converts an Arrow table to a JSON-compatible array of objects
3
+ * @see https://duckdb.org/docs/api/wasm/query.html#arrow-table-to-json
4
+ * @see https://github.com/apache/arrow/issues/37856
5
+ */
6
+ export function arrowTableToJson(table) {
7
+ return table.toArray().map((row) => Object.fromEntries(Object.entries(row).map(([key, value]) => {
8
+ return [key, convertValue(value)];
9
+ })));
10
+ }
11
+ /**
12
+ * Converts an Arrow table value to a JSON-compatible value
13
+ * @param value
14
+ * @returns
15
+ */
16
+ function convertValue(value) {
17
+ if (typeof value === 'bigint') {
18
+ if (value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER) {
19
+ return Number(value);
20
+ }
21
+ return String(value);
22
+ }
23
+ if (typeof value === 'number') {
24
+ return value;
25
+ }
26
+ return String(value);
27
+ }
28
+ //# sourceMappingURL=arrow-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arrow-utils.js","sourceRoot":"","sources":["../src/arrow-utils.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAkB;IAElB,OAAO,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACjC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QACvC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,CACH,CACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,KAAK,IAAI,MAAM,CAAC,gBAAgB,IAAI,KAAK,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;YACzE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC","sourcesContent":["import * as arrow from 'apache-arrow';\n\n/**\n * Converts an Arrow table to a JSON-compatible array of objects\n * @see https://duckdb.org/docs/api/wasm/query.html#arrow-table-to-json\n * @see https://github.com/apache/arrow/issues/37856\n */\nexport function arrowTableToJson(\n table: arrow.Table,\n): Record<string, unknown>[] {\n return table.toArray().map((row) =>\n Object.fromEntries(\n Object.entries(row).map(([key, value]) => {\n return [key, convertValue(value)];\n }),\n ),\n );\n}\n\n/**\n * Converts an Arrow table value to a JSON-compatible value\n * @param value\n * @returns\n */\nfunction convertValue(value: unknown) {\n if (typeof value === 'bigint') {\n if (value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER) {\n return Number(value);\n }\n return String(value);\n }\n if (typeof value === 'number') {\n return value;\n }\n return String(value);\n}\n"]}
@@ -0,0 +1,140 @@
1
+ import * as arrow from 'apache-arrow';
2
+ export type QualifiedTableName = {
3
+ database?: string;
4
+ schema?: string;
5
+ table: string;
6
+ toString: () => string;
7
+ };
8
+ export declare function isQualifiedTableName(tableName: string | QualifiedTableName): tableName is QualifiedTableName;
9
+ /**
10
+ * Get a qualified table name from a table name, schema, and database.
11
+ * @param table - The name of the table.
12
+ * @param schema - The schema of the table.
13
+ * @param database - The database of the table.
14
+ * @returns The qualified table name.
15
+ */
16
+ export declare function makeQualifiedTableName({ database, schema, table, }: QualifiedTableName): {
17
+ database: string | undefined;
18
+ schema: string | undefined;
19
+ table: string;
20
+ toString: () => string;
21
+ };
22
+ /**
23
+ * Escapes a value for use in DuckDB SQL queries by wrapping it in single quotes
24
+ * and escaping any existing single quotes by doubling them.
25
+ *
26
+ * @param val - The value to escape. Will be converted to string if not already a string.
27
+ * @returns The escaped string value wrapped in single quotes.
28
+ * @example
29
+ * escapeVal("John's data") // Returns "'John''s data'"
30
+ */
31
+ export declare const escapeVal: (val: unknown) => string;
32
+ /**
33
+ * Escapes an identifier (like table or column names) for use in DuckDB SQL queries
34
+ * by wrapping it in double quotes and escaping any existing double quotes by doubling them.
35
+ * If the identifier is already properly quoted, returns it as is.
36
+ *
37
+ * @param id - The identifier string to escape
38
+ * @returns The escaped identifier wrapped in double quotes
39
+ * @example
40
+ * escapeId("my_table") // Returns '"my_table"'
41
+ * escapeId("my""table") // Returns '"my""""table"'
42
+ */
43
+ export declare const escapeId: (id: string) => string;
44
+ /**
45
+ * Checks if a DuckDB type string represents a numeric type.
46
+ * Includes INTEGER, DECIMAL, FLOAT, REAL, and DOUBLE types.
47
+ *
48
+ * @param type - The DuckDB type string to check
49
+ * @returns True if the type is numeric, false otherwise
50
+ * @example
51
+ * isNumericDuckType('INTEGER') // Returns true
52
+ * isNumericDuckType('VARCHAR') // Returns false
53
+ */
54
+ export declare const isNumericDuckType: (type: string) => boolean;
55
+ /**
56
+ * Extracts a numeric value from an Arrow Table at the specified column and row index.
57
+ * Handles both column name and index-based access. Converts BigInt values to numbers.
58
+ *
59
+ * @param res - The Arrow Table containing the data
60
+ * @param column - The column name or index (0-based) to read from. Defaults to first column (0)
61
+ * @param index - The row index (0-based) to read from. Defaults to first row (0)
62
+ * @returns The numeric value at the specified position, or NaN if the value is null/undefined
63
+ * @example
64
+ * const value = getColValAsNumber(table, "amount", 0)
65
+ */
66
+ export declare function getColValAsNumber(res: arrow.Table, column?: string | number, index?: number): number;
67
+ /**
68
+ * Function given a query and position finds the line and column of the console.error();
69
+ *
70
+ * @param query - The query to parse
71
+ * @param position - The position of the error
72
+ * @returns The line and column of the error
73
+ */
74
+ export declare const getSqlErrorWithPointer: (query: string, position: number) => {
75
+ line: number;
76
+ column: number;
77
+ lineText: string;
78
+ pointerLine: string;
79
+ formatted: string;
80
+ };
81
+ /**
82
+ * Split a string with potentially multiple SQL queries (separated as usual by ';')
83
+ * into an array of queries.
84
+ * This implementation:
85
+ * - Handles single and double quoted strings with proper escaping
86
+ * - Removes all comments: line comments (--) and block comments (/* ... *\/)
87
+ * - Ignores semicolons in quoted strings and comments
88
+ * - Trims whitespace from queries
89
+ * - Handles SQL-style escaped quotes ('' inside strings)
90
+ * - Returns only non-empty queries
91
+ *
92
+ * @param input - The SQL string containing one or more statements
93
+ * @returns An array of SQL statements with all comments removed
94
+ */
95
+ export declare function splitSqlStatements(input: string): string[];
96
+ /**
97
+ * Sanitizes a SQL query by removing trailing semicolons, comments, and normalizing whitespace
98
+ */
99
+ export declare function sanitizeQuery(query: string): string;
100
+ /**
101
+ * Make a limit query from a query and a limit.
102
+ * @param query - The SELECT query to make limited.
103
+ * @param options - The options for the limit query.
104
+ * @param options.limit - The number of rows to limit the query to.
105
+ * @param options.offset - The number of rows to offset the query by.
106
+ * @param options.sanitize - Whether to sanitize the query.
107
+ * @returns The limited query.
108
+ */
109
+ export declare function makeLimitQuery(query: string, { limit, offset, sanitize, }?: {
110
+ limit?: number;
111
+ offset?: number;
112
+ sanitize?: boolean;
113
+ }): string;
114
+ /**
115
+ * Result of separating the last SQL statement from preceding ones.
116
+ */
117
+ export type SeparatedStatements = {
118
+ /** All statements except the last one */
119
+ precedingStatements: string[];
120
+ /** The last statement */
121
+ lastStatement: string;
122
+ };
123
+ /**
124
+ * Separates a SQL query into preceding statements and the last statement.
125
+ * Useful when you need to execute multiple statements but handle the last one differently
126
+ * (e.g., wrap it in CREATE TABLE, add LIMIT, etc.).
127
+ *
128
+ * @param query - The SQL query string containing one or more statements
129
+ * @returns Object containing preceding statements and the last statement
130
+ * @throws Error if the query contains no statements
131
+ */
132
+ export declare function separateLastStatement(query: string): SeparatedStatements;
133
+ /**
134
+ * Joins preceding statements with a (potentially modified) last statement into a single query.
135
+ * @param precedingStatements - Statements to execute before the last one
136
+ * @param lastStatement - The final statement (can be modified, e.g., wrapped in CREATE TABLE)
137
+ * @returns A single query string with all statements joined by semicolons
138
+ */
139
+ export declare function joinStatements(precedingStatements: string[], lastStatement: string): string;
140
+ //# sourceMappingURL=duckdb-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duckdb-utils.d.ts","sourceRoot":"","sources":["../src/duckdb-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,MAAM,CAAC;CACxB,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GACrC,SAAS,IAAI,kBAAkB,CAEjC;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,MAAM,EACN,KAAK,GACN,EAAE,kBAAkB;;;;;EAWpB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,OAAO,WAErC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,GAAI,IAAI,MAAM,WAMlC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,YAKjB,CAAC;AAE9B;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,KAAK,CAAC,KAAK,EAChB,MAAM,GAAE,MAAM,GAAG,MAAU,EAC3B,KAAK,SAAI,GACR,MAAM,CASR;AAED;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,EAAE,UAAU,MAAM;;;;;;CAsBrE,CAAC;AAoBF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqG1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,EACE,KAAW,EACX,MAAU,EACV,QAAe,GAChB,GAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACf,UAKP;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,yCAAyC;IACzC,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,yBAAyB;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CASxE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,mBAAmB,EAAE,MAAM,EAAE,EAC7B,aAAa,EAAE,MAAM,GACpB,MAAM,CAIR"}