@malloydata/db-duckdb 0.0.405 → 0.0.407
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/dist/duckdb_config.js +25 -1
- package/dist/duckdb_wasm_connection.js +18 -2
- package/package.json +2 -2
package/dist/duckdb_config.js
CHANGED
|
@@ -47,6 +47,7 @@ exports.sqlStringLiteral = sqlStringLiteral;
|
|
|
47
47
|
exports.sqlStringListLiteral = sqlStringListLiteral;
|
|
48
48
|
exports.stringifyDuckDBOption = stringifyDuckDBOption;
|
|
49
49
|
const path_1 = __importDefault(require("path"));
|
|
50
|
+
const url_1 = require("url");
|
|
50
51
|
const malloy_1 = require("@malloydata/malloy");
|
|
51
52
|
const pathSecurity = __importStar(require("./path_security"));
|
|
52
53
|
class DuckDBConfigValidationError extends Error {
|
|
@@ -348,9 +349,32 @@ function canonicalizeDatabasePath(databasePath) {
|
|
|
348
349
|
}
|
|
349
350
|
return canonicalizeConfigPath(databasePath, 'databasePath');
|
|
350
351
|
}
|
|
352
|
+
// A config path can arrive as a `file://` URL rather than a plain path —
|
|
353
|
+
// notably `workingDirectory`, which defaults to `config.rootDirectory` (the
|
|
354
|
+
// config stack carries it as a URL string). Left as a URL, `path.resolve`
|
|
355
|
+
// treats `file:` as a relative segment and joins it to the process cwd,
|
|
356
|
+
// silently breaking relative `read_parquet`/glob resolution. Decode file URLs
|
|
357
|
+
// to a real path so every downstream consumer (FILE_SEARCH_PATH,
|
|
358
|
+
// allowed_directories, …) sees one. Plain paths and non-file schemes pass
|
|
359
|
+
// through untouched; a malformed file URL throws and surfaces as the caller's
|
|
360
|
+
// field-specific validation error.
|
|
361
|
+
function maybeFileURLToPath(input) {
|
|
362
|
+
// Cheap guard so plain paths (the common case) skip URL parsing entirely.
|
|
363
|
+
if (!/^[a-z][a-z0-9+.-]*:/i.test(input)) {
|
|
364
|
+
return input;
|
|
365
|
+
}
|
|
366
|
+
let url;
|
|
367
|
+
try {
|
|
368
|
+
url = new URL(input);
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
return input; // not a URL — treat as a plain path
|
|
372
|
+
}
|
|
373
|
+
return url.protocol === 'file:' ? (0, url_1.fileURLToPath)(url) : input;
|
|
374
|
+
}
|
|
351
375
|
function canonicalizeConfigPath(input, fieldName, options = {}) {
|
|
352
376
|
try {
|
|
353
|
-
return pathSecurity.canonicalizePath(input, options);
|
|
377
|
+
return pathSecurity.canonicalizePath(maybeFileURLToPath(input), options);
|
|
354
378
|
}
|
|
355
379
|
catch (error) {
|
|
356
380
|
throw new DuckDBConfigValidationError(`${fieldName} is invalid: ${errorMessage(error)}`);
|
|
@@ -214,6 +214,22 @@ function unwrapTable(table) {
|
|
|
214
214
|
return table.toArray().map(row => unwrapRow(row, table.schema));
|
|
215
215
|
}
|
|
216
216
|
const isNode = () => { var _a; return typeof process !== 'undefined' && typeof ((_a = process.versions) === null || _a === void 0 ? void 0 : _a.node) === 'string'; };
|
|
217
|
+
// `workingDirectory` defaults to `config.rootDirectory`, which the config
|
|
218
|
+
// stack carries as a URL string. DuckDB-Wasm's virtual filesystem wants a plain
|
|
219
|
+
// POSIX path; a `file://` URL left intact becomes a bogus FILE_SEARCH_PATH and
|
|
220
|
+
// breaks relative reads. Decode file URLs to their path. Browser-safe — uses
|
|
221
|
+
// the WHATWG `URL` (the native connection's Node `fileURLToPath` is unavailable
|
|
222
|
+
// here). Plain paths and non-file schemes pass through untouched.
|
|
223
|
+
function fileURLToVirtualPath(input) {
|
|
224
|
+
if (!/^file:\/\//i.test(input)) {
|
|
225
|
+
return input;
|
|
226
|
+
}
|
|
227
|
+
const decoded = decodeURIComponent(new URL(input).pathname);
|
|
228
|
+
// Drop a trailing separator but keep the filesystem root '/'.
|
|
229
|
+
return decoded.length > 1 && decoded.endsWith('/')
|
|
230
|
+
? decoded.slice(0, -1)
|
|
231
|
+
: decoded;
|
|
232
|
+
}
|
|
217
233
|
class DuckDBWASMConnection extends duckdb_common_1.DuckDBCommon {
|
|
218
234
|
constructor(arg, arg2, workingDirectory, queryOptions) {
|
|
219
235
|
var _a, _b;
|
|
@@ -233,7 +249,7 @@ class DuckDBWASMConnection extends duckdb_common_1.DuckDBCommon {
|
|
|
233
249
|
this.databasePath = arg2;
|
|
234
250
|
}
|
|
235
251
|
if (typeof workingDirectory === 'string') {
|
|
236
|
-
this.workingDirectory = workingDirectory;
|
|
252
|
+
this.workingDirectory = fileURLToVirtualPath(workingDirectory);
|
|
237
253
|
}
|
|
238
254
|
if (queryOptions) {
|
|
239
255
|
this.queryOptions = queryOptions;
|
|
@@ -248,7 +264,7 @@ class DuckDBWASMConnection extends duckdb_common_1.DuckDBCommon {
|
|
|
248
264
|
this.databasePath = arg.databasePath;
|
|
249
265
|
}
|
|
250
266
|
if (typeof arg.workingDirectory === 'string') {
|
|
251
|
-
this.workingDirectory = arg.workingDirectory;
|
|
267
|
+
this.workingDirectory = fileURLToVirtualPath(arg.workingDirectory);
|
|
252
268
|
}
|
|
253
269
|
if (typeof arg.motherDuckToken === 'string') {
|
|
254
270
|
this.motherDuckToken = arg.motherDuckToken;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/db-duckdb",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.407",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@duckdb/duckdb-wasm": "1.33.1-dev45.0",
|
|
63
63
|
"@duckdb/node-api": "1.5.3-r.2",
|
|
64
|
-
"@malloydata/malloy": "0.0.
|
|
64
|
+
"@malloydata/malloy": "0.0.407",
|
|
65
65
|
"@motherduck/wasm-client": "^0.6.6",
|
|
66
66
|
"apache-arrow": "^17.0.0",
|
|
67
67
|
"web-worker": "^1.5.0"
|