@frontmcp/storage-sqlite 1.8.6 → 1.8.7

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/encryption.d.ts CHANGED
@@ -4,6 +4,14 @@
4
4
  * Provides AES-256-GCM encryption for stored values using @frontmcp/utils crypto.
5
5
  * Keys are stored in plaintext (needed for lookups); only values are encrypted.
6
6
  */
7
+ /**
8
+ * Thrown when a stored value cannot be decrypted: the encryption secret differs
9
+ * from the one the value was written with, or the value was tampered with.
10
+ */
11
+ export declare class SqliteDecryptionError extends Error {
12
+ readonly code = "SQLITE_DECRYPTION_FAILED";
13
+ constructor();
14
+ }
7
15
  /**
8
16
  * Derives a 256-bit encryption key from a user-provided secret using HKDF-SHA256.
9
17
  *
@@ -1 +1 @@
1
- {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../src/encryption.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAG9D;AAQD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAMvE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAYvE"}
1
+ {"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../src/encryption.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,IAAI,8BAA8B;;CAS5C;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAG9D;AAQD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAMvE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAevE"}
package/esm/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { createRequire as __frontmcpCreateRequire } from 'module';
2
- const require = __frontmcpCreateRequire(import.meta.url || 'file:///');
1
+ const __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
2
+ const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
3
+ // __frontmcpCreateRequire
3
4
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
4
5
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
5
6
  }) : x)(function(x) {
@@ -9,13 +10,22 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
9
10
 
10
11
  // libs/storage-sqlite/src/encryption.ts
11
12
  import {
12
- encryptAesGcm,
13
+ base64urlDecode,
14
+ base64urlEncode,
13
15
  decryptAesGcm,
16
+ encryptAesGcm,
14
17
  hkdfSha256,
15
- randomBytes,
16
- base64urlEncode,
17
- base64urlDecode
18
+ randomBytes
18
19
  } from "@frontmcp/utils";
20
+ var SqliteDecryptionError = class extends Error {
21
+ code = "SQLITE_DECRYPTION_FAILED";
22
+ constructor() {
23
+ super(
24
+ "SqliteKvStore: failed to decrypt a stored value. The encryption secret differs from the one the database was written with (or the value is corrupted). Restore the original secret, or delete the database file to start empty."
25
+ );
26
+ this.name = "SqliteDecryptionError";
27
+ }
28
+ };
19
29
  var HKDF_SALT = new TextEncoder().encode("frontmcp-sqlite-storage-v1");
20
30
  var HKDF_INFO = new TextEncoder().encode("aes-256-gcm-value-encryption");
21
31
  var KEY_LENGTH = 32;
@@ -38,8 +48,11 @@ function decryptValue(key, encrypted) {
38
48
  const iv = base64urlDecode(parts[0]);
39
49
  const tag = base64urlDecode(parts[1]);
40
50
  const ciphertext = base64urlDecode(parts[2]);
41
- const plaintext = decryptAesGcm(key, ciphertext, iv, tag);
42
- return new TextDecoder().decode(plaintext);
51
+ try {
52
+ return new TextDecoder().decode(decryptAesGcm(key, ciphertext, iv, tag));
53
+ } catch {
54
+ throw new SqliteDecryptionError();
55
+ }
43
56
  }
44
57
 
45
58
  // libs/storage-sqlite/src/open-database.ts
@@ -58,7 +71,27 @@ function loadBetterSqlite3() {
58
71
 
59
72
  // libs/storage-sqlite/src/open-database.ts
60
73
  var MEMORY_PATH = ":memory:";
61
- function openDatabase(path, storeName) {
74
+ var DEFAULT_BUSY_TIMEOUT_MS = 5e3;
75
+ function isBusyError(err) {
76
+ const code = err?.code;
77
+ return code === "SQLITE_BUSY" || code === "SQLITE_BUSY_RECOVERY" || code === "SQLITE_BUSY_SNAPSHOT";
78
+ }
79
+ function sleepSync(ms) {
80
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
81
+ }
82
+ function withBusyRetry(operation, options = {}) {
83
+ const attempts = options.attempts ?? 5;
84
+ const delayMs = options.delayMs ?? 50;
85
+ for (let attempt = 1; ; attempt++) {
86
+ try {
87
+ return operation();
88
+ } catch (err) {
89
+ if (!isBusyError(err) || attempt >= attempts) throw err;
90
+ sleepSync(delayMs * attempt);
91
+ }
92
+ }
93
+ }
94
+ function openDatabase(path, storeName, options = {}) {
62
95
  const BetterSqlite3 = loadBetterSqlite3();
63
96
  if (path !== MEMORY_PATH && path !== "") {
64
97
  const dir = dirname(path);
@@ -67,16 +100,28 @@ function openDatabase(path, storeName) {
67
100
  ensureDirSync(dir);
68
101
  } catch (err) {
69
102
  const message = err instanceof Error ? err.message : String(err);
70
- throw new Error(`${storeName}: failed to create directory "${dir}" for database "${path}": ${message}`);
103
+ throw new Error(`${storeName}: failed to create directory "${dir}" for database "${path}": ${message}`, {
104
+ cause: err
105
+ });
71
106
  }
72
107
  }
73
108
  }
109
+ let db;
110
+ try {
111
+ db = new BetterSqlite3(path);
112
+ } catch (err) {
113
+ const message = err instanceof Error ? err.message : String(err);
114
+ throw new Error(`${storeName}: failed to open database at "${path}": ${message}`, { cause: err });
115
+ }
74
116
  try {
75
- return new BetterSqlite3(path);
117
+ db.pragma(`busy_timeout = ${Math.max(0, Math.floor(options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS))}`);
118
+ if (options.walMode) withBusyRetry(() => db.pragma("journal_mode = WAL"));
76
119
  } catch (err) {
120
+ db.close();
77
121
  const message = err instanceof Error ? err.message : String(err);
78
- throw new Error(`${storeName}: failed to open database at "${path}": ${message}`);
122
+ throw new Error(`${storeName}: failed to configure database at "${path}": ${message}`, { cause: err });
79
123
  }
124
+ return db;
80
125
  }
81
126
 
82
127
  // libs/storage-sqlite/src/sqlite-kv.store.ts
@@ -86,14 +131,14 @@ var SqliteKvStore = class {
86
131
  cleanupTimer = null;
87
132
  stmts = null;
88
133
  constructor(options) {
89
- this.db = openDatabase(options.path, "SqliteKvStore");
90
- if (options.walMode !== false) {
91
- this.db.pragma("journal_mode = WAL");
92
- }
134
+ this.db = openDatabase(options.path, "SqliteKvStore", {
135
+ busyTimeoutMs: options.busyTimeoutMs,
136
+ walMode: options.walMode !== false
137
+ });
93
138
  if (options.encryption?.secret) {
94
139
  this.encryptionKey = deriveEncryptionKey(options.encryption.secret);
95
140
  }
96
- this.initSchema();
141
+ withBusyRetry(() => this.initSchema());
97
142
  this.prepareStatements();
98
143
  const cleanupInterval = options.ttlCleanupIntervalMs ?? 6e4;
99
144
  if (cleanupInterval > 0) {
@@ -560,17 +605,17 @@ var SqliteTaskStore = class {
560
605
  encryptionKey = null;
561
606
  stmts = null;
562
607
  constructor(options) {
563
- this.db = openDatabase(options.path, "SqliteTaskStore");
564
- if (options.walMode !== false) {
565
- this.db.pragma("journal_mode = WAL");
566
- }
608
+ this.db = openDatabase(options.path, "SqliteTaskStore", {
609
+ busyTimeoutMs: options.busyTimeoutMs,
610
+ walMode: options.walMode !== false
611
+ });
567
612
  this.logger = options.logger;
568
613
  this.liveness = options.livenessProbe ?? defaultLivenessProbe;
569
614
  if (options.encryption?.secret) {
570
615
  this.encryptionKey = deriveEncryptionKey(options.encryption.secret);
571
616
  }
572
617
  this.emitter.setMaxListeners(200);
573
- this.initSchema();
618
+ withBusyRetry(() => this.initSchema());
574
619
  this.prepareStatements();
575
620
  const cleanupInterval = options.ttlCleanupIntervalMs ?? 6e4;
576
621
  if (cleanupInterval > 0) {
@@ -809,13 +854,13 @@ var SqliteEventStore = class {
809
854
  cleanupTimer = null;
810
855
  stmts = null;
811
856
  constructor(options) {
812
- this.db = openDatabase(options.path, "SqliteEventStore");
813
- if (options.walMode !== false) {
814
- this.db.pragma("journal_mode = WAL");
815
- }
857
+ this.db = openDatabase(options.path, "SqliteEventStore", {
858
+ busyTimeoutMs: options.busyTimeoutMs,
859
+ walMode: options.walMode !== false
860
+ });
816
861
  this.maxEvents = options.maxEvents ?? 1e4;
817
862
  this.ttlMs = options.ttlMs ?? 3e5;
818
- this.initSchema();
863
+ withBusyRetry(() => this.initSchema());
819
864
  this.prepareStatements();
820
865
  const cleanupInterval = options.ttlCleanupIntervalMs ?? 6e4;
821
866
  if (cleanupInterval > 0) {
@@ -952,9 +997,11 @@ var sqliteStorageOptionsSchema = z.object({
952
997
  secret: z.string().min(1)
953
998
  }).optional(),
954
999
  ttlCleanupIntervalMs: z.number().int().nonnegative().optional().default(6e4),
955
- walMode: z.boolean().optional().default(true)
1000
+ walMode: z.boolean().optional().default(true),
1001
+ busyTimeoutMs: z.number().int().nonnegative().optional().default(5e3)
956
1002
  });
957
1003
  export {
1004
+ SqliteDecryptionError,
958
1005
  SqliteElicitationStore,
959
1006
  SqliteEventStore,
960
1007
  SqliteKvStore,
@@ -966,5 +1013,6 @@ export {
966
1013
  encryptValue,
967
1014
  loadBetterSqlite3,
968
1015
  openDatabase,
969
- sqliteStorageOptionsSchema
1016
+ sqliteStorageOptionsSchema,
1017
+ withBusyRetry
970
1018
  };
package/esm/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/storage-sqlite",
3
- "version": "1.8.6",
3
+ "version": "1.8.7",
4
4
  "description": "SQLite storage backend for FrontMCP - local session, elicitation, and event persistence without Redis",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",
@@ -44,11 +44,11 @@
44
44
  "node": ">=24.0.0"
45
45
  },
46
46
  "dependencies": {
47
- "@frontmcp/utils": "1.8.6",
47
+ "@frontmcp/utils": "1.8.7",
48
48
  "better-sqlite3": "^12.6.2"
49
49
  },
50
50
  "peerDependencies": {
51
- "@frontmcp/lazy-zod": "1.8.6"
51
+ "@frontmcp/lazy-zod": "1.8.7"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/better-sqlite3": "^7.6.13",
package/index.d.ts CHANGED
@@ -6,7 +6,8 @@
6
6
  */
