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