@sqlrooms/duckdb-node 0.26.1-rc.11

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.
package/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright 2025 Ilya Boyandin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ Node.js DuckDB connector for SQLRooms, based on [@duckdb/node-api](https://duckdb.org/docs/stable/clients/node_neo/overview).
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ pnpm add @sqlrooms/duckdb-node
7
+ ```
8
+
9
+ ## Usage
10
+
11
+ ```typescript
12
+ import {createNodeDuckDbConnector} from '@sqlrooms/duckdb-node';
13
+
14
+ // Create connector
15
+ const connector = createNodeDuckDbConnector({
16
+ dbPath: ':memory:',
17
+ initializationQuery: 'INSTALL json; LOAD json;',
18
+ });
19
+
20
+ // Initialize
21
+ await connector.initialize();
22
+
23
+ // Execute queries
24
+ await connector.execute('CREATE TABLE users (id INTEGER, name VARCHAR)');
25
+
26
+ // Query with Arrow result
27
+ const table = await connector.query('SELECT * FROM users');
28
+ console.log(table.numRows);
29
+
30
+ // Query with JSON result
31
+ const users = await connector.queryJson('SELECT * FROM users');
32
+ for (const user of users) {
33
+ console.log(user);
34
+ }
35
+
36
+ // Clean up
37
+ await connector.destroy();
38
+ ```
39
+
40
+ ## API
41
+
42
+ ### `createNodeDuckDbConnector(options?)`
43
+
44
+ Creates a new Node.js DuckDB connector.
45
+
46
+ **Options:**
47
+
48
+ - `dbPath` - Path to database file or `:memory:` (default: `:memory:`)
49
+ - `initializationQuery` - SQL to run after initialization
50
+ - `config` - DuckDB configuration options
51
+
52
+ **Returns:** `NodeDuckDbConnector`
53
+
54
+ ### `NodeDuckDbConnector`
55
+
56
+ - `initialize()` - Initialize the connector
57
+ - `destroy()` - Clean up resources
58
+ - `execute(sql, options?)` - Execute SQL without returning results
59
+ - `query(sql, options?)` - Execute SQL and return Arrow table
60
+ - `queryJson(sql, options?)` - Execute SQL and return JSON objects
61
+ - `getInstance()` - Get underlying DuckDB instance
62
+ - `getConnection()` - Get underlying DuckDB connection
@@ -0,0 +1,50 @@
1
+ import { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';
2
+ import { DuckDbConnector } from '@sqlrooms/duckdb-core';
3
+ /**
4
+ * Options for the Node.js DuckDB connector.
5
+ */
6
+ export interface NodeDuckDbConnectorOptions {
7
+ /**
8
+ * Path to the database file, or ':memory:' for in-memory database.
9
+ * @default ':memory:'
10
+ */
11
+ dbPath?: string;
12
+ /**
13
+ * SQL to run after initialization.
14
+ */
15
+ initializationQuery?: string;
16
+ /**
17
+ * Configuration options passed to DuckDB instance.
18
+ */
19
+ config?: Record<string, string>;
20
+ }
21
+ /**
22
+ * Extended DuckDB connector for Node.js environments.
23
+ * Includes access to the underlying DuckDB instance and connection.
24
+ */
25
+ export interface NodeDuckDbConnector extends DuckDbConnector {
26
+ /** Get the underlying DuckDB instance */
27
+ getInstance(): DuckDBInstance;
28
+ /** Get the underlying DuckDB connection */
29
+ getConnection(): DuckDBConnection;
30
+ }
31
+ /**
32
+ * Creates a DuckDB connector for Node.js environments using @duckdb/node-api.
33
+ *
34
+ * @param options - Configuration options for the connector
35
+ * @returns A NodeDuckDbConnector instance
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const connector = createNodeDuckDbConnector({
40
+ * dbPath: ':memory:',
41
+ * initializationQuery: 'INSTALL json; LOAD json;'
42
+ * });
43
+ *
44
+ * await connector.initialize();
45
+ * const result = await connector.query('SELECT 1 as value');
46
+ * console.log(result.numRows); // 1
47
+ * ```
48
+ */
49
+ export declare function createNodeDuckDbConnector(options?: NodeDuckDbConnectorOptions): NodeDuckDbConnector;
50
+ //# sourceMappingURL=NodeDuckDbConnector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeDuckDbConnector.d.ts","sourceRoot":"","sources":["../src/NodeDuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAE,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAGL,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAU/B;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,eAAe;IAC1D,yCAAyC;IACzC,WAAW,IAAI,cAAc,CAAC;IAC9B,2CAA2C;IAC3C,aAAa,IAAI,gBAAgB,CAAC;CACnC;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,0BAA+B,GACvC,mBAAmB,CAkHrB"}
@@ -0,0 +1,108 @@
1
+ import { DuckDBInstance } from '@duckdb/node-api';
2
+ import { createBaseDuckDbConnector, } from '@sqlrooms/duckdb-core';
3
+ import * as arrow from 'apache-arrow';
4
+ import { arrowTableToRows, buildQualifiedName, objectsToCreateTableSql, queryToArrowTable, } from './helpers';
5
+ // ============================================================================
6
+ // Connector Factory
7
+ // ============================================================================
8
+ /**
9
+ * Creates a DuckDB connector for Node.js environments using @duckdb/node-api.
10
+ *
11
+ * @param options - Configuration options for the connector
12
+ * @returns A NodeDuckDbConnector instance
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const connector = createNodeDuckDbConnector({
17
+ * dbPath: ':memory:',
18
+ * initializationQuery: 'INSTALL json; LOAD json;'
19
+ * });
20
+ *
21
+ * await connector.initialize();
22
+ * const result = await connector.query('SELECT 1 as value');
23
+ * console.log(result.numRows); // 1
24
+ * ```
25
+ */
26
+ export function createNodeDuckDbConnector(options = {}) {
27
+ const { dbPath = ':memory:', initializationQuery = '', config = {} } = options;
28
+ let instance = null;
29
+ let connection = null;
30
+ const ensureConnection = () => {
31
+ if (!connection) {
32
+ throw new Error('DuckDB not initialized');
33
+ }
34
+ return connection;
35
+ };
36
+ const impl = {
37
+ async initializeInternal() {
38
+ instance = await DuckDBInstance.create(dbPath, config);
39
+ connection = await instance.connect();
40
+ },
41
+ async destroyInternal() {
42
+ if (connection) {
43
+ try {
44
+ connection.closeSync();
45
+ }
46
+ catch (error) {
47
+ // Connection might already be closed, ignore errors
48
+ console.warn('Error closing connection:', error);
49
+ }
50
+ connection = null;
51
+ }
52
+ instance = null;
53
+ // Give native module time to clean up resources
54
+ await new Promise((resolve) => setTimeout(resolve, 0));
55
+ },
56
+ async executeQueryInternal(sql, signal) {
57
+ if (signal.aborted) {
58
+ throw new DOMException('Query was cancelled', 'AbortError');
59
+ }
60
+ return queryToArrowTable(ensureConnection(), sql);
61
+ },
62
+ async loadArrowInternal(table, tableName, opts) {
63
+ if (table instanceof arrow.Table) {
64
+ const rows = arrowTableToRows(table);
65
+ await impl.loadObjectsInternal(rows, tableName, {
66
+ schema: opts?.schema,
67
+ replace: true,
68
+ });
69
+ }
70
+ else {
71
+ throw new Error('Loading Arrow IPC streams is not yet supported in Node connector');
72
+ }
73
+ },
74
+ async loadObjectsInternal(data, tableName, opts) {
75
+ if (data.length === 0) {
76
+ throw new Error('Cannot load empty data array');
77
+ }
78
+ const qualifiedName = buildQualifiedName(tableName, opts?.schema);
79
+ const sql = objectsToCreateTableSql(data, qualifiedName);
80
+ await ensureConnection().run(sql);
81
+ },
82
+ async loadFileInternal(fileName, tableName, opts) {
83
+ if (fileName instanceof File) {
84
+ throw new Error('File objects are not supported in Node connector');
85
+ }
86
+ const qualifiedName = buildQualifiedName(tableName, opts?.schema);
87
+ const method = opts?.method ?? 'auto';
88
+ const sql = method === 'auto'
89
+ ? `CREATE OR REPLACE TABLE ${qualifiedName} AS SELECT * FROM '${fileName}'`
90
+ : `CREATE OR REPLACE TABLE ${qualifiedName} AS SELECT * FROM ${method}('${fileName}')`;
91
+ await ensureConnection().run(sql);
92
+ },
93
+ };
94
+ const baseConnector = createBaseDuckDbConnector({ dbPath, initializationQuery }, impl);
95
+ return {
96
+ ...baseConnector,
97
+ getInstance() {
98
+ if (!instance) {
99
+ throw new Error('DuckDB not initialized');
100
+ }
101
+ return instance;
102
+ },
103
+ getConnection() {
104
+ return ensureConnection();
105
+ },
106
+ };
107
+ }
108
+ //# sourceMappingURL=NodeDuckDbConnector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NodeDuckDbConnector.js","sourceRoot":"","sources":["../src/NodeDuckDbConnector.ts"],"names":[],"mappings":"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","sourcesContent":["import {DuckDBConnection, DuckDBInstance} from '@duckdb/node-api';\nimport {\n BaseDuckDbConnectorImpl,\n createBaseDuckDbConnector,\n DuckDbConnector,\n} from '@sqlrooms/duckdb-core';\nimport {LoadFileOptions, StandardLoadOptions} from '@sqlrooms/room-config';\nimport * as arrow from 'apache-arrow';\nimport {\n arrowTableToRows,\n buildQualifiedName,\n objectsToCreateTableSql,\n queryToArrowTable,\n} from './helpers';\n\n/**\n * Options for the Node.js DuckDB connector.\n */\nexport interface NodeDuckDbConnectorOptions {\n /**\n * Path to the database file, or ':memory:' for in-memory database.\n * @default ':memory:'\n */\n dbPath?: string;\n\n /**\n * SQL to run after initialization.\n */\n initializationQuery?: string;\n\n /**\n * Configuration options passed to DuckDB instance.\n */\n config?: Record<string, string>;\n}\n\n/**\n * Extended DuckDB connector for Node.js environments.\n * Includes access to the underlying DuckDB instance and connection.\n */\nexport interface NodeDuckDbConnector extends DuckDbConnector {\n /** Get the underlying DuckDB instance */\n getInstance(): DuckDBInstance;\n /** Get the underlying DuckDB connection */\n getConnection(): DuckDBConnection;\n}\n\n// ============================================================================\n// Connector Factory\n// ============================================================================\n\n/**\n * Creates a DuckDB connector for Node.js environments using @duckdb/node-api.\n *\n * @param options - Configuration options for the connector\n * @returns A NodeDuckDbConnector instance\n *\n * @example\n * ```typescript\n * const connector = createNodeDuckDbConnector({\n * dbPath: ':memory:',\n * initializationQuery: 'INSTALL json; LOAD json;'\n * });\n *\n * await connector.initialize();\n * const result = await connector.query('SELECT 1 as value');\n * console.log(result.numRows); // 1\n * ```\n */\nexport function createNodeDuckDbConnector(\n options: NodeDuckDbConnectorOptions = {},\n): NodeDuckDbConnector {\n const {dbPath = ':memory:', initializationQuery = '', config = {}} = options;\n\n let instance: DuckDBInstance | null = null;\n let connection: DuckDBConnection | null = null;\n\n const ensureConnection = (): DuckDBConnection => {\n if (!connection) {\n throw new Error('DuckDB not initialized');\n }\n return connection;\n };\n\n const impl: BaseDuckDbConnectorImpl = {\n async initializeInternal() {\n instance = await DuckDBInstance.create(dbPath, config);\n connection = await instance.connect();\n },\n\n async destroyInternal() {\n if (connection) {\n try {\n connection.closeSync();\n } catch (error) {\n // Connection might already be closed, ignore errors\n console.warn('Error closing connection:', error);\n }\n connection = null;\n }\n instance = null;\n // Give native module time to clean up resources\n await new Promise((resolve) => setTimeout(resolve, 0));\n },\n\n async executeQueryInternal<T extends arrow.TypeMap = any>(\n sql: string,\n signal: AbortSignal,\n ): Promise<arrow.Table<T>> {\n if (signal.aborted) {\n throw new DOMException('Query was cancelled', 'AbortError');\n }\n return queryToArrowTable<T>(ensureConnection(), sql);\n },\n\n async loadArrowInternal(\n table: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void> {\n if (table instanceof arrow.Table) {\n const rows = arrowTableToRows(table);\n await impl.loadObjectsInternal!(rows, tableName, {\n schema: opts?.schema,\n replace: true,\n });\n } else {\n throw new Error(\n 'Loading Arrow IPC streams is not yet supported in Node connector',\n );\n }\n },\n\n async loadObjectsInternal(\n data: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void> {\n if (data.length === 0) {\n throw new Error('Cannot load empty data array');\n }\n\n const qualifiedName = buildQualifiedName(tableName, opts?.schema);\n const sql = objectsToCreateTableSql(data, qualifiedName);\n await ensureConnection().run(sql);\n },\n\n async loadFileInternal(\n fileName: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void> {\n if (fileName instanceof File) {\n throw new Error('File objects are not supported in Node connector');\n }\n\n const qualifiedName = buildQualifiedName(tableName, opts?.schema);\n const method = opts?.method ?? 'auto';\n\n const sql =\n method === 'auto'\n ? `CREATE OR REPLACE TABLE ${qualifiedName} AS SELECT * FROM '${fileName}'`\n : `CREATE OR REPLACE TABLE ${qualifiedName} AS SELECT * FROM ${method}('${fileName}')`;\n\n await ensureConnection().run(sql);\n },\n };\n\n const baseConnector = createBaseDuckDbConnector(\n {dbPath, initializationQuery},\n impl,\n );\n\n return {\n ...baseConnector,\n getInstance() {\n if (!instance) {\n throw new Error('DuckDB not initialized');\n }\n return instance;\n },\n getConnection() {\n return ensureConnection();\n },\n };\n}\n"]}
@@ -0,0 +1,22 @@
1
+ import { DuckDBConnection } from '@duckdb/node-api';
2
+ import * as arrow from 'apache-arrow';
3
+ /**
4
+ * Builds a qualified table name string from table name and optional schema.
5
+ */
6
+ export declare function buildQualifiedName(tableName: string, schema?: string): string;
7
+ /**
8
+ * Converts an Arrow table to an array of row objects.
9
+ */
10
+ export declare function arrowTableToRows(table: arrow.Table): Record<string, unknown>[];
11
+ /**
12
+ * Converts an array of objects to a SQL CREATE TABLE AS SELECT statement.
13
+ */
14
+ export declare function objectsToCreateTableSql(data: Record<string, unknown>[], qualifiedName: string): string;
15
+ /**
16
+ * Converts DuckDB query result to an Apache Arrow table.
17
+ *
18
+ * TODO: Remove this once duckdb-node-neo supports Arrow tables directly.
19
+ * @see https://github.com/duckdb/duckdb-node-neo/issues/45
20
+ */
21
+ export declare function queryToArrowTable<T extends arrow.TypeMap = any>(conn: DuckDBConnection, sql: string): Promise<arrow.Table<T>>;
22
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAElD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7E;AAaD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,CAAC,KAAK,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAW3B;AAYD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,aAAa,EAAE,MAAM,GACpB,MAAM,CAWR;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,KAAK,CAAC,OAAO,GAAG,GAAG,EACnE,IAAI,EAAE,gBAAgB,EACtB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAoBzB"}
@@ -0,0 +1,78 @@
1
+ import { literalToSQL, makeQualifiedTableName } from '@sqlrooms/duckdb-core';
2
+ import * as arrow from 'apache-arrow';
3
+ /**
4
+ * Builds a qualified table name string from table name and optional schema.
5
+ */
6
+ export function buildQualifiedName(tableName, schema) {
7
+ return makeQualifiedTableName({ table: tableName, schema }).toString();
8
+ }
9
+ /**
10
+ * Converts a BigInt to a safe JavaScript number or string.
11
+ * Returns number if within safe range, otherwise string.
12
+ */
13
+ function convertBigInt(value) {
14
+ if (value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER) {
15
+ return Number(value);
16
+ }
17
+ return value.toString();
18
+ }
19
+ /**
20
+ * Converts an Arrow table to an array of row objects.
21
+ */
22
+ export function arrowTableToRows(table) {
23
+ const rows = [];
24
+ for (let i = 0; i < table.numRows; i++) {
25
+ const row = {};
26
+ for (const field of table.schema.fields) {
27
+ const col = table.getChild(field.name);
28
+ row[field.name] = col?.get(i);
29
+ }
30
+ rows.push(row);
31
+ }
32
+ return rows;
33
+ }
34
+ /**
35
+ * Converts a value to SQL literal, with bigint support.
36
+ */
37
+ function toSqlLiteral(value) {
38
+ if (typeof value === 'bigint') {
39
+ return value.toString();
40
+ }
41
+ return literalToSQL(value);
42
+ }
43
+ /**
44
+ * Converts an array of objects to a SQL CREATE TABLE AS SELECT statement.
45
+ */
46
+ export function objectsToCreateTableSql(data, qualifiedName) {
47
+ const columns = Object.keys(data[0]);
48
+ const columnList = columns.map((c) => `"${c}"`).join(', ');
49
+ const valueRows = data.map((row) => {
50
+ const values = columns.map((col) => toSqlLiteral(row[col]));
51
+ return `(${values.join(', ')})`;
52
+ });
53
+ return `CREATE OR REPLACE TABLE ${qualifiedName} (${columnList}) AS
54
+ SELECT * FROM (VALUES ${valueRows.join(', ')}) AS t(${columnList})`;
55
+ }
56
+ /**
57
+ * Converts DuckDB query result to an Apache Arrow table.
58
+ *
59
+ * TODO: Remove this once duckdb-node-neo supports Arrow tables directly.
60
+ * @see https://github.com/duckdb/duckdb-node-neo/issues/45
61
+ */
62
+ export async function queryToArrowTable(conn, sql) {
63
+ const reader = await conn.runAndReadAll(sql);
64
+ const columnNames = reader.columnNames();
65
+ const columns = reader.getColumnsJson();
66
+ if (columnNames.length === 0 || reader.currentRowCount === 0) {
67
+ return arrow.tableFromArrays({});
68
+ }
69
+ // Build column name -> array mapping, converting BigInts for Arrow compatibility
70
+ const columnsObject = {};
71
+ for (let i = 0; i < columnNames.length; i++) {
72
+ const name = columnNames[i];
73
+ const columnData = columns[i] ?? [];
74
+ columnsObject[name] = columnData.map((v) => typeof v === 'bigint' ? convertBigInt(v) : v);
75
+ }
76
+ return arrow.tableFromArrays(columnsObject);
77
+ }
78
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAE,sBAAsB,EAAC,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB,EAAE,MAAe;IACnE,OAAO,sBAAsB,CAAC,EAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;AACvE,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,KAAK,IAAI,MAAM,CAAC,gBAAgB,IAAI,KAAK,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;QACzE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAkB;IAElB,MAAM,IAAI,GAA8B,EAAE,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IACD,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAA+B,EAC/B,aAAqB;IAErB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAE3D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACjC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5D,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,OAAO,2BAA2B,aAAa,KAAK,UAAU;4BACpC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,UAAU,GAAG,CAAC;AACxE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAsB,EACtB,GAAW;IAEX,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;IAExC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,eAAe,KAAK,CAAC,EAAE,CAAC;QAC7D,OAAO,KAAK,CAAC,eAAe,CAAC,EAAE,CAA8B,CAAC;IAChE,CAAC;IAED,iFAAiF;IACjF,MAAM,aAAa,GAA8B,EAAE,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAW,CAAC;QACtC,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpC,aAAa,CAAC,IAAI,CAAC,GAAI,UAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACxD,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC7C,CAAC;IACJ,CAAC;IAED,OAAO,KAAK,CAAC,eAAe,CAAC,aAAa,CAA8B,CAAC;AAC3E,CAAC","sourcesContent":["import {DuckDBConnection} from '@duckdb/node-api';\nimport {literalToSQL, makeQualifiedTableName} from '@sqlrooms/duckdb-core';\nimport * as arrow from 'apache-arrow';\n\n/**\n * Builds a qualified table name string from table name and optional schema.\n */\nexport function buildQualifiedName(tableName: string, schema?: string): string {\n return makeQualifiedTableName({table: tableName, schema}).toString();\n}\n\n/**\n * Converts a BigInt to a safe JavaScript number or string.\n * Returns number if within safe range, otherwise string.\n */\nfunction convertBigInt(value: bigint): number | string {\n if (value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER) {\n return Number(value);\n }\n return value.toString();\n}\n\n/**\n * Converts an Arrow table to an array of row objects.\n */\nexport function arrowTableToRows(\n table: arrow.Table,\n): Record<string, unknown>[] {\n const rows: Record<string, unknown>[] = [];\n for (let i = 0; i < table.numRows; i++) {\n const row: Record<string, unknown> = {};\n for (const field of table.schema.fields) {\n const col = table.getChild(field.name);\n row[field.name] = col?.get(i);\n }\n rows.push(row);\n }\n return rows;\n}\n\n/**\n * Converts a value to SQL literal, with bigint support.\n */\nfunction toSqlLiteral(value: unknown): string {\n if (typeof value === 'bigint') {\n return value.toString();\n }\n return literalToSQL(value);\n}\n\n/**\n * Converts an array of objects to a SQL CREATE TABLE AS SELECT statement.\n */\nexport function objectsToCreateTableSql(\n data: Record<string, unknown>[],\n qualifiedName: string,\n): string {\n const columns = Object.keys(data[0]!);\n const columnList = columns.map((c) => `\"${c}\"`).join(', ');\n\n const valueRows = data.map((row) => {\n const values = columns.map((col) => toSqlLiteral(row[col]));\n return `(${values.join(', ')})`;\n });\n\n return `CREATE OR REPLACE TABLE ${qualifiedName} (${columnList}) AS \n SELECT * FROM (VALUES ${valueRows.join(', ')}) AS t(${columnList})`;\n}\n\n/**\n * Converts DuckDB query result to an Apache Arrow table.\n *\n * TODO: Remove this once duckdb-node-neo supports Arrow tables directly.\n * @see https://github.com/duckdb/duckdb-node-neo/issues/45\n */\nexport async function queryToArrowTable<T extends arrow.TypeMap = any>(\n conn: DuckDBConnection,\n sql: string,\n): Promise<arrow.Table<T>> {\n const reader = await conn.runAndReadAll(sql);\n const columnNames = reader.columnNames();\n const columns = reader.getColumnsJson();\n\n if (columnNames.length === 0 || reader.currentRowCount === 0) {\n return arrow.tableFromArrays({}) as unknown as arrow.Table<T>;\n }\n\n // Build column name -> array mapping, converting BigInts for Arrow compatibility\n const columnsObject: Record<string, unknown[]> = {};\n for (let i = 0; i < columnNames.length; i++) {\n const name = columnNames[i] as string;\n const columnData = columns[i] ?? [];\n columnsObject[name] = (columnData as unknown[]).map((v) =>\n typeof v === 'bigint' ? convertBigInt(v) : v,\n );\n }\n\n return arrow.tableFromArrays(columnsObject) as unknown as arrow.Table<T>;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @sqlrooms/duckdb-node - Node.js DuckDB connector for SQLRooms
3
+ *
4
+ * This package provides a DuckDB connector for Node.js environments using
5
+ * the @duckdb/node-api package.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ export { createNodeDuckDbConnector, type NodeDuckDbConnector, type NodeDuckDbConnectorOptions, } from './NodeDuckDbConnector';
10
+ export type { DuckDbConnector, QueryHandle, QueryOptions, } from '@sqlrooms/duckdb-core';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,GAChC,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EACV,eAAe,EACf,WAAW,EACX,YAAY,GACb,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @sqlrooms/duckdb-node - Node.js DuckDB connector for SQLRooms
3
+ *
4
+ * This package provides a DuckDB connector for Node.js environments using
5
+ * the @duckdb/node-api package.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ export { createNodeDuckDbConnector, } from './NodeDuckDbConnector';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,yBAAyB,GAG1B,MAAM,uBAAuB,CAAC","sourcesContent":["/**\n * @sqlrooms/duckdb-node - Node.js DuckDB connector for SQLRooms\n *\n * This package provides a DuckDB connector for Node.js environments using\n * the @duckdb/node-api package.\n *\n * @packageDocumentation\n */\n\nexport {\n createNodeDuckDbConnector,\n type NodeDuckDbConnector,\n type NodeDuckDbConnectorOptions,\n} from './NodeDuckDbConnector';\n\n// Re-export common types from duckdb-core for convenience\nexport type {\n DuckDbConnector,\n QueryHandle,\n QueryOptions,\n} from '@sqlrooms/duckdb-core';\n"]}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@sqlrooms/duckdb-node",
3
+ "version": "0.26.1-rc.11",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "module": "dist/index.js",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "author": "Ilya Boyandin <ilya@boyandin.me>",
10
+ "license": "MIT",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "https://github.com/sqlrooms/sqlrooms.git"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "dependencies": {
22
+ "@duckdb/node-api": "^1.4.2-r.1",
23
+ "@sqlrooms/duckdb-core": "0.26.1-rc.11"
24
+ },
25
+ "devDependencies": {
26
+ "@types/jest": "^30.0.0",
27
+ "jest": "^30.1.3",
28
+ "ts-jest": "^29.4.4"
29
+ },
30
+ "peerDependencies": {
31
+ "@sqlrooms/room-config": "0.26.1-rc.11",
32
+ "apache-arrow": "17.0.0"
33
+ },
34
+ "scripts": {
35
+ "dev": "tsc -w",
36
+ "build": "tsc",
37
+ "lint": "eslint .",
38
+ "typecheck": "tsc --noEmit",
39
+ "typedoc": "typedoc",
40
+ "test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest",
41
+ "test:watch": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest --watch"
42
+ },
43
+ "gitHead": "2675a4e65108dbbe67baac8a7dce471d5a688df7"
44
+ }