7
7
  export { SqliteKvStore } from './sqlite-kv.store';
8
8
  export { SqliteStorageAdapter } from './sqlite-storage.adapter';
9
- export { openDatabase } from './open-database';
9
+ export { openDatabase, withBusyRetry } from './open-database';
10
+ export type { OpenDatabaseOptions, BusyRetryOptions } from './open-database';
10
11
  export { loadBetterSqlite3 } from './better-sqlite3-loader';
11
12
  export { SqliteSessionStore } from './sqlite-session.store';
12
13
  export type { SqliteSessionStoreOptions, SessionStoreInterface, StoredSessionData } from './sqlite-session.store';
@@ -16,7 +17,7 @@ export { SqliteTaskStore } from './sqlite-task.store';
16
17
  export type { SqliteTaskStoreOptions, TaskStoreInterface, TaskRecord as SqliteTaskRecord, TaskStatus as SqliteTaskStatus, TaskOutcome as SqliteTaskOutcome, TaskListPage as SqliteTaskListPage, ProcessLivenessProbe, SqliteTaskLogger, } from './sqlite-task.store';
17
18
  export { SqliteEventStore } from './sqlite-event.store';
18
19
  export type { SqliteEventStoreOptions, EventStoreInterface } from './sqlite-event.store';
19
- export { deriveEncryptionKey, encryptValue, decryptValue } from './encryption';
20
+ export { deriveEncryptionKey, encryptValue, decryptValue, SqliteDecryptionError } from './encryption';
20
21
  export { sqliteStorageOptionsSchema } from './sqlite.options';
