memorio 4.9.35 → 5.1.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 (82) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +95 -516
  3. package/SECURITY.md +159 -33
  4. package/SUMMARY.md +59 -45
  5. package/adr/001-state-proxy-model.md +95 -0
  6. package/adr/002-observer-semantics.md +179 -0
  7. package/adr/003-deep-mutation-semantics.md +128 -0
  8. package/adr/004-array-mutation-semantics.md +127 -0
  9. package/adr/005-scheduler-contract.md +148 -0
  10. package/adr/006-context-isolation.md +91 -0
  11. package/adr/007-mutation-records.md +117 -0
  12. package/adr/008-transactions.md +105 -0
  13. package/adr/009-history-model.md +109 -0
  14. package/adr/README.md +46 -0
  15. package/adr/template.md +48 -0
  16. package/bin/cli.js +68 -0
  17. package/examples/basic.ts +115 -115
  18. package/examples/browser-vanilla.html +358 -358
  19. package/examples/cache.ts +72 -72
  20. package/examples/cross-platform-guards.ts +57 -57
  21. package/examples/history.ts +104 -0
  22. package/examples/idb.ts +109 -109
  23. package/examples/multi-tenant-context.ts +44 -44
  24. package/examples/node-server.ts +308 -308
  25. package/examples/observer.ts +60 -60
  26. package/examples/platform.ts +115 -115
  27. package/examples/react-app.tsx +362 -362
  28. package/examples/react-observer.tsx +63 -63
  29. package/examples/semantic-memory.ts +60 -60
  30. package/examples/session-advanced.ts +91 -91
  31. package/examples/sqlite-batched-writes.ts +57 -57
  32. package/examples/state-advanced.ts +89 -89
  33. package/examples/store-advanced.ts +117 -117
  34. package/examples/sync.ts +90 -0
  35. package/examples/typed-and-schema.ts +102 -100
  36. package/examples/useObserver.tsx +140 -141
  37. package/global.cjs +5733 -0
  38. package/global.d.ts +8 -0
  39. package/global.js +5667 -0
  40. package/index.cjs +2202 -1041
  41. package/index.d.ts +2 -0
  42. package/index.js +2178 -1040
  43. package/llms.txt +113 -8
  44. package/markdown/AUDIT-REPORT.md +134 -0
  45. package/markdown/CACHE.md +191 -0
  46. package/markdown/DEVTOOLS.md +128 -0
  47. package/markdown/DISPATCH.md +176 -0
  48. package/markdown/HISTORY.md +198 -0
  49. package/markdown/IDB.md +177 -0
  50. package/markdown/IMPORT.md +152 -0
  51. package/markdown/INSPECT.md +122 -0
  52. package/markdown/LOGGER.md +153 -0
  53. package/markdown/MEMORY-ATTACHMENT.md +95 -0
  54. package/markdown/MEMORY.md +161 -0
  55. package/markdown/OBSERVER.md +208 -0
  56. package/markdown/PLATFORM.md +277 -0
  57. package/markdown/REDUX.md +54 -0
  58. package/markdown/SCHEMA.md +175 -0
  59. package/markdown/SESSION.md +164 -0
  60. package/markdown/SQLITE.md +189 -0
  61. package/markdown/STATE.md +159 -0
  62. package/markdown/STORE.md +170 -0
  63. package/markdown/SYNC.md +318 -0
  64. package/markdown/TYPED.md +164 -0
  65. package/markdown/USEOBSERVER.md +256 -0
  66. package/modules/redux.cjs +701 -177
  67. package/modules/redux.cjs.map +1 -1
  68. package/modules/redux.js +701 -177
  69. package/modules/redux.js.map +1 -1
  70. package/package.json +26 -4
  71. package/types/broadcast.d.ts +61 -0
  72. package/types/computed.d.ts +96 -0
  73. package/types/encryption.d.ts +129 -0
  74. package/types/env.d.ts +19 -9
  75. package/types/exports.d.ts +29 -0
  76. package/types/history.d.ts +13 -1
  77. package/types/memorio.d.ts +25 -6
  78. package/types/mutation.d.ts +75 -0
  79. package/types/security.d.ts +67 -0
  80. package/types/session.d.ts +23 -5
  81. package/types/store.d.ts +19 -3
  82. package/vsix/memorio.vsix +0 -0
package/index.cjs CHANGED
@@ -8,6 +8,10 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
8
8
  var __esm = (fn, res) => function __init() {
9
9
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
10
  };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
11
15
 
12
16
  // node_modules/tsup/assets/cjs_shims.js
