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.
- package/dist/AbstractSqlEngine-BSfp8S_Y.d.cts +451 -0
- package/dist/AbstractSqlEngine-BSfp8S_Y.d.ts +451 -0
- package/dist/CardCollection-MXTUJV4J.js +9 -0
- package/dist/EventProducer-AWD6YMZR.js +47 -0
- package/dist/Handle-3N4QOA3U.js +13 -0
- package/dist/IndexedDBEngine-2G5KCISA.js +11 -0
- package/dist/LLMRuntime-LBWUJ7ON.js +16 -0
- package/dist/LambdaRuntime-B6D6IQKZ.js +18 -0
- package/dist/Loader-3LSJXJQG.js +11 -0
- package/dist/MCard-H56VOJLR.js +8 -0
- package/dist/NetworkRuntime-IAFHPQSX.js +1570 -0
- package/dist/OllamaProvider-QPX2JXL2.js +8 -0
- package/dist/chunk-2R4ESMZB.js +110 -0
- package/dist/chunk-3EIBJPNF.js +17 -0
- package/dist/chunk-3LPY36OG.js +355 -0
- package/dist/chunk-3MMMJ7NH.js +1068 -0
- package/dist/chunk-42VF42KH.js +273 -0
- package/dist/chunk-4PDYHPR6.js +297 -0
- package/dist/chunk-ADV52544.js +95 -0
- package/dist/chunk-FIE4LAJG.js +215 -0
- package/dist/chunk-PNKVD2UK.js +26 -0
- package/dist/chunk-RSTKX7WM.js +907 -0
- package/dist/chunk-VXV35I5J.js +2315 -0
- package/dist/index.browser.cjs +375 -276
- package/dist/index.browser.d.cts +4 -4
- package/dist/index.browser.d.ts +4 -4
- package/dist/index.browser.js +18 -13
- package/dist/index.cjs +382 -453
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +26 -21
- package/dist/storage/SqliteNodeEngine.cjs +395 -270
- package/dist/storage/SqliteNodeEngine.d.cts +9 -94
- package/dist/storage/SqliteNodeEngine.d.ts +9 -94
- package/dist/storage/SqliteNodeEngine.js +6 -5
- package/dist/storage/SqliteWasmEngine.cjs +382 -252
- package/dist/storage/SqliteWasmEngine.d.cts +8 -29
- package/dist/storage/SqliteWasmEngine.d.ts +8 -29
- package/dist/storage/SqliteWasmEngine.js +6 -5
- package/package.json +1 -1
package/dist/index.browser.cjs
CHANGED
|
@@ -176,6 +176,90 @@ var init_GTime = __esm({
|
|
|
176
176
|
}
|
|
177
177
|
});
|
|
178
178
|
|
|
179
|
+
// src/model/Handle.ts
|
|
180
|
+
var Handle_exports = {};
|
|
181
|
+
__export(Handle_exports, {
|
|
182
|
+
ContentHandle: () => ContentHandle,
|
|
183
|
+
HandleValidationError: () => HandleValidationError,
|
|
184
|
+
validateHandle: () => validateHandle
|
|
185
|
+
});
|
|
186
|
+
function isValidStartChar(char) {
|
|
187
|
+
return /^\p{L}$/u.test(char);
|
|
188
|
+
}
|
|
189
|
+
function isValidBodyChar(char) {
|
|
190
|
+
return /^[\p{L}\p{N}_./ -]$/u.test(char);
|
|
191
|
+
}
|
|
192
|
+
function validateHandle(handle) {
|
|
193
|
+
if (!handle) {
|
|
194
|
+
throw new HandleValidationError("Handle cannot be empty.");
|
|
195
|
+
}
|
|
196
|
+
const normalized = handle.trim().normalize("NFC");
|
|
197
|
+
if (normalized.length === 0) {
|
|
198
|
+
throw new HandleValidationError("Handle cannot be empty after normalization.");
|
|
199
|
+
}
|
|
200
|
+
if (normalized.length > MAX_HANDLE_LENGTH) {
|
|
201
|
+
throw new HandleValidationError(
|
|
202
|
+
`Handle '${handle}' is too long (${normalized.length} chars). Maximum is ${MAX_HANDLE_LENGTH}.`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
if (!isValidStartChar(normalized[0])) {
|
|
206
|
+
throw new HandleValidationError(
|
|
207
|
+
`Invalid handle '${handle}'. Must start with a letter (any language).`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
for (let i = 1; i < normalized.length; i++) {
|
|
211
|
+
if (!isValidBodyChar(normalized[i])) {
|
|
212
|
+
throw new HandleValidationError(
|
|
213
|
+
`Invalid character '${normalized[i]}' at position ${i} in handle '${handle}'.`
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return normalized;
|
|
218
|
+
}
|
|
219
|
+
var MAX_HANDLE_LENGTH, HandleValidationError, ContentHandle;
|
|
220
|
+
var init_Handle = __esm({
|
|
221
|
+
"src/model/Handle.ts"() {
|
|
222
|
+
"use strict";
|
|
223
|
+
MAX_HANDLE_LENGTH = 255;
|
|
224
|
+
HandleValidationError = class extends Error {
|
|
225
|
+
constructor(message) {
|
|
226
|
+
super(message);
|
|
227
|
+
this.name = "HandleValidationError";
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
ContentHandle = class {
|
|
231
|
+
handle;
|
|
232
|
+
currentHash;
|
|
233
|
+
createdAt;
|
|
234
|
+
updatedAt;
|
|
235
|
+
constructor(handle, currentHash, createdAt, updatedAt) {
|
|
236
|
+
this.handle = validateHandle(handle);
|
|
237
|
+
this.currentHash = currentHash;
|
|
238
|
+
this.createdAt = createdAt ?? /* @__PURE__ */ new Date();
|
|
239
|
+
this.updatedAt = updatedAt ?? this.createdAt;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Update handle to point to new hash
|
|
243
|
+
* @returns Previous hash for history tracking
|
|
244
|
+
*/
|
|
245
|
+
update(newHash) {
|
|
246
|
+
const previousHash = this.currentHash;
|
|
247
|
+
this.currentHash = newHash;
|
|
248
|
+
this.updatedAt = /* @__PURE__ */ new Date();
|
|
249
|
+
return previousHash;
|
|
250
|
+
}
|
|
251
|
+
toObject() {
|
|
252
|
+
return {
|
|
253
|
+
handle: this.handle,
|
|
254
|
+
currentHash: this.currentHash,
|
|
255
|
+
createdAt: this.createdAt.toISOString(),
|
|
256
|
+
updatedAt: this.updatedAt.toISOString()
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
179
263
|
// src/model/constants.ts
|
|
180
264
|
var EVENT_CONSTANTS, ALGORITHM_HIERARCHY;
|
|
181
265
|
var init_constants = __esm({
|
|
@@ -1025,6 +1109,18 @@ var mime_extensions_default = {
|
|
|
1025
1109
|
}
|
|
1026
1110
|
};
|
|
1027
1111
|
|
|
1112
|
+
// src/config/constants.ts
|
|
1113
|
+
var DEFAULT_PAGE_SIZE = 10;
|
|
1114
|
+
var DETECTION_SAMPLE_CAP = 8192;
|
|
1115
|
+
var MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
1116
|
+
var KNOWN_TYPE_SIZE_LIMIT = 1024 * 1024;
|
|
1117
|
+
var BINARY_CHECK_SAMPLE_SIZE = 32 * 1024;
|
|
1118
|
+
var CONTENT_DETECTION_SAMPLE_SIZE = 1024 * 1024;
|
|
1119
|
+
var DEFAULT_MAX_PROBLEM_BYTES = 2 * 1024 * 1024;
|
|
1120
|
+
var INDEXEDDB_DEFAULT_DB_NAME = "mcard-db";
|
|
1121
|
+
var INDEXEDDB_DEFAULT_DB_VERSION = 1;
|
|
1122
|
+
var DEFAULT_SQLJS_WASM_URL = "https://sql.js.org/dist/";
|
|
1123
|
+
|
|
1028
1124
|
// src/model/strategies/DetectionStrategy.ts
|
|
1029
1125
|
function loadSharedMimeData() {
|
|
1030
1126
|
return {
|
|
@@ -1057,7 +1153,7 @@ var DefaultDetectionStrategy = class _DefaultDetectionStrategy {
|
|
|
1057
1153
|
return this.extensionsRegistry[mimeType] || "";
|
|
1058
1154
|
}
|
|
1059
1155
|
detect(content, fileExtension) {
|
|
1060
|
-
const contentSample = typeof content === "string" ? content.slice(0,
|
|
1156
|
+
const contentSample = typeof content === "string" ? content.slice(0, DETECTION_SAMPLE_CAP) : content.slice(0, DETECTION_SAMPLE_CAP);
|
|
1061
1157
|
const textSample = this.getTextSample(contentSample);
|
|
1062
1158
|
const lines = textSample.split("\n").slice(0, 20);
|
|
1063
1159
|
const firstLine = lines[0] || "";
|
|
@@ -1091,9 +1187,9 @@ var DefaultDetectionStrategy = class _DefaultDetectionStrategy {
|
|
|
1091
1187
|
}
|
|
1092
1188
|
getTextSample(content) {
|
|
1093
1189
|
if (typeof content === "string") {
|
|
1094
|
-
return content.slice(0,
|
|
1190
|
+
return content.slice(0, DETECTION_SAMPLE_CAP);
|
|
1095
1191
|
}
|
|
1096
|
-
return new TextDecoder("utf-8", { fatal: false }).decode(content.slice(0,
|
|
1192
|
+
return new TextDecoder("utf-8", { fatal: false }).decode(content.slice(0, DETECTION_SAMPLE_CAP));
|
|
1097
1193
|
}
|
|
1098
1194
|
getExtension(mimeType) {
|
|
1099
1195
|
return _DefaultDetectionStrategy.getExtension(mimeType);
|
|
@@ -1313,78 +1409,7 @@ var MCard = class _MCard {
|
|
|
1313
1409
|
|
|
1314
1410
|
// src/index.browser.ts
|
|
1315
1411
|
init_GTime();
|
|
1316
|
-
|
|
1317
|
-
// src/model/Handle.ts
|
|
1318
|
-
var MAX_HANDLE_LENGTH = 255;
|
|
1319
|
-
function isValidStartChar(char) {
|
|
1320
|
-
return /^\p{L}$/u.test(char);
|
|
1321
|
-
}
|
|
1322
|
-
function isValidBodyChar(char) {
|
|
1323
|
-
return /^[\p{L}\p{N}_./ -]$/u.test(char);
|
|
1324
|
-
}
|
|
1325
|
-
var HandleValidationError = class extends Error {
|
|
1326
|
-
constructor(message) {
|
|
1327
|
-
super(message);
|
|
1328
|
-
this.name = "HandleValidationError";
|
|
1329
|
-
}
|
|
1330
|
-
};
|
|
1331
|
-
function validateHandle(handle) {
|
|
1332
|
-
if (!handle) {
|
|
1333
|
-
throw new HandleValidationError("Handle cannot be empty.");
|
|
1334
|
-
}
|
|
1335
|
-
const normalized = handle.trim().normalize("NFC").toLowerCase();
|
|
1336
|
-
if (normalized.length === 0) {
|
|
1337
|
-
throw new HandleValidationError("Handle cannot be empty after normalization.");
|
|
1338
|
-
}
|
|
1339
|
-
if (normalized.length > MAX_HANDLE_LENGTH) {
|
|
1340
|
-
throw new HandleValidationError(
|
|
1341
|
-
`Handle '${handle}' is too long (${normalized.length} chars). Maximum is ${MAX_HANDLE_LENGTH}.`
|
|
1342
|
-
);
|
|
1343
|
-
}
|
|
1344
|
-
if (!isValidStartChar(normalized[0])) {
|
|
1345
|
-
throw new HandleValidationError(
|
|
1346
|
-
`Invalid handle '${handle}'. Must start with a letter (any language).`
|
|
1347
|
-
);
|
|
1348
|
-
}
|
|
1349
|
-
for (let i = 1; i < normalized.length; i++) {
|
|
1350
|
-
if (!isValidBodyChar(normalized[i])) {
|
|
1351
|
-
throw new HandleValidationError(
|
|
1352
|
-
`Invalid character '${normalized[i]}' at position ${i} in handle '${handle}'.`
|
|
1353
|
-
);
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
return normalized;
|
|
1357
|
-
}
|
|
1358
|
-
var ContentHandle = class {
|
|
1359
|
-
handle;
|
|
1360
|
-
currentHash;
|
|
1361
|
-
createdAt;
|
|
1362
|
-
updatedAt;
|
|
1363
|
-
constructor(handle, currentHash, createdAt, updatedAt) {
|
|
1364
|
-
this.handle = validateHandle(handle);
|
|
1365
|
-
this.currentHash = currentHash;
|
|
1366
|
-
this.createdAt = createdAt ?? /* @__PURE__ */ new Date();
|
|
1367
|
-
this.updatedAt = updatedAt ?? this.createdAt;
|
|
1368
|
-
}
|
|
1369
|
-
/**
|
|
1370
|
-
* Update handle to point to new hash
|
|
1371
|
-
* @returns Previous hash for history tracking
|
|
1372
|
-
*/
|
|
1373
|
-
update(newHash) {
|
|
1374
|
-
const previousHash = this.currentHash;
|
|
1375
|
-
this.currentHash = newHash;
|
|
1376
|
-
this.updatedAt = /* @__PURE__ */ new Date();
|
|
1377
|
-
return previousHash;
|
|
1378
|
-
}
|
|
1379
|
-
toObject() {
|
|
1380
|
-
return {
|
|
1381
|
-
handle: this.handle,
|
|
1382
|
-
currentHash: this.currentHash,
|
|
1383
|
-
createdAt: this.createdAt.toISOString(),
|
|
1384
|
-
updatedAt: this.updatedAt.toISOString()
|
|
1385
|
-
};
|
|
1386
|
-
}
|
|
1387
|
-
};
|
|
1412
|
+
init_Handle();
|
|
1388
1413
|
|
|
1389
1414
|
// src/monads/Maybe.ts
|
|
1390
1415
|
var Maybe = class _Maybe {
|
|
@@ -1511,7 +1536,7 @@ var CardCollection = class {
|
|
|
1511
1536
|
/**
|
|
1512
1537
|
* Get a page of cards
|
|
1513
1538
|
*/
|
|
1514
|
-
async getPage(pageNumber = 1, pageSize =
|
|
1539
|
+
async getPage(pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
|
|
1515
1540
|
return this.engine.getPage(pageNumber, pageSize);
|
|
1516
1541
|
}
|
|
1517
1542
|
/**
|
|
@@ -1601,10 +1626,10 @@ var CardCollection = class {
|
|
|
1601
1626
|
async clear() {
|
|
1602
1627
|
return this.engine.clear();
|
|
1603
1628
|
}
|
|
1604
|
-
async searchByString(query, pageNumber = 1, pageSize =
|
|
1629
|
+
async searchByString(query, pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
|
|
1605
1630
|
return this.engine.search(query, pageNumber, pageSize);
|
|
1606
1631
|
}
|
|
1607
|
-
async searchByContent(query, pageNumber = 1, pageSize =
|
|
1632
|
+
async searchByContent(query, pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
|
|
1608
1633
|
return this.engine.search(query, pageNumber, pageSize);
|
|
1609
1634
|
}
|
|
1610
1635
|
async searchByHash(hashPrefix) {
|
|
@@ -1613,7 +1638,7 @@ var CardCollection = class {
|
|
|
1613
1638
|
async getAllMCardsRaw() {
|
|
1614
1639
|
return this.engine.getAll();
|
|
1615
1640
|
}
|
|
1616
|
-
async getAllCards(pageSize =
|
|
1641
|
+
async getAllCards(pageSize = DEFAULT_PAGE_SIZE, processCallback) {
|
|
1617
1642
|
const cards = [];
|
|
1618
1643
|
let pageNumber = 1;
|
|
1619
1644
|
let total = 0;
|
|
@@ -1679,6 +1704,7 @@ init_constants();
|
|
|
1679
1704
|
|
|
1680
1705
|
// src/storage/engines/IndexedDBEngine.ts
|
|
1681
1706
|
var import_idb = require("idb");
|
|
1707
|
+
init_Handle();
|
|
1682
1708
|
|
|
1683
1709
|
// src/storage/StorageAdapter.ts
|
|
1684
1710
|
function createPage(items, totalItems, pageNumber, pageSize) {
|
|
@@ -1698,14 +1724,14 @@ function createPage(items, totalItems, pageNumber, pageSize) {
|
|
|
1698
1724
|
var IndexedDBEngine = class {
|
|
1699
1725
|
db = null;
|
|
1700
1726
|
dbName;
|
|
1701
|
-
constructor(dbName =
|
|
1727
|
+
constructor(dbName = INDEXEDDB_DEFAULT_DB_NAME) {
|
|
1702
1728
|
this.dbName = dbName;
|
|
1703
1729
|
}
|
|
1704
1730
|
/**
|
|
1705
1731
|
* Initialize the database connection
|
|
1706
1732
|
*/
|
|
1707
1733
|
async init() {
|
|
1708
|
-
this.db = await (0, import_idb.openDB)(this.dbName,
|
|
1734
|
+
this.db = await (0, import_idb.openDB)(this.dbName, INDEXEDDB_DEFAULT_DB_VERSION, {
|
|
1709
1735
|
upgrade(db) {
|
|
1710
1736
|
if (!db.objectStoreNames.contains("cards")) {
|
|
1711
1737
|
db.createObjectStore("cards", { keyPath: "hash" });
|
|
@@ -1750,7 +1776,7 @@ var IndexedDBEngine = class {
|
|
|
1750
1776
|
const db = this.ensureDb();
|
|
1751
1777
|
await db.delete("cards", hash);
|
|
1752
1778
|
}
|
|
1753
|
-
async getPage(pageNumber, pageSize) {
|
|
1779
|
+
async getPage(pageNumber, pageSize = DEFAULT_PAGE_SIZE) {
|
|
1754
1780
|
const db = this.ensureDb();
|
|
1755
1781
|
const totalItems = await db.count("cards");
|
|
1756
1782
|
const allCards = await db.getAll("cards");
|
|
@@ -1771,7 +1797,7 @@ var IndexedDBEngine = class {
|
|
|
1771
1797
|
const records = await db.getAll("cards", range);
|
|
1772
1798
|
return records.map((r) => MCard.fromData(r.content, r.hash, r.g_time));
|
|
1773
1799
|
}
|
|
1774
|
-
async search(query, pageNumber, pageSize) {
|
|
1800
|
+
async search(query, pageNumber, pageSize = DEFAULT_PAGE_SIZE) {
|
|
1775
1801
|
const db = this.ensureDb();
|
|
1776
1802
|
const records = await db.getAll("cards");
|
|
1777
1803
|
const decoder = new TextDecoder();
|
|
@@ -2581,159 +2607,129 @@ var CORE_SCHEMAS = {
|
|
|
2581
2607
|
handleIndex: HANDLE_INDEX_SCHEMA
|
|
2582
2608
|
};
|
|
2583
2609
|
|
|
2584
|
-
// src/storage/engines/
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
SQL = null;
|
|
2610
|
+
// src/storage/engines/AbstractSqlEngine.ts
|
|
2611
|
+
init_Handle();
|
|
2612
|
+
var AbstractSqlEngine = class {
|
|
2588
2613
|
/**
|
|
2589
|
-
*
|
|
2590
|
-
*
|
|
2591
|
-
* @param existingData Optional existing database as Uint8Array
|
|
2614
|
+
* SQL expression for casting content to text in search queries.
|
|
2615
|
+
* Override in subclasses: SQLite uses 'TEXT', DuckDB uses 'VARCHAR'.
|
|
2592
2616
|
*/
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
const SQL = await initSqlJs({
|
|
2596
|
-
locateFile: (file) => wasmUrl || `https://sql.js.org/dist/${file}`
|
|
2597
|
-
});
|
|
2598
|
-
this.SQL = SQL;
|
|
2599
|
-
this.db = existingData ? new SQL.Database(existingData) : new SQL.Database();
|
|
2600
|
-
this.db.run(CORE_SCHEMAS.card);
|
|
2601
|
-
this.db.run(CORE_SCHEMAS.handleRegistry);
|
|
2602
|
-
this.db.run(CORE_SCHEMAS.handleHistory);
|
|
2603
|
-
this.db.run(CORE_SCHEMAS.handleIndex);
|
|
2604
|
-
}
|
|
2605
|
-
ensureDb() {
|
|
2606
|
-
if (!this.db) throw new Error("Database not initialized. Call init() first.");
|
|
2607
|
-
return this.db;
|
|
2608
|
-
}
|
|
2609
|
-
/**
|
|
2610
|
-
* Export database as Uint8Array (for persistence)
|
|
2611
|
-
*/
|
|
2612
|
-
export() {
|
|
2613
|
-
return this.ensureDb().export();
|
|
2617
|
+
get castContentAs() {
|
|
2618
|
+
return "TEXT";
|
|
2614
2619
|
}
|
|
2620
|
+
// ======================================================================
|
|
2621
|
+
// Concrete: Card Operations (shared across all SQL engines)
|
|
2622
|
+
// ======================================================================
|
|
2615
2623
|
/**
|
|
2616
|
-
*
|
|
2617
|
-
*
|
|
2618
|
-
* Example:
|
|
2619
|
-
* const vecStore = createWasmVectorStore(engine.getRawDb());
|
|
2624
|
+
* Add a card. Default uses INSERT OR REPLACE (SQLite).
|
|
2625
|
+
* DuckDB overrides with DELETE + INSERT.
|
|
2620
2626
|
*/
|
|
2621
|
-
getRawDb() {
|
|
2622
|
-
return this.ensureDb();
|
|
2623
|
-
}
|
|
2624
|
-
// =========== Card Operations ===========
|
|
2625
2627
|
async add(card) {
|
|
2626
|
-
const
|
|
2627
|
-
|
|
2628
|
+
const contentBytes = card.content instanceof Uint8Array ? card.content : new TextEncoder().encode(String(card.content));
|
|
2629
|
+
await this.execSql(
|
|
2628
2630
|
"INSERT OR REPLACE INTO card (hash, content, g_time) VALUES (?, ?, ?)",
|
|
2629
|
-
|
|
2631
|
+
card.hash,
|
|
2632
|
+
contentBytes,
|
|
2633
|
+
card.g_time
|
|
2630
2634
|
);
|
|
2631
2635
|
return card.hash;
|
|
2632
2636
|
}
|
|
2633
2637
|
async get(hash) {
|
|
2634
|
-
const
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
}
|
|
2641
|
-
const row = stmt.get();
|
|
2642
|
-
stmt.free();
|
|
2643
|
-
return MCard.fromData(new Uint8Array(row[1]), row[0], row[2]);
|
|
2638
|
+
const rows = await this.queryRows(
|
|
2639
|
+
"SELECT hash, content, g_time FROM card WHERE hash = ?",
|
|
2640
|
+
hash
|
|
2641
|
+
);
|
|
2642
|
+
if (rows.length === 0) return null;
|
|
2643
|
+
return this.rowToCard(rows[0]);
|
|
2644
2644
|
}
|
|
2645
2645
|
async delete(hash) {
|
|
2646
|
-
this.
|
|
2646
|
+
await this.execSql("DELETE FROM card WHERE hash = ?", hash);
|
|
2647
2647
|
}
|
|
2648
|
-
async getPage(pageNumber, pageSize) {
|
|
2649
|
-
|
|
2648
|
+
async getPage(pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
|
|
2649
|
+
if (pageNumber < 1) throw new Error("Page number must be >= 1");
|
|
2650
|
+
if (pageSize < 1) throw new Error("Page size must be >= 1");
|
|
2650
2651
|
const totalItems = await this.count();
|
|
2651
2652
|
const offset = (pageNumber - 1) * pageSize;
|
|
2652
|
-
const
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
}
|
|
2659
|
-
stmt.free();
|
|
2653
|
+
const rows = await this.queryRows(
|
|
2654
|
+
"SELECT hash, content, g_time FROM card ORDER BY g_time DESC LIMIT ? OFFSET ?",
|
|
2655
|
+
pageSize,
|
|
2656
|
+
offset
|
|
2657
|
+
);
|
|
2658
|
+
const items = rows.map((r) => this.rowToCard(r));
|
|
2660
2659
|
return createPage(items, totalItems, pageNumber, pageSize);
|
|
2661
2660
|
}
|
|
2662
2661
|
async count() {
|
|
2663
|
-
const
|
|
2664
|
-
return
|
|
2662
|
+
const rows = await this.queryRows("SELECT COUNT(*) as cnt FROM card");
|
|
2663
|
+
return Number(rows[0]?.cnt ?? 0);
|
|
2665
2664
|
}
|
|
2666
2665
|
async searchByHash(hashPrefix) {
|
|
2667
|
-
const
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
const row = stmt.get();
|
|
2673
|
-
items.push(MCard.fromData(new Uint8Array(row[1]), row[0], row[2]));
|
|
2674
|
-
}
|
|
2675
|
-
stmt.free();
|
|
2676
|
-
return items;
|
|
2666
|
+
const rows = await this.queryRows(
|
|
2667
|
+
"SELECT hash, content, g_time FROM card WHERE hash LIKE ?",
|
|
2668
|
+
`${hashPrefix}%`
|
|
2669
|
+
);
|
|
2670
|
+
return rows.map((r) => this.rowToCard(r));
|
|
2677
2671
|
}
|
|
2678
|
-
async search(
|
|
2679
|
-
|
|
2672
|
+
async search(queryStr, pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
|
|
2673
|
+
if (pageNumber < 1) throw new Error("Page number must be >= 1");
|
|
2674
|
+
if (pageSize < 1) throw new Error("Page size must be >= 1");
|
|
2680
2675
|
const offset = (pageNumber - 1) * pageSize;
|
|
2681
|
-
const pattern = `%${
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2676
|
+
const pattern = `%${queryStr}%`;
|
|
2677
|
+
const cast = this.castContentAs;
|
|
2678
|
+
const countRows = await this.queryRows(
|
|
2679
|
+
`SELECT COUNT(*) as cnt FROM card WHERE CAST(content AS ${cast}) LIKE ?`,
|
|
2680
|
+
pattern
|
|
2681
|
+
);
|
|
2682
|
+
const totalItems = Number(countRows[0]?.cnt ?? 0);
|
|
2683
|
+
const rows = await this.queryRows(
|
|
2684
|
+
`SELECT hash, content, g_time FROM card WHERE CAST(content AS ${cast}) LIKE ? ORDER BY g_time DESC LIMIT ? OFFSET ?`,
|
|
2685
|
+
pattern,
|
|
2686
|
+
pageSize,
|
|
2687
|
+
offset
|
|
2688
|
+
);
|
|
2689
|
+
const items = rows.map((r) => this.rowToCard(r));
|
|
2695
2690
|
return createPage(items, totalItems, pageNumber, pageSize);
|
|
2696
2691
|
}
|
|
2697
2692
|
async getAll() {
|
|
2698
|
-
const
|
|
2699
|
-
return (
|
|
2700
|
-
([h, content, g_time]) => MCard.fromData(new Uint8Array(content), h, g_time)
|
|
2701
|
-
);
|
|
2693
|
+
const rows = await this.queryRows("SELECT hash, content, g_time FROM card ORDER BY g_time DESC");
|
|
2694
|
+
return rows.map((r) => this.rowToCard(r));
|
|
2702
2695
|
}
|
|
2696
|
+
// ======================================================================
|
|
2697
|
+
// Concrete: clear (FK-safe delete order)
|
|
2698
|
+
// ======================================================================
|
|
2703
2699
|
async clear() {
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
db.run("DELETE FROM handle_history");
|
|
2700
|
+
await this.execSql("DELETE FROM handle_history");
|
|
2701
|
+
await this.execSql("DELETE FROM handle_registry");
|
|
2702
|
+
await this.execSql("DELETE FROM card");
|
|
2708
2703
|
}
|
|
2709
|
-
//
|
|
2704
|
+
// ======================================================================
|
|
2705
|
+
// Concrete: Handle Operations
|
|
2706
|
+
// ======================================================================
|
|
2710
2707
|
async registerHandle(handle, hash) {
|
|
2711
|
-
const db = this.ensureDb();
|
|
2712
2708
|
const normalized = validateHandle(handle);
|
|
2713
|
-
const
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2709
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2710
|
+
const existing = await this.queryRows(
|
|
2711
|
+
"SELECT handle FROM handle_registry WHERE handle = ?",
|
|
2712
|
+
normalized
|
|
2713
|
+
);
|
|
2714
|
+
if (existing.length > 0) {
|
|
2718
2715
|
throw new Error(`Handle '${handle}' already exists.`);
|
|
2719
2716
|
}
|
|
2720
|
-
|
|
2721
|
-
db.run(
|
|
2717
|
+
await this.execSql(
|
|
2722
2718
|
"INSERT INTO handle_registry (handle, current_hash, created_at, updated_at) VALUES (?, ?, ?, ?)",
|
|
2723
|
-
|
|
2719
|
+
normalized,
|
|
2720
|
+
hash,
|
|
2721
|
+
now,
|
|
2722
|
+
now
|
|
2724
2723
|
);
|
|
2725
2724
|
}
|
|
2726
2725
|
async resolveHandle(handle) {
|
|
2727
2726
|
const normalized = validateHandle(handle);
|
|
2728
|
-
const
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
const hash = stmt.get()[0];
|
|
2735
|
-
stmt.free();
|
|
2736
|
-
return hash || null;
|
|
2727
|
+
const rows = await this.queryRows(
|
|
2728
|
+
"SELECT current_hash FROM handle_registry WHERE handle = ?",
|
|
2729
|
+
normalized
|
|
2730
|
+
);
|
|
2731
|
+
if (rows.length === 0) return null;
|
|
2732
|
+
return String(rows[0].current_hash);
|
|
2737
2733
|
}
|
|
2738
2734
|
async getByHandle(handle) {
|
|
2739
2735
|
const hash = await this.resolveHandle(handle);
|
|
@@ -2741,42 +2737,206 @@ var SqliteWasmEngine = class {
|
|
|
2741
2737
|
return this.get(hash);
|
|
2742
2738
|
}
|
|
2743
2739
|
async updateHandle(handle, newHash) {
|
|
2744
|
-
const db = this.ensureDb();
|
|
2745
2740
|
const normalized = validateHandle(handle);
|
|
2746
|
-
const
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2741
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2742
|
+
const rows = await this.queryRows(
|
|
2743
|
+
"SELECT current_hash FROM handle_registry WHERE handle = ?",
|
|
2744
|
+
normalized
|
|
2745
|
+
);
|
|
2746
|
+
if (rows.length === 0) {
|
|
2750
2747
|
throw new Error(`Handle '${handle}' not found.`);
|
|
2751
2748
|
}
|
|
2752
|
-
const previousHash =
|
|
2753
|
-
|
|
2754
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2755
|
-
db.run(
|
|
2749
|
+
const previousHash = String(rows[0].current_hash);
|
|
2750
|
+
await this.execSql(
|
|
2756
2751
|
"INSERT INTO handle_history (handle, previous_hash, changed_at) VALUES (?, ?, ?)",
|
|
2757
|
-
|
|
2752
|
+
normalized,
|
|
2753
|
+
previousHash,
|
|
2754
|
+
now
|
|
2758
2755
|
);
|
|
2759
|
-
|
|
2756
|
+
await this.execSql(
|
|
2760
2757
|
"UPDATE handle_registry SET current_hash = ?, updated_at = ? WHERE handle = ?",
|
|
2761
|
-
|
|
2758
|
+
newHash,
|
|
2759
|
+
now,
|
|
2760
|
+
normalized
|
|
2762
2761
|
);
|
|
2763
2762
|
return previousHash;
|
|
2764
2763
|
}
|
|
2765
2764
|
async getHandleHistory(handle) {
|
|
2766
2765
|
const normalized = validateHandle(handle);
|
|
2767
|
-
const
|
|
2768
|
-
|
|
2766
|
+
const rows = await this.queryRows(
|
|
2767
|
+
"SELECT previous_hash, changed_at FROM handle_history WHERE handle = ? ORDER BY id DESC",
|
|
2768
|
+
normalized
|
|
2769
|
+
);
|
|
2770
|
+
return rows.map((r) => ({
|
|
2771
|
+
previousHash: String(r.previous_hash),
|
|
2772
|
+
changedAt: String(r.changed_at)
|
|
2773
|
+
}));
|
|
2774
|
+
}
|
|
2775
|
+
async pruneHandleHistory(handle, options = {}) {
|
|
2776
|
+
const normalized = validateHandle(handle);
|
|
2777
|
+
if (options.deleteAll) {
|
|
2778
|
+
return this.execSql("DELETE FROM handle_history WHERE handle = ?", normalized);
|
|
2779
|
+
} else if (options.olderThan) {
|
|
2780
|
+
return this.execSql(
|
|
2781
|
+
"DELETE FROM handle_history WHERE handle = ? AND changed_at < ?",
|
|
2782
|
+
normalized,
|
|
2783
|
+
options.olderThan
|
|
2784
|
+
);
|
|
2785
|
+
}
|
|
2786
|
+
return 0;
|
|
2787
|
+
}
|
|
2788
|
+
// ======================================================================
|
|
2789
|
+
// Concrete: Handle Management Operations
|
|
2790
|
+
// ======================================================================
|
|
2791
|
+
async getAllHandles() {
|
|
2792
|
+
const rows = await this.queryRows("SELECT handle, current_hash FROM handle_registry");
|
|
2793
|
+
return rows.map((r) => ({
|
|
2794
|
+
handle: String(r.handle),
|
|
2795
|
+
hash: String(r.current_hash)
|
|
2796
|
+
}));
|
|
2797
|
+
}
|
|
2798
|
+
async removeHandle(handle) {
|
|
2799
|
+
const normalized = validateHandle(handle);
|
|
2800
|
+
await this.execSql("DELETE FROM handle_history WHERE handle = ?", normalized);
|
|
2801
|
+
await this.execSql("DELETE FROM handle_registry WHERE handle = ?", normalized);
|
|
2802
|
+
}
|
|
2803
|
+
async renameHandle(oldHandle, newHandle) {
|
|
2804
|
+
const normalizedOld = validateHandle(oldHandle);
|
|
2805
|
+
const normalizedNew = validateHandle(newHandle);
|
|
2806
|
+
if (normalizedOld === normalizedNew) return;
|
|
2807
|
+
const existsOld = await this.queryRows(
|
|
2808
|
+
"SELECT handle FROM handle_registry WHERE handle = ?",
|
|
2809
|
+
normalizedOld
|
|
2810
|
+
);
|
|
2811
|
+
if (existsOld.length === 0) throw new Error(`Handle '${oldHandle}' not found.`);
|
|
2812
|
+
const existsNew = await this.queryRows(
|
|
2813
|
+
"SELECT handle FROM handle_registry WHERE handle = ?",
|
|
2814
|
+
normalizedNew
|
|
2815
|
+
);
|
|
2816
|
+
if (existsNew.length > 0) throw new Error(`Handle '${newHandle}' already exists.`);
|
|
2817
|
+
const oldRow = await this.queryRows(
|
|
2818
|
+
"SELECT current_hash, created_at, updated_at FROM handle_registry WHERE handle = ?",
|
|
2819
|
+
normalizedOld
|
|
2820
|
+
);
|
|
2821
|
+
await this.execSql(
|
|
2822
|
+
"INSERT INTO handle_registry (handle, current_hash, created_at, updated_at) VALUES (?, ?, ?, ?)",
|
|
2823
|
+
normalizedNew,
|
|
2824
|
+
String(oldRow[0].current_hash),
|
|
2825
|
+
String(oldRow[0].created_at),
|
|
2826
|
+
String(oldRow[0].updated_at)
|
|
2827
|
+
);
|
|
2828
|
+
await this.execSql(
|
|
2829
|
+
"UPDATE handle_history SET handle = ? WHERE handle = ?",
|
|
2830
|
+
normalizedNew,
|
|
2831
|
+
normalizedOld
|
|
2832
|
+
);
|
|
2833
|
+
await this.execSql(
|
|
2834
|
+
"DELETE FROM handle_registry WHERE handle = ?",
|
|
2835
|
+
normalizedOld
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
async deleteHistoryEntry(handle, previousHash) {
|
|
2839
|
+
const normalized = validateHandle(handle);
|
|
2840
|
+
const rOutRows = await this.queryRows(
|
|
2841
|
+
"SELECT id, previous_hash FROM handle_history WHERE handle = ? AND previous_hash = ? ORDER BY id DESC LIMIT 1",
|
|
2842
|
+
normalized,
|
|
2843
|
+
previousHash
|
|
2844
|
+
);
|
|
2845
|
+
if (rOutRows.length === 0) return;
|
|
2846
|
+
const rOutId = Number(rOutRows[0].id);
|
|
2847
|
+
const rInRows = await this.queryRows(
|
|
2848
|
+
"SELECT id, previous_hash FROM handle_history WHERE handle = ? AND id < ? ORDER BY id DESC LIMIT 1",
|
|
2849
|
+
normalized,
|
|
2850
|
+
rOutId
|
|
2851
|
+
);
|
|
2852
|
+
if (rInRows.length > 0) {
|
|
2853
|
+
const rInId = Number(rInRows[0].id);
|
|
2854
|
+
const rInPrevHash = String(rInRows[0].previous_hash);
|
|
2855
|
+
await this.execSql("UPDATE handle_history SET previous_hash = ? WHERE id = ?", rInPrevHash, rOutId);
|
|
2856
|
+
await this.execSql("DELETE FROM handle_history WHERE id = ?", rInId);
|
|
2857
|
+
} else {
|
|
2858
|
+
await this.execSql("DELETE FROM handle_history WHERE id = ?", rOutId);
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
};
|
|
2862
|
+
|
|
2863
|
+
// src/storage/engines/SqliteWasmEngine.ts
|
|
2864
|
+
var SqliteWasmEngine = class extends AbstractSqlEngine {
|
|
2865
|
+
db = null;
|
|
2866
|
+
SQL = null;
|
|
2867
|
+
/**
|
|
2868
|
+
* Initialize the database
|
|
2869
|
+
* @param wasmUrl URL to sql-wasm.wasm file (optional, defaults to CDN)
|
|
2870
|
+
* @param existingData Optional existing database as Uint8Array
|
|
2871
|
+
*/
|
|
2872
|
+
async init(wasmUrl, existingData) {
|
|
2873
|
+
const initSqlJs = (await import("sql.js")).default;
|
|
2874
|
+
const SQL = await initSqlJs({
|
|
2875
|
+
locateFile: (file) => wasmUrl || `${DEFAULT_SQLJS_WASM_URL}${file}`
|
|
2876
|
+
});
|
|
2877
|
+
this.SQL = SQL;
|
|
2878
|
+
this.db = existingData ? new SQL.Database(existingData) : new SQL.Database();
|
|
2879
|
+
this.db.run(CORE_SCHEMAS.card);
|
|
2880
|
+
this.db.run(CORE_SCHEMAS.handleRegistry);
|
|
2881
|
+
this.db.run(CORE_SCHEMAS.handleHistory);
|
|
2882
|
+
this.db.run(CORE_SCHEMAS.handleIndex);
|
|
2883
|
+
}
|
|
2884
|
+
ensureDb() {
|
|
2885
|
+
if (!this.db) throw new Error("Database not initialized. Call init() first.");
|
|
2886
|
+
return this.db;
|
|
2887
|
+
}
|
|
2888
|
+
// ======================================================================
|
|
2889
|
+
// AbstractSqlEngine primitives
|
|
2890
|
+
// ======================================================================
|
|
2891
|
+
async queryRows(sql, ...params) {
|
|
2892
|
+
const db = this.ensureDb();
|
|
2893
|
+
const stmt = db.prepare(sql);
|
|
2894
|
+
if (params.length > 0) stmt.bind(params);
|
|
2769
2895
|
const results = [];
|
|
2770
2896
|
while (stmt.step()) {
|
|
2771
|
-
const row = stmt.
|
|
2772
|
-
results.push(
|
|
2897
|
+
const row = stmt.getAsObject();
|
|
2898
|
+
results.push(row);
|
|
2773
2899
|
}
|
|
2774
2900
|
stmt.free();
|
|
2775
2901
|
return results;
|
|
2776
2902
|
}
|
|
2903
|
+
async execSql(sql, ...params) {
|
|
2904
|
+
const db = this.ensureDb();
|
|
2905
|
+
if (params.length === 0) {
|
|
2906
|
+
db.run(sql);
|
|
2907
|
+
} else {
|
|
2908
|
+
db.run(sql, params);
|
|
2909
|
+
}
|
|
2910
|
+
return 0;
|
|
2911
|
+
}
|
|
2912
|
+
// ======================================================================
|
|
2913
|
+
// Row → MCard conversion (sql.js returns Uint8Array for BLOBs)
|
|
2914
|
+
// ======================================================================
|
|
2915
|
+
rowToCard(row) {
|
|
2916
|
+
const rawContent = row.content;
|
|
2917
|
+
const content = rawContent instanceof Uint8Array ? rawContent : typeof rawContent === "string" ? new TextEncoder().encode(rawContent) : new Uint8Array(0);
|
|
2918
|
+
return MCard.fromData(content, String(row.hash), String(row.g_time));
|
|
2919
|
+
}
|
|
2920
|
+
// ======================================================================
|
|
2921
|
+
// sql.js-specific helpers
|
|
2922
|
+
// ======================================================================
|
|
2923
|
+
/**
|
|
2924
|
+
* Export database as Uint8Array (for persistence)
|
|
2925
|
+
*/
|
|
2926
|
+
export() {
|
|
2927
|
+
return this.ensureDb().export();
|
|
2928
|
+
}
|
|
2929
|
+
/**
|
|
2930
|
+
* Get raw sql.js Database for use with VectorStore adapter.
|
|
2931
|
+
*/
|
|
2932
|
+
getRawDb() {
|
|
2933
|
+
return this.ensureDb();
|
|
2934
|
+
}
|
|
2935
|
+
// =========== pruneHandleHistory override (needs count before delete) ===========
|
|
2777
2936
|
async pruneHandleHistory(handle, options = {}) {
|
|
2937
|
+
const { validateHandle: validateHandle2 } = await Promise.resolve().then(() => (init_Handle(), Handle_exports));
|
|
2778
2938
|
const db = this.ensureDb();
|
|
2779
|
-
const normalized =
|
|
2939
|
+
const normalized = validateHandle2(handle);
|
|
2780
2940
|
if (options.deleteAll) {
|
|
2781
2941
|
const stmt = db.prepare("SELECT COUNT(*) FROM handle_history WHERE handle = ?");
|
|
2782
2942
|
stmt.bind([normalized]);
|
|
@@ -2796,67 +2956,6 @@ var SqliteWasmEngine = class {
|
|
|
2796
2956
|
}
|
|
2797
2957
|
return 0;
|
|
2798
2958
|
}
|
|
2799
|
-
// =========== Handle Management Operations ===========
|
|
2800
|
-
async getAllHandles() {
|
|
2801
|
-
const result = this.ensureDb().exec("SELECT handle, current_hash FROM handle_registry");
|
|
2802
|
-
return (result[0]?.values || []).map(([handle, hash]) => ({
|
|
2803
|
-
handle,
|
|
2804
|
-
hash
|
|
2805
|
-
}));
|
|
2806
|
-
}
|
|
2807
|
-
async removeHandle(handle) {
|
|
2808
|
-
const db = this.ensureDb();
|
|
2809
|
-
const normalized = validateHandle(handle);
|
|
2810
|
-
db.run("DELETE FROM handle_history WHERE handle = ?", [normalized]);
|
|
2811
|
-
db.run("DELETE FROM handle_registry WHERE handle = ?", [normalized]);
|
|
2812
|
-
}
|
|
2813
|
-
async renameHandle(oldHandle, newHandle) {
|
|
2814
|
-
const db = this.ensureDb();
|
|
2815
|
-
const normalizedOld = validateHandle(oldHandle);
|
|
2816
|
-
const normalizedNew = validateHandle(newHandle);
|
|
2817
|
-
if (normalizedOld === normalizedNew) return;
|
|
2818
|
-
const checkOld = db.prepare("SELECT handle FROM handle_registry WHERE handle = ?");
|
|
2819
|
-
checkOld.bind([normalizedOld]);
|
|
2820
|
-
const oldExists = checkOld.step();
|
|
2821
|
-
checkOld.free();
|
|
2822
|
-
if (!oldExists) throw new Error(`Handle '${oldHandle}' not found.`);
|
|
2823
|
-
const checkNew = db.prepare("SELECT handle FROM handle_registry WHERE handle = ?");
|
|
2824
|
-
checkNew.bind([normalizedNew]);
|
|
2825
|
-
const newExists = checkNew.step();
|
|
2826
|
-
checkNew.free();
|
|
2827
|
-
if (newExists) throw new Error(`Handle '${newHandle}' already exists.`);
|
|
2828
|
-
db.run("UPDATE handle_registry SET handle = ? WHERE handle = ?", [normalizedNew, normalizedOld]);
|
|
2829
|
-
db.run("UPDATE handle_history SET handle = ? WHERE handle = ?", [normalizedNew, normalizedOld]);
|
|
2830
|
-
}
|
|
2831
|
-
async deleteHistoryEntry(handle, previousHash) {
|
|
2832
|
-
const db = this.ensureDb();
|
|
2833
|
-
const normalized = validateHandle(handle);
|
|
2834
|
-
const rOutStmt = db.prepare(
|
|
2835
|
-
"SELECT id, previous_hash FROM handle_history WHERE handle = ? AND previous_hash = ? ORDER BY id DESC LIMIT 1"
|
|
2836
|
-
);
|
|
2837
|
-
rOutStmt.bind([normalized, previousHash]);
|
|
2838
|
-
if (!rOutStmt.step()) {
|
|
2839
|
-
rOutStmt.free();
|
|
2840
|
-
return;
|
|
2841
|
-
}
|
|
2842
|
-
const rOutId = rOutStmt.get()[0];
|
|
2843
|
-
rOutStmt.free();
|
|
2844
|
-
const rInStmt = db.prepare(
|
|
2845
|
-
"SELECT id, previous_hash FROM handle_history WHERE handle = ? AND id < ? ORDER BY id DESC LIMIT 1"
|
|
2846
|
-
);
|
|
2847
|
-
rInStmt.bind([normalized, rOutId]);
|
|
2848
|
-
const hasRIn = rInStmt.step();
|
|
2849
|
-
if (hasRIn) {
|
|
2850
|
-
const rInPrevHash = rInStmt.get()[1];
|
|
2851
|
-
const rInId = rInStmt.get()[0];
|
|
2852
|
-
rInStmt.free();
|
|
2853
|
-
db.run("UPDATE handle_history SET previous_hash = ? WHERE id = ?", [rInPrevHash, rOutId]);
|
|
2854
|
-
db.run("DELETE FROM handle_history WHERE id = ?", [rInId]);
|
|
2855
|
-
} else {
|
|
2856
|
-
rInStmt.free();
|
|
2857
|
-
db.run("DELETE FROM handle_history WHERE id = ?", [rOutId]);
|
|
2858
|
-
}
|
|
2859
|
-
}
|
|
2860
2959
|
};
|
|
2861
2960
|
|
|
2862
2961
|
// src/index.browser.ts
|