21
22
  export type { SqliteStorageOptions, SqliteStorageOptionsInput, SqliteStorageOptionsParsed } from './sqlite.options';
22
23
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClH,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,YAAY,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC3G,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,YAAY,EACV,sBAAsB,EACtB,kBAAkB,EAClB,UAAU,IAAI,gBAAgB,EAC9B,UAAU,IAAI,gBAAgB,EAC9B,WAAW,IAAI,iBAAiB,EAChC,YAAY,IAAI,kBAAkB,EAClC,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC9D,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClH,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,YAAY,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC3G,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,YAAY,EACV,sBAAsB,EACtB,kBAAkB,EAClB,UAAU,IAAI,gBAAgB,EAC9B,UAAU,IAAI,gBAAgB,EAC9B,WAAW,IAAI,iBAAiB,EAChC,YAAY,IAAI,kBAAkB,EAClC,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACtG,OAAO,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9D,YAAY,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC"}
package/index.js CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // libs/storage-sqlite/src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ SqliteDecryptionError: () => SqliteDecryptionError,
23
24
  SqliteElicitationStore: () => SqliteElicitationStore,
24
25
  SqliteEventStore: () => SqliteEventStore,
25
26
  SqliteKvStore: () => SqliteKvStore,
@@ -31,12 +32,22 @@ __export(index_exports, {
31
32
  encryptValue: () => encryptValue,
32
33
  loadBetterSqlite3: () => loadBetterSqlite3,
33
34
  openDatabase: () => openDatabase,
34
- sqliteStorageOptionsSchema: () => sqliteStorageOptionsSchema
35
+ sqliteStorageOptionsSchema: () => sqliteStorageOptionsSchema,
36
+ withBusyRetry: () => withBusyRetry
35
37
  });
