memorio 5.1.2 → 5.1.4

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/global.js CHANGED
@@ -1092,6 +1092,123 @@ var init_store = __esm({
1092
1092
  }
1093
1093
  });
1094
1094
 
1095
+ // core/hlc.ts
1096
+ function getNodeId() {
1097
+ if (typeof globalThis === "undefined") return "node";
1098
+ try {
1099
+ if (typeof sessionStorage !== "undefined" && sessionStorage) {
1100
+ let id = sessionStorage.getItem(NODE_ID_KEY);
1101
+ if (!id) {
1102
+ id = generateNodeId();
1103
+ sessionStorage.setItem(NODE_ID_KEY, id);
1104
+ }
1105
+ return id;
1106
+ }
1107
+ } catch {
1108
+ }
1109
+ if (!globalThis.__memorioHlcNodeId) {
1110
+ globalThis.__memorioHlcNodeId = generateNodeId();
1111
+ }
1112
+ return globalThis.__memorioHlcNodeId;
1113
+ }
1114
+ function generateNodeId() {
1115
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
1116
+ return crypto.randomUUID().slice(0, 8);
1117
+ }
1118
+ return Math.random().toString(36).slice(2, 10);
1119
+ }
1120
+ function tick(_incoming) {
1121
+ const now2 = Date.now();
1122
+ const base = local.physical;
1123
+ let physical;
1124
+ let logical;
1125
+ if (now2 > base) {
1126
+ physical = now2;
1127
+ logical = 0;
1128
+ } else if (now2 < base) {
1129
+ physical = base;
1130
+ logical = local.logical + 1;
1131
+ } else {
1132
+ physical = base;
1133
+ logical = local.logical + 1;
1134
+ }
1135
+ local.physical = physical;
1136
+ local.logical = logical;
1137
+ return { physical, logical, node: local.node };
1138
+ }
1139
+ function receive(remote) {
1140
+ const now2 = Date.now();
1141
+ if (remote.physical > local.physical) {
1142
+ local.physical = remote.physical > now2 ? remote.physical : now2;
1143
+ local.logical = 1;
1144
+ } else if (remote.physical === local.physical) {
1145
+ local.logical = Math.max(local.logical, remote.logical) + 1;
1146
+ }
1147
+ local.node = getNodeId();
1148
+ return { ...local };
1149
+ }
1150
+ function compare(a, b) {
1151
+ if (a.physical !== b.physical) {
1152
+ return a.physical < b.physical ? -1 : 1;
1153
+ }
1154
+ if (a.logical !== b.logical) {
1155
+ return a.logical < b.logical ? -1 : 1;
1156
+ }
1157
+ if (a.node !== b.node) {
1158
+ return a.node < b.node ? -1 : 1;
1159
+ }
1160
+ return 0;
1161
+ }
1162
+ function happenedBefore(a, b) {
1163
+ return compare(a, b) < 0;
1164
+ }
1165
+ function serialize(hlc2) {
1166
+ return `hlc:${hlc2.physical}:${hlc2.logical}:${hlc2.node}`;
1167
+ }
1168
+ function parse(serialized) {
1169
+ if (!serialized.startsWith("hlc:")) return null;
1170
+ const parts = serialized.split(":");
1171
+ if (parts.length !== 4) return null;
1172
+ const physical = parseInt(parts[1], 10);
1173
+ const logical = parseInt(parts[2], 10);
1174
+ const node = parts[3];
1175
+ if (isNaN(physical) || isNaN(logical)) return null;
1176
+ return { physical, logical, node };
1177
+ }
1178
+ var NODE_ID_KEY, HLC_KEY, local, hlc;
1179
+ var init_hlc = __esm({
1180
+ "core/hlc.ts"() {
1181
+ init_esm_shims();
1182
+ NODE_ID_KEY = "__memorio_hlc_node";
1183
+ __name(getNodeId, "getNodeId");
1184
+ __name(generateNodeId, "generateNodeId");
1185
+ HLC_KEY = "__memorio_hlc_local";
1186
+ local = globalThis[HLC_KEY] || {
1187
+ physical: 0,
1188
+ logical: 0,
1189
+ node: getNodeId()
1190
+ };
1191
+ if (!globalThis[HLC_KEY]) {
1192
+ globalThis[HLC_KEY] = local;
1193
+ }
1194
+ __name(tick, "tick");
1195
+ __name(receive, "receive");
1196
+ __name(compare, "compare");
1197
+ __name(happenedBefore, "happenedBefore");
1198
+ __name(serialize, "serialize");
1199
+ __name(parse, "parse");
1200
+ hlc = {
1201
+ tick,
1202
+ receive,
1203
+ compare,
1204
+ happenedBefore,
1205
+ serialize,
1206
+ parse,
1207
+ getNodeId
1208
+ };
1209
+ }
1210
+ });
1211
+
1095
1212
  // functions/idb/tools/db.create.ts
1096
1213
  var db_create_exports = {};
