memorio 4.9.35 → 5.0.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.
Files changed (76) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +307 -359
  3. package/SECURITY.md +17 -1
  4. package/SUMMARY.md +59 -45
  5. package/adr/001-state-proxy-model.md +96 -0
  6. package/adr/002-observer-semantics.md +180 -0
  7. package/adr/003-deep-mutation-semantics.md +129 -0
  8. package/adr/004-array-mutation-semantics.md +128 -0
  9. package/adr/005-scheduler-contract.md +149 -0
  10. package/adr/006-context-isolation.md +92 -0
  11. package/adr/007-mutation-records.md +118 -0
  12. package/adr/008-transactions.md +106 -0
  13. package/adr/009-history-model.md +110 -0
  14. package/adr/README.md +46 -0
  15. package/adr/template.md +49 -0
  16. package/examples/basic.ts +115 -115
  17. package/examples/browser-vanilla.html +358 -358
  18. package/examples/cache.ts +72 -72
  19. package/examples/cross-platform-guards.ts +57 -57
  20. package/examples/history.ts +104 -0
  21. package/examples/idb.ts +109 -109
  22. package/examples/multi-tenant-context.ts +44 -44
  23. package/examples/node-server.ts +308 -308
  24. package/examples/observer.ts +60 -60
  25. package/examples/platform.ts +115 -115
  26. package/examples/react-app.tsx +362 -362
  27. package/examples/react-observer.tsx +63 -63
  28. package/examples/semantic-memory.ts +60 -60
  29. package/examples/session-advanced.ts +91 -91
  30. package/examples/sqlite-batched-writes.ts +57 -57
  31. package/examples/state-advanced.ts +89 -89
  32. package/examples/store-advanced.ts +117 -117
  33. package/examples/sync.ts +90 -0
  34. package/examples/typed-and-schema.ts +102 -100
  35. package/examples/useObserver.tsx +140 -141
  36. package/global.cjs +4594 -0
  37. package/global.d.ts +8 -0
  38. package/global.js +4532 -0
  39. package/index.cjs +700 -678
  40. package/index.d.ts +1 -0
  41. package/index.js +680 -677
  42. package/llms.txt +72 -4
  43. package/markdown/AUDIT-REPORT.md +135 -0
  44. package/markdown/CACHE.md +100 -0
  45. package/markdown/CHANGELOG.md +243 -0
  46. package/markdown/DEVTOOLS.md +129 -0
  47. package/markdown/DISPATCH.md +177 -0
  48. package/markdown/HISTORY.md +199 -0
  49. package/markdown/IDB.md +178 -0
  50. package/markdown/IMPORT.md +153 -0
  51. package/markdown/INSPECT.md +123 -0
  52. package/markdown/LOGGER.md +154 -0
  53. package/markdown/MEMORY-ATTACHMENT.md +96 -0
  54. package/markdown/MEMORY.md +162 -0
  55. package/markdown/OBSERVER.md +209 -0
  56. package/markdown/PLATFORM.md +271 -0
  57. package/markdown/PROJECT.md +311 -0
  58. package/markdown/SCHEMA.md +176 -0
  59. package/markdown/SECURITY.md +330 -0
  60. package/markdown/SESSION.md +165 -0
  61. package/markdown/SQLITE.md +190 -0
  62. package/markdown/STATE.md +160 -0
  63. package/markdown/STORE.md +171 -0
  64. package/markdown/SYNC.md +319 -0
  65. package/markdown/TYPED.md +165 -0
  66. package/markdown/USEOBSERVER.md +257 -0
  67. package/modules/redux.cjs +320 -167
  68. package/modules/redux.cjs.map +1 -1
  69. package/modules/redux.js +320 -167
  70. package/modules/redux.js.map +1 -1
  71. package/package.json +13 -3
  72. package/types/env.d.ts +19 -9
  73. package/types/exports.d.ts +20 -0
  74. package/types/history.d.ts +13 -1
  75. package/types/memorio.d.ts +17 -5
  76. package/types/mutation.d.ts +75 -0
