memorio 2.5.1 → 2.5.3
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/docs/CACHE.md +77 -0
- package/docs/DEVTOOLS.md +120 -0
- package/docs/IDB.md +156 -0
- package/docs/LOGGER.md +145 -0
- package/docs/OBSERVER.md +180 -0
- package/docs/SESSION.md +129 -0
- package/docs/STATE.md +135 -0
- package/docs/STORE.md +137 -0
- package/docs/SUMMARY.md +25 -0
- package/docs/USEOBSERVER.md +156 -0
- package/examples/basic.ts +75 -0
- package/examples/cache.ts +72 -0
- package/examples/idb.ts +109 -0
- package/examples/observer.ts +60 -0
- package/examples/session-advanced.ts +78 -0
- package/examples/state-advanced.ts +89 -0
- package/examples/store-advanced.ts +104 -0
- package/examples/useObserver.ts +141 -0
- package/index.js +1 -1
- package/package.json +5 -4
- package/COPYRIGHT.md +0 -6
- package/FUNDING.yml +0 -12
- package/SECURITY.md +0 -3
- package/index.js.map +0 -7
- package/index.mjs +0 -23
- package/index.mjs.map +0 -7
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memorio Cache Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates the cache module for in-memory storage.
|
|
5
|
+
* Cache is perfect for temporary data that doesn't need persistence.
|
|
6
|
+
*
|
|
7
|
+
* Run: npx ts-node examples/cache.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import '../index'
|
|
11
|
+
|
|
12
|
+
// ============================================
|
|
13
|
+
// BASIC CACHE OPERATIONS
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
// Set values
|
|
17
|
+
cache.set('username', 'Mario')
|
|
18
|
+
cache.set('score', 1500)
|
|
19
|
+
cache.set('player', { name: 'Mario', level: 5 })
|
|
20
|
+
|
|
21
|
+
// Get values
|
|
22
|
+
console.log('Username:', cache.get('username'))
|
|
23
|
+
console.log('Score:', cache.get('score'))
|
|
24
|
+
console.log('Player:', cache.get('player'))
|
|
25
|
+
|
|
26
|
+
// Direct property access
|
|
27
|
+
cache.tempData = 'Hello'
|
|
28
|
+
console.log('Temp data:', cache.tempData)
|
|
29
|
+
|
|
30
|
+
// ============================================
|
|
31
|
+
// CACHE WITH OBJECTS
|
|
32
|
+
// ============================================
|
|
33
|
+
|
|
34
|
+
// Store complex objects
|
|
35
|
+
cache.set('gameState', {
|
|
36
|
+
level: 3,
|
|
37
|
+
score: 2500,
|
|
38
|
+
inventory: ['sword', 'shield', 'potion'],
|
|
39
|
+
position: { x: 100, y: 200 }
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const gameState = cache.get('gameState')
|
|
43
|
+
console.log('Game level:', gameState?.level)
|
|
44
|
+
console.log('Inventory:', gameState?.inventory)
|
|
45
|
+
|
|
46
|
+
// ============================================
|
|
47
|
+
// CACHE SIZE
|
|
48
|
+
// ============================================
|
|
49
|
+
|
|
50
|
+
// Add multiple items
|
|
51
|
+
for (let i = 0; i < 10; i++) {
|
|
52
|
+
cache.set(`item_${i}`, { id: i, data: `item-${i}` })
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
console.log('Cache keys:', Object.keys(cache))
|
|
56
|
+
|
|
57
|
+
// ============================================
|
|
58
|
+
// CLEANUP
|
|
59
|
+
// ============================================
|
|
60
|
+
|
|
61
|
+
// Remove single item
|
|
62
|
+
cache.remove('username')
|
|
63
|
+
|
|
64
|
+
// Clear all cache
|
|
65
|
+
cache.removeAll()
|
|
66
|
+
|
|
67
|
+
// Or use clearAll alias
|
|
68
|
+
// cache.clearAll()
|
|
69
|
+
|
|
70
|
+
console.log('Cache after clear:', cache.get('score'))
|
|
71
|
+
|
|
72
|
+
console.log('Cache example complete!')
|
package/examples/idb.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memorio IDB Example
|
|
3
|
+
*
|
|
4
|
+
* This example shows how to use IndexedDB for large data storage.
|
|
5
|
+
* IDB is perfect for caching, offline data, and large datasets.
|
|
6
|
+
*
|
|
7
|
+
* Run: npx ts-node examples/idb.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import '../index'
|
|
11
|
+
|
|
12
|
+
// ============================================
|
|
13
|
+
// CHECK SUPPORT
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
if (!idb.db.support()) {
|
|
17
|
+
console.log('IndexedDB not supported')
|
|
18
|
+
process.exit(0)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// ============================================
|
|
22
|
+
// CREATE DATABASE
|
|
23
|
+
// ============================================
|
|
24
|
+
|
|
25
|
+
// Create a new database
|
|
26
|
+
idb.db.create('myApp')
|
|
27
|
+
|
|
28
|
+
// Create tables (stores)
|
|
29
|
+
idb.table.create('myApp', 'users')
|
|
30
|
+
idb.table.create('myApp', 'products')
|
|
31
|
+
|
|
32
|
+
// ============================================
|
|
33
|
+
// ADD DATA
|
|
34
|
+
// ============================================
|
|
35
|
+
|
|
36
|
+
// Add user records
|
|
37
|
+
idb.data.set('myApp', 'users', {
|
|
38
|
+
id: 1,
|
|
39
|
+
name: 'Mario',
|
|
40
|
+
email: 'mario@example.com',
|
|
41
|
+
role: 'admin'
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
idb.data.set('myApp', 'users', {
|
|
45
|
+
id: 2,
|
|
46
|
+
name: 'Luigi',
|
|
47
|
+
email: 'luigi@example.com',
|
|
48
|
+
role: 'user'
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// Add product records
|
|
52
|
+
idb.data.set('myApp', 'products', {
|
|
53
|
+
id: 1,
|
|
54
|
+
name: 'Super Mushroom',
|
|
55
|
+
price: 99,
|
|
56
|
+
inStock: true
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
idb.data.set('myApp', 'products', {
|
|
60
|
+
id: 2,
|
|
61
|
+
name: 'Fire Flower',
|
|
62
|
+
price: 199,
|
|
63
|
+
inStock: true
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
// ============================================
|
|
67
|
+
// READ DATA
|
|
68
|
+
// ============================================
|
|
69
|
+
|
|
70
|
+
const user1 = idb.data.get('myApp', 'users', 1)
|
|
71
|
+
console.log('User 1:', user1)
|
|
72
|
+
|
|
73
|
+
const product1 = idb.data.get('myApp', 'products', 1)
|
|
74
|
+
console.log('Product 1:', product1)
|
|
75
|
+
|
|
76
|
+
// ============================================
|
|
77
|
+
// DATABASE INFO
|
|
78
|
+
// ============================================
|
|
79
|
+
|
|
80
|
+
// List all databases
|
|
81
|
+
const databases = idb.db.list()
|
|
82
|
+
console.log('Databases:', databases)
|
|
83
|
+
|
|
84
|
+
// Check if database exists
|
|
85
|
+
const exists = idb.db.exist('myApp')
|
|
86
|
+
console.log('myApp exists:', exists)
|
|
87
|
+
|
|
88
|
+
// Get database version
|
|
89
|
+
const version = idb.db.version('myApp')
|
|
90
|
+
console.log('myApp version:', version)
|
|
91
|
+
|
|
92
|
+
// Get database size
|
|
93
|
+
const size = idb.db.size('myApp')
|
|
94
|
+
console.log('myApp size:', size, 'bytes')
|
|
95
|
+
|
|
96
|
+
// ============================================
|
|
97
|
+
// DELETE DATA
|
|
98
|
+
// ============================================
|
|
99
|
+
|
|
100
|
+
// Delete a record
|
|
101
|
+
idb.data.delete('myApp', 'users', 1)
|
|
102
|
+
|
|
103
|
+
// Delete entire table
|
|
104
|
+
// idb.table.delete('myApp', 'users');
|
|
105
|
+
|
|
106
|
+
// Delete entire database
|
|
107
|
+
// idb.db.delete('myApp');
|
|
108
|
+
|
|
109
|
+
console.log('IDB example complete!')
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memorio Observer Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates the observer pattern for reactive state changes.
|
|
5
|
+
* Perfect for logging, analytics, auto-save, and UI updates.
|
|
6
|
+
*
|
|
7
|
+
* Run: npx ts-node examples/observer.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import '../index'
|
|
11
|
+
|
|
12
|
+
// ============================================
|
|
13
|
+
// SIMPLE OBSERVER
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
// Watch a single value
|
|
17
|
+
observer('state.counter', (newValue, oldValue) => {
|
|
18
|
+
console.log(`Counter: ${oldValue} → ${newValue}`)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
state.counter = 0
|
|
22
|
+
state.counter = 1
|
|
23
|
+
state.counter = 2
|
|
24
|
+
|
|
25
|
+
// ============================================
|
|
26
|
+
// OBJECT OBSERVER
|
|
27
|
+
// ============================================
|
|
28
|
+
|
|
29
|
+
// Watch entire objects
|
|
30
|
+
observer('state.user', (newUser, oldUser) => {
|
|
31
|
+
console.log(`User changed: ${oldUser?.name} → ${newUser?.name}`)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
state.user = { name: 'Mario', level: 1 }
|
|
35
|
+
state.user = { name: 'Luigi', level: 2 }
|
|
36
|
+
|
|
37
|
+
// ============================================
|
|
38
|
+
// MULTIPLE OBSERVERS
|
|
39
|
+
// ============================================
|
|
40
|
+
|
|
41
|
+
// Multiple observers on same path
|
|
42
|
+
observer('state.notifications', (count) => {
|
|
43
|
+
console.log(`New notification count: ${count}`)
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// List all observers
|
|
47
|
+
console.log('Active observers:', observer.list)
|
|
48
|
+
|
|
49
|
+
// ============================================
|
|
50
|
+
// CLEANUP
|
|
51
|
+
// ============================================
|
|
52
|
+
|
|
53
|
+
// Remove specific observer
|
|
54
|
+
observer.remove('state.counter')
|
|
55
|
+
|
|
56
|
+
// Remove all observers - call remove for each path
|
|
57
|
+
// observer.remove('state.counter')
|
|
58
|
+
// observer.remove('state.notifications')
|
|
59
|
+
|
|
60
|
+
console.log('Observer example complete!')
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memorio Session Advanced Example
|
|
3
|
+
*
|
|
4
|
+
* This example shows advanced session (sessionStorage) operations.
|
|
5
|
+
* Session data is cleared when the browser tab closes.
|
|
6
|
+
*
|
|
7
|
+
* Run: npx ts-node examples/session-advanced.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import '../index'
|
|
11
|
+
|
|
12
|
+
// ============================================
|
|
13
|
+
// AUTHENTICATION
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
// Store auth token (temporary - cleared when tab closes)
|
|
17
|
+
session.set('authToken', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...')
|
|
18
|
+
session.set('userId', 12345)
|
|
19
|
+
|
|
20
|
+
// Check if user is logged in
|
|
21
|
+
const token = session.get('authToken')
|
|
22
|
+
if (token) {
|
|
23
|
+
console.log('User is logged in, token:', token.substring(0, 20) + '...')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ============================================
|
|
27
|
+
// FORM PROGRESS
|
|
28
|
+
// ============================================
|
|
29
|
+
|
|
30
|
+
// Save form draft
|
|
31
|
+
session.set('formDraft', {
|
|
32
|
+
name: 'Mario',
|
|
33
|
+
email: 'mario@example.com',
|
|
34
|
+
message: 'Hello world!'
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
// Restore on page refresh
|
|
38
|
+
const draft = session.get('formDraft')
|
|
39
|
+
if (draft) {
|
|
40
|
+
console.log('Restored draft:', draft)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ============================================
|
|
44
|
+
// SHOPPING CART
|
|
45
|
+
// ============================================
|
|
46
|
+
|
|
47
|
+
// Store cart items (temporary)
|
|
48
|
+
session.set('cart', [
|
|
49
|
+
{ id: 1, name: 'Super Mushroom', price: 99, qty: 2 },
|
|
50
|
+
{ id: 2, name: 'Fire Flower', price: 199, qty: 1 }
|
|
51
|
+
])
|
|
52
|
+
|
|
53
|
+
// Calculate total
|
|
54
|
+
const cart = session.get('cart') || []
|
|
55
|
+
const total = cart.reduce((sum, item) => sum + (item.price * item.qty), 0)
|
|
56
|
+
console.log('Cart total:', total)
|
|
57
|
+
|
|
58
|
+
// ============================================
|
|
59
|
+
// SESSION SIZE
|
|
60
|
+
// ============================================
|
|
61
|
+
|
|
62
|
+
// Get session storage size
|
|
63
|
+
console.log('Session size:', session.size(), 'bytes')
|
|
64
|
+
|
|
65
|
+
// ============================================
|
|
66
|
+
// CLEANUP
|
|
67
|
+
// ============================================
|
|
68
|
+
|
|
69
|
+
// Remove specific item
|
|
70
|
+
session.remove('formDraft')
|
|
71
|
+
|
|
72
|
+
// Clear all session data (logout)
|
|
73
|
+
// session.removeAll()
|
|
74
|
+
|
|
75
|
+
// Or use alias
|
|
76
|
+
// session.clearAll()
|
|
77
|
+
|
|
78
|
+
console.log('Session advanced example complete!')
|
|
@@ -0,0 +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 '../index'
|
|
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.log('User name:', state.user.name)
|
|
29
|
+
console.log('Email:', state.user.profile.email)
|
|
30
|
+
console.log('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.log('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.log('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.log('Config locked:', state.config)
|
|
60
|
+
|
|
61
|
+
// ============================================
|
|
62
|
+
// PATH TRACKING
|
|
63
|
+
// ============================================
|
|
64
|
+
|
|
65
|
+
// Get path information
|
|
66
|
+
console.log('Path:', state.user.__path) // "state.user"
|
|
67
|
+
|
|
68
|
+
// Use path tracker for debugging
|
|
69
|
+
const path = state.user.profile
|
|
70
|
+
console.log('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.log('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.log('State advanced example complete!')
|
|
@@ -0,0 +1,104 @@
|
|
|
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 '../index'
|
|
10
|
+
|
|
11
|
+
// ============================================
|
|
12
|
+
// PERSIST USER PREFERENCES
|
|
13
|
+
// ============================================
|
|
14
|
+
|
|
15
|
+
// Save user preferences
|
|
16
|
+
store.set('preferences', {
|
|
17
|
+
theme: 'dark',
|
|
18
|
+
language: 'en',
|
|
19
|
+
notifications: true,
|
|
20
|
+
fontSize: 16
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
// ============================================
|
|
24
|
+
// CHECK AND LOAD PREFERENCES
|
|
25
|
+
// ============================================
|
|
26
|
+
|
|
27
|
+
const savedPrefs = store.get('preferences')
|
|
28
|
+
if (savedPrefs) {
|
|
29
|
+
console.log('Loaded preferences:', savedPrefs)
|
|
30
|
+
} else {
|
|
31
|
+
console.log('No preferences found, using defaults')
|
|
32
|
+
store.set('preferences', { theme: 'light', language: 'en' })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ============================================
|
|
36
|
+
// STORAGE QUOTA
|
|
37
|
+
// ============================================
|
|
38
|
+
|
|
39
|
+
// Get storage size
|
|
40
|
+
const currentSize = store.size()
|
|
41
|
+
console.log('Current storage size:', currentSize, 'bytes')
|
|
42
|
+
|
|
43
|
+
// ============================================
|
|
44
|
+
// ALIAS METHODS
|
|
45
|
+
// ============================================
|
|
46
|
+
|
|
47
|
+
// store.delete() is alias for store.remove()
|
|
48
|
+
store.set('temp', 'value')
|
|
49
|
+
store.delete('temp')
|
|
50
|
+
|
|
51
|
+
// store.clearAll() is alias for store.removeAll()
|
|
52
|
+
// store.clearAll()
|
|
53
|
+
|
|
54
|
+
// ============================================
|
|
55
|
+
// ERROR HANDLING
|
|
56
|
+
// ============================================
|
|
57
|
+
|
|
58
|
+
// Try-catch for large data
|
|
59
|
+
try {
|
|
60
|
+
// Store large data
|
|
61
|
+
const largeData = {
|
|
62
|
+
items: Array(1000).fill(null).map((_, i) => ({ id: i, data: 'x'.repeat(100) }))
|
|
63
|
+
}
|
|
64
|
+
store.set('largeData', largeData)
|
|
65
|
+
console.log('Large data stored successfully')
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('Storage full:', error)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ============================================
|
|
71
|
+
// DATA SERIALIZATION
|
|
72
|
+
// ============================================
|
|
73
|
+
|
|
74
|
+
// Store supports all JSON-serializable types
|
|
75
|
+
store.set('string', 'hello')
|
|
76
|
+
store.set('number', 42)
|
|
77
|
+
store.set('boolean', true)
|
|
78
|
+
store.set('array', [1, 2, 3])
|
|
79
|
+
store.set('object', { nested: { value: 'deep' } })
|
|
80
|
+
store.set('null', null)
|
|
81
|
+
|
|
82
|
+
// Functions are not supported (logged as error)
|
|
83
|
+
store.set('function', () => { }) // logs: "It's not secure to store functions."
|
|
84
|
+
|
|
85
|
+
// ============================================
|
|
86
|
+
// PRACTICAL EXAMPLE: APP STATE
|
|
87
|
+
// ============================================
|
|
88
|
+
|
|
89
|
+
// Save app state
|
|
90
|
+
const appState = {
|
|
91
|
+
lastPage: '/dashboard',
|
|
92
|
+
sidebarOpen: true,
|
|
93
|
+
recentFiles: ['file1.txt', 'file2.pdf'],
|
|
94
|
+
lastSaved: Date.now()
|
|
95
|
+
}
|
|
96
|
+
store.set('appState', appState)
|
|
97
|
+
|
|
98
|
+
// Load on next visit
|
|
99
|
+
const restored = store.get('appState')
|
|
100
|
+
if (restored) {
|
|
101
|
+
console.log('Restored app state:', restored.lastPage)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log('Store advanced example complete!')
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memorio useObserver Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates the useObserver hook for React.
|
|
5
|
+
* useObserver automatically tracks state changes and triggers re-renders.
|
|
6
|
+
*
|
|
7
|
+
* Note: This example requires React to be present in the environment.
|
|
8
|
+
* Run in a React environment.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import '../index'
|
|
12
|
+
|
|
13
|
+
// ============================================
|
|
14
|
+
// BASIC USEOBSERVER
|
|
15
|
+
// ============================================
|
|
16
|
+
|
|
17
|
+
// Example 1: Watch single value
|
|
18
|
+
useObserver(callback, [state.value])
|
|
19
|
+
|
|
20
|
+
function Counter() {
|
|
21
|
+
useObserver(() => {
|
|
22
|
+
console.debug('Count changed:', state.count)
|
|
23
|
+
}, [state.count])
|
|
24
|
+
|
|
25
|
+
return <div>{ state.count } </div>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ============================================
|
|
29
|
+
// MULTIPLE DEPENDENCIES
|
|
30
|
+
// ============================================
|
|
31
|
+
|
|
32
|
+
// Example 2: Watch multiple values
|
|
33
|
+
function UserProfile() {
|
|
34
|
+
useObserver(() => {
|
|
35
|
+
console.debug('User or theme changed')
|
|
36
|
+
}, [state.user, state.theme])
|
|
37
|
+
|
|
38
|
+
return <div>{ state.user.name } </div>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============================================
|
|
42
|
+
// AUTO-DISCOVERY
|
|
43
|
+
// ============================================
|
|
44
|
+
|
|
45
|
+
// Example 3: No dependencies - auto-discovers all state access
|
|
46
|
+
function AutoDiscovery() {
|
|
47
|
+
useObserver(() => {
|
|
48
|
+
// Automatically tracks state.user, state.items, state.count
|
|
49
|
+
console.debug('Changed:', state.user.name, state.items.length, state.count)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return <div>{ state.user.name } </div>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ============================================
|
|
56
|
+
// SYNC WITH USESTATE
|
|
57
|
+
// ============================================
|
|
58
|
+
|
|
59
|
+
// Example 4: Sync with useState
|
|
60
|
+
function SyncedComponent() {
|
|
61
|
+
const [localData, setLocalData] = useState(null)
|
|
62
|
+
|
|
63
|
+
useObserver((newValue) => {
|
|
64
|
+
setLocalData(newValue)
|
|
65
|
+
}, [state.data])
|
|
66
|
+
|
|
67
|
+
return <div>{ localData } </div>
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ============================================
|
|
71
|
+
// PRACTICAL EXAMPLE
|
|
72
|
+
// ============================================
|
|
73
|
+
|
|
74
|
+
// Real-world React component example:
|
|
75
|
+
import { useObserver } from 'memorio'
|
|
76
|
+
|
|
77
|
+
function TodoApp() {
|
|
78
|
+
// Track todos
|
|
79
|
+
useObserver(() => {
|
|
80
|
+
console.debug('Todos updated:', state.todos)
|
|
81
|
+
// Optionally save to store
|
|
82
|
+
store.set('todos', state.todos)
|
|
83
|
+
}, [state.todos])
|
|
84
|
+
|
|
85
|
+
// Track filter
|
|
86
|
+
useObserver(() => {
|
|
87
|
+
console.debug('Filter changed:', state.filter)
|
|
88
|
+
}, [state.filter])
|
|
89
|
+
|
|
90
|
+
const addTodo = (text) => {
|
|
91
|
+
state.todos = [...(state.todos || []), { text, done: false }]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const toggleTodo = (index) => {
|
|
95
|
+
const todos = [...state.todos]
|
|
96
|
+
todos[index].done = !todos[index].done
|
|
97
|
+
state.todos = todos
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const filteredTodos = (state.todos || []).filter(t =>
|
|
101
|
+
state.filter === 'all' ||
|
|
102
|
+
(state.filter === 'done' && t.done) ||
|
|
103
|
+
(state.filter === 'todo' && !t.done)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<div>
|
|
108
|
+
<select
|
|
109
|
+
value= { state.filter }
|
|
110
|
+
onChange = { e => state.filter = e.target.value }
|
|
111
|
+
>
|
|
112
|
+
<option value="all" > All </option>
|
|
113
|
+
< option value = "done" > Done </option>
|
|
114
|
+
< option value = "todo" > Todo </option>
|
|
115
|
+
</select>
|
|
116
|
+
<ul>
|
|
117
|
+
{
|
|
118
|
+
filteredTodos.map((todo, i) => (
|
|
119
|
+
<li
|
|
120
|
+
key= { i }
|
|
121
|
+
onClick = {() => toggleTodo(i)}
|
|
122
|
+
style = {{ textDecoration: todo.done ? 'line-through' : 'none' }
|
|
123
|
+
}
|
|
124
|
+
>
|
|
125
|
+
{ todo.text }
|
|
126
|
+
</li>
|
|
127
|
+
))}
|
|
128
|
+
</ul>
|
|
129
|
+
< input
|
|
130
|
+
onKeyDown = { e => {
|
|
131
|
+
if (e.key === 'Enter') {
|
|
132
|
+
addTodo(e.target.value)
|
|
133
|
+
e.target.value = ''
|
|
134
|
+
}
|
|
135
|
+
}}
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.log('useObserver example - run in React environment!')
|