@atscript/db-sqlite 0.1.131 → 0.1.133

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
@@ -39,7 +39,7 @@ await users.insertOne({ name: "John", email: "john@example.com" });
39
39
 
40
40
  ## Features
41
41
 
42
- - Swappable driver via `TSqliteDriver` interface (5 methods)
42
+ - Swappable driver via `TSqliteDriver` interface (5 methods, plus the optional `registerFunction` hook calendar-bucket grouping needs)
43
43
  - Built-in `BetterSqlite3Driver` for immediate use (with optional `{ vector: true }` and `loadExtensions` hooks)
44
44
  - MongoDB-style filter translation to parameterized SQL (no injection risk)
45
45
  - Automatic schema management from `@db.*` annotations
package/dist/index.cjs CHANGED
@@ -3,6 +3,7 @@ let _atscript_db = require("@atscript/db");
3
3
  let node_module = require("node:module");
4
4
  let _atscript_db_agg = require("@atscript/db/agg");
5
5
  let _atscript_db_sql_tools = require("@atscript/db-sql-tools");
6
+ let _uniqu_core = require("@uniqu/core");
6
7
  let node_async_hooks = require("node:async_hooks");
7
8
  //#region src/better-sqlite3-driver.ts
8
9
  /**
@@ -74,11 +75,93 @@ var BetterSqlite3Driver = class {
74
75
  exec(sql) {
75
76
  this.db.exec(sql);
76
77
  }
78
+ registerFunction(name, fn, opts) {
79
+ this.db.function(name, { deterministic: opts?.deterministic ?? false }, fn);
80
+ }
77
81
  close() {
78
82
  this.db.close();
79
83
  }
80
84
  };
81
85
  //#endregion
86
+ //#region src/calendar-bucket.ts
87
+ /**
88
+ * Name of the scalar SQL function the adapter registers on its driver:
89
+ * `atscript_bucket(value, unit, tz, weekStart)` → TEXT `'YYYY-MM-DD'` or NULL.
90
+ */
91
+ const SQLITE_BUCKET_FN = "atscript_bucket";
92
+ /**
93
+ * Prepared kernels by `unit|tz|weekStart`. Bounded by construction: the
94
+ * arguments are the literals `sqliteCalendarBucket` inlines — closed unit /
95
+ * week-start sets and validated IANA zones — and an invalid combination
96
+ * throws before it is stored.
97
+ */
98
+ const bucketers = /* @__PURE__ */ new Map();
99
+ /** The last arguments and their kernel — a query calls the UDF with one combination per row. */
100
+ let last;
101
+ function cachedBucketer(unit, tz, weekStart) {
102
+ if (last && last.unit === unit && last.tz === tz && last.weekStart === weekStart) return last.fn;
103
+ const u = String(unit);
104
+ const z = String(tz);
105
+ const w = String(weekStart);
106
+ const key = `${u}|${z}|${w}`;
107
+ let fn = bucketers.get(key);
108
+ if (!fn) {
109
+ fn = (0, _uniqu_core.bucketer)(u, z, w);
110
+ bucketers.set(key, fn);
111
+ }
112
+ last = {
113
+ unit,
114
+ tz,
115
+ weekStart,
116
+ fn
117
+ };
118
+ return fn;
119
+ }
120
+ /**
121
+ * Body of the `atscript_bucket` UDF: the `@uniqu/core` calendar kernel — the
122
+ * same definition the in-memory adapter groups with. INTEGER / REAL values
123
+ * arrive as `number` (or `bigint` in better-sqlite3's safe-integer mode);
124
+ * NULL and any other storage class (TEXT, BLOB) label as NULL, as does an
125
+ * instant outside the supported range. The kernel is prepared once per
126
+ * (unit, zone, week start), not per row.
127
+ *
128
+ * Four declared parameters on purpose: SQLite drivers take a UDF's arity from
129
+ * `fn.length`.
130
+ */
131
+ function atscriptBucketUdf(value, unit, tz, weekStart) {
132
+ if (typeof value !== "number" && typeof value !== "bigint") return null;
133
+ return cachedBucketer(unit, tz, weekStart)(value);
134
+ }
135
+ /** Drivers the UDF is registered on. */
136
+ const registered = /* @__PURE__ */ new WeakSet();
137
+ /**
138
+ * Registers {@link SQLITE_BUCKET_FN} on `driver` once — every table adapter
139
+ * of a space shares one driver — and reports whether the driver has the UDF.
140
+ * A driver without {@link TSqliteDriver.registerFunction} cannot run calendar
141
+ * buckets (the adapter then advertises no bucket units → `BUCKET_NOT_SUPPORTED`).
142
+ * A failing `registerFunction` propagates: it is a broken driver, not a
143
+ * missing capability.
144
+ */
145
+ function registerBucketFunction(driver) {
146
+ if (typeof driver.registerFunction !== "function") return false;
147
+ if (!registered.has(driver)) {
148
+ driver.registerFunction(SQLITE_BUCKET_FN, atscriptBucketUdf, { deterministic: true });
149
+ registered.add(driver);
150
+ }
151
+ return true;
152
+ }
153
+ /**
154
+ * The SQLite dialect's calendar-bucket expression:
155
+ * `atscript_bucket("col", 'week', 'Europe/Berlin', 'sun')`. Parameter-free —
156
+ * the shared builder asserts the unit and week start against their closed
157
+ * sets, and the zone passes {@link sqlTimeZoneLiteral}'s charset — so SELECT,
158
+ * GROUP BY and HAVING render identical text. Deterministic, so SQLite treats
159
+ * repeated calls as one expression.
160
+ */
161
+ function sqliteCalendarBucket(quotedCol, b) {
162
+ return `${SQLITE_BUCKET_FN}(${quotedCol}, '${b.unit}', ${(0, _atscript_db_sql_tools.sqlTimeZoneLiteral)(b.tz)}, '${b.weekStart}')`;
163
+ }
164
+ //#endregion
82
165
  //#region src/sql-builder.ts