36
38
  module.exports = __toCommonJS(index_exports);
37
39
 
38
40
  // libs/storage-sqlite/src/encryption.ts
39
41
  var import_utils = require("@frontmcp/utils");
42
+ var SqliteDecryptionError = class extends Error {
43
+ code = "SQLITE_DECRYPTION_FAILED";
44
+ constructor() {
45
+ super(
46
+ "SqliteKvStore: failed to decrypt a stored value. The encryption secret differs from the one the database was written with (or the value is corrupted). Restore the original secret, or delete the database file to start empty."
47
+ );
48
+ this.name = "SqliteDecryptionError";
49
+ }
50
+ };
40
51
  var HKDF_SALT = new TextEncoder().encode("frontmcp-sqlite-storage-v1");
41
52
  var HKDF_INFO = new TextEncoder().encode("aes-256-gcm-value-encryption");
42
53
  var KEY_LENGTH = 32;
@@ -59,8 +70,11 @@ function decryptValue(key, encrypted) {
59
70
  const iv = (0, import_utils.base64urlDecode)(parts[0]);
60
71
  const tag = (0, import_utils.base64urlDecode)(parts[1]);
61
72
  const ciphertext = (0, import_utils.base64urlDecode)(parts[2]);
62
- const plaintext = (0, import_utils.decryptAesGcm)(key, ciphertext, iv, tag);
63
- return new TextDecoder().decode(plaintext);
73
+ try {
74
+ return new TextDecoder().decode((0, import_utils.decryptAesGcm)(key, ciphertext, iv, tag));
75
+ } catch {
76
+ throw new SqliteDecryptionError();
77
+ }
64
78
  }
