memorio 4.9.35 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +307 -359
  3. package/SECURITY.md +17 -1
  4. package/SUMMARY.md +59 -45
  5. package/adr/001-state-proxy-model.md +96 -0
  6. package/adr/002-observer-semantics.md +180 -0
  7. package/adr/003-deep-mutation-semantics.md +129 -0
  8. package/adr/004-array-mutation-semantics.md +128 -0
  9. package/adr/005-scheduler-contract.md +149 -0
  10. package/adr/006-context-isolation.md +92 -0
  11. package/adr/007-mutation-records.md +118 -0
  12. package/adr/008-transactions.md +106 -0
  13. package/adr/009-history-model.md +110 -0
  14. package/adr/README.md +46 -0
  15. package/adr/template.md +49 -0
  16. package/examples/basic.ts +115 -115
  17. package/examples/browser-vanilla.html +358 -358
  18. package/examples/cache.ts +72 -72
  19. package/examples/cross-platform-guards.ts +57 -57
  20. package/examples/history.ts +104 -0
  21. package/examples/idb.ts +109 -109
  22. package/examples/multi-tenant-context.ts +44 -44
  23. package/examples/node-server.ts +308 -308
  24. package/examples/observer.ts +60 -60
  25. package/examples/platform.ts +115 -115
  26. package/examples/react-app.tsx +362 -362
  27. package/examples/react-observer.tsx +63 -63
  28. package/examples/semantic-memory.ts +60 -60
  29. package/examples/session-advanced.ts +91 -91
  30. package/examples/sqlite-batched-writes.ts +57 -57
  31. package/examples/state-advanced.ts +89 -89
  32. package/examples/store-advanced.ts +117 -117
  33. package/examples/sync.ts +90 -0
  34. package/examples/typed-and-schema.ts +102 -100
  35. package/examples/useObserver.tsx +140 -141
  36. package/global.cjs +4594 -0
  37. package/global.d.ts +8 -0
  38. package/global.js +4532 -0
  39. package/index.cjs +700 -678
  40. package/index.d.ts +1 -0
  41. package/index.js +680 -677
  42. package/llms.txt +72 -4
  43. package/markdown/AUDIT-REPORT.md +135 -0
  44. package/markdown/CACHE.md +100 -0
  45. package/markdown/CHANGELOG.md +243 -0
  46. package/markdown/DEVTOOLS.md +129 -0
  47. package/markdown/DISPATCH.md +177 -0
  48. package/markdown/HISTORY.md +199 -0
  49. package/markdown/IDB.md +178 -0
  50. package/markdown/IMPORT.md +153 -0
  51. package/markdown/INSPECT.md +123 -0
  52. package/markdown/LOGGER.md +154 -0
  53. package/markdown/MEMORY-ATTACHMENT.md +96 -0
  54. package/markdown/MEMORY.md +162 -0
  55. package/markdown/OBSERVER.md +209 -0
  56. package/markdown/PLATFORM.md +271 -0
  57. package/markdown/PROJECT.md +311 -0
  58. package/markdown/SCHEMA.md +176 -0
  59. package/markdown/SECURITY.md +330 -0
  60. package/markdown/SESSION.md +165 -0
  61. package/markdown/SQLITE.md +190 -0
  62. package/markdown/STATE.md +160 -0
  63. package/markdown/STORE.md +171 -0
  64. package/markdown/SYNC.md +319 -0
  65. package/markdown/TYPED.md +165 -0
  66. package/markdown/USEOBSERVER.md +257 -0
  67. package/modules/redux.cjs +320 -167
  68. package/modules/redux.cjs.map +1 -1
  69. package/modules/redux.js +320 -167
  70. package/modules/redux.js.map +1 -1
  71. package/package.json +13 -3
  72. package/types/env.d.ts +19 -9
  73. package/types/exports.d.ts +20 -0
  74. package/types/history.d.ts +13 -1
  75. package/types/memorio.d.ts +17 -5
  76. package/types/mutation.d.ts +75 -0
package/index.cjs CHANGED
@@ -20,8 +20,11 @@ exports.DEV = void 0; exports.PROD = void 0;
20
20
  var init_env = __esm({
21
21
  "core/env.ts"() {
22
22
  init_cjs_shims();
23
- exports.DEV = typeof process !== "undefined" ? false : true;
23
+ exports.DEV = false ;
24
24
  exports.PROD = !exports.DEV;
25
+ if (typeof globalThis !== "undefined") {
26
+ globalThis["__DEV__"] = exports.DEV;
27
+ }
25
28
  }
26
29
  });
27
30
 