13
17
  var init_cjs_shims = __esm({
@@ -20,8 +24,11 @@ exports.DEV = void 0; exports.PROD = void 0;
20
24
  var init_env = __esm({
21
25
  "core/env.ts"() {
22
26
  init_cjs_shims();
23
- exports.DEV = typeof process !== "undefined" ? false : true;
27
+ exports.DEV = false ;
24
28
  exports.PROD = !exports.DEV;
29
+ if (typeof globalThis !== "undefined") {
30
+ globalThis["__DEV__"] = exports.DEV;
31
+ }
25
32
  }
26
33
  });
27
34
 
@@ -205,6 +212,241 @@ var init_message = __esm({
205
212
  }
206
213
  });
207
214
 
215
+ // functions/encryption/index.ts
216
+ function _hasWebCrypto() {
217
+ const g3 = globalThis;
218
+ return typeof g3.crypto !== "undefined" && typeof g3.crypto.subtle !== "undefined" && typeof g3.crypto.subtle.encrypt === "function";
219
+ }
220
+ function _b64encode(buf) {
221
+ const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
222
+ if (typeof btoa === "function") {
223
+ let binary = "";
224
+ for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
225
+ return btoa(binary);
226
+ }
227
+ if (typeof Buffer !== "undefined") {
228
+ return Buffer.from(bytes).toString("base64");
229
+ }
230
+ return "";
231
+ }
232
+ function _b64decode(b64) {
233
+ if (typeof Buffer !== "undefined") {
234
+ return new Uint8Array(Buffer.from(b64, "base64"));
235
+ }
236
+ if (typeof atob === "function") {
237
+ const binary = atob(b64);
238
+ const out = new Uint8Array(binary.length);
239
+ for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
240
+ return out;
241
+ }
242
+ throw new Error("memorio encryption: no base64 decoder available");
243
+ }
244
+ function _isEncrypted(value) {
245
+ return typeof value === "object" && value !== null && value.__memorio_encrypted === true && typeof value.alg === "string";
246
+ }
247
+ var AES_GCM, PBKDF2_ITERATIONS; exports.encryption = void 0;
248
+ var init_encryption = __esm({
249
+ "functions/encryption/index.ts"() {
250
+ init_cjs_shims();
251
+ init_env();
252
+ init_message();
253
+ __name(_hasWebCrypto, "_hasWebCrypto");
254
+ __name(_b64encode, "_b64encode");
255
+ __name(_b64decode, "_b64decode");
256
+ __name(_isEncrypted, "_isEncrypted");
257
+ AES_GCM = { name: "AES-GCM", length: 256 };
258
+ PBKDF2_ITERATIONS = 6e5;
259
+ exports.encryption = {
260
+ ///
261
+ // Capability detection
262
+ ///
263
+ isAvailable() {
264
+ return _hasWebCrypto();
265
+ },
266
+ ///
267
+ // Derive a CryptoKey from a password using PBKDF2.
268
+ //
269
+ // @param password The password string.
270
+ // @param salt Salt (string or Uint8Array). Defaults to a static value.
271
+ // @param alg 'AES-GCM' (default) or 'AES-CBC'.
272
+ // @returns A Promise<CryptoKey>.
273
+ ///
274
+ async deriveKey(password, salt, alg = "AES-GCM", iterations = PBKDF2_ITERATIONS) {
275
+ if (!_hasWebCrypto()) {
276
+ throw new Error("memorio encryption: Web Crypto API is not available in this environment");
277
+ }
278
+ const enc = new TextEncoder();
279
+ const saltBytes = typeof salt === "string" ? enc.encode(salt) : salt ?? enc.encode("memorio:salt");
280
+ const keyMaterial = await globalThis.crypto.subtle.importKey(
281
+ "raw",
282
+ enc.encode(password),
283
+ { name: "PBKDF2" },
284
+ false,
285
+ ["deriveKey"]
286
+ );
287
+ return globalThis.crypto.subtle.deriveKey(
288
+ { name: "PBKDF2", salt: saltBytes, iterations, hash: "SHA-256" },
289
+ keyMaterial,
290
+ { name: alg, length: 256 },
291
+ false,
292
+ ["encrypt", "decrypt"]
293
+ );
294
+ },
295
+ ///
296
+ // Generate a fresh random CryptoKey (AES-GCM, 256-bit).
297
+ ///
298
+ async generateKey(alg = "AES-GCM") {
299
+ if (!_hasWebCrypto()) {
300
+ throw new Error("memorio encryption: Web Crypto API is not available in this environment");
301
+ }
302
+ return globalThis.crypto.subtle.generateKey(
303
+ { name: alg, length: 256 },
304
+ true,
305
+ ["encrypt", "decrypt"]
306
+ );
307
+ },
308
+ ///
309
+ // Generate a random salt for PBKDF2 key derivation.
310
+ ///
311
+ generateSalt(bytes = 16) {
312
+ const arr = new Uint8Array(bytes);
313
+ globalThis.crypto?.getRandomValues?.(arr);
314
+ return _b64encode(arr);
315
+ },
316
+ ///
317
+ // Export a CryptoKey to portable base64 strings so it can be stored
318
+ // (e.g. in an httpOnly cookie) and re-imported later with importKey().
319
+ //
320
+ // @param cryptoKey A raw CryptoKey (not a password string).
321
+ // @returns { key: string, iv: string } base64-encoded.
322
+ ///
323
+ async exportKey(cryptoKey) {
324
+ if (!_hasWebCrypto()) {
325
+ throw new Error("memorio encryption: Web Crypto API is not available in this environment");
326
+ }
327
+ const exported = await globalThis.crypto.subtle.exportKey("raw", cryptoKey);
328
+ return {
329
+ key: _b64encode(exported),
330
+ iv: ""
331
+ };
332
+ },
333
+ ///
334
+ // Import a CryptoKey from base64 strings produced by exportKey().
335
+ //
336
+ // @param keyData Base64-encoded raw key bytes.
337
+ // @param _ivData Ignored (kept for API compatibility with exportKey return).
338
+ // @returns A Promise<CryptoKey>.
339
+ ///
340
+ async importKey(keyData, _ivData) {
341
+ if (!_hasWebCrypto()) {
342
+ throw new Error("memorio encryption: Web Crypto API is not available in this environment");
343
+ }
344
+ const keyBytes = _b64decode(keyData);
345
+ if (keyBytes.length !== 32) {
346
+ throw new Error(`memorio encryption: AES-256 key must be exactly 32 bytes, got ${keyBytes.length}`);
347
+ }
348
+ return globalThis.crypto.subtle.importKey(
349
+ "raw",
350
+ keyBytes,
351
+ AES_GCM,
352
+ true,
353
+ ["encrypt", "decrypt"]
354
+ );
355
+ },
356
+ ///
357
+ // Encrypt a JavaScript value.
358
+ //
359
+ // @param value The value to encrypt (any JSON-serializable object).
360
+ // @param key A CryptoKey or a password string (password is derived via PBKDF2).
361
+ // @param keyId Optional label, stored in the envelope for key rotation.
362
+ // @returns An EncryptedEnvelope object.
363
+ ///
364
+ async encrypt(value, key, keyId) {
365
+ const cryptoKey = typeof key === "string" ? await this.deriveKey(key, void 0, "AES-GCM") : key;
366
+ const data = new TextEncoder().encode(JSON.stringify(value));
367
+ const iv = new Uint8Array(12);
368
+ globalThis.crypto.getRandomValues(iv);
369
+ const ciphertext = await globalThis.crypto.subtle.encrypt(
370
+ { name: "AES-GCM", iv },
371
+ cryptoKey,
372
+ data
373
+ );
374
+ const envelope = {
375
+ __memorio_encrypted: true,
376
+ v: 1,
377
+ alg: "AES-GCM",
378
+ iv: _b64encode(iv),
379
+ data: _b64encode(ciphertext)
380
+ };
381
+ if (keyId) envelope.keyId = keyId;
382
+ if (exports.DEV) message_default(`encryption: encrypted value (alg=${envelope.alg})`);
383
+ return envelope;
384
+ },
385
+ ///
386
+ // Decrypt an EncryptedEnvelope.
387
+ //
388
+ // @param envelope The envelope object returned by encrypt().
389
+ // @param key A CryptoKey or a password string.
390
+ // @returns The original value (parsed from JSON).
391
+ ///
392
+ async decrypt(envelope, key) {
393
+ if (!_isEncrypted(envelope)) {
394
+ throw new Error("memorio encryption: value is not a valid encrypted envelope");
395
+ }
396
+ const cryptoKey = typeof key === "string" ? await this.deriveKey(key, void 0, "AES-GCM") : key;
397
+ const iv = _b64decode(envelope.iv);
398
+ const data = _b64decode(envelope.data);
399
+ const decrypted = await globalThis.crypto.subtle.decrypt(
400
+ { name: "AES-GCM", iv },
401
+ cryptoKey,
402
+ data
403
+ );
404
+ return JSON.parse(new TextDecoder().decode(new Uint8Array(decrypted)));
405
+ },
406
+ ///
407
+ // Convenience: encrypt with a password (derives the key internally).
408
+ // Returns a JSON string you can store anywhere.
409
+ ///
410
+ async encryptWithPassword(value, password, salt, keyId) {
411
+ const env = await this.encrypt(value, password, keyId);
412
+ return JSON.stringify(env);
413
+ },
414
+ ///
415
+ // Convenience: decrypt a JSON envelope string with a password.
416
+ ///
417
+ async decryptWithPassword(envelopeJson, password, _salt) {
418
+ const envelope = JSON.parse(envelopeJson);
419
+ return this.decrypt(envelope, password);
420
+ },
421
+ ///
422
+ // Type guard: check whether a value is an encrypted envelope.
423
+ ///
424
+ isEncrypted(value) {
425
+ return _isEncrypted(value);
426
+ },
427
+ ///
428
+ // Configure a default encryption key for auto-encrypt mode.
429
+ // When set on `store` or `session`, all writes are encrypted and all
430
+ // reads attempt decryption automatically.
431
+ ///
432
+ config(opts) {
433
+ if (opts.key !== void 0) this._defaultKey = opts.key;
434
+ if (opts.keyId !== void 0) this._defaultKeyId = opts.keyId;
435
+ return this;
436
+ },
437
+ ///
438
+ // Internal: resolve the configured default key.
439
+ ///
440
+ get _key() {
441
+ return this._defaultKey ?? null;
442
+ },
443
+ get _keyId() {
444
+ return this._defaultKeyId;
445
+ }
446
+ };
447
+ }
448
+ });
449
+
208
450
  // core/platform.ts
209
451
  function generateSessionId() {
210
452
  const anyGlobal = globalThis;
@@ -219,6 +461,9 @@ function generateSessionId() {
219
461
  return `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
220
462
  }
221
463
  function detectPlatform() {
464
+ if (_isBun()) {
465
+ return "bun";
466
+ }
222
467
  const globalAny = globalThis;
223
468
  if (globalAny.Deno && globalAny.Deno.version) {
224
469
  return "deno";
@@ -234,6 +479,13 @@ function detectPlatform() {
234
479
  }
235
480
  return "unknown";
236
481
  }
482
+ function _isBun() {
483
+ const globalAny = globalThis;
484
+ return typeof globalAny.Bun !== "undefined" && typeof globalAny.Bun.version === "string";
485
+ }
486
+ function isBun() {
487
+ return _isBun();
488
+ }
237
489
  function isBrowser() {
238
490
  const platform = detectPlatform();
239
491
  return platform === "browser";
@@ -287,6 +539,9 @@ function hasSqlJs() {
287
539
  }
288
540
  return typeof anyGlobal.window !== "undefined";
289
541
  }
542
+ function hasBunSqlite() {
543
+ return _isBun();
544
+ }
290
545
  function hasDispatchEvent() {
291
546
  return typeof globalThis.dispatchEvent === "function";
292
547
  }
@@ -299,6 +554,7 @@ function getCapabilities() {
299
554
  hasLocalStorage: getLocalStorage() !== null,
300
555
  hasIndexedDB: hasIndexedDB(),
301
556
  hasSqlJs: hasSqlJs(),
557
+ hasBunSqlite: hasBunSqlite(),
302
558
  hasDispatchEvent: hasDispatchEvent(),
303
559
  hasNavigator: typeof navigator !== "undefined",
304
560
  hasProcess: typeof process !== "undefined",
@@ -358,8 +614,9 @@ function initializePlatform() {
358
614
  };
359
615
  }
360
616
  }
361
- function createContext(name) {
617
+ function createContext(name, opts) {
362
618
  const contextId = name || `context_${generateSessionId()}`;
619
+ const encKey = opts?.encryptionKey;
363
620
  setCurrentContext(contextId);
364
621
  const contextStorage = {
365
622
  state: {},
@@ -368,10 +625,31 @@ function createContext(name) {
368
625
  cache: /* @__PURE__ */ new Map()
369
626
  };
370
627
  _contexts.set(contextId, contextStorage);
628
+ function _isEncrypted2(value) {
629
+ return exports.encryption.isEncrypted(value);
630
+ }
631
+ __name(_isEncrypted2, "_isEncrypted");
371
632
  return {
372
633
  id: contextId,
373
634
  state: contextStorage.state,
374
- store: {
635
+ store: encKey ? {
636
+ get: /* @__PURE__ */ __name(async (key) => {
637
+ const data = contextStorage.store.get(key);
638
+ if (!data) return null;
639
+ const parsed = JSON.parse(data);
640
+ if (_isEncrypted2(parsed)) return exports.encryption.decrypt(parsed, encKey);
641
+ return parsed;
642
+ }, "get"),
643
+ set: /* @__PURE__ */ __name(async (key, value) => {
644
+ const env = await exports.encryption.encrypt(value, encKey);
645
+ contextStorage.store.set(key, JSON.stringify(env));
646
+ }, "set"),
647
+ remove: /* @__PURE__ */ __name((key) => contextStorage.store.delete(key), "remove"),
648
+ removeAll: /* @__PURE__ */ __name(() => contextStorage.store.clear(), "removeAll"),
649
+ clearAll: /* @__PURE__ */ __name(() => contextStorage.store.clear(), "clearAll"),
650
+ size: /* @__PURE__ */ __name(() => contextStorage.store.size, "size"),
651
+ isPersistent: false
652
+ } : {
375
653
  get: /* @__PURE__ */ __name((key) => {
376
654
  const data = contextStorage.store.get(key);
377
655
  return data ? JSON.parse(data) : null;
@@ -385,7 +663,24 @@ function createContext(name) {
385
663
  size: /* @__PURE__ */ __name(() => contextStorage.store.size, "size"),
386
664
  isPersistent: false
387
665
  },
388
- session: {
666
+ session: encKey ? {
667
+ get: /* @__PURE__ */ __name(async (key) => {
668
+ const data = contextStorage.session.get(key);
669
+ if (!data) return null;
670
+ const parsed = JSON.parse(data);
671
+ if (_isEncrypted2(parsed)) return exports.encryption.decrypt(parsed, encKey);
672
+ return parsed;
673
+ }, "get"),
674
+ set: /* @__PURE__ */ __name(async (key, value) => {
675
+ const env = await exports.encryption.encrypt(value, encKey);
676
+ contextStorage.session.set(key, JSON.stringify(env));
677
+ }, "set"),
678
+ remove: /* @__PURE__ */ __name((key) => contextStorage.session.delete(key), "remove"),
679
+ removeAll: /* @__PURE__ */ __name(() => contextStorage.session.clear(), "removeAll"),
680
+ clearAll: /* @__PURE__ */ __name(() => contextStorage.session.clear(), "clearAll"),
681
+ size: /* @__PURE__ */ __name(() => contextStorage.session.size, "size"),
682
+ isPersistent: false
683
+ } : {
389
684
  get: /* @__PURE__ */ __name((key) => {
390
685
  const data = contextStorage.session.get(key);
391
686
  return data ? JSON.parse(data) : null;
@@ -405,7 +700,8 @@ function createContext(name) {
405
700
  remove: /* @__PURE__ */ __name((key) => contextStorage.cache.delete(key), "remove"),
406
701
  removeAll: /* @__PURE__ */ __name(() => contextStorage.cache.clear(), "removeAll"),
407
702
  clear: /* @__PURE__ */ __name(() => contextStorage.cache.clear(), "clear")
408
- }
703
+ },
704
+ encryptionKey: encKey
409
705
  };
410
706
  }
411
707
  function listContexts() {
@@ -422,8 +718,11 @@ var init_platform = __esm({
422
718
  "core/platform.ts"() {
423
719
  init_cjs_shims();
424
720
  init_internal();
721
+ init_encryption();
425
722
  __name(generateSessionId, "generateSessionId");
426
723
  __name(detectPlatform, "detectPlatform");
724
+ __name(_isBun, "_isBun");
725
+ __name(isBun, "isBun");
427
726
  __name(isBrowser, "isBrowser");
428
727
  __name(isNode, "isNode");
429
728
  __name(isDeno, "isDeno");
@@ -432,6 +731,7 @@ var init_platform = __esm({
432
731
  __name(getLocalStorage, "getLocalStorage");
433
732
  __name(hasIndexedDB, "hasIndexedDB");
434
733
  __name(hasSqlJs, "hasSqlJs");
734
+ __name(hasBunSqlite, "hasBunSqlite");
435
735
  __name(hasDispatchEvent, "hasDispatchEvent");
436
736
  __name(getCapabilities, "getCapabilities");
437
737
  _eventListenerStorage = /* @__PURE__ */ new Map();
@@ -457,6 +757,9 @@ function _getFallbackStorage() {
457
757
  }
458
758
  return _fallbackStorageByContext.get(key);
459
759
  }
760
+ function _isEncryptedEnvelope(value) {
761
+ return exports.encryption.isEncrypted(value);
762
+ }
460
763
  function _getPrefix() {
461
764
  const contextName = exports.internal.currentContext || "";
462
765
  return contextName ? `${contextName}-` : `memorio_store_`;
@@ -493,17 +796,23 @@ function _remove(prefixedName) {
493
796
  }
494
797
  return false;
495
798
  }
496
- var _localStorage, _fallbackStorageByContext, _hasStorage, STORE_INSTANCE_KEY; exports.store = void 0;
799
+ var _localStorage, _fallbackStorageByContext, _hasStorage, _encryptionKey, _onError, _maxObjectSize, _maxTotalSize, STORE_INSTANCE_KEY; exports.store = void 0;
497
800
  var init_store = __esm({
498
801
  "functions/store/index.ts"() {
499
802
  init_cjs_shims();
500
803
  init_platform();
501
804
  init_internal();
502
805
  init_message();
806
+ init_encryption();
503
807
  _localStorage = getLocalStorage();
504
808
  _fallbackStorageByContext = /* @__PURE__ */ new Map();
505
809
  __name(_getFallbackStorage, "_getFallbackStorage");
506
810
  _hasStorage = _localStorage !== null;
811
+ _encryptionKey = null;
812
+ _onError = null;
813
+ _maxObjectSize = 0;
814
+ _maxTotalSize = 0;
815
+ __name(_isEncryptedEnvelope, "_isEncryptedEnvelope");
507
816
  __name(_getPrefix, "_getPrefix");
508
817
  __name(_prefixKey, "_prefixKey");
509
818
  __name(_read, "_read");
@@ -520,16 +829,24 @@ var init_store = __esm({
520
829
  /**
521
830
  * Gets a value from storage.
522
831
  * @param name The key to retrieve.
523
- * @returns The parsed value or null if not found.
832
+ * @param opts Optional { decrypt: key } to decrypt an encrypted envelope.
833
+ * When no key is passed, encrypted envelopes are returned as-is.
834
+ * If a default key was configured via store.config(), it is used automatically.
835
+ * @returns The parsed value, a Promise<parsed value> when decrypting, or null if not found.
524
836
  */
525
837
  get: {
526
- value: /* @__PURE__ */ __name((name) => {
838
+ value: /* @__PURE__ */ __name((name, opts) => {
527
839
  if (!name) {
528
840
  console.warn("[memorio store] store.get() called with empty or null key - returning null");
529
841
  return null;
530
842
  }
531
843
  try {
532
- return _read(_prefixKey(name));
844
+ const raw = _read(_prefixKey(name));
845
+ const key = opts?.decrypt ?? _encryptionKey;
846
+ if (key && _isEncryptedEnvelope(raw)) {
847
+ return exports.encryption.decrypt(raw, key);
848
+ }
849
+ return raw;
533
850
  } catch (err) {
534
851
  exports.message(`Error parsing store item '${name}': ${err}`);
535
852
  }
@@ -554,10 +871,13 @@ var init_store = __esm({
554
871
  * Sets a value in storage.
555
872
  * @param name The key to set.
556
873
  * @param value The value to store (objects, arrays, primitives).
557
- * @returns true if written, false if the key was rejected.
874
+ * @param opts Optional { encrypt: key } to encrypt the value before storage.
875
+ * If a default key was configured via store.config(), it is used automatically.
876
+ * When encryption is used, returns a Promise<boolean>.
877
+ * @returns true if written, false if rejected or error.
558
878
  */
559
879
  set: {
560
- value: /* @__PURE__ */ __name((name, value) => {
880
+ value: /* @__PURE__ */ __name((name, value, opts) => {
561
881
  if (!name) {
562
882
  console.warn("[memorio store] store.set() called with empty or null key - write aborted");
563
883
  return false;
@@ -569,15 +889,66 @@ var init_store = __esm({
569
889
  exports.message("Storing functions is not secure and is blocked for safety.");
570
890
  return false;
571
891
  }
892
+ if (_maxObjectSize > 0 || _maxTotalSize > 0) {
893
+ let serializedSize = 0;
894
+ try {
895
+ serializedSize = new TextEncoder().encode(JSON.stringify(value)).length;
896
+ } catch {
897
+ serializedSize = 0;
898
+ }
899
+ if (_maxObjectSize > 0 && serializedSize > _maxObjectSize) {
900
+ const err = new Error(`Object size (${serializedSize} bytes) exceeds maxObjectSize (${_maxObjectSize} bytes)`);
901
+ _onError?.(err, { operation: "set" });
902
+ return false;
903
+ }
904
+ if (_maxTotalSize > 0) {
905
+ const currentTotal = exports.store.size() * 1024;
906
+ const existingItemSize = _hasStorage ? _localStorage.getItem(prefixedName)?.length ?? 0 : _getFallbackStorage().get(prefixedName)?.length ?? 0;
907
+ const projected = currentTotal * 1024 - existingItemSize + serializedSize;
908
+ if (projected > _maxTotalSize) {
909
+ const err = new Error(`Total store size (${projected} bytes) exceeds maxTotalSize (${_maxTotalSize} bytes)`);
910
+ _onError?.(err, { operation: "set" });
911
+ return false;
912
+ }
913
+ }
914
+ }
915
+ const key = opts?.encrypt ?? _encryptionKey;
916
+ if (key) {
917
+ return exports.encryption.encrypt(value, key).then((env) => {
918
+ _write(prefixedName, env);
919
+ return true;
920
+ }).catch((err) => {
921
+ exports.message(`Error encrypting store item '${name}': ${err}`);
922
+ _onError?.(err, { operation: "set" });
923
+ return false;
924
+ });
925
+ }
572
926
  try {
573
927
  _write(prefixedName, value);
574
928
  } catch (err) {
575
929
  exports.message(`Error setting store item '${name}': ${err}`);
930
+ _onError?.(err, { operation: "set" });
576
931
  return false;
577
932
  }
578
933
  return true;
579
934
  }, "value")
580
935
  },
936
+ /**
937
+ * Configure store-wide behavior.
938
+ * @param opts Optional { encryptionKey } to enable automatic encryption
939
+ * for all set/get operations. When set, values are encrypted
940
+ * on write and decrypted on read (if the value is an envelope).
941
+ * @returns The store instance for chaining.
942
+ */
943
+ config: {
944
+ value: /* @__PURE__ */ __name((opts) => {
945
+ if (opts.encryptionKey !== void 0) _encryptionKey = opts.encryptionKey;
946
+ if (opts.onError !== void 0) _onError = opts.onError;
947
+ if (opts.maxObjectSize !== void 0) _maxObjectSize = opts.maxObjectSize;
948
+ if (opts.maxTotalSize !== void 0) _maxTotalSize = opts.maxTotalSize;
949
+ return exports.store;
950
+ }, "value")
951
+ },
581
952
  /**
582
953
  * Removes a value from storage.
583
954
  * @param name The key to remove.
@@ -948,8 +1319,8 @@ var init_table_size = __esm({
948
1319
  if (!db.objectStoreNames.contains(table)) return resolve(0);
949
1320
  let size = 0;
950
1321
  let count = 0;
951
- const transaction = db.transaction([table], "readonly");
952
- const store2 = transaction.objectStore(table);
1322
+ const transaction2 = db.transaction([table], "readonly");
1323
+ const store2 = transaction2.objectStore(table);
953
1324
  const request = store2.openCursor();
954
1325
  request.onsuccess = async (event) => {
955
1326
  const cursor = event.target.result;
@@ -993,8 +1364,8 @@ var init_data_delete = __esm({
993
1364
  db.close();
994
1365
  return reject(new Error(`Table ${table} not found`));
995
1366
  }
996
- const transaction = db.transaction(table, "readwrite");
997
- const objectStore = transaction.objectStore(table);
1367
+ const transaction2 = db.transaction(table, "readwrite");
1368
+ const objectStore = transaction2.objectStore(table);
998
1369
  const deleteRequest = objectStore.delete(key);
999
1370
  deleteRequest.onsuccess = () => {
1000
1371
  db.close();
@@ -1018,8 +1389,8 @@ var init_data_delete = __esm({
1018
1389
  db.close();
1019
1390
  return reject(new Error(`Table ${table} not found`));
1020
1391
  }
1021
- const transaction = db.transaction(table, "readwrite");
1022
- const store2 = transaction.objectStore(table);
1392
+ const transaction2 = db.transaction(table, "readwrite");
1393
+ const store2 = transaction2.objectStore(table);
1023
1394
  const clearRequest = store2.clear();
1024
1395
  clearRequest.onsuccess = () => {
1025
1396
  db.close();
@@ -1053,8 +1424,8 @@ var init_data_set = __esm({
1053
1424
  db.close();
1054
1425
  return reject(new Error(`Table ${table} does not exist in ${storeName}`));
1055
1426
  }
1056
- const transaction = db.transaction(table, "readwrite");
1057
- const objectStore = transaction.objectStore(table);
1427
+ const transaction2 = db.transaction(table, "readwrite");
1428
+ const objectStore = transaction2.objectStore(table);
1058
1429
  const putRequest = objectStore.put(value);
1059
1430
  putRequest.onsuccess = () => {
1060
1431
  db.close();
@@ -1090,8 +1461,8 @@ var init_data_get = __esm({
1090
1461
  db.close();
1091
1462
  return reject(new Error(`Table ${table} not found in ${storeName}`));
1092
1463
  }
1093
- const transaction = db.transaction(table, "readonly");
1094
- const store2 = transaction.objectStore(table);
1464
+ const transaction2 = db.transaction(table, "readonly");
1465
+ const store2 = transaction2.objectStore(table);
1095
1466
  const getRequest = store2.get(key);
1096
1467
  getRequest.onsuccess = () => {
1097
1468
  db.close();
@@ -1163,6 +1534,91 @@ var init_idb = __esm({
1163
1534
  }
1164
1535
  });
1165
1536
 
1537
+ // functions/sqlite/tools/bun-sqlite-adapter.ts
1538
+ var bun_sqlite_adapter_exports = {};
1539
+ __export(bun_sqlite_adapter_exports, {
1540
+ BunSqlJsDatabase: () => BunSqlJsDatabase,
1541
+ createBunSqlJs: () => createBunSqlJs
1542
+ });
1543
+ async function _loadDatabase() {
1544
+ if (!_DatabaseClass) {
1545
+ const mod = await import('bun:sqlite');
1546
+ _DatabaseClass = mod.Database;
1547
+ }
1548
+ return _DatabaseClass;
1549
+ }
1550
+ async function createBunSqlJs() {
1551
+ await _loadDatabase();
1552
+ return {
1553
+ Database: BunSqlJsDatabase,
1554
+ version: "bun:sqlite"
1555
+ };
1556
+ }
1557
+ var _DatabaseClass, BunSqlJsDatabase;
1558
+ var init_bun_sqlite_adapter = __esm({
1559
+ "functions/sqlite/tools/bun-sqlite-adapter.ts"() {
1560
+ init_cjs_shims();
1561
+ _DatabaseClass = null;
1562
+ __name(_loadDatabase, "_loadDatabase");
1563
+ BunSqlJsDatabase = class {
1564
+ static {
1565
+ __name(this, "BunSqlJsDatabase");
1566
+ }
1567
+ _db;
1568
+ _lastRunChanges = 0;
1569
+ constructor(data) {
1570
+ this._lastRunChanges = 0;
1571
+ if (typeof data === "string") {
1572
+ this._db = new _DatabaseClass(data);
1573
+ } else {
1574
+ this._db = new _DatabaseClass(":memory:");
1575
+ }
1576
+ }
1577
+ run(sql, params = []) {
1578
+ const info = this._db.run(sql, ...params);
1579
+ this._lastRunChanges = info?.changes ?? 0;
1580
+ return info;
1581
+ }
1582
+ getRowsModified() {
1583
+ return this._lastRunChanges;
1584
+ }
1585
+ prepare(sql, params = []) {
1586
+ const rows = params.length > 0 ? this._db.query(sql).all(...params) : this._db.query(sql).all();
1587
+ return {
1588
+ _rows: rows,
1589
+ _idx: -1,
1590
+ step() {
1591
+ this._idx++;
1592
+ return this._idx < this._rows.length;
1593
+ },
1594
+ getAsObject() {
1595
+ return this._rows[this._idx] || {};
1596
+ },
1597
+ get() {
1598
+ return this._rows[this._idx] ? Object.values(this._rows[this._idx]) : [];
1599
+ },
1600
+ free() {
1601
+ this._rows = null;
1602
+ }
1603
+ };
1604
+ }
1605
+ export() {
1606
+ throw new Error("Bun:sqlite does not support in-memory export - use store/session for persistence, or use the sql.js backend for export/import operations");
1607
+ }
1608
+ close() {
1609
+ try {
1610
+ this._db.close();
1611
+ } catch {
1612
+ }
1613
+ }
1614
+ get version() {
1615
+ return "bun:sqlite";
1616
+ }
1617
+ };
1618
+ __name(createBunSqlJs, "createBunSqlJs");
1619
+ }
1620
+ });
1621
+
1166
1622
  // functions/sqlite/tools/db.support.ts
1167
1623
  var db_support_exports2 = {};
1168
1624
  function _inDocument() {
@@ -1223,11 +1679,18 @@ var init_db_support2 = __esm({
1223
1679
  return g3.initSqlJs || g3;
1224
1680
  }, "_loadSqlJsFromCdn");
1225
1681
  exports.sqlite.db.support = () => {
1226
- return hasSqlJs();
1682
+ return hasSqlJs() || hasBunSqlite();
1227
1683
  };
1228
1684
  exports.sqlite.db.getSQL = async () => {
1229
1685
  if (_SQL) return _SQL;
1230
1686
  if (_loading) return _loading;
1687
+ if (hasBunSqlite()) {
1688
+ const { createBunSqlJs: createBunSqlJs2 } = await Promise.resolve().then(() => (init_bun_sqlite_adapter(), bun_sqlite_adapter_exports));
1689
+ _SQL = await createBunSqlJs2();
1690
+ globalThis.sqliteVersion = _SQL.version;
1691
+ message_default("Memorio SQLite: bun:sqlite engine loaded");
1692
+ return _SQL;
1693
+ }
1231
1694
  const g3 = globalThis;
1232
1695
  const cfg = g3.sqliteConfig || {};
1233
1696
  const p = (async () => {
@@ -1254,7 +1717,7 @@ var init_db_support2 = __esm({
1254
1717
  } catch (_) {
1255
1718
  }
1256
1719
  try {
1257
- exports.sqlite._warning = "Memorio SQLite: sql.js could not be loaded. Install sql.js (npm i sql.js) and pass a loader via sqlite.config({ loader: () => <your sql.js import>() }).";
1720
+ exports.sqlite._warning = "Memorio SQLite: sql.js could not be loaded. Install sql.js (npm i sql.js) and pass a loader via sqlite.config({ loader: () => import(<your sql.js import>()) }).";
1258
1721
  } catch (_) {
1259
1722
  }
1260
1723
  console.warn("Memorio SQLite: failed to load sql.js", err);
@@ -1277,7 +1740,7 @@ function _ns() {
1277
1740
  function _key(name) {
1278
1741
  return `memorio:sqlite:db:${_ns()}:${name}`;
1279
1742
  }
1280
- function _b64encode(buf) {
1743
+ function _b64encode2(buf) {
1281
1744
  const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);
1282
1745
  let binary = "";
1283
1746
  const len = bytes.byteLength;
@@ -1285,7 +1748,7 @@ function _b64encode(buf) {
1285
1748
  if (typeof btoa === "function") return btoa(binary);
1286
1749
  return typeof Buffer !== "undefined" ? Buffer.from(bytes).toString("base64") : "";
1287
1750
  }
1288
- function _b64decode(b64) {
1751
+ function _b64decode2(b64) {
1289
1752
  if (typeof Buffer !== "undefined") {
1290
1753
  return new Uint8Array(Buffer.from(b64, "base64"));
1291
1754
  }
@@ -1307,7 +1770,7 @@ function saveSnapshot(name) {
1307
1770
  }
1308
1771
  try {
1309
1772
  const blob = db.export();
1310
- exports.store.set(_key(name), _b64encode(blob));
1773
+ exports.store.set(_key(name), _b64encode2(blob));
1311
1774
  message_default(`Memorio SQLite: persisted '${name}' to store`);
1312
1775
  resolve(true);
1313
1776
  } catch (err) {
@@ -1320,7 +1783,7 @@ function loadSnapshot(name) {
1320
1783
  const b64 = exports.store.get(_key(name));
1321
1784
  if (!b64) return null;
1322
1785
  try {
1323
- return _b64decode(b64);
1786
+ return _b64decode2(b64);
1324
1787
  } catch {
1325
1788
  return null;
1326
1789
  }
@@ -1355,8 +1818,8 @@ var init_persist = __esm({
1355
1818
  _exportTimers = {};
1356
1819
  __name(_ns, "_ns");
1357
1820
  __name(_key, "_key");
1358
- __name(_b64encode, "_b64encode");
1359
- __name(_b64decode, "_b64decode");
1821
+ __name(_b64encode2, "_b64encode");
1822
+ __name(_b64decode2, "_b64decode");
1360
1823
  __name(saveSnapshot, "saveSnapshot");
1361
1824
  __name(loadSnapshot, "loadSnapshot");
1362
1825
  __name(removeSnapshot, "removeSnapshot");
@@ -1561,7 +2024,14 @@ var init_db_export = __esm({
1561
2024
  init_sqlite();
1562
2025
  exports.sqlite.db.export = async (name = "memorio") => {
1563
2026
  const db = exports.sqlite.db.get(name);
1564
- return db.export();
2027
+ try {
2028
+ return db.export();
2029
+ } catch (err) {
2030
+ if (db && db.version === "bun:sqlite") {
2031
+ throw new Error(`memorio sqlite: export is not supported under Bun's native sqlite. Use \`store\` or \`session\` for persistence instead. If you need a binary dump, run this code under the browser/sql.js backend.`);
2032
+ }
2033
+ throw err;
2034
+ }
1565
2035
  };
1566
2036
  }
1567
2037
  });
@@ -1645,13 +2115,14 @@ var init_data_get2 = __esm({
1645
2115
  });
1646
2116
 
1647
2117
  // functions/sqlite/index.ts
