memorio 4.1.0 → 4.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs CHANGED
@@ -323,7 +323,7 @@ Object.defineProperty(globalThis, "memorio", {
323
323
  }), Object.defineProperty(memorio, "version", {
324
324
  writable: !1,
325
325
  enumerable: !1,
326
- value: "4.1.0"
326
+ value: "4.1.6"
327
327
  }), Object.defineProperty(memorio, "debug", {
328
328
  writable: !0,
329
329
  enumerable: !1,
@@ -392,7 +392,10 @@ Object.defineProperty(memorio, "_sessionId", {
392
392
  },
393
393
  listen: (e, t = null, o = !1) => {
394
394
  globalThis.observer?.list?.[e]?.length > 0 && globalThis.observer?.remove?.(e);
395
- const r = t ? e => setTimeout(() => t(e), 1) : void 0;
395
+ const r = t ? e => {
396
+ const o = e;
397
+ return globalThis.queueMicrotask ? globalThis.queueMicrotask(() => t(o)) : Promise.resolve().then(() => t(o));
398
+ } : void 0;
396
399
  r && globalThis.addEventListener(e, r), r && (globalThis.events[e] = r);
397
400
  },
398
401
  remove: e => {
@@ -621,7 +624,7 @@ globalThis.observer = (e, t = null, o = !0) => {
621
624
 
622
625
  var W = x(), R = new Map, U = null !== W, K = "memorio_store_";
623
626
 
624
- function F(e) {
627
+ function q(e) {
625
628
  return e && "string" == typeof e ? e.length > 512 ? (memorio.message("Key too long (max 512 characters)"),
626
629
  "") : /^[a-zA-Z0-9_.-]+$/.test(e) ? K + e : (memorio.message("Key contains invalid characters (only a-z, A-Z, 0-9, _, ., - allowed)"),
627
630
  "") : "";
@@ -635,7 +638,7 @@ Object.defineProperty(globalThis, "store", {
635
638
  get: {
636
639
  value: e => {
637
640
  if (!e) return;
638
- const t = F(e);
641
+ const t = q(e);
639
642
  try {
640
643
  if (U) {
641
644
  const e = W.getItem(t);
@@ -651,10 +654,20 @@ Object.defineProperty(globalThis, "store", {
651
654
  return null;
652
655
  }
653
656
  },
657
+ getMultiple: {
658
+ value: e => {
659
+ const t = {};
660
+ for (const o of e) try {
661
+ const e = store.get(o);
662
+ e && (t[o] = e);
663
+ } catch {}
664
+ return t;
665
+ }
666
+ },
654
667
  set: {
655
668
  value: (e, t) => {
656
669
  if (!e) return;
657
- const o = F(e);
670
+ const o = q(e);
658
671
  try {
659
672
  if (U) {
660
673
  if (null == t) W.setItem(o, JSON.stringify(null)); else if ("object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t) W.setItem(o, JSON.stringify(t)); else if ("function" == typeof t) return void memorio.message("Storing functions is not secure and is blocked for safety.");
@@ -668,7 +681,7 @@ Object.defineProperty(globalThis, "store", {
668
681
  remove: {
669
682
  value: e => {
670
683
  if (!e) return;
671
- const t = F(e);
684
+ const t = q(e);
672
685
  try {
673
686
  if (U) {
674
687
  if (W.getItem(t)) return W.removeItem(t), !0;
@@ -749,7 +762,7 @@ Object.defineProperty(globalThis, "store", {
749
762
  }
750
763
  }), Object.freeze(store);
751
764
 
752
- var q = D(), L = new Map, H = null !== q, V = "memorio_session_";
765
+ var F = D(), L = new Map, H = null !== F, V = "memorio_session_";
753
766
 
754
767
  function Y(e) {
755
768
  return e && "string" == typeof e ? e.length > 512 ? (memorio.message("Key too long (max 512 characters)"),
@@ -768,7 +781,7 @@ Object.defineProperty(globalThis, "session", {
768
781
  const t = Y(e);
769
782
  try {
770
783
  if (H) {
771
- const e = q.getItem(t);
784
+ const e = F.getItem(t);
772
785
  return e ? JSON.parse(e) : e;
773
786
  }
774
787
  {
@@ -785,7 +798,7 @@ Object.defineProperty(globalThis, "session", {
785
798
  if (!e) return;
786
799
  const o = Y(e);
787
800
  try {
788
- H ? null == t ? q.setItem(o, JSON.stringify(null)) : "object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t ? q.setItem(o, JSON.stringify(t)) : "function" == typeof t && memorio.message("It's not secure to session functions.") : null == t ? L.set(o, JSON.stringify(null)) : "object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t ? L.set(o, JSON.stringify(t)) : "function" == typeof t && memorio.message("It's not secure to session functions.");
801
+ H ? null == t ? F.setItem(o, JSON.stringify(null)) : "object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t ? F.setItem(o, JSON.stringify(t)) : "function" == typeof t && memorio.message("It's not secure to session functions.") : null == t ? L.set(o, JSON.stringify(null)) : "object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t ? L.set(o, JSON.stringify(t)) : "function" == typeof t && memorio.message("It's not secure to session functions.");
789
802
  } catch (t) {
790
803
  memorio.message(`Error setting session item '${e}': ${t}`);
791
804
  }
@@ -797,7 +810,7 @@ Object.defineProperty(globalThis, "session", {
797
810
  const t = Y(e);
798
811
  try {
799
812
  if (H) {
800
- if (q.getItem(t)) return q.removeItem(t), !0;
813
+ if (F.getItem(t)) return F.removeItem(t), !0;
801
814
  } else if (L.has(t)) return L.delete(t), !0;
802
815
  } catch (t) {
803
816
  memorio.message(`Error removing session item '${e}': ${t}`);
@@ -811,11 +824,11 @@ Object.defineProperty(globalThis, "session", {
811
824
  value: () => {
812
825
  if (H) {
813
826
  const e = [];
814
- for (let t = 0; t < q.length; t++) {
815
- const o = q.key(t);
827
+ for (let t = 0; t < F.length; t++) {
828
+ const o = F.key(t);
816
829
  o?.startsWith(V) && e.push(o);
817
830
  }
818
- e.forEach(e => q.removeItem(e));
831
+ e.forEach(e => F.removeItem(e));
819
832
  } else L.clear();
820
833
  return !0;
821
834
  }
@@ -829,9 +842,9 @@ Object.defineProperty(globalThis, "session", {
829
842
  size: {
830
843
  value: () => {
831
844
  let e = 0;
832
- return H ? Object.keys(q).forEach(t => {
845
+ return H ? Object.keys(F).forEach(t => {
833
846
  if (t.startsWith(V)) {
834
- const o = q.getItem(t);
847
+ const o = F.getItem(t);
835
848
  o && (e += o.length);
836
849
  }
837
850
  }) : L.forEach(t => {
@@ -846,10 +859,10 @@ Object.defineProperty(globalThis, "session", {
846
859
  value: () => {
847
860
  const e = {};
848
861
  try {
849
- if (H) for (let t = 0; t < q.length; t++) {
850
- const o = q.key(t);
862
+ if (H) for (let t = 0; t < F.length; t++) {
863
+ const o = F.key(t);
851
864
  if (o?.startsWith(V)) {
852
- const t = o.replace(V, ""), r = q.getItem(o);
865
+ const t = o.replace(V, ""), r = F.getItem(o);
853
866
  if (null !== r) try {
854
867
  e[t] = JSON.parse(r);
855
868
  } catch {
package/index.js CHANGED
@@ -321,7 +321,7 @@ Object.defineProperty(globalThis, "memorio", {
321
321
  }), Object.defineProperty(memorio, "version", {
322
322
  writable: !1,
323
323
  enumerable: !1,
324
- value: "4.1.0"
324
+ value: "4.1.6"
325
325
  }), Object.defineProperty(memorio, "debug", {
326
326
  writable: !0,
327
327
  enumerable: !1,
@@ -390,7 +390,10 @@ Object.defineProperty(memorio, "_sessionId", {
390
390
  },
391
391
  listen: (e, t = null, o = !1) => {
392
392
  globalThis.observer?.list?.[e]?.length > 0 && globalThis.observer?.remove?.(e);
393
- const r = t ? e => setTimeout(() => t(e), 1) : void 0;
393
+ const r = t ? e => {
394
+ const o = e;
395
+ return globalThis.queueMicrotask ? globalThis.queueMicrotask(() => t(o)) : Promise.resolve().then(() => t(o));
396
+ } : void 0;
394
397
  r && globalThis.addEventListener(e, r), r && (globalThis.events[e] = r);
395
398
  },
396
399
  remove: e => {
@@ -619,7 +622,7 @@ globalThis.observer = (e, t = null, o = !0) => {
619
622
 
620
623
  var W = x(), R = new Map, U = null !== W, K = "memorio_store_";
621
624
 
622
- function F(e) {
625
+ function q(e) {
623
626
  return e && "string" == typeof e ? e.length > 512 ? (memorio.message("Key too long (max 512 characters)"),
624
627
  "") : /^[a-zA-Z0-9_.-]+$/.test(e) ? K + e : (memorio.message("Key contains invalid characters (only a-z, A-Z, 0-9, _, ., - allowed)"),
625
628
  "") : "";
@@ -633,7 +636,7 @@ Object.defineProperty(globalThis, "store", {
633
636
  get: {
634
637
  value: e => {
635
638
  if (!e) return;
636
- const t = F(e);
639
+ const t = q(e);
637
640
  try {
638
641
  if (U) {
639
642
  const e = W.getItem(t);
@@ -649,10 +652,20 @@ Object.defineProperty(globalThis, "store", {
649
652
  return null;
650
653
  }
651
654
  },
655
+ getMultiple: {
656
+ value: e => {
657
+ const t = {};
658
+ for (const o of e) try {
659
+ const e = store.get(o);
660
+ e && (t[o] = e);
661
+ } catch {}
662
+ return t;
663
+ }
664
+ },
652
665
  set: {
653
666
  value: (e, t) => {
654
667
  if (!e) return;
655
- const o = F(e);
668
+ const o = q(e);
656
669
  try {
657
670
  if (U) {
658
671
  if (null == t) W.setItem(o, JSON.stringify(null)); else if ("object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t) W.setItem(o, JSON.stringify(t)); else if ("function" == typeof t) return void memorio.message("Storing functions is not secure and is blocked for safety.");
@@ -666,7 +679,7 @@ Object.defineProperty(globalThis, "store", {
666
679
  remove: {
667
680
  value: e => {
668
681
  if (!e) return;
669
- const t = F(e);
682
+ const t = q(e);
670
683
  try {
671
684
  if (U) {
672
685
  if (W.getItem(t)) return W.removeItem(t), !0;
@@ -747,7 +760,7 @@ Object.defineProperty(globalThis, "store", {
747
760
  }
748
761
  }), Object.freeze(store);
749
762
 
750
- var q = D(), L = new Map, H = null !== q, V = "memorio_session_";
763
+ var F = D(), L = new Map, H = null !== F, V = "memorio_session_";
751
764
 
752
765
  function Y(e) {
753
766
  return e && "string" == typeof e ? e.length > 512 ? (memorio.message("Key too long (max 512 characters)"),
@@ -766,7 +779,7 @@ Object.defineProperty(globalThis, "session", {
766
779
  const t = Y(e);
767
780
  try {
768
781
  if (H) {
769
- const e = q.getItem(t);
782
+ const e = F.getItem(t);
770
783
  return e ? JSON.parse(e) : e;
771
784
  }
772
785
  {
@@ -783,7 +796,7 @@ Object.defineProperty(globalThis, "session", {
783
796
  if (!e) return;
784
797
  const o = Y(e);
785
798
  try {
786
- H ? null == t ? q.setItem(o, JSON.stringify(null)) : "object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t ? q.setItem(o, JSON.stringify(t)) : "function" == typeof t && memorio.message("It's not secure to session functions.") : null == t ? L.set(o, JSON.stringify(null)) : "object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t ? L.set(o, JSON.stringify(t)) : "function" == typeof t && memorio.message("It's not secure to session functions.");
799
+ H ? null == t ? F.setItem(o, JSON.stringify(null)) : "object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t ? F.setItem(o, JSON.stringify(t)) : "function" == typeof t && memorio.message("It's not secure to session functions.") : null == t ? L.set(o, JSON.stringify(null)) : "object" == typeof t || "number" == typeof t || "boolean" == typeof t || "string" == typeof t ? L.set(o, JSON.stringify(t)) : "function" == typeof t && memorio.message("It's not secure to session functions.");
787
800
  } catch (t) {
788
801
  memorio.message(`Error setting session item '${e}': ${t}`);
789
802
  }
@@ -795,7 +808,7 @@ Object.defineProperty(globalThis, "session", {
795
808
  const t = Y(e);
796
809
  try {
797
810
  if (H) {
798
- if (q.getItem(t)) return q.removeItem(t), !0;
811
+ if (F.getItem(t)) return F.removeItem(t), !0;
799
812
  } else if (L.has(t)) return L.delete(t), !0;
800
813
  } catch (t) {
801
814
  memorio.message(`Error removing session item '${e}': ${t}`);
@@ -809,11 +822,11 @@ Object.defineProperty(globalThis, "session", {
809
822
  value: () => {
810
823
  if (H) {
811
824
  const e = [];
812
- for (let t = 0; t < q.length; t++) {
813
- const o = q.key(t);
825
+ for (let t = 0; t < F.length; t++) {
826
+ const o = F.key(t);
814
827
  o?.startsWith(V) && e.push(o);
815
828
  }
816
- e.forEach(e => q.removeItem(e));
829
+ e.forEach(e => F.removeItem(e));
817
830
  } else L.clear();
818
831
  return !0;
819
832
  }
@@ -827,9 +840,9 @@ Object.defineProperty(globalThis, "session", {
827
840
  size: {
828
841
  value: () => {
829
842
  let e = 0;
830
- return H ? Object.keys(q).forEach(t => {
843
+ return H ? Object.keys(F).forEach(t => {
831
844
  if (t.startsWith(V)) {
832
- const o = q.getItem(t);
845
+ const o = F.getItem(t);
833
846
  o && (e += o.length);
834
847
  }
835
848
  }) : L.forEach(t => {
@@ -844,10 +857,10 @@ Object.defineProperty(globalThis, "session", {
844
857
  value: () => {
845
858
  const e = {};
846
859
  try {
847
- if (H) for (let t = 0; t < q.length; t++) {
848
- const o = q.key(t);
860
+ if (H) for (let t = 0; t < F.length; t++) {
861
+ const o = F.key(t);
849
862
  if (o?.startsWith(V)) {
850
- const t = o.replace(V, ""), r = q.getItem(o);
863
+ const t = o.replace(V, ""), r = F.getItem(o);
851
864
  if (null !== r) try {
852
865
  e[t] = JSON.parse(r);
853
866
  } catch {
package/llms.txt ADDED
@@ -0,0 +1,405 @@
1
+ # Memorio - LLM Documentation
2
+
3
+ ## Overview
4
+
5
+ **Memorio** is a cross-platform state management library that provides reactive state, persistence, and observation capabilities with zero dependencies. It works in Node.js, Deno, browsers, and edge environments.
6
+
7
+ ```
8
+ npm i memorio
9
+ ```
10
+
11
+ ## Core Concepts
12
+
13
+ Memorio provides 6 storage modules plus utilities:
14
+
15
+ | Module | Purpose | Persistence |
16
+ |--------|---------|-------------|
17
+ | `state` | Reactive, volatile state | In-memory (resets on refresh) |
18
+ | `store` | localStorage persistence | Survives browser refresh |
19
+ | `session` | sessionStorage | Dies with browser tab |
20
+ | `cache` | In-memory cache | Fastest read, no persistence |
21
+ | `idb` | IndexedDB | Structured, async, persistent (browser-only) |
22
+ | `observer` | Object watcher | Legacy, deprecated |
23
+ | `useObserver` | React hook | Auto-discovery of state paths |
24
+
25
+ ## Quick Start
26
+
27
+ ```javascript
28
+ import 'memorio'
29
+
30
+ // Set reactive state
31
+ state.user = { name: 'Sara', role: 'admin' }
32
+ state.counter = 0
33
+
34
+ // Observe changes (React hook)
35
+ useObserver(
36
+ () => { console.log('counter:', state.counter) },
37
+ [state.counter]
38
+ )
39
+ ```
40
+
41
+ ## API Reference
42
+
43
+ ### `state` — Reactive State
44
+
45
+ Global, Proxy-based, reactive state management.
46
+
47
+ ```javascript
48
+ // Set values
49
+ state.user = { name: 'Sara', role: 'admin' }
50
+ state.items = [1, 2, 3]
51
+ state.counter = 0
52
+
53
+ // Get values
54
+ const name = state.user.name // 'Sara'
55
+
56
+ // List all keys
57
+ console.log(state.list) // ['user', 'items', 'counter']
58
+
59
+ // Remove one key
60
+ state.remove('items')
61
+
62
+ // Clear all
63
+ state.removeAll()
64
+
65
+ // Lock/unlock for frozen objects
66
+ state.lock() // freeze everything
67
+ state.unlock() // unfreeze
68
+ ```
69
+
70
+ **Features:**
71
+ - Automatic path tracking via `__path` property
72
+ - Nested proxy support
73
+ - Lock/unlock per-key or globally
74
+ - Auto-dispatches events on changes
75
+
76
+ ### `store` — localStorage Persistence
77
+
78
+ Persistent storage that survives browser refresh.
79
+
80
+ ```javascript
81
+ // Set
82
+ store.set('preferences', { theme: 'dark' })
83
+
84
+ // Get
85
+ const prefs = store.get('preferences') // { theme: 'dark' } or null
86
+
87
+ // List all keys
88
+ store.list() // { preferences: { theme: 'dark' } }
89
+
90
+ // Remove
91
+ store.remove('preferences')
92
+
93
+ // Delete (alias for remove)
94
+ store.delete('preferences')
95
+
96
+ // Clear all memorio items
97
+ store.removeAll()
98
+
99
+ // Clear all (alias for removeAll)
100
+ store.clearAll()
101
+
102
+ // Check size
103
+ console.log(store.size(), 'chars stored')
104
+
105
+ // Check if persistent (real localStorage vs memory fallback)
106
+ console.log(store.isPersistent) // true → real localStorage
107
+
108
+ // Estimate quota usage (returns [0, 0] for localStorage)
109
+ await store.quota() // [usage, quota] in KB
110
+ ```
111
+
112
+ ### `session` — sessionStorage
113
+
114
+ Storage that dies when browser tab closes.
115
+
116
+ ```javascript
117
+ // Set
118
+ session.set('token', 'user-abc-123')
119
+
120
+ // Get
121
+ const token = session.get('token') // 'user-abc-123' or null
122
+
123
+ // List all keys
124
+ session.list() // { token: 'user-abc-123' }
125
+
126
+ // Remove
127
+ session.remove('token')
128
+
129
+ // Delete (alias for remove)
130
+ session.delete('token')
131
+
132
+ // Clear all
133
+ session.removeAll()
134
+
135
+ // Clear all (alias for removeAll)
136
+ session.clearAll()
137
+
138
+ // Check size
139
+ console.log(session.size(), 'chars stored')
140
+
141
+ // Check if persistent
142
+ console.log(session.isPersistent)
143
+ ```
144
+
145
+ ### `cache` — In-Memory Cache
146
+
147
+ Fastest possible read, data lost on refresh.
148
+
149
+ ```javascript
150
+ // Set
151
+ cache.set('temp', computeExpensiveResult())
152
+
153
+ // Get
154
+ const result = cache.get('temp') // undefined or the value
155
+
156
+ // List all keys
157
+ cache.list() // { temp: <value> }
158
+
159
+ // Remove
160
+ cache.remove('temp')
161
+
162
+ // Clear all
163
+ cache.clear()
164
+
165
+ // Remove all (alias for clear)
166
+ cache.removeAll()
167
+
168
+ // Direct access (also works)
169
+ cache['myKey'] = value
170
+ const value = cache['myKey']
171
+ delete cache['myKey']
172
+ ```
173
+
174
+ ### `idb` — IndexedDB
175
+
176
+ Structured, persistent, async database (browser-only).
177
+
178
+ ```javascript
179
+ // Create database
180
+ await idb.db.create('my-db', 1) // version defaults to 1
181
+
182
+ // Create table (object store)
183
+ await idb.table.create('my-db', 'users')
184
+
185
+ // Set data
186
+ await idb.data.set('my-db', 'users', { id: 1, name: 'Sara' })
187
+
188
+ // Get data by key
189
+ const user = await idb.data.get('my-db', 'users', 1)
190
+
191
+ // Delete data
192
+ await idb.data.delete('my-db', 'users', 1)
193
+
194
+ // List databases
195
+ const dbs = await idb.db.list()
196
+
197
+ // Check if database exists
198
+ const exists = await idb.db.exist('my-db')
199
+
200
+ // Delete database
201
+ await idb.db.delete('my-db')
202
+
203
+ // Get database size
204
+ const size = await idb.db.size('my-db')
205
+
206
+ // Get table size
207
+ const tableSize = await idb.table.size('my-db', 'users')
208
+
209
+ // Check support
210
+ idb.db.support() // true if IndexedDB available
211
+
212
+ // Check quota
213
+ const [usage, quota] = await idb.db.quota()
214
+ ```
215
+
216
+ **Note:** In Node.js/Deno, `idb` is disabled with a warning. Use `store` or `session` instead.
217
+
218
+ ### `observer` — Object Watcher (DEPRECATED)
219
+
220
+ Legacy observer API. Use `useObserver` instead.
221
+
222
+ ```javascript
223
+ // Listen to state changes
224
+ observer('state.user', (newVal, oldVal) => {
225
+ console.log('user changed:', newVal, oldVal)
226
+ })
227
+
228
+ // Toggle listening (no callback)
229
+ observer('state.counter')
230
+
231
+ // Remove observer
232
+ observer.remove('state.user')
233
+
234
+ // List all observers
235
+ console.log(observer.list)
236
+
237
+ // Remove all observers
238
+ observer.removeAll()
239
+ ```
240
+
241
+ ### `useObserver` — React Hook
242
+
243
+ Primary way to observe state changes in React components.
244
+
245
+ ```jsx
246
+ import 'memorio'
247
+ import { useReducer } from 'react'
248
+
249
+ function Counter() {
250
+ const [, forceUpdate] = useReducer(x => x + 1, 0)
251
+
252
+ // Auto-discovery mode (no deps)
253
+ useObserver(() => {
254
+ console.log('counter:', state.counter)
255
+ }, state.counter)
256
+
257
+ // Explicit deps mode
258
+ useObserver(
259
+ () => { console.log('user:', state.user) },
260
+ [state.user]
261
+ )
262
+
263
+ return <div>Count: {state.counter}</div>
264
+ }
265
+ ```
266
+
267
+ **Features:**
268
+ - Auto-discovery of state paths during render
269
+ - Returns cleanup function to stop monitoring
270
+ - Supports both Proxy objects and string paths
271
+
272
+ ### `devtools` — Inspection Tools
273
+
274
+ Inspect all memorio data in console.
275
+
276
+ ```javascript
277
+ // Pretty-print state, store, session, cache
278
+ memorio.devtools.inspect()
279
+
280
+ // Get stats
281
+ memorio.devtools.stats() // { stateKeys, storeKeys, sessionKeys, ... }
282
+
283
+ // Clear specific module
284
+ memorio.devtools.clear('state')
285
+
286
+ // Clear all modules
287
+ memorio.devtools.clearAll()
288
+
289
+ // Export all data as JSON
290
+ memorio.devtools.exportData()
291
+
292
+ // Import data from JSON
293
+ memorio.devtools.importData(jsonString)
294
+
295
+ // Show help
296
+ memorio.devtools.help()
297
+
298
+ // Console shortcuts
299
+ $state // same as globalThis.state
300
+ $store // same as globalThis.store
301
+ $session // same as globalThis.session
302
+ $cache // same as globalThis.cache
303
+ ```
304
+
305
+ ### `logger` — Change Tracking
306
+
307
+ Track every state change with timestamps.
308
+
309
+ ```javascript
310
+ // Configure logger
311
+ memorio.logger.configure({
312
+ enabled: true,
313
+ logToConsole: true,
314
+ modules: ['state', 'store', 'session', 'cache', 'idb']
315
+ })
316
+
317
+ // Get history
318
+ memorio.logger.getHistory() // [{ timestamp, module, action, path, value }, ...]
319
+
320
+ // Get stats
321
+ memorio.logger.getStats() // { total, state, store, session, cache, idb, set, get, ... }
322
+
323
+ // Clear history
324
+ memorio.logger.clearHistory()
325
+
326
+ // Export logs
327
+ memorio.logger.exportLogs() // JSON string of all history
328
+ ```
329
+
330
+ ## Platform Detection
331
+
332
+ Access via `memorio.*` after `import 'memorio'`:
333
+
334
+ ```javascript
335
+ memorio.isBrowser() // true in Chrome, Firefox, Safari
336
+ memorio.isNode() // true in Node.js
337
+ memorio.isDeno() // true in Deno
338
+ memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
339
+
340
+ const caps = memorio.getCapabilities()
341
+ // { platform: 'browser', hasLocalStorage: true, hasIndexedDB: true, sessionId: 'uuid', ... }
342
+
343
+ // Create isolated context
344
+ memorio.createContext('tenant-name')
345
+ memorio.listContexts()
346
+ memorio.deleteContext('context-id')
347
+ memorio.isolate('tenant-name') // alias for createContext
348
+ ```
349
+
350
+ ## Cross-Platform Support
351
+
352
+ | Module | Browser | Node.js | Deno | Edge/Workers |
353
+ |--------|---------|---------|------|--------------|
354
+ | `state` | ✅ | ✅ | ✅ | ✅ |
355
+ | `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
356
+ | `cache` | ✅ | ✅ | ✅ | ✅ |
357
+ | `store` | ✅ localStorage | ⚠️ memory | ⚠️ memory | ✅ localStorage |
358
+ | `session` | ✅ sessionStorage | ⚠️ memory | ⚠️ memory | ✅ sessionStorage |
359
+ | `idb` | ✅ IndexedDB | ❌ | ❌ | ⚠️ |
360
+ | `devtools` | ✅ | ❌ | ❌ | ⚠️ |
361
+
362
+ **Note:** `store` and `session` fall back to in-memory `Map` in Node.js/Deno.
363
+
364
+ ## Session Isolation
365
+
366
+ Each browser tab and server request gets an isolated namespace automatically via session IDs.
367
+
368
+ ```javascript
369
+ // Create isolated context
370
+ memorio.createContext('tenant-name')
371
+ memorio.listContexts()
372
+ memorio.deleteContext('context-id')
373
+ memorio.isolate('tenant-name') // alias for createContext
374
+ ```
375
+
376
+ ## Security
377
+
378
+ - Zero production dependencies
379
+ - NIST & NSA aligned security standards
380
+ - No `eval`, no obfuscation, no hardcoded secrets
381
+ - All inputs validated, keys sanitized
382
+ - Secure random session IDs via `crypto.randomUUID`
383
+
384
+ ## License
385
+
386
+ MIT © Dario Passariello (BigLogic Inc Canada)
387
+
388
+ ## Utilities
389
+
390
+ ### `memorio.dispatch` — Event Dispatch System
391
+
392
+ Internal event system used by state changes.
393
+
394
+ ```javascript
395
+ // Dispatch a custom event
396
+ memorio.dispatch.set('custom:event', { detail: { data: 'value' } })
397
+
398
+ // Listen for an event
399
+ memorio.dispatch.listen('custom:event', (e) => {
400
+ console.log('Event triggered:', e.detail)
401
+ })
402
+
403
+ // Remove listener
404
+ memorio.dispatch.remove('custom:event')
405
+ ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "memorio",
3
3
  "codeName": "memorio",
4
- "version": "4.1.0",
4
+ "version": "4.1.6",
5
5
  "description": "Memorio, State + Observer, Store and iDB for an easy life - Cross-platform compatible",
6
6
  "main": "./index.cjs",
7
7
  "browser": "./index.cjs",
@@ -54,7 +54,7 @@ interface _observer {
54
54
 
55
55
  }
56
56
 
57
- declare var observer: _observer | null
57
+ declare var observer: _observer
58
58
  type observer = _observer
59
59
 
60
60
  // Extend globalThis to include observer