memorio 4.9.31 → 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 +327 -330
  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 +706 -649
  40. package/index.d.ts +1 -0
  41. package/index.js +686 -648
  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 +561 -374
  68. package/modules/redux.cjs.map +1 -1
  69. package/modules/redux.js +561 -374
  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);
@@ -1889,11 +1908,500 @@ var schema = {
1889
1908
  };
1890
1909
 
1891
1910
  // functions/state/index.ts
1911
+ init_store();
1892
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
1893
2399
  var TARGET = /* @__PURE__ */ Symbol("memorio.target");
1894
2400
  var wrapperCache = /* @__PURE__ */ new WeakMap();
2401
+ var arrayRootDedup = /* @__PURE__ */ new Set();
1895
2402
  var deepRaw = /* @__PURE__ */ __name((val, seen = null) => {
1896
2403
  if (val === null || typeof val !== "object") return val;
2404
+ if (!seen) seen = /* @__PURE__ */ new WeakSet();
1897
2405
  if (val[TARGET] !== void 0) return deepRaw(val[TARGET], seen);
1898
2406
  if (seen) {
1899
2407
  if (seen.has(val)) return val;
@@ -1903,6 +2411,7 @@ var deepRaw = /* @__PURE__ */ __name((val, seen = null) => {
1903
2411
  if (ctor !== "Object" && ctor !== "Array") return val;
1904
2412
  const copy = Array.isArray(val) ? [] : {};
1905
2413
  for (const k of Reflect.ownKeys(val)) {
2414
+ if (!Object.prototype.propertyIsEnumerable.call(val, k)) continue;
1906
2415
  copy[k] = deepRaw(val[k], seen);
1907
2416
  }
1908
2417
  return copy;
@@ -1955,8 +2464,8 @@ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
1955
2464
  if (prop === "removeAll") {
1956
2465
  return () => {
1957
2466
  try {
1958
- for (const key in target) {
1959
- 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)) {
1960
2469
  delete target[key];
1961
2470
  }
1962
2471
  }
@@ -2030,6 +2539,16 @@ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
2030
2539
  }
2031
2540
  );
2032
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
+ }
2033
2552
  Reflect.set(target, key, rawValue);
2034
2553
  exports.internal.bumpStateVersion();
2035
2554
  if (target[key] && typeof target[key] === "object") {
@@ -2086,6 +2605,17 @@ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
2086
2605
  const path = objPath(prop, tree);
2087
2606
  const previousValue = Reflect.get(target, prop);
2088
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
+ }
2089
2619
  return Reflect.deleteProperty(target, prop);
2090
2620
  } catch (error) {
2091
2621
  console.error("Error in deleteProperty trap:", error);
@@ -2107,28 +2637,87 @@ if (globalThis[STATE_INSTANCE_KEY]) {
2107
2637
  exports.state = globalThis[STATE_INSTANCE_KEY];
2108
2638
  } else {
2109
2639
  exports.state = buildProxy({}, (mutation) => {
2110
- if (exports.internal.historyEnabled) {
2111
- exports.internal.recordMutation({
2112
- path: mutation.path,
2113
- action: mutation.action,
2114
- newValue: mutation.newValue,
2115
- previousValue: mutation.previousValue,
2116
- timestamp: Date.now()
2117
- });
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
2650
+ }
2651
+ );
2652
+ exports.internal.recordMutation(record);
2118
2653
  }
2119
2654
  });
2120
- exports.state.lock = () => {
2121
- exports.internal.locked = true;
2122
- message_default("State is now locked. All modifications are blocked.");
2123
- };
2124
- exports.state.unlock = () => {
2125
- exports.internal.locked = false;
2126
- message_default("State is now unlocked. Modifications are allowed.");
2127
- };
2128
- globalThis[STATE_INSTANCE_KEY] = exports.state;
2129
- }
2130
-
2131
- // index.ts
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
+ }
2717
+ globalThis[STATE_INSTANCE_KEY] = exports.state;
2718
+ }
2719
+
2720
+ // index.ts
2132
2721
  init_store();
2133
2722
 
2134
2723
  // functions/session/index.ts
@@ -2476,12 +3065,17 @@ var observerFunction = /* @__PURE__ */ __name((s, cb = null, option = true) => {
2476
3065
  const callbacks = Array.isArray(cb) ? cb : [cb];
2477
3066
  const obs = globalThis.observer;
2478
3067
  if (obs?.list?.[resolvedPath]) dispatch.remove(resolvedPath);
3068
+ const unsubs = [];
2479
3069
  callbacks.forEach((callback) => {
2480
3070
  if (typeof callback === "function") {
2481
- dispatch.listen(resolvedPath, callback, option);
3071
+ const off = dispatch.listen(resolvedPath, callback, option);
3072
+ if (typeof off === "function") unsubs.push(off);
2482
3073
  }
2483
3074
  });
2484
- return;
3075
+ if (unsubs.length === 1) return unsubs[0];
3076
+ if (unsubs.length > 1) return () => unsubs.forEach((u) => u());
3077
+ return () => {
3078
+ };
2485
3079
  }
2486
3080
  }, "observerFunction");
