@flowblade/sqlduck 0.17.2 → 0.17.3

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 CHANGED
@@ -128,76 +128,75 @@ const queryResult = await dbDuckDbMemoryConn.query<{
128
128
 
129
129
  ## Benchmarks
130
130
 
131
- ### Node 24
131
+ ### Node 24.15
132
132
 
133
133
  ```
134
+ RUN v4.1.5 /home/sebastien/github/flowblade/packages/sqlduck
134
135
 
135
- RUN v4.1.4 /home/sebastien/github/flowblade/packages/sqlduck
136
136
 
137
+ ✓ bench/appender.bench.ts > appender benches 3477ms
138
+ name hz min max mean p75 p99 p995 p999 rme samples
139
+ · duckdb appender memory, count: 100000, chunk size 2048 2.9578 336.81 339.37 338.09 339.37 339.37 339.37 339.37 ±4.82% 2
140
+ · duckdb appender file, count: 100000, chunk size 2048 1.5359 651.07 651.07 651.07 651.07 651.07 651.07 651.07 ±0.00% 1
141
+ · duckdb appender, count: 100000, chunk size 1024 2.8450 328.25 374.74 351.50 374.74 374.74 374.74 374.74 ±84.06% 2
137
142
 
138
- ✓ bench/appender.bench.ts > appender benches 2910ms
139
- name hz min max mean p75 p99 p995 p999 rme samples
140
- · duckdb appender memory, count: 100000, chunk size 2048 3.5446 265.91 298.32 282.12 298.32 298.32 298.32 298.32 ±72.99% 2
141
- · duckdb appender file, count: 100000, chunk size 2048 2.6130 355.30 410.10 382.70 410.10 410.10 410.10 410.10 ±91.00% 2
142
- · duckdb appender, count: 100000, chunk size 1024 3.8027 226.52 299.42 262.97 299.42 299.42 299.42 299.42 ±176.17% 2
143
-
144
- ✓ bench/stream.bench.ts > Bench rowsToColumnsChunks 2998ms
143
+ ✓ bench/stream.bench.ts > Bench rowsToColumnsChunks 3514ms
145
144
  name hz min max mean p75 p99 p995 p999 rme samples
146
- · rowToColumnsChunk with chunkSize 2048 (count: 100000) 11.3182 60.6404 190.56 88.3532 79.4999 190.56 190.56 190.56 ±30.64% 10
147
- · rowToColumnsChunk with transformer with chunkSize 2048 (count: 100000) 13.4430 63.9716 102.73 74.3883 75.2151 102.73 102.73 102.73 ±10.40% 10
148
- · mapFakeRowStream with chunkSize 2048 (count: 100000) 10.7785 84.3040 117.57 92.7773 97.1595 117.57 117.57 117.57 ±7.61% 10
145
+ · rowToColumnsChunk with chunkSize 2048 (count: 100000) 10.6932 76.7549 197.03 93.5173 88.9991 197.03 197.03 197.03 ±28.09% 10
146
+ · rowToColumnsChunk with transformer with chunkSize 2048 (count: 100000) 10.2660 87.8295 141.15 97.4092 97.0299 141.15 141.15 141.15 ±11.56% 10
147
+ · mapFakeRowStream with chunkSize 2048 (count: 100000) 8.3811 113.83 136.27 119.32 118.84 136.27 136.27 136.27 ±4.30% 10
149
148
 
150
- ✓ bench/table-create.bench.ts > Bench getTableCreateFromZod 615ms
149
+ ✓ bench/table-create.bench.ts > Bench getTableCreateFromZod 614ms
151
150
  name hz min max mean p75 p99 p995 p999 rme samples
152
- · getTableCreateFromZod 27,048.71 0.0239 3.2029 0.0370 0.0404 0.1310 0.1980 0.5674 ±2.08% 13525
151
+ · getTableCreateFromZod 20,399.65 0.0328 1.2897 0.0490 0.0425 0.1957 0.2681 0.6023 ±1.77% 10201
153
152
 
154
153
  BENCH Summary
155
154
 
156
- duckdb appender, count: 100000, chunk size 1024 - bench/appender.bench.ts > appender benches
157
- 1.07x faster than duckdb appender memory, count: 100000, chunk size 2048
158
- 1.46x faster than duckdb appender file, count: 100000, chunk size 2048
155
+ duckdb appender memory, count: 100000, chunk size 2048 - bench/appender.bench.ts > appender benches
156
+ 1.04x faster than duckdb appender, count: 100000, chunk size 1024
157
+ 1.93x faster than duckdb appender file, count: 100000, chunk size 2048
159
158
 
160
- rowToColumnsChunk with transformer with chunkSize 2048 (count: 100000) - bench/stream.bench.ts > Bench rowsToColumnsChunks
161
- 1.19x faster than rowToColumnsChunk with chunkSize 2048 (count: 100000)
162
- 1.25x faster than mapFakeRowStream with chunkSize 2048 (count: 100000)
159
+ rowToColumnsChunk with chunkSize 2048 (count: 100000) - bench/stream.bench.ts > Bench rowsToColumnsChunks
160
+ 1.04x faster than rowToColumnsChunk with transformer with chunkSize 2048 (count: 100000)
161
+ 1.28x faster than mapFakeRowStream with chunkSize 2048 (count: 100000)
163
162
 
164
163
  getTableCreateFromZod - bench/table-create.bench.ts > Bench getTableCreateFromZod
164
+
165
165
  ```
166
166
 
167
- ### Bun 1.3.12
167
+ ### Bun 1.3.13
168
168
 
169
169
  ```
170
- RUN v4.1.4 /home/sebastien/github/flowblade/packages/sqlduck
170
+ RUN v4.1.5 /home/sebastien/github/flowblade/packages/sqlduck
171
171
 
172
172
 
173
- ✓ bench/appender.bench.ts > appender benches 2811ms
173
+ ✓ bench/appender.bench.ts > appender benches 3382ms
174
174
  name hz min max mean p75 p99 p995 p999 rme samples
175
- · duckdb appender memory, count: 100000, chunk size 2048 3.9242 224.75 285.38 254.83 285.38 285.38 285.38 285.38 ±29.56% 3
176
- · duckdb appender file, count: 100000, chunk size 2048 3.8209 256.09 267.34 261.72 267.34 267.34 267.34 267.34 ±27.31% 2
177
- · duckdb appender, count: 100000, chunk size 1024 4.6118 196.77 234.22 216.84 234.22 234.22 234.22 234.22 ±21.62% 3
175
+ · duckdb appender memory, count: 100000, chunk size 2048 3.0570 310.57 343.67 327.12 343.67 343.67 343.67 343.67 ±64.30% 2
176
+ · duckdb appender file, count: 100000, chunk size 2048 2.6163 377.75 386.70 382.22 386.70 386.70 386.70 386.70 ±14.88% 2
177
+ · duckdb appender, count: 100000, chunk size 1024 3.0427 319.38 337.93 328.65 337.93 337.93 337.93 337.93 ±35.86% 2
178
178
 
179
- ✓ bench/stream.bench.ts > Bench rowsToColumnsChunks 2667ms
179
+ ✓ bench/stream.bench.ts > Bench rowsToColumnsChunks 3075ms
180
180
  name hz min max mean p75 p99 p995 p999 rme samples
181
- · rowToColumnsChunk with chunkSize 2048 (count: 100000) 14.4994 57.7717 81.8690 68.9683 78.5234 81.8690 81.8690 81.8690 ±9.43% 10
182
- · rowToColumnsChunk with transformer with chunkSize 2048 (count: 100000) 13.2052 68.7139 96.8400 75.7275 79.4380 96.8400 96.8400 96.8400 ±8.22% 10
183
- · mapFakeRowStream with chunkSize 2048 (count: 100000) 12.7827 73.9127 85.0696 78.2310 82.5510 85.0696 85.0696 85.0696 ±3.69% 10
181
+ · rowToColumnsChunk with chunkSize 2048 (count: 100000) 12.5039 68.9091 89.8222 79.9751 84.4430 89.8222 89.8222 89.8222 ±5.45% 10
182
+ · rowToColumnsChunk with transformer with chunkSize 2048 (count: 100000) 10.9097 83.6090 124.66 91.6616 92.3154 124.66 124.66 124.66 ±9.42% 10
183
+ · mapFakeRowStream with chunkSize 2048 (count: 100000) 10.2729 90.7410 104.18 97.3436 100.41 104.18 104.18 104.18 ±2.93% 10
184
184
 
185
- ✓ bench/table-create.bench.ts > Bench getTableCreateFromZod 624ms
185
+ ✓ bench/table-create.bench.ts > Bench getTableCreateFromZod 629ms
186
186
  name hz min max mean p75 p99 p995 p999 rme samples
187
- · getTableCreateFromZod 28,477.04 0.0191 6.4836 0.0351 0.0335 0.1071 0.1530 2.4823 ±6.21% 14239
187
+ · getTableCreateFromZod 20,285.23 0.0260 6.9886 0.0493 0.0466 0.1700 0.2249 2.6988 ±6.12% 10143
188
188
 
189
189
  BENCH Summary
190
190
 
191
191
  rowToColumnsChunk with chunkSize 2048 (count: 100000) - bench/stream.bench.ts > Bench rowsToColumnsChunks
192
- 1.10x faster than rowToColumnsChunk with transformer with chunkSize 2048 (count: 100000)
193
- 1.13x faster than mapFakeRowStream with chunkSize 2048 (count: 100000)
192
+ 1.15x faster than rowToColumnsChunk with transformer with chunkSize 2048 (count: 100000)
193
+ 1.22x faster than mapFakeRowStream with chunkSize 2048 (count: 100000)
194
194
 
195
195
  getTableCreateFromZod - bench/table-create.bench.ts > Bench getTableCreateFromZod
196
196
 
197
- duckdb appender, count: 100000, chunk size 1024 - bench/appender.bench.ts > appender benches
198
- 1.18x faster than duckdb appender memory, count: 100000, chunk size 2048
199
- 1.21x faster than duckdb appender file, count: 100000, chunk size 2048
200
-
197
+ duckdb appender memory, count: 100000, chunk size 2048 - bench/appender.bench.ts > appender benches
198
+ 1.00x faster than duckdb appender, count: 100000, chunk size 1024
199
+ 1.17x faster than duckdb appender file, count: 100000, chunk size 2048
201
200
  ```
202
201
 
203
202
  ### Local scripts
package/dist/index.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { n as DuckConnectionParams } from "./types-dnhcognF.mjs";
2
- import * as _$_duckdb_node_api0 from "@duckdb/node-api";
3
2
  import { DuckDBConnection, DuckDBType } from "@duckdb/node-api";
4
3
  import * as _$_logtape_logtape0 from "@logtape/logtape";
5
4
  import { Logger } from "@logtape/logtape";
@@ -276,6 +275,7 @@ type DuckDatabaseAttachCommandOptions = {
276
275
  //#region src/manager/database/duck-database-manager.d.ts
277
276
  declare class DuckDatabaseManager {
278
277
  #private;
278
+ readonly className = "DuckDatabaseManager";
279
279
  constructor(conn: DuckDBConnection, params?: {
280
280
  logger?: Logger;
281
281
  });
@@ -297,7 +297,7 @@ declare class DuckDatabaseManager {
297
297
  attach: (dbParams: DuckConnectionParams, options?: DuckDatabaseAttachCommandOptions) => Promise<Database>;
298
298
  attachOrReplace: (dbParams: DuckConnectionParams) => Promise<Database>;
299
299
  attachIfNotExists: (dbParams: DuckConnectionParams) => Promise<Database>;
300
- showDatabases: () => Promise<Record<string, _$_duckdb_node_api0.JS>[]>;
300
+ showDatabases: () => Promise<Record<string, unknown>[]>;
301
301
  detach: (dbAlias: string) => Promise<boolean>;
302
302
  detachIfExists: (dbAlias: string) => Promise<boolean>;
303
303
  /**
@@ -322,6 +322,36 @@ declare class DuckDatabaseManager {
322
322
  }>;
323
323
  }
324
324
  //#endregion
325
+ //#region src/manager/extensions/duck-extensions-manager.d.ts
326
+ declare class DuckExtensionsManager {
327
+ #private;
328
+ readonly className = "DuckExtensionsManager";
329
+ constructor(conn: DuckDBConnection, params?: {
330
+ logger?: Logger;
331
+ });
332
+ install: (name: string, params?: {
333
+ force?: boolean;
334
+ }) => Promise<true>;
335
+ search: (filters?: {
336
+ installed?: boolean;
337
+ name?: string;
338
+ }) => Promise<{
339
+ extension_name: string;
340
+ installed: boolean;
341
+ description: string;
342
+ }[]>;
343
+ }
344
+ //#endregion
345
+ //#region src/manager/settings/duck-settings-manager.d.ts
346
+ declare class DuckSettingsManager {
347
+ #private;
348
+ readonly className = "DuckSettingsManager";
349
+ constructor(conn: DuckDBConnection, params?: {
350
+ logger?: Logger;
351
+ });
352
+ getCurrentSettings: <T extends string>(settings: T[]) => Promise<Record<T, string>>;
353
+ }
354
+ //#endregion
325
355
  //#region src/config/flowblade-logtape-sqlduck.config.d.ts
326
356
  declare const flowbladeLogtapeSqlduckConfig: {
327
357
  categories: string[];
@@ -330,4 +360,4 @@ declare const flowbladeLogtapeSqlduckConfig: {
330
360
  //#region src/logger/sqlduck-default-logtape-logger.d.ts
331
361
  declare const sqlduckDefaultLogtapeLogger: _$_logtape_logtape0.Logger;
332
362
  //#endregion
333
- export { Database, type DuckConnectionParams, DuckDatabaseManager, DuckMemory, type DuckMemoryTag, type DuckdbReservedKeywords, type OnChunkAppendedCb, type OnChunkAppendedStats, SqlDuck, type SqlDuckParams, Table, type ToTableParams, duckReservedKeywords, flowbladeLogtapeSqlduckConfig, getTableCreateFromZod, sqlduckDefaultLogtapeLogger, zodCodecs };
363
+ export { Database, type DuckConnectionParams, DuckDatabaseManager, DuckExtensionsManager, DuckMemory, type DuckMemoryTag, DuckSettingsManager, type DuckdbReservedKeywords, type OnChunkAppendedCb, type OnChunkAppendedStats, SqlDuck, type SqlDuckParams, Table, type ToTableParams, duckReservedKeywords, flowbladeLogtapeSqlduckConfig, getTableCreateFromZod, sqlduckDefaultLogtapeLogger, zodCodecs };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as duckReservedKeywords } from "./duck-reserved-keywords-B8XUjnaY.mjs";
2
- import { c as duckValidatorsZod, r as assertValidAliasName, s as duckConnectionParamsZodSchema } from "./zod-D87TPB5c.mjs";
2
+ import { c as duckValidatorsZod, r as assertValidAliasName, s as duckConnectionParamsZodSchema } from "./zod-CVF6XJKu.mjs";
3
3
  import { BIGINT, BOOLEAN, DOUBLE, DuckDBDataChunk, DuckDBInstanceCache, DuckDBTimestampMillisecondsValue, DuckDBTypeId, ENUM, FLOAT, HUGEINT, INTEGER, SMALLINT, TIMESTAMP, TIMESTAMP_MS, TINYINT, UBIGINT, UHUGEINT, UINTEGER, USMALLINT, UTINYINT, UUID, VARCHAR } from "@duckdb/node-api";
4
4
  import { getLogger } from "@logtape/logtape";
5
5
  import fs from "node:fs";
@@ -331,6 +331,38 @@ var Database = class {
331
331
  }
332
332
  };
333
333
  //#endregion
334
+ //#region src/manager/core/manager-query-executor.ts
335
+ var ManagerQueryExecutor = class {
336
+ #conn;
337
+ #logger;
338
+ #className;
339
+ constructor(conn, className, params) {
340
+ this.#conn = conn;
341
+ this.#logger = params.logger;
342
+ this.#className = className;
343
+ }
344
+ getRowObjectsJS = async (name, rawSql) => {
345
+ const fnName = `${this.#className}.${name}`;
346
+ const startTime = Date.now();
347
+ try {
348
+ const result = await this.#conn.runAndReadAll(rawSql);
349
+ const timeMs = Math.round(Date.now() - startTime);
350
+ const data = result.getRowObjectsJS();
351
+ this.#logger.debug(`${fnName} in ${timeMs}ms`, { timeMs });
352
+ return data;
353
+ } catch (e) {
354
+ const msg = `Failed to run "${fnName}" - ${e?.message ?? ""}`;
355
+ const timeMs = Math.round(Date.now() - startTime);
356
+ this.#logger.error(msg, {
357
+ name: fnName,
358
+ sql: rawSql,
359
+ timeMs
360
+ });
361
+ throw new Error(msg, { cause: e });
362
+ }
363
+ };
364
+ };
365
+ //#endregion
334
366
  //#region src/manager/database/commands/duck-database-attach-command.ts
335
367
  var DuckDatabaseAttachCommand = class {
336
368
  options;
@@ -391,9 +423,12 @@ var DuckDatabaseManager = class {
391
423
  #conn;
392
424
  #logger;
393
425
  #fs;
426
+ #executor;
427
+ className = "DuckDatabaseManager";
394
428
  constructor(conn, params) {
395
429
  this.#conn = conn;
396
- this.#logger = params?.logger ?? sqlduckDefaultLogtapeLogger.with({ source: "DuckDatabaseManager" });
430
+ this.#logger = params?.logger ?? sqlduckDefaultLogtapeLogger.with({ source: this.className });
431
+ this.#executor = new ManagerQueryExecutor(this.#conn, this.className, { logger: this.#logger });
397
432
  }
398
433
  /**
399
434
  * Attach a database to the current connection
@@ -414,7 +449,7 @@ var DuckDatabaseManager = class {
414
449
  const params = duckConnectionParamsZodSchema.parse(dbParams);
415
450
  const rawSql = new DuckDatabaseAttachCommand(params, options).getRawSql();
416
451
  const { behaviour } = options ?? {};
417
- await this.#executeRawSqlCommand([
452
+ await this.#executor.getRowObjectsJS([
418
453
  `attach(${params.alias}`,
419
454
  behaviour ?? null,
420
455
  ")"
@@ -428,16 +463,16 @@ var DuckDatabaseManager = class {
428
463
  return this.attach(dbParams, { behaviour: "IF NOT EXISTS" });
429
464
  };
430
465
  showDatabases = async () => {
431
- return await this.#executeRawSqlCommand("showDatabases()", `SHOW DATABASES`);
466
+ return await this.#executor.getRowObjectsJS("showDatabases()", `SHOW DATABASES`);
432
467
  };
433
468
  detach = async (dbAlias) => {
434
469
  assertValidAliasName(dbAlias);
435
- await this.#executeRawSqlCommand(`detach(${dbAlias})`, `DETACH ${dbAlias}`);
470
+ await this.#executor.getRowObjectsJS(`detach(${dbAlias})`, `DETACH ${dbAlias}`);
436
471
  return true;
437
472
  };
438
473
  detachIfExists = async (dbAlias) => {
439
474
  assertValidAliasName(dbAlias);
440
- await this.#executeRawSqlCommand(`detachIfExists(${dbAlias})`, `DETACH IF EXISTS ${dbAlias}`);
475
+ await this.#executor.getRowObjectsJS(`detachIfExists(${dbAlias})`, `DETACH IF EXISTS ${dbAlias}`);
441
476
  return true;
442
477
  };
443
478
  /**
@@ -449,16 +484,16 @@ var DuckDatabaseManager = class {
449
484
  * @link https://duckdb.org/docs/stable/sql/statements/analyze
450
485
  */
451
486
  analyze = async () => {
452
- await this.#executeRawSqlCommand("analyze()", "ANALYZE");
487
+ await this.#executor.getRowObjectsJS("analyze()", "ANALYZE");
453
488
  return true;
454
489
  };
455
490
  checkpoint = async (dbAlias) => {
456
491
  const safeAlias = duckValidatorsZod.aliasName.parse(dbAlias);
457
- await this.#executeRawSqlCommand(`checkpoint(${safeAlias})`, `CHECKPOINT ${safeAlias}`);
492
+ await this.#executor.getRowObjectsJS(`checkpoint(${safeAlias})`, `CHECKPOINT ${safeAlias}`);
458
493
  return true;
459
494
  };
460
495
  vacuum = async () => {
461
- await this.#executeRawSqlCommand("vacuum()", "VACUUM");
496
+ await this.#executor.getRowObjectsJS("vacuum()", "VACUUM");
462
497
  return true;
463
498
  };
464
499
  /**
@@ -487,25 +522,6 @@ var DuckDatabaseManager = class {
487
522
  }
488
523
  return { status: "created" };
489
524
  };
490
- #executeRawSqlCommand = async (name, rawSql) => {
491
- const startTime = Date.now();
492
- try {
493
- const result = await this.#conn.runAndReadAll(rawSql);
494
- const timeMs = Math.round(Date.now() - startTime);
495
- const data = result.getRowObjectsJS();
496
- this.#logger.debug(`DuckDatabaseManager.${name} in ${timeMs}ms`, { timeMs });
497
- return data;
498
- } catch (e) {
499
- const msg = `DuckDatabaseManager: failed to run "${name}" - ${e?.message ?? ""}`;
500
- const timeMs = Math.round(Date.now() - startTime);
501
- this.#logger.error(msg, {
502
- name,
503
- sql: rawSql,
504
- timeMs
505
- });
506
- throw new Error(msg, { cause: e });
507
- }
508
- };
509
525
  #getFs = () => {
510
526
  if (this.#fs === void 0) this.#fs = new FileSystemUtils({ logger: this.#logger });
511
527
  return this.#fs;
@@ -929,4 +945,61 @@ var Table = class Table {
929
945
  };
930
946
  };
931
947
  //#endregion
932
- export { Database, DuckDatabaseManager, DuckMemory, SqlDuck, Table, duckReservedKeywords, flowbladeLogtapeSqlduckConfig, getTableCreateFromZod, sqlduckDefaultLogtapeLogger, zodCodecs };
948
+ //#region src/manager/extensions/duck-extensions-manager.ts
949
+ var DuckExtensionsManager = class {
950
+ #conn;
951
+ #logger;
952
+ #executor;
953
+ className = "DuckExtensionsManager";
954
+ constructor(conn, params) {
955
+ this.#conn = conn;
956
+ this.#logger = params?.logger ?? sqlduckDefaultLogtapeLogger.with({ source: this.className });
957
+ this.#executor = new ManagerQueryExecutor(this.#conn, this.className, { logger: this.#logger });
958
+ }
959
+ install = async (name, params) => {
960
+ const { force } = params ?? {};
961
+ await this.#executor.getRowObjectsJS("install", `${force ? "FORCE " : ""} INSTALL ${name}`);
962
+ return true;
963
+ };
964
+ search = async (filters) => {
965
+ const { installed, name } = filters ?? {};
966
+ const conditions = [installed === void 0 ? "" : `installed = ${installed ? "true" : "false"}`, name === void 0 ? "" : `extension_name = '${name}'`].filter(Boolean);
967
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
968
+ return await this.#executor.getRowObjectsJS("showExtensions", `
969
+ SELECT extension_name, installed, description
970
+ FROM duckdb_extensions()
971
+ ${where}
972
+ ORDER BY extension_name
973
+ `);
974
+ };
975
+ };
976
+ //#endregion
977
+ //#region src/manager/settings/duck-settings-manager.ts
978
+ var DuckSettingsManager = class {
979
+ #conn;
980
+ #logger;
981
+ #executor;
982
+ className = "DuckSettingsManager";
983
+ constructor(conn, params) {
984
+ this.#conn = conn;
985
+ this.#logger = params?.logger ?? sqlduckDefaultLogtapeLogger.with({ source: this.className });
986
+ this.#executor = new ManagerQueryExecutor(this.#conn, this.className, { logger: this.#logger });
987
+ }
988
+ getCurrentSettings = async (settings) => {
989
+ const fnName = `${this.className}.getCurrentSettings`;
990
+ const query = `SELECT ${settings.map((s) => {
991
+ return `current_setting('${s}') as '${s}'`;
992
+ }).join(",\n")}`;
993
+ const firstRow = (await this.#executor.getRowObjectsJS(fnName, query))[0];
994
+ if (firstRow === void 0) {
995
+ const msg = `Failed to get current settings - no rows returned`;
996
+ this.#logger.error(msg, { sql: query });
997
+ throw new Error(msg);
998
+ }
999
+ const currentSettings = {};
1000
+ for (const [key, value] of Object.entries(firstRow)) currentSettings[key] = typeof value === "string" ? value : String(value);
1001
+ return currentSettings;
1002
+ };
1003
+ };
1004
+ //#endregion
1005
+ export { Database, DuckDatabaseManager, DuckExtensionsManager, DuckMemory, DuckSettingsManager, SqlDuck, Table, duckReservedKeywords, flowbladeLogtapeSqlduckConfig, getTableCreateFromZod, sqlduckDefaultLogtapeLogger, zodCodecs };
@@ -19,6 +19,10 @@ const duckIdentifierValibotSchema = v.pipe(v.string(), v.minLength(1), v.maxLeng
19
19
  * ```
20
20
  */
21
21
  const duckValidatorsValibot = {
22
+ /**
23
+ * Validate duckdb objects names like table, alias, and schemas
24
+ * for validity.
25
+ */
22
26
  aliasName: duckIdentifierValibotSchema,
23
27
  schemaName: duckIdentifierValibotSchema,
24
28
  tableName: duckIdentifierValibotSchema
@@ -7,7 +7,7 @@ declare function assertValidSchemaName(schemaName: string): asserts schemaName i
7
7
  declare function assertValidTableName(tableName: string): asserts tableName is DuckTableName;
8
8
  //#endregion
9
9
  //#region src/validation/zod/duck-dsn-zod-schema.d.ts
10
- declare const duckDsnZodSchema: z.ZodPipe<z.ZodString, z.ZodPipe<z.ZodTransform<{
10
+ declare const duckDsnZodSchema: z.ZodPipe<z.ZodPipe<z.ZodString, z.ZodTransform<{
11
11
  type: "memory";
12
12
  alias: string;
13
13
  options?: {
@@ -34,7 +34,7 @@ declare const duckDsnZodSchema: z.ZodPipe<z.ZodString, z.ZodPipe<z.ZodTransform<
34
34
  encryptionKey?: string | undefined;
35
35
  encryptionCipher?: "CBC" | "CTR" | "GCM" | undefined;
36
36
  } | undefined;
37
- }, string>, z.ZodDiscriminatedUnion<[z.ZodObject<{
37
+ }, string>>, z.ZodDiscriminatedUnion<[z.ZodObject<{
38
38
  type: z.ZodLiteral<"memory">;
39
39
  alias: z.ZodString;
40
40
  options: z.ZodOptional<z.ZodObject<{
@@ -85,7 +85,7 @@ declare const duckDsnZodSchema: z.ZodPipe<z.ZodString, z.ZodPipe<z.ZodTransform<
85
85
  GCM: "GCM";
86
86
  }>>;
87
87
  }, z.core.$strict>>;
88
- }, z.core.$strict>], "type">>>;
88
+ }, z.core.$strict>], "type">>;
89
89
  //#endregion
90
90
  //#region src/validation/zod/duck-validators-zod.d.ts
91
91
  /**
@@ -1,2 +1,2 @@
1
- import { a as assertValidTableName, c as duckValidatorsZod, i as assertValidSchemaName, n as duckDsnZodSchema, o as duckAllConnectionOptionsZodSchema, r as assertValidAliasName, s as duckConnectionParamsZodSchema, t as ensureZodTableSchema } from "../../zod-D87TPB5c.mjs";
1
+ import { a as assertValidTableName, c as duckValidatorsZod, i as assertValidSchemaName, n as duckDsnZodSchema, o as duckAllConnectionOptionsZodSchema, r as assertValidAliasName, s as duckConnectionParamsZodSchema, t as ensureZodTableSchema } from "../../zod-CVF6XJKu.mjs";
2
2
  export { assertValidAliasName, assertValidSchemaName, assertValidTableName, duckAllConnectionOptionsZodSchema, duckConnectionParamsZodSchema, duckDsnZodSchema, duckValidatorsZod, ensureZodTableSchema };
@@ -21,6 +21,10 @@ const duckIdentifierZodSchema = z.string().min(1).max(120).regex(duckIdentifierN
21
21
  * ```
22
22
  */
23
23
  const duckValidatorsZod = {
24
+ /**
25
+ * Validate duckdb objects names like table, alias, and schemas
26
+ * for validity.
27
+ */
24
28
  aliasName: duckIdentifierZodSchema,
25
29
  schemaName: duckIdentifierZodSchema,
26
30
  tableName: duckIdentifierZodSchema
@@ -75,26 +79,24 @@ function assertValidTableName(tableName) {
75
79
  }
76
80
  //#endregion
77
81
  //#region src/validation/zod/duck-dsn-zod-schema.ts
78
- const duckDsnZodSchema = z.string().pipe(z.preprocess((dsn, ctx) => {
82
+ const duckDsnZodSchema = z.string().transform((dsn, ctx) => {
79
83
  const result = parseDsn(dsn);
80
- if (result.success) {
81
- const parsed = result.value;
82
- const { path, ...options } = parsed.params ?? {};
83
- return {
84
- type: parsed.host,
85
- alias: parsed.db,
86
- ...path ? { path } : {},
87
- options: { ...options }
88
- };
89
- } else {
90
- ctx.issues.push({
84
+ if (!result.success) {
85
+ ctx.addIssue({
91
86
  code: "custom",
92
- message: result.message,
93
- input: dsn
87
+ message: result.message
94
88
  });
95
89
  return z.NEVER;
96
90
  }
97
- }, duckConnectionParamsZodSchema));
91
+ const parsed = result.value;
92
+ const { path, ...options } = parsed.params ?? {};
93
+ return {
94
+ type: parsed.host,
95
+ alias: parsed.db,
96
+ ...path === void 0 ? {} : { path },
97
+ options: { ...options }
98
+ };
99
+ }).pipe(duckConnectionParamsZodSchema);
98
100
  //#endregion
99
101
  //#region src/validation/zod/ensure-zod-table-schema.ts
100
102
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowblade/sqlduck",
3
- "version": "0.17.2",
3
+ "version": "0.17.3",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -59,14 +59,14 @@
59
59
  "@flowblade/core": "^0.2.28",
60
60
  "@flowblade/source-duckdb": "^0.20.5",
61
61
  "@flowblade/sql-tag": "^0.3.3",
62
- "@httpx/assert": "^0.16.9",
63
- "@httpx/dsn-parser": "^1.9.9",
62
+ "@httpx/assert": "^0.17.0",
63
+ "@httpx/dsn-parser": "^1.9.10",
64
64
  "@httpx/plain-object": "^2.1.9",
65
- "@logtape/logtape": "^2.0.5",
65
+ "@logtape/logtape": "^2.0.6",
66
66
  "@standard-schema/spec": "^1.1.0",
67
67
  "is-safe-filename": "0.1.1",
68
- "p-queue": "9.1.2",
69
- "zod": "^4.3.6"
68
+ "p-queue": "9.2.0",
69
+ "zod": "^4.4.2"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "@duckdb/node-api": "^1.5.2-r.1",
@@ -78,34 +78,34 @@
78
78
  }
79
79
  },
80
80
  "devDependencies": {
81
- "@belgattitude/eslint-config-bases": "8.13.0",
82
- "@dotenvx/dotenvx": "1.61.0",
81
+ "@belgattitude/eslint-config-bases": "8.14.0",
82
+ "@dotenvx/dotenvx": "1.64.0",
83
83
  "@duckdb/node-api": "1.5.2-r.1",
84
84
  "@faker-js/faker": "10.4.0",
85
85
  "@flowblade/source-kysely": "^1.3.3",
86
- "@httpx/assert": "0.16.9",
86
+ "@httpx/assert": "0.17.0",
87
87
  "@mitata/counters": "0.0.8",
88
88
  "@size-limit/esbuild": "12.1.0",
89
89
  "@size-limit/file": "12.1.0",
90
90
  "@testcontainers/mssqlserver": "11.14.0",
91
91
  "@total-typescript/ts-reset": "0.6.1",
92
92
  "@types/node": "25.6.0",
93
- "@typescript-eslint/eslint-plugin": "8.58.2",
94
- "@typescript-eslint/parser": "8.58.2",
95
- "@typescript/native-preview": "7.0.0-dev.20260415.1",
96
- "@vitest/coverage-v8": "4.1.4",
97
- "@vitest/ui": "4.1.4",
93
+ "@typescript-eslint/eslint-plugin": "8.59.1",
94
+ "@typescript-eslint/parser": "8.59.1",
95
+ "@typescript/native-preview": "7.0.0-dev.20260501.1",
96
+ "@vitest/coverage-v8": "4.1.5",
97
+ "@vitest/ui": "4.1.5",
98
98
  "ansis": "4.2.0",
99
99
  "browserslist-to-esbuild": "2.1.1",
100
100
  "core-js": "3.49.0",
101
101
  "cross-env": "10.1.0",
102
102
  "es-check": "9.6.4",
103
- "es-toolkit": "1.45.1",
103
+ "es-toolkit": "1.46.1",
104
104
  "esbuild": "0.28.0",
105
105
  "eslint": "8.57.1",
106
106
  "execa": "9.6.1",
107
107
  "is-in-ci": "2.0.0",
108
- "kysely": "0.28.16",
108
+ "kysely": "0.28.17",
109
109
  "mitata": "1.0.34",
110
110
  "npm-run-all2": "8.0.4",
111
111
  "prettier": "3.8.3",
@@ -117,13 +117,13 @@
117
117
  "tarn": "3.0.2",
118
118
  "tedious": "19.2.1",
119
119
  "testcontainers": "11.14.0",
120
- "tsdown": "0.21.9",
120
+ "tsdown": "0.21.10",
121
121
  "tsx": "4.21.0",
122
122
  "typedoc": "0.28.19",
123
123
  "typedoc-plugin-markdown": "4.11.0",
124
- "typescript": "6.0.2",
124
+ "typescript": "6.0.3",
125
125
  "valibot": "1.3.1",
126
- "vitest": "4.1.4"
126
+ "vitest": "4.1.5"
127
127
  },
128
128
  "files": [
129
129
  "dist"