@flowblade/sqlduck 0.14.0 → 0.16.0

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
@@ -131,32 +131,32 @@ const queryResult = await dbDuckDbMemoryConn.query<{
131
131
  ### Node 24
132
132
 
133
133
  ```
134
- RUN v4.1.1 /home/sebastien/github/flowblade/packages/sqlduck
134
+ RUN v4.1.4 /home/sebastien/github/flowblade/packages/sqlduck
135
135
 
136
136
 
137
- ✓ bench/appender.bench.ts > appender benches 4157ms
138
- name hz min max mean p75 p99 p995 p999 rme samples
139
- · duckdb appender memory, count: 100000, chunk size 2048 2.6950 357.08 385.05 371.06 385.05 385.05 385.05 385.05 ±47.90% 2
140
- · duckdb appender file, count: 100000, chunk size 2048 1.4218 703.35 703.35 703.35 703.35 703.35 703.35 703.35 ±0.00% 1
141
- · duckdb appender, count: 100000, chunk size 1024 2.5157 391.12 403.89 397.50 403.89 403.89 403.89 403.89 ±20.41% 2
137
+ ✓ bench/appender.bench.ts > appender benches 3412ms
138
+ name hz min max mean p75 p99 p995 p999 rme samples
139
+ · duckdb appender memory, count: 100000, chunk size 2048 2.8872 295.84 396.87 346.35 396.87 396.87 396.87 396.87 ±185.36% 2
140
+ · duckdb appender file, count: 100000, chunk size 2048 1.7908 558.40 558.40 558.40 558.40 558.40 558.40 558.40 ±0.00% 1
141
+ · duckdb appender, count: 100000, chunk size 1024 1.9967 500.82 500.82 500.82 500.82 500.82 500.82 500.82 ±0.00% 1
142
142
 
143
- ✓ bench/stream.bench.ts > Bench stream 2809ms
144
- name hz min max mean p75 p99 p995 p999 rme samples
145
- · rowToColumnsChunk with chunkSize 2048 (count: 100000) 9.2627 87.7271 151.56 107.96 116.92 151.56 151.56 151.56 ±15.98% 10
146
- · mapFakeRowStream with chunkSize 2048 (count: 100000) 7.1479 125.04 168.13 139.90 152.97 168.13 168.13 168.13 ±7.78% 10
143
+ ✓ bench/stream.bench.ts > Bench stream 2140ms
144
+ name hz min max mean p75 p99 p995 p999 rme samples
145
+ · rowToColumnsChunk with chunkSize 2048 (count: 100000) 11.8099 63.0430 172.82 84.6748 81.4757 172.82 172.82 172.82 ±27.12% 10
146
+ · mapFakeRowStream with chunkSize 2048 (count: 100000) 10.0442 79.5805 125.81 99.5603 112.35 125.81 125.81 125.81 ±12.04% 10
147
147
 
148
- ✓ bench/table-create.bench.ts > Bench getTableCreateFromZod 614ms
148
+ ✓ bench/table-create.bench.ts > Bench getTableCreateFromZod 617ms
149
149
  name hz min max mean p75 p99 p995 p999 rme samples
150
- · getTableCreateFromZod 18,899.24 0.0334 5.3351 0.0529 0.0546 0.1943 0.3087 0.7214 ±2.72% 9450
150
+ · getTableCreateFromZod 27,583.03 0.0226 2.7818 0.0363 0.0403 0.1185 0.1583 0.4321 ±1.66% 13792
151
151
 
152
152
  BENCH Summary
153
153
 
154
154
  duckdb appender memory, count: 100000, chunk size 2048 - bench/appender.bench.ts > appender benches
155
- 1.07x faster than duckdb appender, count: 100000, chunk size 1024
156
- 1.90x faster than duckdb appender file, count: 100000, chunk size 2048
155
+ 1.45x faster than duckdb appender, count: 100000, chunk size 1024
156
+ 1.61x faster than duckdb appender file, count: 100000, chunk size 2048
157
157
 
158
158
  rowToColumnsChunk with chunkSize 2048 (count: 100000) - bench/stream.bench.ts > Bench stream
159
- 1.30x faster than mapFakeRowStream with chunkSize 2048 (count: 100000)
159
+ 1.18x faster than mapFakeRowStream with chunkSize 2048 (count: 100000)
160
160
 
161
161
  getTableCreateFromZod - bench/table-create.bench.ts > Bench getTableCreateFromZod
162
162
  ```
@@ -164,34 +164,34 @@ const queryResult = await dbDuckDbMemoryConn.query<{
164
164
  ### Bun 1.3.11
165
165
 
166
166
  ```
167
- RUN v4.1.1 /home/sebastien/github/flowblade/packages/sqlduck
167
+ RUN v4.1.4 /home/sebastien/github/flowblade/packages/sqlduck
168
168
 
169
169
 
170
- ✓ bench/appender.bench.ts > appender benches 4159ms
170
+ ✓ bench/appender.bench.ts > appender benches 3357ms
171
171
  name hz min max mean p75 p99 p995 p999 rme samples
172
- · duckdb appender memory, count: 100000, chunk size 2048 2.6465 375.34 380.38 377.86 380.38 380.38 380.38 380.38 ±8.48% 2
173
- · duckdb appender file, count: 100000, chunk size 2048 1.5016 665.98 665.98 665.98 665.98 665.98 665.98 665.98 ±0.00% 1
174
- · duckdb appender, count: 100000, chunk size 1024 2.2828 413.11 463.01 438.06 463.01 463.01 463.01 463.01 ±72.39% 2
172
+ · duckdb appender memory, count: 100000, chunk size 2048 2.9741 315.71 356.77 336.24 356.77 356.77 356.77 356.77 ±77.59% 2
173
+ · duckdb appender file, count: 100000, chunk size 2048 1.8953 527.62 527.62 527.62 527.62 527.62 527.62 527.62 ±0.00% 1
174
+ · duckdb appender, count: 100000, chunk size 1024 1.7803 561.70 561.70 561.70 561.70 561.70 561.70 561.70 ±0.00% 1
175
175
 
176
- ✓ bench/stream.bench.ts > Bench stream 2690ms
177
- name hz min max mean p75 p99 p995 p999 rme samples
178
- · rowToColumnsChunk with chunkSize 2048 (count: 100000) 9.5675 95.6610 114.11 104.52 107.75 114.11 114.11 114.11 ±3.46% 10
179
- · mapFakeRowStream with chunkSize 2048 (count: 100000) 7.6895 117.83 138.26 130.05 137.51 138.26 138.26 138.26 ±4.05% 10
176
+ ✓ bench/stream.bench.ts > Bench stream 2058ms
177
+ name hz min max mean p75 p99 p995 p999 rme samples
178
+ · rowToColumnsChunk with chunkSize 2048 (count: 100000) 12.0130 60.7081 111.32 83.2432 99.7116 111.32 111.32 111.32 ±14.15% 10
179
+ · mapFakeRowStream with chunkSize 2048 (count: 100000) 10.9710 76.4253 145.14 91.1493 91.1424 145.14 145.14 145.14 ±16.04% 10
180
180
 
181
- ✓ bench/table-create.bench.ts > Bench getTableCreateFromZod 629ms
181
+ ✓ bench/table-create.bench.ts > Bench getTableCreateFromZod 621ms
182
182
  name hz min max mean p75 p99 p995 p999 rme samples
183
- · getTableCreateFromZod 18,892.06 0.0281 7.5844 0.0529 0.0516 0.1893 0.2477 3.2823 ±6.26% 9447
183
+ · getTableCreateFromZod 27,472.91 0.0185 4.6226 0.0364 0.0369 0.1137 0.1476 1.9138 ±5.20% 13737
184
184
 
185
185
  BENCH Summary
186
186
 
187
187
  rowToColumnsChunk with chunkSize 2048 (count: 100000) - bench/stream.bench.ts > Bench stream
188
- 1.24x faster than mapFakeRowStream with chunkSize 2048 (count: 100000)
188
+ 1.09x faster than mapFakeRowStream with chunkSize 2048 (count: 100000)
189
189
 
190
190
  getTableCreateFromZod - bench/table-create.bench.ts > Bench getTableCreateFromZod
191
191
 
192
192
  duckdb appender memory, count: 100000, chunk size 2048 - bench/appender.bench.ts > appender benches
193
- 1.16x faster than duckdb appender, count: 100000, chunk size 1024
194
- 1.76x faster than duckdb appender file, count: 100000, chunk size 2048
193
+ 1.57x faster than duckdb appender file, count: 100000, chunk size 2048
194
+ 1.67x faster than duckdb appender, count: 100000, chunk size 1024
195
195
 
196
196
  ```
197
197
 
@@ -3,12 +3,20 @@ const duckIdentifierNameRegex = /^[a-z_]\w*$/i;
3
3
  const duckStorageVersionRegexp = /^v?\d{1,4}\.\d{1,4}\.\d{1,4}$/;
4
4
  //#endregion
5
5
  //#region src/validation/core/duck-connections-options.ts
6
- const duckConnectionsOptions = { types: [
7
- "DUCKDB",
8
- "SQLITE",
9
- "MYSQL",
10
- "PostgreSQL"
11
- ] };
6
+ const duckConnectionsOptions = {
7
+ types: [
8
+ "DUCKDB",
9
+ "SQLITE",
10
+ "MYSQL",
11
+ "PostgreSQL"
12
+ ],
13
+ accessModes: ["READ_ONLY", "READ_WRITE"],
14
+ encryptionCiphers: [
15
+ "CBC",
16
+ "CTR",
17
+ "GCM"
18
+ ]
19
+ };
12
20
  //#endregion
13
21
  //#region src/validation/core/duck-reserved-keywords.ts
14
22
  /**
package/dist/index.d.mts CHANGED
@@ -81,7 +81,7 @@ declare class Table {
81
81
  }
82
82
  //#endregion
83
83
  //#region src/table/table-schema-zod.type.d.ts
84
- type ZodSchemaSupportedTypes = z.ZodString | z.ZodNumber | z.ZodInt | z.ZodInt32 | z.ZodUInt32 | z.ZodBigInt | z.ZodBoolean | z.ZodDate | z.ZodISODateTime | z.ZodISOTime | z.ZodISODate | z.ZodEmail | z.ZodURL | z.ZodUUID | z.ZodCUID | z.ZodCUID2 | z.ZodULID;
84
+ type ZodSchemaSupportedTypes = z.ZodString | z.ZodNumber | z.ZodInt | z.ZodInt32 | z.ZodUInt32 | z.ZodBigInt | z.ZodBoolean | z.ZodDate | z.ZodISODateTime | z.ZodISOTime | z.ZodISODate | z.ZodEmail | z.ZodURL | z.ZodUUID | z.ZodCUID | z.ZodCUID2 | z.ZodULID | z.ZodEnum;
85
85
  type TableSchemaZod = z.ZodObject<Record<string, ZodSchemaSupportedTypes | z.ZodNullable<ZodSchemaSupportedTypes> | z.ZodCodec | z.ZodNullable<z.ZodCodec>>>;
86
86
  //#endregion
87
87
  //#region src/table/get-table-create-from-zod.d.ts
@@ -283,6 +283,15 @@ declare class DuckDatabaseManager {
283
283
  analyze: () => Promise<boolean>;
284
284
  checkpoint: (dbAlias: string) => Promise<boolean>;
285
285
  vacuum: () => Promise<boolean>;
286
+ /**
287
+ * Helper to create an initial database file.
288
+ */
289
+ createDatabaseFile: (params: {
290
+ path: string;
291
+ createDirectory?: boolean;
292
+ }) => Promise<{
293
+ status: "exists" | "created";
294
+ }>;
286
295
  }
287
296
  //#endregion
288
297
  //#region src/config/flowblade-logtape-sqlduck.config.d.ts
package/dist/index.mjs CHANGED
@@ -1,7 +1,9 @@
1
- import { t as duckReservedKeywords } from "./duck-reserved-keywords-CUmaTbrD.mjs";
2
- import { n as assertValidAliasName, o as duckConnectionParamsZodSchema, s as duckValidatorsZod } from "./zod-BRUUIdGW.mjs";
3
- import { BIGINT, BOOLEAN, DOUBLE, DuckDBDataChunk, DuckDBTimestampValue, FLOAT, HUGEINT, INTEGER, SMALLINT, TIMESTAMP, TINYINT, UBIGINT, UHUGEINT, UINTEGER, USMALLINT, UTINYINT, UUID, VARCHAR } from "@duckdb/node-api";
1
+ import { t as duckReservedKeywords } from "./duck-reserved-keywords-B8XUjnaY.mjs";
2
+ import { n as assertValidAliasName, o as duckConnectionParamsZodSchema, s as duckValidatorsZod } from "./zod-CuPjTLv8.mjs";
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
+ import fs from "node:fs";
6
+ import { basename, dirname } from "node:path";
5
7
  import * as z from "zod";
6
8
  import { assertNever } from "@httpx/assert";
7
9
  import { isPlainObject } from "@httpx/plain-object";
@@ -122,12 +124,191 @@ const createOnDataAppendedCollector = () => {
122
124
  };
123
125
  };