2487
3081
  var observer = observerFunction;
@@ -2544,7 +3138,6 @@ Object.defineProperties(
2544
3138
  init_cjs_shims();
2545
3139
  init_message();
2546
3140
  init_internal();
2547
- init_env();
2548
3141
  var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
2549
3142
  if (!deps || typeof func !== "function") {
2550
3143
  return () => {
@@ -2605,20 +3198,6 @@ var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
2605
3198
  };
2606
3199
  }
2607
3200
  }), "useObserver");
2608
- if (exports.DEV && !("useObserver" in globalThis)) {
2609
- if (!globalThis.useObserver) globalThis.useObserver = null;
2610
- Object.defineProperty(
2611
- globalThis,
2612
- "useObserver",
2613
- {
2614
- value: useObserver,
2615
- writable: true,
2616
- enumerable: false,
2617
- configurable: true
2618
- }
2619
- );
2620
- Object.freeze(globalThis.useObserver);
2621
- }
2622
3201
 
2623
3202
  // index.ts
2624
3203
  init_message();
@@ -2702,7 +3281,7 @@ var clearHistory = /* @__PURE__ */ __name(() => {
2702
3281
  logHistory.length = 0;
2703
3282
  }, "clearHistory");
2704
3283
  var getStats = /* @__PURE__ */ __name(() => {
2705
- const stats2 = {
3284
+ const stats = {
2706
3285
  total: logHistory.length,
2707
3286
  state: 0,
2708
3287
  store: 0,
@@ -2718,11 +3297,11 @@ var getStats = /* @__PURE__ */ __name(() => {
2718
3297
  if (entry) {
2719
3298
  const module = entry.module;
2720
3299
  const action = entry.action;
2721
- if (module && typeof stats2[module] === "number") stats2[module]++;
2722
- 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]++;
2723
3302
  }
2724
3303
  }
2725
- return stats2;
3304
+ return stats;
2726
3305
  }, "getStats");
2727
3306
  var exportLogs = /* @__PURE__ */ __name(() => {
2728
3307
  return JSON.stringify(logHistory, null, 2);
@@ -2739,378 +3318,6 @@ var logger = {
2739
3318
  exportLogs
2740
3319
  };
2741
3320
 
2742
- // functions/devtools/index.ts
2743
- init_cjs_shims();
2744
- init_internal();
2745
- init_env();
2746
- var _state = globalThis.__memorio_state_instance__;
2747
- var _store = globalThis.__memorio_store_instance__;
2748
- var _session = globalThis.__memorio_session_instance__;
2749
- var _cache = globalThis.__memorio_cache_instance__;
2750
- function isDebugEnabled2() {
2751
- return exports.DEV && exports.internal.debug === true;
2752
- }
2753
- __name(isDebugEnabled2, "isDebugEnabled");
2754
- function extractStoreData() {
2755
- if (!_store) return {};
2756
- const result = {};
2757
- const store2 = _store;
2758
- if (typeof store2.list === "function") {
2759
- try {
2760
- return store2.list();
2761
- } catch {
2762
- }
2763
- }
2764
- if (typeof store2.get === "function") {
2765
- for (const key of Object.keys(store2)) {
2766
- if (!["get", "set", "remove", "delete", "removeAll", "clearAll", "size", "isPersistent", "list"].includes(key)) {
2767
- try {
2768
- const val = store2.get(key);
2769
- if (val !== null && val !== void 0) {
2770
- result[key] = val;
2771
- }
2772
- } catch {
2773
- }
2774
- }
2775
- }
2776
- }
2777
- return result;
2778
- }
2779
- __name(extractStoreData, "extractStoreData");
2780
- function extractSessionData() {
2781
- if (!_session) return {};
2782
- const result = {};
2783
- const session2 = _session;
2784
- if (typeof session2.list === "function") {
2785
- try {
2786
- return session2.list();
2787
- } catch {
2788
- }
2789
- }
2790
- if (typeof session2.get === "function") {
2791
- for (const key of Object.keys(session2)) {
2792
- if (!["get", "set", "remove", "delete", "removeAll", "clearAll", "size", "isPersistent", "list"].includes(key)) {
2793
- try {
2794
- const val = session2.get(key);
2795
- if (val !== null && val !== void 0) {
2796
- result[key] = val;
2797
- }
2798
- } catch {
2799
- }
2800
- }
2801
- }
2802
- }
2803
- return result;
2804
- }
2805
- __name(extractSessionData, "extractSessionData");
2806
- var inspect = /* @__PURE__ */ __name(() => {
2807
- if (!isDebugEnabled2()) return;
2808
- if (_state) {
2809
- const stateList = _state.list;
2810
- let stateData;
2811
- if (typeof stateList === "function") {
2812
- stateData = stateList();
2813
- } else if (typeof stateList === "object" && stateList !== null) {
2814
- stateData = stateList;
2815
- } else {
2816
- stateData = _state;
2817
- }
2818
- console.table(stateData);
2819
- }
2820
- if (_store) {
2821
- console.table(extractStoreData());
2822
- }
2823
- if (_session) {
2824
- console.table(extractSessionData());
2825
- }
2826
- if (_cache) {
2827
- const cacheList = _cache.list;
2828
- let cacheData2;
2829
- if (typeof cacheList === "function") {
2830
- cacheData2 = cacheList();
2831
- } else if (typeof cacheList === "object" && cacheList !== null) {
2832
- cacheData2 = cacheList;
2833
- } else {
2834
- cacheData2 = _cache;
2835
- }
2836
- console.table(cacheData2);
2837
- }
2838
- }, "inspect");
2839
- var stats = /* @__PURE__ */ __name(() => {
2840
- const getKeys = /* @__PURE__ */ __name((obj) => {
2841
- if (!obj) return 0;
2842
- if (typeof obj.list === "function") {
2843
- try {
2844
- const list = obj.list();
2845
- return Object.keys(list).length;
2846
- } catch {
2847
- }
2848
- }
2849
- return Object.keys(obj).length;
2850
- }, "getKeys");
2851
- return {
2852
- stateKeys: getKeys(_state),
2853
- storeKeys: getKeys(_store),
2854
- sessionKeys: getKeys(_session),
2855
- cacheKeys: getKeys(_cache),
2856
- idbDatabases: 0,
2857
- sqliteDbCount: 0,
2858
- lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
2859
- };
2860
- }, "stats");
2861
- var clear = /* @__PURE__ */ __name((moduleName) => {
2862
- const targets = { state: _state, store: _store, session: _session, cache: _cache };
2863
- const target = targets[moduleName];
2864
- if (target && typeof target.clear === "function") {
2865
- target.clear();
2866
- } else if (target && typeof target.removeAll === "function") {
2867
- target.removeAll();
2868
- } else {
2869
- console.debug(`Module ${moduleName} not found or does not support clear()/removeAll()`);
2870
- }
2871
- }, "clear");
2872
- var clearAll = /* @__PURE__ */ __name(() => {
2873
- clear("state");
2874
- clear("store");
2875
- clear("session");
2876
- clear("cache");
2877
- }, "clearAll");
2878
- var exportData = /* @__PURE__ */ __name(() => {
2879
- const getStateData = /* @__PURE__ */ __name(() => {
2880
- if (!_state) return void 0;
2881
- try {
2882
- if (typeof _state.list === "function") {
2883
- return _state.list();
2884
- }
2885
- return _state;
2886
- } catch {
2887
- return void 0;
2888
- }
2889
- }, "getStateData");
2890
- const getStoreData = /* @__PURE__ */ __name(() => {
2891
- return extractStoreData();
2892
- }, "getStoreData");
2893
- const getSessionData = /* @__PURE__ */ __name(() => {
2894
- return extractSessionData();
2895
- }, "getSessionData");
2896
- const getCacheData = /* @__PURE__ */ __name(() => {
2897
- if (!_cache) return void 0;
2898
- try {
2899
- if (typeof _cache.list === "function") {
2900
- return _cache.list();
2901
- }
2902
- return _cache;
2903
- } catch {
2904
- return void 0;
2905
- }
2906
- }, "getCacheData");
2907
- const data = {
2908
- state: getStateData(),
2909
- store: getStoreData(),
2910
- session: getSessionData(),
2911
- cache: getCacheData(),
2912
- exportedAt: (/* @__PURE__ */ new Date()).toISOString()
2913
- };
2914
- return JSON.stringify(data, null, 2);
2915
- }, "exportData");
2916
- var importData = /* @__PURE__ */ __name((jsonString) => {
2917
- try {
2918
- const data = JSON.parse(jsonString);
2919
- if (data.state) {
2920
- Object.entries(data.state).forEach(([key, value]) => {
2921
- if (_state && key !== "list" && key !== "remove" && key !== "removeAll") {
2922
- ;
2923
- _state[key] = value;
2924
- }
2925
- });
2926
- }
2927
- if (data.store && _store && typeof _store.set === "function") {
2928
- Object.entries(data.store).forEach(([key, value]) => {
2929
- ;
2930
- _store.set(key, value);
2931
- });
2932
- }
2933
- if (data.session && _session && typeof _session.set === "function") {
2934
- Object.entries(data.session).forEach(([key, value]) => {
2935
- ;
2936
- _session.set(key, value);
2937
- });
2938
- }
2939
- if (data.cache && _cache) {
2940
- Object.entries(data.cache).forEach(([key, value]) => {
2941
- if (_cache && key !== "get" && key !== "set" && key !== "remove" && key !== "clear") {
2942
- ;
2943
- _cache[key] = value;
2944
- }
2945
- });
2946
- }
2947
- } catch (error) {
2948
- console.debug("Import failed:", error);
2949
- }
2950
- }, "importData");
2951
- var watch = /* @__PURE__ */ __name((moduleName, path) => {
2952
- const targets = { state: _state, store: _store, session: _session, cache: _cache };
2953
- const target = targets[moduleName];
2954
- if (!target) {
2955
- console.debug(`Module ${moduleName} not found`);
2956
- return;
2957
- }
2958
- const initialValue = target[path];
2959
- console.debug(`Watching ${moduleName}.${path} (initial: ${JSON.stringify(initialValue)})`);
2960
- if (moduleName === "state" && globalThis.memorio?.dispatch) {
2961
- const handler = /* @__PURE__ */ __name((e) => {
2962
- const detail = e.detail;
2963
- if (detail?.name?.includes(path)) {
2964
- console.debug(`Change: ${moduleName}.${path} =`, e.detail.value);
2965
- }
2966
- }, "handler");
2967
- target.addEventListener?.("memorio-change", handler);
2968
- }
2969
- }, "watch");
2970
- var help = /* @__PURE__ */ __name(() => {
2971
- console.debug(`
2972
- Memorio DevTools Help
2973
-
2974
- Available commands:
2975
- memorio.devtools.inspect() - Inspect all state modules
2976
- memorio.devtools.stats() - Show statistics
2977
- memorio.devtools.clear('module') - Clear specific module
2978
- memorio.devtools.clearAll() - Clear all modules
2979
- memorio.devtools.exportData() - Export all data as JSON
2980
- memorio.devtools.importData(json) - Import data from JSON
2981
- memorio.devtools.watch(module, path) - Watch a path for changes
2982
- memorio.devtools.help() - Show this help
2983
-
2984
- Shortcuts (dev only):
2985
- state - global state proxy
2986
- store - localStorage wrapper
2987
- session - sessionStorage wrapper
2988
- cache - in-memory cache
2989
- `);
2990
- }, "help");
2991
- var devtools = {
2992
- inspect,
2993
- stats,
2994
- clear,
2995
- clearAll,
2996
- exportData,
2997
- importData,
2998
- watch,
2999
- help
3000
- };
3001
-
3002
- // core/hlc.ts
3003
- init_cjs_shims();
3004
- var NODE_ID_KEY = "__memorio_hlc_node";
3005
- function getNodeId() {
3006
- if (typeof globalThis === "undefined") return "node";
3007
- try {
3008
- if (typeof sessionStorage !== "undefined" && sessionStorage) {
3009
- let id = sessionStorage.getItem(NODE_ID_KEY);
3010
- if (!id) {
3011
- id = generateNodeId();
3012
- sessionStorage.setItem(NODE_ID_KEY, id);
3013
- }
3014
- return id;
3015
- }
3016
- } catch {
3017
- }
3018
- if (!globalThis.__memorioHlcNodeId) {
3019
- globalThis.__memorioHlcNodeId = generateNodeId();
3020
- }
3021
- return globalThis.__memorioHlcNodeId;
3022
- }
3023
- __name(getNodeId, "getNodeId");
3024
- function generateNodeId() {
3025
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
3026
- return crypto.randomUUID().slice(0, 8);
3027
- }
3028
- return Math.random().toString(36).slice(2, 10);
3029
- }
3030
- __name(generateNodeId, "generateNodeId");
3031
- var HLC_KEY = "__memorio_hlc_local";
3032
- var local = globalThis[HLC_KEY] || {
3033
- physical: 0,
3034
- logical: 0,
3035
- node: getNodeId()
3036
- };
3037
- if (!globalThis[HLC_KEY]) {
3038
- globalThis[HLC_KEY] = local;
3039
- }
3040
- function tick(_incoming) {
3041
- const now2 = Date.now();
3042
- const base = local.physical;
3043
- let physical;
3044
- let logical;
3045
- if (now2 > base) {
3046
- physical = now2;
3047
- logical = 0;
3048
- } else if (now2 < base) {
3049
- physical = base;
3050
- logical = local.logical + 1;
3051
- } else {
3052
- physical = base;
3053
- logical = local.logical + 1;
3054
- }
3055
- local.physical = physical;
3056
- local.logical = logical;
3057
- return { physical, logical, node: local.node };
3058
- }
3059
- __name(tick, "tick");
3060
- function receive(remote) {
3061
- const now2 = Date.now();
3062
- if (remote.physical > local.physical) {
3063
- local.physical = remote.physical > now2 ? remote.physical : now2;
3064
- local.logical = 1;
3065
- } else if (remote.physical === local.physical) {
3066
- local.logical = Math.max(local.logical, remote.logical) + 1;
3067
- }
3068
- local.node = getNodeId();
3069
- return { ...local };
3070
- }
3071
- __name(receive, "receive");
3072
- function compare(a, b) {
3073
- if (a.physical !== b.physical) {
3074
- return a.physical < b.physical ? -1 : 1;
3075
- }
3076
- if (a.logical !== b.logical) {
3077
- return a.logical < b.logical ? -1 : 1;
3078
- }
3079
- if (a.node !== b.node) {
3080
- return a.node < b.node ? -1 : 1;
3081
- }
3082
- return 0;
3083
- }
3084
- __name(compare, "compare");
3085
- function happenedBefore(a, b) {
3086
- return compare(a, b) < 0;
3087
- }
3088
- __name(happenedBefore, "happenedBefore");
3089
- function serialize(hlc2) {
3090
- return `hlc:${hlc2.physical}:${hlc2.logical}:${hlc2.node}`;
3091
- }
3092
- __name(serialize, "serialize");
3093
- function parse(serialized) {
3094
- if (!serialized.startsWith("hlc:")) return null;
3095
- const parts = serialized.split(":");
3096
- if (parts.length !== 4) return null;
3097
- const physical = parseInt(parts[1], 10);
3098
- const logical = parseInt(parts[2], 10);
3099
- const node = parts[3];
3100
- if (isNaN(physical) || isNaN(logical)) return null;
3101
- return { physical, logical, node };
3102
- }
3103
- __name(parse, "parse");
3104
- var hlc = {
3105
- tick,
3106
- receive,
3107
- compare,
3108
- happenedBefore,
3109
- serialize,
3110
- parse,
3111
- getNodeId
3112
- };
3113
-
3114
3321
  // core/fractional.ts
3115
3322
  init_cjs_shims();
3116
3323
  function generateBetween(left, right, minChars = 2) {
@@ -3303,7 +3510,7 @@ init_internal();
3303
3510
 
3304
3511
  // package.json
3305
3512
  var package_default = {
3306
- version: "4.9.31"};
3513
+ version: "5.0.0"};
3307
3514
 
3308
3515
  // core/global.ts
3309
3516
  init_env();
@@ -3388,7 +3595,7 @@ var undo = /* @__PURE__ */ __name(() => {
3388
3595
  }
3389
3596
  const record = exports.internal.popUndo();
3390
3597
  if (!record) return void 0;
3391
- _applyInverse(record);
3598
+ _applyInverse2(record);
3392
3599
  message_default(`[memorio history] Undid: ${record.action} ${record.path}`);
3393
3600
  return record;
3394
3601
  }, "undo");
@@ -3403,41 +3610,41 @@ var redo = /* @__PURE__ */ __name(() => {
3403
3610
  message_default(`[memorio history] Redid: ${record.action} ${record.path}`);
3404
3611
  return record;
3405
3612
  }, "redo");
3406
- function _applyInverse(record) {
3613
+ function _applyInverse2(record) {
3407
3614
  const wasEnabled = exports.internal.historyEnabled;
3408
3615
  exports.internal.historyEnabled = false;
3409
3616
  try {
3410
3617
  if (record.action === "set") {
3411
3618
  if (record.previousValue === void 0) {
3412
- _deletePath(record.path);
3619
+ _deletePath2(record.path);
3413
3620
  } else {
3414
- _setPath(record.path, record.previousValue);
3621
+ _setPath2(record.path, record.previousValue);
3415
3622
  }
3416
3623
  } else if (record.action === "delete") {
3417
3624
  if (record.previousValue !== void 0) {
3418
- _setPath(record.path, record.previousValue);
3625
+ _setPath2(record.path, record.previousValue);
3419
3626
  }
3420
3627
  }
3421
3628
  } finally {
3422
3629
  exports.internal.historyEnabled = wasEnabled;
3423
3630
  }
3424
3631
  }
3425
- __name(_applyInverse, "_applyInverse");
3632
+ __name(_applyInverse2, "_applyInverse");
3426
3633
  function _applyForward(record) {
3427
3634
  const wasEnabled = exports.internal.historyEnabled;
3428
3635
  exports.internal.historyEnabled = false;
3429
3636
  try {
3430
3637
  if (record.action === "set") {
3431
- _setPath(record.path, record.newValue);
3638
+ _setPath2(record.path, record.newValue);
3432
3639
  } else if (record.action === "delete") {
3433
- _deletePath(record.path);
3640
+ _deletePath2(record.path);
3434
3641
  }
3435
3642
  } finally {
3436
3643
  exports.internal.historyEnabled = wasEnabled;
3437
3644
  }
3438
3645
  }
3439
3646
  __name(_applyForward, "_applyForward");
3440
- function _setPath(path, value) {
3647
+ function _setPath2(path, value) {
3441
3648
  const parts = path.split(".");
3442
3649
  let current = exports.state;
3443
3650
  for (let i = 0; i < parts.length - 1; i++) {
@@ -3449,8 +3656,8 @@ function _setPath(path, value) {
3449
3656
  }
3450
3657
  current[parts[parts.length - 1]] = value;
3451
3658
  }
3452
- __name(_setPath, "_setPath");
3453
- function _deletePath(path) {
3659
+ __name(_setPath2, "_setPath");
3660
+ function _deletePath2(path) {
3454
3661
  const parts = path.split(".");
3455
3662
  if (parts.length === 1) {
3456
3663
  exports.state.remove(parts[0]);
@@ -3464,7 +3671,7 @@ function _deletePath(path) {
3464
3671
  }
3465
3672
  delete current[parts[parts.length - 1]];
3466
3673
  }
3467
- __name(_deletePath, "_deletePath");
3674
+ __name(_deletePath2, "_deletePath");
3468
3675
  var rollback = /* @__PURE__ */ __name((snap) => {
3469
3676
  exports.state.removeAll();
3470
3677
  for (const key of Object.keys(snap)) {
@@ -4172,84 +4379,6 @@ var memory = {
4172
4379
  }
4173
4380
  };
4174
4381
 
4175
- // functions/inspect/index.ts
4176
- init_cjs_shims();
4177
- init_env();
4178
- var stateKeys = /* @__PURE__ */ __name(() => {
4179
- const raw = deepRaw(exports.state);
4180
- return Object.keys(raw).filter(
4181
- (k) => !["list", "remove", "removeAll", "lock", "unlock"].includes(k)
4182
- );
4183
- }, "stateKeys");
4184
- var pathExists = /* @__PURE__ */ __name((path) => {
4185
- if (!path || typeof path !== "string") return false;
4186
- const parts = path.replace(/^state\./, "").split(".");
4187
- let current = exports.state;
4188
- for (const part of parts) {
4189
- if (current === null || current === void 0) {
4190
- return false;
4191
- }
4192
- current = current[part];
4193
- }
4194
- return current !== void 0;
4195
- }, "pathExists");
4196
- var stateType = /* @__PURE__ */ __name((path) => {
4197
- const [exists, value] = _getValue(path);
4198
- if (!exists || value === void 0) return "undefined";
4199
- return Array.isArray(value) ? "array" : typeof value;
4200
- }, "stateType");
4201
- var stateGet = /* @__PURE__ */ __name((path) => {
4202
- const [exists, value] = _getValue(path);
4203
- if (!exists || value === void 0) return void 0;
4204
- return _clone2(value);
4205
- }, "stateGet");
4206
- var stateSchema = /* @__PURE__ */ __name(() => {
4207
- const result = [];
4208
- const _walk = /* @__PURE__ */ __name((obj, prefix) => {
4209
- if (obj === null || typeof obj !== "object" || Array.isArray(obj)) {
4210
- return;
4211
- }
4212
- const keys = Object.keys(obj).filter(
4213
- (k) => !["list", "remove", "removeAll", "lock", "unlock"].includes(k)
4214
- );
4215
- for (const key of keys) {
4216
- const newPath = prefix ? `${prefix}.${key}` : key;
4217
- const value = obj[key];
4218
- const defined = value !== void 0;
4219
- const type = defined ? Array.isArray(value) ? "array" : typeof value : "undefined";
4220
- result.push({ path: newPath, type, defined });
4221
- if (defined && typeof value === "object" && !Array.isArray(value) && value.constructor?.name === "Object") {
4222
- _walk(value, newPath);
4223
- }
4224
- }
4225
- }, "_walk");
4226
- _walk(deepRaw(exports.state), "");
4227
- return result;
4228
- }, "stateSchema");
4229
- function _getValue(path) {
4230
- if (!path || typeof path !== "string") return [false, void 0];
4231
- const parts = path.replace(/^state\./, "").split(".");
4232
- let current = exports.state;
4233
- for (const part of parts) {
4234
- if (current === null || current === void 0) {
4235
- return [false, void 0];
4236
- }
4237
- current = current[part];
4238
- }
4239
- return [current !== void 0, current];
4240
- }
4241
- __name(_getValue, "_getValue");
4242
- function _clone2(value) {
4243
- if (value === null || typeof value !== "object") return value;
4244
- try {
4245
- return deepRaw(value, /* @__PURE__ */ new WeakSet());
4246
- } catch (err) {
4247
- if (exports.DEV) console.warn("[memorio inspect] deep clone failed:", err);
4248
- return value;
4249
- }
4250
- }
4251
- __name(_clone2, "_clone");
4252
-
4253
4382
  // core/global.ts
4254
4383
  if (!("memorio" in globalThis)) {
4255
4384
  Object.defineProperty(
@@ -4283,6 +4412,26 @@ if (!("memorio" in globalThis)) {
4283
4412
  }
4284
4413
  );
4285
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
+ }
4286
4435
  if (typeof globalThis.addEventListener === "function") {
4287
4436
  dispatch.listen("memorio:memory:cleanup", async () => memory.forgetExpired?.());
4288
4437
  }
@@ -4324,10 +4473,17 @@ if (!("memorio" in globalThis)) {
4324
4473
  memorio.enableHistory = enableHistory;
4325
4474
  memorio.clearHistory = clearHistory2;
4326
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;
4327
4484
  Object.defineProperty(memorio, "dispatch", { value: dispatch, writable: true, enumerable: false, configurable: true });
4328
- const isDev = exports.DEV;
4329
4485
  memorio.env = {
4330
- isDev,
4486
+ isDev: exports.DEV,
4331
4487
  isProd: exports.PROD
4332
4488
  };
4333
4489
  memorio.global = function() {
@@ -4346,163 +4502,57 @@ if (!("memorio" in globalThis)) {
4346
4502
  Object.defineProperty(globalThis, key, {
4347
4503
  value: globalDefinitions[key],
4348
4504
  writable: true,
4349
- enumerable: false,
4350
- configurable: true
4505
+ configurable: true,
4506
+ enumerable: false
4351
4507
  });
4352
4508
  }
4353
4509
  }
4510
+ if (typeof globalThis.useObserver === "function") {
4511
+ Object.freeze(globalThis.useObserver);
4512
+ }
4354
4513
  };
4355
- if (isDev) {
4356
- memorio.global();
4357
- }
4358
- if (exports.DEV) {
4359
- Object.defineProperty(
4360
- memorio,
4361
- "debug",
4362
- {
4363
- get: /* @__PURE__ */ __name(() => exports.internal.debug, "get"),
4364
- set: /* @__PURE__ */ __name((v) => {
4365
- exports.internal.debug = v;
4366
- }, "set"),
4367
- enumerable: false
4368
- }
4369
- );
4370
- const caps = getCapabilities();
4371
- Object.defineProperty(memorio, "_platform", { writable: false, enumerable: false, value: caps.platform });
4372
- Object.defineProperty(memorio, "_capabilities", { writable: false, enumerable: false, value: caps });
4373
- Object.defineProperty(memorio, "_sessionId", { writable: false, enumerable: false, value: generateSessionId() });
4374
- memorio.logger = logger;
4375
- if (!("$state" in globalThis)) Object.defineProperty(globalThis, "$state", { get: /* @__PURE__ */ __name(() => globalThis.state, "get"), configurable: true });
4376
- if (!("$store" in globalThis)) Object.defineProperty(globalThis, "$store", { get: /* @__PURE__ */ __name(() => globalThis.store, "get"), configurable: true });
4377
- if (!("$session" in globalThis)) Object.defineProperty(globalThis, "$session", { get: /* @__PURE__ */ __name(() => globalThis.session, "get"), configurable: true });
4378
- if (!("$cache" in globalThis)) Object.defineProperty(globalThis, "$cache", { get: /* @__PURE__ */ __name(() => globalThis.cache, "get"), configurable: true });
4379
- memorio.devtools = devtools;
4380
- memorio.inspect = stateKeys;
4381
- memorio.stateKeys = stateKeys;
4382
- memorio.pathExists = pathExists;
4383
- memorio.stateType = stateType;
4384
- memorio.stateGet = stateGet;
4385
- memorio.stateSchema = stateSchema;
4386
- memorio.help = function() {
4387
- console.debug(`
4388
- \u{1F9E0} Memorio ${package_default.version} - Help
4389
-
4390
- Core Modules (runtime):
4391
- state - Reactive state management (DEV global)
4392
- store - Persistent storage (localStorage/Map)
4393
- session - Session storage (sessionStorage/Map)
4394
- cache - In-memory cache
4395
- idb - IndexedDB (browser only)
4396
- sqlite - SQLite in browser (sql.js, optional)
4397
-
4398
- Platform Detection:
4399
- memorio.isBrowser() - Browser environment
4400
- memorio.isNode() - Node.js environment
4401
- memorio.isDeno() - Deno environment
4402
- memorio.isEdge() - Edge/Worker environment
4403
- memorio.getCapabilities() - Full capabilities object
4404
-
4405
- Context Management:
4406
- memorio.isolate(name) - Create isolated context
4407
- memorio.listContexts() - List all contexts
4408
- memorio.deleteContext(id) - Delete a context
4409
-
4410
- Schema Validation (runtime):
4411
- memorio.registerSchema() - Register a validator for a state path
4412
- memorio.validate() - Manually validate a value
4413
- memorio.unregisterSchema() - Remove a registered schema
4414
- memorio.listSchemas() - List all registered schema paths
4415
- memorio.typed<T>() - Type-safe view of global state (compile-time only)
4416
-
4417
- History & Time Travel (runtime):
4418
- memorio.snapshot() - Capture a deep snapshot of state
4419
- memorio.diff(snap) - Diff snapshot against current state
4420
- memorio.undo() / redo() - Undo / redo the last mutation
4421
- memorio.canUndo() / canRedo() - Check availability
4422
- memorio.rollback(snap) - Restore state from a snapshot
4423
- memorio.trace() - List all recorded mutations
4424
- memorio.enableHistory() - Enable/disable mutation tracking
4425
- memorio.clearHistory() - Clear undo/redo stacks and trace log
4426
-
4427
- DevTools (development-only):
4428
- memorio.devtools.inspect() - Inspect all modules
4429
- memorio.devtools.stats() - Show statistics
4430
- memorio.devtools.watch() - Watch a path
4431
- memorio.devtools.exportData() - Export as JSON
4432
- memorio.devtools.importData() - Import from JSON
4433
- memorio.devtools.clear() - Clear specific module
4434
- memorio.devtools.clearAll() - Clear all modules
4435
-
4436
- Introspection (development-only):
4437
- memorio.stateKeys() - List top-level state keys
4438
- memorio.pathExists(path) - Check if a state path exists
4439
- memorio.stateType(path) - Get runtime type of a state value
4440
- memorio.stateGet(path) - Get a deep-cloned value at a path
4441
- memorio.stateSchema() - Get a schema report of all state paths
4442
-
4443
- Debug:
4444
- memorio.debug = true - Enable debug output (DEV only)
4445
-
4446
- Memory System (runtime):
4447
- memorio.memory.remember(key, value, opts) - Store a memory with type, confidence, scope, TTL, tags
4448
- memorio.memory.recall(key, opts) - Retrieve a memory with filtering
4449
- memorio.memory.update(key, value, opts) - Update an existing memory
4450
- memorio.memory.forget(key) - Delete a specific memory
4451
- memorio.memory.context(opts) - Get ranked relevant memories (semantic context for AI)
4452
- memorio.memory.stats() - Memory usage statistics
4453
- memorio.memory.forgetExpired() - Remove all expired entries
4454
- memorio.memory.clear() - Wipe all memories
4455
- memorio.memory.configure({ sync }) - Optional cloud-sync provider + namespace
4456
- memorio.memory.journal.pending() - Local op journal (SQLite/store)
4457
-
4458
- Scopes:
4459
- hot - In-memory reactive state (volatile, fastest)
4460
- session - sessionStorage (persists across page reloads, cleared on tab close)
4461
- local - localStorage (persistent, survives browser restart)
4462
- durable - IndexedDB (large datasets, async)
4463
- sql - SQLite / sql.js (browser, optional, full SQL)
4464
-
4465
- TTL options:
4466
- ttl: number (milliseconds) or null (never expires)
4467
-
4468
- Memory types:
4469
- fact, preference, decision, task, context
4470
-
4471
- Console shortcuts (DEV only):
4472
- state, store, session, cache, idb, sqlite - direct access to modules
4473
- $state, $store, $session, $cache - aliases for the above
4474
- `);
4475
- };
4476
- }
4477
4514
  }
4478
4515
 
4479
4516
  // index.ts
4480
- var devtools2 = exports.DEV ? devtools : void 0;
4517
+ var transaction = beginTransaction;
4518
+ var devtools = void 0;
4481
4519
  var memorio2 = globalThis.memorio;
4482
4520
  var events = globalThis.events;
4483
4521
  var isolate = /* @__PURE__ */ __name((name) => createContext(name), "isolate");
4484
- var help2 = globalThis.memorio?.help;
4522
+ var help = globalThis.memorio?.help;
4485
4523
  var setContext = /* @__PURE__ */ __name((id) => exports.internal.currentContext = id, "setContext");
4486
4524
  var getContext = /* @__PURE__ */ __name(() => exports.internal.currentContext, "getContext");
4487
4525
  var index_default = memorio2;
4488
4526
 
4527
+ exports.abortTransaction = abortTransaction;
4528
+ exports.activeTransactionId = activeTransactionId;
4529
+ exports.beginTransaction = beginTransaction;
4489
4530
  exports.cache = cache;
4531
+ exports.canMerge = canMerge;
4490
4532
  exports.canRedo = canRedo;
4491
4533
  exports.canUndo = canUndo;
4492
4534
  exports.clearHistory = clearHistory2;
4493
4535
  exports.clearRedo = clearRedo;
4536
+ exports.commitTransaction = commitTransaction;
4494
4537
  exports.createContext = createContext;
4538
+ exports.createMutation = createMutation;
4539
+ exports.currentTimestamp = currentTimestamp;
4540
+ exports.currentTransaction = currentTransaction;
4495
4541
  exports.default = index_default;
4496
4542
  exports.deleteContext = deleteContext;
4497
- exports.devtools = devtools2;
4543
+ exports.devtools = devtools;
4498
4544
  exports.diff = diff;
4545
+ exports.diffToPatch = diffToPatch;
4499
4546
  exports.dispatch = dispatch;
4500
4547
  exports.enableHistory = enableHistory;
4501
4548
  exports.events = events;
4502
4549
  exports.fractional = fractional;
4550
+ exports.generateCommitId = generateCommitId;
4551
+ exports.generateMutationId = generateMutationId;
4552
+ exports.generateTransactionId = generateTransactionId;
4503
4553
  exports.getCapabilities = getCapabilities;
4504
4554
  exports.getContext = getContext;
4505
- exports.help = help2;
4555
+ exports.help = help;
4506
4556
  exports.hlc = hlc;
4507
4557
  exports.isBrowser = isBrowser;
4508
4558
  exports.isDeno = isDeno;
@@ -4511,17 +4561,24 @@ exports.isNode = isNode;
4511
4561
  exports.isolate = isolate;
4512
4562
  exports.listContexts = listContexts;
4513
4563
  exports.listSchemas = listSchemas;
4564
+ exports.listTransactions = listTransactions;
4514
4565
  exports.logger = logger;
4515
4566
  exports.memorio = memorio2;
4516
4567
  exports.memory = memory;
4568
+ exports.mergePatches = mergePatches;
4569
+ exports.mutate = mutate;
4570
+ exports.mutationToPatch = mutationToPatch;
4517
4571
  exports.observer = observer;
4572
+ exports.recordMutation = recordMutation;
4518
4573
  exports.redo = redo;
4519
4574
  exports.registerSchema = registerSchema;
4520
4575
  exports.rollback = rollback;
4521
4576
  exports.schema = schema;
4522
4577
  exports.setContext = setContext;
4523
4578
  exports.snapshot = snapshot;
4579
+ exports.toPatch = toPatch;
4524
4580
  exports.trace = trace;
4581
+ exports.transaction = transaction;
4525
4582
  exports.typed = typed;
4526
4583
  exports.undo = undo;
4527
4584
  exports.unregisterSchema = unregisterSchema;