@ducklings/workers 1.4.3-dev.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.
- package/README.md +216 -0
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +426 -0
- package/dist/index.d.ts +426 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/wasm/duckdb-workers.js +8 -0
- package/dist/wasm/duckdb-workers.wasm +0 -0
- package/package.json +73 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import { Table } from '@uwdata/flechette';
|
|
2
|
+
export { Table, tableFromArrays, tableFromIPC, tableToIPC } from '@uwdata/flechette';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Ducklings Workers - Minimal DuckDB for Cloudflare Workers
|
|
6
|
+
*
|
|
7
|
+
* This package provides a lightweight DuckDB binding for WebAssembly,
|
|
8
|
+
* designed for Cloudflare Workers and serverless environments.
|
|
9
|
+
*
|
|
10
|
+
* IMPORTANT: In this build, query() and execute() are async and return Promises.
|
|
11
|
+
* Always use: `await conn.query(...)` or `await conn.execute(...)`
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* DuckDB type constants mapping to the C API type IDs.
|
|
18
|
+
* @category Types
|
|
19
|
+
*/
|
|
20
|
+
declare const DuckDBType: {
|
|
21
|
+
readonly INVALID: 0;
|
|
22
|
+
readonly BOOLEAN: 1;
|
|
23
|
+
readonly TINYINT: 2;
|
|
24
|
+
readonly SMALLINT: 3;
|
|
25
|
+
readonly INTEGER: 4;
|
|
26
|
+
readonly BIGINT: 5;
|
|
27
|
+
readonly UTINYINT: 6;
|
|
28
|
+
readonly USMALLINT: 7;
|
|
29
|
+
readonly UINTEGER: 8;
|
|
30
|
+
readonly UBIGINT: 9;
|
|
31
|
+
readonly FLOAT: 10;
|
|
32
|
+
readonly DOUBLE: 11;
|
|
33
|
+
readonly TIMESTAMP: 12;
|
|
34
|
+
readonly DATE: 13;
|
|
35
|
+
readonly TIME: 14;
|
|
36
|
+
readonly INTERVAL: 15;
|
|
37
|
+
readonly HUGEINT: 16;
|
|
38
|
+
readonly UHUGEINT: 32;
|
|
39
|
+
readonly VARCHAR: 17;
|
|
40
|
+
readonly BLOB: 18;
|
|
41
|
+
readonly DECIMAL: 19;
|
|
42
|
+
readonly TIMESTAMP_S: 20;
|
|
43
|
+
readonly TIMESTAMP_MS: 21;
|
|
44
|
+
readonly TIMESTAMP_NS: 22;
|
|
45
|
+
readonly ENUM: 23;
|
|
46
|
+
readonly LIST: 24;
|
|
47
|
+
readonly STRUCT: 25;
|
|
48
|
+
readonly MAP: 26;
|
|
49
|
+
readonly ARRAY: 33;
|
|
50
|
+
readonly UUID: 27;
|
|
51
|
+
readonly UNION: 28;
|
|
52
|
+
readonly BIT: 29;
|
|
53
|
+
readonly TIME_TZ: 30;
|
|
54
|
+
readonly TIMESTAMP_TZ: 31;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Type ID from DuckDB type constants.
|
|
58
|
+
* @category Types
|
|
59
|
+
*/
|
|
60
|
+
type DuckDBTypeId = (typeof DuckDBType)[keyof typeof DuckDBType];
|
|
61
|
+
/**
|
|
62
|
+
* Database access mode.
|
|
63
|
+
* @category Configuration
|
|
64
|
+
*/
|
|
65
|
+
declare enum AccessMode {
|
|
66
|
+
/** DuckDB determines mode based on context (resolves to READ_WRITE for in-memory) */
|
|
67
|
+
AUTOMATIC = "automatic",
|
|
68
|
+
/** Read-only mode - all write operations are blocked */
|
|
69
|
+
READ_ONLY = "read_only",
|
|
70
|
+
/** Read-write mode - allows both reads and writes */
|
|
71
|
+
READ_WRITE = "read_write"
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* DuckDB configuration options.
|
|
75
|
+
* @category Configuration
|
|
76
|
+
*/
|
|
77
|
+
interface DuckDBConfig {
|
|
78
|
+
/**
|
|
79
|
+
* Database access mode.
|
|
80
|
+
* Use READ_ONLY to prevent any data modification.
|
|
81
|
+
* @default AccessMode.AUTOMATIC
|
|
82
|
+
*/
|
|
83
|
+
accessMode?: AccessMode;
|
|
84
|
+
/**
|
|
85
|
+
* Enable external access (file I/O, httpfs, etc.).
|
|
86
|
+
* Set to false to prevent all external data access.
|
|
87
|
+
* WARNING: Setting to false will disable httpfs functionality.
|
|
88
|
+
* @default true
|
|
89
|
+
*/
|
|
90
|
+
enableExternalAccess?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Lock configuration after startup.
|
|
93
|
+
* Prevents runtime configuration changes via SQL SET commands.
|
|
94
|
+
* @default true (secure default)
|
|
95
|
+
*/
|
|
96
|
+
lockConfiguration?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Custom configuration options.
|
|
99
|
+
* Key-value pairs passed directly to duckdb_set_config.
|
|
100
|
+
* @see https://duckdb.org/docs/configuration/overview
|
|
101
|
+
*/
|
|
102
|
+
customConfig?: Record<string, string>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Error thrown by DuckDB operations.
|
|
106
|
+
* @category Types
|
|
107
|
+
*/
|
|
108
|
+
declare class DuckDBError extends Error {
|
|
109
|
+
readonly code?: string;
|
|
110
|
+
readonly query?: string;
|
|
111
|
+
constructor(message: string, code?: string, query?: string);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Options for SQL sanitization.
|
|
115
|
+
* @category Security
|
|
116
|
+
*/
|
|
117
|
+
interface SanitizeSqlOptions {
|
|
118
|
+
/** Allow PRAGMA statements (default: false) */
|
|
119
|
+
allowPragma?: boolean;
|
|
120
|
+
/** Allow COPY ... TO statements (default: false) */
|
|
121
|
+
allowCopyTo?: boolean;
|
|
122
|
+
/** Allow EXPORT DATABASE statements (default: false) */
|
|
123
|
+
allowExportDatabase?: boolean;
|
|
124
|
+
/** Allow duckdb_secrets() function (default: false) */
|
|
125
|
+
allowSecretsFunction?: boolean;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Result of SQL sanitization check.
|
|
129
|
+
* @category Security
|
|
130
|
+
*/
|
|
131
|
+
interface SanitizeResult {
|
|
132
|
+
/** Whether the SQL is considered safe */
|
|
133
|
+
safe: boolean;
|
|
134
|
+
/** The original SQL string */
|
|
135
|
+
sql: string;
|
|
136
|
+
/** Reason why the SQL was blocked (if unsafe) */
|
|
137
|
+
reason?: string;
|
|
138
|
+
/** The pattern that matched (if unsafe) */
|
|
139
|
+
matchedPattern?: string;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Checks if a SQL statement contains dangerous patterns.
|
|
143
|
+
*
|
|
144
|
+
* This function does not throw - it returns a result object indicating
|
|
145
|
+
* whether the SQL is safe or not. Use this when you want to handle
|
|
146
|
+
* unsafe SQL yourself.
|
|
147
|
+
*
|
|
148
|
+
* @category Security
|
|
149
|
+
* @param sql - The SQL statement to check
|
|
150
|
+
* @param options - Options to selectively allow certain patterns
|
|
151
|
+
* @returns A SanitizeResult object with safety status
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```typescript
|
|
155
|
+
* const result = checkSql("SELECT * FROM duckdb_secrets()");
|
|
156
|
+
* if (!result.safe) {
|
|
157
|
+
* console.log(`Blocked: ${result.reason}`);
|
|
158
|
+
* }
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
declare function checkSql(sql: string, options?: SanitizeSqlOptions): SanitizeResult;
|
|
162
|
+
/**
|
|
163
|
+
* Sanitizes a SQL statement by checking for dangerous patterns.
|
|
164
|
+
*
|
|
165
|
+
* This function throws a DuckDBError if the SQL contains dangerous patterns.
|
|
166
|
+
* Use this in request handlers to automatically reject unsafe queries.
|
|
167
|
+
*
|
|
168
|
+
* **Blocked patterns:**
|
|
169
|
+
* - `duckdb_secrets()` - Exposes database credentials
|
|
170
|
+
* - `PRAGMA` - Can modify database settings
|
|
171
|
+
* - `COPY ... TO` - Writes files to disk (COPY FROM is allowed)
|
|
172
|
+
* - `EXPORT DATABASE` - Exports database to files
|
|
173
|
+
*
|
|
174
|
+
* Note: SET commands are blocked separately by `lockConfiguration: true` in DuckDBConfig.
|
|
175
|
+
*
|
|
176
|
+
* @category Security
|
|
177
|
+
* @param sql - The SQL statement to sanitize
|
|
178
|
+
* @param options - Options to selectively allow certain patterns
|
|
179
|
+
* @returns The original SQL if safe
|
|
180
|
+
* @throws DuckDBError with code 'SANITIZE_ERROR' if dangerous patterns detected
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* import { sanitizeSql, DuckDBError } from '@ducklings/workers';
|
|
185
|
+
*
|
|
186
|
+
* // In a request handler
|
|
187
|
+
* try {
|
|
188
|
+
* const safeSql = sanitizeSql(userInput);
|
|
189
|
+
* const result = await conn.query(safeSql);
|
|
190
|
+
* return Response.json({ data: result });
|
|
191
|
+
* } catch (e) {
|
|
192
|
+
* if (e instanceof DuckDBError && e.code === 'SANITIZE_ERROR') {
|
|
193
|
+
* return Response.json({ error: e.message }, { status: 400 });
|
|
194
|
+
* }
|
|
195
|
+
* throw e;
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
declare function sanitizeSql(sql: string, options?: SanitizeSqlOptions): string;
|
|
200
|
+
/**
|
|
201
|
+
* Column metadata for query results.
|
|
202
|
+
* @category Types
|
|
203
|
+
*/
|
|
204
|
+
interface ColumnInfo {
|
|
205
|
+
name: string;
|
|
206
|
+
type: DuckDBTypeId;
|
|
207
|
+
alias?: string;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Options for initializing the DuckDB WASM module (workers build).
|
|
211
|
+
* @category Types
|
|
212
|
+
*/
|
|
213
|
+
interface InitOptions {
|
|
214
|
+
/**
|
|
215
|
+
* Pre-compiled WebAssembly.Module (required for Cloudflare Workers)
|
|
216
|
+
* In Workers, import the WASM file directly and pass it here.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* import wasmModule from '@ducklings/workers/wasm';
|
|
221
|
+
* await init({ wasmModule });
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
wasmModule: WebAssembly.Module;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Initialize the DuckDB WASM module (workers build with Asyncify).
|
|
228
|
+
*
|
|
229
|
+
* This version is optimized for Cloudflare Workers and uses the workers-specific
|
|
230
|
+
* WASM build that includes Asyncify support for async HTTP operations.
|
|
231
|
+
*
|
|
232
|
+
* @category Database
|
|
233
|
+
* @param options - Initialization options with pre-compiled WASM module
|
|
234
|
+
* @returns Promise that resolves when initialization is complete
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* import { init, DuckDB } from '@ducklings/workers';
|
|
239
|
+
* import wasmModule from '@ducklings/workers/wasm';
|
|
240
|
+
*
|
|
241
|
+
* await init({ wasmModule });
|
|
242
|
+
*
|
|
243
|
+
* const db = new DuckDB();
|
|
244
|
+
* const conn = db.connect();
|
|
245
|
+
*
|
|
246
|
+
* // httpfs works in CF Workers with this build!
|
|
247
|
+
* const result = await conn.query("SELECT * FROM 'https://example.com/data.parquet'");
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
declare function init(options: InitOptions): Promise<void>;
|
|
251
|
+
/**
|
|
252
|
+
* Returns the DuckDB library version.
|
|
253
|
+
* @category Database
|
|
254
|
+
*/
|
|
255
|
+
declare function version(): string;
|
|
256
|
+
/**
|
|
257
|
+
* A prepared SQL statement with parameter binding.
|
|
258
|
+
* @category Query Results
|
|
259
|
+
*/
|
|
260
|
+
declare class PreparedStatement {
|
|
261
|
+
private stmtPtr;
|
|
262
|
+
private closed;
|
|
263
|
+
private readonly sql;
|
|
264
|
+
/** @internal */
|
|
265
|
+
constructor(stmtPtr: number, _connPtr: number, sql: string);
|
|
266
|
+
parameterCount(): number;
|
|
267
|
+
bindBoolean(index: number, value: boolean): this;
|
|
268
|
+
bindInt32(index: number, value: number): this;
|
|
269
|
+
bindInt64(index: number, value: bigint | number): this;
|
|
270
|
+
bindFloat(index: number, value: number): this;
|
|
271
|
+
bindDouble(index: number, value: number): this;
|
|
272
|
+
bindString(index: number, value: string): this;
|
|
273
|
+
bindBlob(index: number, value: Uint8Array): this;
|
|
274
|
+
bindNull(index: number): this;
|
|
275
|
+
bindTimestamp(index: number, value: Date): this;
|
|
276
|
+
bindDate(index: number, value: Date): this;
|
|
277
|
+
bind(index: number, value: unknown): this;
|
|
278
|
+
/**
|
|
279
|
+
* Executes the prepared statement and returns results as an array of objects.
|
|
280
|
+
* @returns Promise resolving to array of result rows
|
|
281
|
+
*/
|
|
282
|
+
run<T = Record<string, unknown>>(): Promise<T[]>;
|
|
283
|
+
/**
|
|
284
|
+
* Executes the prepared statement without returning results.
|
|
285
|
+
* @returns Promise resolving to number of rows affected
|
|
286
|
+
*/
|
|
287
|
+
execute(): Promise<number>;
|
|
288
|
+
close(): void;
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* A chunk of data from a streaming query result.
|
|
292
|
+
* @category Query Results
|
|
293
|
+
*/
|
|
294
|
+
declare class DataChunk {
|
|
295
|
+
private chunkPtr;
|
|
296
|
+
private destroyed;
|
|
297
|
+
private readonly columns;
|
|
298
|
+
/** @internal */
|
|
299
|
+
constructor(chunkPtr: number, columns: ColumnInfo[]);
|
|
300
|
+
get rowCount(): number;
|
|
301
|
+
get columnCount(): number;
|
|
302
|
+
getColumnInfo(): ColumnInfo[];
|
|
303
|
+
getColumn(columnIndex: number): unknown[];
|
|
304
|
+
toArray<T = Record<string, unknown>>(): T[];
|
|
305
|
+
private readVectorData;
|
|
306
|
+
destroy(): void;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* A streaming query result that yields data in chunks.
|
|
310
|
+
* @category Query Results
|
|
311
|
+
*/
|
|
312
|
+
declare class StreamingResult implements Iterable<DataChunk> {
|
|
313
|
+
private resultPtr;
|
|
314
|
+
private closed;
|
|
315
|
+
private readonly columns;
|
|
316
|
+
private currentChunkIndex;
|
|
317
|
+
private readonly totalChunks;
|
|
318
|
+
/** @internal */
|
|
319
|
+
constructor(resultPtr: number, columns: ColumnInfo[]);
|
|
320
|
+
getColumns(): ColumnInfo[];
|
|
321
|
+
get columnCount(): number;
|
|
322
|
+
get chunkCount(): number;
|
|
323
|
+
nextChunk(): DataChunk | null;
|
|
324
|
+
reset(): void;
|
|
325
|
+
[Symbol.iterator](): Iterator<DataChunk>;
|
|
326
|
+
toArray<T = Record<string, unknown>>(): T[];
|
|
327
|
+
toArrowTable(): Table;
|
|
328
|
+
private getFlechetteType;
|
|
329
|
+
close(): void;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* DuckDB database instance for Cloudflare Workers.
|
|
333
|
+
*
|
|
334
|
+
* @category Database
|
|
335
|
+
* @example
|
|
336
|
+
* ```typescript
|
|
337
|
+
* import { init, DuckDB, AccessMode } from '@ducklings/workers';
|
|
338
|
+
* import wasmModule from '@ducklings/workers/wasm';
|
|
339
|
+
*
|
|
340
|
+
* await init({ wasmModule });
|
|
341
|
+
*
|
|
342
|
+
* // Default configuration (httpfs enabled, config locked)
|
|
343
|
+
* const db = new DuckDB();
|
|
344
|
+
*
|
|
345
|
+
* // Or with custom security configuration
|
|
346
|
+
* const secureDb = new DuckDB({
|
|
347
|
+
* accessMode: AccessMode.READ_ONLY,
|
|
348
|
+
* lockConfiguration: true,
|
|
349
|
+
* });
|
|
350
|
+
*
|
|
351
|
+
* const conn = db.connect();
|
|
352
|
+
* const result = await conn.query('SELECT 42 as answer');
|
|
353
|
+
* console.log(result);
|
|
354
|
+
*
|
|
355
|
+
* conn.close();
|
|
356
|
+
* db.close();
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
359
|
+
declare class DuckDB {
|
|
360
|
+
private dbPtr;
|
|
361
|
+
private closed;
|
|
362
|
+
/**
|
|
363
|
+
* Creates a new DuckDB database instance.
|
|
364
|
+
*
|
|
365
|
+
* @param config - Optional configuration options
|
|
366
|
+
*/
|
|
367
|
+
constructor(config?: DuckDBConfig);
|
|
368
|
+
/**
|
|
369
|
+
* Creates a new DuckDB database instance asynchronously.
|
|
370
|
+
*
|
|
371
|
+
* @param config - Optional configuration options
|
|
372
|
+
*/
|
|
373
|
+
static create(config?: DuckDBConfig): Promise<DuckDB>;
|
|
374
|
+
connect(): Connection;
|
|
375
|
+
close(): void;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* A connection to a DuckDB database (async API for Cloudflare Workers).
|
|
379
|
+
*
|
|
380
|
+
* All query methods in this class are async and return Promises.
|
|
381
|
+
* @category Connection
|
|
382
|
+
*/
|
|
383
|
+
declare class Connection {
|
|
384
|
+
private connPtr;
|
|
385
|
+
private closed;
|
|
386
|
+
/** @internal */
|
|
387
|
+
constructor(connPtr: number);
|
|
388
|
+
/**
|
|
389
|
+
* Executes a SQL query and returns the results.
|
|
390
|
+
* This is async to support httpfs in Cloudflare Workers.
|
|
391
|
+
*
|
|
392
|
+
* @param sql - The SQL query to execute
|
|
393
|
+
* @returns Promise resolving to array of result rows as objects
|
|
394
|
+
*/
|
|
395
|
+
query<T = Record<string, unknown>>(sql: string): Promise<T[]>;
|
|
396
|
+
private readColumnData;
|
|
397
|
+
/**
|
|
398
|
+
* Executes a SQL query and returns results as an Arrow table.
|
|
399
|
+
*
|
|
400
|
+
* @param sql - The SQL query to execute
|
|
401
|
+
* @returns Promise resolving to Arrow Table
|
|
402
|
+
*/
|
|
403
|
+
queryArrow(sql: string): Promise<Table>;
|
|
404
|
+
private getFlechetteType;
|
|
405
|
+
/**
|
|
406
|
+
* Executes a SQL statement without returning results.
|
|
407
|
+
*
|
|
408
|
+
* @param sql - The SQL statement to execute
|
|
409
|
+
* @returns Promise resolving to number of rows affected
|
|
410
|
+
*/
|
|
411
|
+
execute(sql: string): Promise<number>;
|
|
412
|
+
/**
|
|
413
|
+
* Creates a prepared statement for the given SQL.
|
|
414
|
+
*
|
|
415
|
+
* @param sql - The SQL statement to prepare (use ? for parameters)
|
|
416
|
+
* @returns A PreparedStatement instance
|
|
417
|
+
*/
|
|
418
|
+
prepare(sql: string): PreparedStatement;
|
|
419
|
+
beginTransaction(): Promise<void>;
|
|
420
|
+
commit(): Promise<void>;
|
|
421
|
+
rollback(): Promise<void>;
|
|
422
|
+
transaction<T>(fn: () => Promise<T>): Promise<T>;
|
|
423
|
+
close(): void;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export { AccessMode, type ColumnInfo, Connection, DataChunk, DuckDB, type DuckDBConfig, DuckDBError, DuckDBType, type DuckDBTypeId, type InitOptions, PreparedStatement, type SanitizeResult, type SanitizeSqlOptions, StreamingResult, checkSql, init, sanitizeSql, version };
|