@flowblade/sqlduck 0.26.0 → 0.28.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.
@@ -1,2 +1,2 @@
1
- import { t as FileSystemUtils } from "../file-system-utils-BX51TrfT.mjs";
1
+ import { t as FileSystemUtils } from "../file-system-utils-DT6smf4C.mjs";
2
2
  export { FileSystemUtils };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,5 @@
1
- import { n as DuckConnectionParams } from "./types-C6EIVpFJ.mjs";
1
+ import { n as DuckConnectionParams } from "./types-BKI2f-Rk.mjs";
2
2
  import { DuckDBConnection, DuckDBType } from "@duckdb/node-api";
3
- import * as _$_logtape_logtape0 from "@logtape/logtape";
4
3
  import { Logger } from "@logtape/logtape";
5
4
  import * as z from "zod";
6
5
  import { ZodObject } from "zod";
@@ -394,6 +393,6 @@ declare const flowbladeLogtapeSqlduckConfig: {
394
393
  };
395
394
  //#endregion
396
395
  //#region src/logger/sqlduck-default-logtape-logger.d.ts
397
- declare const sqlduckDefaultLogtapeLogger: _$_logtape_logtape0.Logger;
396
+ declare const sqlduckDefaultLogtapeLogger: import("@logtape/logtape").Logger;
398
397
  //#endregion
399
398
  export { Database, type DuckConnectionParams, DuckDatabaseManager, DuckExtensionsManager, DuckMemory, type DuckMemoryTag, DuckSettingsManager, type DuckdbReservedKeywords, type OnChunkAppendedCb, type OnChunkAppendedStats, SqlDuck, type SqlDuckParams, Table, type ToTableParams, duckReservedKeywords, flowbladeLogtapeSqlduckConfig, getTableCreateFromZod, sqlduckDefaultLogtapeLogger, zodCodecs };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { n as sqlduckDefaultLogtapeLogger, r as flowbladeLogtapeSqlduckConfig, t as FileSystemUtils } from "./file-system-utils-BX51TrfT.mjs";
2
- import { t as duckReservedKeywords } from "./duck-reserved-keywords-D_yi_PVW.mjs";
3
- import { c as duckValidatorsZod, r as assertValidAliasName, s as duckConnectionParamsZodSchema } from "./zod-uQPzaK64.mjs";
4
- 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";
1
+ import { n as sqlduckDefaultLogtapeLogger, r as flowbladeLogtapeSqlduckConfig, t as FileSystemUtils } from "./file-system-utils-DT6smf4C.mjs";
2
+ import { t as duckReservedKeywords } from "./duck-reserved-keywords-BzYA7jvN.mjs";
3
+ import { c as duckValidatorsZod, r as assertValidAliasName, s as duckConnectionParamsZodSchema } from "./zod-DB5FHzXW.mjs";
4
+ import { BIGINT, BOOLEAN, DECIMAL, DOUBLE, DuckDBDataChunk, DuckDBDecimalType, DuckDBDecimalValue, DuckDBInstanceCache, DuckDBTimestampMillisecondsValue, DuckDBTypeId, ENUM, FLOAT, HUGEINT, INTEGER, SMALLINT, TIMESTAMP, TIMESTAMP_MS, TINYINT, UBIGINT, UHUGEINT, UINTEGER, USMALLINT, UTINYINT, UUID, VARCHAR } from "@duckdb/node-api";
5
5
  import * as z from "zod";
6
6
  import { assertNever } from "@httpx/assert";
7
7
  import { isPlainObject } from "@httpx/plain-object";
@@ -154,6 +154,12 @@ var DuckValueConverter = class {
154
154
  value
155
155
  });
156
156
  };