@@ -1,89 +1,89 @@
1
- /**
2
- * Memorio State Advanced Example
3
- *
4
- * This example shows advanced state features: locking, path tracking, and nesting.
5
- *
6
- * Run: npx ts-node examples/state-advanced.ts
7
- */
8
-
9
- import 'memorio'
10
-
11
- // ============================================
12
- // NESTED OBJECTS
13
- // ============================================
14
-
15
- // Create nested state
16
- state.user = {
17
- name: 'Mario',
18
- profile: {
19
- email: 'mario@example.com',
20
- settings: {
21
- theme: 'dark',
22
- notifications: true
23
- }
24
- }
25
- }
26
-
27
- // Access nested values
28
- console.debug('User name:', state.user.name)
29
- console.debug('Email:', state.user.profile.email)
30
- console.debug('Theme:', state.user.profile.settings.theme)
31
-
32
- // ============================================
33
- // ARRAYS
34
- // ============================================
35
-
36
- // State arrays work like regular arrays
37
- state.items = [1, 2, 3]
38
- state.items.push(4)
39
- console.debug('Items:', state.items) // [1, 2, 3, 4]
40
-
41
- state.users = [
42
- { name: 'Mario', id: 1 },
43
- { name: 'Luigi', id: 2 }
44
- ]
45
- state.users.push({ name: 'Peach', id: 3 })
46
- console.debug('Users:', state.users)
47
-
48
- // ============================================
49
- // LOCKING STATE
50
- // ============================================
51
-
52
- // Lock a value to prevent modifications
53
- state.config = { maxUsers: 100, timeout: 30 }
54
- state.config.lock()
55
-
56
- // This will fail:
57
- // state.config.maxUsers = 200 // Error: state 'config' is locked
58
-
59
- console.debug('Config locked:', state.config)
60
-
61
- // ============================================
62
- // PATH TRACKING
63
- // ============================================
64
-
65
- // Get path information
66
- console.debug('Path:', state.user.__path) // "state.user"
67
-
68
- // Use path tracker for debugging
69
- const path = state.user.profile
70
- console.debug('Profile path:', path.email.toString()) // "state.user.profile.email"
71
-
72
- // ============================================
73
- // LIST ALL STATES
74
- // ============================================
75
-
76
- // Get all current state keys
77
- console.debug('All states:', state.list)
78
-
79
- // ============================================
80
- // REMOVE STATE
81
- // ============================================
82
-
83
- // Remove specific state
84
- state.remove('items')
85
-
86
- // Remove all states
87
- // state.removeAll()
88
-
89
- console.debug('State advanced example complete!')
1
+ /**
2
+ * Memorio State Advanced Example
3
+ *
4
+ * This example shows advanced state features: locking, path tracking, and nesting.
5
+ *
6
+ * Run: npx ts-node examples/state-advanced.ts
7
+ */
8
+
9
+ import { state } from 'memorio'
10
+
11
+ // ============================================
12
+ // NESTED OBJECTS
13
+ // ============================================
14
+
15
+ // Create nested state
16
+ state.user = {
17
+ name: 'Mario',
18
+ profile: {
19
+ email: 'mario@example.com',
20
+ settings: {
21
+ theme: 'dark',
22
+ notifications: true
23
+ }
24
+ }
25
+ }
26
+
27
+ // Access nested values
28
+ console.debug('User name:', state.user.name)
29
+ console.debug('Email:', state.user.profile.email)
30
+ console.debug('Theme:', state.user.profile.settings.theme)
31
+
32
+ // ============================================
33
+ // ARRAYS
34
+ // ============================================
35
+
36
+ // State arrays work like regular arrays
37
+ state.items = [1, 2, 3]
38
+ state.items.push(4)
39
+ console.debug('Items:', state.items) // [1, 2, 3, 4]
40
+
41
+ state.users = [
42
+ { name: 'Mario', id: 1 },
43
+ { name: 'Luigi', id: 2 }
44
+ ]
45
+ state.users.push({ name: 'Peach', id: 3 })
46
+ console.debug('Users:', state.users)
47
+
48
+ // ============================================
49
+ // LOCKING STATE
50
+ // ============================================
51
+
52
+ // Lock a value to prevent modifications
53
+ state.config = { maxUsers: 100, timeout: 30 }
54
+ state.config.lock()
55
+
56
+ // This will fail:
57
+ // state.config.maxUsers = 200 // Error: state 'config' is locked
58
+
59
+ console.debug('Config locked:', state.config)
60
+
61
+ // ============================================
62
+ // PATH TRACKING
63
+ // ============================================
64
+
65
+ // Get path information
66
+ console.debug('Path:', state.user.__path) // "state.user"
67
+
68
+ // Use path tracker for debugging
69
+ const path = state.user.profile
70
+ console.debug('Profile path:', path.email.toString()) // "state.user.profile.email"
71
+
72
+ // ============================================
73
+ // LIST ALL STATES
74
+ // ============================================
75
+
76
+ // Get all current state keys
77
+ console.debug('All states:', state.list)
78
+
79
+ // ============================================
80
+ // REMOVE STATE
81
+ // ============================================
82
+
83
+ // Remove specific state
84
+ state.remove('items')
85
+
86
+ // Remove all states
87
+ // state.removeAll()
88
+
89
+ console.debug('State advanced example complete!')
@@ -1,117 +1,117 @@
1
- /**
2
- * Memorio Store Advanced Example
3
- *
4
- * This example shows advanced store (localStorage) operations.
5
- *
6
- * Run: npx ts-node examples/store-advanced.ts
7
- */
8
-
9
- import 'memorio'
10
-
11
- // ============================================
12
- // CHECK PERSISTENCE
13
- // ============================================
14
-
15
- console.debug('=== Store Persistence Check ===')
16
- console.debug('Is persistent (survives restart):', store.isPersistent)
17
- // In browser: true (localStorage)
18
- // In Node.js/Deno: false (memory fallback)
19
-
20
- if (!store.isPersistent) {
21
- console.debug('⚠️ Warning: Using in-memory storage. Data will be lost on restart!')
22
- }
23
-
24
- // ============================================
25
- // PERSIST USER PREFERENCES
26
- // ============================================
27
-
28
- // Save user preferences
29
- store.set('preferences', {
30
- theme: 'dark',
31
- language: 'en',
32
- notifications: true,
33
- fontSize: 16
34
- })
35
-
36
- // ============================================
37
- // CHECK AND LOAD PREFERENCES
38
- // ============================================
39
-
40
- const savedPrefs = store.get('preferences')
41
- if (savedPrefs) {
42
- console.debug('Loaded preferences:', savedPrefs)
43
- } else {
44
- console.debug('No preferences found, using defaults')
45
- store.set('preferences', { theme: 'light', language: 'en' })
46
- }
47
-
48
- // ============================================
49
- // STORAGE QUOTA
50
- // ============================================
51
-
52
- // Get storage size
53
- const currentSize = store.size()
54
- console.debug('Current storage size:', currentSize, 'kilobytes')
55
-
56
- // ============================================
57
- // ALIAS METHODS
58
- // ============================================
59
-
60
- // store.delete() is alias for store.remove()
61
- store.set('temp', 'value')
62
- store.delete('temp')
63
-
64
- // store.clearAll() is alias for store.removeAll()
65
- // store.clearAll()
66
-
67
- // ============================================
68
- // ERROR HANDLING
69
- // ============================================
70
-
71
- // Try-catch for large data
72
- try {
73
- // Store large data
74
- const largeData = {
75
- items: Array(1000).fill(null).map((_, i) => ({ id: i, data: 'x'.repeat(100) }))
76
- }
77
- store.set('largeData', largeData)
78
- console.debug('Large data stored successfully')
79
- } catch (error) {
80
- console.error('Storage full:', error)
81
- }
82
-
83
- // ============================================
84
- // DATA SERIALIZATION
85
- // ============================================
86
-
87
- // Store supports all JSON-serializable types
88
- store.set('string', 'hello')
89
- store.set('number', 42)
90
- store.set('boolean', true)
91
- store.set('array', [1, 2, 3])
92
- store.set('object', { nested: { value: 'deep' } })
93
- store.set('null', null)
94
-
95
- // Functions are not supported (logged as error)
96
- store.set('function', () => { }) // logs: "It's not secure to store functions."
97
-
98
- // ============================================
99
- // PRACTICAL EXAMPLE: APP STATE
100
- // ============================================
101
-
102
- // Save app state
103
- const appState = {
104
- lastPage: '/dashboard',
105
- sidebarOpen: true,
106
- recentFiles: ['file1.txt', 'file2.pdf'],
107
- lastSaved: Date.now()
108
- }
109
- store.set('appState', appState)
110
-
111
- // Load on next visit
112
- const restored = store.get('appState')
113
- if (restored) {
114
- console.debug('Restored app state:', restored.lastPage)
115
- }
116
-
117
- console.debug('Store advanced example complete!')
1
+ /**
2
+ * Memorio Store Advanced Example
3
+ *
4
+ * This example shows advanced store (localStorage) operations.
5
+ *
6
+ * Run: npx ts-node examples/store-advanced.ts
7
+ */
8
+
9
+ import { store } from 'memorio'
10
+
11
+ // ============================================
12
+ // CHECK PERSISTENCE
13
+ // ============================================
14
+
15
+ console.debug('=== Store Persistence Check ===')
16
+ console.debug('Is persistent (survives restart):', store.isPersistent)
17
+ // In browser: true (localStorage)
18
+ // In Node.js/Deno: false (memory fallback)
19
+
20
+ if (!store.isPersistent) {
21
+ console.debug('⚠️ Warning: Using in-memory storage. Data will be lost on restart!')
22
+ }
23
+
24
+ // ============================================
25
+ // PERSIST USER PREFERENCES
26
+ // ============================================
27
+
28
+ // Save user preferences
29
+ store.set('preferences', {
30
+ theme: 'dark',
31
+ language: 'en',
32
+ notifications: true,
33
+ fontSize: 16
34
+ })
35
+
36
+ // ============================================
37
+ // CHECK AND LOAD PREFERENCES
38
+ // ============================================
39
+
40
+ const savedPrefs = store.get('preferences')
41
+ if (savedPrefs) {
42
+ console.debug('Loaded preferences:', savedPrefs)
43
+ } else {
44
+ console.debug('No preferences found, using defaults')
45
+ store.set('preferences', { theme: 'light', language: 'en' })
46
+ }
47
+
48
+ // ============================================
49
+ // STORAGE QUOTA
50
+ // ============================================
51
+
52
+ // Get storage size
53
+ const currentSize = store.size()
54
+ console.debug('Current storage size:', currentSize, 'kilobytes')
55
+
56
+ // ============================================
57
+ // ALIAS METHODS
58
+ // ============================================
59
+
60
+ // store.delete() is alias for store.remove()
61
+ store.set('temp', 'value')
62
+ store.delete('temp')
63
+
64
+ // store.clearAll() is alias for store.removeAll()
65
+ // store.clearAll()
66
+
67
+ // ============================================
68
+ // ERROR HANDLING
69
+ // ============================================
70
+
71
+ // Try-catch for large data
72
+ try {
73
+ // Store large data
74
+ const largeData = {
75
+ items: Array(1000).fill(null).map((_, i) => ({ id: i, data: 'x'.repeat(100) }))
76
+ }
77
+ store.set('largeData', largeData)
78
+ console.debug('Large data stored successfully')
79
+ } catch (error) {
80
+ console.error('Storage full:', error)
81
+ }
82
+
83
+ // ============================================
84
+ // DATA SERIALIZATION
85
+ // ============================================
86
+
87
+ // Store supports all JSON-serializable types
88
+ store.set('string', 'hello')
89
+ store.set('number', 42)
90
+ store.set('boolean', true)
91
+ store.set('array', [1, 2, 3])
92
+ store.set('object', { nested: { value: 'deep' } })
93
+ store.set('null', null)
94
+
95
+ // Functions are not supported (logged as error)
96
+ store.set('function', () => { }) // logs: "It's not secure to store functions."
97
+
98
+ // ============================================
99
+ // PRACTICAL EXAMPLE: APP STATE
100
+ // ============================================
101
+
102
+ // Save app state
103
+ const appState = {
104
+ lastPage: '/dashboard',
105
+ sidebarOpen: true,
106
+ recentFiles: ['file1.txt', 'file2.pdf'],
107
+ lastSaved: Date.now()
108
+ }
109
+ store.set('appState', appState)
110
+
111
+ // Load on next visit
112
+ const restored = store.get('appState')
113
+ if (restored) {
114
+ console.debug('Restored app state:', restored.lastPage)
115
+ }
116
+
117
+ console.debug('Store advanced example complete!')
@@ -0,0 +1,90 @@
1
+ /**
2
+ * sync.ts
3
+ *
4
+ * Scenario: an app using `memorio.memory` that wants to survive being
5
+ * offline (data is born local, in the journal, and always readable) and
6
+ * mirror itself to a backend when a connection is available.
7
+ *
8
+ * The cloud is a transport/persistence provider here, never the source of
9
+ * truth - sync mirrors the local journal, it doesn't replace it. Provide
10
+ * your own `SyncProvider`; memorio doesn't ship one.
11
+ */
12
+ import { memorio } from 'memorio'
13
+
14
+ interface MemoryEntry {
15
+ key: string
16
+ value: unknown
17
+ confidence?: number
18
+ source?: string
19
+ scope?: 'device' | 'user' | 'shared'
20
+ }
21
+
22
+ interface SyncProvider {
23
+ push(ops: MemoryEntry[]): Promise<{ synced: string[]; conflicts?: string[]; error?: string }>
24
+ pull?(since?: number): Promise<MemoryEntry[]>
25
+ resolve?(op: MemoryEntry): Promise<'local' | 'remote' | 'merge'>
26
+ }
27
+
28
+ const backendProvider: SyncProvider = {
29
+ push: ops =>
30
+ fetch('/api/sync', {
31
+ method: 'POST',
32
+ body: JSON.stringify(ops),
33
+ headers: { 'Content-Type': 'application/json' }
34
+ }).then(r => r.json()),
35
+
36
+ pull: since => fetch(`/api/sync?since=${since ?? 0}`).then(r => r.json()),
37
+
38
+ // Higher-confidence entry wins locally; for 'shared' scope the provider
39
+ // (i.e. your backend) makes the final call instead.
40
+ resolve: async op => (op.confidence ?? 0) >= 0.8 ? 'local' : 'remote'
41
+ }
42
+
43
+ export async function configureSync(namespace: string) {
44
+ // `scope: 'device'` data never syncs (sticky to this device) - only
45
+ // 'user' and 'shared' scoped entries flow through the provider below.
46
+ memorio.memory.configure({
47
+ namespace, // e.g. `user:123:device:abc` - partitions the local journal
48
+ provider: backendProvider,
49
+ auto: true // auto-replay the journal on focus/online (default: true)
50
+ })
51
+
52
+ await memorio.memory.ready
53
+ }
54
+
55
+ export async function rememberAndSync(key: string, value: unknown) {
56
+ // Local-first: this resolves immediately from the local store, no
57
+ // network round-trip required.
58
+ await memorio.memory.remember(key, value, { scope: 'user', source: 'app' })
59
+ }
60
+
61
+ // ---------------------------------------------------------------------------
62
+ // The journal: the durable op log that drives cloud reconciliation
63
+ // ---------------------------------------------------------------------------
64
+
65
+ export async function inspectPendingOps() {
66
+ const pending = await memorio.memory.journal.pending()
67
+ console.debug('Operations waiting to sync:', pending)
68
+ return pending
69
+ }
70
+
71
+ export async function forceReplay() {
72
+ // Pushes pending() to the provider, marks synced entries, and pulls if
73
+ // the provider implements it. Normally triggered automatically (`auto:
74
+ // true`) on focus/online - call this manually to sync on demand instead.
75
+ const ack = await memorio.memory.journal.replay()
76
+ console.debug('Sync result:', ack)
77
+ return ack
78
+ }
79
+
80
+ export async function resetJournal() {
81
+ // Wipes the current namespace's journal only - does not touch the
82
+ // memory entries themselves, just the pending sync log.
83
+ await memorio.memory.journal.clear()
84
+ }
85
+
86
+ // Usage:
87
+ // await configureSync('user:123:device:abc')
88
+ // await rememberAndSync('user.language', 'Italian')
89
+ // await inspectPendingOps()
90
+ // await forceReplay()