memorio 4.9.31 → 4.9.35
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/README.md +49 -0
- package/index.cjs +36 -1
- package/index.js +36 -1
- package/modules/redux.cjs +274 -240
- package/modules/redux.cjs.map +1 -1
- package/modules/redux.js +274 -240
- package/modules/redux.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@ The global API is a **choice**, not an architectural requirement.
|
|
|
34
34
|
|
|
35
35
|
- [Why memorio](#why-memorio)
|
|
36
36
|
- [Global is optional](#global-is-optional)
|
|
37
|
+
- [Before / After](#before--after)
|
|
37
38
|
- [Which layer should I use](#which-layer-should-i-use)
|
|
38
39
|
- [Install](#install)
|
|
39
40
|
- [Quick start](#quick-start)
|
|
@@ -50,6 +51,7 @@ The global API is a **choice**, not an architectural requirement.
|
|
|
50
51
|
- [When to use something else](#when-to-use-something-else)
|
|
51
52
|
- [Design philosophy](#design-philosophy)
|
|
52
53
|
- [A mental model](#a-mental-model)
|
|
54
|
+
- [Recipes](#recipes)
|
|
53
55
|
- [License](#license)
|
|
54
56
|
|
|
55
57
|
---
|
|
@@ -124,6 +126,30 @@ npm install sql.js # sqlite engine
|
|
|
124
126
|
|
|
125
127
|
**Zero production dependencies** in the core package. See [Security](#security).
|
|
126
128
|
|
|
129
|
+
## Before / After
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
// Without memorio
|
|
133
|
+
const [user, setUser] = useState(null)
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
const saved = localStorage.getItem('user')
|
|
136
|
+
if (saved) setUser(JSON.parse(saved))
|
|
137
|
+
}, [])
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
localStorage.setItem('user', JSON.stringify(user))
|
|
140
|
+
}, [user])
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
// With memorio
|
|
145
|
+
import 'memorio'
|
|
146
|
+
store.set('user', { name: 'Sara' }) // persistent immediately, no boilerplate
|
|
147
|
+
|
|
148
|
+
const user = store.get('user')
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Same result, one reactive line instead of two effects and manual JSON serialization.
|
|
152
|
+
|
|
127
153
|
## Quick start
|
|
128
154
|
|
|
129
155
|
```ts
|
|
@@ -529,6 +555,29 @@ memorio is intentionally not everything.
|
|
|
529
555
|
|
|
530
556
|
The important part is not that memorio has many layers — it's that **you do not have to use them all**.
|
|
531
557
|
|
|
558
|
+
## Sneak Peek
|
|
559
|
+
|
|
560
|
+
### Making a `state` slice persistent
|
|
561
|
+
|
|
562
|
+
`state` is reactive but not persistent; `store` is persistent but not reactive. `persist()` bridges the two — it restores the value from `store` and then keeps the selected state path synchronized with it:
|
|
563
|
+
|
|
564
|
+
```ts
|
|
565
|
+
import 'memorio'
|
|
566
|
+
|
|
567
|
+
state.user = { name: 'Sara' }
|
|
568
|
+
|
|
569
|
+
const off = persist('state.user') // restore from store, then persist changes
|
|
570
|
+
|
|
571
|
+
// later, e.g. on component unmount
|
|
572
|
+
off()
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
`persist()` uses the same path syntax as `observer()`.
|
|
576
|
+
|
|
577
|
+
Nested paths such as `state.user.preferences.theme` are supported, provided the intermediate objects already exist in `state`.
|
|
578
|
+
|
|
579
|
+
In environments without `localStorage` (Node/Deno/edge), `store` falls back to memory. `persist()` still works there, but persistence does not survive process or runtime restarts.
|
|
580
|
+
|
|
532
581
|
## License
|
|
533
582
|
|
|
534
583
|
MIT © Dario Passariello
|
package/index.cjs
CHANGED
|
@@ -1889,6 +1889,7 @@ var schema = {
|
|
|
1889
1889
|
};
|
|
1890
1890
|
|
|
1891
1891
|
// functions/state/index.ts
|
|
1892
|
+
init_store();
|
|
1892
1893
|
init_env();
|
|
1893
1894
|
var TARGET = /* @__PURE__ */ Symbol("memorio.target");
|
|
1894
1895
|
var wrapperCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -1903,6 +1904,7 @@ var deepRaw = /* @__PURE__ */ __name((val, seen = null) => {
|
|
|
1903
1904
|
if (ctor !== "Object" && ctor !== "Array") return val;
|
|
1904
1905
|
const copy = Array.isArray(val) ? [] : {};
|
|
1905
1906
|
for (const k of Reflect.ownKeys(val)) {
|
|
1907
|
+
if (!Object.prototype.propertyIsEnumerable.call(val, k)) continue;
|
|
1906
1908
|
copy[k] = deepRaw(val[k], seen);
|
|
1907
1909
|
}
|
|
1908
1910
|
return copy;
|
|
@@ -2125,6 +2127,39 @@ if (globalThis[STATE_INSTANCE_KEY]) {
|
|
|
2125
2127
|
exports.internal.locked = false;
|
|
2126
2128
|
message_default("State is now unlocked. Modifications are allowed.");
|
|
2127
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];
|
|
2149
|
+
}
|
|
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
|
+
};
|
|
2128
2163
|
globalThis[STATE_INSTANCE_KEY] = exports.state;
|
|
2129
2164
|
}
|
|
2130
2165
|
|
|
@@ -3303,7 +3338,7 @@ init_internal();
|
|
|
3303
3338
|
|
|
3304
3339
|
// package.json
|
|
3305
3340
|
var package_default = {
|
|
3306
|
-
version: "4.9.
|
|
3341
|
+
version: "4.9.35"};
|
|
3307
3342
|
|
|
3308
3343
|
// core/global.ts
|
|
3309
3344
|
init_env();
|
package/index.js
CHANGED
|
@@ -1886,6 +1886,7 @@ var schema = {
|
|
|
1886
1886
|
};
|
|
1887
1887
|
|
|
1888
1888
|
// functions/state/index.ts
|
|
1889
|
+
init_store();
|
|
1889
1890
|
init_env();
|
|
1890
1891
|
var TARGET = /* @__PURE__ */ Symbol("memorio.target");
|
|
1891
1892
|
var wrapperCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -1900,6 +1901,7 @@ var deepRaw = /* @__PURE__ */ __name((val, seen = null) => {
|
|
|
1900
1901
|
if (ctor !== "Object" && ctor !== "Array") return val;
|
|
1901
1902
|
const copy = Array.isArray(val) ? [] : {};
|
|
1902
1903
|
for (const k of Reflect.ownKeys(val)) {
|
|
1904
|
+
if (!Object.prototype.propertyIsEnumerable.call(val, k)) continue;
|
|
1903
1905
|
copy[k] = deepRaw(val[k], seen);
|
|
1904
1906
|
}
|
|
1905
1907
|
return copy;
|
|
@@ -2122,6 +2124,39 @@ if (globalThis[STATE_INSTANCE_KEY]) {
|
|
|
2122
2124
|
internal_default.locked = false;
|
|
2123
2125
|
message_default("State is now unlocked. Modifications are allowed.");
|
|
2124
2126
|
};
|
|
2127
|
+
state2.persist = (path2) => {
|
|
2128
|
+
if (typeof path2 !== "string" || !path2.length) {
|
|
2129
|
+
if (DEV) console.warn('[memorio state] state.persist() requires a non-empty path string (e.g. "state.user")');
|
|
2130
|
+
return () => {
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
2133
|
+
const normalized = path2.startsWith("state.") ? path2 : "state." + path2;
|
|
2134
|
+
const key = normalized.replace(/^state\./, "");
|
|
2135
|
+
const segments = key.split(".");
|
|
2136
|
+
const initial = store.get(key);
|
|
2137
|
+
if (initial !== void 0 && initial !== null) {
|
|
2138
|
+
let acc = state2;
|
|
2139
|
+
for (let i = 0; i < segments.length; i++) {
|
|
2140
|
+
const seg = segments[i];
|
|
2141
|
+
if (i === segments.length - 1) {
|
|
2142
|
+
acc[seg] = deepRaw(initial);
|
|
2143
|
+
} else {
|
|
2144
|
+
if (acc[seg] === void 0 || acc[seg] === null) acc[seg] = {};
|
|
2145
|
+
acc = acc[seg];
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
const handler = /* @__PURE__ */ __name(() => {
|
|
2150
|
+
let current = state2;
|
|
2151
|
+
for (const seg of segments) {
|
|
2152
|
+
current = current === void 0 || current === null ? void 0 : current[seg];
|
|
2153
|
+
}
|
|
2154
|
+
store.set(key, deepRaw(current));
|
|
2155
|
+
}, "handler");
|
|
2156
|
+
const off = dispatch.listen(normalized, handler);
|
|
2157
|
+
return typeof off === "function" ? off : () => {
|
|
2158
|
+
};
|
|
2159
|
+
};
|
|
2125
2160
|
globalThis[STATE_INSTANCE_KEY] = state2;
|
|
2126
2161
|
}
|
|
2127
2162
|
|
|
@@ -3300,7 +3335,7 @@ init_internal();
|
|
|
3300
3335
|
|
|
3301
3336
|
// package.json
|
|
3302
3337
|
var package_default = {
|
|
3303
|
-
version: "4.9.
|
|
3338
|
+
version: "4.9.35"};
|
|
3304
3339
|
|
|
3305
3340
|
// core/global.ts
|
|
3306
3341
|
init_env();
|