157
+ createDecimalConverter = (width, scale) => (value) => {
158
+ if (value === void 0 || value === null) return null;
159
+ if (typeof value === "number") return DuckDBDecimalValue.fromDouble(value, width, scale);
160
+ if (typeof value === "bigint") return new DuckDBDecimalValue(value, width, scale);
161
+ throw new TypeError("Decimal converter require value to be a number or a bigint");
162
+ };
157
163
  toBigIntString = (value) => {
158
164
  if (typeof value === "string") return value;
159
165
  if (typeof value === "number" || typeof value === "bigint") return value.toString(10);
@@ -221,6 +227,12 @@ const createDuckColumnConverters = (duckTypes) => {
221
227
  case DuckDBTypeId.SMALLINT:
222
228
  conv = false;
223
229
  break;
230
+ case DuckDBTypeId.FLOAT:
231
+ conv = false;
232
+ break;
233
+ case DuckDBTypeId.DECIMAL:
234
+ conv = converter.createDecimalConverter(18, 3);
235
+ break;
224
236
  default: throw new Error(`Unsupported duck type ${duckTypeId} / ${duckType.toString()} for column '${key}'`);
225
237
  }
226
238
  if (conv !== false) convMap[key] = conv;
@@ -527,12 +539,19 @@ var DuckDatabaseManager = class {
527
539
  //#region src/table/get-duckdb-number-column-type.ts
528
540
  const isFloatValue = (value) => {
529
541
  if (!Number.isFinite(value)) return true;
542
+ if (!value.toString(10).includes(".")) return false;
530
543
  if (Math.abs(value) > Number.MAX_SAFE_INTEGER) return true;
531
544
  return !Number.isInteger(value);
532
545
  };
546
+ const getScale = (value) => {
547
+ const parts = value.toString().split(".");
548
+ if (parts.length < 2) return 0;
549
+ return parts[1].length;
550
+ };
533
551
  const getDuckdbNumberColumnType = (params) => {
534
- const { minimum, maximum } = params;
552
+ const { minimum, maximum, multipleOf } = params;
535
553
  if (minimum === void 0 || maximum === void 0) return BIGINT;
554
+ if (multipleOf !== void 0 && isFloatValue(multipleOf)) return DECIMAL(18, getScale(multipleOf));
536
555
  if (isFloatValue(minimum) || isFloatValue(maximum)) {
537
556
  if (minimum >= -34028235e31 && maximum <= 34028235e31) return FLOAT;
538
557
  return DOUBLE;
@@ -557,7 +576,7 @@ const createOptions = {
557
576
  CREATE_OR_REPLACE: "CREATE OR REPLACE TABLE",
558
577
  IF_NOT_EXISTS: "CREATE TABLE IF NOT EXISTS"
559
578
  };
560
- const duckDbTypesMap = new Map([
579
+ const duckDbTypes = [
561
580
  ["VARCHAR", VARCHAR],
562
581
  ["BIGINT", BIGINT],
563
582
  ["UBIGINT", UBIGINT],
@@ -568,8 +587,10 @@ const duckDbTypesMap = new Map([
568
587
  ["BOOLEAN", BOOLEAN],
569
588
  ["INTEGER", INTEGER],
570
589
  ["DOUBLE", DOUBLE],
571
- ["FLOAT", FLOAT]
572
- ]);
590
+ ["FLOAT", FLOAT],
591
+ ["DECIMAL", new DuckDBDecimalType(18, 3)]
592
+ ];
593
+ const duckDbTypesMap = new Map(duckDbTypes);
573
594
  const getTableCreateFromZod = (params) => {
574
595
  const { table, schema, options } = params;
575
596
  const { create = "CREATE" } = options ?? {};
@@ -582,7 +603,7 @@ const getTableCreateFromZod = (params) => {
582
603
  if (json.properties === void 0) throw new TypeError("Schema must have at least one property");
583
604
  const columnTypesMap = /* @__PURE__ */ new Map();
584
605
  for (const [columnName, def] of Object.entries(json.properties)) {
585
- const { type, duckdbType, nullable, format, primaryKey, minimum, maximum } = def;
606
+ const { type, duckdbType, nullable, format, primaryKey, minimum, maximum, multipleOf } = def;
586
607
  const c = { name: columnName };
587
608
  if (duckdbType !== void 0 && duckDbTypesMap.has(duckdbType)) c.duckdbType = duckDbTypesMap.get(duckdbType);
588
609
  else switch (type) {
@@ -604,7 +625,8 @@ const getTableCreateFromZod = (params) => {
604
625
  case "number":
605
626
  c.duckdbType = getDuckdbNumberColumnType({
606
627
  minimum,
607
- maximum
628
+ maximum,
629
+ multipleOf
608
630
  });
609
631
  break;
610
632
  case "integer":
@@ -0,0 +1,16 @@
1
+ import { Kysely, SelectQueryBuilder } from "kysely";
2
+
3
+ //#region src/integrations/kysely/compile-duck-query.d.ts
4
+ type SqlTagInformation = {
5
+ text: string;
6
+ values: unknown[];
7
+ };
8
+ declare const compileDuckQuery: <T extends SelectQueryBuilder<any, any, any>>(query: T) => SqlTagInformation;
9
+ //#endregion
10
+ //#region src/integrations/kysely/create-duck-kysely-query-builder.d.ts
11
+ type KyselyQueryBuilder<TDatabase> = Pick<Kysely<TDatabase>, 'mergeInto' | 'selectFrom' | 'selectNoFrom' | 'deleteFrom' | 'updateTable' | 'insertInto' | 'replaceInto' | 'with' | 'withRecursive' | 'withTables'>;
12
+ declare const createDuckKysekyQueryBuilder: <TDatabase>(params?: {
13
+ schema?: string;
14
+ }) => KyselyQueryBuilder<TDatabase>;
15
+ //#endregion
16
+ export { compileDuckQuery, createDuckKysekyQueryBuilder };
@@ -0,0 +1,24 @@
1
+ import { DummyDriver, Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler } from "kysely";
2
+ //#region src/integrations/kysely/compile-duck-query.ts
3
+ const compileDuckQuery = (query) => {
4
+ const { sql, parameters } = query.compile();
5
+ return {
6
+ text: sql,
7
+ values: parameters
8
+ };
9
+ };
10
+ //#endregion
11
+ //#region src/integrations/kysely/create-duck-kysely-query-builder.ts
12
+ let kyselyCache;
13
+ const createDuckKysekyQueryBuilder = (params) => {
14
+ kyselyCache ??= new Kysely({ dialect: {
15
+ createAdapter: () => new PostgresAdapter(),
16
+ createDriver: () => new DummyDriver(),
17
+ createIntrospector: (db) => new PostgresIntrospector(db),
18
+ createQueryCompiler: () => new PostgresQueryCompiler()
19
+ } });
20
+ if (params?.schema) return kyselyCache.withSchema(params.schema);
21
+ return kyselyCache;
22
+ };
23
+ //#endregion
24
+ export { compileDuckQuery, createDuckKysekyQueryBuilder };
@@ -126,9 +126,9 @@ declare const duckValidatorsValibot: {
126
126
  * Validate duckdb objects names like table, alias, and schemas
127
127
  * for validity.
128
128
  */
129
- 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">]>;
130
- 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">]>;
131
- 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">]>;
129
+ readonly aliasName: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 120, undefined>, import("valibot").RegexAction<string, "Identifier must start with a letter or underscore, and contain only letters, numbers and underscores">, import("valibot").CheckAction<string, "Identifier value is a DuckDB reserved keyword and cannot be used as an identifier">]>;
130
+ readonly schemaName: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 120, undefined>, import("valibot").RegexAction<string, "Identifier must start with a letter or underscore, and contain only letters, numbers and underscores">, import("valibot").CheckAction<string, "Identifier value is a DuckDB reserved keyword and cannot be used as an identifier">]>;
131
+ readonly tableName: import("valibot").SchemaWithPipe<readonly [import("valibot").StringSchema<undefined>, import("valibot").MinLengthAction<string, 1, undefined>, import("valibot").MaxLengthAction<string, 120, undefined>, import("valibot").RegexAction<string, "Identifier must start with a letter or underscore, and contain only letters, numbers and underscores">, import("valibot").CheckAction<string, "Identifier value is a DuckDB reserved keyword and cannot be used as an identifier">]>;
132
132
  };
133
133
  //#endregion
134
134
  export { type DuckAllConnectionOptionsValibotSchema, duckAllConnectionOptionsValibotSchema, duckConnectionParamsValibotSchema, duckDsnValibotSchema, duckIdentifierValibotSchema, duckValidatorsValibot };
@@ -1,4 +1,4 @@
1
- import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "../../duck-reserved-keywords-D_yi_PVW.mjs";
1
+ import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "../../duck-reserved-keywords-BzYA7jvN.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";
@@ -1,4 +1,4 @@
1
- import { a as duckAllConnectionOptionsZodSchema, i as DuckTableName, o as duckConnectionParamsZodSchema, r as DuckSchemaName, t as DuckAliasName } from "../../types-C6EIVpFJ.mjs";
1
+ import { a as duckAllConnectionOptionsZodSchema, i as DuckTableName, o as duckConnectionParamsZodSchema, r as DuckSchemaName, t as DuckAliasName } from "../../types-BKI2f-Rk.mjs";
2
2
  import * as z from "zod";
3
3
 
4
4
  //#region src/validation/zod/duck-asserts-zod.d.ts
@@ -112,9 +112,9 @@ declare const duckValidatorsZod: {
112
112
  * Validate duckdb objects names like table, alias, and schemas
113
113
  * for validity.
114
114
  */
115
- readonly aliasName: z.ZodString;
116
- readonly schemaName: z.ZodString;
117
- readonly tableName: z.ZodString;
115
+ readonly aliasName: import("zod").ZodString;
116
+ readonly schemaName: import("zod").ZodString;
117
+ readonly tableName: import("zod").ZodString;
118
118
  };
119
119
  //#endregion
120
120
  //#region src/validation/zod/ensure-zod-table-schema.d.ts
@@ -1,2 +1,2 @@
1
- import { a as assertValidTableName, c as duckValidatorsZod, i as assertValidSchemaName, n as duckDsnZodSchema, o as duckAllConnectionOptionsZodSchema, r as assertValidAliasName, s as duckConnectionParamsZodSchema, t as ensureZodTableSchema } from "../../zod-uQPzaK64.mjs";
1
+ import { a as assertValidTableName, c as duckValidatorsZod, i as assertValidSchemaName, n as duckDsnZodSchema, o as duckAllConnectionOptionsZodSchema, r as assertValidAliasName, s as duckConnectionParamsZodSchema, t as ensureZodTableSchema } from "../../zod-DB5FHzXW.mjs";
2
2
  export { assertValidAliasName, assertValidSchemaName, assertValidTableName, duckAllConnectionOptionsZodSchema, duckConnectionParamsZodSchema, duckDsnZodSchema, duckValidatorsZod, ensureZodTableSchema };
@@ -1,4 +1,4 @@
1
- import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "./duck-reserved-keywords-D_yi_PVW.mjs";
1
+ import { a as duckStorageVersionRegexp, i as duckIdentifierNameRegex, n as duckdbReservedKeywordsSet, r as duckConnectionsOptions } from "./duck-reserved-keywords-BzYA7jvN.mjs";
2
2
  import isSafeFilename from "is-safe-filename";
3
3
  import * as z from "zod";
4
4
  import { parseDsn } from "@httpx/dsn-parser";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowblade/sqlduck",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -20,6 +20,10 @@
20
20
  "types": "./dist/validation/valibot/index.d.mts",
21
21
  "default": "./dist/validation/valibot/index.mjs"
22
22
  },
23
+ "./kysely": {
24
+ "types": "./dist/integrations/kysely/index.d.mts",
25
+ "default": "./dist/integrations/kysely/index.mjs"
26
+ },
23
27
  "./package.json": "./package.json"
24
28
  },
25
29
  "author": {
@@ -63,7 +67,7 @@
63
67
  },
64
68
  "dependencies": {
65
69
  "@flowblade/core": "^0.2.29",
66
- "@flowblade/source-duckdb": "^0.22.0",
70
+ "@flowblade/source-duckdb": "^0.23.0",
67
71
  "@flowblade/sql-tag": "^0.3.4",
68
72
  "@httpx/assert": "^0.17.1",
69
73
  "@httpx/dsn-parser": "^1.9.11",
@@ -89,22 +93,22 @@
89
93
  },
90
94
  "devDependencies": {
91
95
  "@belgattitude/eslint-config-bases": "8.15.0",
92
- "@dotenvx/dotenvx": "1.69.1",
93
- "@duckdb/node-api": "1.5.3-r.2",
96
+ "@dotenvx/dotenvx": "1.69.2",
97
+ "@duckdb/node-api": "1.5.3-r.3",
94
98
  "@faker-js/faker": "10.4.0",
95
99
  "@flowblade/source-kysely": "^1.4.1",
96
100
  "@httpx/assert": "0.17.1",
97
101
  "@mitata/counters": "0.0.8",
98
102
  "@size-limit/esbuild": "12.1.0",
99
103
  "@size-limit/file": "12.1.0",
100
- "@testcontainers/mssqlserver": "12.0.0",
104
+ "@testcontainers/mssqlserver": "12.0.1",
101
105
  "@total-typescript/ts-reset": "0.6.1",
102
106
  "@types/node": "25.9.1",
103
- "@typescript-eslint/eslint-plugin": "8.60.0",
104
- "@typescript-eslint/parser": "8.60.0",
105
- "@typescript/native-preview": "7.0.0-dev.20260526.1",
106
- "@vitest/coverage-v8": "4.1.7",
107
- "@vitest/ui": "4.1.7",
107
+ "@typescript-eslint/eslint-plugin": "8.60.1",
108
+ "@typescript-eslint/parser": "8.60.1",
109
+ "@typescript/native-preview": "7.0.0-dev.20260527.2",
110
+ "@vitest/coverage-v8": "4.1.8",
111
+ "@vitest/ui": "4.1.8",
108
112
  "ansis": "4.3.0",
109
113
  "browserslist-to-esbuild": "2.1.1",
110
114
  "core-js": "3.49.0",
@@ -126,14 +130,14 @@
126
130
  "sql-formatter": "15.8.0",
127
131
  "tarn": "3.0.2",
128
132
  "tedious": "19.2.1",
129
- "testcontainers": "12.0.0",
130
- "tsdown": "0.22.0",
133
+ "testcontainers": "12.0.1",
134
+ "tsdown": "0.22.1",
131
135
  "tsx": "4.22.3",
132
136
  "typedoc": "0.28.19",
133
137
  "typedoc-plugin-markdown": "4.11.0",
134
138
  "typescript": "6.0.3",
135
139
  "valibot": "1.4.1",
136
- "vitest": "4.1.7"
140
+ "vitest": "4.1.8"
137
141
  },
138
142
  "files": [
139
143
  "dist"