1097
1214
  var init_db_create = __esm({
@@ -1730,13 +1847,41 @@ var init_db_support2 = __esm({
1730
1847
  });
1731
1848
 
1732
1849
  // functions/sqlite/tools/persist.ts
1850
+ var persist_exports = {};
1851
+ __export(persist_exports, {
1852
+ CHECKPOINT_INTERVAL: () => CHECKPOINT_INTERVAL,
1853
+ DEBOUNCE_MS: () => DEBOUNCE_MS,
1854
+ _attachJournal: () => _attachJournal,
1855
+ _checkpoint: () => _checkpoint,
1856
+ _clearJournal: () => _clearJournal,
1857
+ _journalAppend: () => _journalAppend,
1858
+ _journalCount: () => _journalCount,
1859
+ _journalEntries: () => _journalEntries,
1860
+ _journalReplay: () => _journalReplay,
1861
+ _loadCheckpoint: () => _loadCheckpoint,
1862
+ _removeCheckpoint: () => _removeCheckpoint,
1863
+ _saveCheckpoint: () => _saveCheckpoint,
1864
+ _scheduleCheckpoint: () => _scheduleCheckpoint
1865
+ });
1733
1866
  function _ns() {
1734
1867
  const cfg = g.sqliteConfig || {};
1735
1868
  return cfg.namespace ? `ns:${cfg.namespace}` : "default";
1736
1869
  }
1737
- function _key(name) {
1870
+ function _dbKey(name) {
1738
1871
  return `memorio:sqlite:db:${_ns()}:${name}`;
1739
1872
  }
1873
+ function _journalKey(name, seq) {
1874
+ return `memorio:sqlite:journal:${_ns()}:${name}:${seq}`;
1875
+ }
1876
+ function _journalIndexKey(name) {
1877
+ return `memorio:sqlite:journal:${_ns()}:${name}:index`;
1878
+ }
1879
+ function _journalSeqKey(name) {
1880
+ return `memorio:sqlite:journal:${_ns()}:${name}:seq`;
1881
+ }
1882
+ function _opCounterKey(name) {
1883
+ return `memorio:sqlite:journal:${_ns()}:${name}:ops`;
1884
+ }
1740
1885
  function _b64encode2(buf) {
1741
1886
  const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
1742
1887
  let binary = "";
@@ -1749,35 +1894,81 @@ function _b64decode2(b64) {
1749
1894
  if (typeof Buffer !== "undefined") {
1750
1895
  return new Uint8Array(Buffer.from(b64, "base64"));
1751
1896
  }
1752
- if (typeof atob !== "function") {
1753
- throw new Error("memorio sqlite: no base64 decoder available");
1897
+ if (typeof atob === "function") {
1898
+ const binary = atob(b64);
1899
+ const len = binary.length;
1900
+ const out = new Uint8Array(len);
1901
+ for (let i = 0; i < len; i++) out[i] = binary.charCodeAt(i);
1902
+ return out;
1754
1903
  }
1755
- const binary = atob(b64);
1756
- const len = binary.length;
1757
- const out = new Uint8Array(len);
1758
- for (let i = 0; i < len; i++) out[i] = binary.charCodeAt(i);
1759
- return out;
1904
+ throw new Error("memorio sqlite: no base64 decoder available");
1760
1905
  }
1761
- function saveSnapshot(name) {
1762
- return new Promise((resolve) => {
1763
- const db = g.__sqliteDbs && g.__sqliteDbs[name];
1764
- if (!db || typeof db.export !== "function") {
1765
- resolve(false);
1766
- return;
1767
- }
1768
- try {
1769
- const blob = db.export();
1770
- store.set(_key(name), _b64encode2(blob));
1771
- message_default(`Memorio SQLite: persisted '${name}' to store`);
1772
- resolve(true);
1773
- } catch (err) {
1774
- console.warn("Memorio SQLite: persist snapshot failed", err);
1775
- resolve(false);
1776
- }
1906
+ function _nextSeq(name) {
1907
+ const seq = (store.get(_journalSeqKey(name)) || 0) + 1;
1908
+ store.set(_journalSeqKey(name), seq);
1909
+ return seq;
1910
+ }
1911
+ function _journalAppend(name, sql, params) {
1912
+ const seq = _nextSeq(name);
1913
+ const entry = {
1914
+ hlc: hlc.serialize(hlc.tick()),
1915
+ sql,
1916
+ params: params || [],
1917
+ seq,
1918
+ ts: Date.now()
1919
+ };
1920
+ store.set(_journalKey(name, seq), entry);
1921
+ const idx = store.get(_journalIndexKey(name)) || [];
1922
+ idx.push(seq);
1923
+ store.set(_journalIndexKey(name), idx);
1924
+ return seq;
1925
+ }
1926
+ function _journalEntries(name) {
1927
+ const idx = store.get(_journalIndexKey(name)) || [];
1928
+ const entries = [];
1929
+ for (const seq of idx) {
1930
+ const raw = store.get(_journalKey(name, seq));
1931
+ if (raw && typeof raw === "object" && raw.hlc) entries.push(raw);
1932
+ }
1933
+ entries.sort((a, b) => {
1934
+ const ha = hlc.parse(a.hlc);
1935
+ const hb = hlc.parse(b.hlc);
1936
+ if (ha && hb) return hlc.compare(ha, hb);
1937
+ return a.seq - b.seq;
1777
1938
  });
1939
+ return entries;
1940
+ }
1941
+ function _journalCount(name) {
1942
+ const idx = store.get(_journalIndexKey(name)) || [];
1943
+ return idx.length;
1778
1944
  }
1779
- function loadSnapshot(name) {
1780
- const b64 = store.get(_key(name));
1945
+ function _clearJournal(name) {
1946
+ const idx = store.get(_journalIndexKey(name)) || [];
1947
+ for (const seq of idx) {
1948
+ store.remove(_journalKey(name, seq));
1949
+ }
1950
+ store.remove(_journalIndexKey(name));
1951
+ store.remove(_journalSeqKey(name));
1952
+ store.remove(_opCounterKey(name));
1953
+ }
1954
+ async function _saveCheckpoint(name) {
1955
+ const db = g.__sqliteDbs && g.__sqliteDbs[name];
1956
+ if (!db || typeof db.export !== "function") return false;
1957
+ try {
1958
+ const blob = db.export();
1959
+ store.set(_dbKey(name), _b64encode2(blob));
1960
+ message_default(`Memorio SQLite: checkpoint saved for '${name}'`);
1961
+ return true;
1962
+ } catch (err) {
1963
+ if (db && db.version === "bun:sqlite") {
1964
+ return false;
1965
+ }
1966
+ console.warn("Memorio SQLite: checkpoint failed", err);
1967
+ return false;
1968
+ }
1969
+ }
1970
+ function _loadCheckpoint(name) {
1971
+ const b64 = store.get(_dbKey(name));
1781
1972
  if (!b64) return null;
1782
1973
  try {
1783
1974
  return _b64decode2(b64);
@@ -1785,48 +1976,108 @@ function loadSnapshot(name) {
1785
1976
  return null;
1786
1977
  }
1787
1978
  }
1788
- function removeSnapshot(name) {
1789
- store.remove(_key(name));
1979
+ function _removeCheckpoint(name) {
1980
+ store.remove(_dbKey(name));
1790
1981
  }
1791
- function attachAutoExport(name, db) {
1792
- if (!db || typeof db.updateHook !== "function") return;
1793
- _persistDbs[name] = true;
1794
- try {
1795
- db.updateHook(() => {
1796
- if (_exportTimers[name]) clearTimeout(_exportTimers[name]);
1797
- _exportTimers[name] = setTimeout(() => {
1798
- _exportTimers[name] = null;
1799
- void saveSnapshot(name);
1800
- }, 250);
1801
- });
1802
- } catch (err) {
1803
- console.warn("Memorio SQLite: could not attach updateHook", err);
1982
+ async function _journalReplay(name, db) {
1983
+ const entries = _journalEntries(name);
1984
+ if (!entries.length) return 0;
1985
+ let replayed = 0;
1986
+ for (const entry of entries) {
1987
+ try {
1988
+ db.run(entry.sql, entry.params || []);
1989
+ replayed++;
1990
+ } catch (err) {
1991
+ console.warn(`Memorio SQLite: failed to replay journal entry ${entry.seq} for '${name}'`, err);
1992
+ }
1993
+ }
1994
+ message_default(`Memorio SQLite: replayed ${replayed} journal entries for '${name}'`);
1995
+ return replayed;
1996
+ }
1997
+ function _scheduleCheckpoint(name) {
1998
+ if (_checkpointTimers[name]) clearTimeout(_checkpointTimers[name]);
1999
+ _checkpointTimers[name] = setTimeout(() => {
2000
+ _checkpointTimers[name] = null;
2001
+ void _checkpoint(name);
2002
+ }, DEBOUNCE_MS);
2003
+ }
2004
+ async function _checkpoint(name) {
2005
+ if (_checkpointTimers[name]) {
2006
+ clearTimeout(_checkpointTimers[name]);
2007
+ _checkpointTimers[name] = null;
2008
+ }
2009
+ const saved = await _saveCheckpoint(name);
2010
+ if (saved) _clearJournal(name);
2011
+ return saved;
2012
+ }
2013
+ function _attachJournal(name, db) {
2014
+ if (!db || typeof db.run !== "function") return;
2015
+ if (db.__memorioJournalAttached) return;
2016
+ db.__memorioJournalAttached = true;
2017
+ const originalRun = db.run.bind(db);
2018
+ db.run = function(sql, params) {
2019
+ const paramArr = Array.isArray(params) ? params : params !== void 0 ? [params] : [];
2020
+ _journalAppend(name, sql, paramArr);
2021
+ const ops = (store.get(_opCounterKey(name)) || 0) + 1;
2022
+ store.set(_opCounterKey(name), ops);
2023
+ if (ops >= CHECKPOINT_INTERVAL) {
2024
+ store.set(_opCounterKey(name), 0);
2025
+ void _checkpoint(name);
2026
+ } else {
2027
+ _scheduleCheckpoint(name);
2028
+ }
2029
+ return originalRun(sql, params);
2030
+ };
2031
+ if (typeof db.updateHook === "function") {
2032
+ try {
2033
+ db.updateHook(() => {
2034
+ _scheduleCheckpoint(name);
2035
+ });
2036
+ } catch (err) {
2037
+ console.warn("Memorio SQLite: could not attach updateHook", err);
2038
+ }
1804
2039
  }
1805
2040
  }
1806
- var g, _persistDbs, _exportTimers;
2041
+ var g, CHECKPOINT_INTERVAL, DEBOUNCE_MS, _checkpointTimers;
1807
2042
  var init_persist = __esm({
1808
2043
  "functions/sqlite/tools/persist.ts"() {
1809
2044
  init_esm_shims();
1810
2045
  init_sqlite();
1811
2046
  init_store();
2047
+ init_hlc();
1812
2048
  init_message();
1813
2049
  g = globalThis;
1814
- _persistDbs = {};
1815
- _exportTimers = {};
2050
+ CHECKPOINT_INTERVAL = 50;
2051
+ DEBOUNCE_MS = 250;
2052
+ _checkpointTimers = {};
1816
2053
  __name(_ns, "_ns");
1817
- __name(_key, "_key");
2054
+ __name(_dbKey, "_dbKey");
2055
+ __name(_journalKey, "_journalKey");
2056
+ __name(_journalIndexKey, "_journalIndexKey");
2057
+ __name(_journalSeqKey, "_journalSeqKey");
2058
+ __name(_opCounterKey, "_opCounterKey");
1818
2059
  __name(_b64encode2, "_b64encode");
1819
2060
  __name(_b64decode2, "_b64decode");
1820
- __name(saveSnapshot, "saveSnapshot");
1821
- __name(loadSnapshot, "loadSnapshot");
1822
- __name(removeSnapshot, "removeSnapshot");
1823
- __name(attachAutoExport, "attachAutoExport");
2061
+ __name(_nextSeq, "_nextSeq");
2062
+ __name(_journalAppend, "_journalAppend");
2063
+ __name(_journalEntries, "_journalEntries");
2064
+ __name(_journalCount, "_journalCount");
2065
+ __name(_clearJournal, "_clearJournal");
2066
+ __name(_saveCheckpoint, "_saveCheckpoint");
2067
+ __name(_loadCheckpoint, "_loadCheckpoint");
2068
+ __name(_removeCheckpoint, "_removeCheckpoint");
2069
+ __name(_journalReplay, "_journalReplay");
2070
+ __name(_scheduleCheckpoint, "_scheduleCheckpoint");
2071
+ __name(_checkpoint, "_checkpoint");
2072
+ __name(_attachJournal, "_attachJournal");
1824
2073
  sqlite.db.persist = async (name = "memorio") => {
1825
- return saveSnapshot(name);
2074
+ return _checkpoint(name);
2075
+ };
2076
+ sqlite.db.flush = async (name = "memorio") => {
2077
+ return _checkpoint(name);
1826
2078
  };
1827
2079
  sqlite.db.download = async (name = "memorio", filename = `${name}.sqlite`) => {
1828
- const g3 = globalThis;
1829
- const db = g3.__sqliteDbs && g3.__sqliteDbs[name];
2080
+ const db = g.__sqliteDbs && g.__sqliteDbs[name];
1830
2081
  if (!db) {
1831
2082
  console.warn(`Memorio SQLite: cannot download '${name}' - database not found. Create it with sqlite.db.create('${name}').`);
1832
2083
  return false;
@@ -1839,18 +2090,18 @@ var init_persist = __esm({
1839
2090
  return false;
1840
2091
  }
1841
2092
  if (!blob) return false;
1842
- if (typeof g3.document === "undefined" || typeof g3.Blob === "undefined") {
2093
+ if (typeof g.document === "undefined" || typeof g.Blob === "undefined") {
1843
2094
  console.warn("Memorio SQLite: sqlite.db.download() requires a browser environment.");
1844
2095
  return false;
1845
2096
  }
1846
- const URL = g3.URL || g3.webkitURL;
2097
+ const URL = g.URL || g.webkitURL;
1847
2098
  if (!URL || typeof URL.createObjectURL !== "function") return false;
1848
2099
  const objectUrl = URL.createObjectURL(new Blob([blob], { type: "application/x-sqlite3" }));
1849
- const a = g3.document.createElement("a");
2100
+ const a = g.document.createElement("a");
1850
2101
  a.style.display = "none";
1851
2102
  a.href = objectUrl;
1852
2103
  a.download = filename;
1853
- g3.document.body.appendChild(a);
2104
+ g.document.body.appendChild(a);
1854
2105
  a.click();
1855
2106
  setTimeout(() => {
1856
2107
  try {
@@ -1865,7 +2116,7 @@ var init_persist = __esm({
1865
2116
  const db = g.__sqliteDbs && g.__sqliteDbs[name];
1866
2117
  if (db && typeof db.close === "function") {
1867
2118
  try {
1868
- await saveSnapshot(name);
2119
+ await _checkpoint(name);
1869
2120
  } catch (_) {
1870
2121
  }
1871
2122
  try {
@@ -1879,15 +2130,22 @@ var init_persist = __esm({
1879
2130
  const idx = g.sqlbases.findIndex((x) => x && x.name === name);
1880
2131
  if (idx > -1) g.sqlbases.splice(idx, 1);
1881
2132
  }
1882
- delete _persistDbs[name];
1883
- if (_exportTimers[name]) {
1884
- clearTimeout(_exportTimers[name]);
1885
- _exportTimers[name] = null;
2133
+ if (_checkpointTimers[name]) {
2134
+ clearTimeout(_checkpointTimers[name]);
2135
+ _checkpointTimers[name] = null;
1886
2136
  }
1887
- removeSnapshot(name);
1888
2137
  };
1889
- sqlite.db.loadSnapshot = loadSnapshot;
1890
- sqlite.db.saveSnapshot = saveSnapshot;
2138
+ sqlite.db.loadSnapshot = _loadCheckpoint;
2139
+ sqlite.db.saveSnapshot = _saveCheckpoint;
2140
+ sqlite.db.removeSnapshot = _removeCheckpoint;
2141
+ sqlite.db.journal = {
2142
+ append: _journalAppend,
2143
+ entries: _journalEntries,
2144
+ count: _journalCount,
2145
+ clear: _clearJournal,
2146
+ replay: _journalReplay,
2147
+ checkpoint: _checkpoint
2148
+ };
1891
2149
  }
1892
2150
  });
1893
2151
 
@@ -1905,7 +2163,7 @@ var init_db_create2 = __esm({
1905
2163
  const persistence = !!(opts && opts.persistence) || !!(g3.sqliteConfig && g3.sqliteConfig.persistence);
1906
2164
  let data;
1907
2165
  if (persistence && !opts.data) {
1908
- const restored = loadSnapshot(name);
2166
+ const restored = _loadCheckpoint(name);
1909
2167
  if (restored) data = restored;
1910
2168
  }
1911
2169
  const useData = opts && opts.data || data;
@@ -1927,7 +2185,13 @@ var init_db_create2 = __esm({
1927
2185
  } else {
1928
2186
  g3.sqlbases.push({ name, db, persistence: createOpts.persistence });
1929
2187
  }
1930
- if (persistence) attachAutoExport(name, db);
2188
+ if (persistence && !opts.data) {
2189
+ _attachJournal(name, db);
2190
+ const replayed = await _journalReplay(name, db);
2191
+ if (replayed > 0) {
2192
+ message_default(`Memorio SQLite: replayed ${replayed} journal entries for '${name}'`);
2193
+ }
2194
+ }
1931
2195
  return db;
1932
2196
  };
1933
2197
  }
@@ -1958,9 +2222,14 @@ var init_db_delete2 = __esm({
1958
2222
  init_esm_shims();
1959
2223
  init_sqlite();
1960
2224
  init_message();
1961
- sqlite.db.delete = (name) => {
2225
+ init_persist();
2226
+ sqlite.db.delete = async (name) => {
1962
2227
  const dbs = globalThis.__sqliteDbs;
1963
2228
  if (!dbs || !dbs[name]) return false;
2229
+ try {
2230
+ await _checkpoint(name);
2231
+ } catch (_) {
2232
+ }
1964
2233
  try {
1965
2234
  dbs[name].close();
1966
2235
  } catch (_) {
@@ -1968,6 +2237,7 @@ var init_db_delete2 = __esm({
1968
2237
  delete dbs[name];
1969
2238
  const g3 = globalThis;
1970
2239
  if (g3.sqlbases) g3.sqlbases = g3.sqlbases.filter((x) => x && x.name !== name);
2240
+ _removeCheckpoint(name);
1971
2241
  message_default(`Memorio SQLite: database '${name}' deleted`);
1972
2242
  return true;
1973
2243
  };
@@ -2112,7 +2382,7 @@ var init_data_get2 = __esm({
2112
2382
  });
2113
2383
 
2114
2384
  // functions/sqlite/index.ts
2115
- var _hasSqlJs, _hasBunSqlite, sqlite;
2385
+ var _hasSqlJs, _hasBunSqlite, sqlite, _toolsLoaded;
2116
2386
  var init_sqlite = __esm({
2117
2387
  "functions/sqlite/index.ts"() {
2118
2388
  init_esm_shims();
@@ -2125,6 +2395,7 @@ var init_sqlite = __esm({
2125
2395
  query: {},
2126
2396
  data: {}
2127
2397
  };
2398
+ _toolsLoaded = Promise.resolve();
2128
2399
  sqlite.config = (opts) => {
2129
2400
  const g3 = globalThis;
2130
2401
  g3.sqliteConfig = { ...g3.sqliteConfig, ...opts };
@@ -2139,15 +2410,19 @@ var init_sqlite = __esm({
2139
2410
  get: /* @__PURE__ */ __name(() => {
2140
2411
  const g3 = globalThis;
2141
2412
  if (!g3.sqliteReady) {
2142
- g3.sqliteReady = typeof sqlite.db.getSQL === "function" ? sqlite.db.getSQL().then(() => {
2413
+ g3.sqliteReady = _toolsLoaded.then(() => {
2414
+ if (typeof sqlite.db.getSQL !== "function") return;
2415
+ return sqlite.db.getSQL().then(() => {
2416
+ }).catch(() => {
2417
+ });
2143
2418
  }).catch(() => {
2144
- }) : Promise.resolve();
2419
+ });
2145
2420
  }
2146
2421
  return g3.sqliteReady;
2147
2422
  }, "get")
2148
2423
  });
2149
2424
  if (_hasSqlJs || _hasBunSqlite) {
2150
- (async () => {
2425
+ _toolsLoaded = (async () => {
2151
2426
  Object.defineProperty(sqlite, "db", { value: {}, writable: false, configurable: true, enumerable: true });
2152
2427
  Object.defineProperty(sqlite, "query", { value: {}, writable: false, configurable: true, enumerable: true });
2153
2428
  Object.defineProperty(sqlite, "data", { value: {}, writable: false, configurable: true, enumerable: true });
@@ -2159,6 +2434,7 @@ var init_sqlite = __esm({
2159
2434
  });
2160
2435
  await Promise.all([
2161
2436
  Promise.resolve().then(() => (init_db_support2(), db_support_exports2)),
2437
+ Promise.resolve().then(() => (init_persist(), persist_exports)),
2162
2438
  Promise.resolve().then(() => (init_db_create2(), db_create_exports2)),
2163
2439
  Promise.resolve().then(() => (init_db_get(), db_get_exports)),
2164
2440
  Promise.resolve().then(() => (init_db_delete2(), db_delete_exports2)),
@@ -2382,121 +2658,11 @@ init_env();
2382
2658
  // core/mutation/engine.ts
2383
2659
  init_esm_shims();
2384
2660
  init_internal();
2385
-
2386
- // core/hlc.ts
2387
- init_esm_shims();
2388
- var NODE_ID_KEY = "__memorio_hlc_node";
2389
- function getNodeId() {
2390
- if (typeof globalThis === "undefined") return "node";
2391
- try {
2392
- if (typeof sessionStorage !== "undefined" && sessionStorage) {
2393
- let id = sessionStorage.getItem(NODE_ID_KEY);
2394
- if (!id) {
2395
- id = generateNodeId();
2396
- sessionStorage.setItem(NODE_ID_KEY, id);
2397
- }
2398
- return id;
2399
- }
2400
- } catch {
2401
- }
2402
- if (!globalThis.__memorioHlcNodeId) {
2403
- globalThis.__memorioHlcNodeId = generateNodeId();
2404
- }
2405
- return globalThis.__memorioHlcNodeId;
2406
- }
2407
- __name(getNodeId, "getNodeId");
2408
- function generateNodeId() {
2409
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
2410
- return crypto.randomUUID().slice(0, 8);
2411
- }
2412
- return Math.random().toString(36).slice(2, 10);
2413
- }
2414
- __name(generateNodeId, "generateNodeId");
2415
- var HLC_KEY = "__memorio_hlc_local";
2416
- var local = globalThis[HLC_KEY] || {
2417
- physical: 0,
2418
- logical: 0,
2419
- node: getNodeId()
2420
- };
2421
- if (!globalThis[HLC_KEY]) {
2422
- globalThis[HLC_KEY] = local;
2423
- }
2424
- function tick(_incoming) {
2425
- const now2 = Date.now();
2426
- const base = local.physical;
2427
- let physical;
2428
- let logical;
2429
- if (now2 > base) {
2430
- physical = now2;
2431
- logical = 0;
2432
- } else if (now2 < base) {
2433
- physical = base;
2434
- logical = local.logical + 1;
2435
- } else {
2436
- physical = base;
2437
- logical = local.logical + 1;
2438
- }
2439
- local.physical = physical;
2440
- local.logical = logical;
2441
- return { physical, logical, node: local.node };
2442
- }
2443
- __name(tick, "tick");
2444
- function receive(remote) {
2445
- const now2 = Date.now();
2446
- if (remote.physical > local.physical) {
2447
- local.physical = remote.physical > now2 ? remote.physical : now2;
2448
- local.logical = 1;
2449
- } else if (remote.physical === local.physical) {
2450
- local.logical = Math.max(local.logical, remote.logical) + 1;
2451
- }
2452
- local.node = getNodeId();
2453
- return { ...local };
2454
- }
2455
- __name(receive, "receive");
2456
- function compare(a, b) {
2457
- if (a.physical !== b.physical) {
2458
- return a.physical < b.physical ? -1 : 1;
2459
- }
2460
- if (a.logical !== b.logical) {
2461
- return a.logical < b.logical ? -1 : 1;
2462
- }
2463
- if (a.node !== b.node) {
2464
- return a.node < b.node ? -1 : 1;
2465
- }
2466
- return 0;
2467
- }
2468
- __name(compare, "compare");
2469
- function happenedBefore(a, b) {
2470
- return compare(a, b) < 0;
2471
- }
2472
- __name(happenedBefore, "happenedBefore");
2473
- function serialize(hlc2) {
2474
- return `hlc:${hlc2.physical}:${hlc2.logical}:${hlc2.node}`;
2475
- }
2476
- __name(serialize, "serialize");
2477
- function parse(serialized) {
2478
- if (!serialized.startsWith("hlc:")) return null;
2479
- const parts = serialized.split(":");
2480
- if (parts.length !== 4) return null;
2481
- const physical = parseInt(parts[1], 10);
2482
- const logical = parseInt(parts[2], 10);
2483
- const node = parts[3];
2484
- if (isNaN(physical) || isNaN(logical)) return null;
2485
- return { physical, logical, node };
2486
- }
2487
- __name(parse, "parse");
2488
- var hlc = {
2489
- tick,
2490
- receive,
2491
- compare,
2492
- happenedBefore,
2493
- serialize,
2494
- parse,
2495
- getNodeId
2496
- };
2661
+ init_hlc();
2497
2662
 
2498
2663
  // core/mutation/id.ts
2499
2664
  init_esm_shims();
2665
+ init_hlc();
2500
2666
  function generateMutationId() {
2501
2667
  const now2 = hlc.tick();
2502
2668
  return "m_" + encodeHLC(now2);
@@ -2588,6 +2754,7 @@ __name(mergePatches, "mergePatches");
2588
2754
  // core/mutation/transaction.ts
2589
2755
  init_esm_shims();
2590
2756
  init_internal();
2757
+ init_hlc();
2591
2758
  var TX_REGISTRY_KEY = "__memorio_transaction_registry__";
2592
2759
  var registry = globalThis[TX_REGISTRY_KEY] || /* @__PURE__ */ new Map();
2593
2760
  if (!globalThis[TX_REGISTRY_KEY]) {
@@ -3157,19 +3324,39 @@ if (globalThis[STATE_INSTANCE_KEY]) {
3157
3324
  const initial = store.get(key);
3158
3325
  if (initial !== void 0 && initial !== null) {
3159
3326
  let acc = state2;
3327
+ let seedOk = true;
3160
3328
  for (let i = 0; i < segments.length - 1; i++) {
3161
3329
  const seg = segments[i];
3162
- if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
3163
- acc = acc[seg];
3330
+ const existing = acc[seg];
3331
+ if (existing === void 0 || existing === null) {
3332
+ acc[seg] = {};
3333
+ acc = acc[seg];
3334
+ } else if (typeof existing === "object") {
3335
+ acc = existing;
3336
+ } else {
3337
+ if (DEV) {
3338
+ console.warn(
3339
+ `[memorio state] state.persist('${normalized}') aborted seeding: '${seg}' already holds a primitive value (${typeof existing}), cannot nest '${segments.slice(i + 1).join(".")}' under it.`
3340
+ );
3341
+ }
3342
+ seedOk = false;
3343
+ break;
3344
+ }
3345
+ }
3346
+ if (seedOk && acc) {
3347
+ acc[segments[segments.length - 1]] = deepRaw(initial);
3164
3348
  }
3165
- if (acc) acc[segments[segments.length - 1]] = deepRaw(initial);
3166
3349
  }
3167
3350
  const handler = /* @__PURE__ */ __name(() => {
3168
3351
  let current = state2;
3169
3352
  for (const seg of segments) {
3170
3353
  current = current === void 0 || current === null ? void 0 : current[seg];
3171
3354
  }
3172
- store.set(key, deepRaw(current));
3355
+ if (current === void 0) {
3356
+ store.remove(key);
3357
+ } else {
3358
+ store.set(key, deepRaw(current));
3359
+ }
3173
3360
  }, "handler");
3174
3361
  const off = dispatch.listen(normalized, handler);
3175
3362
  return typeof off === "function" ? off : () => {
@@ -3589,8 +3776,7 @@ var observerFunction = /* @__PURE__ */ __name((s, cb = null, option = true) => {
3589
3776
  }
3590
3777
  if (s && cb) {
3591
3778
  const resolvedPath = resolvePath(s);
3592
- if (!resolvedPath) return;
3593
- if (typeof s !== "string" && !(s && typeof s === "object")) {
3779
+ if (!resolvedPath) {
3594
3780
  console.error(`Observer Error: name of state need to be a 'string' like 'state.test' or a direct state value`);
3595
3781
  return;
3596
3782
  }
@@ -3640,7 +3826,7 @@ Object.defineProperties(
3640
3826
  * @returns void
3641
3827
  */
3642
3828
  removeAll: {
3643
- get: /* @__PURE__ */ __name(() => {
3829
+ value: /* @__PURE__ */ __name(() => {
3644
3830
  const obs = globalThis.observer;
3645
3831
  const list = obs?.list;
3646
3832
  if (list) {
@@ -3649,7 +3835,7 @@ Object.defineProperties(
3649
3835
  });
3650
3836
  }
3651
3837
  return true;
3652
- }, "get")
3838
+ }, "value")
3653
3839
  },
3654
3840
  ///
3655
3841
  /**
@@ -3679,40 +3865,58 @@ var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
3679
3865
  const unsubs = [];
3680
3866
  const depList = Array.isArray(deps) && !deps.__path ? deps : [deps];
3681
3867
  try {
3682
- depList.forEach((dep) => {
3683
- let t = "";
3684
- if (typeof dep === "function") {
3685
- const result = propertyName(dep);
3686
- if (result) t = result;
3687
- } else if (typeof dep === "object" && dep !== null) {
3688
- t = dep.__path || (typeof dep.toString === "function" && dep.toString() !== "[object Object]" ? dep.toString() : "");
3868
+ if (depList.length === 0) {
3869
+ internal_default.clearTrackedPaths();
3870
+ internal_default.tracking = true;
3871
+ try {
3872
+ func();
3873
+ } catch (_) {
3689
3874
  }
3690
- if (t) {
3691
- t = t.replace(/^(\(\)\s*=>\s*)/, "").replace(/^globalThis\./, "").replace(/^state\./, "");
3692
- const path2 = t.startsWith("store.") || t.startsWith("state.") ? t : "state." + t;
3875
+ internal_default.tracking = false;
3876
+ internal_default.trackedPaths.forEach((path2) => {
3693
3877
  if (!handlers.includes(path2)) {
3878
+ message_default(`useObserver: [Auto-Discovery] -> "${path2}"`);
3694
3879
  handlers.push(path2);
3695
3880
  const off = dispatch.listen(path2, () => func());
3696
3881
  if (typeof off === "function") unsubs.push({ path: path2, off });
3697
3882
  }
3698
- } else {
3699
- internal_default.clearTrackedPaths();
3700
- internal_default.tracking = true;
3701
- try {
3702
- func();
3703
- } catch (_) {
3883
+ });
3884
+ } else {
3885
+ depList.forEach((dep) => {
3886
+ let t = "";
3887
+ if (typeof dep === "function") {
3888
+ const result = propertyName(dep);
3889
+ if (result) t = result;
3890
+ } else if (typeof dep === "object" && dep !== null) {
3891
+ t = dep.__path || (typeof dep.toString === "function" && dep.toString() !== "[object Object]" ? dep.toString() : "");
3704
3892
  }
3705
- internal_default.tracking = false;
3706
- internal_default.trackedPaths.forEach((path2) => {
3893
+ if (t) {
3894
+ t = t.replace(/^(\(\)\s*=>\s*)/, "").replace(/^globalThis\./, "").replace(/^state\./, "");
3895
+ const path2 = t.startsWith("store.") || t.startsWith("state.") ? t : "state." + t;
3707
3896
  if (!handlers.includes(path2)) {
3708
- message_default(`useObserver: [Auto-Discovery] -> "${path2}"`);
3709
3897
  handlers.push(path2);
3710
3898
  const off = dispatch.listen(path2, () => func());
3711
3899
  if (typeof off === "function") unsubs.push({ path: path2, off });
3712
3900
  }
3713
- });
3714
- }
3715
- });
3901
+ } else {
3902
+ internal_default.clearTrackedPaths();
3903
+ internal_default.tracking = true;
3904
+ try {
3905
+ func();
3906
+ } catch (_) {
3907
+ }
3908
+ internal_default.tracking = false;
3909
+ internal_default.trackedPaths.forEach((path2) => {
3910
+ if (!handlers.includes(path2)) {
3911
+ message_default(`useObserver: [Auto-Discovery] -> "${path2}"`);
3912
+ handlers.push(path2);
3913
+ const off = dispatch.listen(path2, () => func());
3914
+ if (typeof off === "function") unsubs.push({ path: path2, off });
3915
+ }
3916
+ });
3917
+ }
3918
+ });
3919
+ }
3716
3920
  if (handlers.length > 0) {
3717
3921
  message_default(`useObserver: Monitoring ${handlers.length} paths.`);
3718
3922
  } else {
@@ -4199,8 +4403,8 @@ function isAuditActive() {
4199
4403
  return _auditLogger !== null;
4200
4404
  }
4201
4405
  __name(isAuditActive, "isAuditActive");
4202
- function setAuditLogger(logger3) {
4203
- _auditLogger = logger3;
4406
+ function setAuditLogger(logger2) {
4407
+ _auditLogger = logger2;
4204
4408
  }
4205
4409
  __name(setAuditLogger, "setAuditLogger");
4206
4410
  function logAudit(entry) {
@@ -4443,6 +4647,9 @@ var logger = {
4443
4647
  exportLogs
4444
4648
  };
4445
4649
 
4650
+ // index.ts
4651
+ init_hlc();
4652
+
4446
4653
  // core/fractional.ts
4447
4654
  init_esm_shims();
4448
4655
  function generateBetween(left, right, minChars = 2) {
@@ -4635,7 +4842,7 @@ init_internal();
4635
4842
 
4636
4843
  // package.json
4637
4844
  var package_default = {
4638
- version: "5.1.2"};
4845
+ version: "5.1.4"};
4639
4846
 
4640
4847
  // core/global.ts
4641
4848
  init_env();
@@ -4656,10 +4863,12 @@ __name(typed, "typed");
4656
4863
  init_esm_shims();
4657
4864
  init_store();
4658
4865
  init_idb();
4866
+ init_hlc();
4659
4867
  init_env();
4660
4868
 
4661
4869
  // functions/memory/journal.ts
4662
4870
  init_esm_shims();
4871
+ init_hlc();
4663
4872
  init_env();
4664
4873
  init_store();
4665
4874
  var g2 = globalThis;
@@ -5309,19 +5518,22 @@ var memory = {
5309
5518
  async patch(key, patches) {
5310
5519
  const entry = await this._getEntry(key);
5311
5520
  if (!entry) return;
5521
+ const patchedValue = JSON.parse(JSON.stringify(entry.value ?? {}));
5312
5522
  let patched = false;
5313
5523
  for (const p of patches) {
5524
+ const relativePath = p.path.replace(/^[^.]+\./, "");
5314
5525
  if (p.op === "set") {
5315
- setNestedPath({ [entry.key]: entry.value }, p.path.replace(/^[^.]+\./, ""), p.value);
5526
+ setNestedPath(patchedValue, relativePath, p.value);
5316
5527
  patched = true;
5317
5528
  } else if (p.op === "delete") {
5318
- deleteNestedPath({ [entry.key]: entry.value }, p.path.replace(/^[^.]+\./, ""));
5529
+ deleteNestedPath(patchedValue, relativePath);
5319
5530
  patched = true;
5320
5531
  }
5321
5532
  }
5322
5533
  if (!patched) return;
5323
5534
  const updated = {
5324
5535
  ...entry,
5536
+ value: patchedValue,
5325
5537
  updatedAt: now(),
5326
5538
  lastConfirmedAt: now(),
5327
5539
  version: (entry.version ? entry.version : 0) + 1,
@@ -5572,6 +5784,7 @@ if (!("memorio" in globalThis)) {
5572
5784
  );
5573
5785
  memorio.memory = memory;
5574
5786
  memorio.encryption = encryption;
5787
+ memorio.sqlite = sqlite;
5575
5788
  initializePlatform();
5576
5789
  memorio.isBrowser = isBrowser;
5577
5790
  memorio.isNode = isNode;