124
126
  //#endregion
127
+ //#region src/converter/duck-value-converter.ts
128
+ const stringTimestampRegexp = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d{3,6})?Z?$/i;
129
+ const dateRegexp = /^\d{4}-\d{2}-\d{2}$/;
130
+ const createDuckValueConverterTypeError = (params) => {
131
+ let serializableValue;
132
+ try {
133
+ serializableValue = JSON.stringify(params.value);
134
+ } catch {
135
+ serializableValue = "<unserializable>";
136
+ }
137
+ return /* @__PURE__ */ new TypeError(`[DuckValueConverter.${params.method}]: Unsupported type ${typeof params.value} with value ${serializableValue}`);
138
+ };
139
+ var DuckValueConverter = class {
140
+ toUUID = (value) => {
141
+ if (typeof value === "bigint") return value;
142
+ else if (typeof value === "string") return BigInt("0x" + value.replaceAll("-", ""));
143
+ if (value === void 0 || value === null) return null;
144
+ throw createDuckValueConverterTypeError({
145
+ method: "toUUID",
146
+ value
147
+ });
148
+ };
149
+ toStringEnum = (value) => {
150
+ if (typeof value === "string") return value;
151
+ if (value === void 0 || value === null) return null;
152
+ throw createDuckValueConverterTypeError({
153
+ method: "toStringEnum",
154
+ value
155
+ });
156
+ };
157
+ toBigIntString = (value) => {
158
+ if (typeof value === "string") return value;
159
+ if (typeof value === "number" || typeof value === "bigint") return value.toString(10);
160
+ if (value === void 0 || value === null) return null;
161
+ throw createDuckValueConverterTypeError({
162
+ method: "toBigIntString",
163
+ value
164
+ });
165
+ };
166
+ toTimestampMs = (value) => {
167
+ if (value instanceof Date) return new DuckDBTimestampMillisecondsValue(BigInt(value.getTime()));
168
+ if (value === void 0 || value === null) return null;
169
+ if (typeof value === "string") {
170
+ const len = value.length;
171
+ if (len > 18 && len < 31 && stringTimestampRegexp.test(value)) {
172
+ const date = /* @__PURE__ */ new Date(value + (value.endsWith("Z") ? "" : "Z"));
173
+ return new DuckDBTimestampMillisecondsValue(BigInt(date.getTime()));
174
+ }
175
+ if (len === 10 && dateRegexp.test(value)) {
176
+ const date = /* @__PURE__ */ new Date(value + "T00:00:00Z");
177
+ return new DuckDBTimestampMillisecondsValue(BigInt(date.getTime()));
178
+ }
179
+ }
180
+ if (typeof value === "bigint") return new DuckDBTimestampMillisecondsValue(value);
181
+ if (typeof value === "number") return new DuckDBTimestampMillisecondsValue(BigInt(value));
182
+ throw createDuckValueConverterTypeError({
183
+ method: "toTimestampMs",
184
+ value
185
+ });
186
+ };
187
+ };
188
+ //#endregion
189
+ //#region src/converter/create-duck-column-converters.ts
190
+ const createDuckColumnConverters = (duckTypes) => {
191
+ const convMap = /* @__PURE__ */ new Map();
192
+ const converter = new DuckValueConverter();
193
+ for (const [key, duckType] of Object.entries(duckTypes)) {
194
+ let conv;
195
+ const duckTypeId = duckType.typeId;
196
+ switch (duckTypeId) {
197
+ case DuckDBTypeId.TIMESTAMP_MS:
198
+ conv = converter.toTimestampMs;
199
+ break;
200
+ case DuckDBTypeId.BIGINT:
201
+ case DuckDBTypeId.UBIGINT:
202
+ case DuckDBTypeId.HUGEINT:
203
+ case DuckDBTypeId.UHUGEINT:
204
+ case DuckDBTypeId.INTEGER:
205
+ case DuckDBTypeId.UINTEGER:
206
+ case DuckDBTypeId.BIGNUM:
207
+ conv = converter.toBigIntString;
208
+ break;
209
+ case DuckDBTypeId.ENUM:
210
+ conv = converter.toStringEnum;
211
+ break;
212
+ case DuckDBTypeId.UUID:
213
+ conv = converter.toUUID;
214
+ break;
215
+ case DuckDBTypeId.BIT:
216
+ case DuckDBTypeId.BOOLEAN:
217
+ case DuckDBTypeId.TINYINT:
218
+ case DuckDBTypeId.USMALLINT:
219
+ case DuckDBTypeId.UTINYINT:
220
+ case DuckDBTypeId.VARCHAR:
221
+ case DuckDBTypeId.SMALLINT:
222
+ conv = false;
223
+ break;
224
+ default: throw new Error(`Unsupported duck type ${duckTypeId} / ${duckType.toString()} for column '${key}'`);
225
+ }
226
+ if (conv !== false) convMap.set(key, conv);
227
+ }
228
+ return convMap;
229
+ };
230
+ //#endregion
125
231
  //#region src/config/flowblade-logtape-sqlduck.config.ts