83
166
  function esc(name) {
84
167
  return name.replace(/"/g, "\"\"");
@@ -189,6 +272,7 @@ const sqliteDialect = {
189
272
  params: [...dist.params, circle.radius]
190
273
  };
191
274
  },
275
+ calendarBucket: sqliteCalendarBucket,
192
276
  createViewPrefix: "CREATE VIEW IF NOT EXISTS"
193
277
  };
194
278
  /**
@@ -579,6 +663,14 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
579
663
  supportsNativeValueDefaults() {
580
664
  return true;
581
665
  }
666
+ /**
667
+ * Every calendar-bucket unit when the driver could register the
668
+ * `atscript_bucket` UDF (at construction — see {@link registerBucketFunction}),
669
+ * none otherwise (`BUCKET_NOT_SUPPORTED`, a clean 400).
670
+ */
671
+ calendarBucketUnits() {
672
+ return this._hasBucketFn ? _atscript_db.ALL_BUCKET_UNITS : super.calendarBucketUnits();
673
+ }
582
674
  /** Whether the SQLite connection has the sqlite-vec extension loaded. */
583
675
  _supportsVector;
584
676
  /** Whether SQLite math functions (radians/asin/...) are available — geo search. */
@@ -592,12 +684,15 @@ var SqliteAdapter = class SqliteAdapter extends _atscript_db.BaseDbAdapter {
592
684
  /** Per-driver transaction gate (shared by every adapter over this driver). */
593
685
  _gate;
594
686
  _txOptions;
687
+ /** Whether the driver has the calendar-bucket UDF — fixed at construction, when it is registered. */
688
+ _hasBucketFn;
595
689
  constructor(driver, options) {
596
690
  super();
597
691
  this.driver = driver;
598
692
  this._gate = getSqliteTxGate(driver);
599
693
  this._txOptions = { ...options };
600
694
  this.driver.exec("PRAGMA foreign_keys = ON");
695
+ this._hasBucketFn = registerBucketFunction(driver);
601
696
  }
602
697
  onFieldScanned(field, _type, metadata) {
603
698
  const vectorMeta = metadata.get("db.search.vector");
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseDbAdapter, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
1
+ import { BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
2
2
  import { TMetadataMap } from "@atscript/typescript/utils";
3
3
  import { FilterExpr as FilterExpr$1 } from "@uniqu/core";
4
4
  import { TSqlFragment, TSqlFragment as TSqlFragment$1 } from "@atscript/db-sql-tools";
@@ -47,6 +47,21 @@ interface TSqliteDriver {
47
47
  * Close the database connection.
48
48
  */
49
49
  close(): void;
50
+ /**
51
+ * Registers a scalar SQL function (a user-defined function) on the
52
+ * connection. Optional: the adapter registers `atscript_bucket` through it
53
+ * for calendar-bucket grouping, and a driver without it advertises no
54
+ * calendar-bucket units (`BUCKET_NOT_SUPPORTED`). The function's arity is
55
+ * `fn.length`; `deterministic` marks it pure, which lets SQLite use it in
56
+ * GROUP BY / indexes and fold repeated calls.
57
+ *
58
+ * better-sqlite3: `db.function(name, { deterministic }, fn)`;
59
+ * node:sqlite: `DatabaseSync#function(name, { deterministic }, fn)` (Node ≥ 22.13).
60
+ * Since 0.1.132.
61
+ */
62
+ registerFunction?(name: string, fn: (...args: any[]) => unknown, opts?: {
63
+ deterministic?: boolean;
64
+ }): void;
50
65
  /**
51
66
  * Whether a vector search extension (e.g., `sqlite-vec`) is loaded.
52
67
  * Consumers gate vec0 virtual tables and KNN queries on this flag.
@@ -103,6 +118,9 @@ declare class BetterSqlite3Driver implements TSqliteDriver {
103
118
  all<T = Record<string, unknown>>(sql: string, params?: unknown[]): T[];
104
119
  get<T = Record<string, unknown>>(sql: string, params?: unknown[]): T | null;
105
120
  exec(sql: string): void;
121
+ registerFunction(name: string, fn: (...args: any[]) => unknown, opts?: {
122
+ deterministic?: boolean;
123
+ }): void;
106
124
  close(): void;
107
125
  }
108
126
  //#endregion
@@ -243,6 +261,12 @@ declare function getSqliteTxGate(driver: TSqliteDriver): SqliteTxGate;
243
261
  declare class SqliteAdapter extends BaseDbAdapter {
244
262
  protected readonly driver: TSqliteDriver;
245
263
  supportsNativeValueDefaults(): boolean;
264
+ /**
265
+ * Every calendar-bucket unit when the driver could register the
266
+ * `atscript_bucket` UDF (at construction — see {@link registerBucketFunction}),
267
+ * none otherwise (`BUCKET_NOT_SUPPORTED`, a clean 400).
268
+ */
269
+ calendarBucketUnits(): ReadonlySet<BucketUnit>;
246
270
  /** Whether the SQLite connection has the sqlite-vec extension loaded. */
247
271
  private _supportsVector;
248
272
  /** Whether SQLite math functions (radians/asin/...) are available — geo search. */
@@ -256,6 +280,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
256
280
  /** Per-driver transaction gate (shared by every adapter over this driver). */
257
281
  private readonly _gate;
258
282
  private readonly _txOptions;
283
+ /** Whether the driver has the calendar-bucket UDF — fixed at construction, when it is registered. */
284
+ private readonly _hasBucketFn;
259
285
  constructor(driver: TSqliteDriver, options?: SqliteAdapterOptions);
260
286
  onFieldScanned(field: string, _type: unknown, metadata: TMetadataMap<AtscriptMetadata>): void;
261
287
  formatValue(field: TDbFieldMeta): TValueFormatterPair | undefined;
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { BaseDbAdapter, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
1
+ import { BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TGenericLogger, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
2
2
  import { TSqlFragment, TSqlFragment as TSqlFragment$1 } from "@atscript/db-sql-tools";
3
- import { TMetadataMap } from "@atscript/typescript/utils";
4
3
  import { FilterExpr as FilterExpr$1 } from "@uniqu/core";
4
+ import { TMetadataMap } from "@atscript/typescript/utils";
5
5
 
6
6
  //#region src/types.d.ts
7
7
  /**
@@ -47,6 +47,21 @@ interface TSqliteDriver {
47
47
  * Close the database connection.
48
48
  */
49
49
  close(): void;
50
+ /**
51
+ * Registers a scalar SQL function (a user-defined function) on the
52
+ * connection. Optional: the adapter registers `atscript_bucket` through it
53
+ * for calendar-bucket grouping, and a driver without it advertises no
54
+ * calendar-bucket units (`BUCKET_NOT_SUPPORTED`). The function's arity is
55
+ * `fn.length`; `deterministic` marks it pure, which lets SQLite use it in
56
+ * GROUP BY / indexes and fold repeated calls.
57
+ *
58
+ * better-sqlite3: `db.function(name, { deterministic }, fn)`;
59
+ * node:sqlite: `DatabaseSync#function(name, { deterministic }, fn)` (Node ≥ 22.13).
60
+ * Since 0.1.132.
61
+ */
62
+ registerFunction?(name: string, fn: (...args: any[]) => unknown, opts?: {
63
+ deterministic?: boolean;
64
+ }): void;
50
65
  /**
51
66
  * Whether a vector search extension (e.g., `sqlite-vec`) is loaded.
52
67
  * Consumers gate vec0 virtual tables and KNN queries on this flag.
@@ -103,6 +118,9 @@ declare class BetterSqlite3Driver implements TSqliteDriver {
103
118
  all<T = Record<string, unknown>>(sql: string, params?: unknown[]): T[];
104
119
  get<T = Record<string, unknown>>(sql: string, params?: unknown[]): T | null;
105
120
  exec(sql: string): void;
121
+ registerFunction(name: string, fn: (...args: any[]) => unknown, opts?: {
122
+ deterministic?: boolean;
123
+ }): void;
106
124
  close(): void;
107
125
  }
108
126
  //#endregion
@@ -243,6 +261,12 @@ declare function getSqliteTxGate(driver: TSqliteDriver): SqliteTxGate;
243
261
  declare class SqliteAdapter extends BaseDbAdapter {
244
262
  protected readonly driver: TSqliteDriver;
245
263
  supportsNativeValueDefaults(): boolean;
264
+ /**
265
+ * Every calendar-bucket unit when the driver could register the
266
+ * `atscript_bucket` UDF (at construction — see {@link registerBucketFunction}),
267
+ * none otherwise (`BUCKET_NOT_SUPPORTED`, a clean 400).
268
+ */
269
+ calendarBucketUnits(): ReadonlySet<BucketUnit>;
246
270
  /** Whether the SQLite connection has the sqlite-vec extension loaded. */
247
271
  private _supportsVector;
248
272
  /** Whether SQLite math functions (radians/asin/...) are available — geo search. */
@@ -256,6 +280,8 @@ declare class SqliteAdapter extends BaseDbAdapter {
256
280
  /** Per-driver transaction gate (shared by every adapter over this driver). */
257
281
  private readonly _gate;
258
282
  private readonly _txOptions;
283
+ /** Whether the driver has the calendar-bucket UDF — fixed at construction, when it is registered. */
284
+ private readonly _hasBucketFn;
259
285
  constructor(driver: TSqliteDriver, options?: SqliteAdapterOptions);
260
286
  onFieldScanned(field: string, _type: unknown, metadata: TMetadataMap<AtscriptMetadata>): void;
261
287
  formatValue(field: TDbFieldMeta): TValueFormatterPair | undefined;
package/dist/index.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { createRequire } from "node:module";
2
- import { BaseDbAdapter, DbError, DbSpace } from "@atscript/db";
2
+ import { ALL_BUCKET_UNITS, BaseDbAdapter, DbError, DbSpace } from "@atscript/db";
3
3
  import { resolveAggregateSearch } from "@atscript/db/agg";
4
- import { EMPTY_AND, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildSelect, buildUpdate, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, fillReplacePayload, geoWindowFromControls, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, toSqlValue } from "@atscript/db-sql-tools";
4
+ import { EMPTY_AND, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildSelect, buildUpdate, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, fillReplacePayload, geoWindowFromControls, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlTimeZoneLiteral, toSqlValue } from "@atscript/db-sql-tools";
5
+ import { bucketer } from "@uniqu/core";
5
6
  import { AsyncLocalStorage } from "node:async_hooks";
6
7
  //#region src/better-sqlite3-driver.ts
7
8
  /**
@@ -73,11 +74,93 @@ var BetterSqlite3Driver = class {
73
74
  exec(sql) {
74
75
  this.db.exec(sql);
75
76
  }
77
+ registerFunction(name, fn, opts) {
78
+ this.db.function(name, { deterministic: opts?.deterministic ?? false }, fn);
79
+ }
76
80
  close() {
77
81
  this.db.close();
78
82
  }
79
83
  };
80
84
  //#endregion
85
+ //#region src/calendar-bucket.ts
86
+ /**
87
+ * Name of the scalar SQL function the adapter registers on its driver:
88
+ * `atscript_bucket(value, unit, tz, weekStart)` → TEXT `'YYYY-MM-DD'` or NULL.
89
+ */
90
+ const SQLITE_BUCKET_FN = "atscript_bucket";
91
+ /**
92
+ * Prepared kernels by `unit|tz|weekStart`. Bounded by construction: the
93
+ * arguments are the literals `sqliteCalendarBucket` inlines — closed unit /
94
+ * week-start sets and validated IANA zones — and an invalid combination
95
+ * throws before it is stored.
96
+ */
97
+ const bucketers = /* @__PURE__ */ new Map();
98
+ /** The last arguments and their kernel — a query calls the UDF with one combination per row. */
99
+ let last;
100
+ function cachedBucketer(unit, tz, weekStart) {
101
+ if (last && last.unit === unit && last.tz === tz && last.weekStart === weekStart) return last.fn;
102
+ const u = String(unit);
103
+ const z = String(tz);
104
+ const w = String(weekStart);
105
+ const key = `${u}|${z}|${w}`;
106
+ let fn = bucketers.get(key);
107
+ if (!fn) {
108
+ fn = bucketer(u, z, w);
109
+ bucketers.set(key, fn);
110
+ }
111
+ last = {
112
+ unit,
113
+ tz,
114
+ weekStart,
115
+ fn
116
+ };
117
+ return fn;
118
+ }
119
+ /**
120
+ * Body of the `atscript_bucket` UDF: the `@uniqu/core` calendar kernel — the
121
+ * same definition the in-memory adapter groups with. INTEGER / REAL values
122
+ * arrive as `number` (or `bigint` in better-sqlite3's safe-integer mode);
123
+ * NULL and any other storage class (TEXT, BLOB) label as NULL, as does an
124
+ * instant outside the supported range. The kernel is prepared once per
125
+ * (unit, zone, week start), not per row.
126
+ *
127
+ * Four declared parameters on purpose: SQLite drivers take a UDF's arity from
128
+ * `fn.length`.
129
+ */
130
+ function atscriptBucketUdf(value, unit, tz, weekStart) {
131
+ if (typeof value !== "number" && typeof value !== "bigint") return null;
132
+ return cachedBucketer(unit, tz, weekStart)(value);
133
+ }
134
+ /** Drivers the UDF is registered on. */
135
+ const registered = /* @__PURE__ */ new WeakSet();
136
+ /**
137
+ * Registers {@link SQLITE_BUCKET_FN} on `driver` once — every table adapter
138
+ * of a space shares one driver — and reports whether the driver has the UDF.
139
+ * A driver without {@link TSqliteDriver.registerFunction} cannot run calendar
140
+ * buckets (the adapter then advertises no bucket units → `BUCKET_NOT_SUPPORTED`).
141
+ * A failing `registerFunction` propagates: it is a broken driver, not a
142
+ * missing capability.
143
+ */
144
+ function registerBucketFunction(driver) {
145
+ if (typeof driver.registerFunction !== "function") return false;
146
+ if (!registered.has(driver)) {
147
+ driver.registerFunction(SQLITE_BUCKET_FN, atscriptBucketUdf, { deterministic: true });
148
+ registered.add(driver);
149
+ }
150
+ return true;
151
+ }
152
+ /**
153
+ * The SQLite dialect's calendar-bucket expression:
154
+ * `atscript_bucket("col", 'week', 'Europe/Berlin', 'sun')`. Parameter-free —
155
+ * the shared builder asserts the unit and week start against their closed
156
+ * sets, and the zone passes {@link sqlTimeZoneLiteral}'s charset — so SELECT,
157
+ * GROUP BY and HAVING render identical text. Deterministic, so SQLite treats
158
+ * repeated calls as one expression.
159
+ */
160
+ function sqliteCalendarBucket(quotedCol, b) {
161
+ return `${SQLITE_BUCKET_FN}(${quotedCol}, '${b.unit}', ${sqlTimeZoneLiteral(b.tz)}, '${b.weekStart}')`;
162
+ }
163
+ //#endregion
81
164
  //#region src/sql-builder.ts
82
165
  function esc(name) {
83
166
  return name.replace(/"/g, "\"\"");
@@ -188,6 +271,7 @@ const sqliteDialect = {
188
271
  params: [...dist.params, circle.radius]
189
272
  };
190
273
  },
274
+ calendarBucket: sqliteCalendarBucket,
191
275
  createViewPrefix: "CREATE VIEW IF NOT EXISTS"
192
276
  };
193
277
  /**
@@ -578,6 +662,14 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
578
662
  supportsNativeValueDefaults() {
579
663
  return true;
580
664
  }
665
+ /**
666
+ * Every calendar-bucket unit when the driver could register the
667
+ * `atscript_bucket` UDF (at construction — see {@link registerBucketFunction}),
668
+ * none otherwise (`BUCKET_NOT_SUPPORTED`, a clean 400).
669
+ */
670
+ calendarBucketUnits() {
671
+ return this._hasBucketFn ? ALL_BUCKET_UNITS : super.calendarBucketUnits();
672
+ }
581
673
  /** Whether the SQLite connection has the sqlite-vec extension loaded. */
582
674
  _supportsVector;
583
675
  /** Whether SQLite math functions (radians/asin/...) are available — geo search. */
@@ -591,12 +683,15 @@ var SqliteAdapter = class SqliteAdapter extends BaseDbAdapter {
591
683
  /** Per-driver transaction gate (shared by every adapter over this driver). */
592
684
  _gate;
593
685
  _txOptions;
686
+ /** Whether the driver has the calendar-bucket UDF — fixed at construction, when it is registered. */
687
+ _hasBucketFn;
594
688
  constructor(driver, options) {
595
689
  super();
596
690
  this.driver = driver;
597
691
  this._gate = getSqliteTxGate(driver);
598
692
  this._txOptions = { ...options };
599
693
  this.driver.exec("PRAGMA foreign_keys = ON");
694
+ this._hasBucketFn = registerBucketFunction(driver);
600
695
  }
601
696
  onFieldScanned(field, _type, metadata) {
602
697
  const vectorMeta = metadata.get("db.search.vector");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db-sqlite",
3
- "version": "0.1.131",
3
+ "version": "0.1.133",
4
4
  "description": "SQLite adapter for @atscript/db with swappable driver support.",
5
5
  "keywords": [
6
6
  "atscript",
@@ -39,7 +39,7 @@
39
39
  "@atscript/core": "^0.1.92",
40
40
  "@atscript/typescript": "^0.1.92",
41
41
  "@types/better-sqlite3": "^7.6.13",
42
- "@uniqu/core": "^0.1.8",
42
+ "@uniqu/core": "^0.1.10",
43
43
  "better-sqlite3": "^12.6.2",
44
44
  "sqlite-vec": "^0.1.9",
45
45
  "unplugin-atscript": "^0.1.92"
@@ -47,10 +47,10 @@
47
47
  "peerDependencies": {
48
48
  "@atscript/core": "^0.1.92",
49
49
  "@atscript/typescript": "^0.1.92",
50
- "@uniqu/core": "^0.1.8",
50
+ "@uniqu/core": "^0.1.10",
51
51
  "better-sqlite3": ">=11.0.0",
52
- "@atscript/db": "^0.1.131",
53
- "@atscript/db-sql-tools": "^0.1.131"
52
+ "@atscript/db": "^0.1.133",
53
+ "@atscript/db-sql-tools": "^0.1.133"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "better-sqlite3": {