memorio 4.6.8 → 4.7.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.
@@ -0,0 +1,122 @@
1
+ # Memorio DevTools
2
+
3
+ > 🖥️ **Browser Only**: This feature is only available in browser console
4
+
5
+ Browser console debugging tools for inspecting and managing Memorio state.
6
+
7
+ ## Quick Start
8
+
9
+ ```javascript
10
+ // Load memorio first
11
+ import 'memorio'
12
+ ```
13
+
14
+ ## Available Methods
15
+
16
+ ### inspect()
17
+
18
+ Inspect all Memorio modules in the console.
19
+
20
+ ```javascript
21
+ memorio.devtools.inspect()
22
+ ```
23
+
24
+ ### stats()
25
+
26
+ Get statistics about all modules.
27
+
28
+ ```javascript
29
+ memorio.devtools.stats()
30
+ // Returns: { stateKeys, storeKeys, sessionKeys, cacheKeys, idbDatabases, lastUpdate }
31
+ ```
32
+
33
+ ### clear(module)
34
+
35
+ Clear data from a specific module.
36
+
37
+ ```javascript
38
+ memorio.devtools.clear('state')
39
+ memorio.devtools.clear('store')
40
+ memorio.devtools.clear('session')
41
+ memorio.devtools.clear('cache')
42
+ ```
43
+
44
+ ### clearAll()
45
+
46
+ Clear all Memorio data.
47
+
48
+ ```javascript
49
+ memorio.devtools.clearAll()
50
+ ```
51
+
52
+ ### watch(module, path)
53
+
54
+ Watch a specific path for changes.
55
+
56
+ ```javascript
57
+ memorio.devtools.watch('state', 'user.name')
58
+ ```
59
+
60
+ ### exportData()
61
+
62
+ Export all data as JSON.
63
+
64
+ ```javascript
65
+ const json = memorio.devtools.exportData()
66
+ console.debug(json)
67
+ ```
68
+
69
+ ### importData(jsonString)
70
+
71
+ Import data from JSON.
72
+
73
+ ```javascript
74
+ memorio.devtools.importData('{"state":{"key":"value"}}')
75
+ ```
76
+
77
+ ### help()
78
+
79
+ Show help information.
80
+
81
+ ```javascript
82
+ memorio.devtools.help()
83
+ ```
84
+
85
+ ## Console Shortcuts
86
+
87
+ Memorio provides global shortcuts for quick access:
88
+
89
+ ```javascript
90
+ $state // globalThis.state
91
+ $store // globalThis.store
92
+ $session // globalThis.session
93
+ $cache // globalThis.cache
94
+ ```
95
+
96
+ ## Examples
97
+
98
+ ### Inspect current state
99
+
100
+ ```javascript
101
+ memorio.devtools.inspect()
102
+ ```
103
+
104
+ ### Export and restore state
105
+
106
+ ```javascript
107
+ // Export
108
+ const backup = memorio.devtools.exportData()
109
+
110
+ // Later... import
111
+ memorio.devtools.importData(backup)
112
+ ```
113
+
114
+ ### Monitor changes
115
+
116
+ ```javascript
117
+ // Watch a specific path
118
+ memorio.devtools.watch('state', 'counter')
119
+
120
+ // Now changes will be logged to console
121
+ state.counter = 42 // Console shows: 👁 Change: state.counter = 42
122
+ ```
@@ -0,0 +1,168 @@
1
+ # Dispatch - Memorio
2
+
3
+ > ⚛️ **Vanilla JS**: This is for non-React applications. For React, use [`useObserver`](USEOBSERVER.md).
4
+
5
+ `memorio.dispatch` is an event system for vanilla JavaScript applications. It enables pub/sub patterns without React hooks.
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 Event Listening
22
+
23
+ ```javascript
24
+ // Listen for an event
25
+ memorio.dispatch.listen('my:event', (event) => {
26
+ console.debug('Event triggered:', event.detail);
27
+ });
28
+
29
+ // Trigger the event
30
+ memorio.dispatch.set('my:event', { detail: { data: 'Hello World' } });
31
+ // Output: "Event triggered: { data: 'Hello World' }"
32
+ ```
33
+
34
+ ### Example 2: State Reactivity (Vanilla JS)
35
+
36
+ ```javascript
37
+ // React to state changes without React
38
+ memorio.dispatch.listen('state.counter', (event) => {
39
+ console.debug('Counter is now:', event.detail);
40
+ });
41
+
42
+ // Update state
43
+ state.counter = 1;
44
+ // Output: "Counter is now: 1"
45
+
46
+ state.counter = 5;
47
+ // Output: "Counter is now: 5"
48
+ ```
49
+
50
+ ### Example 3: Remove Listener
51
+
52
+ ```javascript
53
+ // Remove a specific event listener
54
+ memorio.dispatch.remove('my:event');
55
+
56
+ // Or remove all listeners for state changes
57
+ memorio.dispatch.remove('state.user');
58
+ ```
59
+
60
+ ---
61
+
62
+ ## API Reference
63
+
64
+ ### memorio.dispatch.set(name, value)
65
+
66
+ Dispatches a custom event with the specified name and value.
67
+
68
+ | Parameter | Type | Description |
69
+ |-----------|------|-------------|
70
+ | `name` | `string` | Event name (e.g., `'my:event'`, `'state.counter'`) |
71
+ | `value` | `object` | Object with `detail` property (default: `{}`) |
72
+
73
+ ```javascript
74
+ memorio.dispatch.set('custom:event', { detail: { data: 'value' } });
75
+ ```
76
+
77
+ ### memorio.dispatch.listen(name, callback)
78
+
79
+ Listens for the specified event and executes the callback when triggered.
80
+
81
+ | Parameter | Type | Description |
82
+ |-----------|------|-------------|
83
+ | `name` | `string` | Event name to listen for |
84
+ | `callback` | `function` | Function called with the event object |
85
+
86
+ ```javascript
87
+ memorio.dispatch.listen('state.user', (event) => {
88
+ console.debug('User changed:', event.detail);
89
+ });
90
+ ```
91
+
92
+ ### memorio.dispatch.remove(name)
93
+
94
+ Removes the event listener for the specified event name.
95
+
96
+ | Parameter | Type | Description |
97
+ |-----------|------|-------------|
98
+ | `name` | `string` | Event name to stop listening |
99
+
100
+ ```javascript
101
+ memorio.dispatch.remove('state.counter');
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Common Patterns
107
+
108
+ ### Form Validation
109
+
110
+ ```javascript
111
+ memorio.dispatch.listen('state.form.email', (event) => {
112
+ const email = event.detail;
113
+ const isValid = email.includes('@');
114
+ state.form.isValid = isValid;
115
+ });
116
+ ```
117
+
118
+ ### Analytics Tracking
119
+
120
+ ```javascript
121
+ memorio.dispatch.listen('state.page', (event) => {
122
+ const page = event.detail;
123
+ analytics.track('page_view', { page });
124
+ });
125
+ ```
126
+
127
+ ### Auto-save
128
+
129
+ ```javascript
130
+ memorio.dispatch.listen('state.draft', (event) => {
131
+ const content = event.detail;
132
+ store.set('autosave', content);
133
+ });
134
+ ```
135
+
136
+ ### Multiple Listeners
137
+
138
+ ```javascript
139
+ // Listen for multiple state changes
140
+ memorio.dispatch.listen('state.user', (e) => console.log('User:', e.detail));
141
+ memorio.dispatch.listen('state.settings', (e) => console.log('Settings:', e.detail));
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Migration from observer()
147
+
148
+ The `observer()` Replace it with `memorio.dispatch.listen()`:
149
+
150
+ ```javascript
151
+ observer('state.counter', (newValue) => {
152
+ console.debug('Counter:', newValue);
153
+ });
154
+
155
+ // NEW (recommended for vanilla JS)
156
+ memorio.dispatch.listen('state.counter', (event) => {
157
+ console.debug('Counter:', event.detail);
158
+ });
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Best Practices
164
+
165
+ 1. Use specific event names: `'state.user.name'` not `'state'`
166
+ 2. Clean up listeners when no longer needed with `memorio.dispatch.remove()`
167
+ 3. Use `event.detail` to access the value
168
+ 4. For React applications, use [`useObserver`](USEOBSERVER.md) instead
@@ -0,0 +1,169 @@
1
+ # IDB - Memorio
2
+
3
+ > 🖥️ **Browser Only**: Requires IndexedDB (not available in Node.js/Deno)
4
+
5
+ IDB provides access to browser IndexedDB for large data storage. Unlike localStorage, IDB can store large amounts of structured data.
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
+ // Create a database
25
+ idb.db.create('myApp');
26
+
27
+ // Add data
28
+ idb.data.set('myApp', 'users', { id: 1, name: 'Mario' });
29
+
30
+ // Get data
31
+ const user = idb.data.get('myApp', 'users', 1);
32
+ console.debug(user.name); // "Mario"
33
+ ```
34
+
35
+ ### Example 2: Intermediate
36
+
37
+ ```javascript
38
+ // Create database with tables
39
+ idb.db.create('store');
40
+ idb.table.create('store', 'products');
41
+
42
+ // Add multiple records
43
+ idb.data.set('store', 'products', { id: 1, name: 'Apple', price: 1.5 });
44
+ idb.data.set('store', 'products', { id: 2, name: 'Banana', price: 0.8 });
45
+
46
+ // List databases
47
+ const databases = idb.db.list();
48
+ console.debug(databases); // ['myApp', 'store']
49
+ ```
50
+
51
+ ### Example 3: Advanced
52
+
53
+ ```javascript
54
+ // Check database support
55
+ if (idb.db.support()) {
56
+ // Use IDB
57
+ }
58
+
59
+ // Get database info
60
+ const version = idb.db.version('store');
61
+ const size = idb.db.size('store');
62
+
63
+ // Delete database
64
+ idb.db.delete('store');
65
+
66
+ // Handle quota
67
+ const quota = idb.db.quota();
68
+ console.debug(`Using ${quota.used} of ${quota.total} bytes`);
69
+ ```
70
+
71
+ ---
72
+
73
+ ## API Reference
74
+
75
+ ### Database Methods
76
+
77
+ | Method | Parameters | Returns | Description |
78
+ |--------|------------|---------|-------------|
79
+ | `idb.db.create(name)` | `name: string` | `void` | Create database |
80
+ | `idb.db.delete(name)` | `name: string` | `void` | Delete database |
81
+ | `idb.db.list()` | none | `string[]` | List all databases |
82
+ | `idb.db.exist(name)` | `name: string` | `boolean` | Check if exists |
83
+ | `idb.db.size(name)` | `name: string` | `number` | Get database size |
84
+ | `idb.db.version(name)` | `name: string` | `number` | Get version |
85
+ | `idb.db.support()` | none | `boolean` | Check browser support |
86
+ | `idb.db.quota()` | none | `object` | Get storage quota |
87
+
88
+ ### Table Methods
89
+
90
+ | Method | Parameters | Returns | Description |
91
+ |--------|------------|---------|-------------|
92
+ | `idb.table.create(db, table)` | `db: string, table: string` | `void` | Create table |
93
+ | `idb.table.size(db, table)` | `db: string, table: string` | `number` | Get table size |
94
+
95
+ ### Data Methods
96
+
97
+ | Method | Parameters | Returns | Description |
98
+ |--------|------------|---------|-------------|
99
+ | `idb.data.get(db, table, id)` | `db, table, id` | `any` | Get single record |
100
+ | `idb.data.set(db, table, data)` | `db, table, data` | `void` | Set record |
101
+ | `idb.data.delete(db, table, id)` | `db, table, id` | `void` | Delete record |
102
+
103
+ ---
104
+
105
+ ## Data Structure
106
+
107
+ Each record needs an `id` field:
108
+
109
+ ```javascript
110
+ idb.data.set('myDB', 'users', {
111
+ id: 1, // Required!
112
+ name: 'Mario',
113
+ email: 'm@test.com'
114
+ });
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Platform Support
120
+
121
+ | Platform | Support | Notes |
122
+ |----------|---------|-------|
123
+ | Browser | ✅ Full | Full IndexedDB support |
124
+ | Edge Worker | ⚠️ Limited | May not be available in all workers |
125
+ | Node.js | ❌ Not available | Use store or session instead |
126
+ | Deno | ❌ Not available | Use store or session instead |
127
+
128
+ ---
129
+
130
+ ## Storage Limits
131
+
132
+ - **Desktop browsers**: 50+ MB (often unlimited)
133
+ - **Mobile browsers**: 50-100 MB
134
+ - **More than localStorage**: Much higher limits
135
+
136
+ ---
137
+
138
+ ## Best Practices
139
+
140
+ 1. Always include `id` in records
141
+ 2. Use for large data: images, caches, offline data
142
+ 3. Check support: `idb.db.support()`
143
+ 4. Clean up: `idb.db.delete('tempDB')`
144
+
145
+ ---
146
+
147
+ ## Use Cases
148
+
149
+ ### Offline Data
150
+
151
+ ```javascript
152
+ // Cache API response
153
+ idb.data.set('cache', 'apiResponse', {
154
+ id: 'users',
155
+ data: usersArray,
156
+ timestamp: Date.now()
157
+ });
158
+ ```
159
+
160
+ ### Large User Data
161
+
162
+ ```javascript
163
+ // Store user-generated content
164
+ idb.data.set('app', 'uploads', {
165
+ id: Date.now(),
166
+ file: fileData,
167
+ userId: currentUser.id
168
+ });
169
+ ```
@@ -0,0 +1,139 @@
1
+ # Classic `import` support
2
+
3
+ Memorio supports two equivalent styles: the original global side-effect import,
4
+ and the new named exports. Both share the same instances (one source of truth).
5
+
6
+ ```typescript
7
+ // Global style (original)
8
+ import 'memorio'
9
+ state.user = { name: 'Sara' }
10
+
11
+ // Classic import style (new)
12
+ import { state } from 'memorio'
13
+ state.user = { name: 'Sara' }
14
+ ```
15
+
16
+ `state` in both examples is the exact same Proxy object.
17
+
18
+ ---
19
+
20
+ ## Why two styles?
21
+
22
+ | Style | When to use |
23
+ |-------|-------------|
24
+ | `import 'memorio'` | Zero-config, global access everywhere, legacy scripts |
25
+ | `import { state } from 'memorio'` | Explicit dependencies, tree-shakeable bundles, TypeScript IntelliSense |
26
+
27
+ ---
28
+
29
+ ## ESM named imports
30
+
31
+ All modules are available as named exports:
32
+
33
+ ```typescript
34
+ import {
35
+ state,
36
+ store,
37
+ session,
38
+ cache,
39
+ idb,
40
+ observer,
41
+ useObserver,
42
+ dispatch,
43
+ message,
44
+ devtools,
45
+ logger
46
+ } from 'memorio'
47
+ ```
48
+
49
+ Platform helpers:
50
+
51
+ ```typescript
52
+ import {
53
+ isBrowser,
54
+ isNode,
55
+ isDeno,
56
+ isEdge,
57
+ getCapabilities,
58
+ createContext,
59
+ listContexts,
60
+ deleteContext
61
+ } from 'memorio'
62
+ ```
63
+
64
+ Internal utilities (for tests/debug):
65
+
66
+ ```typescript
67
+ import internal, { propertyName } from 'memorio'
68
+ import { setContext, getContext } from 'memorio'
69
+ ```
70
+
71
+ Default export (the public `memorio` namespace):
72
+
73
+ ```typescript
74
+ import memorio from 'memorio'
75
+ memorio.help()
76
+ ```
77
+
78
+ ---
79
+
80
+ ## CJS usage
81
+
82
+ ```javascript
83
+ const { state, store, memorio } = require('memorio')
84
+ ```
85
+
86
+ ---
87
+
88
+ ## React / useObserver
89
+
90
+ `useObserver` works the same way via named import:
91
+
92
+ ```tsx
93
+ import { useObserver, state } from 'memorio'
94
+
95
+ function Counter() {
96
+ const [, forceUpdate] = useReducer(x => x + 1, 0)
97
+
98
+ useObserver(forceUpdate, [state.counter])
99
+
100
+ return <div>Count: {state.counter}</div>
101
+ }
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Context isolation
107
+
108
+ ```typescript
109
+ import { createContext, listContexts, deleteContext, isolate } from 'memorio'
110
+
111
+ const ctx = createContext('tenant-123')
112
+ ctx.state.user = { name: 'Isolated' }
113
+ ctx.store.set('settings', { theme: 'dark' })
114
+
115
+ listContexts() // ['tenant-123']
116
+ deleteContext('tenant-123')
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Same-instance guarantee
122
+
123
+ Named exports point to the same instances published on `globalThis` by
124
+ `core/global` at bootstrap. Mutating via named export mutates the global,
125
+ and vice versa.
126
+
127
+ ```typescript
128
+ import { state } from 'memorio'
129
+
130
+ state.importedFlag = true
131
+ console.debug(globalThis.state.importedFlag) // true
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Migration from global-only
137
+
138
+ No code changes required. Existing `import 'memorio'` + `state.foo = 1`
139
+ continues to work unchanged. Named exports are additive.