126
232
  const flowbladeLogtapeSqlduckConfig = { categories: ["flowblade", "sqlduck"] };
127
233
  //#endregion
128
234
  //#region src/logger/sqlduck-default-logtape-logger.ts
129
235
  const sqlduckDefaultLogtapeLogger = getLogger(flowbladeLogtapeSqlduckConfig.categories);
130
236
  //#endregion
237
+ //#region src/filesystem/file-system-utils.ts
238
+ var FileSystemUtils = class {
239
+ #logger;
240
+ constructor(params) {
241
+ this.#logger = params?.logger ?? sqlduckDefaultLogtapeLogger.with({ source: "FileSystemUtils" });
242
+ }
243
+ /**
244
+ * Create a directory recursively if it doesn't exist
245
+ *
246
+ * @throws Error if it can't be created
247
+ */
248
+ createDirectory = (path) => {
249
+ try {
250
+ fs.mkdirSync(path, { recursive: true });
251
+ } catch (err) {
252
+ if (err.code !== "EEXIST") throw err;
253
+ }
254
+ };
255
+ /**
256
+ * Create a directory recursively if it doesn't exist and ensure it's writable
257
+ */
258
+ createAndEnsureWritableDirectory = (label, path) => {
259
+ if (path === void 0) return;
260
+ if (!fs.existsSync(path)) try {
261
+ this.createDirectory(path);
262
+ } catch (e) {
263
+ throw new Error(`Failed to create ${label} '${path}' - ${e?.message ?? ""}`);
264
+ }
265
+ if (!fs.statSync(path).isDirectory()) throw new Error(`${label} '${path}' must be a directory`);
266
+ try {
267
+ fs.accessSync(path, fs.constants.W_OK);
268
+ } catch {
269
+ throw new Error(`${label} '${path}' must be writable`);
270
+ }
271
+ };
272
+ /**
273
+ * Check if a path is a regular file and exists
274
+ */
275
+ isFile = (path) => {
276
+ try {
277
+ return fs.statSync(path).isFile();
278
+ } catch {
279
+ return false;
280
+ }
281
+ };
282
+ /**
283
+ * Check if a path is a directory and exists
284
+ */
285
+ isDirectory = (path) => {
286
+ try {
287
+ return fs.statSync(path).isDirectory();
288
+ } catch {
289
+ return false;
290
+ }
291
+ };
292
+ parsePath = (path) => {
293
+ const dir = dirname(path);
294
+ if (dir.trim() === "") throw new Error(`Invalid path, missing directory '${path}'`);
295
+ const base = basename(path);
296
+ if (base.trim() === "") throw new Error(`Invalid path, missing filename '${path}'`);
297
+ return {
298
+ directory: dir,
299
+ filename: base
300
+ };
301
+ };
302
+ removeFileIfExists = (path) => {
303
+ try {
304
+ fs.rmSync(path);
305
+ return true;
306
+ } catch {
307
+ return false;
308
+ }
309
+ };
310
+ };
311
+ //#endregion
131
312
  //#region src/objects/database.ts