1648
- var _hasSqlJs; exports.sqlite = void 0;
2118
+ var _hasSqlJs, _hasBunSqlite; exports.sqlite = void 0;
1649
2119
  var init_sqlite = __esm({
1650
2120
  "functions/sqlite/index.ts"() {
1651
2121
  init_cjs_shims();
1652
2122
  init_platform();
1653
2123
  init_env();
1654
2124
  _hasSqlJs = hasSqlJs();
2125
+ _hasBunSqlite = hasBunSqlite();
1655
2126
  exports.sqlite = {
1656
2127
  db: {},
1657
2128
  query: {},
@@ -1678,7 +2149,7 @@ var init_sqlite = __esm({
1678
2149
  return g3.sqliteReady;
1679
2150
  }, "get")
1680
2151
  });
1681
- if (_hasSqlJs) {
2152
+ if (_hasSqlJs || _hasBunSqlite) {
1682
2153
  (async () => {
1683
2154
  Object.defineProperty(exports.sqlite, "db", { value: {}, writable: false, configurable: true, enumerable: true });
1684
2155
  Object.defineProperty(exports.sqlite, "query", { value: {}, writable: false, configurable: true, enumerable: true });
@@ -1706,11 +2177,11 @@ var init_sqlite = __esm({
1706
2177
  })();
1707
2178
  } else {
1708
2179
  exports.sqlite._disabled = true;
1709
- exports.sqlite._warning = 'SQLite (sql.js) is not available in this environment. It requires a browser with WebAssembly support. Install the optional "sql.js" package to enable it.';
2180
+ exports.sqlite._warning = 'SQLite is not available in this environment. It requires a browser with WebAssembly (sql.js) or the Bun runtime (bun:sqlite). Install the optional "sql.js" package to enable it in browsers.';
1710
2181
  if (exports.DEV) {
1711
2182
  globalThis.sqliteDisabled = true;
1712
2183
  globalThis.sqliteWarning = exports.sqlite._warning;
1713
- console.warn("Memorio SQLite: sql.js is not available in this environment (requires browser + WebAssembly). Use store or session for persistence.");
2184
+ console.warn("Memorio SQLite: no engine available in this environment (requires browser + WebAssembly, or Bun runtime with bun:sqlite). Use store or session for persistence.");
1714
2185
  }
1715
2186
  }
1716
2187
  }
@@ -1753,9 +2224,25 @@ var dispatch = {
1753
2224
  const wrapped = /* @__PURE__ */ __name((e) => {
1754
2225
  const target = e;
1755
2226
  if (globalThis.queueMicrotask) {
1756
- globalThis.queueMicrotask(() => cb(target));
2227
+ globalThis.queueMicrotask(() => {
2228
+ try {
2229
+ cb(target);
2230
+ } catch (err) {
2231
+ if (typeof console !== "undefined") {
2232
+ console.error("[memorio dispatch] observer error:", err);
2233
+ }
2234
+ }
2235
+ });
1757
2236
  } else {
1758
- Promise.resolve().then(() => cb(target));
2237
+ Promise.resolve().then(() => {
2238
+ try {
2239
+ cb(target);
2240
+ } catch (err) {
2241
+ if (typeof console !== "undefined") {
2242
+ console.error("[memorio dispatch] observer error:", err);
2243
+ }
2244
+ }
2245
+ });
1759
2246
  }
1760
2247
  }, "wrapped");
1761
2248
  globalThis.addEventListener(name, wrapped);
@@ -1891,101 +2378,589 @@ var schema = {
1891
2378
  // functions/state/index.ts
1892
2379
  init_store();
1893
2380
  init_env();
1894
- var TARGET = /* @__PURE__ */ Symbol("memorio.target");
1895
- var wrapperCache = /* @__PURE__ */ new WeakMap();
1896
- var deepRaw = /* @__PURE__ */ __name((val, seen = null) => {
1897
- if (val === null || typeof val !== "object") return val;
1898
- if (val[TARGET] !== void 0) return deepRaw(val[TARGET], seen);
1899
- if (seen) {
1900
- if (seen.has(val)) return val;
1901
- seen.add(val);
2381
+
2382
+ // core/mutation/engine.ts
2383
+ init_cjs_shims();
2384
+ init_internal();
2385
+
2386
+ // core/hlc.ts
2387
+ init_cjs_shims();
2388
+ var NODE_ID_KEY = "__memorio_hlc_node";
2389
+ function getNodeId() {
2390
+ if (typeof globalThis === "undefined") return "node";
2391
+ try {
2392
+ if (typeof sessionStorage !== "undefined" && sessionStorage) {
2393
+ let id = sessionStorage.getItem(NODE_ID_KEY);
2394
+ if (!id) {
2395
+ id = generateNodeId();
2396
+ sessionStorage.setItem(NODE_ID_KEY, id);
2397
+ }
2398
+ return id;
2399
+ }
2400
+ } catch {
1902
2401
  }
1903
- const ctor = val.constructor?.name;
1904
- if (ctor !== "Object" && ctor !== "Array") return val;
1905
- const copy = Array.isArray(val) ? [] : {};
1906
- for (const k of Reflect.ownKeys(val)) {
1907
- if (!Object.prototype.propertyIsEnumerable.call(val, k)) continue;
1908
- copy[k] = deepRaw(val[k], seen);
2402
+ if (!globalThis.__memorioHlcNodeId) {
2403
+ globalThis.__memorioHlcNodeId = generateNodeId();
1909
2404
  }
1910
- return copy;
1911
- }, "deepRaw");
1912
- var objPath = /* @__PURE__ */ __name((prop, object, separator = ".") => {
1913
- return object.concat(prop).join(separator);
1914
- }, "objPath");
1915
- var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
1916
- const event = /* @__PURE__ */ __name((name) => {
1917
- try {
1918
- dispatch.set(name, { detail: { name } });
1919
- } catch (err) {
1920
- if (exports.DEV) console.warn("[memorio state] event dispatch failed:", err);
1921
- }
1922
- return;
1923
- }, "event");
1924
- return new Proxy(
1925
- obj,
1926
- {
1927
- get(target, prop) {
1928
- if (prop === "__path") {
1929
- return tree.length > 0 ? "state." + tree.join(".") : "state";
1930
- }
1931
- if (prop === TARGET) {
1932
- return target;
1933
- }
1934
- if (target[TARGET] !== void 0) {
1935
- return target;
1936
- }
1937
- if (prop === "list") {
1938
- message_default('Some state could be hidden when you use "state.list". Use "state" to see the complete list ');
1939
- return deepRaw(target, /* @__PURE__ */ new WeakSet());
1940
- }
1941
- if (typeof prop === "string") {
1942
- const path = tree.length > 0 ? "state." + tree.concat(prop).join(".") : "state." + prop;
1943
- exports.internal.lastAccessedPath = path;
1944
- if (exports.internal.tracking) {
1945
- exports.internal.trackedPaths.add(path);
1946
- }
1947
- }
1948
- if (prop === "_lastPath") {
1949
- return exports.internal.lastAccessedPath;
1950
- }
1951
- if (prop === "remove") {
1952
- return (key) => {
1953
- delete target[key];
1954
- return true;
1955
- };
1956
- }
1957
- if (prop === "removeAll") {
1958
- return () => {
1959
- try {
1960
- for (const key in target) {
1961
- if (typeof target[key] !== "function" && !["list", "remove", "removeAll", "lock", "unlock"].includes(key)) {
1962
- delete target[key];
1963
- }
1964
- }
1965
- } catch (error) {
1966
- console.error(error);
1967
- }
1968
- return;
1969
- };
1970
- }
1971
- if (Object.isFrozen(target[prop])) return target[prop];
1972
- if (prop === "lock" || prop === "unlock") {
1973
- const value = Reflect.get(target, prop);
1974
- if (value) return value;
1975
- }
1976
- try {
1977
- const value = Reflect.get(target, prop);
1978
- if (value && typeof value === "object" && ["Array", "Object"].includes(value.constructor.name)) {
1979
- let wrapper = wrapperCache.get(value);
1980
- if (!wrapper) {
1981
- wrapper = buildProxy(value, callback, tree.concat(prop));
1982
- wrapperCache.set(value, wrapper);
1983
- }
1984
- return wrapper;
1985
- }
1986
- return value;
1987
- } catch (error) {
1988
- console.error("Error: ", error);
2405
+ return globalThis.__memorioHlcNodeId;
2406
+ }
2407
+ __name(getNodeId, "getNodeId");
2408
+ function generateNodeId() {
2409
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
2410
+ return crypto.randomUUID().slice(0, 8);
2411
+ }
2412
+ return Math.random().toString(36).slice(2, 10);
2413
+ }
2414
+ __name(generateNodeId, "generateNodeId");
2415
+ var HLC_KEY = "__memorio_hlc_local";
2416
+ var local = globalThis[HLC_KEY] || {
2417
+ physical: 0,
2418
+ logical: 0,
2419
+ node: getNodeId()
2420
+ };
2421
+ if (!globalThis[HLC_KEY]) {
2422
+ globalThis[HLC_KEY] = local;
2423
+ }
2424
+ function tick(_incoming) {
2425
+ const now2 = Date.now();
2426
+ const base = local.physical;
2427
+ let physical;
2428
+ let logical;
2429
+ if (now2 > base) {
2430
+ physical = now2;
2431
+ logical = 0;
2432
+ } else if (now2 < base) {
2433
+ physical = base;
2434
+ logical = local.logical + 1;
2435
+ } else {
2436
+ physical = base;
2437
+ logical = local.logical + 1;
2438
+ }
2439
+ local.physical = physical;
2440
+ local.logical = logical;
2441
+ return { physical, logical, node: local.node };
2442
+ }
2443
+ __name(tick, "tick");
2444
+ function receive(remote) {
2445
+ const now2 = Date.now();
2446
+ if (remote.physical > local.physical) {
2447
+ local.physical = remote.physical > now2 ? remote.physical : now2;
2448
+ local.logical = 1;
2449
+ } else if (remote.physical === local.physical) {
2450
+ local.logical = Math.max(local.logical, remote.logical) + 1;
2451
+ }
2452
+ local.node = getNodeId();
2453
+ return { ...local };
2454
+ }
2455
+ __name(receive, "receive");
2456
+ function compare(a, b) {
2457
+ if (a.physical !== b.physical) {
2458
+ return a.physical < b.physical ? -1 : 1;
2459
+ }
2460
+ if (a.logical !== b.logical) {
2461
+ return a.logical < b.logical ? -1 : 1;
2462
+ }
2463
+ if (a.node !== b.node) {
2464
+ return a.node < b.node ? -1 : 1;
2465
+ }
2466
+ return 0;
2467
+ }
2468
+ __name(compare, "compare");
2469
+ function happenedBefore(a, b) {
2470
+ return compare(a, b) < 0;
2471
+ }
2472
+ __name(happenedBefore, "happenedBefore");
2473
+ function serialize(hlc2) {
2474
+ return `hlc:${hlc2.physical}:${hlc2.logical}:${hlc2.node}`;
2475
+ }
2476
+ __name(serialize, "serialize");
2477
+ function parse(serialized) {
2478
+ if (!serialized.startsWith("hlc:")) return null;
2479
+ const parts = serialized.split(":");
2480
+ if (parts.length !== 4) return null;
2481
+ const physical = parseInt(parts[1], 10);
2482
+ const logical = parseInt(parts[2], 10);
2483
+ const node = parts[3];
2484
+ if (isNaN(physical) || isNaN(logical)) return null;
2485
+ return { physical, logical, node };
2486
+ }
2487
+ __name(parse, "parse");
2488
+ var hlc = {
2489
+ tick,
2490
+ receive,
2491
+ compare,
2492
+ happenedBefore,
2493
+ serialize,
2494
+ parse,
2495
+ getNodeId
2496
+ };
2497
+
2498
+ // core/mutation/id.ts
2499
+ init_cjs_shims();
2500
+ function generateMutationId() {
2501
+ const now2 = hlc.tick();
2502
+ return "m_" + encodeHLC(now2);
2503
+ }
2504
+ __name(generateMutationId, "generateMutationId");
2505
+ function generateTransactionId() {
2506
+ const now2 = hlc.tick();
2507
+ return "tx_" + encodeHLC(now2);
2508
+ }
2509
+ __name(generateTransactionId, "generateTransactionId");
2510
+ function generateCommitId() {
2511
+ const now2 = hlc.tick();
2512
+ return "c_" + encodeHLC(now2);
2513
+ }
2514
+ __name(generateCommitId, "generateCommitId");
2515
+ function encodeHLC(hlcValue) {
2516
+ const timePart = hlcValue.physical.toString(36);
2517
+ const logicalPart = hlcValue.logical.toString(36).padStart(2, "0");
2518
+ const nodePart = hlcValue.node.slice(0, 4);
2519
+ return `${timePart}${logicalPart}${nodePart}`;
2520
+ }
2521
+ __name(encodeHLC, "encodeHLC");
2522
+
2523
+ // core/mutation/patch.ts
2524
+ init_cjs_shims();
2525
+ function mutationToPatch(mutation) {
2526
+ if (mutation.before === mutation.after) return null;
2527
+ const op = mutationToPatchOp(mutation.operation, mutation.before, mutation.after);
2528
+ if (!op) return null;
2529
+ const patch = { op, path: mutation.path };
2530
+ if (op === "add" || op === "replace") {
2531
+ patch.value = mutation.after;
2532
+ }
2533
+ if (op === "replace") {
2534
+ patch.oldValue = mutation.before;
2535
+ }
2536
+ if (op === "remove") {
2537
+ patch.oldValue = mutation.before;
2538
+ }
2539
+ return patch;
2540
+ }
2541
+ __name(mutationToPatch, "mutationToPatch");
2542
+ function mutationToPatchOp(operation, _before, _after) {
2543
+ switch (operation) {
2544
+ case "set":
2545
+ if (_before === void 0) return "add";
2546
+ return "replace";
2547
+ case "delete":
2548
+ return "remove";
2549
+ case "insert":
2550
+ return "add";
2551
+ case "remove":
2552
+ return "remove";
2553
+ case "replace":
2554
+ return "replace";
2555
+ case "length":
2556
+ return "replace";
2557
+ default:
2558
+ return null;
2559
+ }
2560
+ }
2561
+ __name(mutationToPatchOp, "mutationToPatchOp");
2562
+ function diffToPatch(path, before2, after2) {
2563
+ if (before2 === after2) return null;
2564
+ if (after2 === void 0) {
2565
+ return { op: "remove", path, oldValue: before2 };
2566
+ }
2567
+ if (before2 === void 0) {
2568
+ return { op: "add", path, value: after2 };
2569
+ }
2570
+ return { op: "replace", path, value: after2, oldValue: before2 };
2571
+ }
2572
+ __name(diffToPatch, "diffToPatch");
2573
+ function canMerge(patch1, patch2) {
2574
+ return patch1.path === patch2.path && patch1.op === patch2.op;
2575
+ }
2576
+ __name(canMerge, "canMerge");
2577
+ function mergePatches(patch1, patch2) {
2578
+ const op = patch1.op === "remove" && patch2.op === "remove" ? "remove" : "replace";
2579
+ return {
2580
+ op,
2581
+ path: patch1.path,
2582
+ value: patch2.value ?? patch1.value,
2583
+ oldValue: patch1.oldValue
2584
+ };
2585
+ }
2586
+ __name(mergePatches, "mergePatches");
2587
+
2588
+ // core/mutation/transaction.ts
2589
+ init_cjs_shims();
2590
+ init_internal();
2591
+ var TX_REGISTRY_KEY = "__memorio_transaction_registry__";
2592
+ var registry = globalThis[TX_REGISTRY_KEY] || /* @__PURE__ */ new Map();
2593
+ if (!globalThis[TX_REGISTRY_KEY]) {
2594
+ globalThis[TX_REGISTRY_KEY] = registry;
2595
+ }
2596
+ var TX_STACK_KEY = "__memorio_transaction_stack__";
2597
+ var txStack = globalThis[TX_STACK_KEY] || [];
2598
+ if (!globalThis[TX_STACK_KEY]) {
2599
+ globalThis[TX_STACK_KEY] = txStack;
2600
+ }
2601
+ function getActiveTxId() {
2602
+ return txStack.length > 0 ? txStack[txStack.length - 1] : null;
2603
+ }
2604
+ __name(getActiveTxId, "getActiveTxId");
2605
+ function setActiveTx(id) {
2606
+ if (id === null) {
2607
+ txStack.pop();
2608
+ } else {
2609
+ txStack.push(id);
2610
+ }
2611
+ }
2612
+ __name(setActiveTx, "setActiveTx");
2613
+ function beginTransaction(source, message2, metadata) {
2614
+ const id = generateTransactionId();
2615
+ const ctx = {
2616
+ id,
2617
+ startedAt: hlc.serialize(hlc.tick()),
2618
+ source,
2619
+ message: message2,
2620
+ metadata,
2621
+ mutations: [],
2622
+ active: true
2623
+ };
2624
+ registry.set(id, ctx);
2625
+ setActiveTx(id);
2626
+ return ctx;
2627
+ }
2628
+ __name(beginTransaction, "beginTransaction");
2629
+ function tagForTransaction() {
2630
+ const txId = getActiveTxId();
2631
+ if (!txId) return void 0;
2632
+ const ctx = registry.get(txId);
2633
+ if (ctx && ctx.active) {
2634
+ return txId;
2635
+ }
2636
+ return void 0;
2637
+ }
2638
+ __name(tagForTransaction, "tagForTransaction");
2639
+ function commitTransaction() {
2640
+ const txId = getActiveTxId();
2641
+ if (!txId) return null;
2642
+ const ctx = registry.get(txId);
2643
+ if (!ctx || !ctx.active) return null;
2644
+ ctx.active = false;
2645
+ ctx.committedAt = hlc.serialize(hlc.tick());
2646
+ const tx = {
2647
+ id: ctx.id,
2648
+ mutations: ctx.mutations,
2649
+ startedAt: ctx.startedAt,
2650
+ committedAt: ctx.committedAt,
2651
+ source: ctx.source,
2652
+ message: ctx.message,
2653
+ metadata: ctx.metadata
2654
+ };
2655
+ setActiveTx(null);
2656
+ return tx;
2657
+ }
2658
+ __name(commitTransaction, "commitTransaction");
2659
+ function _setPath(path, value) {
2660
+ const parts = path.replace(/^state\./, "").split(".");
2661
+ let current = globalThis.state;
2662
+ for (let i = 0; i < parts.length - 1; i++) {
2663
+ const part = parts[i];
2664
+ if (current[part] === void 0) {
2665
+ current[part] = {};
2666
+ }
2667
+ current = current[part];
2668
+ }
2669
+ current[parts[parts.length - 1]] = value;
2670
+ }
2671
+ __name(_setPath, "_setPath");
2672
+ function _deletePath(path) {
2673
+ const parts = path.replace(/^state\./, "").split(".");
2674
+ let current = globalThis.state;
2675
+ for (let i = 0; i < parts.length - 1; i++) {
2676
+ const part = parts[i];
2677
+ if (current[part] === void 0) return;
2678
+ current = current[part];
2679
+ }
2680
+ if (current.remove) {
2681
+ current.remove(parts[parts.length - 1]);
2682
+ } else {
2683
+ delete current[parts[parts.length - 1]];
2684
+ }
2685
+ }
2686
+ __name(_deletePath, "_deletePath");
2687
+ function _applyInverse(record) {
2688
+ const wasEnabled = exports.internal.historyEnabled;
2689
+ const wasRecording = exports.internal._recording;
2690
+ exports.internal.historyEnabled = false;
2691
+ exports.internal._recording = false;
2692
+ try {
2693
+ if (record.action === "set" || record.operation === "set") {
2694
+ if (record.previousValue === void 0) {
2695
+ _deletePath(record.path);
2696
+ } else {
2697
+ _setPath(record.path, record.previousValue);
2698
+ }
2699
+ } else if (record.action === "delete" || record.operation === "delete") {
2700
+ if (record.previousValue !== void 0) {
2701
+ _setPath(record.path, record.previousValue);
2702
+ }
2703
+ }
2704
+ } finally {
2705
+ exports.internal.historyEnabled = wasEnabled;
2706
+ exports.internal._recording = wasRecording;
2707
+ }
2708
+ }
2709
+ __name(_applyInverse, "_applyInverse");
2710
+ function abortTransaction() {
2711
+ const txId = getActiveTxId();
2712
+ if (!txId) return null;
2713
+ const ctx = registry.get(txId);
2714
+ if (!ctx || !ctx.active) return null;
2715
+ for (let i = ctx.mutations.length - 1; i >= 0; i--) {
2716
+ const undoStack = exports.internal.undoStack;
2717
+ const idx = undoStack.findIndex((r) => r.id === ctx.mutations[i]);
2718
+ if (idx >= 0) {
2719
+ const record = undoStack[idx];
2720
+ exports.internal.undoStack.splice(idx, 1);
2721
+ _applyInverse(record);
2722
+ }
2723
+ }
2724
+ ctx.active = false;
2725
+ ctx.committedAt = hlc.serialize(hlc.tick());
2726
+ const tx = {
2727
+ id: ctx.id,
2728
+ mutations: ctx.mutations,
2729
+ startedAt: ctx.startedAt,
2730
+ committedAt: ctx.committedAt,
2731
+ source: ctx.source,
2732
+ message: ctx.message,
2733
+ metadata: ctx.metadata
2734
+ };
2735
+ registry.delete(txId);
2736
+ setActiveTx(null);
2737
+ return tx;
2738
+ }
2739
+ __name(abortTransaction, "abortTransaction");
2740
+ function listTransactions() {
2741
+ const result = [];
2742
+ for (const ctx of registry.values()) {
2743
+ result.push({
2744
+ id: ctx.id,
2745
+ mutations: ctx.mutations,
2746
+ startedAt: ctx.startedAt,
2747
+ committedAt: ctx.committedAt,
2748
+ source: ctx.source,
2749
+ message: ctx.message,
2750
+ metadata: ctx.metadata
2751
+ });
2752
+ }
2753
+ return result;
2754
+ }
2755
+ __name(listTransactions, "listTransactions");
2756
+ function currentTransaction() {
2757
+ const txId = getActiveTxId();
2758
+ if (!txId) return null;
2759
+ const ctx = registry.get(txId);
2760
+ if (!ctx || !ctx.active) return null;
2761
+ return {
2762
+ id: ctx.id,
2763
+ mutations: ctx.mutations,
2764
+ startedAt: ctx.startedAt,
2765
+ source: ctx.source,
2766
+ message: ctx.message,
2767
+ metadata: ctx.metadata
2768
+ };
2769
+ }
2770
+ __name(currentTransaction, "currentTransaction");
2771
+ function registerMutationInTransaction(mutationId) {
2772
+ const txId = getActiveTxId();
2773
+ if (!txId) return;
2774
+ const ctx = registry.get(txId);
2775
+ if (ctx && ctx.active) {
2776
+ ctx.mutations.push(mutationId);
2777
+ }
2778
+ }
2779
+ __name(registerMutationInTransaction, "registerMutationInTransaction");
2780
+
2781
+ // core/mutation/engine.ts
2782
+ function currentTimestamp() {
2783
+ return hlc.serialize(hlc.tick());
2784
+ }
2785
+ __name(currentTimestamp, "currentTimestamp");
2786
+ function createMutation(path, operation, before2, after2, options) {
2787
+ const now2 = hlc.tick();
2788
+ const mutation = {
2789
+ id: generateMutationId(),
2790
+ path,
2791
+ operation,
2792
+ after: after2,
2793
+ before: before2,
2794
+ timestamp: now2.physical,
2795
+ hlc: hlc.serialize(now2),
2796
+ context: options?.context || exports.internal.currentContext || void 0,
2797
+ source: options?.source,
2798
+ transactionId: options?.transactionId || (operation !== "length" ? tagForTransaction() : void 0),
2799
+ // Legacy fields for backward compatibility
2800
+ action: operation === "set" ? "set" : "delete",
2801
+ newValue: after2,
2802
+ previousValue: before2
2803
+ };
2804
+ if (mutation.transactionId) {
2805
+ registerMutationInTransaction(mutation.id);
2806
+ }
2807
+ return mutation;
2808
+ }
2809
+ __name(createMutation, "createMutation");
2810
+ function recordMutation(mutation) {
2811
+ if (!exports.internal.historyEnabled) return;
2812
+ exports.internal.recordMutation(mutation);
2813
+ }
2814
+ __name(recordMutation, "recordMutation");
2815
+ function toPatch(mutation) {
2816
+ return mutationToPatch(mutation);
2817
+ }
2818
+ __name(toPatch, "toPatch");
2819
+ function mutate(path, value, options) {
2820
+ const normalizedPath = path.startsWith("state.") ? path : "state." + path;
2821
+ const keyPath = normalizedPath.replace(/^state\./, "");
2822
+ let current;
2823
+ try {
2824
+ const parts2 = keyPath.split(".");
2825
+ let obj = globalThis.state;
2826
+ for (const part of parts2) {
2827
+ obj = obj?.[part];
2828
+ }
2829
+ current = obj;
2830
+ } catch {
2831
+ current = void 0;
2832
+ }
2833
+ const operation = value === void 0 ? "delete" : "set";
2834
+ const mutation = createMutation(
2835
+ normalizedPath,
2836
+ operation,
2837
+ current,
2838
+ value === void 0 ? void 0 : value,
2839
+ options
2840
+ );
2841
+ const wasRecording = exports.internal._recording;
2842
+ exports.internal._recording = false;
2843
+ const parts = keyPath.split(".");
2844
+ let target = globalThis.state;
2845
+ for (let i = 0; i < parts.length - 1; i++) {
2846
+ if (target[parts[i]] === void 0) {
2847
+ target[parts[i]] = {};
2848
+ }
2849
+ target = target[parts[i]];
2850
+ }
2851
+ if (operation === "delete") {
2852
+ delete target[parts[parts.length - 1]];
2853
+ } else {
2854
+ target[parts[parts.length - 1]] = value;
2855
+ }
2856
+ exports.internal._recording = wasRecording;
2857
+ recordMutation(mutation);
2858
+ return mutation;
2859
+ }
2860
+ __name(mutate, "mutate");
2861
+ function activeTransactionId() {
2862
+ return exports.internal.currentTransactionId || null;
2863
+ }
2864
+ __name(activeTransactionId, "activeTransactionId");
2865
+
2866
+ // functions/state/index.ts
2867
+ var TARGET = /* @__PURE__ */ Symbol("memorio.target");
2868
+ var wrapperCache = /* @__PURE__ */ new WeakMap();
2869
+ var arrayRootDedup = /* @__PURE__ */ new Set();
2870
+ var deepRaw = /* @__PURE__ */ __name((val, seen = null) => {
2871
+ if (val === null || typeof val !== "object") return val;
2872
+ if (!seen) seen = /* @__PURE__ */ new WeakSet();
2873
+ if (val[TARGET] !== void 0) return deepRaw(val[TARGET], seen);
2874
+ if (seen) {
2875
+ if (seen.has(val)) return val;
2876
+ seen.add(val);
2877
+ }
2878
+ const ctor = val.constructor?.name;
2879
+ if (ctor !== "Object" && ctor !== "Array") return val;
2880
+ const copy = Array.isArray(val) ? [] : {};
2881
+ for (const k of Reflect.ownKeys(val)) {
2882
+ if (!Object.prototype.propertyIsEnumerable.call(val, k)) continue;
2883
+ copy[k] = deepRaw(val[k], seen);
2884
+ }
2885
+ return copy;
2886
+ }, "deepRaw");
2887
+ var objPath = /* @__PURE__ */ __name((prop, object, separator = ".") => {
2888
+ return object.concat(prop).join(separator);
2889
+ }, "objPath");
2890
+ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
2891
+ const event = /* @__PURE__ */ __name((name) => {
2892
+ try {
2893
+ dispatch.set(name, { detail: { name } });
2894
+ } catch (err) {
2895
+ if (exports.DEV) console.warn("[memorio state] event dispatch failed:", err);
2896
+ }
2897
+ return;
2898
+ }, "event");
2899
+ return new Proxy(
2900
+ obj,
2901
+ {
2902
+ get(target, prop) {
2903
+ if (prop === "__path") {
2904
+ return tree.length > 0 ? "state." + tree.join(".") : "state";
2905
+ }
2906
+ if (prop === TARGET) {
2907
+ return target;
2908
+ }
2909
+ if (target[TARGET] !== void 0) {
2910
+ return target;
2911
+ }
2912
+ if (prop === "list") {
2913
+ message_default('Some state could be hidden when you use "state.list". Use "state" to see the complete list ');
2914
+ return deepRaw(target, /* @__PURE__ */ new WeakSet());
2915
+ }
2916
+ if (typeof prop === "string") {
2917
+ const path = tree.length > 0 ? "state." + tree.concat(prop).join(".") : "state." + prop;
2918
+ exports.internal.lastAccessedPath = path;
2919
+ if (exports.internal.tracking) {
2920
+ exports.internal.trackedPaths.add(path);
2921
+ }
2922
+ }
2923
+ if (prop === "_lastPath") {
2924
+ return exports.internal.lastAccessedPath;
2925
+ }
2926
+ if (prop === "remove") {
2927
+ return (key) => {
2928
+ delete target[key];
2929
+ return true;
2930
+ };
2931
+ }
2932
+ if (prop === "removeAll") {
2933
+ return () => {
2934
+ try {
2935
+ for (const key of Reflect.ownKeys(target)) {
2936
+ if (typeof target[key] !== "function" && !["list", "remove", "removeAll", "lock", "unlock", "persist"].includes(key)) {
2937
+ delete target[key];
2938
+ }
2939
+ }
2940
+ } catch (error) {
2941
+ console.error(error);
2942
+ }
2943
+ return;
2944
+ };
2945
+ }
2946
+ if (Object.isFrozen(target[prop])) return target[prop];
2947
+ if (prop === "lock" || prop === "unlock") {
2948
+ const value = Reflect.get(target, prop);
2949
+ if (value) return value;
2950
+ }
2951
+ try {
2952
+ const value = Reflect.get(target, prop);
2953
+ if (value && typeof value === "object" && ["Array", "Object"].includes(value.constructor.name)) {
2954
+ let wrapper = wrapperCache.get(value);
2955
+ if (!wrapper) {
2956
+ wrapper = buildProxy(value, callback, tree.concat(prop));
2957
+ wrapperCache.set(value, wrapper);
2958
+ }
2959
+ return wrapper;
2960
+ }
2961
+ return value;
2962
+ } catch (error) {
2963
+ console.error("Error: ", error);
1989
2964
  return void 0;
1990
2965
  }
1991
2966
  },
@@ -2032,6 +3007,16 @@ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
2032
3007
  }
2033
3008
  );
2034
3009
  event("state." + path);
3010
+ if (Array.isArray(target) && tree.length > 0) {
3011
+ const rootName = "state." + tree.join(".");
3012
+ if (!arrayRootDedup.has(rootName)) {
3013
+ arrayRootDedup.add(rootName);
3014
+ event(rootName);
3015
+ if (typeof globalThis.queueMicrotask === "function") {
3016
+ globalThis.queueMicrotask(() => arrayRootDedup.clear());
3017
+ }
3018
+ }
3019
+ }
2035
3020
  Reflect.set(target, key, rawValue);
2036
3021
  exports.internal.bumpStateVersion();
2037
3022
  if (target[key] && typeof target[key] === "object") {
@@ -2088,6 +3073,17 @@ var buildProxy = /* @__PURE__ */ __name((obj, callback, tree = []) => {
2088
3073
  const path = objPath(prop, tree);
2089
3074
  const previousValue = Reflect.get(target, prop);
2090
3075
  callback({ action: "delete", path, target, previousValue });
3076
+ event("state." + path);
3077
+ if (Array.isArray(target) && tree.length > 0) {
3078
+ const rootName = "state." + tree.join(".");
3079
+ if (!arrayRootDedup.has(rootName)) {
3080
+ arrayRootDedup.add(rootName);
3081
+ event(rootName);
3082
+ if (typeof globalThis.queueMicrotask === "function") {
3083
+ globalThis.queueMicrotask(() => arrayRootDedup.clear());
3084
+ }
3085
+ }
3086
+ }
2091
3087
  return Reflect.deleteProperty(target, prop);
2092
3088
  } catch (error) {
2093
3089
  console.error("Error in deleteProperty trap:", error);
@@ -2109,57 +3105,83 @@ if (globalThis[STATE_INSTANCE_KEY]) {
2109
3105
  exports.state = globalThis[STATE_INSTANCE_KEY];
2110
3106
  } else {
2111
3107
  exports.state = buildProxy({}, (mutation) => {
2112
- if (exports.internal.historyEnabled) {
2113
- exports.internal.recordMutation({
2114
- path: mutation.path,
2115
- action: mutation.action,
2116
- newValue: mutation.newValue,
2117
- previousValue: mutation.previousValue,
2118
- timestamp: Date.now()
2119
- });
3108
+ if (exports.internal.historyEnabled && exports.internal._recording !== false) {
3109
+ const operation = mutation.action === "delete" ? "delete" : "set";
3110
+ const record = createMutation(
3111
+ mutation.path,
3112
+ operation,
3113
+ mutation.previousValue,
3114
+ mutation.newValue,
3115
+ {
3116
+ context: mutation.context,
3117
+ source: mutation.source
3118
+ }
3119
+ );
3120
+ exports.internal.recordMutation(record);
2120
3121
  }
2121
3122
  });
2122
- exports.state.lock = () => {
2123
- exports.internal.locked = true;
2124
- message_default("State is now locked. All modifications are blocked.");
2125
- };
2126
- exports.state.unlock = () => {
2127
- exports.internal.locked = false;
2128
- message_default("State is now unlocked. Modifications are allowed.");
2129
- };
2130
- exports.state.persist = (path) => {
2131
- if (typeof path !== "string" || !path.length) {
2132
- if (exports.DEV) console.warn('[memorio state] state.persist() requires a non-empty path string (e.g. "state.user")');
2133
- return () => {
2134
- };
2135
- }
2136
- const normalized = path.startsWith("state.") ? path : "state." + path;
2137
- const key = normalized.replace(/^state\./, "");
2138
- const segments = key.split(".");
2139
- const initial = exports.store.get(key);
2140
- if (initial !== void 0 && initial !== null) {
2141
- let acc = exports.state;
2142
- for (let i = 0; i < segments.length; i++) {
2143
- const seg = segments[i];
2144
- if (i === segments.length - 1) {
2145
- acc[seg] = deepRaw(initial);
2146
- } else {
2147
- if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
2148
- acc = acc[seg];
3123
+ const _rawTarget = exports.state[TARGET];
3124
+ try {
3125
+ Object.defineProperty(_rawTarget, "lock", {
3126
+ value: /* @__PURE__ */ __name(() => {
3127
+ exports.internal.locked = true;
3128
+ message_default("State is now locked. All modifications are blocked.");
3129
+ }, "value"),
3130
+ writable: true,
3131
+ configurable: true,
3132
+ enumerable: false
3133
+ });
3134
+ Object.defineProperty(_rawTarget, "unlock", {
3135
+ value: /* @__PURE__ */ __name(() => {
3136
+ exports.internal.locked = false;
3137
+ message_default("State is now unlocked. Modifications are allowed.");
3138
+ }, "value"),
3139
+ writable: true,
3140
+ configurable: true,
3141
+ enumerable: false
3142
+ });
3143
+ } catch (e) {
3144
+ if (exports.DEV) console.warn("[memorio state] lock/unlock defineProperty failed:", e);
3145
+ }
3146
+ try {
3147
+ Object.defineProperty(_rawTarget, "persist", {
3148
+ value: /* @__PURE__ */ __name((path) => {
3149
+ if (typeof path !== "string" || !path.length) {
3150
+ if (exports.DEV) console.warn('[memorio state] state.persist() requires a non-empty path string (e.g. "state.user")');
3151
+ return () => {
3152
+ };
2149
3153
  }
2150
- }
2151
- }
2152
- const handler = /* @__PURE__ */ __name(() => {
2153
- let current = exports.state;
2154
- for (const seg of segments) {
2155
- current = current === void 0 || current === null ? void 0 : current[seg];
2156
- }
2157
- exports.store.set(key, deepRaw(current));
2158
- }, "handler");
2159
- const off = dispatch.listen(normalized, handler);
2160
- return typeof off === "function" ? off : () => {
2161
- };
2162
- };
3154
+ const normalized = path.startsWith("state.") ? path : "state." + path;
3155
+ const key = normalized.replace(/^state\./, "");
3156
+ const segments = key.split(".");
3157
+ const initial = exports.store.get(key);
3158
+ if (initial !== void 0 && initial !== null) {
3159
+ let acc = exports.state;
3160
+ for (let i = 0; i < segments.length - 1; i++) {
3161
+ const seg = segments[i];
3162
+ if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
3163
+ acc = acc[seg];
3164
+ }
3165
+ if (acc) acc[segments[segments.length - 1]] = deepRaw(initial);
3166
+ }
3167
+ const handler = /* @__PURE__ */ __name(() => {
3168
+ let current = exports.state;
3169
+ for (const seg of segments) {
3170
+ current = current === void 0 || current === null ? void 0 : current[seg];
3171
+ }
3172
+ exports.store.set(key, deepRaw(current));
3173
+ }, "handler");
3174
+ const off = dispatch.listen(normalized, handler);
3175
+ return typeof off === "function" ? off : () => {
3176
+ };
3177
+ }, "value"),
3178
+ writable: true,
3179
+ configurable: true,
3180
+ enumerable: false
3181
+ });
3182
+ } catch (e) {
3183
+ if (exports.DEV) console.warn("[memorio state] persist defineProperty failed:", e);
3184
+ }
2163
3185
  globalThis[STATE_INSTANCE_KEY] = exports.state;
2164
3186
  }
2165
3187
 
@@ -2171,6 +3193,7 @@ init_cjs_shims();
2171
3193
  init_platform();
2172
3194
  init_internal();
2173
3195
  init_message();
3196
+ init_encryption();
2174
3197
  var _sessionStorage = getSessionStorage();
2175
3198
  var _fallbackStorageByContext2 = /* @__PURE__ */ new Map();
2176
3199
  function _getFallbackStorage2() {
@@ -2183,6 +3206,14 @@ function _getFallbackStorage2() {
2183
3206
  }
2184
3207
  __name(_getFallbackStorage2, "_getFallbackStorage");
2185
3208
  var _hasStorage2 = _sessionStorage !== null;
3209
+ var _encryptionKey2 = null;
3210
+ var _onError2 = null;
3211
+ var _maxObjectSize2 = 0;
3212
+ var _maxTotalSize2 = 0;
3213
+ function _isEncryptedEnvelope2(value) {
3214
+ return exports.encryption.isEncrypted(value);
3215
+ }
3216
+ __name(_isEncryptedEnvelope2, "_isEncryptedEnvelope");
2186
3217
  function _getPrefix2() {
2187
3218
  const contextName = exports.internal.currentContext || "";
2188
3219
  return contextName ? `${contextName}-` : `memorio_session_`;
@@ -2236,16 +3267,22 @@ if (globalThis[SESSION_INSTANCE_KEY]) {
2236
3267
  /**
2237
3268
  * Gets a value from storage.
2238
3269
  * @param name The key to retrieve.
2239
- * @returns The parsed value or null if not found.
3270
+ * @param opts Optional { decrypt: key } to decrypt an encrypted envelope.
3271
+ * @returns The parsed value, a Promise when decrypting, or null if not found.
2240
3272
  */
2241
3273
  get: {
2242
- value: /* @__PURE__ */ __name((name) => {
3274
+ value: /* @__PURE__ */ __name((name, opts) => {
2243
3275
  if (!name) {
2244
3276
  console.warn("[memorio session] session.get() called with empty or null key - returning null");
2245
3277
  return null;
2246
3278
  }
2247
3279
  try {
2248
- return _read2(_prefixKey2(name));
3280
+ const raw = _read2(_prefixKey2(name));
3281
+ const key = opts?.decrypt ?? _encryptionKey2;
3282
+ if (key && _isEncryptedEnvelope2(raw)) {
3283
+ return exports.encryption.decrypt(raw, key);
3284
+ }
3285
+ return raw;
2249
3286
  } catch (err) {
2250
3287
  exports.message(`Error parsing session item '${name}':${err}`);
2251
3288
  }
@@ -2256,10 +3293,11 @@ if (globalThis[SESSION_INSTANCE_KEY]) {
2256
3293
  * Sets a value in storage.
2257
3294
  * @param name The key to set.
2258
3295
  * @param value The value to store.
2259
- * @returns true if written, false if the key was rejected.
3296
+ * @param opts Optional { encrypt: key } to encrypt before storage.
3297
+ * @returns true if written, false if rejected. Returns a Promise when encrypting.
2260
3298
  */
2261
3299
  set: {
2262
- value: /* @__PURE__ */ __name((name, value) => {
3300
+ value: /* @__PURE__ */ __name((name, value, opts) => {
2263
3301
  if (!name) {
2264
3302
  console.warn("[memorio session] session.set() called with empty or null key - write aborted");
2265
3303
  return false;
@@ -2271,15 +3309,63 @@ if (globalThis[SESSION_INSTANCE_KEY]) {
2271
3309
  exports.message("It's not secure to session functions.");
2272
3310
  return false;
2273
3311
  }
3312
+ if (_maxObjectSize2 > 0 || _maxTotalSize2 > 0) {
3313
+ let serializedSize = 0;
3314
+ try {
3315
+ serializedSize = new TextEncoder().encode(JSON.stringify(value)).length;
3316
+ } catch {
3317
+ serializedSize = 0;
3318
+ }
3319
+ if (_maxObjectSize2 > 0 && serializedSize > _maxObjectSize2) {
3320
+ const err = new Error(`Object size (${serializedSize} bytes) exceeds maxObjectSize (${_maxObjectSize2} bytes)`);
3321
+ _onError2?.(err, { operation: "set" });
3322
+ return false;
3323
+ }
3324
+ if (_maxTotalSize2 > 0) {
3325
+ const currentTotal = exports.session.size() * 1024;
3326
+ const existingItemSize = _sessionStorage ? _sessionStorage.getItem(prefixedName)?.length ?? 0 : _getFallbackStorage2().get(prefixedName)?.length ?? 0;
3327
+ const projected = currentTotal - existingItemSize + serializedSize;
3328
+ if (projected > _maxTotalSize2) {
3329
+ const err = new Error(`Total session size (${projected} bytes) exceeds maxTotalSize (${_maxTotalSize2} bytes)`);
3330
+ _onError2?.(err, { operation: "set" });
3331
+ return false;
3332
+ }
3333
+ }
3334
+ }
3335
+ const key = opts?.encrypt ?? _encryptionKey2;
3336
+ if (key) {
3337
+ return exports.encryption.encrypt(value, key).then((env) => {
3338
+ _write2(prefixedName, env);
3339
+ return true;
3340
+ }).catch((err) => {
3341
+ exports.message(`Error encrypting session item '${name}': ${err}`);
3342
+ _onError2?.(err, { operation: "set" });
3343
+ return false;
3344
+ });
3345
+ }
2274
3346
  try {
2275
3347
  _write2(prefixedName, value);
2276
3348
  } catch (err) {
2277
3349
  exports.message(`Error setting session item '${name}': ${err}`);
3350
+ _onError2?.(err, { operation: "set" });
2278
3351
  return false;
2279
3352
  }
2280
3353
  return true;
2281
3354
  }, "value")
2282
3355
  },
3356
+ /**
3357
+ * Configure session-wide behavior.
3358
+ * @param opts { encryptionKey, onError, maxObjectSize, maxTotalSize }
3359
+ */
3360
+ config: {
3361
+ value: /* @__PURE__ */ __name((opts) => {
3362
+ if (opts.encryptionKey !== void 0) _encryptionKey2 = opts.encryptionKey;
3363
+ if (opts.onError !== void 0) _onError2 = opts.onError;
3364
+ if (opts.maxObjectSize !== void 0) _maxObjectSize2 = opts.maxObjectSize;
3365
+ if (opts.maxTotalSize !== void 0) _maxTotalSize2 = opts.maxTotalSize;
3366
+ return exports.session;
3367
+ }, "value")
3368
+ },
2283
3369
  /**
2284
3370
  * Removes a value from storage.
2285
3371
  * @param name The key to remove.
@@ -2511,12 +3597,17 @@ var observerFunction = /* @__PURE__ */ __name((s, cb = null, option = true) => {
2511
3597
  const callbacks = Array.isArray(cb) ? cb : [cb];
2512
3598
  const obs = globalThis.observer;
2513
3599
  if (obs?.list?.[resolvedPath]) dispatch.remove(resolvedPath);
3600
+ const unsubs = [];
2514
3601
  callbacks.forEach((callback) => {
2515
3602
  if (typeof callback === "function") {
2516
- dispatch.listen(resolvedPath, callback, option);
3603
+ const off = dispatch.listen(resolvedPath, callback, option);
3604
+ if (typeof off === "function") unsubs.push(off);
2517
3605
  }
2518
3606
  });
2519
- return;
3607
+ if (unsubs.length === 1) return unsubs[0];
3608
+ if (unsubs.length > 1) return () => unsubs.forEach((u) => u());
3609
+ return () => {
3610
+ };
2520
3611
  }
2521
3612
  }, "observerFunction");
2522
3613
  var observer = observerFunction;
@@ -2579,7 +3670,6 @@ Object.defineProperties(
2579
3670
  init_cjs_shims();
2580
3671
  init_message();
2581
3672
  init_internal();
2582
- init_env();
2583
3673
  var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
2584
3674
  if (!deps || typeof func !== "function") {
2585
3675
  return () => {
@@ -2623,37 +3713,616 @@ var useObserver = /* @__PURE__ */ __name(((func, deps = []) => {
2623
3713
  });
2624
3714
  }
2625
3715
  });
2626
- if (handlers.length > 0) {
2627
- message_default(`useObserver: Monitoring ${handlers.length} paths.`);
2628
- } else {
2629
- console.warn(`useObserver: No paths resolved for monitoring. Check your dependencies!`);
3716
+ if (handlers.length > 0) {
3717
+ message_default(`useObserver: Monitoring ${handlers.length} paths.`);
3718
+ } else {
3719
+ console.warn(`useObserver: No paths resolved for monitoring. Check your dependencies!`);
3720
+ }
3721
+ return () => {
3722
+ unsubs.forEach(({ path, off }) => {
3723
+ off();
3724
+ message_default(`useObserver: Stopped monitoring "${path}"`);
3725
+ });
3726
+ };
3727
+ } catch (err) {
3728
+ message_default(`useObserver Error: ${err}`);
3729
+ return () => {
3730
+ };
3731
+ }
3732
+ }), "useObserver");
3733
+
3734
+ // index.ts
3735
+ init_encryption();
3736
+
3737
+ // functions/computed/index.ts
3738
+ init_cjs_shims();
3739
+ init_env();
3740
+ init_message();
3741
+ var DEFAULT_EQUALITY = /* @__PURE__ */ __name((prev, next) => {
3742
+ if (prev === next) return true;
3743
+ if (prev == null || next == null) return false;
3744
+ if (typeof prev !== typeof next) return false;
3745
+ if (typeof prev !== "object") return false;
3746
+ try {
3747
+ return JSON.stringify(prev) === JSON.stringify(next);
3748
+ } catch {
3749
+ return false;
3750
+ }
3751
+ }, "DEFAULT_EQUALITY");
3752
+ var computedMap = /* @__PURE__ */ new Map();
3753
+ function _normalizeKey(key) {
3754
+ if (!key || typeof key !== "string") return "";
3755
+ const normalized = key.startsWith("state.") ? key : `state.${key}`;
3756
+ return normalized;
3757
+ }
3758
+ __name(_normalizeKey, "_normalizeKey");
3759
+ function _invalidate(key) {
3760
+ const entry = computedMap.get(key);
3761
+ if (!entry) return;
3762
+ const newValue = _recompute(entry);
3763
+ if (entry.equality(entry.lastValue, newValue)) {
3764
+ return;
3765
+ }
3766
+ entry.lastValue = newValue;
3767
+ for (const sub of entry.subscribers) {
3768
+ try {
3769
+ sub(newValue);
3770
+ } catch (err) {
3771
+ if (exports.DEV) console.error("[memorio computed] subscriber error:", err);
3772
+ }
3773
+ }
3774
+ dispatch.set("memorio:computed:" + key, { detail: { key, value: newValue } });
3775
+ }
3776
+ __name(_invalidate, "_invalidate");
3777
+ function _readStatePath(path) {
3778
+ const entry = computedMap.get(path);
3779
+ if (entry) {
3780
+ return entry.lastValue;
3781
+ }
3782
+ const normalized = path.startsWith("state.") ? path : `state.${path}`;
3783
+ const segments = normalized.replace(/^state\./, "").split(".");
3784
+ let current = globalThis.state;
3785
+ if (current) {
3786
+ for (const seg of segments) {
3787
+ if (current === null || current === void 0) break;
3788
+ try {
3789
+ current = current[seg];
3790
+ } catch {
3791
+ return void 0;
3792
+ }
3793
+ }
3794
+ }
3795
+ return current === void 0 ? null : current;
3796
+ }
3797
+ __name(_readStatePath, "_readStatePath");
3798
+ function _recompute(entry) {
3799
+ const newDeps = /* @__PURE__ */ new Set();
3800
+ const trackerGet = /* @__PURE__ */ __name((path) => {
3801
+ if (!path || typeof path !== "string") return void 0;
3802
+ newDeps.add(path);
3803
+ return _readStatePath(path);
3804
+ }, "trackerGet");
3805
+ try {
3806
+ return entry.selector(trackerGet);
3807
+ } catch (err) {
3808
+ if (exports.DEV) console.error("[memorio computed] selector error:", err);
3809
+ message_default(`[memorio computed] selector error: ${err}`);
3810
+ return entry.lastValue;
3811
+ }
3812
+ }
3813
+ __name(_recompute, "_recompute");
3814
+ function _setupDeps(key, entry, deps) {
3815
+ for (const off of entry._dispatchUnsubscribers) off();
3816
+ entry._dispatchUnsubscribers = [];
3817
+ for (const dep of deps) {
3818
+ if (computedMap.has(dep)) {
3819
+ const computedEvent = "memorio:computed:" + dep;
3820
+ const off = dispatch.listen(computedEvent, () => _invalidate(key));
3821
+ if (off) entry._dispatchUnsubscribers.push(off);
3822
+ } else {
3823
+ const off = dispatch.listen(dep, () => _invalidate(key));
3824
+ if (off) entry._dispatchUnsubscribers.push(off);
3825
+ }
3826
+ }
3827
+ entry.deps = deps;
3828
+ }
3829
+ __name(_setupDeps, "_setupDeps");
3830
+ function _compute(key, selector, opts) {
3831
+ const normalizedKey = _normalizeKey(key);
3832
+ const cacheKey = opts?.equalityKey ? `${opts.equalityKey}:${normalizedKey}` : normalizedKey;
3833
+ if (computedMap.has(cacheKey)) {
3834
+ const entry2 = computedMap.get(cacheKey);
3835
+ entry2.selector = selector;
3836
+ entry2.equality = opts?.equality || DEFAULT_EQUALITY;
3837
+ const newDeps2 = /* @__PURE__ */ new Set();
3838
+ const wrappedGet = /* @__PURE__ */ __name((path) => {
3839
+ newDeps2.add(path);
3840
+ return _readStatePath(path);
3841
+ }, "wrappedGet");
3842
+ let newValue;
3843
+ try {
3844
+ newValue = selector(wrappedGet);
3845
+ } catch (err) {
3846
+ if (exports.DEV) console.error("[memorio computed] selector error:", err);
3847
+ return entry2.lastValue;
3848
+ }
3849
+ if (entry2.equality(entry2.lastValue, newValue)) {
3850
+ return entry2.lastValue;
3851
+ }
3852
+ entry2.lastValue = newValue;
3853
+ _setupDeps(cacheKey, entry2, newDeps2);
3854
+ for (const sub of entry2.subscribers) {
3855
+ try {
3856
+ sub(newValue);
3857
+ } catch (err) {
3858
+ if (exports.DEV) console.error("[memorio computed] subscriber error:", err);
3859
+ }
3860
+ }
3861
+ return newValue;
3862
+ }
3863
+ const newDeps = /* @__PURE__ */ new Set();
3864
+ const get = /* @__PURE__ */ __name((path) => {
3865
+ newDeps.add(path);
3866
+ return _readStatePath(path);
3867
+ }, "get");
3868
+ let lastValue;
3869
+ try {
3870
+ lastValue = selector(get);
3871
+ } catch (err) {
3872
+ if (exports.DEV) console.error("[memorio computed] selector error:", err);
3873
+ message_default(`[memorio computed] selector error: ${err}`);
3874
+ lastValue = null;
3875
+ }
3876
+ const entry = {
3877
+ selector,
3878
+ lastValue,
3879
+ deps: newDeps,
3880
+ equality: opts?.equality || DEFAULT_EQUALITY,
3881
+ subscribers: /* @__PURE__ */ new Set(),
3882
+ _dispatchUnsubscribers: []
3883
+ };
3884
+ computedMap.set(cacheKey, entry);
3885
+ _setupDeps(cacheKey, entry, newDeps);
3886
+ return lastValue;
3887
+ }
3888
+ __name(_compute, "_compute");
3889
+ function _getValue(key) {
3890
+ const normalizedKey = _normalizeKey(key);
3891
+ const entry = computedMap.get(normalizedKey);
3892
+ if (!entry) return null;
3893
+ return entry.lastValue;
3894
+ }
3895
+ __name(_getValue, "_getValue");
3896
+ function _subscribe(key, cb) {
3897
+ const normalizedKey = _normalizeKey(key);
3898
+ const entry = computedMap.get(normalizedKey);
3899
+ if (!entry) {
3900
+ if (exports.DEV) console.warn(`[memorio computed] subscribe: no computed value registered for key '${key}'`);
3901
+ return () => {
3902
+ };
3903
+ }
3904
+ entry.subscribers.add(cb);
3905
+ return () => {
3906
+ entry.subscribers.delete(cb);
3907
+ };
3908
+ }
3909
+ __name(_subscribe, "_subscribe");
3910
+ function _remove3(key) {
3911
+ const normalizedKey = _normalizeKey(key);
3912
+ if (!computedMap.has(normalizedKey)) return false;
3913
+ const entry = computedMap.get(normalizedKey);
3914
+ for (const off of entry._dispatchUnsubscribers) off();
3915
+ computedMap.delete(normalizedKey);
3916
+ return true;
3917
+ }
3918
+ __name(_remove3, "_remove");
3919
+ function _list() {
3920
+ return Array.from(computedMap.keys());
3921
+ }
3922
+ __name(_list, "_list");
3923
+ function _clear() {
3924
+ for (const [, entry] of computedMap) {
3925
+ for (const off of entry._dispatchUnsubscribers) off();
3926
+ }
3927
+ computedMap.clear();
3928
+ }
3929
+ __name(_clear, "_clear");
3930
+ var computed = {
3931
+ compute: _compute,
3932
+ getValue: _getValue,
3933
+ subscribe: _subscribe,
3934
+ remove: _remove3,
3935
+ list: _list,
3936
+ clear: _clear
3937
+ };
3938
+
3939
+ // functions/broadcast/index.ts
3940
+ init_cjs_shims();
3941
+ init_env();
3942
+ init_message();
3943
+ var _channel = null;
3944
+ var _storageListener = null;
3945
+ var _originalDispatchSet = null;
3946
+ var _installed = false;
3947
+ var _targets = "all";
3948
+ var _isLocalChange = false;
3949
+ function _hasBroadcastChannel() {
3950
+ return typeof BroadcastChannel !== "undefined";
3951
+ }
3952
+ __name(_hasBroadcastChannel, "_hasBroadcastChannel");
3953
+ function _hasStorageEvents() {
3954
+ return typeof window !== "undefined" && "addEventListener" in window;
3955
+ }
3956
+ __name(_hasStorageEvents, "_hasStorageEvents");
3957
+ function _shouldSync(target) {
3958
+ if (_targets === "all") return true;
3959
+ return _targets === target;
3960
+ }
3961
+ __name(_shouldSync, "_shouldSync");
3962
+ function _onBroadcastMessage(event) {
3963
+ let msg;
3964
+ try {
3965
+ msg = event.data;
3966
+ } catch {
3967
+ return;
3968
+ }
3969
+ if (!msg || !msg.__memorio_sync) return;
3970
+ if (!_shouldSync(msg.target)) return;
3971
+ if (_isLocalChange) return;
3972
+ try {
3973
+ if (msg.target === "state" || msg.target === "all") {
3974
+ const s = globalThis.state;
3975
+ if (s) {
3976
+ _isLocalChange = true;
3977
+ try {
3978
+ const segments = msg.path.replace(/^state\./, "").split(".");
3979
+ let current = s;
3980
+ for (let i = 0; i < segments.length - 1; i++) {
3981
+ const seg = segments[i];
3982
+ if (current[seg] === void 0 || current[seg] === null) {
3983
+ current[seg] = {};
3984
+ }
3985
+ current = current[seg];
3986
+ }
3987
+ const lastSeg = segments[segments.length - 1];
3988
+ if (msg.action === "set") {
3989
+ current[lastSeg] = msg.value;
3990
+ } else if (msg.action === "delete") {
3991
+ delete current[lastSeg];
3992
+ }
3993
+ } finally {
3994
+ queueMicrotask(() => {
3995
+ _isLocalChange = false;
3996
+ });
3997
+ }
3998
+ }
3999
+ }
4000
+ } catch (err) {
4001
+ if (exports.DEV) console.error("[memorio broadcast] apply state error:", err);
4002
+ }
4003
+ }
4004
+ __name(_onBroadcastMessage, "_onBroadcastMessage");
4005
+ function _onStorageEvent(e) {
4006
+ if (!e.key) return;
4007
+ const prefixes = [
4008
+ ["memorio_store_", "store"],
4009
+ ["memorio_session_", "session"]
4010
+ ];
4011
+ for (const [prefix, target] of prefixes) {
4012
+ if (e.key.startsWith(prefix)) {
4013
+ if (!_shouldSync(target)) continue;
4014
+ const cleanKey = e.key.slice(prefix.length);
4015
+ dispatch.set(`memorio:broadcast:${target}:${cleanKey}`, {
4016
+ detail: { key: cleanKey, oldValue: e.oldValue, newValue: e.newValue }
4017
+ });
4018
+ break;
4019
+ }
4020
+ }
4021
+ }
4022
+ __name(_onStorageEvent, "_onStorageEvent");
4023
+ function _wrapDispatchSet() {
4024
+ if (_originalDispatchSet !== null) return;
4025
+ _originalDispatchSet = dispatch.set;
4026
+ const original = dispatch.set;
4027
+ dispatch.set = (name, value) => {
4028
+ original(name, value);
4029
+ if (name.startsWith("state.") && _shouldSync("state") && _channel) {
4030
+ _isLocalChange = true;
4031
+ try {
4032
+ _channel.postMessage({
4033
+ __memorio_sync: true,
4034
+ target: "state",
4035
+ action: "set",
4036
+ path: name,
4037
+ value: _extractStateValue(name),
4038
+ timestamp: Date.now()
4039
+ });
4040
+ } finally {
4041
+ queueMicrotask(() => {
4042
+ _isLocalChange = false;
4043
+ });
4044
+ }
4045
+ }
4046
+ };
4047
+ }
4048
+ __name(_wrapDispatchSet, "_wrapDispatchSet");
4049
+ function _restoreDispatchSet() {
4050
+ if (_originalDispatchSet !== null) {
4051
+ dispatch.set = _originalDispatchSet;
4052
+ _originalDispatchSet = null;
4053
+ }
4054
+ }
4055
+ __name(_restoreDispatchSet, "_restoreDispatchSet");
4056
+ function _extractStateValue(path) {
4057
+ const s = globalThis.state;
4058
+ if (!s) return void 0;
4059
+ try {
4060
+ const segments = path.replace(/^state\./, "").split(".");
4061
+ let current = s;
4062
+ for (const seg of segments) {
4063
+ if (current === null || current === void 0) break;
4064
+ current = current[seg];
4065
+ }
4066
+ return current === void 0 ? null : current;
4067
+ } catch {
4068
+ return null;
4069
+ }
4070
+ }
4071
+ __name(_extractStateValue, "_extractStateValue");
4072
+ var broadcast = {
4073
+ install: /* @__PURE__ */ __name((channelName, opts) => {
4074
+ if (_installed) return;
4075
+ const name = channelName || opts?.channelName || "memorio_sync";
4076
+ _targets = opts?.targets || "all";
4077
+ if (_hasBroadcastChannel()) {
4078
+ _channel = new BroadcastChannel(name);
4079
+ _channel.addEventListener("message", _onBroadcastMessage);
4080
+ _installed = true;
4081
+ _wrapDispatchSet();
4082
+ if (exports.DEV) message_default(`memorio broadcast: installed (channel="${name}", targets="${_targets}")`);
4083
+ }
4084
+ if (_hasStorageEvents()) {
4085
+ _storageListener = _onStorageEvent;
4086
+ window.addEventListener("storage", _storageListener);
4087
+ _installed = true;
4088
+ if (!_hasBroadcastChannel() && exports.DEV) {
4089
+ message_default(`memorio broadcast: using storage event fallback (targets="${_targets}")`);
4090
+ }
4091
+ }
4092
+ if (!_installed) {
4093
+ console.warn("[memorio broadcast] Neither BroadcastChannel nor storage events are available in this environment.");
4094
+ }
4095
+ }, "install"),
4096
+ uninstall: /* @__PURE__ */ __name(() => {
4097
+ if (_channel) {
4098
+ _channel.removeEventListener("message", _onBroadcastMessage);
4099
+ _channel.close();
4100
+ _channel = null;
4101
+ }
4102
+ if (_storageListener && typeof window !== "undefined") {
4103
+ window.removeEventListener("storage", _storageListener);
4104
+ _storageListener = null;
4105
+ }
4106
+ _restoreDispatchSet();
4107
+ _installed = false;
4108
+ }, "uninstall"),
4109
+ isInstalled: /* @__PURE__ */ __name(() => _installed, "isInstalled"),
4110
+ broadcast: /* @__PURE__ */ __name((msg) => {
4111
+ if (!_channel) return;
4112
+ _channel.postMessage({ ...msg, timestamp: Date.now() });
4113
+ }, "broadcast")
4114
+ };
4115
+
4116
+ // functions/security/index.ts
4117
+ init_cjs_shims();
4118
+ init_env();
4119
+ function _safeRandomUUID() {
4120
+ const g3 = globalThis;
4121
+ if (typeof g3.crypto !== "undefined" && typeof g3.crypto.randomUUID === "function") {
4122
+ try {
4123
+ return g3.crypto.randomUUID();
4124
+ } catch {
4125
+ }
4126
+ }
4127
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
4128
+ }
4129
+ __name(_safeRandomUUID, "_safeRandomUUID");
4130
+ var REGEX_TIMEOUT_MS = 100;
4131
+ function _safeRegexTest(pattern, key) {
4132
+ if (/\(.*[+*?].*.*\)[+*?]/.test(pattern)) {
4133
+ if (exports.DEV) console.warn(`[memorio security] Potentially dangerous regex blocked: ${pattern}`);
4134
+ return false;
4135
+ }
4136
+ if (pattern.length > 500) {
4137
+ if (exports.DEV) console.warn("[memorio security] Regex pattern exceeds max length (500)");
4138
+ return false;
4139
+ }
4140
+ const startTime = Date.now();
4141
+ try {
4142
+ const regex = new RegExp(pattern);
4143
+ const result = regex.test(key);
4144
+ const elapsed = Date.now() - startTime;
4145
+ if (elapsed > REGEX_TIMEOUT_MS) {
4146
+ if (exports.DEV) console.warn(`[memorio security] Slow regex detected (${elapsed}ms): ${pattern}`);
4147
+ }
4148
+ return result;
4149
+ } catch {
4150
+ return false;
4151
+ }
4152
+ }
4153
+ __name(_safeRegexTest, "_safeRegexTest");
4154
+ function addAccessRule(rules, pattern, perms) {
4155
+ const key = pattern instanceof RegExp ? pattern.source : pattern;
4156
+ rules.set(key, perms);
4157
+ return rules;
4158
+ }
4159
+ __name(addAccessRule, "addAccessRule");
4160
+ function hasPermission(rules, key, action, userId) {
4161
+ if (rules.size === 0) return true;
4162
+ for (const [pattern, perms] of rules) {
4163
+ let matches;
4164
+ if (typeof pattern === "function") {
4165
+ try {
4166
+ matches = pattern(key, userId);
4167
+ } catch {
4168
+ matches = false;
4169
+ }
4170
+ } else {
4171
+ matches = _safeRegexTest(pattern, key);
4172
+ }
4173
+ if (matches) {
4174
+ const allowed = perms.includes(action) || perms.includes("admin");
4175
+ if (!allowed) {
4176
+ logAudit({
4177
+ action,
4178
+ key,
4179
+ userId,
4180
+ success: false,
4181
+ error: "RBAC Denied: insufficient permissions"
4182
+ });
4183
+ }
4184
+ return allowed;
4185
+ }
4186
+ }
4187
+ logAudit({
4188
+ action: "permission_check",
4189
+ key,
4190
+ userId,
4191
+ success: false,
4192
+ error: "RBAC Denied: no matching rule"
4193
+ });
4194
+ return false;
4195
+ }
4196
+ __name(hasPermission, "hasPermission");
4197
+ var _auditLogger = null;
4198
+ function isAuditActive() {
4199
+ return _auditLogger !== null;
4200
+ }
4201
+ __name(isAuditActive, "isAuditActive");
4202
+ function setAuditLogger(logger3) {
4203
+ _auditLogger = logger3;
4204
+ }
4205
+ __name(setAuditLogger, "setAuditLogger");
4206
+ function logAudit(entry) {
4207
+ if (!_auditLogger) return;
4208
+ _auditLogger({
4209
+ timestamp: Date.now(),
4210
+ success: true,
4211
+ ...entry
4212
+ });
4213
+ }
4214
+ __name(logAudit, "logAudit");
4215
+ function sanitizeValue(value) {
4216
+ if (typeof value === "string") {
4217
+ let decoded = value.replace(/&#[xX]?[0-9a-fA-F]+;?/g, (match) => {
4218
+ const hexMatch = match.match(/&#x([0-9a-fA-F]+);?/i);
4219
+ if (hexMatch && hexMatch[1]) {
4220
+ return String.fromCharCode(parseInt(hexMatch[1], 16));
4221
+ }
4222
+ const decMatch = match.match(/&#([0-9]+);?/);
4223
+ if (decMatch && decMatch[1]) {
4224
+ return String.fromCharCode(parseInt(decMatch[1], 10));
4225
+ }
4226
+ return match;
4227
+ });
4228
+ try {
4229
+ decoded = decodeURIComponent(decoded);
4230
+ } catch {
2630
4231
  }
2631
- return () => {
2632
- unsubs.forEach(({ path, off }) => {
2633
- off();
2634
- message_default(`useObserver: Stopped monitoring "${path}"`);
2635
- });
2636
- };
2637
- } catch (err) {
2638
- message_default(`useObserver Error: ${err}`);
2639
- return () => {
2640
- };
4232
+ decoded = decoded.replace(/(javascript|vbscript|data:text\/html|about:blank|chrome:)/gi, "[SEC-REMOVED]");
4233
+ return decoded.replace(/<script\b[^>]*>[\s\S]*?<\s*\/\s*script\b[^>]*>/gi, "[SEC-REMOVED]").replace(/on\w+\s*=/gi, "[SEC-REMOVED]=").replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, "[SEC-REMOVED]").replace(/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi, "[SEC-REMOVED]").replace(/<embed\b[^>]*>/gi, "[SEC-REMOVED]").replace(/<svg\b[^<]*(?:(?!<\/svg>)<[^<]*)*<\/svg>/gi, "[SEC-REMOVED]").replace(/<form\b[^<]*(?:(?!<\/form>)<[^<]*)*<\/form>/gi, "[SEC-REMOVED]").replace(/<base\b[^<]*(?:(?!<\/base>)<[^<]*)*<\/base>/gi, "[SEC-REMOVED]").replace(/<link\b[^<]*(?:(?!<\/link>)<[^<]*)*<\/link>/gi, "[SEC-REMOVED]").replace(/<meta\b[^<]*(?:(?!<\/meta>)<[^<]*)*<\/meta>/gi, "[SEC-REMOVED]").replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, "[SEC-REMOVED]");
4234
+ }
4235
+ if (value && typeof value === "object" && !Array.isArray(value)) {
4236
+ const ctor = value.constructor?.name;
4237
+ if (ctor === "Object" || ctor === void 0) {
4238
+ const sanitized = {};
4239
+ for (const [k, v] of Object.entries(value)) {
4240
+ if (k === "__proto__" || k === "constructor" || k === "prototype") continue;
4241
+ sanitized[k] = sanitizeValue(v);
4242
+ }
4243
+ return sanitized;
4244
+ }
4245
+ return value;
2641
4246
  }
2642
- }), "useObserver");
2643
- if (exports.DEV && !("useObserver" in globalThis)) {
2644
- if (!globalThis.useObserver) globalThis.useObserver = null;
2645
- Object.defineProperty(
2646
- globalThis,
2647
- "useObserver",
2648
- {
2649
- value: useObserver,
2650
- writable: true,
2651
- enumerable: false,
2652
- configurable: true
4247
+ if (Array.isArray(value)) {
4248
+ return value.map((v) => sanitizeValue(v));
4249
+ }
4250
+ return value;
4251
+ }
4252
+ __name(sanitizeValue, "sanitizeValue");
4253
+ function validateKey(key) {
4254
+ return /^[a-zA-Z0-9_.-]+$/.test(key) && key.length <= 256 && key.length > 0;
4255
+ }
4256
+ __name(validateKey, "validateKey");
4257
+ function recordConsent(consents, userId, purpose, granted) {
4258
+ const record = {
4259
+ id: _safeRandomUUID(),
4260
+ purpose,
4261
+ granted,
4262
+ timestamp: Date.now()
4263
+ };
4264
+ const user = consents.get(userId) || [];
4265
+ user.push(record);
4266
+ consents.set(userId, user);
4267
+ return record;
4268
+ }
4269
+ __name(recordConsent, "recordConsent");
4270
+ function hasConsent(consents, userId, purpose) {
4271
+ const userConsents = consents.get(userId);
4272
+ if (!userConsents) return false;
4273
+ for (let i = userConsents.length - 1; i >= 0; i--) {
4274
+ const record = userConsents[i];
4275
+ if (record && record.purpose === purpose) {
4276
+ return record.granted;
2653
4277
  }
2654
- );
2655
- Object.freeze(globalThis.useObserver);
4278
+ }
4279
+ return false;
4280
+ }
4281
+ __name(hasConsent, "hasConsent");
4282
+ function revokeConsent(consents, userId, purpose) {
4283
+ return recordConsent(consents, userId, purpose, false);
4284
+ }
4285
+ __name(revokeConsent, "revokeConsent");
4286
+ function getConsents(consents, userId) {
4287
+ return consents.get(userId) || [];
4288
+ }
4289
+ __name(getConsents, "getConsents");
4290
+ function exportUserData(consents, userId) {
4291
+ return {
4292
+ userId,
4293
+ exportedAt: Date.now(),
4294
+ consents: consents.get(userId) || []
4295
+ };
2656
4296
  }
4297
+ __name(exportUserData, "exportUserData");
4298
+ function deleteUserData(consents, userId) {
4299
+ const count = consents.get(userId)?.length || 0;
4300
+ consents.delete(userId);
4301
+ return { success: true, deletedConsents: count };
4302
+ }
4303
+ __name(deleteUserData, "deleteUserData");
4304
+ var security = {
4305
+ // Re-exports for convenience
4306
+ safeRandomUUID: _safeRandomUUID,
4307
+ safeRegexTest: _safeRegexTest,
4308
+ // RBAC
4309
+ addAccessRule,
4310
+ hasPermission,
4311
+ // Audit logging
4312
+ isAuditActive,
4313
+ setAuditLogger,
4314
+ logAudit,
4315
+ // Input sanitization
4316
+ sanitizeValue,
4317
+ validateKey,
4318
+ // Consent management
4319
+ recordConsent,
4320
+ hasConsent,
4321
+ revokeConsent,
4322
+ getConsents,
4323
+ exportUserData,
4324
+ deleteUserData
4325
+ };
2657
4326
 
2658
4327
  // index.ts
2659
4328
  init_message();
@@ -2711,439 +4380,67 @@ var log = /* @__PURE__ */ __name((module, action, path, value, previousValue) =>
2711
4380
  );
2712
4381
  if (value !== void 0) {
2713
4382
  message_default(` \u2192 value:${value}`);
2714
- }
2715
- if (previousValue !== void 0) {
2716
- message_default(` \u2190 previous:${previousValue}`);
2717
- }
2718
- }
2719
- if (config.customHandler) {
2720
- config.customHandler(entry);
2721
- }
2722
- }, "log");
2723
- var getModuleColor = /* @__PURE__ */ __name((module) => {
2724
- const colors = {
2725
- state: "#4CAF50",
2726
- store: "#2196F3",
2727
- session: "#FF9800",
2728
- cache: "#9C27B0",
2729
- idb: "#F44336"
2730
- };
2731
- return colors[module] || "#888888";
2732
- }, "getModuleColor");
2733
- var getHistory = /* @__PURE__ */ __name(() => {
2734
- return [...logHistory];
2735
- }, "getHistory");
2736
- var clearHistory = /* @__PURE__ */ __name(() => {
2737
- logHistory.length = 0;
2738
- }, "clearHistory");
2739
- var getStats = /* @__PURE__ */ __name(() => {
2740
- const stats2 = {
2741
- total: logHistory.length,
2742
- state: 0,
2743
- store: 0,
2744
- session: 0,
2745
- cache: 0,
2746
- idb: 0,
2747
- set: 0,
2748
- get: 0,
2749
- delete: 0,
2750
- clear: 0
2751
- };
2752
- for (const entry of logHistory) {
2753
- if (entry) {
2754
- const module = entry.module;
2755
- const action = entry.action;
2756
- if (module && typeof stats2[module] === "number") stats2[module]++;
2757
- if (action && typeof stats2[action] === "number") stats2[action]++;
2758
- }
2759
- }
2760
- return stats2;
2761
- }, "getStats");
2762
- var exportLogs = /* @__PURE__ */ __name(() => {
2763
- return JSON.stringify(logHistory, null, 2);
2764
- }, "exportLogs");
2765
- var logger = {
2766
- configure,
2767
- enable,
2768
- disable,
2769
- isEnabled,
2770
- log,
2771
- getHistory,
2772
- clearHistory,
2773
- getStats,
2774
- exportLogs
2775
- };
2776
-
2777
- // functions/devtools/index.ts
2778
- init_cjs_shims();
2779
- init_internal();
2780
- init_env();
2781
- var _state = globalThis.__memorio_state_instance__;
2782
- var _store = globalThis.__memorio_store_instance__;
2783
- var _session = globalThis.__memorio_session_instance__;
2784
- var _cache = globalThis.__memorio_cache_instance__;
2785
- function isDebugEnabled2() {
2786
- return exports.DEV && exports.internal.debug === true;
2787
- }
2788
- __name(isDebugEnabled2, "isDebugEnabled");
2789
- function extractStoreData() {
2790
- if (!_store) return {};
2791
- const result = {};
2792
- const store2 = _store;
2793
- if (typeof store2.list === "function") {
2794
- try {
2795
- return store2.list();
2796
- } catch {
2797
- }
2798
- }
2799
- if (typeof store2.get === "function") {
2800
- for (const key of Object.keys(store2)) {
2801
- if (!["get", "set", "remove", "delete", "removeAll", "clearAll", "size", "isPersistent", "list"].includes(key)) {
2802
- try {
2803
- const val = store2.get(key);
2804
- if (val !== null && val !== void 0) {
2805
- result[key] = val;
2806
- }
2807
- } catch {
2808
- }
2809
- }
2810
- }
2811
- }
2812
- return result;
2813
- }
2814
- __name(extractStoreData, "extractStoreData");
2815
- function extractSessionData() {
2816
- if (!_session) return {};
2817
- const result = {};
2818
- const session2 = _session;
2819
- if (typeof session2.list === "function") {
2820
- try {
2821
- return session2.list();
2822
- } catch {
2823
- }
2824
- }
2825
- if (typeof session2.get === "function") {
2826
- for (const key of Object.keys(session2)) {
2827
- if (!["get", "set", "remove", "delete", "removeAll", "clearAll", "size", "isPersistent", "list"].includes(key)) {
2828
- try {
2829
- const val = session2.get(key);
2830
- if (val !== null && val !== void 0) {
2831
- result[key] = val;
2832
- }
2833
- } catch {
2834
- }
2835
- }
2836
- }
2837
- }
2838
- return result;
2839
- }
2840
- __name(extractSessionData, "extractSessionData");
2841
- var inspect = /* @__PURE__ */ __name(() => {
2842
- if (!isDebugEnabled2()) return;
2843
- if (_state) {
2844
- const stateList = _state.list;
2845
- let stateData;
2846
- if (typeof stateList === "function") {
2847
- stateData = stateList();
2848
- } else if (typeof stateList === "object" && stateList !== null) {
2849
- stateData = stateList;
2850
- } else {
2851
- stateData = _state;
2852
- }
2853
- console.table(stateData);
2854
- }
2855
- if (_store) {
2856
- console.table(extractStoreData());
2857
- }
2858
- if (_session) {
2859
- console.table(extractSessionData());
2860
- }
2861
- if (_cache) {
2862
- const cacheList = _cache.list;
2863
- let cacheData2;
2864
- if (typeof cacheList === "function") {
2865
- cacheData2 = cacheList();
2866
- } else if (typeof cacheList === "object" && cacheList !== null) {
2867
- cacheData2 = cacheList;
2868
- } else {
2869
- cacheData2 = _cache;
2870
- }
2871
- console.table(cacheData2);
2872
- }
2873
- }, "inspect");
2874
- var stats = /* @__PURE__ */ __name(() => {
2875
- const getKeys = /* @__PURE__ */ __name((obj) => {
2876
- if (!obj) return 0;
2877
- if (typeof obj.list === "function") {
2878
- try {
2879
- const list = obj.list();
2880
- return Object.keys(list).length;
2881
- } catch {
2882
- }
2883
- }
2884
- return Object.keys(obj).length;
2885
- }, "getKeys");
2886
- return {
2887
- stateKeys: getKeys(_state),
2888
- storeKeys: getKeys(_store),
2889
- sessionKeys: getKeys(_session),
2890
- cacheKeys: getKeys(_cache),
2891
- idbDatabases: 0,
2892
- sqliteDbCount: 0,
2893
- lastUpdate: (/* @__PURE__ */ new Date()).toISOString()
2894
- };
2895
- }, "stats");
2896
- var clear = /* @__PURE__ */ __name((moduleName) => {
2897
- const targets = { state: _state, store: _store, session: _session, cache: _cache };
2898
- const target = targets[moduleName];
2899
- if (target && typeof target.clear === "function") {
2900
- target.clear();
2901
- } else if (target && typeof target.removeAll === "function") {
2902
- target.removeAll();
2903
- } else {
2904
- console.debug(`Module ${moduleName} not found or does not support clear()/removeAll()`);
2905
- }
2906
- }, "clear");
2907
- var clearAll = /* @__PURE__ */ __name(() => {
2908
- clear("state");
2909
- clear("store");
2910
- clear("session");
2911
- clear("cache");
2912
- }, "clearAll");
2913
- var exportData = /* @__PURE__ */ __name(() => {
2914
- const getStateData = /* @__PURE__ */ __name(() => {
2915
- if (!_state) return void 0;
2916
- try {
2917
- if (typeof _state.list === "function") {
2918
- return _state.list();
2919
- }
2920
- return _state;
2921
- } catch {
2922
- return void 0;
2923
- }
2924
- }, "getStateData");
2925
- const getStoreData = /* @__PURE__ */ __name(() => {
2926
- return extractStoreData();
2927
- }, "getStoreData");
2928
- const getSessionData = /* @__PURE__ */ __name(() => {
2929
- return extractSessionData();
2930
- }, "getSessionData");
2931
- const getCacheData = /* @__PURE__ */ __name(() => {
2932
- if (!_cache) return void 0;
2933
- try {
2934
- if (typeof _cache.list === "function") {
2935
- return _cache.list();
2936
- }
2937
- return _cache;
2938
- } catch {
2939
- return void 0;
2940
- }
2941
- }, "getCacheData");
2942
- const data = {
2943
- state: getStateData(),
2944
- store: getStoreData(),
2945
- session: getSessionData(),
2946
- cache: getCacheData(),
2947
- exportedAt: (/* @__PURE__ */ new Date()).toISOString()
2948
- };
2949
- return JSON.stringify(data, null, 2);
2950
- }, "exportData");
2951
- var importData = /* @__PURE__ */ __name((jsonString) => {
2952
- try {
2953
- const data = JSON.parse(jsonString);
2954
- if (data.state) {
2955
- Object.entries(data.state).forEach(([key, value]) => {
2956
- if (_state && key !== "list" && key !== "remove" && key !== "removeAll") {
2957
- ;
2958
- _state[key] = value;
2959
- }
2960
- });
2961
- }
2962
- if (data.store && _store && typeof _store.set === "function") {
2963
- Object.entries(data.store).forEach(([key, value]) => {
2964
- ;
2965
- _store.set(key, value);
2966
- });
2967
- }
2968
- if (data.session && _session && typeof _session.set === "function") {
2969
- Object.entries(data.session).forEach(([key, value]) => {
2970
- ;
2971
- _session.set(key, value);
2972
- });
2973
- }
2974
- if (data.cache && _cache) {
2975
- Object.entries(data.cache).forEach(([key, value]) => {
2976
- if (_cache && key !== "get" && key !== "set" && key !== "remove" && key !== "clear") {
2977
- ;
2978
- _cache[key] = value;
2979
- }
2980
- });
2981
- }
2982
- } catch (error) {
2983
- console.debug("Import failed:", error);
2984
- }
2985
- }, "importData");
2986
- var watch = /* @__PURE__ */ __name((moduleName, path) => {
2987
- const targets = { state: _state, store: _store, session: _session, cache: _cache };
2988
- const target = targets[moduleName];
2989
- if (!target) {
2990
- console.debug(`Module ${moduleName} not found`);
2991
- return;
2992
- }
2993
- const initialValue = target[path];
2994
- console.debug(`Watching ${moduleName}.${path} (initial: ${JSON.stringify(initialValue)})`);
2995
- if (moduleName === "state" && globalThis.memorio?.dispatch) {
2996
- const handler = /* @__PURE__ */ __name((e) => {
2997
- const detail = e.detail;
2998
- if (detail?.name?.includes(path)) {
2999
- console.debug(`Change: ${moduleName}.${path} =`, e.detail.value);
3000
- }
3001
- }, "handler");
3002
- target.addEventListener?.("memorio-change", handler);
3003
- }
3004
- }, "watch");
3005
- var help = /* @__PURE__ */ __name(() => {
3006
- console.debug(`
3007
- Memorio DevTools Help
3008
-
3009
- Available commands:
3010
- memorio.devtools.inspect() - Inspect all state modules
3011
- memorio.devtools.stats() - Show statistics
3012
- memorio.devtools.clear('module') - Clear specific module
3013
- memorio.devtools.clearAll() - Clear all modules
3014
- memorio.devtools.exportData() - Export all data as JSON
3015
- memorio.devtools.importData(json) - Import data from JSON
3016
- memorio.devtools.watch(module, path) - Watch a path for changes
3017
- memorio.devtools.help() - Show this help
3018
-
3019
- Shortcuts (dev only):
3020
- state - global state proxy
3021
- store - localStorage wrapper
3022
- session - sessionStorage wrapper
3023
- cache - in-memory cache
3024
- `);
3025
- }, "help");
3026
- var devtools = {
3027
- inspect,
3028
- stats,
3029
- clear,
3030
- clearAll,
3031
- exportData,
3032
- importData,
3033
- watch,
3034
- help
3035
- };
3036
-
3037
- // core/hlc.ts
3038
- init_cjs_shims();
3039
- var NODE_ID_KEY = "__memorio_hlc_node";
3040
- function getNodeId() {
3041
- if (typeof globalThis === "undefined") return "node";
3042
- try {
3043
- if (typeof sessionStorage !== "undefined" && sessionStorage) {
3044
- let id = sessionStorage.getItem(NODE_ID_KEY);
3045
- if (!id) {
3046
- id = generateNodeId();
3047
- sessionStorage.setItem(NODE_ID_KEY, id);
3048
- }
3049
- return id;
3050
- }
3051
- } catch {
3052
- }
3053
- if (!globalThis.__memorioHlcNodeId) {
3054
- globalThis.__memorioHlcNodeId = generateNodeId();
3055
- }
3056
- return globalThis.__memorioHlcNodeId;
3057
- }
3058
- __name(getNodeId, "getNodeId");
3059
- function generateNodeId() {
3060
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
3061
- return crypto.randomUUID().slice(0, 8);
3062
- }
3063
- return Math.random().toString(36).slice(2, 10);
3064
- }
3065
- __name(generateNodeId, "generateNodeId");
3066
- var HLC_KEY = "__memorio_hlc_local";
3067
- var local = globalThis[HLC_KEY] || {
3068
- physical: 0,
3069
- logical: 0,
3070
- node: getNodeId()
3071
- };
3072
- if (!globalThis[HLC_KEY]) {
3073
- globalThis[HLC_KEY] = local;
3074
- }
3075
- function tick(_incoming) {
3076
- const now2 = Date.now();
3077
- const base = local.physical;
3078
- let physical;
3079
- let logical;
3080
- if (now2 > base) {
3081
- physical = now2;
3082
- logical = 0;
3083
- } else if (now2 < base) {
3084
- physical = base;
3085
- logical = local.logical + 1;
3086
- } else {
3087
- physical = base;
3088
- logical = local.logical + 1;
3089
- }
3090
- local.physical = physical;
3091
- local.logical = logical;
3092
- return { physical, logical, node: local.node };
3093
- }
3094
- __name(tick, "tick");
3095
- function receive(remote) {
3096
- const now2 = Date.now();
3097
- if (remote.physical > local.physical) {
3098
- local.physical = remote.physical > now2 ? remote.physical : now2;
3099
- local.logical = 1;
3100
- } else if (remote.physical === local.physical) {
3101
- local.logical = Math.max(local.logical, remote.logical) + 1;
3102
- }
3103
- local.node = getNodeId();
3104
- return { ...local };
3105
- }
3106
- __name(receive, "receive");
3107
- function compare(a, b) {
3108
- if (a.physical !== b.physical) {
3109
- return a.physical < b.physical ? -1 : 1;
4383
+ }
4384
+ if (previousValue !== void 0) {
4385
+ message_default(` \u2190 previous:${previousValue}`);
4386
+ }
3110
4387
  }
3111
- if (a.logical !== b.logical) {
3112
- return a.logical < b.logical ? -1 : 1;
4388
+ if (config.customHandler) {
4389
+ config.customHandler(entry);
3113
4390
  }
3114
- if (a.node !== b.node) {
3115
- return a.node < b.node ? -1 : 1;
4391
+ }, "log");
4392
+ var getModuleColor = /* @__PURE__ */ __name((module) => {
4393
+ const colors = {
4394
+ state: "#4CAF50",
4395
+ store: "#2196F3",
4396
+ session: "#FF9800",
4397
+ cache: "#9C27B0",
4398
+ idb: "#F44336"
4399
+ };
4400
+ return colors[module] || "#888888";
4401
+ }, "getModuleColor");
4402
+ var getHistory = /* @__PURE__ */ __name(() => {
4403
+ return [...logHistory];
4404
+ }, "getHistory");
4405
+ var clearHistory = /* @__PURE__ */ __name(() => {
4406
+ logHistory.length = 0;
4407
+ }, "clearHistory");
4408
+ var getStats = /* @__PURE__ */ __name(() => {
4409
+ const stats = {
4410
+ total: logHistory.length,
4411
+ state: 0,
4412
+ store: 0,
4413
+ session: 0,
4414
+ cache: 0,
4415
+ idb: 0,
4416
+ set: 0,
4417
+ get: 0,
4418
+ delete: 0,
4419
+ clear: 0
4420
+ };
4421
+ for (const entry of logHistory) {
4422
+ if (entry) {
4423
+ const module = entry.module;
4424
+ const action = entry.action;
4425
+ if (module && typeof stats[module] === "number") stats[module]++;
4426
+ if (action && typeof stats[action] === "number") stats[action]++;
4427
+ }
3116
4428
  }
3117
- return 0;
3118
- }
3119
- __name(compare, "compare");
3120
- function happenedBefore(a, b) {
3121
- return compare(a, b) < 0;
3122
- }
3123
- __name(happenedBefore, "happenedBefore");
3124
- function serialize(hlc2) {
3125
- return `hlc:${hlc2.physical}:${hlc2.logical}:${hlc2.node}`;
3126
- }
3127
- __name(serialize, "serialize");
3128
- function parse(serialized) {
3129
- if (!serialized.startsWith("hlc:")) return null;
3130
- const parts = serialized.split(":");
3131
- if (parts.length !== 4) return null;
3132
- const physical = parseInt(parts[1], 10);
3133
- const logical = parseInt(parts[2], 10);
3134
- const node = parts[3];
3135
- if (isNaN(physical) || isNaN(logical)) return null;
3136
- return { physical, logical, node };
3137
- }
3138
- __name(parse, "parse");
3139
- var hlc = {
3140
- tick,
3141
- receive,
3142
- compare,
3143
- happenedBefore,
3144
- serialize,
3145
- parse,
3146
- getNodeId
4429
+ return stats;
4430
+ }, "getStats");
4431
+ var exportLogs = /* @__PURE__ */ __name(() => {
4432
+ return JSON.stringify(logHistory, null, 2);
4433
+ }, "exportLogs");
4434
+ var logger = {
4435
+ configure,
4436
+ enable,
4437
+ disable,
4438
+ isEnabled,
4439
+ log,
4440
+ getHistory,
4441
+ clearHistory,
4442
+ getStats,
4443
+ exportLogs
3147
4444
  };
3148
4445
 
3149
4446
  // core/fractional.ts
@@ -3307,214 +4604,53 @@ function reindex(items) {
3307
4604
  if (prev === null) {
3308
4605
  newItem.key = before(items[0].key);
3309
4606
  } else if (next === null) {
3310
- newItem.key = after(prev);
3311
- } else {
3312
- newItem.key = between(prev, next);
3313
- }
3314
- result.push(newItem);
3315
- prev = newItem.key;
3316
- }
3317
- return result;
3318
- }
3319
- __name(reindex, "reindex");
3320
- var fractional = {
3321
- generateBetween,
3322
- firstKey,
3323
- after,
3324
- before,
3325
- between,
3326
- reorder,
3327
- reindex
3328
- };
3329
-
3330
- // index.ts
3331
- init_internal();
3332
- init_platform();
3333
-
3334
- // core/global.ts
3335
- init_cjs_shims();
3336
- init_platform();
3337
- init_internal();
3338
-
3339
- // package.json
3340
- var package_default = {
3341
- version: "4.9.35"};
3342
-
3343
- // core/global.ts
3344
- init_env();
3345
- init_store();
3346
- init_idb();
3347
- init_sqlite();
3348
- init_message();
3349
-
3350
- // functions/typed/index.ts
3351
- init_cjs_shims();
3352
- function typed() {
3353
- return exports.state;
3354
- }
3355
- __name(typed, "typed");
3356
-
3357
- // functions/history/index.ts
3358
- init_cjs_shims();
3359
- init_internal();
3360
- init_env();
3361
- init_message();
3362
- function _clone(value) {
3363
- if (value === null || typeof value !== "object") return value;
3364
- try {
3365
- return deepRaw(value, /* @__PURE__ */ new WeakSet());
3366
- } catch (err) {
3367
- if (exports.DEV) console.warn("[memorio history] deep clone failed:", err);
3368
- return value;
3369
- }
3370
- }
3371
- __name(_clone, "_clone");
3372
- var snapshot = /* @__PURE__ */ __name(() => {
3373
- return deepRaw(exports.state, /* @__PURE__ */ new WeakSet());
3374
- }, "snapshot");
3375
- var diff = /* @__PURE__ */ __name((snap) => {
3376
- const changes = [];
3377
- const _walk = /* @__PURE__ */ __name((oldObj, newObj, prefix) => {
3378
- const oldKeys = oldObj ? Object.keys(oldObj) : [];
3379
- const newKeys = newObj ? Object.keys(newObj) : [];
3380
- for (const key of newKeys) {
3381
- const newPath = prefix ? `${prefix}.${key}` : key;
3382
- const oldVal = oldObj ? oldObj[key] : void 0;
3383
- const newVal = newObj[key];
3384
- if (oldVal !== newVal) {
3385
- const oldType = typeof oldVal;
3386
- const newType = typeof newVal;
3387
- if (oldType !== newType || oldVal === void 0) {
3388
- changes.push({ path: newPath, oldValue: oldVal, newValue: newVal });
3389
- } else if (oldVal && typeof oldVal === "object") {
3390
- _walk(oldVal, newVal, newPath);
3391
- } else if (oldVal !== newVal) {
3392
- changes.push({ path: newPath, oldValue: oldVal, newValue: newVal });
3393
- }
3394
- }
3395
- }
3396
- for (const key of oldKeys) {
3397
- if (!(key in (newObj || {}))) {
3398
- const newPath = prefix ? `${prefix}.${key}` : key;
3399
- changes.push({ path: newPath, oldValue: oldObj[key], newValue: void 0 });
3400
- }
3401
- }
3402
- }, "_walk");
3403
- _walk(snap, deepRaw(exports.state), "");
3404
- return changes;
3405
- }, "diff");
3406
- var enableHistory = /* @__PURE__ */ __name((enabled = true) => {
3407
- exports.internal.historyEnabled = enabled;
3408
- message_default(`[memorio history] Tracking ${enabled ? "enabled" : "disabled"}`);
3409
- }, "enableHistory");
3410
- var trace = /* @__PURE__ */ __name(() => {
3411
- return [...exports.internal.mutations];
3412
- }, "trace");
3413
- var canUndo = /* @__PURE__ */ __name(() => {
3414
- return exports.internal.canUndo();
3415
- }, "canUndo");
3416
- var canRedo = /* @__PURE__ */ __name(() => {
3417
- return exports.internal.canRedo();
3418
- }, "canRedo");
3419
- var undo = /* @__PURE__ */ __name(() => {
3420
- if (!exports.internal.historyEnabled) {
3421
- message_default("[memorio history] History is not enabled");
3422
- return void 0;
3423
- }
3424
- const record = exports.internal.popUndo();
3425
- if (!record) return void 0;
3426
- _applyInverse(record);
3427
- message_default(`[memorio history] Undid: ${record.action} ${record.path}`);
3428
- return record;
3429
- }, "undo");
3430
- var redo = /* @__PURE__ */ __name(() => {
3431
- if (!exports.internal.historyEnabled) {
3432
- message_default("[memorio history] History is not enabled");
3433
- return void 0;
3434
- }
3435
- const record = exports.internal.popRedo();
3436
- if (!record) return void 0;
3437
- _applyForward(record);
3438
- message_default(`[memorio history] Redid: ${record.action} ${record.path}`);
3439
- return record;
3440
- }, "redo");
3441
- function _applyInverse(record) {
3442
- const wasEnabled = exports.internal.historyEnabled;
3443
- exports.internal.historyEnabled = false;
3444
- try {
3445
- if (record.action === "set") {
3446
- if (record.previousValue === void 0) {
3447
- _deletePath(record.path);
3448
- } else {
3449
- _setPath(record.path, record.previousValue);
3450
- }
3451
- } else if (record.action === "delete") {
3452
- if (record.previousValue !== void 0) {
3453
- _setPath(record.path, record.previousValue);
3454
- }
3455
- }
3456
- } finally {
3457
- exports.internal.historyEnabled = wasEnabled;
3458
- }
3459
- }
3460
- __name(_applyInverse, "_applyInverse");
3461
- function _applyForward(record) {
3462
- const wasEnabled = exports.internal.historyEnabled;
3463
- exports.internal.historyEnabled = false;
3464
- try {
3465
- if (record.action === "set") {
3466
- _setPath(record.path, record.newValue);
3467
- } else if (record.action === "delete") {
3468
- _deletePath(record.path);
3469
- }
3470
- } finally {
3471
- exports.internal.historyEnabled = wasEnabled;
3472
- }
3473
- }
3474
- __name(_applyForward, "_applyForward");
3475
- function _setPath(path, value) {
3476
- const parts = path.split(".");
3477
- let current = exports.state;
3478
- for (let i = 0; i < parts.length - 1; i++) {
3479
- const part = parts[i];
3480
- if (current[part] === void 0) {
3481
- current[part] = {};
4607
+ newItem.key = after(prev);
4608
+ } else {
4609
+ newItem.key = between(prev, next);
3482
4610
  }
3483
- current = current[part];
4611
+ result.push(newItem);
4612
+ prev = newItem.key;
3484
4613
  }
3485
- current[parts[parts.length - 1]] = value;
4614
+ return result;
3486
4615
  }
3487
- __name(_setPath, "_setPath");
3488
- function _deletePath(path) {
3489
- const parts = path.split(".");
3490
- if (parts.length === 1) {
3491
- exports.state.remove(parts[0]);
3492
- return;
3493
- }
3494
- let current = exports.state;
3495
- for (let i = 0; i < parts.length - 1; i++) {
3496
- const part = parts[i];
3497
- if (current[part] === void 0) return;
3498
- current = current[part];
3499
- }
3500
- delete current[parts[parts.length - 1]];
4616
+ __name(reindex, "reindex");
4617
+ var fractional = {
4618
+ generateBetween,
4619
+ firstKey,
4620
+ after,
4621
+ before,
4622
+ between,
4623
+ reorder,
4624
+ reindex
4625
+ };
4626
+
4627
+ // index.ts
4628
+ init_internal();
4629
+ init_platform();
4630
+
4631
+ // core/global.ts
4632
+ init_cjs_shims();
4633
+ init_platform();
4634
+ init_internal();
4635
+
4636
+ // package.json
4637
+ var package_default = {
4638
+ version: "5.1.0"};
4639
+
4640
+ // core/global.ts
4641
+ init_env();
4642
+ init_store();
4643
+ init_idb();
4644
+ init_sqlite();
4645
+ init_encryption();
4646
+ init_message();
4647
+
4648
+ // functions/typed/index.ts
4649
+ init_cjs_shims();
4650
+ function typed() {
4651
+ return exports.state;
3501
4652
  }
3502
- __name(_deletePath, "_deletePath");
3503
- var rollback = /* @__PURE__ */ __name((snap) => {
3504
- exports.state.removeAll();
3505
- for (const key of Object.keys(snap)) {
3506
- exports.state[key] = _clone(snap[key]);
3507
- }
3508
- exports.internal.clearHistory();
3509
- message_default("[memorio history] State rolled back to snapshot");
3510
- }, "rollback");
3511
- var clearHistory2 = /* @__PURE__ */ __name(() => {
3512
- exports.internal.clearHistory();
3513
- message_default("[memorio history] History cleared");
3514
- }, "clearHistory");
3515
- var clearRedo = /* @__PURE__ */ __name(() => {
3516
- exports.internal.clearRedo();
3517
- }, "clearRedo");
4653
+ __name(typed, "typed");
3518
4654
 
3519
4655
  // functions/memory/index.ts
3520
4656
  init_cjs_shims();
@@ -4207,83 +5343,167 @@ var memory = {
4207
5343
  }
4208
5344
  };
4209
5345
 
4210
- // functions/inspect/index.ts
5346
+ // functions/history/index.ts
4211
5347
  init_cjs_shims();
5348
+ init_internal();
4212
5349
  init_env();
4213
- var stateKeys = /* @__PURE__ */ __name(() => {
4214
- const raw = deepRaw(exports.state);
4215
- return Object.keys(raw).filter(
4216
- (k) => !["list", "remove", "removeAll", "lock", "unlock"].includes(k)
4217
- );
4218
- }, "stateKeys");
4219
- var pathExists = /* @__PURE__ */ __name((path) => {
4220
- if (!path || typeof path !== "string") return false;
4221
- const parts = path.replace(/^state\./, "").split(".");
4222
- let current = exports.state;
4223
- for (const part of parts) {
4224
- if (current === null || current === void 0) {
4225
- return false;
4226
- }
4227
- current = current[part];
5350
+ init_message();
5351
+ function _clone(value) {
5352
+ if (value === null || typeof value !== "object") return value;
5353
+ try {
5354
+ return deepRaw(value, /* @__PURE__ */ new WeakSet());
5355
+ } catch (err) {
5356
+ if (exports.DEV) console.warn("[memorio history] deep clone failed:", err);
5357
+ return value;
4228
5358
  }
4229
- return current !== void 0;
4230
- }, "pathExists");
4231
- var stateType = /* @__PURE__ */ __name((path) => {
4232
- const [exists, value] = _getValue(path);
4233
- if (!exists || value === void 0) return "undefined";
4234
- return Array.isArray(value) ? "array" : typeof value;
4235
- }, "stateType");
4236
- var stateGet = /* @__PURE__ */ __name((path) => {
4237
- const [exists, value] = _getValue(path);
4238
- if (!exists || value === void 0) return void 0;
4239
- return _clone2(value);
4240
- }, "stateGet");
4241
- var stateSchema = /* @__PURE__ */ __name(() => {
4242
- const result = [];
4243
- const _walk = /* @__PURE__ */ __name((obj, prefix) => {
4244
- if (obj === null || typeof obj !== "object" || Array.isArray(obj)) {
4245
- return;
4246
- }
4247
- const keys = Object.keys(obj).filter(
4248
- (k) => !["list", "remove", "removeAll", "lock", "unlock"].includes(k)
4249
- );
4250
- for (const key of keys) {
5359
+ }
5360
+ __name(_clone, "_clone");
5361
+ var snapshot = /* @__PURE__ */ __name(() => {
5362
+ return deepRaw(exports.state, /* @__PURE__ */ new WeakSet());
5363
+ }, "snapshot");
5364
+ var diff = /* @__PURE__ */ __name((snap) => {
5365
+ const changes = [];
5366
+ const _walk = /* @__PURE__ */ __name((oldObj, newObj, prefix) => {
5367
+ const oldKeys = oldObj ? Object.keys(oldObj) : [];
5368
+ const newKeys = newObj ? Object.keys(newObj) : [];
5369
+ for (const key of newKeys) {
4251
5370
  const newPath = prefix ? `${prefix}.${key}` : key;
4252
- const value = obj[key];
4253
- const defined = value !== void 0;
4254
- const type = defined ? Array.isArray(value) ? "array" : typeof value : "undefined";
4255
- result.push({ path: newPath, type, defined });
4256
- if (defined && typeof value === "object" && !Array.isArray(value) && value.constructor?.name === "Object") {
4257
- _walk(value, newPath);
5371
+ const oldVal = oldObj ? oldObj[key] : void 0;
5372
+ const newVal = newObj[key];
5373
+ if (oldVal !== newVal) {
5374
+ const oldType = typeof oldVal;
5375
+ const newType = typeof newVal;
5376
+ if (oldType !== newType || oldVal === void 0) {
5377
+ changes.push({ path: newPath, oldValue: oldVal, newValue: newVal });
5378
+ } else if (oldVal && typeof oldVal === "object") {
5379
+ _walk(oldVal, newVal, newPath);
5380
+ } else if (oldVal !== newVal) {
5381
+ changes.push({ path: newPath, oldValue: oldVal, newValue: newVal });
5382
+ }
5383
+ }
5384
+ }
5385
+ for (const key of oldKeys) {
5386
+ if (!(key in (newObj || {}))) {
5387
+ const newPath = prefix ? `${prefix}.${key}` : key;
5388
+ changes.push({ path: newPath, oldValue: oldObj[key], newValue: void 0 });
4258
5389
  }
4259
5390
  }
4260
5391
  }, "_walk");
4261
- _walk(deepRaw(exports.state), "");
4262
- return result;
4263
- }, "stateSchema");
4264
- function _getValue(path) {
4265
- if (!path || typeof path !== "string") return [false, void 0];
4266
- const parts = path.replace(/^state\./, "").split(".");
5392
+ _walk(snap, deepRaw(exports.state), "");
5393
+ return changes;
5394
+ }, "diff");
5395
+ var enableHistory = /* @__PURE__ */ __name((enabled = true) => {
5396
+ exports.internal.historyEnabled = enabled;
5397
+ message_default(`[memorio history] Tracking ${enabled ? "enabled" : "disabled"}`);
5398
+ }, "enableHistory");
5399
+ var trace = /* @__PURE__ */ __name(() => {
5400
+ return [...exports.internal.mutations];
5401
+ }, "trace");
5402
+ var canUndo = /* @__PURE__ */ __name(() => {
5403
+ return exports.internal.canUndo();
5404
+ }, "canUndo");
5405
+ var canRedo = /* @__PURE__ */ __name(() => {
5406
+ return exports.internal.canRedo();
5407
+ }, "canRedo");
5408
+ var undo = /* @__PURE__ */ __name(() => {
5409
+ if (!exports.internal.historyEnabled) {
5410
+ message_default("[memorio history] History is not enabled");
5411
+ return void 0;
5412
+ }
5413
+ const record = exports.internal.popUndo();
5414
+ if (!record) return void 0;
5415
+ _applyInverse2(record);
5416
+ message_default(`[memorio history] Undid: ${record.action} ${record.path}`);
5417
+ return record;
5418
+ }, "undo");
5419
+ var redo = /* @__PURE__ */ __name(() => {
5420
+ if (!exports.internal.historyEnabled) {
5421
+ message_default("[memorio history] History is not enabled");
5422
+ return void 0;
5423
+ }
5424
+ const record = exports.internal.popRedo();
5425
+ if (!record) return void 0;
5426
+ _applyForward(record);
5427
+ message_default(`[memorio history] Redid: ${record.action} ${record.path}`);
5428
+ return record;
5429
+ }, "redo");
5430
+ function _applyInverse2(record) {
5431
+ const wasEnabled = exports.internal.historyEnabled;
5432
+ exports.internal.historyEnabled = false;
5433
+ try {
5434
+ if (record.action === "set") {
5435
+ if (record.previousValue === void 0) {
5436
+ _deletePath2(record.path);
5437
+ } else {
5438
+ _setPath2(record.path, record.previousValue);
5439
+ }
5440
+ } else if (record.action === "delete") {
5441
+ if (record.previousValue !== void 0) {
5442
+ _setPath2(record.path, record.previousValue);
5443
+ }
5444
+ }
5445
+ } finally {
5446
+ exports.internal.historyEnabled = wasEnabled;
5447
+ }
5448
+ }
5449
+ __name(_applyInverse2, "_applyInverse");
5450
+ function _applyForward(record) {
5451
+ const wasEnabled = exports.internal.historyEnabled;
5452
+ exports.internal.historyEnabled = false;
5453
+ try {
5454
+ if (record.action === "set") {
5455
+ _setPath2(record.path, record.newValue);
5456
+ } else if (record.action === "delete") {
5457
+ _deletePath2(record.path);
5458
+ }
5459
+ } finally {
5460
+ exports.internal.historyEnabled = wasEnabled;
5461
+ }
5462
+ }
5463
+ __name(_applyForward, "_applyForward");
5464
+ function _setPath2(path, value) {
5465
+ const parts = path.split(".");
4267
5466
  let current = exports.state;
4268
- for (const part of parts) {
4269
- if (current === null || current === void 0) {
4270
- return [false, void 0];
5467
+ for (let i = 0; i < parts.length - 1; i++) {
5468
+ const part = parts[i];
5469
+ if (current[part] === void 0) {
5470
+ current[part] = {};
4271
5471
  }
4272
5472
  current = current[part];
4273
5473
  }
4274
- return [current !== void 0, current];
5474
+ current[parts[parts.length - 1]] = value;
4275
5475
  }
4276
- __name(_getValue, "_getValue");
4277
- function _clone2(value) {
4278
- if (value === null || typeof value !== "object") return value;
4279
- try {
4280
- return deepRaw(value, /* @__PURE__ */ new WeakSet());
4281
- } catch (err) {
4282
- if (exports.DEV) console.warn("[memorio inspect] deep clone failed:", err);
4283
- return value;
5476
+ __name(_setPath2, "_setPath");
5477
+ function _deletePath2(path) {
5478
+ const parts = path.split(".");
5479
+ if (parts.length === 1) {
5480
+ exports.state.remove(parts[0]);
5481
+ return;
5482
+ }
5483
+ let current = exports.state;
5484
+ for (let i = 0; i < parts.length - 1; i++) {
5485
+ const part = parts[i];
5486
+ if (current[part] === void 0) return;
5487
+ current = current[part];
4284
5488
  }
5489
+ delete current[parts[parts.length - 1]];
4285
5490
  }
4286
- __name(_clone2, "_clone");
5491
+ __name(_deletePath2, "_deletePath");
5492
+ var rollback = /* @__PURE__ */ __name((snap) => {
5493
+ exports.state.removeAll();
5494
+ for (const key of Object.keys(snap)) {
5495
+ exports.state[key] = _clone(snap[key]);
5496
+ }
5497
+ exports.internal.clearHistory();
5498
+ message_default("[memorio history] State rolled back to snapshot");
5499
+ }, "rollback");
5500
+ var clearHistory2 = /* @__PURE__ */ __name(() => {
5501
+ exports.internal.clearHistory();
5502
+ message_default("[memorio history] History cleared");
5503
+ }, "clearHistory");
5504
+ var clearRedo = /* @__PURE__ */ __name(() => {
5505
+ exports.internal.clearRedo();
5506
+ }, "clearRedo");
4287
5507
 
4288
5508
  // core/global.ts
4289
5509
  if (!("memorio" in globalThis)) {
@@ -4318,6 +5538,26 @@ if (!("memorio" in globalThis)) {
4318
5538
  }
4319
5539
  );
4320
5540
  }
5541
+ if (typeof globalThis.addEventListener !== "function") {
5542
+ const listeners = {};
5543
+ globalThis.addEventListener = (name, cb) => {
5544
+ (listeners[name] = listeners[name] ?? []).push(cb);
5545
+ };
5546
+ globalThis.removeEventListener = (name, cb) => {
5547
+ const arr = listeners[name];
5548
+ if (arr) {
5549
+ const idx = arr.indexOf(cb);
5550
+ if (idx > -1) arr.splice(idx, 1);
5551
+ }
5552
+ };
5553
+ globalThis.dispatchEvent = (e) => {
5554
+ const type = (e && typeof e === "object" ? e.type : null) || String(e);
5555
+ const arr = listeners[type];
5556
+ if (arr) {
5557
+ arr.slice().forEach((cb) => cb(e));
5558
+ }
5559
+ };
5560
+ }
4321
5561
  if (typeof globalThis.addEventListener === "function") {
4322
5562
  dispatch.listen("memorio:memory:cleanup", async () => memory.forgetExpired?.());
4323
5563
  }
@@ -4331,16 +5571,18 @@ if (!("memorio" in globalThis)) {
4331
5571
  }
4332
5572
  );
4333
5573
  memorio.memory = memory;
5574
+ memorio.encryption = exports.encryption;
4334
5575
  initializePlatform();
4335
5576
  memorio.isBrowser = isBrowser;
4336
5577
  memorio.isNode = isNode;
4337
5578
  memorio.isDeno = isDeno;
5579
+ memorio.isBun = isBun;
4338
5580
  memorio.isEdge = isEdge;
4339
5581
  memorio.getCapabilities = getCapabilities;
4340
5582
  memorio.createContext = createContext;
4341
5583
  memorio.listContexts = listContexts;
4342
5584
  memorio.deleteContext = deleteContext;
4343
- memorio.isolate = (name) => createContext(name);
5585
+ memorio.isolate = (name, opts) => createContext(name, opts);
4344
5586
  Object.defineProperty(memorio, "setContext", { writable: false, enumerable: false, value: /* @__PURE__ */ __name((id) => setCurrentContext(id), "value") });
4345
5587
  Object.defineProperty(memorio, "getContext", { writable: false, enumerable: false, value: /* @__PURE__ */ __name(() => exports.internal.currentContext, "value") });
4346
5588
  memorio.registerSchema = schema.register;
@@ -4348,6 +5590,9 @@ if (!("memorio" in globalThis)) {
4348
5590
  memorio.unregisterSchema = schema.unregister;
4349
5591
  memorio.listSchemas = schema.list;
4350
5592
  memorio.typed = typed;
5593
+ memorio.computed = computed;
5594
+ memorio.broadcast = broadcast;
5595
+ memorio.security = security;
4351
5596
  memorio.snapshot = snapshot;
4352
5597
  memorio.diff = diff;
4353
5598
  memorio.undo = undo;
@@ -4359,10 +5604,17 @@ if (!("memorio" in globalThis)) {
4359
5604
  memorio.enableHistory = enableHistory;
4360
5605
  memorio.clearHistory = clearHistory2;
4361
5606
  memorio.clearRedo = clearRedo;
5607
+ memorio.mutate = mutate;
5608
+ memorio.createMutation = createMutation;
5609
+ memorio.recordMutation = recordMutation;
5610
+ memorio.toPatch = toPatch;
5611
+ memorio.transaction = beginTransaction;
5612
+ memorio.commitTransaction = commitTransaction;
5613
+ memorio.abortTransaction = abortTransaction;
5614
+ memorio.currentTransaction = currentTransaction;
4362
5615
  Object.defineProperty(memorio, "dispatch", { value: dispatch, writable: true, enumerable: false, configurable: true });
4363
- const isDev = exports.DEV;
4364
5616
  memorio.env = {
4365
- isDev,
5617
+ isDev: exports.DEV,
4366
5618
  isProd: exports.PROD
4367
5619
  };
4368
5620
  memorio.global = function() {
@@ -4374,189 +5626,98 @@ if (!("memorio" in globalThis)) {
4374
5626
  idb: exports.idb,
4375
5627
  sqlite: exports.sqlite,
4376
5628
  observer,
4377
- useObserver
5629
+ useObserver,
5630
+ encryption: exports.encryption,
5631
+ computed,
5632
+ broadcast,
5633
+ security
4378
5634
  };
4379
5635
  for (const key of Object.keys(globalDefinitions)) {
4380
5636
  if (!(key in globalThis)) {
4381
5637
  Object.defineProperty(globalThis, key, {
4382
5638
  value: globalDefinitions[key],
4383
5639
  writable: true,
4384
- enumerable: false,
4385
- configurable: true
5640
+ configurable: true,
5641
+ enumerable: false
4386
5642
  });
4387
5643
  }
4388
5644
  }
5645
+ if (typeof globalThis.useObserver === "function") {
5646
+ Object.freeze(globalThis.useObserver);
5647
+ }
4389
5648
  };
4390
- if (isDev) {
4391
- memorio.global();
4392
- }
4393
- if (exports.DEV) {
4394
- Object.defineProperty(
4395
- memorio,
4396
- "debug",
4397
- {
4398
- get: /* @__PURE__ */ __name(() => exports.internal.debug, "get"),
4399
- set: /* @__PURE__ */ __name((v) => {
4400
- exports.internal.debug = v;
4401
- }, "set"),
4402
- enumerable: false
4403
- }
4404
- );
4405
- const caps = getCapabilities();
4406
- Object.defineProperty(memorio, "_platform", { writable: false, enumerable: false, value: caps.platform });
4407
- Object.defineProperty(memorio, "_capabilities", { writable: false, enumerable: false, value: caps });
4408
- Object.defineProperty(memorio, "_sessionId", { writable: false, enumerable: false, value: generateSessionId() });
4409
- memorio.logger = logger;
4410
- if (!("$state" in globalThis)) Object.defineProperty(globalThis, "$state", { get: /* @__PURE__ */ __name(() => globalThis.state, "get"), configurable: true });
4411
- if (!("$store" in globalThis)) Object.defineProperty(globalThis, "$store", { get: /* @__PURE__ */ __name(() => globalThis.store, "get"), configurable: true });
4412
- if (!("$session" in globalThis)) Object.defineProperty(globalThis, "$session", { get: /* @__PURE__ */ __name(() => globalThis.session, "get"), configurable: true });
4413
- if (!("$cache" in globalThis)) Object.defineProperty(globalThis, "$cache", { get: /* @__PURE__ */ __name(() => globalThis.cache, "get"), configurable: true });
4414
- memorio.devtools = devtools;
4415
- memorio.inspect = stateKeys;
4416
- memorio.stateKeys = stateKeys;
4417
- memorio.pathExists = pathExists;
4418
- memorio.stateType = stateType;
4419
- memorio.stateGet = stateGet;
4420
- memorio.stateSchema = stateSchema;
4421
- memorio.help = function() {
4422
- console.debug(`
4423
- \u{1F9E0} Memorio ${package_default.version} - Help
4424
-
4425
- Core Modules (runtime):
4426
- state - Reactive state management (DEV global)
4427
- store - Persistent storage (localStorage/Map)
4428
- session - Session storage (sessionStorage/Map)
4429
- cache - In-memory cache
4430
- idb - IndexedDB (browser only)
4431
- sqlite - SQLite in browser (sql.js, optional)
4432
-
4433
- Platform Detection:
4434
- memorio.isBrowser() - Browser environment
4435
- memorio.isNode() - Node.js environment
4436
- memorio.isDeno() - Deno environment
4437
- memorio.isEdge() - Edge/Worker environment
4438
- memorio.getCapabilities() - Full capabilities object
4439
-
4440
- Context Management:
4441
- memorio.isolate(name) - Create isolated context
4442
- memorio.listContexts() - List all contexts
4443
- memorio.deleteContext(id) - Delete a context
4444
-
4445
- Schema Validation (runtime):
4446
- memorio.registerSchema() - Register a validator for a state path
4447
- memorio.validate() - Manually validate a value
4448
- memorio.unregisterSchema() - Remove a registered schema
4449
- memorio.listSchemas() - List all registered schema paths
4450
- memorio.typed<T>() - Type-safe view of global state (compile-time only)
4451
-
4452
- History & Time Travel (runtime):
4453
- memorio.snapshot() - Capture a deep snapshot of state
4454
- memorio.diff(snap) - Diff snapshot against current state
4455
- memorio.undo() / redo() - Undo / redo the last mutation
4456
- memorio.canUndo() / canRedo() - Check availability
4457
- memorio.rollback(snap) - Restore state from a snapshot
4458
- memorio.trace() - List all recorded mutations
4459
- memorio.enableHistory() - Enable/disable mutation tracking
4460
- memorio.clearHistory() - Clear undo/redo stacks and trace log
4461
-
4462
- DevTools (development-only):
4463
- memorio.devtools.inspect() - Inspect all modules
4464
- memorio.devtools.stats() - Show statistics
4465
- memorio.devtools.watch() - Watch a path
4466
- memorio.devtools.exportData() - Export as JSON
4467
- memorio.devtools.importData() - Import from JSON
4468
- memorio.devtools.clear() - Clear specific module
4469
- memorio.devtools.clearAll() - Clear all modules
4470
-
4471
- Introspection (development-only):
4472
- memorio.stateKeys() - List top-level state keys
4473
- memorio.pathExists(path) - Check if a state path exists
4474
- memorio.stateType(path) - Get runtime type of a state value
4475
- memorio.stateGet(path) - Get a deep-cloned value at a path
4476
- memorio.stateSchema() - Get a schema report of all state paths
4477
-
4478
- Debug:
4479
- memorio.debug = true - Enable debug output (DEV only)
4480
-
4481
- Memory System (runtime):
4482
- memorio.memory.remember(key, value, opts) - Store a memory with type, confidence, scope, TTL, tags
4483
- memorio.memory.recall(key, opts) - Retrieve a memory with filtering
4484
- memorio.memory.update(key, value, opts) - Update an existing memory
4485
- memorio.memory.forget(key) - Delete a specific memory
4486
- memorio.memory.context(opts) - Get ranked relevant memories (semantic context for AI)
4487
- memorio.memory.stats() - Memory usage statistics
4488
- memorio.memory.forgetExpired() - Remove all expired entries
4489
- memorio.memory.clear() - Wipe all memories
4490
- memorio.memory.configure({ sync }) - Optional cloud-sync provider + namespace
4491
- memorio.memory.journal.pending() - Local op journal (SQLite/store)
4492
-
4493
- Scopes:
4494
- hot - In-memory reactive state (volatile, fastest)
4495
- session - sessionStorage (persists across page reloads, cleared on tab close)
4496
- local - localStorage (persistent, survives browser restart)
4497
- durable - IndexedDB (large datasets, async)
4498
- sql - SQLite / sql.js (browser, optional, full SQL)
4499
-
4500
- TTL options:
4501
- ttl: number (milliseconds) or null (never expires)
4502
-
4503
- Memory types:
4504
- fact, preference, decision, task, context
4505
-
4506
- Console shortcuts (DEV only):
4507
- state, store, session, cache, idb, sqlite - direct access to modules
4508
- $state, $store, $session, $cache - aliases for the above
4509
- `);
4510
- };
4511
- }
4512
5649
  }
4513
5650
 
4514
5651
  // index.ts
4515
- var devtools2 = exports.DEV ? devtools : void 0;
5652
+ var transaction = beginTransaction;
5653
+ var devtools = void 0;
4516
5654
  var memorio2 = globalThis.memorio;
4517
5655
  var events = globalThis.events;
4518
5656
  var isolate = /* @__PURE__ */ __name((name) => createContext(name), "isolate");
4519
- var help2 = globalThis.memorio?.help;
5657
+ var help = globalThis.memorio?.help;
4520
5658
  var setContext = /* @__PURE__ */ __name((id) => exports.internal.currentContext = id, "setContext");
4521
5659
  var getContext = /* @__PURE__ */ __name(() => exports.internal.currentContext, "getContext");
4522
5660
  var index_default = memorio2;
4523
5661
 
5662
+ exports.abortTransaction = abortTransaction;
5663
+ exports.activeTransactionId = activeTransactionId;
5664
+ exports.beginTransaction = beginTransaction;
5665
+ exports.broadcast = broadcast;
4524
5666
  exports.cache = cache;
5667
+ exports.canMerge = canMerge;
4525
5668
  exports.canRedo = canRedo;
4526
5669
  exports.canUndo = canUndo;
4527
5670
  exports.clearHistory = clearHistory2;
4528
5671
  exports.clearRedo = clearRedo;
5672
+ exports.commitTransaction = commitTransaction;
5673
+ exports.computed = computed;
4529
5674
  exports.createContext = createContext;
5675
+ exports.createMutation = createMutation;
5676
+ exports.currentTimestamp = currentTimestamp;
5677
+ exports.currentTransaction = currentTransaction;
4530
5678
  exports.default = index_default;
4531
5679
  exports.deleteContext = deleteContext;
4532
- exports.devtools = devtools2;
5680
+ exports.devtools = devtools;
4533
5681
  exports.diff = diff;
5682
+ exports.diffToPatch = diffToPatch;
4534
5683
  exports.dispatch = dispatch;
4535
5684
  exports.enableHistory = enableHistory;
4536
5685
  exports.events = events;
4537
5686
  exports.fractional = fractional;
5687
+ exports.generateCommitId = generateCommitId;
5688
+ exports.generateMutationId = generateMutationId;
5689
+ exports.generateTransactionId = generateTransactionId;
4538
5690
  exports.getCapabilities = getCapabilities;
4539
5691
  exports.getContext = getContext;
4540
- exports.help = help2;
5692
+ exports.help = help;
4541
5693
  exports.hlc = hlc;
4542
5694
  exports.isBrowser = isBrowser;
5695
+ exports.isBun = isBun;
4543
5696
  exports.isDeno = isDeno;
4544
5697
  exports.isEdge = isEdge;
4545
5698
  exports.isNode = isNode;
4546
5699
  exports.isolate = isolate;
4547
5700
  exports.listContexts = listContexts;
4548
5701
  exports.listSchemas = listSchemas;
5702
+ exports.listTransactions = listTransactions;
4549
5703
  exports.logger = logger;
4550
5704
  exports.memorio = memorio2;
4551
5705
  exports.memory = memory;
5706
+ exports.mergePatches = mergePatches;
5707
+ exports.mutate = mutate;
5708
+ exports.mutationToPatch = mutationToPatch;
4552
5709
  exports.observer = observer;
5710
+ exports.recordMutation = recordMutation;
4553
5711
  exports.redo = redo;
4554
5712
  exports.registerSchema = registerSchema;
4555
5713
  exports.rollback = rollback;
4556
5714
  exports.schema = schema;
5715
+ exports.security = security;
4557
5716
  exports.setContext = setContext;
4558
5717
  exports.snapshot = snapshot;
5718
+ exports.toPatch = toPatch;
4559
5719
  exports.trace = trace;
5720
+ exports.transaction = transaction;
4560
5721
  exports.typed = typed;
4561
5722
  exports.undo = undo;
4562
5723
  exports.unregisterSchema = unregisterSchema;