@flowblade/sqlduck 0.13.0 → 0.15.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 +1 -1
- package/dist/duck-reserved-keywords-B8XUjnaY.mjs +126 -0
- package/dist/index.d.mts +18 -2
- package/dist/index.mjs +126 -8
- package/dist/{types-DCqYqEsa.d.mts → types-dnhcognF.d.mts} +7 -1
- package/dist/validation/valibot/index.d.mts +127 -0
- package/dist/validation/valibot/index.mjs +69 -0
- package/dist/validation/zod/index.d.mts +87 -12
- package/dist/validation/zod/index.mjs +2 -2
- package/dist/{zod-DcIc8xQC.mjs → zod-CuPjTLv8.mjs} +33 -141
- package/package.json +28 -16
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ import { conn } from "./db.config.ts";
|
|
|
29
29
|
|
|
30
30
|
const dbManager = new DuckDatabaseManager(conn);
|
|
31
31
|
const database = await dbManager.attach({
|
|
32
|
-
type: 'memory', // can be '
|
|
32
|
+
type: 'memory', // can be 'filesystem', ...
|
|
33
33
|
alias: 'mydb',
|
|
34
34
|
options: { COMPRESS: 'false' },
|
|
35
35
|
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
//#region src/validation/core/base-validators.ts
|
|
2
|
+
const duckIdentifierNameRegex = /^[a-z_]\w*$/i;
|
|
3
|
+
const duckStorageVersionRegexp = /^v?\d{1,4}\.\d{1,4}\.\d{1,4}$/;
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/validation/core/duck-connections-options.ts
|
|
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
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/validation/core/duck-reserved-keywords.ts
|
|
22
|
+
/**
|
|
23
|
+
* DuckDB reserved keywords that cannot be used as unquoted identifiers.
|
|
24
|
+
* @see https://duckdb.org/docs/sql/keywords-and-identifiers.html
|
|
25
|
+
*/
|
|
26
|
+
const duckReservedKeywords = [
|
|
27
|
+
"ALL",
|
|
28
|
+
"ANALYSE",
|
|
29
|
+
"ANALYZE",
|
|
30
|
+
"AND",
|
|
31
|
+
"ANY",
|
|
32
|
+
"ARRAY",
|
|
33
|
+
"AS",
|
|
34
|
+
"ASC",
|
|
35
|
+
"ASYMMETRIC",
|
|
36
|
+
"BOTH",
|
|
37
|
+
"CASE",
|
|
38
|
+
"CAST",
|
|
39
|
+
"CHECK",
|
|
40
|
+
"COLLATE",
|
|
41
|
+
"COLUMN",
|
|
42
|
+
"CONSTRAINT",
|
|
43
|
+
"CREATE",
|
|
44
|
+
"CROSS",
|
|
45
|
+
"CURRENT_CATALOG",
|
|
46
|
+
"CURRENT_DATE",
|
|
47
|
+
"CURRENT_ROLE",
|
|
48
|
+
"CURRENT_SCHEMA",
|
|
49
|
+
"CURRENT_TIME",
|
|
50
|
+
"CURRENT_TIMESTAMP",
|
|
51
|
+
"CURRENT_USER",
|
|
52
|
+
"DEFAULT",
|
|
53
|
+
"DEFERRABLE",
|
|
54
|
+
"DESC",
|
|
55
|
+
"DISTINCT",
|
|
56
|
+
"DO",
|
|
57
|
+
"ELSE",
|
|
58
|
+
"END",
|
|
59
|
+
"EXCEPT",
|
|
60
|
+
"EXISTS",
|
|
61
|
+
"EXTRACT",
|
|
62
|
+
"FALSE",
|
|
63
|
+
"FETCH",
|
|
64
|
+
"FOR",
|
|
65
|
+
"FOREIGN",
|
|
66
|
+
"FROM",
|
|
67
|
+
"GRANT",
|
|
68
|
+
"GROUP",
|
|
69
|
+
"HAVING",
|
|
70
|
+
"IF",
|
|
71
|
+
"ILIKE",
|
|
72
|
+
"IN",
|
|
73
|
+
"INITIALLY",
|
|
74
|
+
"INNER",
|
|
75
|
+
"INTERSECT",
|
|
76
|
+
"INTO",
|
|
77
|
+
"IS",
|
|
78
|
+
"ISNULL",
|
|
79
|
+
"JOIN",
|
|
80
|
+
"LATERAL",
|
|
81
|
+
"LEADING",
|
|
82
|
+
"LEFT",
|
|
83
|
+
"LIKE",
|
|
84
|
+
"LIMIT",
|
|
85
|
+
"LOCALTIME",
|
|
86
|
+
"LOCALTIMESTAMP",
|
|
87
|
+
"NATURAL",
|
|
88
|
+
"NOT",
|
|
89
|
+
"NOTNULL",
|
|
90
|
+
"NULL",
|
|
91
|
+
"OFFSET",
|
|
92
|
+
"ON",
|
|
93
|
+
"ONLY",
|
|
94
|
+
"OR",
|
|
95
|
+
"ORDER",
|
|
96
|
+
"OUTER",
|
|
97
|
+
"OVERLAPS",
|
|
98
|
+
"PLACING",
|
|
99
|
+
"PRIMARY",
|
|
100
|
+
"REFERENCES",
|
|
101
|
+
"RETURNING",
|
|
102
|
+
"RIGHT",
|
|
103
|
+
"ROW",
|
|
104
|
+
"SELECT",
|
|
105
|
+
"SESSION_USER",
|
|
106
|
+
"SIMILAR",
|
|
107
|
+
"SOME",
|
|
108
|
+
"SYMMETRIC",
|
|
109
|
+
"TABLE",
|
|
110
|
+
"THEN",
|
|
111
|
+
"TO",
|
|
112
|
+
"TRAILING",
|
|
113
|
+
"TRUE",
|
|
114
|
+
"UNION",
|
|
115
|
+
"UNIQUE",
|
|
116
|
+
"USING",
|
|
117
|
+
"VARIADIC",
|
|
118
|
+
"VERBOSE",
|
|
119
|
+
"WHEN",
|
|
120
|
+
"WHERE",
|
|
121
|
+
"WINDOW",
|
|
122
|
+
"WITH"
|
|
123
|
+
];
|
|
124
|
+
const duckdbReservedKeywordsSet = new Set(duckReservedKeywords);
|
|
125
|
+
//#endregion
|
|
126
|
+
export { duckStorageVersionRegexp as a, duckIdentifierNameRegex as i, duckdbReservedKeywordsSet as n, duckConnectionsOptions as r, duckReservedKeywords as t };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as DuckConnectionParams } from "./types-
|
|
1
|
+
import { n as DuckConnectionParams } from "./types-dnhcognF.mjs";
|
|
2
2
|
import * as _$_duckdb_node_api0 from "@duckdb/node-api";
|
|
3
3
|
import { DuckDBConnection, DuckDBType } from "@duckdb/node-api";
|
|
4
4
|
import * as _$_logtape_logtape0 from "@logtape/logtape";
|
|
@@ -143,6 +143,13 @@ type ToTableParams<TSchema extends TableSchemaZod> = {
|
|
|
143
143
|
* @default true
|
|
144
144
|
*/
|
|
145
145
|
autoCheckpoint?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Checkpoint the table after 'n' chunks have been appended
|
|
148
|
+
*
|
|
149
|
+
* For example if the chunkSize is 2048, setting frequency to 2
|
|
150
|
+
* will checkpoint the table every 4096 rows (2x chunksize)
|
|
151
|
+
*/
|
|
152
|
+
checkpointChunksFrequency?: number;
|
|
146
153
|
};
|
|
147
154
|
type ToTableResult = {
|
|
148
155
|
/**
|
|
@@ -251,7 +258,7 @@ declare class DuckDatabaseManager {
|
|
|
251
258
|
* ```typescript
|
|
252
259
|
* const dbManager = new DuckDatabaseManager(conn);
|
|
253
260
|
* const database = dbManager.attach({
|
|
254
|
-
* type: 'memory', // can be '
|
|
261
|
+
* type: 'memory', // can be 'filesystem'...
|
|
255
262
|
* alias: 'mydb',
|
|
256
263
|
* options: { COMPRESS: 'true' }
|
|
257
264
|
* });
|
|
@@ -276,6 +283,15 @@ declare class DuckDatabaseManager {
|
|
|
276
283
|
analyze: () => Promise<boolean>;
|
|
277
284
|
checkpoint: (dbAlias: string) => Promise<boolean>;
|
|
278
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
|
+
}>;
|
|
279
295
|
}
|
|
280
296
|
//#endregion
|
|
281
297
|
//#region src/config/flowblade-logtape-sqlduck.config.d.ts
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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, DuckDBTimestampValue, FLOAT, HUGEINT, INTEGER, SMALLINT, TIMESTAMP, TINYINT, UBIGINT, UHUGEINT, UINTEGER, USMALLINT, UTINYINT, UUID, VARCHAR } from "@duckdb/node-api";
|
|
3
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import { basename, dirname } from "node:path";
|
|
4
7
|
import * as z from "zod";
|
|
5
8
|
import { assertNever } from "@httpx/assert";
|
|
6
9
|
import { isPlainObject } from "@httpx/plain-object";
|
|
@@ -127,6 +130,81 @@ const flowbladeLogtapeSqlduckConfig = { categories: ["flowblade", "sqlduck"] };
|
|
|
127
130
|
//#region src/logger/sqlduck-default-logtape-logger.ts
|
|
128
131
|
const sqlduckDefaultLogtapeLogger = getLogger(flowbladeLogtapeSqlduckConfig.categories);
|
|
129
132
|
//#endregion
|
|
133
|
+
//#region src/filesystem/file-system-utils.ts
|
|
134
|
+
var FileSystemUtils = class {
|
|
135
|
+
#logger;
|
|
136
|
+
constructor(params) {
|
|
137
|
+
this.#logger = params?.logger ?? sqlduckDefaultLogtapeLogger.with({ source: "FileSystemUtils" });
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Create a directory recursively if it doesn't exist
|
|
141
|
+
*
|
|
142
|
+
* @throws Error if it can't be created
|
|
143
|
+
*/
|
|
144
|
+
createDirectory = (path) => {
|
|
145
|
+
try {
|
|
146
|
+
fs.mkdirSync(path, { recursive: true });
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if (err.code !== "EEXIST") throw err;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Create a directory recursively if it doesn't exist and ensure it's writable
|
|
153
|
+
*/
|
|
154
|
+
createAndEnsureWritableDirectory = (label, path) => {
|
|
155
|
+
if (path === void 0) return;
|
|
156
|
+
if (!fs.existsSync(path)) try {
|
|
157
|
+
this.createDirectory(path);
|
|
158
|
+
} catch (e) {
|
|
159
|
+
throw new Error(`Failed to create ${label} '${path}' - ${e?.message ?? ""}`);
|
|
160
|
+
}
|
|
161
|
+
if (!fs.statSync(path).isDirectory()) throw new Error(`${label} '${path}' must be a directory`);
|
|
162
|
+
try {
|
|
163
|
+
fs.accessSync(path, fs.constants.W_OK);
|
|
164
|
+
} catch {
|
|
165
|
+
throw new Error(`${label} '${path}' must be writable`);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* Check if a path is a regular file and exists
|
|
170
|
+
*/
|
|
171
|
+
isFile = (path) => {
|
|
172
|
+
try {
|
|
173
|
+
return fs.statSync(path).isFile();
|
|
174
|
+
} catch {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Check if a path is a directory and exists
|
|
180
|
+
*/
|
|
181
|
+
isDirectory = (path) => {
|
|
182
|
+
try {
|
|
183
|
+
return fs.statSync(path).isDirectory();
|
|
184
|
+
} catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
parsePath = (path) => {
|
|
189
|
+
const dir = dirname(path);
|
|
190
|
+
if (dir.trim() === "") throw new Error(`Invalid path, missing directory '${path}'`);
|
|
191
|
+
const base = basename(path);
|
|
192
|
+
if (base.trim() === "") throw new Error(`Invalid path, missing filename '${path}'`);
|
|
193
|
+
return {
|
|
194
|
+
directory: dir,
|
|
195
|
+
filename: base
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
removeFileIfExists = (path) => {
|
|
199
|
+
try {
|
|
200
|
+
fs.rmSync(path);
|
|
201
|
+
return true;
|
|
202
|
+
} catch {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
//#endregion
|
|
130
208
|
//#region src/objects/database.ts
|
|
131
209
|
var Database = class {
|
|
132
210
|
#params;
|
|
@@ -163,7 +241,7 @@ var DuckDatabaseAttachCommand = class {
|
|
|
163
241
|
case "memory":
|
|
164
242
|
parts.push("':memory:'");
|
|
165
243
|
break;
|
|
166
|
-
case "
|
|
244
|
+
case "filesystem":
|
|
167
245
|
parts.push(`'${dbParams.path}'`);
|
|
168
246
|
break;
|
|
169
247
|
default: assertNever(type);
|
|
@@ -206,6 +284,7 @@ var DuckDatabaseAttachCommand = class {
|
|
|
206
284
|
var DuckDatabaseManager = class {
|
|
207
285
|
#conn;
|
|
208
286
|
#logger;
|
|
287
|
+
#fs;
|
|
209
288
|
constructor(conn, params) {
|
|
210
289
|
this.#conn = conn;
|
|
211
290
|
this.#logger = params?.logger ?? sqlduckDefaultLogtapeLogger.with({ source: "DuckDatabaseManager" });
|
|
@@ -217,7 +296,7 @@ var DuckDatabaseManager = class {
|
|
|
217
296
|
* ```typescript
|
|
218
297
|
* const dbManager = new DuckDatabaseManager(conn);
|
|
219
298
|
* const database = dbManager.attach({
|
|
220
|
-
* type: 'memory', // can be '
|
|
299
|
+
* type: 'memory', // can be 'filesystem'...
|
|
221
300
|
* alias: 'mydb',
|
|
222
301
|
* options: { COMPRESS: 'true' }
|
|
223
302
|
* });
|
|
@@ -228,7 +307,12 @@ var DuckDatabaseManager = class {
|
|
|
228
307
|
attach = async (dbParams, options) => {
|
|
229
308
|
const params = duckConnectionParamsZodSchema.parse(dbParams);
|
|
230
309
|
const rawSql = new DuckDatabaseAttachCommand(params, options).getRawSql();
|
|
231
|
-
|
|
310
|
+
const { behaviour } = options ?? {};
|
|
311
|
+
await this.#executeRawSqlCommand([
|
|
312
|
+
`attach(${params.alias}`,
|
|
313
|
+
behaviour ?? null,
|
|
314
|
+
")"
|
|
315
|
+
].filter(Boolean).join(","), rawSql);
|
|
232
316
|
return new Database({ alias: params.alias });
|
|
233
317
|
};
|
|
234
318
|
attachOrReplace = async (dbParams) => {
|
|
@@ -271,13 +355,39 @@ var DuckDatabaseManager = class {
|
|
|
271
355
|
await this.#executeRawSqlCommand("vacuum()", "VACUUM");
|
|
272
356
|
return true;
|
|
273
357
|
};
|
|
358
|
+
/**
|
|
359
|
+
* Helper to create an initial database file.
|
|
360
|
+
*/
|
|
361
|
+
createDatabaseFile = async (params) => {
|
|
362
|
+
const startTime = Date.now();
|
|
363
|
+
const { path, createDirectory = true } = params;
|
|
364
|
+
const fs = this.#getFs();
|
|
365
|
+
if (fs.isFile(path)) return { status: "exists" };
|
|
366
|
+
if (createDirectory) {
|
|
367
|
+
const { directory } = fs.parsePath(path);
|
|
368
|
+
fs.createAndEnsureWritableDirectory("database file directory", directory);
|
|
369
|
+
}
|
|
370
|
+
const instanceCache = new DuckDBInstanceCache();
|
|
371
|
+
try {
|
|
372
|
+
(await (await instanceCache.getOrCreateInstance(path)).connect()).closeSync();
|
|
373
|
+
const timeMs = Math.round(Date.now() - startTime);
|
|
374
|
+
this.#logger.info(`DuckDatabaseManager.createDatabaseFile('${path}') in ${timeMs}ms`, {
|
|
375
|
+
timeMs,
|
|
376
|
+
path
|
|
377
|
+
});
|
|
378
|
+
} catch (e) {
|
|
379
|
+
this.#logger.error(`DuckDatabaseManager.createDatabaseFile('${path}') failed - ${e?.message ?? ""}`, { path });
|
|
380
|
+
throw e;
|
|
381
|
+
}
|
|
382
|
+
return { status: "created" };
|
|
383
|
+
};
|
|
274
384
|
#executeRawSqlCommand = async (name, rawSql) => {
|
|
275
385
|
const startTime = Date.now();
|
|
276
386
|
try {
|
|
277
387
|
const result = await this.#conn.runAndReadAll(rawSql);
|
|
278
388
|
const timeMs = Math.round(Date.now() - startTime);
|
|
279
389
|
const data = result.getRowObjectsJS();
|
|
280
|
-
this.#logger.
|
|
390
|
+
this.#logger.debug(`DuckDatabaseManager.${name} in ${timeMs}ms`, { timeMs });
|
|
281
391
|
return data;
|
|
282
392
|
} catch (e) {
|
|
283
393
|
const msg = `DuckDatabaseManager: failed to run "${name}" - ${e?.message ?? ""}`;
|
|
@@ -290,6 +400,10 @@ var DuckDatabaseManager = class {
|
|
|
290
400
|
throw new Error(msg, { cause: e });
|
|
291
401
|
}
|
|
292
402
|
};
|
|
403
|
+
#getFs = () => {
|
|
404
|
+
if (this.#fs === void 0) this.#fs = new FileSystemUtils({ logger: this.#logger });
|
|
405
|
+
return this.#fs;
|
|
406
|
+
};
|
|
293
407
|
};
|
|
294
408
|
//#endregion
|
|
295
409
|
//#region src/table/get-duckdb-number-column-type.ts
|
|
@@ -514,9 +628,11 @@ var SqlDuck = class {
|
|
|
514
628
|
* ```
|
|
515
629
|
*/
|
|
516
630
|
toTable = async (params) => {
|
|
517
|
-
const { table, schema, chunkSize = 2048, rowStream, createOptions, onDataAppended, autoCheckpoint = true } = params;
|
|
631
|
+
const { table, schema, chunkSize = 2048, rowStream, createOptions, onDataAppended, autoCheckpoint = true, checkpointChunksFrequency = 10 } = params;
|
|
518
632
|
if (!Number.isSafeInteger(chunkSize) || chunkSize < 1 || chunkSize > 2048) throw new Error("chunkSize must be a number between 1 and 2048");
|
|
519
633
|
if (autoCheckpoint && typeof table.databaseName !== "string") throw new Error("autoCheckpoint requires table.databaseName to be provided.");
|
|
634
|
+
if (checkpointChunksFrequency && typeof table.databaseName !== "string") throw new Error("checkpointChunksFrequency requires table.databaseName to be provided.");
|
|
635
|
+
if (checkpointChunksFrequency !== void 0 && checkpointChunksFrequency < 1) throw new Error("checkpointChunksFrequency must be a positive number.");
|
|
520
636
|
const dbManager = new DuckDatabaseManager(this.#conn);
|
|
521
637
|
const timeStart = Date.now();
|
|
522
638
|
const { columnTypes, ddl } = await createTableFromZod({
|
|
@@ -533,6 +649,7 @@ var SqlDuck = class {
|
|
|
533
649
|
rows: rowStream,
|
|
534
650
|
chunkSize
|
|
535
651
|
});
|
|
652
|
+
let appendedChunkCount = 0;
|
|
536
653
|
try {
|
|
537
654
|
for await (const dataChunk of columnStream) {
|
|
538
655
|
const chunk = DuckDBDataChunk.create(chunkTypes);
|
|
@@ -541,12 +658,13 @@ var SqlDuck = class {
|
|
|
541
658
|
chunk.setColumns(dataChunk);
|
|
542
659
|
appender.appendDataChunk(chunk);
|
|
543
660
|
appender.flushSync();
|
|
661
|
+
appendedChunkCount += 1;
|
|
544
662
|
if (onDataAppended !== void 0) {
|
|
545
663
|
const payload = dataAppendedCollector(totalRows);
|
|
546
664
|
if (isOnDataAppendedAsyncCb(onDataAppended)) await onDataAppended(payload);
|
|
547
665
|
else onDataAppended(payload);
|
|
548
666
|
}
|
|
549
|
-
if (
|
|
667
|
+
if (checkpointChunksFrequency !== void 0 && appendedChunkCount % checkpointChunksFrequency === 0 && typeof table.databaseName === "string") try {
|
|
550
668
|
await dbManager.checkpoint(table.databaseName);
|
|
551
669
|
} catch (e) {
|
|
552
670
|
this.#logger.warning(`Failed to checkpoint database '${table.databaseName}' after appending chunk into table '${table.getFullName()}' - ${e?.message ?? ""}`, { table: table.getFullName() });
|
|
@@ -10,6 +10,8 @@ declare const duckAllConnectionOptionsZodSchema: z.ZodObject<{
|
|
|
10
10
|
type: z.ZodOptional<z.ZodEnum<{
|
|
11
11
|
DUCKDB: "DUCKDB";
|
|
12
12
|
SQLITE: "SQLITE";
|
|
13
|
+
MYSQL: "MYSQL";
|
|
14
|
+
PostgreSQL: "PostgreSQL";
|
|
13
15
|
}>>;
|
|
14
16
|
blockSize: z.ZodOptional<z.ZodInt32>;
|
|
15
17
|
rowGroupSize: z.ZodOptional<z.ZodInt32>;
|
|
@@ -33,6 +35,8 @@ declare const duckConnectionParamsZodSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
|
|
|
33
35
|
type: z.ZodOptional<z.ZodEnum<{
|
|
34
36
|
DUCKDB: "DUCKDB";
|
|
35
37
|
SQLITE: "SQLITE";
|
|
38
|
+
MYSQL: "MYSQL";
|
|
39
|
+
PostgreSQL: "PostgreSQL";
|
|
36
40
|
}>>;
|
|
37
41
|
blockSize: z.ZodOptional<z.ZodInt32>;
|
|
38
42
|
rowGroupSize: z.ZodOptional<z.ZodInt32>;
|
|
@@ -45,7 +49,7 @@ declare const duckConnectionParamsZodSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
|
|
|
45
49
|
}>>;
|
|
46
50
|
}, z.core.$strict>>;
|
|
47
51
|
}, z.core.$strict>, z.ZodObject<{
|
|
48
|
-
type: z.ZodLiteral<"
|
|
52
|
+
type: z.ZodLiteral<"filesystem">;
|
|
49
53
|
path: z.ZodString;
|
|
50
54
|
alias: z.ZodString;
|
|
51
55
|
options: z.ZodOptional<z.ZodObject<{
|
|
@@ -57,6 +61,8 @@ declare const duckConnectionParamsZodSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
|
|
|
57
61
|
type: z.ZodOptional<z.ZodEnum<{
|
|
58
62
|
DUCKDB: "DUCKDB";
|
|
59
63
|
SQLITE: "SQLITE";
|
|
64
|
+
MYSQL: "MYSQL";
|
|
65
|
+
PostgreSQL: "PostgreSQL";
|
|
60
66
|
}>>;
|
|
61
67
|
blockSize: z.ZodOptional<z.ZodInt32>;
|
|
62
68
|
rowGroupSize: z.ZodOptional<z.ZodInt32>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
|
|
3
|
+
//#region src/validation/valibot/duck-connection-params-valibot-schema.d.ts
|
|
4
|
+
declare const duckAllConnectionOptionsValibotSchema: v.ObjectSchema<{
|
|
5
|
+
readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
|
|
6
|
+
readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
7
|
+
readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
|
|
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
|
+
readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
|
|
10
|
+
readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
11
|
+
readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
|
|
12
|
+
readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
|
|
13
|
+
}, undefined>;
|
|
14
|
+
type DuckAllConnectionOptionsValibotSchema = v.InferOutput<typeof duckAllConnectionOptionsValibotSchema>;
|
|
15
|
+
declare const duckConnectionParamsValibotSchema: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
16
|
+
readonly type: v.LiteralSchema<"memory", undefined>;
|
|
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
|
+
readonly options: v.OptionalSchema<v.ObjectSchema<{
|
|
19
|
+
readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
|
|
20
|
+
readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
21
|
+
readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
|
|
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
|
+
readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
|
|
24
|
+
readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
25
|
+
readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
|
|
26
|
+
readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
|
|
27
|
+
}, undefined>, undefined>;
|
|
28
|
+
}, undefined>, v.ObjectSchema<{
|
|
29
|
+
readonly type: v.LiteralSchema<"filesystem", undefined>;
|
|
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
|
+
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
|
+
readonly options: v.OptionalSchema<v.ObjectSchema<{
|
|
33
|
+
readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
|
|
34
|
+
readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
35
|
+
readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
|
|
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
|
+
readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
|
|
38
|
+
readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
39
|
+
readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
|
|
40
|
+
readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
|
|
41
|
+
}, undefined>, undefined>;
|
|
42
|
+
}, undefined>], undefined>;
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/validation/valibot/duck-dsn-valibot-schema.d.ts
|
|
45
|
+
declare const duckDsnValibotSchema: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, (input: v.CheckIssue<string>) => string>, v.TransformAction<string, {
|
|
46
|
+
type: "memory";
|
|
47
|
+
alias: string;
|
|
48
|
+
options?: {
|
|
49
|
+
accessMode?: "READ_ONLY" | "READ_WRITE" | undefined;
|
|
50
|
+
compress?: boolean | undefined;
|
|
51
|
+
type?: "DUCKDB" | "SQLITE" | "MYSQL" | "PostgreSQL" | undefined;
|
|
52
|
+
blockSize?: number | undefined;
|
|
53
|
+
rowGroupSize?: number | undefined;
|
|
54
|
+
storageVersion?: string | undefined;
|
|
55
|
+
encryptionKey?: string | undefined;
|
|
56
|
+
encryptionCipher?: "CBC" | "CTR" | "GCM" | undefined;
|
|
57
|
+
} | undefined;
|
|
58
|
+
} | {
|
|
59
|
+
type: "filesystem";
|
|
60
|
+
path: string;
|
|
61
|
+
alias: string;
|
|
62
|
+
options?: {
|
|
63
|
+
accessMode?: "READ_ONLY" | "READ_WRITE" | undefined;
|
|
64
|
+
compress?: boolean | undefined;
|
|
65
|
+
type?: "DUCKDB" | "SQLITE" | "MYSQL" | "PostgreSQL" | undefined;
|
|
66
|
+
blockSize?: number | undefined;
|
|
67
|
+
rowGroupSize?: number | undefined;
|
|
68
|
+
storageVersion?: string | undefined;
|
|
69
|
+
encryptionKey?: string | undefined;
|
|
70
|
+
encryptionCipher?: "CBC" | "CTR" | "GCM" | undefined;
|
|
71
|
+
} | undefined;
|
|
72
|
+
}>, v.VariantSchema<"type", [v.ObjectSchema<{
|
|
73
|
+
readonly type: v.LiteralSchema<"memory", undefined>;
|
|
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
|
+
readonly options: v.OptionalSchema<v.ObjectSchema<{
|
|
76
|
+
readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
|
|
77
|
+
readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
78
|
+
readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
|
|
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
|
+
readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
|
|
81
|
+
readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
82
|
+
readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
|
|
83
|
+
readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
|
|
84
|
+
}, undefined>, undefined>;
|
|
85
|
+
}, undefined>, v.ObjectSchema<{
|
|
86
|
+
readonly type: v.LiteralSchema<"filesystem", undefined>;
|
|
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
|
+
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
|
+
readonly options: v.OptionalSchema<v.ObjectSchema<{
|
|
90
|
+
readonly accessMode: v.OptionalSchema<v.PicklistSchema<readonly ["READ_ONLY", "READ_WRITE"], undefined>, undefined>;
|
|
91
|
+
readonly compress: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
92
|
+
readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["DUCKDB", "SQLITE", "MYSQL", "PostgreSQL"], undefined>, undefined>;
|
|
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
|
+
readonly rowGroupSize: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, undefined>;
|
|
95
|
+
readonly storageVersion: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.StartsWithAction<string, "v", undefined>, v.RegexAction<string, undefined>]>, undefined>;
|
|
96
|
+
readonly encryptionKey: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 8, undefined>]>, undefined>;
|
|
97
|
+
readonly encryptionCipher: v.OptionalSchema<v.PicklistSchema<readonly ["CBC", "CTR", "GCM"], undefined>, undefined>;
|
|
98
|
+
}, undefined>, undefined>;
|
|
99
|
+
}, undefined>], undefined>]>;
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/validation/valibot/duck-identifier-valibot-schema.d.ts
|
|
102
|
+
/**
|
|
103
|
+
* Check whether a table name identifier is valid
|
|
104
|
+
*/
|
|
105
|
+
declare const duckIdentifierValibotSchema: 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">]>;
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/validation/valibot/duck-validators-valibot.d.ts
|
|
108
|
+
/**
|
|
109
|
+
* Common validators for duckdb parameters, tables...
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* import { duckValidatorsValibot } from '@flowblade/sqlduck/valibot';
|
|
114
|
+
*
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
declare const duckValidatorsValibot: {
|
|
118
|
+
/**
|
|
119
|
+
* Validate duckdb objects names like table, alias, and schemas
|
|
120
|
+
* for validity.
|
|
121
|
+
*/
|
|
122
|
+
readonly aliasName: 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">]>;
|
|
123
|
+
readonly schemaName: 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">]>;
|
|
124
|
+
readonly tableName: 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">]>;
|
|
125
|
+
};
|
|
126
|
+
//#endregion
|
|
127
|
+
export { type DuckAllConnectionOptionsValibotSchema, duckAllConnectionOptionsValibotSchema, duckConnectionParamsValibotSchema, duckDsnValibotSchema, duckIdentifierValibotSchema, duckValidatorsValibot };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "../../duck-reserved-keywords-B8XUjnaY.mjs";
|
|
2
|
+
import isSafeFilename from "is-safe-filename";
|
|
3
|
+
import { parseDsn, parseDsnOrThrow } from "@httpx/dsn-parser";
|
|
4
|
+
import * as v from "valibot";
|
|
5
|
+
//#region src/validation/valibot/duck-identifier-valibot-schema.ts
|
|
6
|
+
/**
|
|
7
|
+
* Check whether a table name identifier is valid
|
|
8
|
+
*/
|
|
9
|
+
const duckIdentifierValibotSchema = v.pipe(v.string(), v.minLength(1), v.maxLength(120), v.regex(duckIdentifierNameRegex, "Identifier must start with a letter or underscore, and contain only letters, numbers and underscores"), v.check((value) => !duckdbReservedKeywordsSet.has(value.toUpperCase()), "Identifier value is a DuckDB reserved keyword and cannot be used as an identifier"));
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/validation/valibot/duck-validators-valibot.ts
|
|
12
|
+
/**
|
|
13
|
+
* Common validators for duckdb parameters, tables...
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { duckValidatorsValibot } from '@flowblade/sqlduck/valibot';
|
|
18
|
+
*
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
const duckValidatorsValibot = {
|
|
22
|
+
aliasName: duckIdentifierValibotSchema,
|
|
23
|
+
schemaName: duckIdentifierValibotSchema,
|
|
24
|
+
tableName: duckIdentifierValibotSchema
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region src/validation/valibot/duck-connection-params-valibot-schema.ts
|
|
28
|
+
const duckAllConnectionOptionsValibotSchema = v.object({
|
|
29
|
+
accessMode: v.optional(v.picklist(duckConnectionsOptions.accessModes)),
|
|
30
|
+
compress: v.optional(v.boolean()),
|
|
31
|
+
type: v.optional(v.picklist(duckConnectionsOptions.types)),
|
|
32
|
+
blockSize: v.optional(v.pipe(v.number(), v.integer(), v.minValue(16384), v.maxValue(262144))),
|
|
33
|
+
rowGroupSize: v.optional(v.pipe(v.number(), v.integer(), v.minValue(1))),
|
|
34
|
+
storageVersion: v.optional(v.pipe(v.string(), v.startsWith("v"), v.regex(duckStorageVersionRegexp))),
|
|
35
|
+
encryptionKey: v.optional(v.pipe(v.string(), v.minLength(8))),
|
|
36
|
+
encryptionCipher: v.optional(v.picklist(duckConnectionsOptions.encryptionCiphers))
|
|
37
|
+
});
|
|
38
|
+
const duckConnectionParamsValibotSchema = v.variant("type", [v.object({
|
|
39
|
+
type: v.literal("memory"),
|
|
40
|
+
alias: duckValidatorsValibot.aliasName,
|
|
41
|
+
options: v.optional(duckAllConnectionOptionsValibotSchema)
|
|
42
|
+
}), v.object({
|
|
43
|
+
type: v.literal("filesystem"),
|
|
44
|
+
path: v.pipe(v.string(), v.check((path) => {
|
|
45
|
+
const filename = path.replace("\\", "/").split("/").at(-1);
|
|
46
|
+
return typeof filename === "string" && isSafeFilename(filename);
|
|
47
|
+
}, "Invalid database filename - it must be a safe filename (no path traversal, no absolute paths, no reserved names, etc.)"), v.check((path) => {
|
|
48
|
+
const pathname = "/" + path.replace("\\", "/").split("/").slice(0, -1).filter(Boolean).join("/");
|
|
49
|
+
return pathname.length > 0 && pathname.startsWith("/") && !pathname.includes("..");
|
|
50
|
+
}, "Invalid database pathname - it must be an absolute path with no traversal")),
|
|
51
|
+
alias: duckValidatorsValibot.aliasName,
|
|
52
|
+
options: v.optional(duckAllConnectionOptionsValibotSchema)
|
|
53
|
+
})]);
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/validation/valibot/duck-dsn-valibot-schema.ts
|
|
56
|
+
const duckDsnValibotSchema = v.pipe(v.string(), v.check((dsn) => parseDsn(dsn).success, (input) => {
|
|
57
|
+
return parseDsn(input.input)?.message ?? "Invalid DSN";
|
|
58
|
+
}), v.transform((dsn) => {
|
|
59
|
+
const parsed = parseDsnOrThrow(dsn);
|
|
60
|
+
const { path, ...options } = parsed.params ?? {};
|
|
61
|
+
return {
|
|
62
|
+
type: parsed.host,
|
|
63
|
+
alias: parsed.db,
|
|
64
|
+
...path ? { path } : {},
|
|
65
|
+
options: { ...options }
|
|
66
|
+
};
|
|
67
|
+
}), duckConnectionParamsValibotSchema);
|
|
68
|
+
//#endregion
|
|
69
|
+
export { duckAllConnectionOptionsValibotSchema, duckConnectionParamsValibotSchema, duckDsnValibotSchema, duckIdentifierValibotSchema, duckValidatorsValibot };
|
|
@@ -1,11 +1,92 @@
|
|
|
1
|
-
import { a as duckAllConnectionOptionsZodSchema, i as DuckTableName,
|
|
2
|
-
import * as
|
|
1
|
+
import { a as duckAllConnectionOptionsZodSchema, i as DuckTableName, o as duckConnectionParamsZodSchema, r as DuckSchemaName, t as DuckAliasName } from "../../types-dnhcognF.mjs";
|
|
2
|
+
import * as z from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/validation/zod/duck-asserts-zod.d.ts
|
|
5
5
|
declare function assertValidAliasName(aliasName: string): asserts aliasName is DuckAliasName;
|
|
6
6
|
declare function assertValidSchemaName(schemaName: string): asserts schemaName is DuckSchemaName;
|
|
7
7
|
declare function assertValidTableName(tableName: string): asserts tableName is DuckTableName;
|
|
8
8
|
//#endregion
|
|
9
|
+
//#region src/validation/zod/duck-dsn-zod-schema.d.ts
|
|
10
|
+
declare const duckDsnZodSchema: z.ZodPipe<z.ZodString, z.ZodPipe<z.ZodTransform<{
|
|
11
|
+
type: "memory";
|
|
12
|
+
alias: string;
|
|
13
|
+
options?: {
|
|
14
|
+
accessMode?: "READ_ONLY" | "READ_WRITE" | undefined;
|
|
15
|
+
compress?: boolean | undefined;
|
|
16
|
+
type?: "DUCKDB" | "SQLITE" | "MYSQL" | "PostgreSQL" | undefined;
|
|
17
|
+
blockSize?: number | undefined;
|
|
18
|
+
rowGroupSize?: number | undefined;
|
|
19
|
+
storageVersion?: string | undefined;
|
|
20
|
+
encryptionKey?: string | undefined;
|
|
21
|
+
encryptionCipher?: "CBC" | "CTR" | "GCM" | undefined;
|
|
22
|
+
} | undefined;
|
|
23
|
+
} | {
|
|
24
|
+
type: "filesystem";
|
|
25
|
+
path: string;
|
|
26
|
+
alias: string;
|
|
27
|
+
options?: {
|
|
28
|
+
accessMode?: "READ_ONLY" | "READ_WRITE" | undefined;
|
|
29
|
+
compress?: boolean | undefined;
|
|
30
|
+
type?: "DUCKDB" | "SQLITE" | "MYSQL" | "PostgreSQL" | undefined;
|
|
31
|
+
blockSize?: number | undefined;
|
|
32
|
+
rowGroupSize?: number | undefined;
|
|
33
|
+
storageVersion?: string | undefined;
|
|
34
|
+
encryptionKey?: string | undefined;
|
|
35
|
+
encryptionCipher?: "CBC" | "CTR" | "GCM" | undefined;
|
|
36
|
+
} | undefined;
|
|
37
|
+
}, string>, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
38
|
+
type: z.ZodLiteral<"memory">;
|
|
39
|
+
alias: z.ZodString;
|
|
40
|
+
options: z.ZodOptional<z.ZodObject<{
|
|
41
|
+
accessMode: z.ZodOptional<z.ZodEnum<{
|
|
42
|
+
READ_ONLY: "READ_ONLY";
|
|
43
|
+
READ_WRITE: "READ_WRITE";
|
|
44
|
+
}>>;
|
|
45
|
+
compress: z.ZodOptional<z.ZodBoolean>;
|
|
46
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
47
|
+
DUCKDB: "DUCKDB";
|
|
48
|
+
SQLITE: "SQLITE";
|
|
49
|
+
MYSQL: "MYSQL";
|
|
50
|
+
PostgreSQL: "PostgreSQL";
|
|
51
|
+
}>>;
|
|
52
|
+
blockSize: z.ZodOptional<z.ZodInt32>;
|
|
53
|
+
rowGroupSize: z.ZodOptional<z.ZodInt32>;
|
|
54
|
+
storageVersion: z.ZodOptional<z.ZodString>;
|
|
55
|
+
encryptionKey: z.ZodOptional<z.ZodString>;
|
|
56
|
+
encryptionCipher: z.ZodOptional<z.ZodEnum<{
|
|
57
|
+
CBC: "CBC";
|
|
58
|
+
CTR: "CTR";
|
|
59
|
+
GCM: "GCM";
|
|
60
|
+
}>>;
|
|
61
|
+
}, z.core.$strict>>;
|
|
62
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
63
|
+
type: z.ZodLiteral<"filesystem">;
|
|
64
|
+
path: z.ZodString;
|
|
65
|
+
alias: z.ZodString;
|
|
66
|
+
options: z.ZodOptional<z.ZodObject<{
|
|
67
|
+
accessMode: z.ZodOptional<z.ZodEnum<{
|
|
68
|
+
READ_ONLY: "READ_ONLY";
|
|
69
|
+
READ_WRITE: "READ_WRITE";
|
|
70
|
+
}>>;
|
|
71
|
+
compress: z.ZodOptional<z.ZodBoolean>;
|
|
72
|
+
type: z.ZodOptional<z.ZodEnum<{
|
|
73
|
+
DUCKDB: "DUCKDB";
|
|
74
|
+
SQLITE: "SQLITE";
|
|
75
|
+
MYSQL: "MYSQL";
|
|
76
|
+
PostgreSQL: "PostgreSQL";
|
|
77
|
+
}>>;
|
|
78
|
+
blockSize: z.ZodOptional<z.ZodInt32>;
|
|
79
|
+
rowGroupSize: z.ZodOptional<z.ZodInt32>;
|
|
80
|
+
storageVersion: z.ZodOptional<z.ZodString>;
|
|
81
|
+
encryptionKey: z.ZodOptional<z.ZodString>;
|
|
82
|
+
encryptionCipher: z.ZodOptional<z.ZodEnum<{
|
|
83
|
+
CBC: "CBC";
|
|
84
|
+
CTR: "CTR";
|
|
85
|
+
GCM: "GCM";
|
|
86
|
+
}>>;
|
|
87
|
+
}, z.core.$strict>>;
|
|
88
|
+
}, z.core.$strict>], "type">>>;
|
|
89
|
+
//#endregion
|
|
9
90
|
//#region src/validation/zod/duck-validators-zod.d.ts
|
|
10
91
|
/**
|
|
11
92
|
* Common validators for duckdb parameters, tables...
|
|
@@ -23,15 +104,9 @@ declare const duckValidatorsZod: {
|
|
|
23
104
|
* Validate duckdb objects names like table, alias, and schemas
|
|
24
105
|
* for validity.
|
|
25
106
|
*/
|
|
26
|
-
readonly aliasName:
|
|
27
|
-
readonly schemaName:
|
|
28
|
-
readonly tableName:
|
|
107
|
+
readonly aliasName: z.ZodString;
|
|
108
|
+
readonly schemaName: z.ZodString;
|
|
109
|
+
readonly tableName: z.ZodString;
|
|
29
110
|
};
|
|
30
111
|
//#endregion
|
|
31
|
-
|
|
32
|
-
declare const isParsableDuckDsnZod: (dsn: unknown) => boolean;
|
|
33
|
-
//#endregion
|
|
34
|
-
//#region src/validation/zod/parse-duck-dsn-zod.d.ts
|
|
35
|
-
declare const parseDuckDSNZod: (dsn: string) => DuckConnectionParams;
|
|
36
|
-
//#endregion
|
|
37
|
-
export { assertValidAliasName, assertValidSchemaName, assertValidTableName, duckAllConnectionOptionsZodSchema, duckConnectionParamsZodSchema, duckValidatorsZod, isParsableDuckDsnZod, parseDuckDSNZod };
|
|
112
|
+
export { assertValidAliasName, assertValidSchemaName, assertValidTableName, duckAllConnectionOptionsZodSchema, duckConnectionParamsZodSchema, duckDsnZodSchema, duckValidatorsZod };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { assertValidAliasName, assertValidSchemaName, assertValidTableName, duckAllConnectionOptionsZodSchema, duckConnectionParamsZodSchema,
|
|
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
|
+
export { assertValidAliasName, assertValidSchemaName, assertValidTableName, duckAllConnectionOptionsZodSchema, duckConnectionParamsZodSchema, duckDsnZodSchema, duckValidatorsZod };
|
|
@@ -1,115 +1,8 @@
|
|
|
1
|
+
import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "./duck-reserved-keywords-B8XUjnaY.mjs";
|
|
2
|
+
import isSafeFilename from "is-safe-filename";
|
|
1
3
|
import * as z from "zod";
|
|
2
4
|
import { parseDsn } from "@httpx/dsn-parser";
|
|
3
|
-
//#region src/validation/core/base-validators.ts
|
|
4
|
-
const duckIdentifierNameRegex = /^[a-z_]\w*$/i;
|
|
5
|
-
const duckStorageVersionRegexp = /^v?\d{1,4}\.\d{1,4}\.\d{1,4}$/;
|
|
6
|
-
//#endregion
|
|
7
|
-
//#region src/validation/core/duck-reserved-keywords.ts
|
|
8
|
-
/**
|
|
9
|
-
* DuckDB reserved keywords that cannot be used as unquoted identifiers.
|
|
10
|
-
* @see https://duckdb.org/docs/sql/keywords-and-identifiers.html
|
|
11
|
-
*/
|
|
12
|
-
const duckReservedKeywords = [
|
|
13
|
-
"ALL",
|
|
14
|
-
"ANALYSE",
|
|
15
|
-
"ANALYZE",
|
|
16
|
-
"AND",
|
|
17
|
-
"ANY",
|
|
18
|
-
"ARRAY",
|
|
19
|
-
"AS",
|
|
20
|
-
"ASC",
|
|
21
|
-
"ASYMMETRIC",
|
|
22
|
-
"BOTH",
|
|
23
|
-
"CASE",
|
|
24
|
-
"CAST",
|
|
25
|
-
"CHECK",
|
|
26
|
-
"COLLATE",
|
|
27
|
-
"COLUMN",
|
|
28
|
-
"CONSTRAINT",
|
|
29
|
-
"CREATE",
|
|
30
|
-
"CROSS",
|
|
31
|
-
"CURRENT_CATALOG",
|
|
32
|
-
"CURRENT_DATE",
|
|
33
|
-
"CURRENT_ROLE",
|
|
34
|
-
"CURRENT_SCHEMA",
|
|
35
|
-
"CURRENT_TIME",
|
|
36
|
-
"CURRENT_TIMESTAMP",
|
|
37
|
-
"CURRENT_USER",
|
|
38
|
-
"DEFAULT",
|
|
39
|
-
"DEFERRABLE",
|
|
40
|
-
"DESC",
|
|
41
|
-
"DISTINCT",
|
|
42
|
-
"DO",
|
|
43
|
-
"ELSE",
|
|
44
|
-
"END",
|
|
45
|
-
"EXCEPT",
|
|
46
|
-
"EXISTS",
|
|
47
|
-
"EXTRACT",
|
|
48
|
-
"FALSE",
|
|
49
|
-
"FETCH",
|
|
50
|
-
"FOR",
|
|
51
|
-
"FOREIGN",
|
|
52
|
-
"FROM",
|
|
53
|
-
"GRANT",
|
|
54
|
-
"GROUP",
|
|
55
|
-
"HAVING",
|
|
56
|
-
"IF",
|
|
57
|
-
"ILIKE",
|
|
58
|
-
"IN",
|
|
59
|
-
"INITIALLY",
|
|
60
|
-
"INNER",
|
|
61
|
-
"INTERSECT",
|
|
62
|
-
"INTO",
|
|
63
|
-
"IS",
|
|
64
|
-
"ISNULL",
|
|
65
|
-
"JOIN",
|
|
66
|
-
"LATERAL",
|
|
67
|
-
"LEADING",
|
|
68
|
-
"LEFT",
|
|
69
|
-
"LIKE",
|
|
70
|
-
"LIMIT",
|
|
71
|
-
"LOCALTIME",
|
|
72
|
-
"LOCALTIMESTAMP",
|
|
73
|
-
"NATURAL",
|
|
74
|
-
"NOT",
|
|
75
|
-
"NOTNULL",
|
|
76
|
-
"NULL",
|
|
77
|
-
"OFFSET",
|
|
78
|
-
"ON",
|
|
79
|
-
"ONLY",
|
|
80
|
-
"OR",
|
|
81
|
-
"ORDER",
|
|
82
|
-
"OUTER",
|
|
83
|
-
"OVERLAPS",
|
|
84
|
-
"PLACING",
|
|
85
|
-
"PRIMARY",
|
|
86
|
-
"REFERENCES",
|
|
87
|
-
"RETURNING",
|
|
88
|
-
"RIGHT",
|
|
89
|
-
"ROW",
|
|
90
|
-
"SELECT",
|
|
91
|
-
"SESSION_USER",
|
|
92
|
-
"SIMILAR",
|
|
93
|
-
"SOME",
|
|
94
|
-
"SYMMETRIC",
|
|
95
|
-
"TABLE",
|
|
96
|
-
"THEN",
|
|
97
|
-
"TO",
|
|
98
|
-
"TRAILING",
|
|
99
|
-
"TRUE",
|
|
100
|
-
"UNION",
|
|
101
|
-
"UNIQUE",
|
|
102
|
-
"USING",
|
|
103
|
-
"VARIADIC",
|
|
104
|
-
"VERBOSE",
|
|
105
|
-
"WHEN",
|
|
106
|
-
"WHERE",
|
|
107
|
-
"WINDOW",
|
|
108
|
-
"WITH"
|
|
109
|
-
];
|
|
110
|
-
//#endregion
|
|
111
5
|
//#region src/validation/zod/duck-identifier-zod-schema.ts
|
|
112
|
-
const duckdbReservedKeywordsSet = new Set(duckReservedKeywords.map((k) => k.toUpperCase()));
|
|
113
6
|
/**
|
|
114
7
|
* Check whether a table name identifier is valid
|
|
115
8
|
*/
|
|
@@ -135,26 +28,28 @@ const duckValidatorsZod = {
|
|
|
135
28
|
//#endregion
|
|
136
29
|
//#region src/validation/zod/duck-connection-params-zod-schema.ts
|
|
137
30
|
const duckAllConnectionOptionsZodSchema = z.strictObject({
|
|
138
|
-
accessMode: z.optional(z.enum(
|
|
31
|
+
accessMode: z.optional(z.enum(duckConnectionsOptions.accessModes)),
|
|
139
32
|
compress: z.optional(z.boolean()),
|
|
140
|
-
type: z.optional(z.enum(
|
|
33
|
+
type: z.optional(z.enum(duckConnectionsOptions.types)),
|
|
141
34
|
blockSize: z.optional(z.int32().min(16384).max(262144)),
|
|
142
35
|
rowGroupSize: z.optional(z.int32().positive()),
|
|
143
36
|
storageVersion: z.optional(z.string().startsWith("v").regex(duckStorageVersionRegexp)),
|
|
144
37
|
encryptionKey: z.optional(z.string().min(8)),
|
|
145
|
-
encryptionCipher: z.optional(z.enum(
|
|
146
|
-
"CBC",
|
|
147
|
-
"CTR",
|
|
148
|
-
"GCM"
|
|
149
|
-
]))
|
|
38
|
+
encryptionCipher: z.optional(z.enum(duckConnectionsOptions.encryptionCiphers))
|
|
150
39
|
});
|
|
151
40
|
const duckConnectionParamsZodSchema = z.discriminatedUnion("type", [z.strictObject({
|
|
152
41
|
type: z.literal("memory"),
|
|
153
42
|
alias: duckValidatorsZod.aliasName,
|
|
154
43
|
options: z.optional(duckAllConnectionOptionsZodSchema)
|
|
155
44
|
}), z.strictObject({
|
|
156
|
-
type: z.literal("
|
|
157
|
-
path: z.string().
|
|
45
|
+
type: z.literal("filesystem"),
|
|
46
|
+
path: z.string().refine((path) => {
|
|
47
|
+
const filename = path.replace("\\", "/").split("/").at(-1);
|
|
48
|
+
return typeof filename === "string" && isSafeFilename(filename);
|
|
49
|
+
}, { message: "Invalid database filename - it must be a safe filename (no path traversal, no absolute paths, no reserved names, etc.)" }).refine((path) => {
|
|
50
|
+
const pathname = "/" + path.replace("\\", "/").split("/").slice(0, -1).filter(Boolean).join("/");
|
|
51
|
+
return pathname.length > 0 && pathname.startsWith("/") && !pathname.includes("..");
|
|
52
|
+
}, { message: "Invalid database pathname - it must be an absolute path with no traversal" }),
|
|
158
53
|
alias: duckValidatorsZod.aliasName,
|
|
159
54
|
options: z.optional(duckAllConnectionOptionsZodSchema)
|
|
160
55
|
})]);
|
|
@@ -179,29 +74,26 @@ function assertValidTableName(tableName) {
|
|
|
179
74
|
if (parsed.error) throw createAssertError(`'${tableName}' is not a valid table name: ${parsed.error.message}`);
|
|
180
75
|
}
|
|
181
76
|
//#endregion
|
|
182
|
-
//#region src/validation/zod/
|
|
183
|
-
const
|
|
77
|
+
//#region src/validation/zod/duck-dsn-zod-schema.ts
|
|
78
|
+
const duckDsnZodSchema = z.string().pipe(z.preprocess((dsn, ctx) => {
|
|
184
79
|
const result = parseDsn(dsn);
|
|
185
|
-
if (
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
return true;
|
|
202
|
-
} catch {
|
|
203
|
-
return false;
|
|
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({
|
|
91
|
+
code: "custom",
|
|
92
|
+
message: result.message,
|
|
93
|
+
input: dsn
|
|
94
|
+
});
|
|
95
|
+
return z.NEVER;
|
|
204
96
|
}
|
|
205
|
-
};
|
|
97
|
+
}, duckConnectionParamsZodSchema));
|
|
206
98
|
//#endregion
|
|
207
|
-
export {
|
|
99
|
+
export { duckAllConnectionOptionsZodSchema as a, assertValidTableName as i, assertValidAliasName as n, duckConnectionParamsZodSchema as o, assertValidSchemaName as r, duckValidatorsZod as s, duckDsnZodSchema as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowblade/sqlduck",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": {
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
"types": "./dist/validation/zod/index.d.mts",
|
|
13
13
|
"default": "./dist/validation/zod/index.mjs"
|
|
14
14
|
},
|
|
15
|
+
"./valibot": {
|
|
16
|
+
"types": "./dist/validation/valibot/index.d.mts",
|
|
17
|
+
"default": "./dist/validation/valibot/index.mjs"
|
|
18
|
+
},
|
|
15
19
|
"./package.json": "./package.json"
|
|
16
20
|
},
|
|
17
21
|
"author": {
|
|
@@ -49,48 +53,55 @@
|
|
|
49
53
|
"fix-staged": "lint-staged --allow-empty",
|
|
50
54
|
"check-dist": "es-check --config=.escheckrc.json",
|
|
51
55
|
"check-pub": "publint",
|
|
52
|
-
"check-size": "size-limit"
|
|
56
|
+
"check-size-disabled": "size-limit"
|
|
53
57
|
},
|
|
54
58
|
"dependencies": {
|
|
55
59
|
"@flowblade/core": "^0.2.26",
|
|
56
60
|
"@flowblade/source-duckdb": "^0.20.1",
|
|
57
61
|
"@flowblade/sql-tag": "^0.3.2",
|
|
58
|
-
"@httpx/assert": "^0.16.
|
|
62
|
+
"@httpx/assert": "^0.16.9",
|
|
59
63
|
"@httpx/dsn-parser": "^1.9.9",
|
|
60
64
|
"@httpx/plain-object": "^2.1.8",
|
|
61
65
|
"@logtape/logtape": "^2.0.5",
|
|
62
66
|
"@standard-schema/spec": "^1.1.0",
|
|
63
|
-
"
|
|
67
|
+
"is-safe-filename": "0.1.1",
|
|
68
|
+
"p-queue": "9.1.1",
|
|
64
69
|
"zod": "^4.3.6"
|
|
65
70
|
},
|
|
66
71
|
"peerDependencies": {
|
|
67
|
-
"@duckdb/node-api": "^1.5.0-r.1"
|
|
72
|
+
"@duckdb/node-api": "^1.5.0-r.1",
|
|
73
|
+
"valibot": "^1.3.1"
|
|
74
|
+
},
|
|
75
|
+
"peerDependenciesMeta": {
|
|
76
|
+
"valibot": {
|
|
77
|
+
"optional": true
|
|
78
|
+
}
|
|
68
79
|
},
|
|
69
80
|
"devDependencies": {
|
|
70
|
-
"@belgattitude/eslint-config-bases": "8.
|
|
81
|
+
"@belgattitude/eslint-config-bases": "8.12.0",
|
|
71
82
|
"@dotenvx/dotenvx": "1.59.1",
|
|
72
83
|
"@duckdb/node-api": "1.5.1-r.1",
|
|
73
84
|
"@faker-js/faker": "10.4.0",
|
|
74
85
|
"@flowblade/source-kysely": "^1.3.0",
|
|
75
|
-
"@httpx/assert": "0.16.
|
|
86
|
+
"@httpx/assert": "0.16.9",
|
|
76
87
|
"@mitata/counters": "0.0.8",
|
|
77
88
|
"@size-limit/esbuild": "12.0.1",
|
|
78
89
|
"@size-limit/file": "12.0.1",
|
|
79
90
|
"@testcontainers/mssqlserver": "11.13.0",
|
|
80
91
|
"@total-typescript/ts-reset": "0.6.1",
|
|
81
|
-
"@types/node": "25.5.
|
|
82
|
-
"@typescript-eslint/eslint-plugin": "8.58.
|
|
83
|
-
"@typescript-eslint/parser": "8.58.
|
|
84
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
85
|
-
"@vitest/coverage-v8": "4.1.
|
|
86
|
-
"@vitest/ui": "4.1.
|
|
92
|
+
"@types/node": "25.5.2",
|
|
93
|
+
"@typescript-eslint/eslint-plugin": "8.58.1",
|
|
94
|
+
"@typescript-eslint/parser": "8.58.1",
|
|
95
|
+
"@typescript/native-preview": "7.0.0-dev.20260406.1",
|
|
96
|
+
"@vitest/coverage-v8": "4.1.3",
|
|
97
|
+
"@vitest/ui": "4.1.3",
|
|
87
98
|
"ansis": "4.2.0",
|
|
88
99
|
"browserslist-to-esbuild": "2.1.1",
|
|
89
100
|
"core-js": "3.49.0",
|
|
90
101
|
"cross-env": "10.1.0",
|
|
91
|
-
"es-check": "9.6.
|
|
102
|
+
"es-check": "9.6.4",
|
|
92
103
|
"es-toolkit": "1.45.1",
|
|
93
|
-
"esbuild": "0.
|
|
104
|
+
"esbuild": "0.28.0",
|
|
94
105
|
"eslint": "8.57.1",
|
|
95
106
|
"execa": "9.6.1",
|
|
96
107
|
"is-in-ci": "2.0.0",
|
|
@@ -111,7 +122,8 @@
|
|
|
111
122
|
"typedoc": "0.28.18",
|
|
112
123
|
"typedoc-plugin-markdown": "4.11.0",
|
|
113
124
|
"typescript": "6.0.2",
|
|
114
|
-
"
|
|
125
|
+
"valibot": "1.3.1",
|
|
126
|
+
"vitest": "4.1.3"
|
|
115
127
|
},
|
|
116
128
|
"files": [
|
|
117
129
|
"dist"
|