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
|
@@ -0,0 +1,907 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createPage
|
|
3
|
+
} from "./chunk-3EIBJPNF.js";
|
|
4
|
+
import {
|
|
5
|
+
init_Handle,
|
|
6
|
+
validateHandle
|
|
7
|
+
} from "./chunk-ADV52544.js";
|
|
8
|
+
import {
|
|
9
|
+
DEFAULT_PAGE_SIZE
|
|
10
|
+
} from "./chunk-3MMMJ7NH.js";
|
|
11
|
+
|
|
12
|
+
// src/storage/schema_constants.ts
|
|
13
|
+
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
|
|
14
|
+
-- MCard Unified Database Schema (Monadic Core)
|
|
15
|
+
-- \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
|
|
16
|
+
--
|
|
17
|
+
-- STABILITY WARNING: This schema is the invariant "seeding meta-language" for all
|
|
18
|
+
-- Domain Specific Languages (DSLs). It must remain as stable as possible.
|
|
19
|
+
--
|
|
20
|
+
-- THE UNIFICATION THESIS:
|
|
21
|
+
-- This design unites three distinct namespaces into a single relational network
|
|
22
|
+
-- by leveraging the power of cryptographic hash functions:
|
|
23
|
+
-- 1. CONTENT SPACE (Intrinsic Identity): Content-Addressable Storage (CAS).
|
|
24
|
+
-- 2. HANDLE SPACE (Reserved Words): Mapping human logic to content hashes.
|
|
25
|
+
-- 3. VERSION SPACE (Temporal Evolution): Tracking state transitions via hash history.
|
|
26
|
+
--
|
|
27
|
+
-- TURING MACHINE ANALOGY (The Infinitely Long Tape):
|
|
28
|
+
-- The \`card\` table stores content blobs with unique identities, emulating the
|
|
29
|
+
-- "Infinitely Long Tape" of the Turing Machine formalism. By using relational
|
|
30
|
+
-- queries, this tape can be dynamically constructed and traversed for different
|
|
31
|
+
-- DSLs, providing a flexible substrate for practically all computable languages.
|
|
32
|
+
--
|
|
33
|
+
-- By using hash values as the universal primitives across content, handles, and
|
|
34
|
+
-- time, we create a "Wordless Book" \u2014 a minimal substrate capable of seeding any
|
|
35
|
+
-- domain-specific knowledge system without requiring schema changes.
|
|
36
|
+
--
|
|
37
|
+
-- Monadic Mapping (See: Monadic Justification for Schema Design.md):
|
|
38
|
+
-- 1. Card = Monad (Perception/State/Exponent) - Intrinsic Identity
|
|
39
|
+
-- 2. Handle = Registry (Appetition/Reader/Sum) - Mutable Reference
|
|
40
|
+
-- 3. Version = History (Harmony/Writer/Product) - Coordinated Evolution
|
|
41
|
+
--
|
|
42
|
+
-- Version: 3.0.2 (Turing Tape Refinement)
|
|
43
|
+
-- Last Updated: 2025-12-20
|
|
44
|
+
-- \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
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
-- \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
|
|
48
|
+
-- LAYER 1: CORE CONTENT-ADDRESSABLE STORAGE (The Monad / Exponent)
|
|
49
|
+
-- \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
|
|
50
|
+
-- The fundamental MCard storage: content-addressed by cryptographic hash.
|
|
51
|
+
-- "Each Monad ... mirrors the universe"
|
|
52
|
+
|
|
53
|
+
-- @table card
|
|
54
|
+
-- @description Core content-addressable storage table (Monad/State)
|
|
55
|
+
-- @column hash - SHA-256 hash of content (primary key)
|
|
56
|
+
-- @column content - The actual content (BLOB for binary safety)
|
|
57
|
+
-- @column g_time - Generation timestamp (ISO 8601)
|
|
58
|
+
CREATE TABLE IF NOT EXISTS card (
|
|
59
|
+
hash TEXT PRIMARY KEY,
|
|
60
|
+
content BLOB NOT NULL,
|
|
61
|
+
g_time TEXT NOT NULL
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
-- \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
|
|
66
|
+
-- LAYER 2: HANDLE SYSTEM (Appetition / Sum)
|
|
67
|
+
-- \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
|
|
68
|
+
-- The mutable pointer that "desires" to reference new content.
|
|
69
|
+
-- "Appetition: the tendency to move to new states"
|
|
70
|
+
|
|
71
|
+
-- @table handle_registry (Monadic Role: Handle)
|
|
72
|
+
-- @description Maps human-readable handles to current content hashes
|
|
73
|
+
-- @column handle - UTF-8 handle name (primary key)
|
|
74
|
+
-- @column current_hash - FK to card.hash of current version
|
|
75
|
+
-- @column created_at - When handle was first created
|
|
76
|
+
-- @column updated_at - When handle was last updated
|
|
77
|
+
CREATE TABLE IF NOT EXISTS handle_registry (
|
|
78
|
+
handle TEXT PRIMARY KEY,
|
|
79
|
+
current_hash TEXT NOT NULL,
|
|
80
|
+
created_at TEXT NOT NULL,
|
|
81
|
+
updated_at TEXT NOT NULL,
|
|
82
|
+
FOREIGN KEY (current_hash) REFERENCES card(hash)
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
-- @index idx_handle_current_hash
|
|
86
|
+
-- @description Efficient reverse lookup from hash to handles
|
|
87
|
+
CREATE INDEX IF NOT EXISTS idx_handle_current_hash
|
|
88
|
+
ON handle_registry(current_hash);
|
|
89
|
+
|
|
90
|
+
-- @table handle_history (Monadic Role: Version / Product)
|
|
91
|
+
-- @description Audit trail for handle pointer changes (Pre-Established Harmony)
|
|
92
|
+
-- @column id - Auto-increment primary key
|
|
93
|
+
-- @column handle - The handle that was updated
|
|
94
|
+
-- @column previous_hash - Hash it pointed to before update
|
|
95
|
+
-- @column changed_at - When the change occurred
|
|
96
|
+
CREATE TABLE IF NOT EXISTS handle_history (
|
|
97
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
98
|
+
handle TEXT NOT NULL,
|
|
99
|
+
previous_hash TEXT NOT NULL,
|
|
100
|
+
changed_at TEXT NOT NULL,
|
|
101
|
+
FOREIGN KEY (handle) REFERENCES handle_registry(handle),
|
|
102
|
+
FOREIGN KEY (previous_hash) REFERENCES card(hash)
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
-- @index idx_handle_history_handle
|
|
106
|
+
-- @description Efficient lookup of history by handle
|
|
107
|
+
CREATE INDEX IF NOT EXISTS idx_handle_history_handle
|
|
108
|
+
ON handle_history(handle);
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
-- \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
|
|
112
|
+
-- LEGACY SUPPORT: FTS5 Documents Table
|
|
113
|
+
-- \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
|
|
114
|
+
-- KEPT FOR BACKWARD COMPATIBILITY with existing codebase.
|
|
115
|
+
-- New implementations should use mcard_vector_schema.sql -> mcard_fts
|
|
116
|
+
|
|
117
|
+
-- @virtual_table documents
|
|
118
|
+
-- @description Legacy FTS table for backward compatibility
|
|
119
|
+
-- @note Synced with card table via triggers
|
|
120
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS documents USING fts5(content);
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
-- \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
|
|
124
|
+
-- SCHEMA METADATA
|
|
125
|
+
-- \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
|
|
126
|
+
|
|
127
|
+
-- @table schema_version
|
|
128
|
+
-- @description Tracks schema version for migrations
|
|
129
|
+
CREATE TABLE IF NOT EXISTS schema_version (
|
|
130
|
+
version TEXT PRIMARY KEY,
|
|
131
|
+
applied_at TEXT NOT NULL,
|
|
132
|
+
description TEXT
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
-- Insert current schema version
|
|
136
|
+
INSERT OR IGNORE INTO schema_version (version, applied_at, description)
|
|
137
|
+
VALUES ('3.0.0', datetime('now'), 'Monadic Core Schema (split vectors to mcard_vector_schema.sql)');
|
|
138
|
+
`;
|
|
139
|
+
var MCARD_VECTOR_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
|
|
140
|
+
-- MCard Vector Database Schema (mcard_vectors.db)
|
|
141
|
+
-- \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
|
|
142
|
+
--
|
|
143
|
+
-- This schema defines the structure for "Secondary Qualities" (Extrinsic Embeddings).
|
|
144
|
+
-- It is separated from the core mcard.db (Monadic Intrinsic Properties) to ensure:
|
|
145
|
+
-- 1. Separation of Concerns (Intrinsic vs Extrinsic)
|
|
146
|
+
-- 2. Linearity (Vectors are observer-dependent and large)
|
|
147
|
+
-- 3. Upgradability (Embedding models change frequently)
|
|
148
|
+
--
|
|
149
|
+
-- See: Monadic Justification for Schema Design.md
|
|
150
|
+
-- \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
|
|
151
|
+
|
|
152
|
+
-- \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
|
|
153
|
+
-- LAYER 3: VECTOR STORAGE (Semantic Embeddings)
|
|
154
|
+
-- \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
|
|
155
|
+
-- Storage for vector embeddings enabling semantic search.
|
|
156
|
+
-- Links to content via hash for content-addressing.
|
|
157
|
+
|
|
158
|
+
-- @table mcard_vector_metadata
|
|
159
|
+
-- @description Metadata for stored embeddings
|
|
160
|
+
-- @column id - Auto-increment primary key
|
|
161
|
+
-- @column hash - FK to card.hash
|
|
162
|
+
-- @column model_name - Embedding model used (e.g., "nomic-embed-text")
|
|
163
|
+
-- @column dimensions - Vector dimensions
|
|
164
|
+
-- @column chunk_index - Index for chunked documents (0 = first/whole)
|
|
165
|
+
-- @column chunk_total - Total chunks for this document
|
|
166
|
+
-- @column chunk_text - Preview text for this chunk
|
|
167
|
+
-- @column created_at - When embedding was created
|
|
168
|
+
CREATE TABLE IF NOT EXISTS mcard_vector_metadata (
|
|
169
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
170
|
+
hash TEXT NOT NULL,
|
|
171
|
+
model_name TEXT NOT NULL,
|
|
172
|
+
dimensions INTEGER NOT NULL,
|
|
173
|
+
chunk_index INTEGER DEFAULT 0,
|
|
174
|
+
chunk_total INTEGER DEFAULT 1,
|
|
175
|
+
chunk_text TEXT,
|
|
176
|
+
created_at TEXT NOT NULL,
|
|
177
|
+
UNIQUE(hash, chunk_index)
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
-- @index idx_vector_metadata_hash
|
|
181
|
+
-- @description Efficient lookup of embeddings by content hash
|
|
182
|
+
CREATE INDEX IF NOT EXISTS idx_vector_metadata_hash
|
|
183
|
+
ON mcard_vector_metadata(hash);
|
|
184
|
+
|
|
185
|
+
-- @table mcard_embeddings
|
|
186
|
+
-- @description Fallback embedding storage when sqlite-vec is unavailable
|
|
187
|
+
-- @column id - Auto-increment primary key
|
|
188
|
+
-- @column metadata_id - FK to mcard_vector_metadata.id
|
|
189
|
+
-- @column embedding - Serialized float32 vector as BLOB
|
|
190
|
+
CREATE TABLE IF NOT EXISTS mcard_embeddings (
|
|
191
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
192
|
+
metadata_id INTEGER NOT NULL,
|
|
193
|
+
embedding BLOB NOT NULL,
|
|
194
|
+
UNIQUE(metadata_id),
|
|
195
|
+
FOREIGN KEY (metadata_id) REFERENCES mcard_vector_metadata(id)
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
-- @virtual_table mcard_fts
|
|
199
|
+
-- @description Full-text search for hybrid retrieval
|
|
200
|
+
-- @note Uses Porter stemming with Unicode support
|
|
201
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS mcard_fts USING fts5(
|
|
202
|
+
hash,
|
|
203
|
+
content,
|
|
204
|
+
tokenize='porter unicode61'
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
-- Note: sqlite-vec virtual table is created dynamically with dimensions:
|
|
208
|
+
-- CREATE VIRTUAL TABLE IF NOT EXISTS mcard_vec USING vec0(
|
|
209
|
+
-- metadata_id INTEGER PRIMARY KEY,
|
|
210
|
+
-- embedding float[\${dimensions}]
|
|
211
|
+
-- );
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
-- \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
|
|
215
|
+
-- LAYER 4: SEMANTIC VERSIONING (Handle-Vector Bridge)
|
|
216
|
+
-- \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
|
|
217
|
+
-- Bridges handles to vector embeddings for semantic version comparison.
|
|
218
|
+
-- Enables measuring semantic drift between document versions.
|
|
219
|
+
|
|
220
|
+
-- @table handle_version_vectors
|
|
221
|
+
-- @description Links handle versions to their semantic embeddings
|
|
222
|
+
-- @column id - Auto-increment primary key
|
|
223
|
+
-- @column handle - FK to handle_registry.handle
|
|
224
|
+
-- @column hash - FK to card.hash (this version)
|
|
225
|
+
-- @column parent_hash - FK to card.hash (previous version)
|
|
226
|
+
-- @column version_order - 0 = current, 1 = previous, etc.
|
|
227
|
+
-- @column is_current - TRUE if this is the current version
|
|
228
|
+
-- @column embedding_id - FK to mcard_vector_metadata.id
|
|
229
|
+
-- @column semantic_delta_from_parent - Cosine similarity to parent [-1, 1]
|
|
230
|
+
-- @column upgrade_type - Classification: 'trivial' | 'minor' | 'major' | 'breaking'
|
|
231
|
+
-- @column created_at - When this version was linked
|
|
232
|
+
CREATE TABLE IF NOT EXISTS handle_version_vectors (
|
|
233
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
234
|
+
handle TEXT NOT NULL,
|
|
235
|
+
hash TEXT NOT NULL,
|
|
236
|
+
parent_hash TEXT,
|
|
237
|
+
version_order INTEGER NOT NULL,
|
|
238
|
+
is_current BOOLEAN DEFAULT FALSE,
|
|
239
|
+
embedding_id INTEGER,
|
|
240
|
+
semantic_delta_from_parent REAL,
|
|
241
|
+
upgrade_type TEXT,
|
|
242
|
+
created_at TEXT NOT NULL,
|
|
243
|
+
UNIQUE(handle, hash),
|
|
244
|
+
FOREIGN KEY (embedding_id) REFERENCES mcard_vector_metadata(id)
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
-- @index idx_hvv_handle
|
|
248
|
+
-- @description Efficient lookup of versions by handle
|
|
249
|
+
CREATE INDEX IF NOT EXISTS idx_hvv_handle
|
|
250
|
+
ON handle_version_vectors(handle);
|
|
251
|
+
|
|
252
|
+
-- @index idx_hvv_hash
|
|
253
|
+
-- @description Efficient lookup of versions by hash
|
|
254
|
+
CREATE INDEX IF NOT EXISTS idx_hvv_hash
|
|
255
|
+
ON handle_version_vectors(hash);
|
|
256
|
+
|
|
257
|
+
-- @index idx_hvv_current
|
|
258
|
+
-- @description Efficient lookup of current versions
|
|
259
|
+
CREATE INDEX IF NOT EXISTS idx_hvv_current
|
|
260
|
+
ON handle_version_vectors(is_current);
|
|
261
|
+
|
|
262
|
+
-- @index idx_hvv_parent
|
|
263
|
+
-- @description Efficient lookup by parent hash
|
|
264
|
+
CREATE INDEX IF NOT EXISTS idx_hvv_parent
|
|
265
|
+
ON handle_version_vectors(parent_hash);
|
|
266
|
+
|
|
267
|
+
-- @table version_similarity_cache
|
|
268
|
+
-- @description Precomputed pairwise similarities for performance
|
|
269
|
+
-- @column id - Auto-increment primary key
|
|
270
|
+
-- @column handle - Handle these versions belong to
|
|
271
|
+
-- @column hash_a - First version hash
|
|
272
|
+
-- @column hash_b - Second version hash
|
|
273
|
+
-- @column similarity_score - Cosine similarity [-1, 1]
|
|
274
|
+
-- @column distance_euclidean - L2 distance [0, \u221E)
|
|
275
|
+
-- @column computed_at - When similarity was computed
|
|
276
|
+
CREATE TABLE IF NOT EXISTS version_similarity_cache (
|
|
277
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
278
|
+
handle TEXT NOT NULL,
|
|
279
|
+
hash_a TEXT NOT NULL,
|
|
280
|
+
hash_b TEXT NOT NULL,
|
|
281
|
+
similarity_score REAL NOT NULL,
|
|
282
|
+
distance_euclidean REAL,
|
|
283
|
+
computed_at TEXT NOT NULL,
|
|
284
|
+
UNIQUE(handle, hash_a, hash_b)
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
-- @index idx_vsc_handle
|
|
288
|
+
-- @description Efficient lookup of cached similarities by handle
|
|
289
|
+
CREATE INDEX IF NOT EXISTS idx_vsc_handle
|
|
290
|
+
ON version_similarity_cache(handle);
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
-- \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
|
|
294
|
+
-- LAYER 5: KNOWLEDGE GRAPH (GraphRAG)
|
|
295
|
+
-- \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
|
|
296
|
+
-- Storage for extracted knowledge graph entities and relationships.
|
|
297
|
+
|
|
298
|
+
-- @table graph_entities
|
|
299
|
+
-- @description Nodes in the knowledge graph
|
|
300
|
+
-- @column id - Auto-increment primary key
|
|
301
|
+
-- @column name - Entity name
|
|
302
|
+
-- @column type - Entity type (e.g., "Person", "Organization")
|
|
303
|
+
-- @column description - Optional description
|
|
304
|
+
-- @column source_hash - FK to card.hash where entity was extracted
|
|
305
|
+
-- @column embedding - Optional entity embedding
|
|
306
|
+
-- @column created_at - When entity was created
|
|
307
|
+
CREATE TABLE IF NOT EXISTS graph_entities (
|
|
308
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
309
|
+
name TEXT NOT NULL,
|
|
310
|
+
type TEXT NOT NULL,
|
|
311
|
+
description TEXT,
|
|
312
|
+
source_hash TEXT NOT NULL,
|
|
313
|
+
embedding BLOB,
|
|
314
|
+
created_at TEXT NOT NULL,
|
|
315
|
+
UNIQUE(name, type, source_hash)
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
-- @index idx_entity_name
|
|
319
|
+
-- @description Efficient entity lookup by name
|
|
320
|
+
CREATE INDEX IF NOT EXISTS idx_entity_name
|
|
321
|
+
ON graph_entities(name);
|
|
322
|
+
|
|
323
|
+
-- @index idx_entity_type
|
|
324
|
+
-- @description Efficient entity lookup by type
|
|
325
|
+
CREATE INDEX IF NOT EXISTS idx_entity_type
|
|
326
|
+
ON graph_entities(type);
|
|
327
|
+
|
|
328
|
+
-- @index idx_entity_source
|
|
329
|
+
-- @description Efficient entity lookup by source document
|
|
330
|
+
CREATE INDEX IF NOT EXISTS idx_entity_source
|
|
331
|
+
ON graph_entities(source_hash);
|
|
332
|
+
|
|
333
|
+
-- @table graph_relationships
|
|
334
|
+
-- @description Edges in the knowledge graph
|
|
335
|
+
-- @column id - Auto-increment primary key
|
|
336
|
+
-- @column source_entity_id - FK to graph_entities.id (from)
|
|
337
|
+
-- @column target_entity_id - FK to graph_entities.id (to)
|
|
338
|
+
-- @column relationship - Relationship type/label
|
|
339
|
+
-- @column description - Optional description
|
|
340
|
+
-- @column weight - Relationship strength
|
|
341
|
+
-- @column source_hash - FK to card.hash where relationship was extracted
|
|
342
|
+
-- @column created_at - When relationship was created
|
|
343
|
+
CREATE TABLE IF NOT EXISTS graph_relationships (
|
|
344
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
345
|
+
source_entity_id INTEGER NOT NULL,
|
|
346
|
+
target_entity_id INTEGER NOT NULL,
|
|
347
|
+
relationship TEXT NOT NULL,
|
|
348
|
+
description TEXT,
|
|
349
|
+
weight REAL DEFAULT 1.0,
|
|
350
|
+
source_hash TEXT NOT NULL,
|
|
351
|
+
created_at TEXT NOT NULL,
|
|
352
|
+
UNIQUE(source_entity_id, target_entity_id, relationship, source_hash),
|
|
353
|
+
FOREIGN KEY (source_entity_id) REFERENCES graph_entities(id),
|
|
354
|
+
FOREIGN KEY (target_entity_id) REFERENCES graph_entities(id)
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
-- @index idx_rel_source
|
|
358
|
+
-- @description Efficient lookup of relationships by source entity
|
|
359
|
+
CREATE INDEX IF NOT EXISTS idx_rel_source
|
|
360
|
+
ON graph_relationships(source_entity_id);
|
|
361
|
+
|
|
362
|
+
-- @index idx_rel_target
|
|
363
|
+
-- @description Efficient lookup of relationships by target entity
|
|
364
|
+
CREATE INDEX IF NOT EXISTS idx_rel_target
|
|
365
|
+
ON graph_relationships(target_entity_id);
|
|
366
|
+
|
|
367
|
+
-- @table graph_communities
|
|
368
|
+
-- @description Hierarchical community summaries (GraphRAG)
|
|
369
|
+
-- @column id - Auto-increment primary key
|
|
370
|
+
-- @column level - Hierarchy level (0 = leaf)
|
|
371
|
+
-- @column title - Community title
|
|
372
|
+
-- @column summary - AI-generated summary
|
|
373
|
+
-- @column embedding - Community embedding
|
|
374
|
+
-- @column member_entity_ids - JSON array of entity IDs
|
|
375
|
+
-- @column parent_community_id - FK to parent community
|
|
376
|
+
-- @column created_at - When community was created
|
|
377
|
+
CREATE TABLE IF NOT EXISTS graph_communities (
|
|
378
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
379
|
+
level INTEGER NOT NULL DEFAULT 0,
|
|
380
|
+
title TEXT,
|
|
381
|
+
summary TEXT NOT NULL,
|
|
382
|
+
embedding BLOB,
|
|
383
|
+
member_entity_ids TEXT,
|
|
384
|
+
parent_community_id INTEGER,
|
|
385
|
+
created_at TEXT NOT NULL,
|
|
386
|
+
FOREIGN KEY (parent_community_id) REFERENCES graph_communities(id)
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
-- @index idx_community_level
|
|
390
|
+
-- @description Efficient lookup of communities by level
|
|
391
|
+
CREATE INDEX IF NOT EXISTS idx_community_level
|
|
392
|
+
ON graph_communities(level);
|
|
393
|
+
|
|
394
|
+
-- @table graph_extractions
|
|
395
|
+
-- @description Tracks which documents have been processed for entity extraction
|
|
396
|
+
-- @column hash - FK to card.hash (primary key)
|
|
397
|
+
-- @column entity_count - Number of entities extracted
|
|
398
|
+
-- @column relationship_count - Number of relationships extracted
|
|
399
|
+
-- @column extracted_at - When extraction was performed
|
|
400
|
+
CREATE TABLE IF NOT EXISTS graph_extractions (
|
|
401
|
+
hash TEXT PRIMARY KEY,
|
|
402
|
+
entity_count INTEGER DEFAULT 0,
|
|
403
|
+
relationship_count INTEGER DEFAULT 0,
|
|
404
|
+
extracted_at TEXT NOT NULL
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
-- \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
|
|
408
|
+
-- SCHEMA METADATA (Vector DB)
|
|
409
|
+
-- \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
|
|
410
|
+
|
|
411
|
+
-- @table schema_version
|
|
412
|
+
-- @description Tracks schema version for migrations
|
|
413
|
+
CREATE TABLE IF NOT EXISTS vector_schema_version (
|
|
414
|
+
version TEXT PRIMARY KEY,
|
|
415
|
+
applied_at TEXT NOT NULL,
|
|
416
|
+
description TEXT
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
-- Insert current schema version
|
|
420
|
+
INSERT OR IGNORE INTO vector_schema_version (version, applied_at, description)
|
|
421
|
+
VALUES ('1.0.0', datetime('now'), 'Initial MCard Vector Schema');
|
|
422
|
+
`;
|
|
423
|
+
|
|
424
|
+
// src/storage/schema.ts
|
|
425
|
+
var TABLE_LAYERS = {
|
|
426
|
+
// Layer 1: Core
|
|
427
|
+
"card": "core",
|
|
428
|
+
// Layer 2: Handle System
|
|
429
|
+
"handle_registry": "handle",
|
|
430
|
+
"handle_history": "handle",
|
|
431
|
+
// Layer 3: Vector Storage
|
|
432
|
+
"mcard_vector_metadata": "vector",
|
|
433
|
+
"mcard_embeddings": "vector",
|
|
434
|
+
"mcard_fts": "vector",
|
|
435
|
+
// Layer 4: Semantic Versioning
|
|
436
|
+
"handle_version_vectors": "semantic",
|
|
437
|
+
"version_similarity_cache": "semantic",
|
|
438
|
+
// Layer 5: Knowledge Graph
|
|
439
|
+
"graph_entities": "graph",
|
|
440
|
+
"graph_relationships": "graph",
|
|
441
|
+
"graph_communities": "graph",
|
|
442
|
+
"graph_extractions": "graph",
|
|
443
|
+
// Metadata
|
|
444
|
+
"schema_version": "metadata"
|
|
445
|
+
};
|
|
446
|
+
var MCardSchema = class _MCardSchema {
|
|
447
|
+
static instance = null;
|
|
448
|
+
schemaPath = "";
|
|
449
|
+
rawSql = "";
|
|
450
|
+
statements = [];
|
|
451
|
+
tables = /* @__PURE__ */ new Map();
|
|
452
|
+
indexes = /* @__PURE__ */ new Map();
|
|
453
|
+
loaded = false;
|
|
454
|
+
constructor() {
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Get the singleton instance.
|
|
458
|
+
*/
|
|
459
|
+
static getInstance() {
|
|
460
|
+
if (!_MCardSchema.instance) {
|
|
461
|
+
_MCardSchema.instance = new _MCardSchema();
|
|
462
|
+
_MCardSchema.instance.load();
|
|
463
|
+
}
|
|
464
|
+
return _MCardSchema.instance;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Reset the singleton (for testing).
|
|
468
|
+
*/
|
|
469
|
+
static resetInstance() {
|
|
470
|
+
_MCardSchema.instance = null;
|
|
471
|
+
}
|
|
472
|
+
load() {
|
|
473
|
+
if (this.loaded) return;
|
|
474
|
+
this.schemaPath = "IN_MEMORY_CONSTANTS";
|
|
475
|
+
this.rawSql = MCARD_SCHEMA_SQL;
|
|
476
|
+
if (MCARD_VECTOR_SCHEMA_SQL) {
|
|
477
|
+
this.rawSql += "\n\n" + MCARD_VECTOR_SCHEMA_SQL;
|
|
478
|
+
}
|
|
479
|
+
this.statements = this.parseStatements(this.rawSql);
|
|
480
|
+
for (const stmt of this.statements) {
|
|
481
|
+
const name = this.extractName(stmt);
|
|
482
|
+
if (name) {
|
|
483
|
+
const upper = stmt.toUpperCase();
|
|
484
|
+
if (upper.includes("CREATE TABLE") || upper.includes("CREATE VIRTUAL TABLE")) {
|
|
485
|
+
this.tables.set(name.toLowerCase(), stmt);
|
|
486
|
+
} else if (upper.includes("CREATE INDEX")) {
|
|
487
|
+
this.indexes.set(name.toLowerCase(), stmt);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
this.loaded = true;
|
|
492
|
+
}
|
|
493
|
+
parseStatements(sql) {
|
|
494
|
+
sql = sql.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
495
|
+
const statements = [];
|
|
496
|
+
let current = [];
|
|
497
|
+
for (const line of sql.split("\n")) {
|
|
498
|
+
const stripped = line.split("--")[0].trim();
|
|
499
|
+
if (!stripped) continue;
|
|
500
|
+
current.push(stripped);
|
|
501
|
+
if (stripped.endsWith(";")) {
|
|
502
|
+
const statement = current.join(" ");
|
|
503
|
+
if (!statement.trim().toUpperCase().startsWith("INSERT")) {
|
|
504
|
+
statements.push(statement);
|
|
505
|
+
}
|
|
506
|
+
current = [];
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return statements.filter((s) => s.trim());
|
|
510
|
+
}
|
|
511
|
+
extractName(statement) {
|
|
512
|
+
let match = statement.match(/CREATE\s+(?:VIRTUAL\s+)?TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)/i);
|
|
513
|
+
if (match) return match[1];
|
|
514
|
+
match = statement.match(/CREATE\s+INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?(\w+)/i);
|
|
515
|
+
if (match) return match[1];
|
|
516
|
+
return null;
|
|
517
|
+
}
|
|
518
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
519
|
+
// Schema Access
|
|
520
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
521
|
+
getSchemaPath() {
|
|
522
|
+
return this.schemaPath;
|
|
523
|
+
}
|
|
524
|
+
getTable(tableName) {
|
|
525
|
+
return this.tables.get(tableName.toLowerCase());
|
|
526
|
+
}
|
|
527
|
+
getIndex(indexName) {
|
|
528
|
+
return this.indexes.get(indexName.toLowerCase());
|
|
529
|
+
}
|
|
530
|
+
getAllTables() {
|
|
531
|
+
return new Map(this.tables);
|
|
532
|
+
}
|
|
533
|
+
getAllIndexes() {
|
|
534
|
+
return new Map(this.indexes);
|
|
535
|
+
}
|
|
536
|
+
getAllStatements() {
|
|
537
|
+
return [...this.statements];
|
|
538
|
+
}
|
|
539
|
+
getTablesByLayer(layer) {
|
|
540
|
+
return Object.entries(TABLE_LAYERS).filter(([_, l]) => l === layer).map(([name, _]) => name);
|
|
541
|
+
}
|
|
542
|
+
getLayerStatements(layer) {
|
|
543
|
+
const statements = [];
|
|
544
|
+
const tables = this.getTablesByLayer(layer);
|
|
545
|
+
for (const table of tables) {
|
|
546
|
+
const stmt = this.getTable(table);
|
|
547
|
+
if (stmt) statements.push(stmt);
|
|
548
|
+
}
|
|
549
|
+
for (const [_, stmt] of this.indexes) {
|
|
550
|
+
const match = stmt.match(/ON\s+(\w+)/i);
|
|
551
|
+
if (match && tables.includes(match[1].toLowerCase())) {
|
|
552
|
+
statements.push(stmt);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return statements;
|
|
556
|
+
}
|
|
557
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
558
|
+
// Database Initialization
|
|
559
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
560
|
+
execStatements(db, statements) {
|
|
561
|
+
for (const stmt of statements) {
|
|
562
|
+
db.exec(stmt);
|
|
563
|
+
}
|
|
564
|
+
return statements.length;
|
|
565
|
+
}
|
|
566
|
+
initLayer(db, layer) {
|
|
567
|
+
return this.execStatements(db, this.getLayerStatements(layer));
|
|
568
|
+
}
|
|
569
|
+
initCoreTables(db) {
|
|
570
|
+
return this.initLayer(db, "core");
|
|
571
|
+
}
|
|
572
|
+
initHandleTables(db) {
|
|
573
|
+
return this.initLayer(db, "handle");
|
|
574
|
+
}
|
|
575
|
+
initVectorTables(db, enableFts = true) {
|
|
576
|
+
const statements = this.getLayerStatements("vector").filter((s) => enableFts || !s.toLowerCase().includes("fts"));
|
|
577
|
+
return this.execStatements(db, statements);
|
|
578
|
+
}
|
|
579
|
+
initSemanticTables(db) {
|
|
580
|
+
return this.initLayer(db, "semantic");
|
|
581
|
+
}
|
|
582
|
+
initGraphTables(db) {
|
|
583
|
+
return this.initLayer(db, "graph");
|
|
584
|
+
}
|
|
585
|
+
initAllTables(db, options = {}) {
|
|
586
|
+
const { enableFts = true, enableGraph = true, enableSemantic = true } = options;
|
|
587
|
+
let count = 0;
|
|
588
|
+
count += this.initCoreTables(db);
|
|
589
|
+
count += this.initHandleTables(db);
|
|
590
|
+
count += this.initVectorTables(db, enableFts);
|
|
591
|
+
if (enableSemantic) {
|
|
592
|
+
count += this.initSemanticTables(db);
|
|
593
|
+
}
|
|
594
|
+
if (enableGraph) {
|
|
595
|
+
count += this.initGraphTables(db);
|
|
596
|
+
}
|
|
597
|
+
return count;
|
|
598
|
+
}
|
|
599
|
+
initVec0Table(db, dimensions) {
|
|
600
|
+
db.exec(`
|
|
601
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS mcard_vec USING vec0(
|
|
602
|
+
metadata_id INTEGER PRIMARY KEY,
|
|
603
|
+
embedding float[${dimensions}]
|
|
604
|
+
)
|
|
605
|
+
`);
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
function getSchemaInstance() {
|
|
609
|
+
return MCardSchema.getInstance();
|
|
610
|
+
}
|
|
611
|
+
var CARD_TABLE_SCHEMA = getSchemaInstance().getTable("card") || "";
|
|
612
|
+
var HANDLE_REGISTRY_SCHEMA = getSchemaInstance().getTable("handle_registry") || "";
|
|
613
|
+
var HANDLE_HISTORY_SCHEMA = getSchemaInstance().getTable("handle_history") || "";
|
|
614
|
+
var HANDLE_INDEX_SCHEMA = getSchemaInstance().getIndex("idx_handle_current_hash") || "";
|
|
615
|
+
var VECTOR_METADATA_SCHEMA = getSchemaInstance().getTable("mcard_vector_metadata") || "";
|
|
616
|
+
var VECTOR_METADATA_INDEX = getSchemaInstance().getIndex("idx_vector_metadata_hash") || "";
|
|
617
|
+
var VECTOR_EMBEDDINGS_SCHEMA = getSchemaInstance().getTable("mcard_embeddings") || "";
|
|
618
|
+
var VECTOR_FTS_SCHEMA = getSchemaInstance().getTable("mcard_fts") || "";
|
|
619
|
+
var HANDLE_VERSION_VECTORS_SCHEMA = getSchemaInstance().getTable("handle_version_vectors") || "";
|
|
620
|
+
var HANDLE_VERSION_VECTORS_INDEXES = [
|
|
621
|
+
getSchemaInstance().getIndex("idx_hvv_handle"),
|
|
622
|
+
getSchemaInstance().getIndex("idx_hvv_hash"),
|
|
623
|
+
getSchemaInstance().getIndex("idx_hvv_current"),
|
|
624
|
+
getSchemaInstance().getIndex("idx_hvv_parent")
|
|
625
|
+
].filter(Boolean).join("; ");
|
|
626
|
+
var VERSION_SIMILARITY_CACHE_SCHEMA = getSchemaInstance().getTable("version_similarity_cache") || "";
|
|
627
|
+
var VERSION_SIMILARITY_CACHE_INDEX = getSchemaInstance().getIndex("idx_vsc_handle") || "";
|
|
628
|
+
var GRAPH_ENTITY_SCHEMA = getSchemaInstance().getTable("graph_entities") || "";
|
|
629
|
+
var GRAPH_ENTITY_INDEX_NAME = getSchemaInstance().getIndex("idx_entity_name") || "";
|
|
630
|
+
var GRAPH_ENTITY_INDEX_TYPE = getSchemaInstance().getIndex("idx_entity_type") || "";
|
|
631
|
+
var GRAPH_ENTITY_INDEX_SOURCE = getSchemaInstance().getIndex("idx_entity_source") || "";
|
|
632
|
+
var GRAPH_RELATIONSHIP_SCHEMA = getSchemaInstance().getTable("graph_relationships") || "";
|
|
633
|
+
var GRAPH_RELATIONSHIP_INDEX_SOURCE = getSchemaInstance().getIndex("idx_rel_source") || "";
|
|
634
|
+
var GRAPH_RELATIONSHIP_INDEX_TARGET = getSchemaInstance().getIndex("idx_rel_target") || "";
|
|
635
|
+
var GRAPH_COMMUNITY_SCHEMA = getSchemaInstance().getTable("graph_communities") || "";
|
|
636
|
+
var GRAPH_COMMUNITY_INDEX_LEVEL = getSchemaInstance().getIndex("idx_community_level") || "";
|
|
637
|
+
var GRAPH_EXTRACTION_SCHEMA = getSchemaInstance().getTable("graph_extractions") || "";
|
|
638
|
+
var CORE_SCHEMAS = {
|
|
639
|
+
card: CARD_TABLE_SCHEMA,
|
|
640
|
+
handleRegistry: HANDLE_REGISTRY_SCHEMA,
|
|
641
|
+
handleHistory: HANDLE_HISTORY_SCHEMA,
|
|
642
|
+
handleIndex: HANDLE_INDEX_SCHEMA
|
|
643
|
+
};
|
|
644
|
+
function initCoreSchemas(db) {
|
|
645
|
+
const schema = MCardSchema.getInstance();
|
|
646
|
+
schema.initCoreTables(db);
|
|
647
|
+
schema.initHandleTables(db);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// src/storage/engines/AbstractSqlEngine.ts
|
|
651
|
+
init_Handle();
|
|
652
|
+
var AbstractSqlEngine = class {
|
|
653
|
+
/**
|
|
654
|
+
* SQL expression for casting content to text in search queries.
|
|
655
|
+
* Override in subclasses: SQLite uses 'TEXT', DuckDB uses 'VARCHAR'.
|
|
656
|
+
*/
|
|
657
|
+
get castContentAs() {
|
|
658
|
+
return "TEXT";
|
|
659
|
+
}
|
|
660
|
+
// ======================================================================
|
|
661
|
+
// Concrete: Card Operations (shared across all SQL engines)
|
|
662
|
+
// ======================================================================
|
|
663
|
+
/**
|
|
664
|
+
* Add a card. Default uses INSERT OR REPLACE (SQLite).
|
|
665
|
+
* DuckDB overrides with DELETE + INSERT.
|
|
666
|
+
*/
|
|
667
|
+
async add(card) {
|
|
668
|
+
const contentBytes = card.content instanceof Uint8Array ? card.content : new TextEncoder().encode(String(card.content));
|
|
669
|
+
await this.execSql(
|
|
670
|
+
"INSERT OR REPLACE INTO card (hash, content, g_time) VALUES (?, ?, ?)",
|
|
671
|
+
card.hash,
|
|
672
|
+
contentBytes,
|
|
673
|
+
card.g_time
|
|
674
|
+
);
|
|
675
|
+
return card.hash;
|
|
676
|
+
}
|
|
677
|
+
async get(hash) {
|
|
678
|
+
const rows = await this.queryRows(
|
|
679
|
+
"SELECT hash, content, g_time FROM card WHERE hash = ?",
|
|
680
|
+
hash
|
|
681
|
+
);
|
|
682
|
+
if (rows.length === 0) return null;
|
|
683
|
+
return this.rowToCard(rows[0]);
|
|
684
|
+
}
|
|
685
|
+
async delete(hash) {
|
|
686
|
+
await this.execSql("DELETE FROM card WHERE hash = ?", hash);
|
|
687
|
+
}
|
|
688
|
+
async getPage(pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
|
|
689
|
+
if (pageNumber < 1) throw new Error("Page number must be >= 1");
|
|
690
|
+
if (pageSize < 1) throw new Error("Page size must be >= 1");
|
|
691
|
+
const totalItems = await this.count();
|
|
692
|
+
const offset = (pageNumber - 1) * pageSize;
|
|
693
|
+
const rows = await this.queryRows(
|
|
694
|
+
"SELECT hash, content, g_time FROM card ORDER BY g_time DESC LIMIT ? OFFSET ?",
|
|
695
|
+
pageSize,
|
|
696
|
+
offset
|
|
697
|
+
);
|
|
698
|
+
const items = rows.map((r) => this.rowToCard(r));
|
|
699
|
+
return createPage(items, totalItems, pageNumber, pageSize);
|
|
700
|
+
}
|
|
701
|
+
async count() {
|
|
702
|
+
const rows = await this.queryRows("SELECT COUNT(*) as cnt FROM card");
|
|
703
|
+
return Number(rows[0]?.cnt ?? 0);
|
|
704
|
+
}
|
|
705
|
+
async searchByHash(hashPrefix) {
|
|
706
|
+
const rows = await this.queryRows(
|
|
707
|
+
"SELECT hash, content, g_time FROM card WHERE hash LIKE ?",
|
|
708
|
+
`${hashPrefix}%`
|
|
709
|
+
);
|
|
710
|
+
return rows.map((r) => this.rowToCard(r));
|
|
711
|
+
}
|
|
712
|
+
async search(queryStr, pageNumber = 1, pageSize = DEFAULT_PAGE_SIZE) {
|
|
713
|
+
if (pageNumber < 1) throw new Error("Page number must be >= 1");
|
|
714
|
+
if (pageSize < 1) throw new Error("Page size must be >= 1");
|
|
715
|
+
const offset = (pageNumber - 1) * pageSize;
|
|
716
|
+
const pattern = `%${queryStr}%`;
|
|
717
|
+
const cast = this.castContentAs;
|
|
718
|
+
const countRows = await this.queryRows(
|
|
719
|
+
`SELECT COUNT(*) as cnt FROM card WHERE CAST(content AS ${cast}) LIKE ?`,
|
|
720
|
+
pattern
|
|
721
|
+
);
|
|
722
|
+
const totalItems = Number(countRows[0]?.cnt ?? 0);
|
|
723
|
+
const rows = await this.queryRows(
|
|
724
|
+
`SELECT hash, content, g_time FROM card WHERE CAST(content AS ${cast}) LIKE ? ORDER BY g_time DESC LIMIT ? OFFSET ?`,
|
|
725
|
+
pattern,
|
|
726
|
+
pageSize,
|
|
727
|
+
offset
|
|
728
|
+
);
|
|
729
|
+
const items = rows.map((r) => this.rowToCard(r));
|
|
730
|
+
return createPage(items, totalItems, pageNumber, pageSize);
|
|
731
|
+
}
|
|
732
|
+
async getAll() {
|
|
733
|
+
const rows = await this.queryRows("SELECT hash, content, g_time FROM card ORDER BY g_time DESC");
|
|
734
|
+
return rows.map((r) => this.rowToCard(r));
|
|
735
|
+
}
|
|
736
|
+
// ======================================================================
|
|
737
|
+
// Concrete: clear (FK-safe delete order)
|
|
738
|
+
// ======================================================================
|
|
739
|
+
async clear() {
|
|
740
|
+
await this.execSql("DELETE FROM handle_history");
|
|
741
|
+
await this.execSql("DELETE FROM handle_registry");
|
|
742
|
+
await this.execSql("DELETE FROM card");
|
|
743
|
+
}
|
|
744
|
+
// ======================================================================
|
|
745
|
+
// Concrete: Handle Operations
|
|
746
|
+
// ======================================================================
|
|
747
|
+
async registerHandle(handle, hash) {
|
|
748
|
+
const normalized = validateHandle(handle);
|
|
749
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
750
|
+
const existing = await this.queryRows(
|
|
751
|
+
"SELECT handle FROM handle_registry WHERE handle = ?",
|
|
752
|
+
normalized
|
|
753
|
+
);
|
|
754
|
+
if (existing.length > 0) {
|
|
755
|
+
throw new Error(`Handle '${handle}' already exists.`);
|
|
756
|
+
}
|
|
757
|
+
await this.execSql(
|
|
758
|
+
"INSERT INTO handle_registry (handle, current_hash, created_at, updated_at) VALUES (?, ?, ?, ?)",
|
|
759
|
+
normalized,
|
|
760
|
+
hash,
|
|
761
|
+
now,
|
|
762
|
+
now
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
async resolveHandle(handle) {
|
|
766
|
+
const normalized = validateHandle(handle);
|
|
767
|
+
const rows = await this.queryRows(
|
|
768
|
+
"SELECT current_hash FROM handle_registry WHERE handle = ?",
|
|
769
|
+
normalized
|
|
770
|
+
);
|
|
771
|
+
if (rows.length === 0) return null;
|
|
772
|
+
return String(rows[0].current_hash);
|
|
773
|
+
}
|
|
774
|
+
async getByHandle(handle) {
|
|
775
|
+
const hash = await this.resolveHandle(handle);
|
|
776
|
+
if (!hash) return null;
|
|
777
|
+
return this.get(hash);
|
|
778
|
+
}
|
|
779
|
+
async updateHandle(handle, newHash) {
|
|
780
|
+
const normalized = validateHandle(handle);
|
|
781
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
782
|
+
const rows = await this.queryRows(
|
|
783
|
+
"SELECT current_hash FROM handle_registry WHERE handle = ?",
|
|
784
|
+
normalized
|
|
785
|
+
);
|
|
786
|
+
if (rows.length === 0) {
|
|
787
|
+
throw new Error(`Handle '${handle}' not found.`);
|
|
788
|
+
}
|
|
789
|
+
const previousHash = String(rows[0].current_hash);
|
|
790
|
+
await this.execSql(
|
|
791
|
+
"INSERT INTO handle_history (handle, previous_hash, changed_at) VALUES (?, ?, ?)",
|
|
792
|
+
normalized,
|
|
793
|
+
previousHash,
|
|
794
|
+
now
|
|
795
|
+
);
|
|
796
|
+
await this.execSql(
|
|
797
|
+
"UPDATE handle_registry SET current_hash = ?, updated_at = ? WHERE handle = ?",
|
|
798
|
+
newHash,
|
|
799
|
+
now,
|
|
800
|
+
normalized
|
|
801
|
+
);
|
|
802
|
+
return previousHash;
|
|
803
|
+
}
|
|
804
|
+
async getHandleHistory(handle) {
|
|
805
|
+
const normalized = validateHandle(handle);
|
|
806
|
+
const rows = await this.queryRows(
|
|
807
|
+
"SELECT previous_hash, changed_at FROM handle_history WHERE handle = ? ORDER BY id DESC",
|
|
808
|
+
normalized
|
|
809
|
+
);
|
|
810
|
+
return rows.map((r) => ({
|
|
811
|
+
previousHash: String(r.previous_hash),
|
|
812
|
+
changedAt: String(r.changed_at)
|
|
813
|
+
}));
|
|
814
|
+
}
|
|
815
|
+
async pruneHandleHistory(handle, options = {}) {
|
|
816
|
+
const normalized = validateHandle(handle);
|
|
817
|
+
if (options.deleteAll) {
|
|
818
|
+
return this.execSql("DELETE FROM handle_history WHERE handle = ?", normalized);
|
|
819
|
+
} else if (options.olderThan) {
|
|
820
|
+
return this.execSql(
|
|
821
|
+
"DELETE FROM handle_history WHERE handle = ? AND changed_at < ?",
|
|
822
|
+
normalized,
|
|
823
|
+
options.olderThan
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
return 0;
|
|
827
|
+
}
|
|
828
|
+
// ======================================================================
|
|
829
|
+
// Concrete: Handle Management Operations
|
|
830
|
+
// ======================================================================
|
|
831
|
+
async getAllHandles() {
|
|
832
|
+
const rows = await this.queryRows("SELECT handle, current_hash FROM handle_registry");
|
|
833
|
+
return rows.map((r) => ({
|
|
834
|
+
handle: String(r.handle),
|
|
835
|
+
hash: String(r.current_hash)
|
|
836
|
+
}));
|
|
837
|
+
}
|
|
838
|
+
async removeHandle(handle) {
|
|
839
|
+
const normalized = validateHandle(handle);
|
|
840
|
+
await this.execSql("DELETE FROM handle_history WHERE handle = ?", normalized);
|
|
841
|
+
await this.execSql("DELETE FROM handle_registry WHERE handle = ?", normalized);
|
|
842
|
+
}
|
|
843
|
+
async renameHandle(oldHandle, newHandle) {
|
|
844
|
+
const normalizedOld = validateHandle(oldHandle);
|
|
845
|
+
const normalizedNew = validateHandle(newHandle);
|
|
846
|
+
if (normalizedOld === normalizedNew) return;
|
|
847
|
+
const existsOld = await this.queryRows(
|
|
848
|
+
"SELECT handle FROM handle_registry WHERE handle = ?",
|
|
849
|
+
normalizedOld
|
|
850
|
+
);
|
|
851
|
+
if (existsOld.length === 0) throw new Error(`Handle '${oldHandle}' not found.`);
|
|
852
|
+
const existsNew = await this.queryRows(
|
|
853
|
+
"SELECT handle FROM handle_registry WHERE handle = ?",
|
|
854
|
+
normalizedNew
|
|
855
|
+
);
|
|
856
|
+
if (existsNew.length > 0) throw new Error(`Handle '${newHandle}' already exists.`);
|
|
857
|
+
const oldRow = await this.queryRows(
|
|
858
|
+
"SELECT current_hash, created_at, updated_at FROM handle_registry WHERE handle = ?",
|
|
859
|
+
normalizedOld
|
|
860
|
+
);
|
|
861
|
+
await this.execSql(
|
|
862
|
+
"INSERT INTO handle_registry (handle, current_hash, created_at, updated_at) VALUES (?, ?, ?, ?)",
|
|
863
|
+
normalizedNew,
|
|
864
|
+
String(oldRow[0].current_hash),
|
|
865
|
+
String(oldRow[0].created_at),
|
|
866
|
+
String(oldRow[0].updated_at)
|
|
867
|
+
);
|
|
868
|
+
await this.execSql(
|
|
869
|
+
"UPDATE handle_history SET handle = ? WHERE handle = ?",
|
|
870
|
+
normalizedNew,
|
|
871
|
+
normalizedOld
|
|
872
|
+
);
|
|
873
|
+
await this.execSql(
|
|
874
|
+
"DELETE FROM handle_registry WHERE handle = ?",
|
|
875
|
+
normalizedOld
|
|
876
|
+
);
|
|
877
|
+
}
|
|
878
|
+
async deleteHistoryEntry(handle, previousHash) {
|
|
879
|
+
const normalized = validateHandle(handle);
|
|
880
|
+
const rOutRows = await this.queryRows(
|
|
881
|
+
"SELECT id, previous_hash FROM handle_history WHERE handle = ? AND previous_hash = ? ORDER BY id DESC LIMIT 1",
|
|
882
|
+
normalized,
|
|
883
|
+
previousHash
|
|
884
|
+
);
|
|
885
|
+
if (rOutRows.length === 0) return;
|
|
886
|
+
const rOutId = Number(rOutRows[0].id);
|
|
887
|
+
const rInRows = await this.queryRows(
|
|
888
|
+
"SELECT id, previous_hash FROM handle_history WHERE handle = ? AND id < ? ORDER BY id DESC LIMIT 1",
|
|
889
|
+
normalized,
|
|
890
|
+
rOutId
|
|
891
|
+
);
|
|
892
|
+
if (rInRows.length > 0) {
|
|
893
|
+
const rInId = Number(rInRows[0].id);
|
|
894
|
+
const rInPrevHash = String(rInRows[0].previous_hash);
|
|
895
|
+
await this.execSql("UPDATE handle_history SET previous_hash = ? WHERE id = ?", rInPrevHash, rOutId);
|
|
896
|
+
await this.execSql("DELETE FROM handle_history WHERE id = ?", rInId);
|
|
897
|
+
} else {
|
|
898
|
+
await this.execSql("DELETE FROM handle_history WHERE id = ?", rOutId);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
|
|
903
|
+
export {
|
|
904
|
+
CORE_SCHEMAS,
|
|
905
|
+
initCoreSchemas,
|
|
906
|
+
AbstractSqlEngine
|
|
907
|
+
};
|