65
79
 
66
80
  // libs/storage-sqlite/src/open-database.ts
@@ -79,7 +93,27 @@ function loadBetterSqlite3() {
79
93
 
80
94
  // libs/storage-sqlite/src/open-database.ts
81
95
  var MEMORY_PATH = ":memory:";
82
- function openDatabase(path, storeName) {
96
+ var DEFAULT_BUSY_TIMEOUT_MS = 5e3;
97
+ function isBusyError(err) {
98
+ const code = err?.code;
99
+ return code === "SQLITE_BUSY" || code === "SQLITE_BUSY_RECOVERY" || code === "SQLITE_BUSY_SNAPSHOT";
100
+ }
101
+ function sleepSync(ms) {
102
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
103
+ }
104
+ function withBusyRetry(operation, options = {}) {
105
+ const attempts = options.attempts ?? 5;
106
+ const delayMs = options.delayMs ?? 50;
107
+ for (let attempt = 1; ; attempt++) {
108
+ try {
109
+ return operation();
110
+ } catch (err) {
111
+ if (!isBusyError(err) || attempt >= attempts) throw err;
112
+ sleepSync(delayMs * attempt);
113
+ }
114
+ }
115
+ }
116
+ function openDatabase(path, storeName, options = {}) {
83
117
  const BetterSqlite3 = loadBetterSqlite3();
84
118
  if (path !== MEMORY_PATH && path !== "") {
85
119
  const dir = (0, import_utils2.dirname)(path);
@@ -88,16 +122,28 @@ function openDatabase(path, storeName) {
88
122
  (0, import_utils2.ensureDirSync)(dir);
89
123
  } catch (err) {
90
124
  const message = err instanceof Error ? err.message : String(err);
91
- throw new Error(`${storeName}: failed to create directory "${dir}" for database "${path}": ${message}`);
125
+ throw new Error(`${storeName}: failed to create directory "${dir}" for database "${path}": ${message}`, {
126
+ cause: err
127
+ });
92
128
  }
93
129
  }
94
130
  }
131
+ let db;
132
+ try {
133
+ db = new BetterSqlite3(path);
134
+ } catch (err) {
135
+ const message = err instanceof Error ? err.message : String(err);
136
+ throw new Error(`${storeName}: failed to open database at "${path}": ${message}`, { cause: err });
137
+ }
95
138
  try {
96
- return new BetterSqlite3(path);
139
+ db.pragma(`busy_timeout = ${Math.max(0, Math.floor(options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS))}`);
140
+ if (options.walMode) withBusyRetry(() => db.pragma("journal_mode = WAL"));
97
141
  } catch (err) {
142
+ db.close();
98
143
  const message = err instanceof Error ? err.message : String(err);
99
- throw new Error(`${storeName}: failed to open database at "${path}": ${message}`);
144
+ throw new Error(`${storeName}: failed to configure database at "${path}": ${message}`, { cause: err });
100
145
  }
146
+ return db;
101
147
  }
102
148
 
103
149
  // libs/storage-sqlite/src/sqlite-kv.store.ts
@@ -107,14 +153,14 @@ var SqliteKvStore = class {
107
153
  cleanupTimer = null;
108
154
  stmts = null;
109
155
  constructor(options) {
110
- this.db = openDatabase(options.path, "SqliteKvStore");
111
- if (options.walMode !== false) {
112
- this.db.pragma("journal_mode = WAL");
113
- }
156
+ this.db = openDatabase(options.path, "SqliteKvStore", {
157
+ busyTimeoutMs: options.busyTimeoutMs,
158
+ walMode: options.walMode !== false
159
+ });
114
160
  if (options.encryption?.secret) {
115
161
  this.encryptionKey = deriveEncryptionKey(options.encryption.secret);
116
162
  }
117
- this.initSchema();
163
+ withBusyRetry(() => this.initSchema());
118
164
  this.prepareStatements();
119
165
  const cleanupInterval = options.ttlCleanupIntervalMs ?? 6e4;
120
166
  if (cleanupInterval > 0) {
@@ -581,17 +627,17 @@ var SqliteTaskStore = class {
581
627
  encryptionKey = null;
582
628
  stmts = null;
583
629
  constructor(options) {
584
- this.db = openDatabase(options.path, "SqliteTaskStore");
585
- if (options.walMode !== false) {
586
- this.db.pragma("journal_mode = WAL");
587
- }
630
+ this.db = openDatabase(options.path, "SqliteTaskStore", {
631
+ busyTimeoutMs: options.busyTimeoutMs,
632
+ walMode: options.walMode !== false
633
+ });
588
634
  this.logger = options.logger;
589
635
  this.liveness = options.livenessProbe ?? defaultLivenessProbe;
590
636
  if (options.encryption?.secret) {
591
637
  this.encryptionKey = deriveEncryptionKey(options.encryption.secret);
592
638
  }
593
639
  this.emitter.setMaxListeners(200);
594
- this.initSchema();
640
+ withBusyRetry(() => this.initSchema());
595
641
  this.prepareStatements();
596
642
  const cleanupInterval = options.ttlCleanupIntervalMs ?? 6e4;
597
643
  if (cleanupInterval > 0) {
@@ -830,13 +876,13 @@ var SqliteEventStore = class {
830
876
  cleanupTimer = null;
831
877
  stmts = null;
832
878
  constructor(options) {
833
- this.db = openDatabase(options.path, "SqliteEventStore");
834
- if (options.walMode !== false) {
835
- this.db.pragma("journal_mode = WAL");
836
- }
879
+ this.db = openDatabase(options.path, "SqliteEventStore", {
880
+ busyTimeoutMs: options.busyTimeoutMs,
881
+ walMode: options.walMode !== false
882
+ });
837
883
  this.maxEvents = options.maxEvents ?? 1e4;
838
884
  this.ttlMs = options.ttlMs ?? 3e5;
839
- this.initSchema();
885
+ withBusyRetry(() => this.initSchema());
840
886
  this.prepareStatements();
841
887
  const cleanupInterval = options.ttlCleanupIntervalMs ?? 6e4;
842
888
  if (cleanupInterval > 0) {
@@ -973,10 +1019,12 @@ var sqliteStorageOptionsSchema = import_lazy_zod.z.object({
973
1019
  secret: import_lazy_zod.z.string().min(1)
974
1020
  }).optional(),
975
1021
  ttlCleanupIntervalMs: import_lazy_zod.z.number().int().nonnegative().optional().default(6e4),
976
- walMode: import_lazy_zod.z.boolean().optional().default(true)
1022
+ walMode: import_lazy_zod.z.boolean().optional().default(true),
1023
+ busyTimeoutMs: import_lazy_zod.z.number().int().nonnegative().optional().default(5e3)
977
1024
  });
978
1025
  // Annotate the CommonJS export names for ESM import in node:
979
1026
  0 && (module.exports = {
1027
+ SqliteDecryptionError,
980
1028
  SqliteElicitationStore,
981
1029
  SqliteEventStore,
982
1030
  SqliteKvStore,
@@ -988,5 +1036,6 @@ var sqliteStorageOptionsSchema = import_lazy_zod.z.object({
988
1036
  encryptValue,
989
1037
  loadBetterSqlite3,
990
1038
  openDatabase,
991
- sqliteStorageOptionsSchema
1039
+ sqliteStorageOptionsSchema,
1040
+ withBusyRetry
992
1041
  });
@@ -12,14 +12,33 @@
12
12
  * 2. **ESM-safe native module load.** See {@link loadBetterSqlite3}.
13
13
  */
14
14
  import type Database from 'better-sqlite3';
15
+ /** How long a connection waits on another process's lock before SQLITE_BUSY. */
16
+ export declare const DEFAULT_BUSY_TIMEOUT_MS = 5000;
17
+ export interface OpenDatabaseOptions {
18
+ /** Milliseconds to wait for a lock held by another connection or process. @default 5000 */
19
+ busyTimeoutMs?: number;
20
+ /** Switch the database to WAL journaling. @default false */
21
+ walMode?: boolean;
22
+ }
23
+ export interface BusyRetryOptions {
24
+ attempts?: number;
25
+ delayMs?: number;
26
+ }
27
+ /**
28
+ * Run a synchronous SQLite operation, retrying while it reports `SQLITE_BUSY`.
29
+ * `busy_timeout` covers ordinary lock waits; a few statements (the WAL switch,
30
+ * schema changes racing another process's first open) can still fail fast.
31
+ */
32
+ export declare function withBusyRetry<T>(operation: () => T, options?: BusyRetryOptions): T;
15
33
  /**
16
34
  * Open (or create) a better-sqlite3 database at `path`, creating the parent
17
35
  * directory if necessary.
18
36
  *
19
37
  * @param path - Filesystem path to the `.sqlite` file, or `:memory:`.
20
38
  * @param storeName - Name used in error messages (e.g. `'SqliteKvStore'`).
39
+ * @param options - `busyTimeoutMs` (set before anything else touches the file) and `walMode`.
21
40
  * @returns An open better-sqlite3 `Database` instance.
22
41
  * @throws Error wrapping the underlying failure with the store name and path.
23
42
  */
24
- export declare function openDatabase(path: string, storeName: string): Database.Database;
43
+ export declare function openDatabase(path: string, storeName: string, options?: OpenDatabaseOptions): Database.Database;
25
44
  //# sourceMappingURL=open-database.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"open-database.d.ts","sourceRoot":"","sources":["../src/open-database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAS3C;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAwB/E"}
1
+ {"version":3,"file":"open-database.d.ts","sourceRoot":"","sources":["../src/open-database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAS3C,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,MAAM,WAAW,mBAAmB;IAClC,2FAA2F;IAC3F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAWD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,GAAE,gBAAqB,GAAG,CAAC,CAWtF;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,QAAQ,CAAC,QAAQ,CAuClH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frontmcp/storage-sqlite",
3
- "version": "1.8.6",
3
+ "version": "1.8.7",
4
4
  "description": "SQLite storage backend for FrontMCP - local session, elicitation, and event persistence without Redis",
5
5
  "author": "AgentFront <info@agentfront.dev>",
6
6
  "homepage": "https://docs.agentfront.dev",
@@ -44,11 +44,11 @@
44
44
  "node": ">=24.0.0"
45
45
  },
46
46
  "dependencies": {
47
- "@frontmcp/utils": "1.8.6",
47
+ "@frontmcp/utils": "1.8.7",
48
48
  "better-sqlite3": "^12.6.2"
49
49
  },
50
50
  "peerDependencies": {
51
- "@frontmcp/lazy-zod": "1.8.6"
51
+ "@frontmcp/lazy-zod": "1.8.7"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/better-sqlite3": "^7.6.13",
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-event.store.d.ts","sourceRoot":"","sources":["../src/sqlite-event.store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,iBAAiB,CACf,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GACxE,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB;;;;OAIG;IACH,qBAAqB,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAiB,YAAW,mBAAmB;IAC1D,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,KAAK,CAAmC;gBAEpC,OAAO,EAAE,uBAAuB;IAwB5C,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,iBAAiB;IAgBzB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAOhB;;OAEG;IACH,OAAO,CAAC,cAAc;IAmBhB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB/D,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKnE,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GACvE,OAAO,CAAC,MAAM,CAAC;IAyBlB,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,WAAW,IAAI,QAAQ,CAAC,QAAQ;IAIhC;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAIjB;CACF"}
1
+ {"version":3,"file":"sqlite-event.store.d.ts","sourceRoot":"","sources":["../src/sqlite-event.store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,iBAAiB,CACf,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GACxE,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB;;;;OAIG;IACH,qBAAqB,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD;;;;;;;;;;;;GAYG;AACH,qBAAa,gBAAiB,YAAW,mBAAmB;IAC1D,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,KAAK,CAAmC;gBAEpC,OAAO,EAAE,uBAAuB;IAuB5C,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,iBAAiB;IAgBzB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAOhB;;OAEG;IACH,OAAO,CAAC,cAAc;IAmBhB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB/D,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKnE,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GACvE,OAAO,CAAC,MAAM,CAAC;IAyBlB,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,WAAW,IAAI,QAAQ,CAAC,QAAQ;IAIhC;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAIjB;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-kv.store.d.ts","sourceRoot":"","sources":["../src/sqlite-kv.store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAI3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAe7D;;;;;;;;;;;GAWG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,aAAa,CAA2B;IAChD,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,KAAK,CAAqC;gBAEtC,OAAO,EAAE,oBAAoB;IA4BzC,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAOhB;;;OAGG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAmB/B;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAW3C;;;;;;OAMG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IASrD;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAI1D;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAItB;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAKzB;;;;;;OAMG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAchC;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAM3C;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAexB;;;OAGG;IACH,YAAY,IAAI,MAAM;IAKtB;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,WAAW,IAAI,QAAQ,CAAC,QAAQ;CAGjC"}
1
+ {"version":3,"file":"sqlite-kv.store.d.ts","sourceRoot":"","sources":["../src/sqlite-kv.store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAI3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAe7D;;;;;;;;;;;GAWG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,aAAa,CAA2B;IAChD,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,KAAK,CAAqC;gBAEtC,OAAO,EAAE,oBAAoB;IA0BzC,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAOhB;;;OAGG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAmB/B;;OAEG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAW3C;;;;;;OAMG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IASrD;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAI1D;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAItB;;OAEG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAKzB;;;;;;OAMG;IACH,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAchC;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAM3C;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAexB;;;OAGG;IACH,YAAY,IAAI,MAAM;IAKtB;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,WAAW,IAAI,QAAQ,CAAC,QAAQ;CAGjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite-task.store.d.ts","sourceRoot":"","sources":["../src/sqlite-task.store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite-task.store.d.ts","sourceRoot":"","sources":["../src/sqlite-task.store.ts"],"names":[],"mappings":"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"}
@@ -28,6 +28,12 @@ export interface SqliteStorageOptions {
28
28
  * @default true
29
29
  */
30
30
  walMode?: boolean;
31
+ /**
32
+ * Milliseconds a connection waits for a lock held by another process before
33
+ * failing with SQLITE_BUSY.
34
+ * @default 5000
35
+ */
36
+ busyTimeoutMs?: number;
31
37
  }
32
38
  /**
33
39
  * Zod schema for SQLite storage configuration.
@@ -39,6 +45,7 @@ export declare const sqliteStorageOptionsSchema: import("@frontmcp/lazy-zod").Zo
39
45
  }, import("zod/v4/core").$strip>>;
40
46
  ttlCleanupIntervalMs: import("@frontmcp/lazy-zod").ZodDefault<import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodNumber>>;
41
47
  walMode: import("@frontmcp/lazy-zod").ZodDefault<import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodBoolean>>;
48
+ busyTimeoutMs: import("@frontmcp/lazy-zod").ZodDefault<import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodNumber>>;
42
49
  }, import("zod/v4/core").$strip>;
43
50
  /**
44
51
  * SQLite storage input type (before Zod defaults).
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.options.d.ts","sourceRoot":"","sources":["../src/sqlite.options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,UAAU,CAAC,EAAE;QACX,qEAAqE;QACrE,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IAEF;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;gCASrC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEnF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
1
+ {"version":3,"file":"sqlite.options.d.ts","sourceRoot":"","sources":["../src/sqlite.options.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,UAAU,CAAC,EAAE;QACX,qEAAqE;QACrE,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IAEF;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;gCAUrC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEnF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}