@@ -948,8 +951,8 @@ var init_table_size = __esm({
948
951
  if (!db.objectStoreNames.contains(table)) return resolve(0);
949
952
  let size = 0;
950
953
  let count = 0;
951
- const transaction = db.transaction([table], "readonly");
952
- const store2 = transaction.objectStore(table);
954
+ const transaction2 = db.transaction([table], "readonly");
955
+ const store2 = transaction2.objectStore(table);
953
956
  const request = store2.openCursor();
954
957
  request.onsuccess = async (event) => {
955
958
  const cursor = event.target.result;
@@ -993,8 +996,8 @@ var init_data_delete = __esm({
993
996
  db.close();
994
997
  return reject(new Error(`Table ${table} not found`));
995
998
  }
996
- const transaction = db.transaction(table, "readwrite");
997
- const objectStore = transaction.objectStore(table);
999
+ const transaction2 = db.transaction(table, "readwrite");
1000
+ const objectStore = transaction2.objectStore(table);
998
1001
  const deleteRequest = objectStore.delete(key);
999
1002
  deleteRequest.onsuccess = () => {
1000
1003
  db.close();
@@ -1018,8 +1021,8 @@ var init_data_delete = __esm({
1018
1021
  db.close();
1019
1022
  return reject(new Error(`Table ${table} not found`));
1020
1023
  }
1021
- const transaction = db.transaction(table, "readwrite");
1022
- const store2 = transaction.objectStore(table);
1024
+ const transaction2 = db.transaction(table, "readwrite");
1025
+ const store2 = transaction2.objectStore(table);
1023
1026
  const clearRequest = store2.clear();
1024
1027
  clearRequest.onsuccess = () => {
1025
1028
  db.close();
@@ -1053,8 +1056,8 @@ var init_data_set = __esm({
1053
1056
  db.close();
1054
1057
  return reject(new Error(`Table ${table} does not exist in ${storeName}`));
1055
1058
  }
1056
- const transaction = db.transaction(table, "readwrite");
1057
- const objectStore = transaction.objectStore(table);
1059
+ const transaction2 = db.transaction(table, "readwrite");
1060
+ const objectStore = transaction2.objectStore(table);
1058
1061
  const putRequest = objectStore.put(value);
1059
1062
  putRequest.onsuccess = () => {
1060
1063
  db.close();
@@ -1090,8 +1093,8 @@ var init_data_get = __esm({
1090
1093
  db.close();
1091
1094
  return reject(new Error(`Table ${table} not found in ${storeName}`));
1092
1095
  }
1093
- const transaction = db.transaction(table, "readonly");
1094
- const store2 = transaction.objectStore(table);
1096
+ const transaction2 = db.transaction(table, "readonly");
1097
+ const store2 = transaction2.objectStore(table);
1095
1098
  const getRequest = store2.get(key);
1096
1099
  getRequest.onsuccess = () => {
1097
1100
  db.close();
@@ -1753,9 +1756,25 @@ var dispatch = {
1753
1756
  const wrapped = /* @__PURE__ */ __name((e) => {
1754
1757
  const target = e;
1755
1758
  if (globalThis.queueMicrotask) {
1756
- globalThis.queueMicrotask(() => cb(target));
1759
+ globalThis.queueMicrotask(() => {
1760
+ try {
1761
+ cb(target);
1762
+ } catch (err) {
1763
+ if (typeof console !== "undefined") {
1764
+ console.error("[memorio dispatch] observer error:", err);
1765
+ }
1766
+ }
1767
+ });
1757
1768
  } else {
1758
- Promise.resolve().then(() => cb(target));
1769
+ Promise.resolve().then(() => {
1770
+ try {
1771
+ cb(target);
1772
+ } catch (err) {
1773
+ if (typeof console !== "undefined") {
1774
+ console.error("[memorio dispatch] observer error:", err);
1775
+ }
1776
+ }
1777
+ });
1759
1778
  }
1760
1779
  }, "wrapped");
1761
1780
  globalThis.addEventListener(name, wrapped);
@@ -1891,10 +1910,498 @@ var schema = {
1891
1910
  // functions/state/index.ts
1892
1911
  init_store();
1893
1912
  init_env();
1913
+
1914
+ // core/mutation/engine.ts
1915
+ init_cjs_shims();
1916
+ init_internal();
1917
+
1918
+ // core/hlc.ts
1919
+ init_cjs_shims();
1920
+ var NODE_ID_KEY = "__memorio_hlc_node";
1921
+ function getNodeId() {
1922
+ if (typeof globalThis === "undefined") return "node";
1923
+ try {
1924
+ if (typeof sessionStorage !== "undefined" && sessionStorage) {
1925
+ let id = sessionStorage.getItem(NODE_ID_KEY);
1926
+ if (!id) {
1927
+ id = generateNodeId();
1928
+ sessionStorage.setItem(NODE_ID_KEY, id);
1929
+ }
1930
+ return id;
1931
+ }
1932
+ } catch {
1933
+ }
1934
+ if (!globalThis.__memorioHlcNodeId) {
1935
+ globalThis.__memorioHlcNodeId = generateNodeId();
1936
+ }
1937
+ return globalThis.__memorioHlcNodeId;
1938
+ }
1939
+ __name(getNodeId, "getNodeId");
1940
+ function generateNodeId() {
1941
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
1942
+ return crypto.randomUUID().slice(0, 8);
1943
+ }
1944
+ return Math.random().toString(36).slice(2, 10);
1945
+ }
1946
+ __name(generateNodeId, "generateNodeId");
1947
+ var HLC_KEY = "__memorio_hlc_local";
1948
+ var local = globalThis[HLC_KEY] || {
1949
+ physical: 0,
1950
+ logical: 0,
1951
+ node: getNodeId()
1952
+ };
1953
+ if (!globalThis[HLC_KEY]) {
1954
+ globalThis[HLC_KEY] = local;
1955
+ }
1956
+ function tick(_incoming) {
1957
+ const now2 = Date.now();
1958
+ const base = local.physical;
1959
+ let physical;
1960
+ let logical;
1961
+ if (now2 > base) {
1962
+ physical = now2;
1963
+ logical = 0;
1964
+ } else if (now2 < base) {
1965
+ physical = base;
1966
+ logical = local.logical + 1;
1967
+ } else {
1968
+ physical = base;
1969
+ logical = local.logical + 1;
1970
+ }
1971
+ local.physical = physical;
1972
+ local.logical = logical;
1973
+ return { physical, logical, node: local.node };
1974
+ }
1975
+ __name(tick, "tick");
1976
+ function receive(remote) {
1977
+ const now2 = Date.now();
1978
+ if (remote.physical > local.physical) {
1979
+ local.physical = remote.physical > now2 ? remote.physical : now2;
1980
+ local.logical = 1;
1981
+ } else if (remote.physical === local.physical) {
1982
+ local.logical = Math.max(local.logical, remote.logical) + 1;
1983
+ }
1984
+ local.node = getNodeId();
1985
+ return { ...local };
1986
+ }
1987
+ __name(receive, "receive");
1988
+ function compare(a, b) {
1989
+ if (a.physical !== b.physical) {
1990
+ return a.physical < b.physical ? -1 : 1;
1991
+ }
1992
+ if (a.logical !== b.logical) {
1993
+ return a.logical < b.logical ? -1 : 1;
1994
+ }
1995
+ if (a.node !== b.node) {
1996
+ return a.node < b.node ? -1 : 1;
1997
+ }
1998
+ return 0;
1999
+ }
2000
+ __name(compare, "compare");
2001
+ function happenedBefore(a, b) {
2002
+ return compare(a, b) < 0;
2003
+ }
2004
+ __name(happenedBefore, "happenedBefore");
2005
+ function serialize(hlc2) {
2006
+ return `hlc:${hlc2.physical}:${hlc2.logical}:${hlc2.node}`;
2007
+ }
2008
+ __name(serialize, "serialize");
2009
+ function parse(serialized) {
2010
+ if (!serialized.startsWith("hlc:")) return null;
2011
+ const parts = serialized.split(":");
2012
+ if (parts.length !== 4) return null;
2013
+ const physical = parseInt(parts[1], 10);
2014
+ const logical = parseInt(parts[2], 10);
2015
+ const node = parts[3];
2016
+ if (isNaN(physical) || isNaN(logical)) return null;
2017
+ return { physical, logical, node };
2018
+ }
2019
+ __name(parse, "parse");
2020
+ var hlc = {
2021
+ tick,
2022
+ receive,
2023
+ compare,
2024
+ happenedBefore,
2025
+ serialize,
2026
+ parse,
2027
+ getNodeId
2028
+ };
2029
+
2030
+ // core/mutation/id.ts
2031
+ init_cjs_shims();
2032
+ function generateMutationId() {
2033
+ const now2 = hlc.tick();
2034
+ return "m_" + encodeHLC(now2);
2035
+ }
2036
+ __name(generateMutationId, "generateMutationId");
2037
+ function generateTransactionId() {
2038
+ const now2 = hlc.tick();
2039
+ return "tx_" + encodeHLC(now2);
2040
+ }
2041
+ __name(generateTransactionId, "generateTransactionId");
2042
+ function generateCommitId() {
2043
+ const now2 = hlc.tick();
2044
+ return "c_" + encodeHLC(now2);
2045
+ }
2046
+ __name(generateCommitId, "generateCommitId");
2047
+ function encodeHLC(hlcValue) {
2048
+ const timePart = hlcValue.physical.toString(36);
2049
+ const logicalPart = hlcValue.logical.toString(36).padStart(2, "0");
2050
+ const nodePart = hlcValue.node.slice(0, 4);
2051
+ return `${timePart}${logicalPart}${nodePart}`;
2052
+ }
2053
+ __name(encodeHLC, "encodeHLC");
2054
+
2055
+ // core/mutation/patch.ts
2056
+ init_cjs_shims();
2057
+ function mutationToPatch(mutation) {
2058
+ if (mutation.before === mutation.after) return null;
2059
+ const op = mutationToPatchOp(mutation.operation, mutation.before, mutation.after);
2060
+ if (!op) return null;
2061
+ const patch = { op, path: mutation.path };
2062
+ if (op === "add" || op === "replace") {
2063
+ patch.value = mutation.after;
2064
+ }
2065
+ if (op === "replace") {
2066
+ patch.oldValue = mutation.before;
2067
+ }
2068
+ if (op === "remove") {
2069
+ patch.oldValue = mutation.before;
2070
+ }
2071
+ return patch;
2072
+ }
2073
+ __name(mutationToPatch, "mutationToPatch");
2074
+ function mutationToPatchOp(operation, _before, _after) {
2075
+ switch (operation) {
2076
+ case "set":
2077
+ if (_before === void 0) return "add";
2078
+ return "replace";
2079
+ case "delete":
2080
+ return "remove";
2081
+ case "insert":
2082
+ return "add";
2083
+ case "remove":
2084
+ return "remove";
2085
+ case "replace":
2086
+ return "replace";
2087
+ case "length":
2088
+ return "replace";
2089
+ default:
2090
+ return null;
2091
+ }
2092
+ }
2093
+ __name(mutationToPatchOp, "mutationToPatchOp");
2094
+ function diffToPatch(path, before2, after2) {
2095
+ if (before2 === after2) return null;
2096
+ if (after2 === void 0) {
2097
+ return { op: "remove", path, oldValue: before2 };
2098
+ }
2099
+ if (before2 === void 0) {
2100
+ return { op: "add", path, value: after2 };
2101
+ }
2102
+ return { op: "replace", path, value: after2, oldValue: before2 };
2103
+ }
2104
+ __name(diffToPatch, "diffToPatch");
2105
+ function canMerge(patch1, patch2) {
2106
+ return patch1.path === patch2.path && patch1.op === patch2.op;
2107
+ }
2108
+ __name(canMerge, "canMerge");
2109
+ function mergePatches(patch1, patch2) {
2110
+ const op = patch1.op === "remove" && patch2.op === "remove" ? "remove" : "replace";
2111
+ return {
2112
+ op,
2113
+ path: patch1.path,
2114
+ value: patch2.value ?? patch1.value,
2115
+ oldValue: patch1.oldValue
2116
+ };
2117
+ }
2118
+ __name(mergePatches, "mergePatches");
2119
+
2120
+ // core/mutation/transaction.ts
2121
+ init_cjs_shims();
2122
+ init_internal();
2123
+ var TX_REGISTRY_KEY = "__memorio_transaction_registry__";
2124
+ var registry = globalThis[TX_REGISTRY_KEY] || /* @__PURE__ */ new Map();
2125
+ if (!globalThis[TX_REGISTRY_KEY]) {
2126
+ globalThis[TX_REGISTRY_KEY] = registry;
2127
+ }
2128
+ var TX_STACK_KEY = "__memorio_transaction_stack__";
2129
+ var txStack = globalThis[TX_STACK_KEY] || [];
2130
+ if (!globalThis[TX_STACK_KEY]) {
2131
+ globalThis[TX_STACK_KEY] = txStack;
2132
+ }
2133
+ function getActiveTxId() {
2134
+ return txStack.length > 0 ? txStack[txStack.length - 1] : null;
2135
+ }
2136
+ __name(getActiveTxId, "getActiveTxId");
2137
+ function setActiveTx(id) {
2138
+ if (id === null) {
2139
+ txStack.pop();
2140
+ } else {
2141
+ txStack.push(id);
2142
+ }
2143
+ }
2144
+ __name(setActiveTx, "setActiveTx");
2145
+ function beginTransaction(source, message2, metadata) {
2146
+ const id = generateTransactionId();
2147
+ const ctx = {
2148
+ id,
2149
+ startedAt: hlc.serialize(hlc.tick()),
2150
+ source,
2151
+ message: message2,
2152
+ metadata,
2153
+ mutations: [],
2154
+ active: true
2155
+ };
2156
+ registry.set(id, ctx);
2157
+ setActiveTx(id);
2158
+ return ctx;
2159
+ }
2160
+ __name(beginTransaction, "beginTransaction");
2161
+ function tagForTransaction() {
2162
+ const txId = getActiveTxId();
2163
+ if (!txId) return void 0;
2164
+ const ctx = registry.get(txId);
2165
+ if (ctx && ctx.active) {
2166
+ return txId;
2167
+ }
2168
+ return void 0;
2169
+ }
2170
+ __name(tagForTransaction, "tagForTransaction");
2171
+ function commitTransaction() {
2172
+ const txId = getActiveTxId();
2173
+ if (!txId) return null;
2174
+ const ctx = registry.get(txId);
2175
+ if (!ctx || !ctx.active) return null;
2176
+ ctx.active = false;
2177
+ ctx.committedAt = hlc.serialize(hlc.tick());
2178
+ const tx = {
2179
+ id: ctx.id,
2180
+ mutations: ctx.mutations,
2181
+ startedAt: ctx.startedAt,
2182
+ committedAt: ctx.committedAt,
2183
+ source: ctx.source,
2184
+ message: ctx.message,
2185
+ metadata: ctx.metadata
2186
+ };
2187
+ setActiveTx(null);
2188
+ return tx;
2189
+ }
2190
+ __name(commitTransaction, "commitTransaction");
2191
+ function _setPath(path, value) {
2192
+ const parts = path.replace(/^state\./, "").split(".");
2193
+ let current = globalThis.state;
2194
+ for (let i = 0; i < parts.length - 1; i++) {
2195
+ const part = parts[i];
2196
+ if (current[part] === void 0) {
2197
+ current[part] = {};
2198
+ }
2199
+ current = current[part];
2200
+ }
2201
+ current[parts[parts.length - 1]] = value;
2202
+ }
2203
+ __name(_setPath, "_setPath");
2204
+ function _deletePath(path) {
2205
+ const parts = path.replace(/^state\./, "").split(".");
2206
+ let current = globalThis.state;
2207
+ for (let i = 0; i < parts.length - 1; i++) {
2208
+ const part = parts[i];
2209
+ if (current[part] === void 0) return;
2210
+ current = current[part];
2211
+ }
2212
+ if (current.remove) {
2213
+ current.remove(parts[parts.length - 1]);
2214
+ } else {
2215
+ delete current[parts[parts.length - 1]];
2216
+ }
2217
+ }
2218
+ __name(_deletePath, "_deletePath");
2219
+ function _applyInverse(record) {
2220
+ const wasEnabled = exports.internal.historyEnabled;
2221
+ const wasRecording = exports.internal._recording;
2222
+ exports.internal.historyEnabled = false;
2223
+ exports.internal._recording = false;
2224
+ try {
2225
+ if (record.action === "set" || record.operation === "set") {
2226
+ if (record.previousValue === void 0) {
2227
+ _deletePath(record.path);
2228
+ } else {
2229
+ _setPath(record.path, record.previousValue);
2230
+ }
2231
+ } else if (record.action === "delete" || record.operation === "delete") {
2232
+ if (record.previousValue !== void 0) {
2233
+ _setPath(record.path, record.previousValue);
2234
+ }
2235
+ }
2236
+ } finally {
2237
+ exports.internal.historyEnabled = wasEnabled;
2238
+ exports.internal._recording = wasRecording;
2239
+ }
2240
+ }
2241
+ __name(_applyInverse, "_applyInverse");
2242
+ function abortTransaction() {
2243
+ const txId = getActiveTxId();
2244
+ if (!txId) return null;
2245
+ const ctx = registry.get(txId);
2246
+ if (!ctx || !ctx.active) return null;
2247
+ for (let i = ctx.mutations.length - 1; i >= 0; i--) {
2248
+ const undoStack = exports.internal.undoStack;
2249
+ const idx = undoStack.findIndex((r) => r.id === ctx.mutations[i]);
2250
+ if (idx >= 0) {
2251
+ const record = undoStack[idx];
2252
+ exports.internal.undoStack.splice(idx, 1);
2253
+ _applyInverse(record);
2254
+ }
2255
+ }
2256
+ ctx.active = false;
2257
+ ctx.committedAt = hlc.serialize(hlc.tick());
2258
+ const tx = {
2259
+ id: ctx.id,
2260
+ mutations: ctx.mutations,
2261
+ startedAt: ctx.startedAt,
2262
+ committedAt: ctx.committedAt,
2263
+ source: ctx.source,
2264
+ message: ctx.message,
2265
+ metadata: ctx.metadata
2266
+ };
2267
+ registry.delete(txId);
2268
+ setActiveTx(null);
2269
+ return tx;
2270
+ }
2271
+ __name(abortTransaction, "abortTransaction");
2272
+ function listTransactions() {
2273
+ const result = [];
2274
+ for (const ctx of registry.values()) {
2275
+ result.push({
2276
+ id: ctx.id,
2277
+ mutations: ctx.mutations,
2278
+ startedAt: ctx.startedAt,
2279
+ committedAt: ctx.committedAt,
2280
+ source: ctx.source,
2281
+ message: ctx.message,
2282
+ metadata: ctx.metadata
2283
+ });
2284
+ }
2285
+ return result;
2286
+ }
2287
+ __name(listTransactions, "listTransactions");
2288
+ function currentTransaction() {
2289
+ const txId = getActiveTxId();
2290
+ if (!txId) return null;
2291
+ const ctx = registry.get(txId);
2292
+ if (!ctx || !ctx.active) return null;
2293
+ return {
2294
+ id: ctx.id,
2295
+ mutations: ctx.mutations,
2296
+ startedAt: ctx.startedAt,
2297
+ source: ctx.source,
2298
+ message: ctx.message,
2299
+ metadata: ctx.metadata
2300
+ };
2301
+ }
2302
+ __name(currentTransaction, "currentTransaction");
2303
+ function registerMutationInTransaction(mutationId) {
2304
+ const txId = getActiveTxId();
2305
+ if (!txId) return;
2306
+ const ctx = registry.get(txId);
2307
+ if (ctx && ctx.active) {
2308
+ ctx.mutations.push(mutationId);
2309
+ }
2310
+ }
2311
+ __name(registerMutationInTransaction, "registerMutationInTransaction");
2312
+
2313
+ // core/mutation/engine.ts
2314
+ function currentTimestamp() {
2315
+ return hlc.serialize(hlc.tick());
2316
+ }
2317
+ __name(currentTimestamp, "currentTimestamp");
2318
+ function createMutation(path, operation, before2, after2, options) {
2319
+ const now2 = hlc.tick();
2320
+ const mutation = {
2321
+ id: generateMutationId(),
2322
+ path,
2323
+ operation,
2324
+ after: after2,
2325
+ before: before2,
2326
+ timestamp: now2.physical,
2327
+ hlc: hlc.serialize(now2),
2328
+ context: options?.context || exports.internal.currentContext || void 0,
2329
+ source: options?.source,
2330
+ transactionId: options?.transactionId || (operation !== "length" ? tagForTransaction() : void 0),
2331
+ // Legacy fields for backward compatibility
2332
+ action: operation === "set" ? "set" : "delete",
2333
+ newValue: after2,
2334
+ previousValue: before2
2335
+ };
2336
+ if (mutation.transactionId) {
2337
+ registerMutationInTransaction(mutation.id);
2338
+ }
2339
+ return mutation;
2340
+ }
2341
+ __name(createMutation, "createMutation");
2342
+ function recordMutation(mutation) {
2343
+ if (!exports.internal.historyEnabled) return;
2344
+ exports.internal.recordMutation(mutation);
2345
+ }
2346
+ __name(recordMutation, "recordMutation");
2347
+ function toPatch(mutation) {
2348
+ return mutationToPatch(mutation);
2349
+ }
2350
+ __name(toPatch, "toPatch");
2351
+ function mutate(path, value, options) {
2352
+ const normalizedPath = path.startsWith("state.") ? path : "state." + path;
2353
+ const keyPath = normalizedPath.replace(/^state\./, "");
2354
+ let current;
2355
+ try {
2356
+ const parts2 = keyPath.split(".");
2357
+ let obj = globalThis.state;
2358
+ for (const part of parts2) {
2359
+ obj = obj?.[part];
2360
+ }
2361
+ current = obj;
2362
+ } catch {
2363
+ current = void 0;
2364
+ }
2365
+ const operation = value === void 0 ? "delete" : "set";
2366
+ const mutation = createMutation(
2367
+ normalizedPath,
2368
+ operation,
2369
+ current,
2370
+ value === void 0 ? void 0 : value,
2371
+ options
2372
+ );
2373
+ const wasRecording = exports.internal._recording;
2374
+ exports.internal._recording = false;
2375
+ const parts = keyPath.split(".");
2376
+ let target = globalThis.state;
2377
+ for (let i = 0; i < parts.length - 1; i++) {
2378
+ if (target[parts[i]] === void 0) {
2379
+ target[parts[i]] = {};
2380
+ }
2381
+ target = target[parts[i]];
2382
+ }
2383
+ if (operation === "delete") {
2384
+ delete target[parts[parts.length - 1]];
2385
+ } else {
2386
+ target[parts[parts.length - 1]] = value;
2387
+ }
2388
+ exports.internal._recording = wasRecording;
2389
+ recordMutation(mutation);
2390
+ return mutation;
2391
+ }
2392
+ __name(mutate, "mutate");
2393
+ function activeTransactionId() {
2394
+ return exports.internal.currentTransactionId || null;
2395
+ }
2396
+ __name(activeTransactionId, "activeTransactionId");
2397
+
2398
+ // functions/state/index.ts
1894
2399
  var TARGET = /* @__PURE__ */ Symbol("memorio.target");
1895
2400
  var wrapperCache = /* @__PURE__ */ new WeakMap();
2401
+ var arrayRootDedup = /* @__PURE__ */ new Set();
1896
2402
  var deepRaw = /* @__PURE__ */ __name((val, seen = null) => {
1897
2403
  if (val === null || typeof val !== "object") return val;
2404
+ if (!seen) seen = /* @__PURE__ */ new WeakSet();
1898
2405
  if (val[TARGET] !== void 0) return deepRaw(val[TARGET], seen);
1899
2406
  if (seen) {
1900
2407
  if (seen.has(val)) return val;
@@ -1957,8 +2464,8 @@ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
1957
2464
  if (prop === "removeAll") {
1958
2465
  return () => {
1959
2466
  try {
1960
- for (const key in target) {
1961
- if (typeof target[key] !== "function" && !["list", "remove", "removeAll", "lock", "unlock"].includes(key)) {
2467
+ for (const key of Reflect.ownKeys(target)) {
2468
+ if (typeof target[key] !== "function" && !["list", "remove", "removeAll", "lock", "unlock", "persist"].includes(key)) {
1962
2469
  delete target[key];
1963
2470
  }
1964
2471
  }
@@ -2032,6 +2539,16 @@ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
2032
2539
  }
2033
2540
  );
2034
2541
  event("state." + path);
2542
+ if (Array.isArray(target) && tree.length > 0) {
2543
+ const rootName = "state." + tree.join(".");
2544
+ if (!arrayRootDedup.has(rootName)) {
2545
+ arrayRootDedup.add(rootName);
2546
+ event(rootName);
2547
+ if (typeof globalThis.queueMicrotask === "function") {
2548
+ globalThis.queueMicrotask(() => arrayRootDedup.clear());
2549
+ }
2550
+ }
2551
+ }
2035
2552
  Reflect.set(target, key, rawValue);
2036
2553
  exports.internal.bumpStateVersion();
2037
2554
  if (target[key] && typeof target[key] === "object") {
@@ -2088,6 +2605,17 @@ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
2088
2605
  const path = objPath(prop, tree);
2089
2606
  const previousValue = Reflect.get(target, prop);
2090
2607
  callback({ action: "delete", path, target, previousValue });
2608
+ event("state." + path);
2609
+ if (Array.isArray(target) && tree.length > 0) {
2610
+ const rootName = "state." + tree.join(".");
2611
+ if (!arrayRootDedup.has(rootName)) {
2612
+ arrayRootDedup.add(rootName);
2613
+ event(rootName);
2614
+ if (typeof globalThis.queueMicrotask === "function") {
2615
+ globalThis.queueMicrotask(() => arrayRootDedup.clear());
2616
+ }
2617
+ }
2618
+ }
2091
2619
  return Reflect.deleteProperty(target, prop);
2092
2620
  } catch (error) {
2093
2621
  console.error("Error in deleteProperty trap:", error);
@@ -2109,57 +2637,83 @@ if (globalThis[STATE_INSTANCE_KEY]) {
2109
2637
  exports.state = globalThis[STATE_INSTANCE_KEY];
2110
2638
  } else {
2111
2639
  exports.state = buildProxy({}, (mutation) => {
2112
- if (exports.internal.historyEnabled) {
2113
- exports.internal.recordMutation({
2114
- path: mutation.path,
2115
- action: mutation.action,
2116
- newValue: mutation.newValue,
2117
- previousValue: mutation.previousValue,
2118
- timestamp: Date.now()
2119
- });
2120
- }
2121
- });
2122
- exports.state.lock = () => {
2123
- exports.internal.locked = true;
2124
- message_default("State is now locked. All modifications are blocked.");
2125
- };
2126
- exports.state.unlock = () => {
2127
- exports.internal.locked = false;
2128
- message_default("State is now unlocked. Modifications are allowed.");
2129
- };
2130
- exports.state.persist = (path) => {
2131
- if (typeof path !== "string" || !path.length) {
2132
- if (exports.DEV) console.warn('[memorio state] state.persist() requires a non-empty path string (e.g. "state.user")');
2133
- return () => {
2134
- };
2135
- }
2136
- const normalized = path.startsWith("state.") ? path : "state." + path;
2137
- const key = normalized.replace(/^state\./, "");
2138
- const segments = key.split(".");
2139
- const initial = exports.store.get(key);
2140
- if (initial !== void 0 && initial !== null) {
2141
- let acc = exports.state;
2142
- for (let i = 0; i < segments.length; i++) {
2143
- const seg = segments[i];
2144
- if (i === segments.length - 1) {
2145
- acc[seg] = deepRaw(initial);
2146
- } else {
2147
- if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
2148
- acc = acc[seg];
2640
+ if (exports.internal.historyEnabled && exports.internal._recording !== false) {
2641
+ const operation = mutation.action === "delete" ? "delete" : "set";
2642
+ const record = createMutation(
2643
+ mutation.path,
2644
+ operation,
2645
+ mutation.previousValue,
2646
+ mutation.newValue,
2647
+ {
2648
+ context: mutation.context,
2649
+ source: mutation.source
2149
2650
  }
2150
- }
2651
+ );
2652
+ exports.internal.recordMutation(record);
2151
2653
  }
2152
- const handler = /* @__PURE__ */ __name(() => {
2153
- let current = exports.state;
2154
- for (const seg of segments) {
2155
- current = current === void 0 || current === null ? void 0 : current[seg];
2156
- }
2157
- exports.store.set(key, deepRaw(current));
2158
- }, "handler");
2159
- const off = dispatch.listen(normalized, handler);
2160
- return typeof off === "function" ? off : () => {
2161
- };
2162
- };
2654
+ });
2655
+ const _rawTarget = exports.state[TARGET];
2656
+ try {
2657
+ Object.defineProperty(_rawTarget, "lock", {
2658
+ value: /* @__PURE__ */ __name(() => {
2659
+ exports.internal.locked = true;
2660
+ message_default("State is now locked. All modifications are blocked.");
2661
+ }, "value"),
2662
+ writable: true,
2663
+ configurable: true,
2664
+ enumerable: false
2665
+ });
2666
+ Object.defineProperty(_rawTarget, "unlock", {
2667
+ value: /* @__PURE__ */ __name(() => {
2668
+ exports.internal.locked = false;
2669
+ message_default("State is now unlocked. Modifications are allowed.");
2670
+ }, "value"),
2671
+ writable: true,
2672
+ configurable: true,
2673
+ enumerable: false
2674
+ });
2675
+ } catch (e) {
2676
+ if (exports.DEV) console.warn("[memorio state] lock/unlock defineProperty failed:", e);
2677
+ }
2678
+ try {
2679
+ Object.defineProperty(_rawTarget, "persist", {
2680
+ value: /* @__PURE__ */ __name((path) => {
2681
+ if (typeof path !== "string" || !path.length) {
2682
+ if (exports.DEV) console.warn('[memorio state] state.persist() requires a non-empty path string (e.g. "state.user")');
2683
+ return () => {
2684
+ };
2685
+ }
2686
+ const normalized = path.startsWith("state.") ? path : "state." + path;
2687
+ const key = normalized.replace(/^state\./, "");
2688
+ const segments = key.split(".");
2689
+ const initial = exports.store.get(key);
2690
+ if (initial !== void 0 && initial !== null) {
2691
+ let acc = exports.state;
2692
+ for (let i = 0; i < segments.length - 1; i++) {
2693
+ const seg = segments[i];
2694
+ if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
2695
+ acc = acc[seg];
2696
+ }
2697
+ if (acc) acc[segments[segments.length - 1]] = deepRaw(initial);
2698
+ }
2699
+ const handler = /* @__PURE__ */ __name(() => {
2700
+ let current = exports.state;
2701
+ for (const seg of segments) {
2702
+ current = current === void 0 || current === null ? void 0 : current[seg];
2703
+ }
2704
+ exports.store.set(key, deepRaw(current));
2705
+ }, "handler");
2706
+ const off = dispatch.listen(normalized, handler);
2707
+ return typeof off === "function" ? off : () => {
2708
+ };
2709
+ }, "value"),
2710
+ writable: true,
2711
+ configurable: true,
2712
+ enumerable: false
2713
+ });
2714
+ } catch (e) {
2715
+ if (exports.DEV) console.warn("[memorio state] persist defineProperty failed:", e);
2716
+ }
2163
2717
  globalThis[STATE_INSTANCE_KEY] = exports.state;
2164
2718
  }
2165
2719
 
@@ -2511,12 +3065,17 @@ var observerFunction = /* @__PURE__ */ __name((s, cb = null, option = true) => {
2511
3065
  const callbacks = Array.isArray(cb) ? cb : [cb];
2512
3066
  const obs = globalThis.observer;
2513
3067
  if (obs?.list?.[resolvedPath]) dispatch.remove(resolvedPath);
3068
+ const unsubs = [];
2514
3069
  callbacks.forEach((callback) => {
2515
3070
  if (typeof callback === "function") {
2516
- dispatch.listen(resolvedPath, callback, option);
3071
+ const off = dispatch.listen(resolvedPath, callback, option);
3072
+ if (typeof off === "function") unsubs.push(off);
2517
3073
  }
2518
3074
  });
2519
- return;
3075
+ if (unsubs.length === 1) return unsubs[0];
3076
+ if (unsubs.length > 1) return () => unsubs.forEach((u) => u());
3077
+ return () => {
3078
+ };
2520
3079
  }
2521
3080
  }, "observerFunction");
2522
3081
  var observer = observerFunction;
@@ -2579,7 +3138,6 @@ Object.defineProperties(
2579
3138
  init_cjs_shims();
2580
3139
  init_message();
2581
3140
  init_internal();
2582
- init_env();
2583
3141
  var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
2584
3142
  if (!deps || typeof func !== "function") {
2585
3143
  return () => {
@@ -2640,20 +3198,6 @@ var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
2640
3198
  };
2641
3199
  }
2642
3200
  }), "useObserver");
2643
- if (exports.DEV && !("useObserver" in globalThis)) {
2644
- if (!globalThis.useObserver) globalThis.useObserver = null;
2645
- Object.defineProperty(
2646
- globalThis,
2647
- "useObserver",
2648
- {
2649
- value: useObserver,
2650
- writable: true,
2651
- enumerable: false,
2652
- configurable: true
2653
- }
2654
- );
2655
- Object.freeze(globalThis.useObserver);
2656
- }
2657
3201
 
2658
3202
  // index.ts
2659
3203
  init_message();
@@ -2737,7 +3281,7 @@ var clearHistory = /* @__PURE__ */ __name(() => {
2737
3281
  logHistory.length = 0;
2738
3282
  }, "clearHistory");
2739
3283
  var getStats = /* @__PURE__ */ __name(() => {
2740
- const stats2 = {
3284
+ const stats = {
2741
3285
  total: logHistory.length,
2742
3286
  state: 0,
2743
3287
  store: 0,
@@ -2753,11 +3297,11 @@ var getStats = /* @__PURE__ */ __name(() => {
2753
3297
  if (entry) {
2754
3298
  const module = entry.module;
2755
3299
  const action = entry.action;
2756
- if (module && typeof stats2[module] === "number") stats2[module]++;
2757
- if (action && typeof stats2[action] === "number") stats2[action]++;
3300
+ if (module && typeof stats[module] === "number") stats[module]++;
3301
+ if (action && typeof stats[action] === "number") stats[action]++;
2758
3302
  }
2759
3303
  }
2760
- return stats2;
3304
+ return stats;
2761
3305
  }, "getStats");
2762
3306
  var exportLogs = /* @__PURE__ */ __name(() => {
2763
3307
  return JSON.stringify(logHistory, null, 2);
@@ -2774,378 +3318,6 @@ var logger = {
2774
3318
  exportLogs
2775
3319
  };
2776
3320
 
2777
- // functions/devtools/index.ts
2778
- init_cjs_shims();
2779
- init_internal();
2780
- init_env();
2781
- var _state = globalThis.__memorio_state_instance__;
2782
- var _store = globalThis.__memorio_store_instance__;
2783
- var _session = globalThis.__memorio_session_instance__;
2784
- var _cache = globalThis.__memorio_cache_instance__;
2785
- function isDebugEnabled2() {
2786
- return exports.DEV && exports.internal.debug === true;
2787
- }
2788
- __name(isDebugEnabled2, "isDebugEnabled");
2789
- function extractStoreData() {
2790
- if (!_store) return {};
2791
- const result = {};
2792
- const store2 = _store;
2793
- if (typeof store2.list === "function") {
2794
- try {
2795
- return store2.list();
2796
- } catch {
2797
- }
2798
- }
2799
- if (typeof store2.get === "function") {
2800
- for (const key of Object.keys(store2)) {
2801
- if (!["get", "set", "remove", "delete", "removeAll", "clearAll", "size", "isPersistent", "list"].includes(key)) {
2802
- try {
2803
- const val = store2.get(key);
2804
- if (val !== null && val !== void 0) {
2805
- result[key] = val;
2806
- }
2807
- } catch {
2808
- }
2809
- }
2810
- }
2811
- }
2812
- return result;
2813
- }
2814
- __name(extractStoreData, "extractStoreData");
2815
- function extractSessionData() {
2816
- if (!_session) return {};
2817
- const result = {};
2818
- const session2 = _session;
2819
- if (typeof session2.list === "function") {
2820
- try {
2821
- return session2.list();
2822
- } catch {
2823
- }
2824
- }
2825
- if (typeof session2.get === "function") {
2826
- for (const key of Object.keys(session2)) {
2827
- if (!["get", "set", "remove", "delete", "removeAll", "clearAll", "size", "isPersistent", "list"].includes(key)) {
2828
- try {
2829
- const val = session2.get(key);
2830
- if (val !== null && val !== void 0) {
2831
- result[key] = val;
2832
- }
2833
- } catch {
2834
- }
2835
- }
2836
- }
2837
- }
2838
- return result;
2839
- }
2840
- __name(extractSessionData, "extractSessionData");
2841
- var inspect = /* @__PURE__ */ __name(() => {
2842
- if (!isDebugEnabled2()) return;
2843
- if (_state) {
2844
- const stateList = _state.list;
2845
- let stateData;
2846
- if (typeof stateList === "function") {
2847
- stateData = stateList();
2848
- } else if (typeof stateList === "object" && stateList !== null) {
2849
- stateData = stateList;
2850
- } else {
2851
- stateData = _state;
2852
- }
2853
- console.table(stateData);
2854
- }
2855
- if (_store) {
2856
- console.table(extractStoreData());
2857
- }
2858
- if (_session) {
2859
- console.table(extractSessionData());
2860
- }
2861
- if (_cache) {
2862
- const cacheList = _cache.list;
2863
- let cacheData2;
2864
- if (typeof cacheList === "function") {
2865
- cacheData2 = cacheList();
2866
- } else if (typeof cacheList === "object" && cacheList !== null) {
2867
- cacheData2 = cacheList;
2868
- } else {
2869
- cacheData2 = _cache;
2870
- }
2871
- console.table(cacheData2);
2872
- }
2873
- }, "inspect");
2874
- var stats = /* @__PURE__ */ __name(() => {
2875
- const getKeys = /* @__PURE__ */ __name((obj) => {
2876
- if (!obj) return 0;
2877
- if (typeof obj.list === "function") {
2878
- try {
2879
- const list = obj.list();
2880
- return Object.keys(list).length;
2881
- } catch {
2882
- }
2883
- }
2884
- return Object.keys(obj).length;
2885
- }, "getKeys");
2886
- return {
2887
- stateKeys: getKeys(_state),
2888
- storeKeys: getKeys(_store),
2889
- sessionKeys: getKeys(_session),
2890
- cacheKeys: getKeys(_cache),
2891
- idbDatabases: 0,
2892
- sqliteDbCount: 0,
2893
- lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
2894
- };
2895
- }, "stats");
2896
- var clear = /* @__PURE__ */ __name((moduleName) => {
2897
- const targets = { state: _state, store: _store, session: _session, cache: _cache };
2898
- const target = targets[moduleName];
2899
- if (target && typeof target.clear === "function") {
2900
- target.clear();
2901
- } else if (target && typeof target.removeAll === "function") {
2902
- target.removeAll();
2903
- } else {
2904
- console.debug(`Module ${moduleName} not found or does not support clear()/removeAll()`);
2905
- }
2906
- }, "clear");
2907
- var clearAll = /* @__PURE__ */ __name(() => {
2908
- clear("state");
2909
- clear("store");
2910
- clear("session");
2911
- clear("cache");
2912
- }, "clearAll");
2913
- var exportData = /* @__PURE__ */ __name(() => {
2914
- const getStateData = /* @__PURE__ */ __name(() => {
2915
- if (!_state) return void 0;
2916
- try {
2917
- if (typeof _state.list === "function") {
2918
- return _state.list();
2919
- }
2920
- return _state;
2921
- } catch {
2922
- return void 0;
2923
- }
2924
- }, "getStateData");
2925
- const getStoreData = /* @__PURE__ */ __name(() => {
2926
- return extractStoreData();
2927
- }, "getStoreData");
2928
- const getSessionData = /* @__PURE__ */ __name(() => {
2929
- return extractSessionData();
2930
- }, "getSessionData");
2931
- const getCacheData = /* @__PURE__ */ __name(() => {
2932
- if (!_cache) return void 0;
2933
- try {
2934
- if (typeof _cache.list === "function") {
2935
- return _cache.list();
2936
- }
2937
- return _cache;
2938
- } catch {
2939
- return void 0;
2940
- }
2941
- }, "getCacheData");
2942
- const data = {
2943
- state: getStateData(),
2944
- store: getStoreData(),
2945
- session: getSessionData(),
2946
- cache: getCacheData(),
2947
- exportedAt: (/* @__PURE__ */ new Date()).toISOString()
2948
- };
2949
- return JSON.stringify(data, null, 2);
2950
- }, "exportData");
2951
- var importData = /* @__PURE__ */ __name((jsonString) => {
2952
- try {
2953
- const data = JSON.parse(jsonString);
2954
- if (data.state) {
2955
- Object.entries(data.state).forEach(([key, value]) => {
2956
- if (_state && key !== "list" && key !== "remove" && key !== "removeAll") {
2957
- ;
2958
- _state[key] = value;
2959
- }
2960
- });
2961
- }
2962
- if (data.store && _store && typeof _store.set === "function") {
2963
- Object.entries(data.store).forEach(([key, value]) => {
2964
- ;
2965
- _store.set(key, value);
2966
- });
2967
- }
2968
- if (data.session && _session && typeof _session.set === "function") {
2969
- Object.entries(data.session).forEach(([key, value]) => {
2970
- ;
2971
- _session.set(key, value);
2972
- });
2973
- }
2974
- if (data.cache && _cache) {
2975
- Object.entries(data.cache).forEach(([key, value]) => {
2976
- if (_cache && key !== "get" && key !== "set" && key !== "remove" && key !== "clear") {
2977
- ;
2978
- _cache[key] = value;
2979
- }
2980
- });
2981
- }
2982
- } catch (error) {
2983
- console.debug("Import failed:", error);
2984
- }
2985
- }, "importData");
2986
- var watch = /* @__PURE__ */ __name((moduleName, path) => {
2987
- const targets = { state: _state, store: _store, session: _session, cache: _cache };
2988
- const target = targets[moduleName];
2989
- if (!target) {
2990
- console.debug(`Module ${moduleName} not found`);
2991
- return;
2992
- }
2993
- const initialValue = target[path];
2994
- console.debug(`Watching ${moduleName}.${path} (initial: ${JSON.stringify(initialValue)})`);
2995
- if (moduleName === "state" && globalThis.memorio?.dispatch) {
2996
- const handler = /* @__PURE__ */ __name((e) => {
2997
- const detail = e.detail;
2998
- if (detail?.name?.includes(path)) {
2999
- console.debug(`Change: ${moduleName}.${path} =`, e.detail.value);
3000
- }
3001
- }, "handler");
3002
- target.addEventListener?.("memorio-change", handler);
3003
- }
3004
- }, "watch");
3005
- var help = /* @__PURE__ */ __name(() => {
3006
- console.debug(`
3007
- Memorio DevTools Help
3008
-
3009
- Available commands:
3010
- memorio.devtools.inspect() - Inspect all state modules
3011
- memorio.devtools.stats() - Show statistics
3012
- memorio.devtools.clear('module') - Clear specific module
3013
- memorio.devtools.clearAll() - Clear all modules
3014
- memorio.devtools.exportData() - Export all data as JSON
3015
- memorio.devtools.importData(json) - Import data from JSON
3016
- memorio.devtools.watch(module, path) - Watch a path for changes
3017
- memorio.devtools.help() - Show this help
3018
-
3019
- Shortcuts (dev only):
3020
- state - global state proxy
3021
- store - localStorage wrapper
3022
- session - sessionStorage wrapper
3023
- cache - in-memory cache
3024
- `);
3025
- }, "help");
3026
- var devtools = {
3027
- inspect,
3028
- stats,
3029
- clear,
3030
- clearAll,
3031
- exportData,
3032
- importData,
3033
- watch,
3034
- help
3035
- };
3036
-
3037
- // core/hlc.ts
3038
- init_cjs_shims();
3039
- var NODE_ID_KEY = "__memorio_hlc_node";
3040
- function getNodeId() {
3041
- if (typeof globalThis === "undefined") return "node";
3042
- try {
3043
- if (typeof sessionStorage !== "undefined" && sessionStorage) {
3044
- let id = sessionStorage.getItem(NODE_ID_KEY);
3045
- if (!id) {
3046
- id = generateNodeId();
3047
- sessionStorage.setItem(NODE_ID_KEY, id);
3048
- }
3049
- return id;
3050
- }
3051
- } catch {
3052
- }
3053
- if (!globalThis.__memorioHlcNodeId) {
3054
- globalThis.__memorioHlcNodeId = generateNodeId();
3055
- }
3056
- return globalThis.__memorioHlcNodeId;
3057
- }
3058
- __name(getNodeId, "getNodeId");
3059
- function generateNodeId() {
3060
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
3061
- return crypto.randomUUID().slice(0, 8);
3062
- }
3063
- return Math.random().toString(36).slice(2, 10);
3064
- }
3065
- __name(generateNodeId, "generateNodeId");
3066
- var HLC_KEY = "__memorio_hlc_local";
3067
- var local = globalThis[HLC_KEY] || {
3068
- physical: 0,
3069
- logical: 0,
3070
- node: getNodeId()
3071
- };
3072
- if (!globalThis[HLC_KEY]) {
3073
- globalThis[HLC_KEY] = local;
3074
- }
3075
- function tick(_incoming) {
3076
- const now2 = Date.now();
3077
- const base = local.physical;
3078
- let physical;
3079
- let logical;
3080
- if (now2 > base) {
3081
- physical = now2;
3082
- logical = 0;
3083
- } else if (now2 < base) {
3084
- physical = base;
3085
- logical = local.logical + 1;
3086
- } else {
3087
- physical = base;
3088
- logical = local.logical + 1;
3089
- }
3090
- local.physical = physical;
3091
- local.logical = logical;
3092
- return { physical, logical, node: local.node };
3093
- }
3094
- __name(tick, "tick");
3095
- function receive(remote) {
3096
- const now2 = Date.now();
3097
- if (remote.physical > local.physical) {
3098
- local.physical = remote.physical > now2 ? remote.physical : now2;
3099
- local.logical = 1;
3100
- } else if (remote.physical === local.physical) {
3101
- local.logical = Math.max(local.logical, remote.logical) + 1;
3102
- }
3103
- local.node = getNodeId();
3104
- return { ...local };
3105
- }
3106
- __name(receive, "receive");
3107
- function compare(a, b) {
3108
- if (a.physical !== b.physical) {
3109
- return a.physical < b.physical ? -1 : 1;
3110
- }
3111
- if (a.logical !== b.logical) {
3112
- return a.logical < b.logical ? -1 : 1;
3113
- }
3114
- if (a.node !== b.node) {
3115
- return a.node < b.node ? -1 : 1;
3116
- }
3117
- return 0;
3118
- }
3119
- __name(compare, "compare");
3120
- function happenedBefore(a, b) {
3121
- return compare(a, b) < 0;
3122
- }
3123
- __name(happenedBefore, "happenedBefore");
3124
- function serialize(hlc2) {
3125
- return `hlc:${hlc2.physical}:${hlc2.logical}:${hlc2.node}`;
3126
- }
3127
- __name(serialize, "serialize");
3128
- function parse(serialized) {
3129
- if (!serialized.startsWith("hlc:")) return null;
3130
- const parts = serialized.split(":");
3131
- if (parts.length !== 4) return null;
3132
- const physical = parseInt(parts[1], 10);
3133
- const logical = parseInt(parts[2], 10);
3134
- const node = parts[3];
3135
- if (isNaN(physical) || isNaN(logical)) return null;
3136
- return { physical, logical, node };
3137
- }
3138
- __name(parse, "parse");
3139
- var hlc = {
3140
- tick,
3141
- receive,
3142
- compare,
3143
- happenedBefore,
3144
- serialize,
3145
- parse,
3146
- getNodeId
3147
- };
3148
-
3149
3321
  // core/fractional.ts
3150
3322
  init_cjs_shims();
3151
3323
  function generateBetween(left, right, minChars = 2) {
@@ -3338,7 +3510,7 @@ init_internal();
3338
3510
 
3339
3511
  // package.json
3340
3512
  var package_default = {
3341
- version: "4.9.35"};
3513
+ version: "5.0.0"};
3342
3514
 
3343
3515
  // core/global.ts
3344
3516
  init_env();
@@ -3423,7 +3595,7 @@ var undo = /* @__PURE__ */ __name(() => {
3423
3595
  }
3424
3596
  const record = exports.internal.popUndo();
3425
3597
  if (!record) return void 0;
3426
- _applyInverse(record);
3598
+ _applyInverse2(record);
3427
3599
  message_default(`[memorio history] Undid: ${record.action} ${record.path}`);
3428
3600
  return record;
3429
3601
  }, "undo");
@@ -3438,41 +3610,41 @@ var redo = /* @__PURE__ */ __name(() => {
3438
3610
  message_default(`[memorio history] Redid: ${record.action} ${record.path}`);
3439
3611
  return record;
3440
3612
  }, "redo");
3441
- function _applyInverse(record) {
3613
+ function _applyInverse2(record) {
3442
3614
  const wasEnabled = exports.internal.historyEnabled;
3443
3615
  exports.internal.historyEnabled = false;
3444
3616
  try {
3445
3617
  if (record.action === "set") {
3446
3618
  if (record.previousValue === void 0) {
3447
- _deletePath(record.path);
3619
+ _deletePath2(record.path);
3448
3620
  } else {
3449
- _setPath(record.path, record.previousValue);
3621
+ _setPath2(record.path, record.previousValue);
3450
3622
  }
3451
3623
  } else if (record.action === "delete") {
3452
3624
  if (record.previousValue !== void 0) {
3453
- _setPath(record.path, record.previousValue);
3625
+ _setPath2(record.path, record.previousValue);
3454
3626
  }
3455
3627
  }
3456
3628
  } finally {
3457
3629
  exports.internal.historyEnabled = wasEnabled;
3458
3630
  }
3459
3631
  }
3460
- __name(_applyInverse, "_applyInverse");
3632
+ __name(_applyInverse2, "_applyInverse");
3461
3633
  function _applyForward(record) {
3462
3634
  const wasEnabled = exports.internal.historyEnabled;
3463
3635
  exports.internal.historyEnabled = false;
3464
3636
  try {
3465
3637
  if (record.action === "set") {
3466
- _setPath(record.path, record.newValue);
3638
+ _setPath2(record.path, record.newValue);
3467
3639
  } else if (record.action === "delete") {
3468
- _deletePath(record.path);
3640
+ _deletePath2(record.path);
3469
3641
  }
3470
3642
  } finally {
3471
3643
  exports.internal.historyEnabled = wasEnabled;
3472
3644
  }
3473
3645
  }
3474
3646
  __name(_applyForward, "_applyForward");
3475
- function _setPath(path, value) {
3647
+ function _setPath2(path, value) {
3476
3648
  const parts = path.split(".");
3477
3649
  let current = exports.state;
3478
3650
  for (let i = 0; i < parts.length - 1; i++) {
@@ -3484,8 +3656,8 @@ function _setPath(path, value) {
3484
3656
  }
3485
3657
  current[parts[parts.length - 1]] = value;
3486
3658
  }
3487
- __name(_setPath, "_setPath");
3488
- function _deletePath(path) {
3659
+ __name(_setPath2, "_setPath");
3660
+ function _deletePath2(path) {
3489
3661
  const parts = path.split(".");
3490
3662
  if (parts.length === 1) {
3491
3663
  exports.state.remove(parts[0]);
@@ -3499,7 +3671,7 @@ function _deletePath(path) {
3499
3671
  }
3500
3672
  delete current[parts[parts.length - 1]];
3501
3673
  }
3502
- __name(_deletePath, "_deletePath");
3674
+ __name(_deletePath2, "_deletePath");
3503
3675
  var rollback = /* @__PURE__ */ __name((snap) => {
3504
3676
  exports.state.removeAll();
3505
3677
  for (const key of Object.keys(snap)) {
@@ -4207,84 +4379,6 @@ var memory = {
4207
4379
  }
4208
4380
  };
4209
4381
 
4210
- // functions/inspect/index.ts
4211
- init_cjs_shims();
4212
- init_env();
4213
- var stateKeys = /* @__PURE__ */ __name(() => {
4214
- const raw = deepRaw(exports.state);
4215
- return Object.keys(raw).filter(
4216
- (k) => !["list", "remove", "removeAll", "lock", "unlock"].includes(k)
4217
- );
4218
- }, "stateKeys");
4219
- var pathExists = /* @__PURE__ */ __name((path) => {
4220
- if (!path || typeof path !== "string") return false;
4221
- const parts = path.replace(/^state\./, "").split(".");
4222
- let current = exports.state;
4223
- for (const part of parts) {
4224
- if (current === null || current === void 0) {
4225
- return false;
4226
- }
4227
- current = current[part];
4228
- }
4229
- return current !== void 0;
4230
- }, "pathExists");
4231
- var stateType = /* @__PURE__ */ __name((path) => {
4232
- const [exists, value] = _getValue(path);
4233
- if (!exists || value === void 0) return "undefined";
4234
- return Array.isArray(value) ? "array" : typeof value;
4235
- }, "stateType");
4236
- var stateGet = /* @__PURE__ */ __name((path) => {
4237
- const [exists, value] = _getValue(path);
4238
- if (!exists || value === void 0) return void 0;
4239
- return _clone2(value);
4240
- }, "stateGet");
4241
- var stateSchema = /* @__PURE__ */ __name(() => {
4242
- const result = [];
4243
- const _walk = /* @__PURE__ */ __name((obj, prefix) => {
4244
- if (obj === null || typeof obj !== "object" || Array.isArray(obj)) {
4245
- return;
4246
- }
4247
- const keys = Object.keys(obj).filter(
4248
- (k) => !["list", "remove", "removeAll", "lock", "unlock"].includes(k)
4249
- );
4250
- for (const key of keys) {
4251
- const newPath = prefix ? `${prefix}.${key}` : key;
4252
- const value = obj[key];
4253
- const defined = value !== void 0;
4254
- const type = defined ? Array.isArray(value) ? "array" : typeof value : "undefined";
4255
- result.push({ path: newPath, type, defined });
4256
- if (defined && typeof value === "object" && !Array.isArray(value) && value.constructor?.name === "Object") {
4257
- _walk(value, newPath);
4258
- }
4259
- }
4260
- }, "_walk");
4261
- _walk(deepRaw(exports.state), "");
4262
- return result;
4263
- }, "stateSchema");
4264
- function _getValue(path) {
4265
- if (!path || typeof path !== "string") return [false, void 0];
4266
- const parts = path.replace(/^state\./, "").split(".");
4267
- let current = exports.state;
4268
- for (const part of parts) {
4269
- if (current === null || current === void 0) {
4270
- return [false, void 0];
4271
- }
4272
- current = current[part];
4273
- }
4274
- return [current !== void 0, current];
4275
- }
4276
- __name(_getValue, "_getValue");
4277
- function _clone2(value) {
4278
- if (value === null || typeof value !== "object") return value;
4279
- try {
4280
- return deepRaw(value, /* @__PURE__ */ new WeakSet());
4281
- } catch (err) {
4282
- if (exports.DEV) console.warn("[memorio inspect] deep clone failed:", err);
4283
- return value;
4284
- }
4285
- }
4286
- __name(_clone2, "_clone");
4287
-
4288
4382
  // core/global.ts
4289
4383
  if (!("memorio" in globalThis)) {
4290
4384
  Object.defineProperty(
@@ -4318,6 +4412,26 @@ if (!("memorio" in globalThis)) {
4318
4412
  }
4319
4413
  );
4320
4414
  }
4415
+ if (typeof globalThis.addEventListener !== "function") {
4416
+ const listeners = {};
4417
+ globalThis.addEventListener = (name, cb) => {
4418
+ (listeners[name] = listeners[name] ?? []).push(cb);
4419
+ };
4420
+ globalThis.removeEventListener = (name, cb) => {
4421
+ const arr = listeners[name];
4422
+ if (arr) {
4423
+ const idx = arr.indexOf(cb);
4424
+ if (idx > -1) arr.splice(idx, 1);
4425
+ }
4426
+ };
4427
+ globalThis.dispatchEvent = (e) => {
4428
+ const type = (e && typeof e === "object" ? e.type : null) || String(e);
4429
+ const arr = listeners[type];
4430
+ if (arr) {
4431
+ arr.slice().forEach((cb) => cb(e));
4432
+ }
4433
+ };
4434
+ }
4321
4435
  if (typeof globalThis.addEventListener === "function") {
4322
4436
  dispatch.listen("memorio:memory:cleanup", async () => memory.forgetExpired?.());
4323
4437
  }
@@ -4359,10 +4473,17 @@ if (!("memorio" in globalThis)) {
4359
4473
  memorio.enableHistory = enableHistory;
4360
4474
  memorio.clearHistory = clearHistory2;
4361
4475
  memorio.clearRedo = clearRedo;
4476
+ memorio.mutate = mutate;
4477
+ memorio.createMutation = createMutation;
4478
+ memorio.recordMutation = recordMutation;
4479
+ memorio.toPatch = toPatch;
4480
+ memorio.transaction = beginTransaction;
4481
+ memorio.commitTransaction = commitTransaction;
4482
+ memorio.abortTransaction = abortTransaction;
4483
+ memorio.currentTransaction = currentTransaction;
4362
4484
  Object.defineProperty(memorio, "dispatch", { value: dispatch, writable: true, enumerable: false, configurable: true });
4363
- const isDev = exports.DEV;
4364
4485
  memorio.env = {
4365
- isDev,
4486
+ isDev: exports.DEV,
4366
4487
  isProd: exports.PROD
4367
4488
  };
4368
4489
  memorio.global = function() {
@@ -4381,163 +4502,57 @@ if (!("memorio" in globalThis)) {
4381
4502
  Object.defineProperty(globalThis, key, {
4382
4503
  value: globalDefinitions[key],
4383
4504
  writable: true,
4384
- enumerable: false,
4385
- configurable: true
4505
+ configurable: true,
4506
+ enumerable: false
4386
4507
  });
4387
4508
  }
4388
4509
  }
4510
+ if (typeof globalThis.useObserver === "function") {
4511
+ Object.freeze(globalThis.useObserver);
4512
+ }
4389
4513
  };
4390
- if (isDev) {
4391
- memorio.global();
4392
- }
4393
- if (exports.DEV) {
4394
- Object.defineProperty(
4395
- memorio,
4396
- "debug",
4397
- {
4398
- get: /* @__PURE__ */ __name(() => exports.internal.debug, "get"),
4399
- set: /* @__PURE__ */ __name((v) => {
4400
- exports.internal.debug = v;
4401
- }, "set"),
4402
- enumerable: false
4403
- }
4404
- );
4405
- const caps = getCapabilities();
4406
- Object.defineProperty(memorio, "_platform", { writable: false, enumerable: false, value: caps.platform });
4407
- Object.defineProperty(memorio, "_capabilities", { writable: false, enumerable: false, value: caps });
4408
- Object.defineProperty(memorio, "_sessionId", { writable: false, enumerable: false, value: generateSessionId() });
4409
- memorio.logger = logger;
4410
- if (!("$state" in globalThis)) Object.defineProperty(globalThis, "$state", { get: /* @__PURE__ */ __name(() => globalThis.state, "get"), configurable: true });
4411
- if (!("$store" in globalThis)) Object.defineProperty(globalThis, "$store", { get: /* @__PURE__ */ __name(() => globalThis.store, "get"), configurable: true });
4412
- if (!("$session" in globalThis)) Object.defineProperty(globalThis, "$session", { get: /* @__PURE__ */ __name(() => globalThis.session, "get"), configurable: true });
4413
- if (!("$cache" in globalThis)) Object.defineProperty(globalThis, "$cache", { get: /* @__PURE__ */ __name(() => globalThis.cache, "get"), configurable: true });
4414
- memorio.devtools = devtools;
4415
- memorio.inspect = stateKeys;
4416
- memorio.stateKeys = stateKeys;
4417
- memorio.pathExists = pathExists;
4418
- memorio.stateType = stateType;
4419
- memorio.stateGet = stateGet;
4420
- memorio.stateSchema = stateSchema;
4421
- memorio.help = function() {
4422
- console.debug(`
4423
- \u{1F9E0} Memorio ${package_default.version} - Help
4424
-
4425
- Core Modules (runtime):
4426
- state - Reactive state management (DEV global)
4427
- store - Persistent storage (localStorage/Map)
4428
- session - Session storage (sessionStorage/Map)
4429
- cache - In-memory cache
4430
- idb - IndexedDB (browser only)
4431
- sqlite - SQLite in browser (sql.js, optional)
4432
-
4433
- Platform Detection:
4434
- memorio.isBrowser() - Browser environment
4435
- memorio.isNode() - Node.js environment
4436
- memorio.isDeno() - Deno environment
4437
- memorio.isEdge() - Edge/Worker environment
4438
- memorio.getCapabilities() - Full capabilities object
4439
-
4440
- Context Management:
4441
- memorio.isolate(name) - Create isolated context
4442
- memorio.listContexts() - List all contexts
4443
- memorio.deleteContext(id) - Delete a context
4444
-
4445
- Schema Validation (runtime):
4446
- memorio.registerSchema() - Register a validator for a state path
4447
- memorio.validate() - Manually validate a value
4448
- memorio.unregisterSchema() - Remove a registered schema
4449
- memorio.listSchemas() - List all registered schema paths
4450
- memorio.typed<T>() - Type-safe view of global state (compile-time only)
4451
-
4452
- History & Time Travel (runtime):
4453
- memorio.snapshot() - Capture a deep snapshot of state
4454
- memorio.diff(snap) - Diff snapshot against current state
4455
- memorio.undo() / redo() - Undo / redo the last mutation
4456
- memorio.canUndo() / canRedo() - Check availability
4457
- memorio.rollback(snap) - Restore state from a snapshot
4458
- memorio.trace() - List all recorded mutations
4459
- memorio.enableHistory() - Enable/disable mutation tracking
4460
- memorio.clearHistory() - Clear undo/redo stacks and trace log
4461
-
4462
- DevTools (development-only):
4463
- memorio.devtools.inspect() - Inspect all modules
4464
- memorio.devtools.stats() - Show statistics
4465
- memorio.devtools.watch() - Watch a path
4466
- memorio.devtools.exportData() - Export as JSON
4467
- memorio.devtools.importData() - Import from JSON
4468
- memorio.devtools.clear() - Clear specific module
4469
- memorio.devtools.clearAll() - Clear all modules
4470
-
4471
- Introspection (development-only):
4472
- memorio.stateKeys() - List top-level state keys
4473
- memorio.pathExists(path) - Check if a state path exists
4474
- memorio.stateType(path) - Get runtime type of a state value
4475
- memorio.stateGet(path) - Get a deep-cloned value at a path
4476
- memorio.stateSchema() - Get a schema report of all state paths
4477
-
4478
- Debug:
4479
- memorio.debug = true - Enable debug output (DEV only)
4480
-
4481
- Memory System (runtime):
4482
- memorio.memory.remember(key, value, opts) - Store a memory with type, confidence, scope, TTL, tags
4483
- memorio.memory.recall(key, opts) - Retrieve a memory with filtering
4484
- memorio.memory.update(key, value, opts) - Update an existing memory
4485
- memorio.memory.forget(key) - Delete a specific memory
4486
- memorio.memory.context(opts) - Get ranked relevant memories (semantic context for AI)
4487
- memorio.memory.stats() - Memory usage statistics
4488
- memorio.memory.forgetExpired() - Remove all expired entries
4489
- memorio.memory.clear() - Wipe all memories
4490
- memorio.memory.configure({ sync }) - Optional cloud-sync provider + namespace
4491
- memorio.memory.journal.pending() - Local op journal (SQLite/store)
4492
-
4493
- Scopes:
4494
- hot - In-memory reactive state (volatile, fastest)
4495
- session - sessionStorage (persists across page reloads, cleared on tab close)
4496
- local - localStorage (persistent, survives browser restart)
4497
- durable - IndexedDB (large datasets, async)
4498
- sql - SQLite / sql.js (browser, optional, full SQL)
4499
-
4500
- TTL options:
4501
- ttl: number (milliseconds) or null (never expires)
4502
-
4503
- Memory types:
4504
- fact, preference, decision, task, context
4505
-
4506
- Console shortcuts (DEV only):
4507
- state, store, session, cache, idb, sqlite - direct access to modules
4508
- $state, $store, $session, $cache - aliases for the above
4509
- `);
4510
- };
4511
- }
4512
4514
  }
4513
4515
 
4514
4516
  // index.ts
4515
- var devtools2 = exports.DEV ? devtools : void 0;
4517
+ var transaction = beginTransaction;
4518
+ var devtools = void 0;
4516
4519
  var memorio2 = globalThis.memorio;
4517
4520
  var events = globalThis.events;
4518
4521
  var isolate = /* @__PURE__ */ __name((name) => createContext(name), "isolate");
4519
- var help2 = globalThis.memorio?.help;
4522
+ var help = globalThis.memorio?.help;
4520
4523
  var setContext = /* @__PURE__ */ __name((id) => exports.internal.currentContext = id, "setContext");
4521
4524
  var getContext = /* @__PURE__ */ __name(() => exports.internal.currentContext, "getContext");
4522
4525
  var index_default = memorio2;
4523
4526
 
4527
+ exports.abortTransaction = abortTransaction;
4528
+ exports.activeTransactionId = activeTransactionId;
4529
+ exports.beginTransaction = beginTransaction;
4524
4530
  exports.cache = cache;
4531
+ exports.canMerge = canMerge;
4525
4532
  exports.canRedo = canRedo;
4526
4533
  exports.canUndo = canUndo;
4527
4534
  exports.clearHistory = clearHistory2;
4528
4535
  exports.clearRedo = clearRedo;
4536
+ exports.commitTransaction = commitTransaction;
4529
4537
  exports.createContext = createContext;
4538
+ exports.createMutation = createMutation;
4539
+ exports.currentTimestamp = currentTimestamp;
4540
+ exports.currentTransaction = currentTransaction;
4530
4541
  exports.default = index_default;
4531
4542
  exports.deleteContext = deleteContext;
4532
- exports.devtools = devtools2;
4543
+ exports.devtools = devtools;
4533
4544
  exports.diff = diff;
4545
+ exports.diffToPatch = diffToPatch;
4534
4546
  exports.dispatch = dispatch;
4535
4547
  exports.enableHistory = enableHistory;
4536
4548
  exports.events = events;
4537
4549
  exports.fractional = fractional;
4550
+ exports.generateCommitId = generateCommitId;
4551
+ exports.generateMutationId = generateMutationId;
4552
+ exports.generateTransactionId = generateTransactionId;
4538
4553
  exports.getCapabilities = getCapabilities;
4539
4554
  exports.getContext = getContext;
4540
- exports.help = help2;
4555
+ exports.help = help;
4541
4556
  exports.hlc = hlc;
4542
4557
  exports.isBrowser = isBrowser;
4543
4558
  exports.isDeno = isDeno;
@@ -4546,17 +4561,24 @@ exports.isNode = isNode;
4546
4561
  exports.isolate = isolate;
4547
4562
  exports.listContexts = listContexts;
4548
4563
  exports.listSchemas = listSchemas;
4564
+ exports.listTransactions = listTransactions;
4549
4565
  exports.logger = logger;
4550
4566
  exports.memorio = memorio2;
4551
4567
  exports.memory = memory;
4568
+ exports.mergePatches = mergePatches;
4569
+ exports.mutate = mutate;
4570
+ exports.mutationToPatch = mutationToPatch;
4552
4571
  exports.observer = observer;
4572
+ exports.recordMutation = recordMutation;
4553
4573
  exports.redo = redo;
4554
4574
  exports.registerSchema = registerSchema;
4555
4575
  exports.rollback = rollback;
4556
4576
  exports.schema = schema;
4557
4577
  exports.setContext = setContext;
4558
4578
  exports.snapshot = snapshot;
4579
+ exports.toPatch = toPatch;
4559
4580
  exports.trace = trace;
4581
+ exports.transaction = transaction;
4560
4582
  exports.typed = typed;
4561
4583
  exports.undo = undo;
4562
4584
  exports.unregisterSchema = unregisterSchema;