mcard-js 2.1.39 → 2.1.41

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.
Files changed (40) hide show
  1. package/dist/AbstractSqlEngine-BSfp8S_Y.d.cts +451 -0
  2. package/dist/AbstractSqlEngine-BSfp8S_Y.d.ts +451 -0
  3. package/dist/CardCollection-MXTUJV4J.js +9 -0
  4. package/dist/EventProducer-AWD6YMZR.js +47 -0
  5. package/dist/Handle-3N4QOA3U.js +13 -0
  6. package/dist/IndexedDBEngine-2G5KCISA.js +11 -0
  7. package/dist/LLMRuntime-LBWUJ7ON.js +16 -0
  8. package/dist/LambdaRuntime-B6D6IQKZ.js +18 -0
  9. package/dist/Loader-3LSJXJQG.js +11 -0
  10. package/dist/MCard-H56VOJLR.js +8 -0
  11. package/dist/NetworkRuntime-IAFHPQSX.js +1570 -0
  12. package/dist/OllamaProvider-QPX2JXL2.js +8 -0
  13. package/dist/chunk-2R4ESMZB.js +110 -0
  14. package/dist/chunk-3EIBJPNF.js +17 -0
  15. package/dist/chunk-3LPY36OG.js +355 -0
  16. package/dist/chunk-3MMMJ7NH.js +1068 -0
  17. package/dist/chunk-42VF42KH.js +273 -0
  18. package/dist/chunk-4PDYHPR6.js +297 -0
  19. package/dist/chunk-ADV52544.js +95 -0
  20. package/dist/chunk-FIE4LAJG.js +215 -0
  21. package/dist/chunk-PNKVD2UK.js +26 -0
  22. package/dist/chunk-RSTKX7WM.js +907 -0
  23. package/dist/chunk-VXV35I5J.js +2315 -0
  24. package/dist/index.browser.cjs +375 -276
  25. package/dist/index.browser.d.cts +4 -4
  26. package/dist/index.browser.d.ts +4 -4
  27. package/dist/index.browser.js +18 -13
  28. package/dist/index.cjs +382 -453
  29. package/dist/index.d.cts +2 -2
  30. package/dist/index.d.ts +2 -2
  31. package/dist/index.js +26 -21
  32. package/dist/storage/SqliteNodeEngine.cjs +395 -270
  33. package/dist/storage/SqliteNodeEngine.d.cts +9 -94
  34. package/dist/storage/SqliteNodeEngine.d.ts +9 -94
  35. package/dist/storage/SqliteNodeEngine.js +6 -5
  36. package/dist/storage/SqliteWasmEngine.cjs +382 -252
  37. package/dist/storage/SqliteWasmEngine.d.cts +8 -29
  38. package/dist/storage/SqliteWasmEngine.d.ts +8 -29
  39. package/dist/storage/SqliteWasmEngine.js +6 -5
  40. package/package.json +1 -1
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -27,6 +30,90 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
30
  ));
28
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
32
 
33
+ // src/model/Handle.ts
34
+ var Handle_exports = {};
35
+ __export(Handle_exports, {
36
+ ContentHandle: () => ContentHandle,
37
+ HandleValidationError: () => HandleValidationError,
38
+ validateHandle: () => validateHandle
39
+ });
40
+ function isValidStartChar(char) {
41
+ return /^\p{L}$/u.test(char);
42
+ }
43
+ function isValidBodyChar(char) {
44
+ return /^[\p{L}\p{N}_./ -]$/u.test(char);
45
+ }
46
+ function validateHandle(handle) {
47
+ if (!handle) {
48
+ throw new HandleValidationError("Handle cannot be empty.");
49
+ }
50
+ const normalized = handle.trim().normalize("NFC");
51
+ if (normalized.length === 0) {
52
+ throw new HandleValidationError("Handle cannot be empty after normalization.");
53
+ }
54
+ if (normalized.length > MAX_HANDLE_LENGTH) {
55
+ throw new HandleValidationError(
56
+ `Handle '${handle}' is too long (${normalized.length} chars). Maximum is ${MAX_HANDLE_LENGTH}.`
57
+ );
58
+ }
59
+ if (!isValidStartChar(normalized[0])) {
60
+ throw new HandleValidationError(
61
+ `Invalid handle '${handle}'. Must start with a letter (any language).`
62
+ );
63
+ }
64
+ for (let i = 1; i < normalized.length; i++) {
65
+ if (!isValidBodyChar(normalized[i])) {
66
+ throw new HandleValidationError(
67
+ `Invalid character '${normalized[i]}' at position ${i} in handle '${handle}'.`
68
+ );
69
+ }
70
+ }
71
+ return normalized;
72
+ }
73
+ var MAX_HANDLE_LENGTH, HandleValidationError, ContentHandle;
74
+ var init_Handle = __esm({
75
+ "src/model/Handle.ts"() {
76
+ "use strict";
77
+ MAX_HANDLE_LENGTH = 255;
78
+ HandleValidationError = class extends Error {
79
+ constructor(message) {
80
+ super(message);
81
+ this.name = "HandleValidationError";
82
+ }
83
+ };
84
+ ContentHandle = class {
85
+ handle;
86
+ currentHash;
87
+ createdAt;
88
+ updatedAt;
89
+ constructor(handle, currentHash, createdAt, updatedAt) {
90
+ this.handle = validateHandle(handle);
91
+ this.currentHash = currentHash;
92
+ this.createdAt = createdAt ?? /* @__PURE__ */ new Date();
93
+ this.updatedAt = updatedAt ?? this.createdAt;
94
+ }
95
+ /**
96
+ * Update handle to point to new hash
97
+ * @returns Previous hash for history tracking
98
+ */
99
+ update(newHash) {
100
+ const previousHash = this.currentHash;
101
+ this.currentHash = newHash;
102
+ this.updatedAt = /* @__PURE__ */ new Date();
103
+ return previousHash;
104
+ }
105
+ toObject() {
106
+ return {
107
+ handle: this.handle,
108
+ currentHash: this.currentHash,
109
+ createdAt: this.createdAt.toISOString(),
110
+ updatedAt: this.updatedAt.toISOString()
111
+ };
112
+ }
113
+ };
114
+ }
115
+ });
116
+
30
117
  // src/storage/SqliteWasmEngine.ts
