memorio 4.1.0 → 4.1.5
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 +21 -20
- package/index.js +21 -18
- package/llms.txt +405 -0
- package/package.json +1 -1
- package/types/observer.d.ts +1 -1
package/index.cjs
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
1
|
var e = Object.getOwnPropertyNames, t = (t, o) => function() {
|
|
4
2
|
return t && (o = (0, t[e(t)[0]])(t = 0)), o;
|
|
5
3
|
}, o = {}, r = t({
|
|
@@ -323,7 +321,7 @@ Object.defineProperty(globalThis, "memorio", {
|
|
|
323
321
|
}), Object.defineProperty(memorio, "version", {
|
|
324
322
|
writable: !1,
|
|
325
323
|
enumerable: !1,
|
|
326
|
-
value: "4.1.
|
|
324
|
+
value: "4.1.5"
|
|
327
325
|
}), Object.defineProperty(memorio, "debug", {
|
|
328
326
|
writable: !0,
|
|
329
327
|
enumerable: !1,
|
|
@@ -392,7 +390,10 @@ Object.defineProperty(memorio, "_sessionId", {
|
|
|
392
390
|
},
|
|
393
391
|
listen: (e, t = null, o = !1) => {
|
|
394
392
|
globalThis.observer?.list?.[e]?.length > 0 && globalThis.observer?.remove?.(e);
|
|
395
|
-
const r = t ? e =>
|
|
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;
|
|
396
397
|
r && globalThis.addEventListener(e, r), r && (globalThis.events[e] = r);
|
|
397
398
|
},
|
|
398
399
|
remove: e => {
|
|
@@ -621,7 +622,7 @@ globalThis.observer = (e, t = null, o = !0) => {
|
|
|
621
622
|
|
|
622
623
|
var W = x(), R = new Map, U = null !== W, K = "memorio_store_";
|
|
623
624
|
|
|
624
|
-
function
|
|
625
|
+
function q(e) {
|
|
625
626
|
return e && "string" == typeof e ? e.length > 512 ? (memorio.message("Key too long (max 512 characters)"),
|
|
626
627
|
"") : /^[a-zA-Z0-9_.-]+$/.test(e) ? K + e : (memorio.message("Key contains invalid characters (only a-z, A-Z, 0-9, _, ., - allowed)"),
|
|
627
628
|
"") : "";
|
|
@@ -635,7 +636,7 @@ Object.defineProperty(globalThis, "store", {
|
|
|
635
636
|
get: {
|
|
636
637
|
value: e => {
|
|
637
638
|
if (!e) return;
|
|
638
|
-
const t =
|
|
639
|
+
const t = q(e);
|
|
639
640
|
try {
|
|
640
641
|
if (U) {
|
|
641
642
|
const e = W.getItem(t);
|
|
@@ -654,7 +655,7 @@ Object.defineProperty(globalThis, "store", {
|
|
|
654
655
|
set: {
|
|
655
656
|
value: (e, t) => {
|
|
656
657
|
if (!e) return;
|
|
657
|
-
const o =
|
|
658
|
+
const o = q(e);
|
|
658
659
|
try {
|
|
659
660
|
if (U) {
|
|
660
661
|
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 +669,7 @@ Object.defineProperty(globalThis, "store", {
|
|
|
668
669
|
remove: {
|
|
669
670
|
value: e => {
|
|
670
671
|
if (!e) return;
|
|
671
|
-
const t =
|
|
672
|
+
const t = q(e);
|
|
672
673
|
try {
|
|
673
674
|
if (U) {
|
|
674
675
|
if (W.getItem(t)) return W.removeItem(t), !0;
|
|
@@ -749,7 +750,7 @@ Object.defineProperty(globalThis, "store", {
|
|
|
749
750
|
}
|
|
750
751
|
}), Object.freeze(store);
|
|
751
752
|
|
|
752
|
-
var
|
|
753
|
+
var F = D(), L = new Map, H = null !== F, V = "memorio_session_";
|
|
753
754
|
|
|
754
755
|
function Y(e) {
|
|
755
756
|
return e && "string" == typeof e ? e.length > 512 ? (memorio.message("Key too long (max 512 characters)"),
|
|
@@ -768,7 +769,7 @@ Object.defineProperty(globalThis, "session", {
|
|
|
768
769
|
const t = Y(e);
|
|
769
770
|
try {
|
|
770
771
|
if (H) {
|
|
771
|
-
const e =
|
|
772
|
+
const e = F.getItem(t);
|
|
772
773
|
return e ? JSON.parse(e) : e;
|
|
773
774
|
}
|
|
774
775
|
{
|
|
@@ -785,7 +786,7 @@ Object.defineProperty(globalThis, "session", {
|
|
|
785
786
|
if (!e) return;
|
|
786
787
|
const o = Y(e);
|
|
787
788
|
try {
|
|
788
|
-
H ? null == t ?
|
|
789
|
+
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
790
|
} catch (t) {
|
|
790
791
|
memorio.message(`Error setting session item '${e}': ${t}`);
|
|
791
792
|
}
|
|
@@ -797,7 +798,7 @@ Object.defineProperty(globalThis, "session", {
|
|
|
797
798
|
const t = Y(e);
|
|
798
799
|
try {
|
|
799
800
|
if (H) {
|
|
800
|
-
if (
|
|
801
|
+
if (F.getItem(t)) return F.removeItem(t), !0;
|
|
801
802
|
} else if (L.has(t)) return L.delete(t), !0;
|
|
802
803
|
} catch (t) {
|
|
803
804
|
memorio.message(`Error removing session item '${e}': ${t}`);
|
|
@@ -811,11 +812,11 @@ Object.defineProperty(globalThis, "session", {
|
|
|
811
812
|
value: () => {
|
|
812
813
|
if (H) {
|
|
813
814
|
const e = [];
|
|
814
|
-
for (let t = 0; t <
|
|
815
|
-
const o =
|
|
815
|
+
for (let t = 0; t < F.length; t++) {
|
|
816
|
+
const o = F.key(t);
|
|
816
817
|
o?.startsWith(V) && e.push(o);
|
|
817
818
|
}
|
|
818
|
-
e.forEach(e =>
|
|
819
|
+
e.forEach(e => F.removeItem(e));
|
|
819
820
|
} else L.clear();
|
|
820
821
|
return !0;
|
|
821
822
|
}
|
|
@@ -829,9 +830,9 @@ Object.defineProperty(globalThis, "session", {
|
|
|
829
830
|
size: {
|
|
830
831
|
value: () => {
|
|
831
832
|
let e = 0;
|
|
832
|
-
return H ? Object.keys(
|
|
833
|
+
return H ? Object.keys(F).forEach(t => {
|
|
833
834
|
if (t.startsWith(V)) {
|
|
834
|
-
const o =
|
|
835
|
+
const o = F.getItem(t);
|
|
835
836
|
o && (e += o.length);
|
|
836
837
|
}
|
|
837
838
|
}) : L.forEach(t => {
|
|
@@ -846,10 +847,10 @@ Object.defineProperty(globalThis, "session", {
|
|
|
846
847
|
value: () => {
|
|
847
848
|
const e = {};
|
|
848
849
|
try {
|
|
849
|
-
if (H) for (let t = 0; t <
|
|
850
|
-
const o =
|
|
850
|
+
if (H) for (let t = 0; t < F.length; t++) {
|
|
851
|
+
const o = F.key(t);
|
|
851
852
|
if (o?.startsWith(V)) {
|
|
852
|
-
const t = o.replace(V, ""), r =
|
|
853
|
+
const t = o.replace(V, ""), r = F.getItem(o);
|
|
853
854
|
if (null !== r) try {
|
|
854
855
|
e[t] = JSON.parse(r);
|
|
855
856
|
} 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.
|
|
324
|
+
value: "4.1.5"
|
|
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 =>
|
|
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
|
|
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 =
|
|
639
|
+
const t = q(e);
|
|
637
640
|
try {
|
|
638
641
|
if (U) {
|
|
639
642
|
const e = W.getItem(t);
|
|
@@ -652,7 +655,7 @@ Object.defineProperty(globalThis, "store", {
|
|
|
652
655
|
set: {
|
|
653
656
|
value: (e, t) => {
|
|
654
657
|
if (!e) return;
|
|
655
|
-
const o =
|
|
658
|
+
const o = q(e);
|
|
656
659
|
try {
|
|
657
660
|
if (U) {
|
|
658
661
|
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 +669,7 @@ Object.defineProperty(globalThis, "store", {
|
|
|
666
669
|
remove: {
|
|
667
670
|
value: e => {
|
|
668
671
|
if (!e) return;
|
|
669
|
-
const t =
|
|
672
|
+
const t = q(e);
|
|
670
673
|
try {
|
|
671
674
|
if (U) {
|
|
672
675
|
if (W.getItem(t)) return W.removeItem(t), !0;
|
|
@@ -747,7 +750,7 @@ Object.defineProperty(globalThis, "store", {
|
|
|
747
750
|
}
|
|
748
751
|
}), Object.freeze(store);
|
|
749
752
|
|
|
750
|
-
var
|
|
753
|
+
var F = D(), L = new Map, H = null !== F, V = "memorio_session_";
|
|
751
754
|
|
|
752
755
|
function Y(e) {
|
|
753
756
|
return e && "string" == typeof e ? e.length > 512 ? (memorio.message("Key too long (max 512 characters)"),
|
|
@@ -766,7 +769,7 @@ Object.defineProperty(globalThis, "session", {
|
|
|
766
769
|
const t = Y(e);
|
|
767
770
|
try {
|
|
768
771
|
if (H) {
|
|
769
|
-
const e =
|
|
772
|
+
const e = F.getItem(t);
|
|
770
773
|
return e ? JSON.parse(e) : e;
|
|
771
774
|
}
|
|
772
775
|
{
|
|
@@ -783,7 +786,7 @@ Object.defineProperty(globalThis, "session", {
|
|
|
783
786
|
if (!e) return;
|
|
784
787
|
const o = Y(e);
|
|
785
788
|
try {
|
|
786
|
-
H ? null == t ?
|
|
789
|
+
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
790
|
} catch (t) {
|
|
788
791
|
memorio.message(`Error setting session item '${e}': ${t}`);
|
|
789
792
|
}
|
|
@@ -795,7 +798,7 @@ Object.defineProperty(globalThis, "session", {
|
|
|
795
798
|
const t = Y(e);
|
|
796
799
|
try {
|
|
797
800
|
if (H) {
|
|
798
|
-
if (
|
|
801
|
+
if (F.getItem(t)) return F.removeItem(t), !0;
|
|
799
802
|
} else if (L.has(t)) return L.delete(t), !0;
|
|
800
803
|
} catch (t) {
|
|
801
804
|
memorio.message(`Error removing session item '${e}': ${t}`);
|
|
@@ -809,11 +812,11 @@ Object.defineProperty(globalThis, "session", {
|
|
|
809
812
|
value: () => {
|
|
810
813
|
if (H) {
|
|
811
814
|
const e = [];
|
|
812
|
-
for (let t = 0; t <
|
|
813
|
-
const o =
|
|
815
|
+
for (let t = 0; t < F.length; t++) {
|
|
816
|
+
const o = F.key(t);
|
|
814
817
|
o?.startsWith(V) && e.push(o);
|
|
815
818
|
}
|
|
816
|
-
e.forEach(e =>
|
|
819
|
+
e.forEach(e => F.removeItem(e));
|
|
817
820
|
} else L.clear();
|
|
818
821
|
return !0;
|
|
819
822
|
}
|
|
@@ -827,9 +830,9 @@ Object.defineProperty(globalThis, "session", {
|
|
|
827
830
|
size: {
|
|
828
831
|
value: () => {
|
|
829
832
|
let e = 0;
|
|
830
|
-
return H ? Object.keys(
|
|
833
|
+
return H ? Object.keys(F).forEach(t => {
|
|
831
834
|
if (t.startsWith(V)) {
|
|
832
|
-
const o =
|
|
835
|
+
const o = F.getItem(t);
|
|
833
836
|
o && (e += o.length);
|
|
834
837
|
}
|
|
835
838
|
}) : L.forEach(t => {
|
|
@@ -844,10 +847,10 @@ Object.defineProperty(globalThis, "session", {
|
|
|
844
847
|
value: () => {
|
|
845
848
|
const e = {};
|
|
846
849
|
try {
|
|
847
|
-
if (H) for (let t = 0; t <
|
|
848
|
-
const o =
|
|
850
|
+
if (H) for (let t = 0; t < F.length; t++) {
|
|
851
|
+
const o = F.key(t);
|
|
849
852
|
if (o?.startsWith(V)) {
|
|
850
|
-
const t = o.replace(V, ""), r =
|
|
853
|
+
const t = o.replace(V, ""), r = F.getItem(o);
|
|
851
854
|
if (null !== r) try {
|
|
852
855
|
e[t] = JSON.parse(r);
|
|
853
856
|
} 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