memorio 4.7.3 → 4.9.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/markdown/STORE.md DELETED
@@ -1,164 +0,0 @@
1
- # Store - Memorio
2
-
3
- > 🖥️ **Browser & Edge**: Uses localStorage for persistence
4
- > ⚙️ **Node.js/Deno**: Falls back to in-memory storage (not persistent)
5
-
6
- Store provides persistent localStorage management with a simple API. Data survives page refreshes and browser restarts.
7
-
8
- ## Installation
9
-
10
- ```bash
11
- npm install memorio
12
- ```
13
-
14
- ```javascript
15
- import 'memorio';
16
- ```
17
-
18
- > **Classic `import`**: `store` is also a named export.
19
- > `import { store } from 'memorio'` returns the exact same instance as `globalThis.store`.
20
-
21
- ---
22
-
23
- ## Quick Examples
24
-
25
- ### Example 1: Basic Usage
26
-
27
- ```javascript
28
- // Save data
29
- store.set('username', 'Mario');
30
- store.set('score', 1500);
31
-
32
- // Read data
33
- console.debug(store.get('username')); // "Mario"
34
- console.debug(store.get('score')); // 1500
35
-
36
- // Check if using real persistence
37
- console.debug(store.isPersistent); // true in browser, false in Node.js/Deno
38
- ```
39
-
40
- ### Example 2: Intermediate
41
-
42
- ```javascript
43
- // Store objects
44
- store.set('user', { name: 'Luigi', level: 5 });
45
- const user = store.get('user');
46
- console.debug(user.name); // "Luigi"
47
-
48
- // Remove single item
49
- store.remove('username');
50
-
51
- // Check size
52
- const totalSize = store.size();
53
- console.debug(`${totalSize} bytes`);
54
- ```
55
-
56
- ### Example 3: Advanced
57
-
58
- ```javascript
59
- // Get storage quota (returns Promise<[usage, quota]> in KB)
60
- const [used, total] = await store.quota();
61
- console.debug(`Using ${used} out of ${total} KB`);
62
-
63
- // Get total size in characters
64
- const size = store.size();
65
- console.debug(`${size} bytes`);
66
-
67
- // Clear all data
68
- store.removeAll();
69
- // or use alias
70
- store.clearAll();
71
-
72
- // Handle errors gracefully
73
- try {
74
- store.set('largeData', hugeObject);
75
- } catch (err) {
76
- console.error('Storage full:', err);
77
- }
78
- ```
79
-
80
- ---
81
-
82
- ## API Reference
83
-
84
- ### Methods
85
-
86
- | Method | Parameters | Returns | Description |
87
- |--------|------------|---------|-------------|
88
- | `store.get(name)` | `name: string` | `any` | Get value from storage |
89
- | `store.set(name, value)` | `name: string, value: any` | `void` | Save value to storage |
90
- | `store.remove(name)` | `name: string` | `boolean` | Remove single item |
91
- | `store.delete(name)` | `name: string` | `boolean` | Alias for remove |
92
- | `store.removeAll()` | none | `boolean` | Clear all storage |
93
- | `store.clearAll()` | none | `boolean` | Alias for removeAll |
94
- | `store.size()` | none | `number` | Get total size in characters |
95
- | `store.quota()` | none | `Promise<[number, number]>` | Get storage usage/quota in KB |
96
-
97
- ### Properties
98
-
99
- | Property | Type | Description |
100
- |----------|------|-------------|
101
- | `store.isPersistent` | `boolean` | `true` if using real localStorage, `false` if in-memory fallback |
102
-
103
- ### Supported Types
104
-
105
- ```javascript
106
- // All JSON-serializable types work
107
- store.set('string', 'hello');
108
- store.set('number', 42);
109
- store.set('boolean', true);
110
- store.set('array', [1, 2, 3]);
111
- store.set('object', { key: 'value' });
112
- store.set('null', null);
113
- store.set('undefined', null); // converted to null
114
- ```
115
-
116
- ### Not Supported
117
-
118
- ```javascript
119
- // Functions will log an error
120
- store.set('myFunc', () => {});
121
- // Output: "It's not secure to store functions."
122
- ```
123
-
124
- ---
125
-
126
- ## Platform Comparison
127
-
128
- | Feature | Store | Session | Cache | IDB |
129
- |---------|-------|---------|-------|-----|
130
- | **Storage** | localStorage | sessionStorage | Memory | IndexedDB |
131
- | **Lifetime** | Forever | Until tab closes | Until refresh | Forever |
132
- | **Capacity** | ~5-10 MB | ~5-10 MB | Unlimited | 50+ MB |
133
- | **Platform** | Browser/Edge | Browser/Edge | All | Browser |
134
- | **Persistence** | ✅ true | N/A | ❌ false | ✅ true |
135
-
136
- ---
137
-
138
- ## How It Works
139
-
140
- Store wraps the browser's `localStorage` API with:
141
-
142
- - Automatic JSON serialization/deserialization
143
- - Error handling for parse failures
144
- - Size calculation
145
- - Quota monitoring
146
-
147
- ---
148
-
149
- ## Storage Limits
150
-
151
- - **Chrome/Safari**: ~5-10 MB
152
- - **Firefox**: ~10 MB
153
- - **Edge**: ~5-10 MB
154
-
155
- Use `store.quota()` to monitor usage.
156
-
157
- ---
158
-
159
- ## Best Practices
160
-
161
- 1. Prefix keys: `store.set('app_username', '...')`
162
- 2. Check before set: `if (store.get('key')) { ... }`
163
- 3. Handle quota: Try/catch around large data
164
- 4. Clean up: `store.removeAll()` on logout
package/markdown/TYPED.md DELETED
@@ -1,158 +0,0 @@
1
- # Typed Stores - Memorio
2
-
3
- > ✅ **Universal**: Works in Browser, Node.js, Deno, and Edge Workers
4
-
5
- `memorio.typed<T>()` returns the global `state` proxy cast to a TypeScript type `T`, giving you **compile-time** type safety on every access and mutation.
6
-
7
- It's a **zero-runtime-cost** wrapper: the returned object is the *exact same* Proxy as `globalThis.state`, just with TypeScript types applied via a generic.
8
-
9
- ---
10
-
11
- ## Quick Start
12
-
13
- ```typescript
14
- import 'memorio'
15
-
16
- interface AppState {
17
- user: { name: string; age: number; email: string }
18
- theme: 'light' | 'dark'
19
- items: string[]
20
- }
21
-
22
- const app = memorio.typed<AppState>()
23
-
24
- // Type-checked at compile time:
25
- app.user = { name: 'Sara', age: 30, email: 'sara@test.com' }
26
- app.theme = 'dark'
27
-
28
- // TypeScript errors:
29
- // app.user = { name: 42 } // age missing, name wrong type
30
- // app.theme = 'purple' // not a valid literal
31
- ```
32
-
33
- ---
34
-
35
- ## Why use typed stores?
36
-
37
- | Without typed | With `memorio.typed<T>()` |
38
- |---|---|
39
- | `state.user = { name: 42 }` — runs silently, bug at runtime | `app.user = { name: 42 }` — TypeScript error at compile time |
40
- | No autocomplete on `state.user.email` | Full IntelliSense: properties, types, method suggestions |
41
- | Rename `user` to `profile` — no compiler warning anywhere | Every `app.user` access flagged as an error |
42
- | AI-generated code lacks guardrails | AI gets autocomplete and type feedback inline |
43
-
44
- ---
45
-
46
- ## Combine with Schema Validation
47
-
48
- Typed stores catch type errors at compile time; schema validation catches invalid values at runtime. Together they form a **defense-in-depth** strategy:
49
-
50
- ```typescript
51
- import 'memorio'
52
-
53
- interface ProfileState {
54
- profile: { bio: string; avatar?: string }
55
- }
56
-
57
- const app = memorio.typed<ProfileState>()
58
-
59
- memorio.registerSchema('profile', {
60
- type: 'object',
61
- required: ['bio'],
62
- properties: {
63
- bio: { type: 'string', min: 1 },
64
- avatar: { type: 'string' }
65
- }
66
- })
67
-
68
- app.profile = { bio: 'Developer', avatar: 'pic.png' } // ✅ type + schema pass
69
- app.profile = { avatar: 'pic.png' } // ❌ TypeScript: bio missing
70
- // ❌ Runtime: bio required
71
- ```
72
-
73
- See [Schema Validation](SCHEMA.md) for runtime validation details.
74
-
75
- ---
76
-
77
- ## Named import variant
78
-
79
- `typed` is also available as a named export if you prefer explicit dependencies:
80
-
81
- ```typescript
82
- import { typed } from 'memorio'
83
-
84
- const app = typed<AppState>()
85
- ```
86
-
87
- The `memorio` namespace object is the same — `import 'memorio'` is the recommended entry, named exports are an alternative.
88
-
89
- ---
90
-
91
- ## Full API
92
-
93
- | Method | Parameters | Returns | Description |
94
- |--------|-----------|---------|-------------|
95
- | `memorio.typed<T>()` | Generic type `T` | `T` | Returns the global `state` proxy cast to `T` |
96
-
97
- The returned object shares the same identity as `globalThis.state`:
98
-
99
- ```typescript
100
- const app = memorio.typed<AppState>()
101
- console.debug(app === state) // true — same Proxy instance
102
- ```
103
-
104
- ---
105
-
106
- ## React + typed stores
107
-
108
- Pair with the `useObserver` hook for type-safe, reactive React components:
109
-
110
- ```tsx
111
- import 'memorio'
112
- import { useReducer } from 'react'
113
-
114
- interface AppState {
115
- user: { name: string; age: number }
116
- theme: 'light' | 'dark'
117
- }
118
-
119
- const app = memorio.typed<AppState>()
120
-
121
- function UserProfile() {
122
- const [, forceUpdate] = useReducer(x => x + 1, 0)
123
-
124
- useObserver(forceUpdate, [state.user.name])
125
-
126
- return (
127
- <div>
128
- <h1>{app.user.name}</h1>
129
- <span>Theme: {app.theme}</span>
130
- </div>
131
- )
132
- }
133
- ```
134
-
135
- ---
136
-
137
- ## Best Practices
138
-
139
- 1. **Define your AppState at the root** of your app and import it everywhere:
140
-
141
- ```typescript
142
- // types/app-state.ts
143
- export interface AppState {
144
- user: { name: string; email: string }
145
- theme: 'light' | 'dark'
146
- }
147
- ```
148
-
149
- ```typescript
150
- // anywhere in your app
151
- import 'memorio'
152
- import type { AppState } from '../types/app-state'
153
- const app = memorio.typed<AppState>()
154
- ```
155
-
156
- 2. **Layer schema validation on top** for runtime safety, especially for data coming from APIs or user input.
157
-
158
- 3. **Use alongside `memorio.help()`** to list available globals during development.
@@ -1,259 +0,0 @@
1
- # useObserver - Memorio
2
-
3
- > ⚛️ **React Only**: This is a React hook and only works within React components
4
-
5
- useObserver is a React hook for observing state changes. It automatically subscribes to state changes and includes powerful auto-discovery features.
6
-
7
- ## Installation
8
-
9
- ```bash
10
- npm install memorio
11
- ```
12
-
13
- ```javascript
14
- import 'memorio';
15
- ```
16
-
17
- ---
18
-
19
- ## Quick Examples
20
-
21
- ### Example 1: Basic Usage
22
-
23
- ```javascript
24
- import 'memorio';
25
-
26
- function Counter() {
27
- // Direct values work! ✅
28
- useObserver(() => {
29
- console.debug('Counter changed:', state.counter);
30
- }, [state.counter]);
31
-
32
- return <div>{state.counter}</div>;
33
- }
34
- ```
35
-
36
- ### Auto-Discovery (Magic Mode)
37
-
38
- ```javascript
39
- // Pass your callback WITHOUT dependencies - it auto-discovers!
40
- function MyComponent() {
41
- useObserver(() => {
42
- // This will automatically track ALL state properties used inside
43
- console.debug('Something changed:', state.user.name, state.items.length);
44
- });
45
-
46
- return <div>{state.user.name}</div>;
47
- }
48
- ```
49
-
50
- ### Example 2: Intermediate
51
-
52
- ```javascript
53
- function UserProfile() {
54
- const [localState, setLocalState] = useState(null);
55
-
56
- useObserver(() => {
57
- setLocalState(state.user);
58
- }, [state.user]);
59
-
60
- return <div>{localState?.name}</div>;
61
- }
62
- ```
63
-
64
- ### Example 3: Advanced
65
-
66
- ```javascript
67
- // Multiple watchers with array - works with direct values
68
- function MultiWatch() {
69
- useObserver(() => {
70
- console.debug('A or B changed:', state.a, state.b);
71
- }, [state.a, state.b]); // Direct values work!
72
-
73
- return <div>{state.a} - {state.b}</div>;
74
- }
75
-
76
- // With string path (for store)
77
- function StoreWatcher() {
78
- useObserver(() => {
79
- console.debug('Store changed');
80
- }, 'store.userPreferences');
81
-
82
- return <div />;
83
- }
84
- ```
85
- // With string path (for store)
86
- function StoreWatcher() {
87
- useObserver(() => {
88
- console.debug('Store changed');
89
- }, 'store.userPreferences');
90
-
91
- return <div />;
92
- }
93
- ```
94
-
95
- ---
96
-
97
- ## API Reference
98
-
99
- ### useObserver(callback, deps)
100
-
101
- | Parameter | Type | Description |
102
- | --------- | ---- | ----------- |
103
- | `callback` | `function` | Function to run on change |
104
- | `deps` | `function \| string \| array \| proxy` | State path(s) to watch. Supports: |
105
- | | | - Direct values: `state.counter` |
106
- | | | - String paths: `'state.counter'` |
107
- | | | - Arrow functions: `() => state.counter` |
108
- | | | - Arrays: `[state.a, state.b]` or `['state.a', 'state.b']` |
109
- | | | - Optional chaining: `[state?.one]` |
110
-
111
- ### Primitive Values
112
-
113
- Direct primitive values are now fully supported:
114
-
115
- ```javascript
116
- // Direct values work with primitives ✅
117
- useObserver(() => { console.debug('changed') }, [state.counter])
118
-
119
- // Arrays of primitives work ✅
120
- useObserver(() => { console.log(state.a, state.b) }, [state.a, state.b])
121
-
122
- // Optional chaining works ✅
123
- useObserver(() => { console.log(state?.one) }, [state?.one])
124
-
125
- // Strings still work ✅
126
- useObserver(() => { console.debug('changed') }, ['state.counter'])
127
-
128
- // Functions still work ✅
129
- useObserver(() => { console.debug('changed') }, [() => state.counter])
130
- ```
131
-
132
- ### Callback Parameters
133
-
134
- ```javascript
135
- // Single value (no array needed)
136
- useObserver(
137
- () => {
138
- console.debug('Changed:', state.key);
139
- }, state.key // Single value works!
140
- );
141
-
142
- // Array of values
143
- useObserver(
144
- () => {
145
- console.debug('Changed:', state.key);
146
- }, [state.key] // Array also works!
147
- );
148
- ```
149
-
150
- ### Auto-Discovery Mode
151
-
152
- When `deps` is omitted, useObserver automatically discovers all state properties accessed inside the callback:
153
-
154
- ```javascript
155
- // No deps needed - magic auto-discovery!
156
- useObserver(() => {
157
- // Automatically tracks state.user, state.items, state.counter
158
- console.debug(state.user.name, state.items.length, state.counter);
159
- },[]);
160
- ```
161
-
162
- Returns a cleanup function:
163
-
164
- ## useObserver vs observer
165
-
166
- | Feature | observer | useObserver |
167
- | ------- | -------- | ----------- |
168
- | Framework | Vanilla JS | React |
169
- | Auto-cleanup | Manual | Auto |
170
- | React lifecycle | No | Yes |
171
-
172
- ---
173
-
174
- ## Common Patterns
175
-
176
- ### Sync with useState (Recommended for Primitives)
177
-
178
- ```javascript
179
- function CounterComponent() {
180
- // Sync memorio state with React state
181
- const [counter, setCounter] = useState(state.counter)
182
-
183
- // React useEffect works correctly with primitive values
184
- useEffect(() => {
185
- console.log('Counter changed:', counter)
186
- }, [counter])
187
-
188
- // Direct values now work with primitives!
189
- useObserver(() => {
190
- setCounter(state.counter)
191
- }, [state.counter]) // ✅ Works now!
192
-
193
- return (
194
- <div>
195
- <button onClick={() => { state.counter++ }}>Increment</button>
196
- <span>{counter}</span>
197
- </div>
198
- )
199
- }
200
- ```
201
-
202
- ### Safe Access with Optional Chaining (Protection)
203
-
204
- ```javascript
205
- // Optional chaining is supported - protects against errors
206
- useObserver(() => {
207
- if (test?.one) {
208
- console.log(test.one)
209
- }
210
- }, [test?.one])
211
-
212
- // Works with objects
213
- function SafeComponent() {
214
- const [test, setTest] = useState(state.test)
215
-
216
- useEffect(() => {
217
- if (test?.one) {
218
- console.log('test.one:', test.one)
219
- }
220
- }, [test?.one])
221
-
222
- useObserver(() => {
223
- if (state.test?.one) {
224
- setTest(state.test)
225
- }
226
- }, ['state.test.one'])
227
-
228
- return <div>{test?.one || 'Loading...'}</div>
229
- }
230
- ```
231
-
232
- ### Multiple Watchers
233
-
234
- ```javascript
235
- // Watch multiple properties with strings
236
- useObserver(() => {
237
- console.log(state.a, state.b)
238
- }, ['state.a', 'state.b'])
239
-
240
- // Watch multiple properties with functions
241
- useObserver(() => {
242
- console.log(state.a, state.b)
243
- }, [() => state.a, () => state.b])
244
-
245
- // Watch with auto-discovery
246
- useObserver(() => {
247
- console.log(state.a, state.b) // Automatically tracks both
248
- }, [])
249
- ```
250
-
251
- ---
252
-
253
- ## Best Practices
254
-
255
- 1. Always use in React components
256
- 2. Use auto-discovery for simpler code: `useObserver(() => { ... })`
257
- 3. No manual cleanup needed - returns cleanup function automatically
258
- 4. Use with state for reactive UI
259
- 5. Check console for auto-discovery logs