31
118
  var SqliteWasmEngine_exports = {};
32
119
  __export(SqliteWasmEngine_exports, {
@@ -905,6 +992,16 @@ var mime_extensions_default = {
905
992
  }
906
993
  };
907
994
 
995
+ // src/config/constants.ts
996
+ var DEFAULT_PAGE_SIZE = 10;
997
+ var DETECTION_SAMPLE_CAP = 8192;
998
+ var MAX_FILE_SIZE = 50 * 1024 * 1024;
999
+ var KNOWN_TYPE_SIZE_LIMIT = 1024 * 1024;
1000
+ var BINARY_CHECK_SAMPLE_SIZE = 32 * 1024;
1001
+ var CONTENT_DETECTION_SAMPLE_SIZE = 1024 * 1024;
1002
+ var DEFAULT_MAX_PROBLEM_BYTES = 2 * 1024 * 1024;
1003
+ var DEFAULT_SQLJS_WASM_URL = "https://sql.js.org/dist/";
1004
+
908
1005
  // src/model/strategies/DetectionStrategy.ts
909
1006
  function loadSharedMimeData() {
910
1007
  return {
@@ -937,7 +1034,7 @@ var DefaultDetectionStrategy = class _DefaultDetectionStrategy {
937
1034
  return this.extensionsRegistry[mimeType] || "";
938
1035
  }
939
1036
  detect(content, fileExtension) {
940
- const contentSample = typeof content === "string" ? content.slice(0, 8192) : content.slice(0, 8192);
1037
+ const contentSample = typeof content === "string" ? content.slice(0, DETECTION_SAMPLE_CAP) : content.slice(0, DETECTION_SAMPLE_CAP);
941
1038
  const textSample = this.getTextSample(contentSample);
942
1039
  const lines = textSample.split("\n").slice(0, 20);
943
1040
  const firstLine = lines[0] || "";
@@ -971,9 +1068,9 @@ var DefaultDetectionStrategy = class _DefaultDetectionStrategy {
971
1068
  }
972
1069
  getTextSample(content) {
973
1070
  if (typeof content === "string") {
974
- return content.slice(0, 8192);
1071
+ return content.slice(0, DETECTION_SAMPLE_CAP);
975
1072
  }
976
- return new TextDecoder("utf-8", { fatal: false }).decode(content.slice(0, 8192));
1073
+ return new TextDecoder("utf-8", { fatal: false }).decode(content.slice(0, DETECTION_SAMPLE_CAP));
977
1074
  }
978
1075
  getExtension(mimeType) {
979
1076
  return _DefaultDetectionStrategy.getExtension(mimeType);
@@ -1191,62 +1288,6 @@ var MCard = class _MCard {
1191
1288
  }
1192
1289
  };
1193
1290
 
1194
- // src/model/Handle.ts
1195
- var MAX_HANDLE_LENGTH = 255;
1196
- function isValidStartChar(char) {
1197
- return /^\p{L}$/u.test(char);
1198
- }
1199
- function isValidBodyChar(char) {
1200
- return /^[\p{L}\p{N}_./ -]$/u.test(char);
1201
- }
1202
- var HandleValidationError = class extends Error {
1203
- constructor(message) {
1204
- super(message);
1205
- this.name = "HandleValidationError";
1206
- }
1207
- };
1208
- function validateHandle(handle) {
1209
- if (!handle) {
1210
- throw new HandleValidationError("Handle cannot be empty.");
1211
- }
1212
- const normalized = handle.trim().normalize("NFC").toLowerCase();
1213
- if (normalized.length === 0) {
1214
- throw new HandleValidationError("Handle cannot be empty after normalization.");
1215
- }
1216
- if (normalized.length > MAX_HANDLE_LENGTH) {
1217
- throw new HandleValidationError(
1218
- `Handle '${handle}' is too long (${normalized.length} chars). Maximum is ${MAX_HANDLE_LENGTH}.`
1219
- );
1220
- }
1221
- if (!isValidStartChar(normalized[0])) {
1222
- throw new HandleValidationError(
1223
- `Invalid handle '${handle}'. Must start with a letter (any language).`
1224
- );
1225
- }
1226
- for (let i = 1; i < normalized.length; i++) {
1227
- if (!isValidBodyChar(normalized[i])) {
1228
- throw new HandleValidationError(
1229
- `Invalid character '${normalized[i]}' at position ${i} in handle '${handle}'.`
1230
- );
1231
- }
1232
- }
1233
- return normalized;
1234
- }
1235
-
1236
- // src/storage/StorageAdapter.ts
1237
- function createPage(items, totalItems, pageNumber, pageSize) {
1238
- const totalPages = Math.ceil(totalItems / pageSize) || 1;
1239
- return {
1240
- items,
1241
- totalItems,
1242
- pageNumber,
1243
- pageSize,
1244
- totalPages,
1245
- hasNext: totalItems > (pageNumber - 1) * pageSize + items.length,
1246
- hasPrevious: pageNumber > 1
1247
- };
1248
- }
1249
-
1250
1291
  // src/storage/schema_constants.ts
1251
1292
  var MCARD_SCHEMA_SQL = `-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
1252
1293
  -- MCard Unified Database Schema (Monadic Core)
@@ -1880,159 +1921,145 @@ var CORE_SCHEMAS = {
1880
1921
  handleIndex: HANDLE_INDEX_SCHEMA
1881
1922
  };
1882
1923
 
1883
- // src/storage/engines/SqliteWasmEngine.ts
1884
- var SqliteWasmEngine = class {
1885
- db = null;
1886
- SQL = null;
1887
- /**
1888
- * Initialize the database
1889
- * @param wasmUrl URL to sql-wasm.wasm file (optional, defaults to CDN)
1890
- * @param existingData Optional existing database as Uint8Array
1891
- */
1892
- async init(wasmUrl, existingData) {
1893
- const initSqlJs = (await import("sql.js")).default;
1894
- const SQL = await initSqlJs({
1895
- locateFile: (file) => wasmUrl || `https://sql.js.org/dist/${file}`
1896
- });
1897
- this.SQL = SQL;
1898
- this.db = existingData ? new SQL.Database(existingData) : new SQL.Database();
1899
- this.db.run(CORE_SCHEMAS.card);
1900
- this.db.run(CORE_SCHEMAS.handleRegistry);
1901
- this.db.run(CORE_SCHEMAS.handleHistory);
1902
- this.db.run(CORE_SCHEMAS.handleIndex);
1903
- }
1904
- ensureDb() {
1905
- if (!this.db) throw new Error("Database not initialized. Call init() first.");
1906
- return this.db;
1907
- }
1924
+ // src/storage/engines/AbstractSqlEngine.ts
1925
+ init_Handle();
1926
+
1927
+ // src/storage/StorageAdapter.ts
1928
+ function createPage(items, totalItems, pageNumber, pageSize) {
1929
+ const totalPages = Math.ceil(totalItems / pageSize) || 1;
1930
+ return {
1931
+ items,
1932
+ totalItems,
1933
+ pageNumber,
1934
+ pageSize,
1935
+ totalPages,
1936
+ hasNext: totalItems > (pageNumber - 1) * pageSize + items.length,
1937
+ hasPrevious: pageNumber > 1
1938
+ };
1939
+ }
1940
+
1941
+ // src/storage/engines/AbstractSqlEngine.ts
1942
+ var AbstractSqlEngine = class {
1908
1943
  /**
1909
- * Export database as Uint8Array (for persistence)
1944
+ * SQL expression for casting content to text in search queries.
1945
+ * Override in subclasses: SQLite uses 'TEXT', DuckDB uses 'VARCHAR'.
1910
1946
  */
1911
- export() {
1912
- return this.ensureDb().export();
1947
+ get castContentAs() {
1948
+ return "TEXT";
1913
1949
  }
1950
+ // ======================================================================
1951
+ // Concrete: Card Operations (shared across all SQL engines)
1952
+ // ======================================================================
1914
1953
  /**
1915
- * Get raw sql.js Database for use with VectorStore adapter.
1916
- *
1917
- * Example:
1918
- * const vecStore = createWasmVectorStore(engine.getRawDb());
1954
+ * Add a card. Default uses INSERT OR REPLACE (SQLite).
1955
+ * DuckDB overrides with DELETE + INSERT.
1919
1956
  */
1920
- getRawDb() {
1921
- return this.ensureDb();
1922
- }
1923
- // =========== Card Operations ===========
1924
1957
  async add(card) {
1925
- const db = this.ensureDb();
1926
- db.run(
1958
+ const contentBytes = card.content instanceof Uint8Array ? card.content : new TextEncoder().encode(String(card.content));
1959
+ await this.execSql(
1927
1960
  "INSERT OR REPLACE INTO card (hash, content, g_time) VALUES (?, ?, ?)",
1928
- [card.hash, card.content, card.g_time]
1961
+ card.hash,
1962
+ contentBytes,
1963
+ card.g_time
1929
1964
  );
1930
1965
  return card.hash;
1931
1966
  }
1932
1967
  async get(hash) {
1933
- const db = this.ensureDb();
1934
- const stmt = db.prepare("SELECT hash, content, g_time FROM card WHERE hash = ?");
1935
- stmt.bind([hash]);
1936
- if (!stmt.step()) {
1937
- stmt.free();
1938
- return null;
1939
- }
1940
- const row = stmt.get();
1941
- stmt.free();
1942
- return MCard.fromData(new Uint8Array(row[1]), row[0], row[2]);
1968
+ const rows = await this.queryRows(
1969
+ "SELECT hash, content, g_time FROM card WHERE hash = ?",
1970
+ hash
1971
+ );
1972
+ if (rows.length === 0) return null;
1973
+ return this.rowToCard(rows[0]);
1943
1974
  }
1944
1975
  async delete(hash) {
1945
- this.ensureDb().run("DELETE FROM card WHERE hash = ?", [hash]);
1976
+ await this.execSql("DELETE FROM card WHERE hash = ?", hash);
1946
1977
  }
1947
- async getPage(pageNumber, pageSize) {
1948
- const db = this.ensureDb();
1978
+ async getPage(pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
1979
+ if (pageNumber < 1) throw new Error("Page number must be >= 1");
1980
+ if (pageSize < 1) throw new Error("Page size must be >= 1");
1949
1981
  const totalItems = await this.count();
1950
1982
  const offset = (pageNumber - 1) * pageSize;
1951
- const stmt = db.prepare("SELECT hash, content, g_time FROM card LIMIT ? OFFSET ?");
1952
- stmt.bind([pageSize, offset]);
1953
- const items = [];
1954
- while (stmt.step()) {
1955
- const row = stmt.get();
1956
- items.push(MCard.fromData(new Uint8Array(row[1]), row[0], row[2]));
1957
- }
1958
- stmt.free();
1983
+ const rows = await this.queryRows(
1984
+ "SELECT hash, content, g_time FROM card ORDER BY g_time DESC LIMIT ? OFFSET ?",
1985
+ pageSize,
1986
+ offset
1987
+ );
1988
+ const items = rows.map((r) => this.rowToCard(r));
1959
1989
  return createPage(items, totalItems, pageNumber, pageSize);
1960
1990
  }
1961
1991
  async count() {
1962
- const result = this.ensureDb().exec("SELECT COUNT(*) FROM card");
1963
- return result[0]?.values[0]?.[0] || 0;
1992
+ const rows = await this.queryRows("SELECT COUNT(*) as cnt FROM card");
1993
+ return Number(rows[0]?.cnt ?? 0);
1964
1994
  }
1965
1995
  async searchByHash(hashPrefix) {
1966
- const db = this.ensureDb();
1967
- const stmt = db.prepare("SELECT hash, content, g_time FROM card WHERE hash LIKE ?");
1968
- stmt.bind([`${hashPrefix}%`]);
1969
- const items = [];
1970
- while (stmt.step()) {
1971
- const row = stmt.get();
1972
- items.push(MCard.fromData(new Uint8Array(row[1]), row[0], row[2]));
1973
- }
1974
- stmt.free();
1975
- return items;
1996
+ const rows = await this.queryRows(
1997
+ "SELECT hash, content, g_time FROM card WHERE hash LIKE ?",
1998
+ `${hashPrefix}%`
1999
+ );
2000
+ return rows.map((r) => this.rowToCard(r));
1976
2001
  }
1977
- async search(query, pageNumber, pageSize) {
1978
- const db = this.ensureDb();
2002
+ async search(queryStr, pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
2003
+ if (pageNumber < 1) throw new Error("Page number must be >= 1");
2004
+ if (pageSize < 1) throw new Error("Page size must be >= 1");
1979
2005
  const offset = (pageNumber - 1) * pageSize;
1980
- const pattern = `%${query}%`;
1981
- let stmt = db.prepare("SELECT COUNT(*) FROM card WHERE CAST(content AS TEXT) LIKE ?");
1982
- stmt.bind([pattern]);
1983
- stmt.step();
1984
- const totalItems = stmt.get()[0];
1985
- stmt.free();
1986
- stmt = db.prepare("SELECT hash, content, g_time FROM card WHERE CAST(content AS TEXT) LIKE ? LIMIT ? OFFSET ?");
1987
- stmt.bind([pattern, pageSize, offset]);
1988
- const items = [];
1989
- while (stmt.step()) {
1990
- const row = stmt.get();
1991
- items.push(MCard.fromData(new Uint8Array(row[1]), row[0], row[2]));
1992
- }
1993
- stmt.free();
2006
+ const pattern = `%${queryStr}%`;
2007
+ const cast = this.castContentAs;
2008
+ const countRows = await this.queryRows(
2009
+ `SELECT COUNT(*) as cnt FROM card WHERE CAST(content AS ${cast}) LIKE ?`,
2010
+ pattern
2011
+ );
2012
+ const totalItems = Number(countRows[0]?.cnt ?? 0);
2013
+ const rows = await this.queryRows(
2014
+ `SELECT hash, content, g_time FROM card WHERE CAST(content AS ${cast}) LIKE ? ORDER BY g_time DESC LIMIT ? OFFSET ?`,
2015
+ pattern,
2016
+ pageSize,
2017
+ offset
2018
+ );
2019
+ const items = rows.map((r) => this.rowToCard(r));
1994
2020
  return createPage(items, totalItems, pageNumber, pageSize);
1995
2021
  }
1996
2022
  async getAll() {
1997
- const result = this.ensureDb().exec("SELECT hash, content, g_time FROM card");
1998
- return (result[0]?.values || []).map(
1999
- ([h, content, g_time]) => MCard.fromData(new Uint8Array(content), h, g_time)
2000
- );
2023
+ const rows = await this.queryRows("SELECT hash, content, g_time FROM card ORDER BY g_time DESC");
2024
+ return rows.map((r) => this.rowToCard(r));
2001
2025
  }
2026
+ // ======================================================================
2027
+ // Concrete: clear (FK-safe delete order)
2028
+ // ======================================================================
2002
2029
  async clear() {
2003
- const db = this.ensureDb();
2004
- db.run("DELETE FROM card");
2005
- db.run("DELETE FROM handle_registry");
2006
- db.run("DELETE FROM handle_history");
2030
+ await this.execSql("DELETE FROM handle_history");
2031
+ await this.execSql("DELETE FROM handle_registry");
2032
+ await this.execSql("DELETE FROM card");
2007
2033
  }
2008
- // =========== Handle Operations ===========
2034
+ // ======================================================================
2035
+ // Concrete: Handle Operations
2036
+ // ======================================================================
2009
2037
  async registerHandle(handle, hash) {
2010
- const db = this.ensureDb();
2011
2038
  const normalized = validateHandle(handle);
2012
- const checkStmt = db.prepare("SELECT handle FROM handle_registry WHERE handle = ?");
2013
- checkStmt.bind([normalized]);
2014
- const exists = checkStmt.step();
2015
- checkStmt.free();
2016
- if (exists) {
2039
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2040
+ const existing = await this.queryRows(
2041
+ "SELECT handle FROM handle_registry WHERE handle = ?",
2042
+ normalized
2043
+ );
2044
+ if (existing.length > 0) {
2017
2045
  throw new Error(`Handle '${handle}' already exists.`);
2018
2046
  }
2019
- const now = (/* @__PURE__ */ new Date()).toISOString();
2020
- db.run(
2047
+ await this.execSql(
2021
2048
  "INSERT INTO handle_registry (handle, current_hash, created_at, updated_at) VALUES (?, ?, ?, ?)",
2022
- [normalized, hash, now, now]
2049
+ normalized,
2050
+ hash,
2051
+ now,
2052
+ now
2023
2053
  );
2024
2054
  }
2025
2055
  async resolveHandle(handle) {
2026
2056
  const normalized = validateHandle(handle);
2027
- const stmt = this.ensureDb().prepare("SELECT current_hash FROM handle_registry WHERE handle = ?");
2028
- stmt.bind([normalized]);
2029
- if (!stmt.step()) {
2030
- stmt.free();
2031
- return null;
2032
- }
2033
- const hash = stmt.get()[0];
2034
- stmt.free();
2035
- return hash || null;
2057
+ const rows = await this.queryRows(
2058
+ "SELECT current_hash FROM handle_registry WHERE handle = ?",
2059
+ normalized
2060
+ );
2061
+ if (rows.length === 0) return null;
2062
+ return String(rows[0].current_hash);
2036
2063
  }
2037
2064
  async getByHandle(handle) {
2038
2065
  const hash = await this.resolveHandle(handle);
@@ -2040,42 +2067,206 @@ var SqliteWasmEngine = class {
2040
2067
  return this.get(hash);
2041
2068
  }
2042
2069
  async updateHandle(handle, newHash) {
2043
- const db = this.ensureDb();
2044
2070
  const normalized = validateHandle(handle);
2045
- const getStmt = db.prepare("SELECT current_hash FROM handle_registry WHERE handle = ?");
2046
- getStmt.bind([normalized]);
2047
- if (!getStmt.step()) {
2048
- getStmt.free();
2071
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2072
+ const rows = await this.queryRows(
2073
+ "SELECT current_hash FROM handle_registry WHERE handle = ?",
2074
+ normalized
2075
+ );
2076
+ if (rows.length === 0) {
2049
2077
  throw new Error(`Handle '${handle}' not found.`);
2050
2078
  }
2051
- const previousHash = getStmt.get()[0];
2052
- getStmt.free();
2053
- const now = (/* @__PURE__ */ new Date()).toISOString();
2054
- db.run(
2079
+ const previousHash = String(rows[0].current_hash);
2080
+ await this.execSql(
2055
2081
  "INSERT INTO handle_history (handle, previous_hash, changed_at) VALUES (?, ?, ?)",
2056
- [normalized, previousHash, now]
2082
+ normalized,
2083
+ previousHash,
2084
+ now
2057
2085
  );
2058
- db.run(
2086
+ await this.execSql(
2059
2087
  "UPDATE handle_registry SET current_hash = ?, updated_at = ? WHERE handle = ?",
2060
- [newHash, now, normalized]
2088
+ newHash,
2089
+ now,
2090
+ normalized
2061
2091
  );
2062
2092
  return previousHash;
2063
2093
  }
2064
2094
  async getHandleHistory(handle) {
2065
2095
  const normalized = validateHandle(handle);
2066
- const stmt = this.ensureDb().prepare("SELECT previous_hash, changed_at FROM handle_history WHERE handle = ? ORDER BY id DESC");
2067
- stmt.bind([normalized]);
2096
+ const rows = await this.queryRows(
2097
+ "SELECT previous_hash, changed_at FROM handle_history WHERE handle = ? ORDER BY id DESC",
2098
+ normalized
2099
+ );
2100
+ return rows.map((r) => ({
2101
+ previousHash: String(r.previous_hash),
2102
+ changedAt: String(r.changed_at)
2103
+ }));
2104
+ }
2105
+ async pruneHandleHistory(handle, options = {}) {
2106
+ const normalized = validateHandle(handle);
2107
+ if (options.deleteAll) {
2108
+ return this.execSql("DELETE FROM handle_history WHERE handle = ?", normalized);
2109
+ } else if (options.olderThan) {
2110
+ return this.execSql(
2111
+ "DELETE FROM handle_history WHERE handle = ? AND changed_at < ?",
2112
+ normalized,
2113
+ options.olderThan
2114
+ );
2115
+ }
2116
+ return 0;
2117
+ }
2118
+ // ======================================================================
2119
+ // Concrete: Handle Management Operations
2120
+ // ======================================================================
2121
+ async getAllHandles() {
2122
+ const rows = await this.queryRows("SELECT handle, current_hash FROM handle_registry");
2123
+ return rows.map((r) => ({
2124
+ handle: String(r.handle),
2125
+ hash: String(r.current_hash)
2126
+ }));
2127
+ }
2128
+ async removeHandle(handle) {
2129
+ const normalized = validateHandle(handle);
2130
+ await this.execSql("DELETE FROM handle_history WHERE handle = ?", normalized);
2131
+ await this.execSql("DELETE FROM handle_registry WHERE handle = ?", normalized);
2132
+ }
2133
+ async renameHandle(oldHandle, newHandle) {
2134
+ const normalizedOld = validateHandle(oldHandle);
2135
+ const normalizedNew = validateHandle(newHandle);
2136
+ if (normalizedOld === normalizedNew) return;
2137
+ const existsOld = await this.queryRows(
2138
+ "SELECT handle FROM handle_registry WHERE handle = ?",
2139
+ normalizedOld
2140
+ );
2141
+ if (existsOld.length === 0) throw new Error(`Handle '${oldHandle}' not found.`);
2142
+ const existsNew = await this.queryRows(
2143
+ "SELECT handle FROM handle_registry WHERE handle = ?",
2144
+ normalizedNew
2145
+ );
2146
+ if (existsNew.length > 0) throw new Error(`Handle '${newHandle}' already exists.`);
2147
+ const oldRow = await this.queryRows(
2148
+ "SELECT current_hash, created_at, updated_at FROM handle_registry WHERE handle = ?",
2149
+ normalizedOld
2150
+ );
2151
+ await this.execSql(
2152
+ "INSERT INTO handle_registry (handle, current_hash, created_at, updated_at) VALUES (?, ?, ?, ?)",
2153
+ normalizedNew,
2154
+ String(oldRow[0].current_hash),
2155
+ String(oldRow[0].created_at),
2156
+ String(oldRow[0].updated_at)
2157
+ );
2158
+ await this.execSql(
2159
+ "UPDATE handle_history SET handle = ? WHERE handle = ?",
2160
+ normalizedNew,
2161
+ normalizedOld
2162
+ );
2163
+ await this.execSql(
2164
+ "DELETE FROM handle_registry WHERE handle = ?",
2165
+ normalizedOld
2166
+ );
2167
+ }
2168
+ async deleteHistoryEntry(handle, previousHash) {
2169
+ const normalized = validateHandle(handle);
2170
+ const rOutRows = await this.queryRows(
2171
+ "SELECT id, previous_hash FROM handle_history WHERE handle = ? AND previous_hash = ? ORDER BY id DESC LIMIT 1",
2172
+ normalized,
2173
+ previousHash
2174
+ );
2175
+ if (rOutRows.length === 0) return;
2176
+ const rOutId = Number(rOutRows[0].id);
2177
+ const rInRows = await this.queryRows(
2178
+ "SELECT id, previous_hash FROM handle_history WHERE handle = ? AND id < ? ORDER BY id DESC LIMIT 1",
2179
+ normalized,
2180
+ rOutId
2181
+ );
2182
+ if (rInRows.length > 0) {
2183
+ const rInId = Number(rInRows[0].id);
2184
+ const rInPrevHash = String(rInRows[0].previous_hash);
2185
+ await this.execSql("UPDATE handle_history SET previous_hash = ? WHERE id = ?", rInPrevHash, rOutId);
2186
+ await this.execSql("DELETE FROM handle_history WHERE id = ?", rInId);
2187
+ } else {
2188
+ await this.execSql("DELETE FROM handle_history WHERE id = ?", rOutId);
2189
+ }
2190
+ }
2191
+ };
2192
+
2193
+ // src/storage/engines/SqliteWasmEngine.ts
2194
+ var SqliteWasmEngine = class extends AbstractSqlEngine {
2195
+ db = null;
2196
+ SQL = null;
2197
+ /**
2198
+ * Initialize the database
2199
+ * @param wasmUrl URL to sql-wasm.wasm file (optional, defaults to CDN)
2200
+ * @param existingData Optional existing database as Uint8Array
2201
+ */
2202
+ async init(wasmUrl, existingData) {
2203
+ const initSqlJs = (await import("sql.js")).default;
2204
+ const SQL = await initSqlJs({
2205
+ locateFile: (file) => wasmUrl || `${DEFAULT_SQLJS_WASM_URL}${file}`
2206
+ });
2207
+ this.SQL = SQL;
2208
+ this.db = existingData ? new SQL.Database(existingData) : new SQL.Database();
2209
+ this.db.run(CORE_SCHEMAS.card);
2210
+ this.db.run(CORE_SCHEMAS.handleRegistry);
2211
+ this.db.run(CORE_SCHEMAS.handleHistory);
2212
+ this.db.run(CORE_SCHEMAS.handleIndex);
2213
+ }
2214
+ ensureDb() {
2215
+ if (!this.db) throw new Error("Database not initialized. Call init() first.");
2216
+ return this.db;
2217
+ }
2218
+ // ======================================================================
2219
+ // AbstractSqlEngine primitives
2220
+ // ======================================================================
2221
+ async queryRows(sql, ...params) {
2222
+ const db = this.ensureDb();
2223
+ const stmt = db.prepare(sql);
2224
+ if (params.length > 0) stmt.bind(params);
2068
2225
  const results = [];
2069
2226
  while (stmt.step()) {
2070
- const row = stmt.get();
2071
- results.push({ previousHash: row[0], changedAt: row[1] });
2227
+ const row = stmt.getAsObject();
2228
+ results.push(row);
2072
2229
  }
2073
2230
  stmt.free();
2074
2231
  return results;
2075
2232
  }
2233
+ async execSql(sql, ...params) {
2234
+ const db = this.ensureDb();
2235
+ if (params.length === 0) {
2236
+ db.run(sql);
2237
+ } else {
2238
+ db.run(sql, params);
2239
+ }
2240
+ return 0;
2241
+ }
2242
+ // ======================================================================
2243
+ // Row → MCard conversion (sql.js returns Uint8Array for BLOBs)
2244
+ // ======================================================================
2245
+ rowToCard(row) {
2246
+ const rawContent = row.content;
2247
+ const content = rawContent instanceof Uint8Array ? rawContent : typeof rawContent === "string" ? new TextEncoder().encode(rawContent) : new Uint8Array(0);
2248
+ return MCard.fromData(content, String(row.hash), String(row.g_time));
2249
+ }
2250
+ // ======================================================================
2251
+ // sql.js-specific helpers
2252
+ // ======================================================================
2253
+ /**
2254
+ * Export database as Uint8Array (for persistence)
2255
+ */
2256
+ export() {
2257
+ return this.ensureDb().export();
2258
+ }
2259
+ /**
2260
+ * Get raw sql.js Database for use with VectorStore adapter.
2261
+ */
2262
+ getRawDb() {
2263
+ return this.ensureDb();
2264
+ }
2265
+ // =========== pruneHandleHistory override (needs count before delete) ===========
2076
2266
  async pruneHandleHistory(handle, options = {}) {
2267
+ const { validateHandle: validateHandle2 } = await Promise.resolve().then(() => (init_Handle(), Handle_exports));
2077
2268
  const db = this.ensureDb();
2078
- const normalized = validateHandle(handle);
2269
+ const normalized = validateHandle2(handle);
2079
2270
  if (options.deleteAll) {
2080
2271
  const stmt = db.prepare("SELECT COUNT(*) FROM handle_history WHERE handle = ?");
2081
2272
  stmt.bind([normalized]);
@@ -2095,67 +2286,6 @@ var SqliteWasmEngine = class {
2095
2286
  }
2096
2287
  return 0;
2097
2288
  }
2098
- // =========== Handle Management Operations ===========
2099
- async getAllHandles() {
2100
- const result = this.ensureDb().exec("SELECT handle, current_hash FROM handle_registry");
2101
- return (result[0]?.values || []).map(([handle, hash]) => ({
2102
- handle,
2103
- hash
2104
- }));
2105
- }
2106
- async removeHandle(handle) {
2107
- const db = this.ensureDb();
2108
- const normalized = validateHandle(handle);
2109
- db.run("DELETE FROM handle_history WHERE handle = ?", [normalized]);
2110
- db.run("DELETE FROM handle_registry WHERE handle = ?", [normalized]);
2111
- }
2112
- async renameHandle(oldHandle, newHandle) {
2113
- const db = this.ensureDb();
2114
- const normalizedOld = validateHandle(oldHandle);
2115
- const normalizedNew = validateHandle(newHandle);
2116
- if (normalizedOld === normalizedNew) return;
2117
- const checkOld = db.prepare("SELECT handle FROM handle_registry WHERE handle = ?");
2118
- checkOld.bind([normalizedOld]);
2119
- const oldExists = checkOld.step();
2120
- checkOld.free();
2121
- if (!oldExists) throw new Error(`Handle '${oldHandle}' not found.`);
2122
- const checkNew = db.prepare("SELECT handle FROM handle_registry WHERE handle = ?");
2123
- checkNew.bind([normalizedNew]);
2124
- const newExists = checkNew.step();
2125
- checkNew.free();
2126
- if (newExists) throw new Error(`Handle '${newHandle}' already exists.`);
2127
- db.run("UPDATE handle_registry SET handle = ? WHERE handle = ?", [normalizedNew, normalizedOld]);
2128
- db.run("UPDATE handle_history SET handle = ? WHERE handle = ?", [normalizedNew, normalizedOld]);
2129
- }
2130
- async deleteHistoryEntry(handle, previousHash) {
2131
- const db = this.ensureDb();
2132
- const normalized = validateHandle(handle);
2133
- const rOutStmt = db.prepare(
2134
- "SELECT id, previous_hash FROM handle_history WHERE handle = ? AND previous_hash = ? ORDER BY id DESC LIMIT 1"
2135
- );
2136
- rOutStmt.bind([normalized, previousHash]);
2137
- if (!rOutStmt.step()) {
2138
- rOutStmt.free();
2139
- return;
2140
- }
2141
- const rOutId = rOutStmt.get()[0];
2142
- rOutStmt.free();
2143
- const rInStmt = db.prepare(
2144
- "SELECT id, previous_hash FROM handle_history WHERE handle = ? AND id < ? ORDER BY id DESC LIMIT 1"
2145
- );
2146
- rInStmt.bind([normalized, rOutId]);
2147
- const hasRIn = rInStmt.step();
2148
- if (hasRIn) {
2149
- const rInPrevHash = rInStmt.get()[1];
2150
- const rInId = rInStmt.get()[0];
2151
- rInStmt.free();
2152
- db.run("UPDATE handle_history SET previous_hash = ? WHERE id = ?", [rInPrevHash, rOutId]);
2153
- db.run("DELETE FROM handle_history WHERE id = ?", [rInId]);
2154
- } else {
2155
- rInStmt.free();
2156
- db.run("DELETE FROM handle_history WHERE id = ?", [rOutId]);
2157
- }
2158
- }
2159
2289
  };
2160
2290
  // Annotate the CommonJS export names for ESM import in node:
2161
2291
  0 && (module.exports = {