132
313
  var Database = class {
133
314
  #params;
@@ -207,6 +388,7 @@ var DuckDatabaseAttachCommand = class {
207
388
  var DuckDatabaseManager = class {
208
389
  #conn;
209
390
  #logger;
391
+ #fs;
210
392
  constructor(conn, params) {
211
393
  this.#conn = conn;
212
394
  this.#logger = params?.logger ?? sqlduckDefaultLogtapeLogger.with({ source: "DuckDatabaseManager" });
@@ -229,7 +411,12 @@ var DuckDatabaseManager = class {
229
411
  attach = async (dbParams, options) => {
230
412
  const params = duckConnectionParamsZodSchema.parse(dbParams);
231
413
  const rawSql = new DuckDatabaseAttachCommand(params, options).getRawSql();
232
- await this.#executeRawSqlCommand(`attach(${params.alias})`, rawSql);
414
+ const { behaviour } = options ?? {};
415
+ await this.#executeRawSqlCommand([
416
+ `attach(${params.alias}`,
417
+ behaviour ?? null,
418
+ ")"
419
+ ].filter(Boolean).join(","), rawSql);
233
420
  return new Database({ alias: params.alias });
234
421
  };
235
422
  attachOrReplace = async (dbParams) => {
@@ -272,6 +459,32 @@ var DuckDatabaseManager = class {
272
459
  await this.#executeRawSqlCommand("vacuum()", "VACUUM");
273
460
  return true;
274
461
  };
462
+ /**
463
+ * Helper to create an initial database file.
464
+ */
465
+ createDatabaseFile = async (params) => {
466
+ const startTime = Date.now();
467
+ const { path, createDirectory = true } = params;
468
+ const fs = this.#getFs();
469
+ if (fs.isFile(path)) return { status: "exists" };
470
+ if (createDirectory) {
471
+ const { directory } = fs.parsePath(path);
472
+ fs.createAndEnsureWritableDirectory("database file directory", directory);
473
+ }
474
+ const instanceCache = new DuckDBInstanceCache();
475
+ try {
476
+ (await (await instanceCache.getOrCreateInstance(path)).connect()).closeSync();
477
+ const timeMs = Math.round(Date.now() - startTime);
478
+ this.#logger.info(`DuckDatabaseManager.createDatabaseFile('${path}') in ${timeMs}ms`, {
479
+ timeMs,
480
+ path
481
+ });
482
+ } catch (e) {
483
+ this.#logger.error(`DuckDatabaseManager.createDatabaseFile('${path}') failed - ${e?.message ?? ""}`, { path });
484
+ throw e;
485
+ }
486
+ return { status: "created" };
487
+ };
275
488
  #executeRawSqlCommand = async (name, rawSql) => {
276
489
  const startTime = Date.now();
277
490
  try {
@@ -291,6 +504,10 @@ var DuckDatabaseManager = class {
291
504
  throw new Error(msg, { cause: e });
292
505
  }
293
506
  };
507
+ #getFs = () => {
508
+ if (this.#fs === void 0) this.#fs = new FileSystemUtils({ logger: this.#logger });
509
+ return this.#fs;
510
+ };
294
511
  };
295
512
  //#endregion
296
513
  //#region src/table/get-duckdb-number-column-type.ts
@@ -329,7 +546,10 @@ const createOptions = {
329
546
  const duckDbTypesMap = new Map([
330
547
  ["VARCHAR", VARCHAR],
331
548
  ["BIGINT", BIGINT],
549
+ ["UBIGINT", UBIGINT],
550
+ ["HUGEINT", HUGEINT],
332
551
  ["TIMESTAMP", TIMESTAMP],
552
+ ["TIMESTAMP_MS", TIMESTAMP_MS],
333
553
  ["UUID", UUID],
334
554
  ["BOOLEAN", BOOLEAN],
335
555
  ["INTEGER", INTEGER],
@@ -353,9 +573,10 @@ const getTableCreateFromZod = (params) => {
353
573
  if (duckdbType !== void 0 && duckDbTypesMap.has(duckdbType)) c.duckdbType = duckDbTypesMap.get(duckdbType);
354
574
  else switch (type) {
355
575
  case "string":
356
- switch (format) {
576
+ if (Array.isArray(def.enum)) c.duckdbType = ENUM(def.enum);
577
+ else switch (format) {
357
578
  case "date-time":
358
- c.duckdbType = TIMESTAMP;
579
+ c.duckdbType = TIMESTAMP_MS;
359
580
  break;
360
581
  case "int64":
361
582
  c.duckdbType = BIGINT;
@@ -428,11 +649,6 @@ const createTableFromZod = async (params) => {
428
649
  };
429
650
  //#endregion
430
651
  //#region src/utils/rows-to-columns-chunks.ts
431
- const toDuckValue = (value) => {
432
- if (value instanceof Date) return new DuckDBTimestampValue(BigInt(value.getTime() * 1e3));
433
- if (typeof value === "bigint") return value.toString(10);
434
- return value === void 0 ? null : value;
435
- };
436
652
  /**
437
653
  * Similar to `rowsToColumns` but yields results in chunks to avoid buffering
438
654
  * the entire dataset in memory. Each yielded item is a columns array for up to
@@ -443,14 +659,17 @@ const toDuckValue = (value) => {
443
659
  * yields: [[['1','2'], ['A','B']], [['3'], ['C']]]
444
660
  */
445
661
  async function* rowsToColumnsChunks(params) {
446
- const { rows, chunkSize } = params;
662
+ const { rows, chunkSize, transformers } = params;
447
663
  if (!Number.isSafeInteger(chunkSize) || chunkSize <= 0) throw new Error(`chunkSize must be a positive integer, got ${chunkSize}`);
448
664
  const first = await rows.next();
449
665
  if (first.done) return;
450
666
  const keys = Object.keys(first.value);
451
667
  let columns = keys.map(() => []);
452
668
  let rowsInChunk = 0;
453
- keys.forEach((k, i) => columns[i].push(toDuckValue(first.value[k])));
669
+ keys.forEach((k, i) => {
670
+ const fn = transformers?.get(k);
671
+ columns[i].push(fn === void 0 ? first.value[k] : fn(first.value[k]));
672
+ });
454
673
  rowsInChunk++;
455
674
  if (rowsInChunk >= chunkSize) {
456
675
  yield columns;
@@ -458,7 +677,10 @@ async function* rowsToColumnsChunks(params) {
458
677
  rowsInChunk = 0;
459
678
  }
460
679
  for await (const row of rows) {
461
- keys.forEach((k, i) => columns[i].push(toDuckValue(row[k])));
680
+ keys.forEach((k, i) => {
681
+ const fn = transformers?.get(k);
682
+ columns[i].push(fn === void 0 ? row[k] : fn(row[k]));
683
+ });
462
684
  rowsInChunk++;
463
685
  if (rowsInChunk >= chunkSize) {
464
686
  yield columns;
@@ -530,11 +752,15 @@ var SqlDuck = class {
530
752
  });
531
753
  const appender = await this.#conn.createAppender(table.tableName, table.schemaName, table.databaseName);
532
754
  const chunkTypes = Array.from(columnTypes.values());
755
+ const transformers = createDuckColumnConverters(Object.fromEntries(Array.from(columnTypes).map(([key, duckType]) => {
756
+ return [key, duckType];
757
+ })));
533
758
  let totalRows = 0;
534
759
  const dataAppendedCollector = createOnDataAppendedCollector();
535
760
  const columnStream = rowsToColumnsChunks({
536
761
  rows: rowStream,
537
- chunkSize
762
+ chunkSize,
763
+ transformers
538
764
  });
539
765
  let appendedChunkCount = 0;
540
766
  try {
@@ -2,42 +2,42 @@ import * as v from "valibot";
2
2
 
3
3
  //#region src/validation/valibot/duck-connection-params-valibot-schema.d.ts
4
4
  declare const duckAllConnectionOptionsValibotSchema: v.ObjectSchema<{
5
- readonly accessMode: v.OptionalSchema<v.PicklistSchema<["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
5
+ readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
6
6
  readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
7
7
  readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
8
8
  readonly blockSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 16384, undefined>, v.MaxValueAction<number, 262144, undefined>]>, undefined>;
9
9
  readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
10
10
  readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
11
11
  readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
12
- readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<["CBC", "CTR", "GCM"], undefined>, undefined>;
12
+ readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
13
13
  }, undefined>;
14
14
  type DuckAllConnectionOptionsValibotSchema = v.InferOutput<typeof duckAllConnectionOptionsValibotSchema>;
15
15
  declare const duckConnectionParamsValibotSchema: v.VariantSchema<"type", [v.ObjectSchema<{
16
16
  readonly type: v.LiteralSchema<"memory", undefined>;
17
17
  readonly alias: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>, v.RegexAction<string, "Identifier must start with a letter or underscore, and contain only letters, numbers and underscores">, v.CheckAction<string, "Identifier value is a DuckDB reserved keyword and cannot be used as an identifier">]>;
18
18
  readonly options: v.OptionalSchema<v.ObjectSchema<{
19
- readonly accessMode: v.OptionalSchema<v.PicklistSchema<["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
19
+ readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
20
20
  readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
21
21
  readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
22
22
  readonly blockSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 16384, undefined>, v.MaxValueAction<number, 262144, undefined>]>, undefined>;
23
23
  readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
24
24
  readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
25
25
  readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
26
- readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<["CBC", "CTR", "GCM"], undefined>, undefined>;
26
+ readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
27
27
  }, undefined>, undefined>;
28
28
  }, undefined>, v.ObjectSchema<{
29
29
  readonly type: v.LiteralSchema<"filesystem", undefined>;
30
30
  readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid database filename - it must be a safe filename (no path traversal, no absolute paths, no reserved names, etc.)">, v.CheckAction<string, "Invalid database pathname - it must be an absolute path with no traversal">]>;
31
31
  readonly alias: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>, v.RegexAction<string, "Identifier must start with a letter or underscore, and contain only letters, numbers and underscores">, v.CheckAction<string, "Identifier value is a DuckDB reserved keyword and cannot be used as an identifier">]>;
32
32
  readonly options: v.OptionalSchema<v.ObjectSchema<{
33
- readonly accessMode: v.OptionalSchema<v.PicklistSchema<["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
33
+ readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
34
34
  readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
35
35
  readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
36
36
  readonly blockSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 16384, undefined>, v.MaxValueAction<number, 262144, undefined>]>, undefined>;
37
37
  readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
38
38
  readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
39
39
  readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
40
- readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<["CBC", "CTR", "GCM"], undefined>, undefined>;
40
+ readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
41
41
  }, undefined>, undefined>;
42
42
  }, undefined>], undefined>;
43
43
  //#endregion
@@ -73,28 +73,28 @@ declare const duckDsnValibotSchema: v.SchemaWithPipe<readonly [v.StringSchema<un
73
73
  readonly type: v.LiteralSchema<"memory", undefined>;
74
74
  readonly alias: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>, v.RegexAction<string, "Identifier must start with a letter or underscore, and contain only letters, numbers and underscores">, v.CheckAction<string, "Identifier value is a DuckDB reserved keyword and cannot be used as an identifier">]>;
75
75
  readonly options: v.OptionalSchema<v.ObjectSchema<{
76
- readonly accessMode: v.OptionalSchema<v.PicklistSchema<["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
76
+ readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
77
77
  readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
78
78
  readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
79
79
  readonly blockSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 16384, undefined>, v.MaxValueAction<number, 262144, undefined>]>, undefined>;
80
80
  readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
81
81
  readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
82
82
  readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
83
- readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<["CBC", "CTR", "GCM"], undefined>, undefined>;
83
+ readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
84
84
  }, undefined>, undefined>;
85
85
  }, undefined>, v.ObjectSchema<{
86
86
  readonly type: v.LiteralSchema<"filesystem", undefined>;
87
87
  readonly path: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid database filename - it must be a safe filename (no path traversal, no absolute paths, no reserved names, etc.)">, v.CheckAction<string, "Invalid database pathname - it must be an absolute path with no traversal">]>;
88
88
  readonly alias: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>, v.MaxLengthAction<string, 120, undefined>, v.RegexAction<string, "Identifier must start with a letter or underscore, and contain only letters, numbers and underscores">, v.CheckAction<string, "Identifier value is a DuckDB reserved keyword and cannot be used as an identifier">]>;
89
89
  readonly options: v.OptionalSchema<v.ObjectSchema<{
90
- readonly accessMode: v.OptionalSchema<v.PicklistSchema<["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
90
+ readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
91
91
  readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
92
92
  readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
93
93
  readonly blockSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 16384, undefined>, v.MaxValueAction<number, 262144, undefined>]>, undefined>;
94
94
  readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
95
95
  readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
96
96
  readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
97
- readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<["CBC", "CTR", "GCM"], undefined>, undefined>;
97
+ readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
98
98
  }, undefined>, undefined>;
99
99
  }, undefined>], undefined>]>;
100
100
  //#endregion
@@ -1,4 +1,4 @@
1
- import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "../../duck-reserved-keywords-CUmaTbrD.mjs";
1
+ import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "../../duck-reserved-keywords-B8XUjnaY.mjs";
2
2
  import isSafeFilename from "is-safe-filename";
3
3
  import { parseDsn, parseDsnOrThrow } from "@httpx/dsn-parser";
4
4
  import * as v from "valibot";
@@ -26,18 +26,14 @@ const duckValidatorsValibot = {
26
26
  //#endregion
27
27
  //#region src/validation/valibot/duck-connection-params-valibot-schema.ts
28
28
  const duckAllConnectionOptionsValibotSchema = v.object({
29
- accessMode: v.optional(v.picklist(["READ_ONLY", "READ_WRITE"])),
29
+ accessMode: v.optional(v.picklist(duckConnectionsOptions.accessModes)),
30
30
  compress: v.optional(v.boolean()),
31
31
  type: v.optional(v.picklist(duckConnectionsOptions.types)),
32
32
  blockSize: v.optional(v.pipe(v.number(), v.integer(), v.minValue(16384), v.maxValue(262144))),
33
33
  rowGroupSize: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1))),
34
34
  storageVersion: v.optional(v.pipe(v.string(), v.startsWith("v"), v.regex(duckStorageVersionRegexp))),
35
35
  encryptionKey: v.optional(v.pipe(v.string(), v.minLength(8))),
36
- encryptionCipher: v.optional(v.picklist([
37
- "CBC",
38
- "CTR",
39
- "GCM"
40
- ]))
36
+ encryptionCipher: v.optional(v.picklist(duckConnectionsOptions.encryptionCiphers))
41
37
  });
42
38
  const duckConnectionParamsValibotSchema = v.variant("type", [v.object({
43
39
  type: v.literal("memory"),
@@ -1,2 +1,2 @@
1
- import { a as duckAllConnectionOptionsZodSchema, i as assertValidTableName, n as assertValidAliasName, o as duckConnectionParamsZodSchema, r as assertValidSchemaName, s as duckValidatorsZod, t as duckDsnZodSchema } from "../../zod-BRUUIdGW.mjs";
1
+ import { a as duckAllConnectionOptionsZodSchema, i as assertValidTableName, n as assertValidAliasName, o as duckConnectionParamsZodSchema, r as assertValidSchemaName, s as duckValidatorsZod, t as duckDsnZodSchema } from "../../zod-CuPjTLv8.mjs";
2
2
  export { assertValidAliasName, assertValidSchemaName, assertValidTableName, duckAllConnectionOptionsZodSchema, duckConnectionParamsZodSchema, duckDsnZodSchema, duckValidatorsZod };
@@ -1,4 +1,4 @@
1
- import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "./duck-reserved-keywords-CUmaTbrD.mjs";
1
+ import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "./duck-reserved-keywords-B8XUjnaY.mjs";
2
2
  import isSafeFilename from "is-safe-filename";
3
3
  import * as z from "zod";
4
4
  import { parseDsn } from "@httpx/dsn-parser";
@@ -28,18 +28,14 @@ const duckValidatorsZod = {
28
28
  //#endregion
29
29
  //#region src/validation/zod/duck-connection-params-zod-schema.ts
30
30
  const duckAllConnectionOptionsZodSchema = z.strictObject({
31
- accessMode: z.optional(z.enum(["READ_ONLY", "READ_WRITE"])),
31
+ accessMode: z.optional(z.enum(duckConnectionsOptions.accessModes)),
32
32
  compress: z.optional(z.boolean()),
33
33
  type: z.optional(z.enum(duckConnectionsOptions.types)),
34
34
  blockSize: z.optional(z.int32().min(16384).max(262144)),
35
35
  rowGroupSize: z.optional(z.int32().positive()),
36
36
  storageVersion: z.optional(z.string().startsWith("v").regex(duckStorageVersionRegexp)),
37
37
  encryptionKey: z.optional(z.string().min(8)),
38
- encryptionCipher: z.optional(z.enum([
39
- "CBC",
40
- "CTR",
41
- "GCM"
42
- ]))
38
+ encryptionCipher: z.optional(z.enum(duckConnectionsOptions.encryptionCiphers))
43
39
  });
44
40
  const duckConnectionParamsZodSchema = z.discriminatedUnion("type", [z.strictObject({
45
41
  type: z.literal("memory"),
@@ -52,7 +48,7 @@ const duckConnectionParamsZodSchema = z.discriminatedUnion("type", [z.strictObje
52
48
  return typeof filename === "string" && isSafeFilename(filename);
53
49
  }, { message: "Invalid database filename - it must be a safe filename (no path traversal, no absolute paths, no reserved names, etc.)" }).refine((path) => {
54
50
  const pathname = "/" + path.replace("\\", "/").split("/").slice(0, -1).filter(Boolean).join("/");
55
- return pathname.length > 0 && pathname.startsWith("/") && pathname.includes("..") === false;
51
+ return pathname.length > 0 && pathname.startsWith("/") && !pathname.includes("..");
56
52
  }, { message: "Invalid database pathname - it must be an absolute path with no traversal" }),
57
53
  alias: duckValidatorsZod.aliasName,
58
54
  options: z.optional(duckAllConnectionOptionsZodSchema)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowblade/sqlduck",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -53,7 +53,7 @@
53
53
  "fix-staged": "lint-staged --allow-empty",
54
54
  "check-dist": "es-check --config=.escheckrc.json",
55
55
  "check-pub": "publint",
56
- "check-size": "size-limit"
56
+ "check-size-disabled": "size-limit"
57
57
  },
58
58
  "dependencies": {
59
59
  "@flowblade/core": "^0.2.26",
@@ -65,7 +65,7 @@
65
65
  "@logtape/logtape": "^2.0.5",
66
66
  "@standard-schema/spec": "^1.1.0",
67
67
  "is-safe-filename": "0.1.1",
68
- "p-queue": "9.1.1",
68
+ "p-queue": "9.1.2",
69
69
  "zod": "^4.3.6"
70
70
  },
71
71
  "peerDependencies": {
@@ -90,11 +90,11 @@
90
90
  "@testcontainers/mssqlserver": "11.13.0",
91
91
  "@total-typescript/ts-reset": "0.6.1",
92
92
  "@types/node": "25.5.2",
93
- "@typescript-eslint/eslint-plugin": "8.58.0",
94
- "@typescript-eslint/parser": "8.58.0",
93
+ "@typescript-eslint/eslint-plugin": "8.58.1",
94
+ "@typescript-eslint/parser": "8.58.1",
95
95
  "@typescript/native-preview": "7.0.0-dev.20260406.1",
96
- "@vitest/coverage-v8": "4.1.2",
97
- "@vitest/ui": "4.1.2",
96
+ "@vitest/coverage-v8": "4.1.4",
97
+ "@vitest/ui": "4.1.4",
98
98
  "ansis": "4.2.0",
99
99
  "browserslist-to-esbuild": "2.1.1",
100
100
  "core-js": "3.49.0",
@@ -123,7 +123,7 @@
123
123
  "typedoc-plugin-markdown": "4.11.0",
124
124
  "typescript": "6.0.2",
125
125
  "valibot": "1.3.1",
126
- "vitest": "4.1.2"
126
+ "vitest": "4.1.4"
127
127
  },
128
128
  "files": [
129
129
  "dist"