memorio 4.6.4 → 4.6.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/COPYRIGHT.md +6 -0
- package/LICENSE.md +21 -0
- package/SECURITY.md +48 -0
- package/index.cjs +1 -1
- package/index.js +1 -1
- package/llms.txt +405 -0
- package/package.json +1 -1
package/COPYRIGHT.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Copyright
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Dario Passariello. All rights reserved.
|
|
4
|
+
<https://dario.passariello.ca>
|
|
5
|
+
|
|
6
|
+
This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Dario Passariello
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
Memorio follows NIST and NSA security standards at the enterprise level.
|
|
4
|
+
|
|
5
|
+
## Security Standards
|
|
6
|
+
|
|
7
|
+
- **NIST Guidelines**: Follows NIST SP 800-53 security controls and NIST Cybersecurity Framework
|
|
8
|
+
- **NSA Standards**: Defense-grade security practices; considers nation-state level threats in risk assessment
|
|
9
|
+
|
|
10
|
+
## Supply Chain Security
|
|
11
|
+
|
|
12
|
+
- **Socket.dev**: Minimum target score 90%; all alarms must be resolved before release
|
|
13
|
+
- **Dependency Management**: Zero production dependencies (fully dependency-free); dev dependencies audited regularly
|
|
14
|
+
- **Prohibited**: No `eval()` usage, no encrypted/obfuscated code in builds, no hardcoded secrets
|
|
15
|
+
|
|
16
|
+
## Code Security
|
|
17
|
+
|
|
18
|
+
- No hardcoded credentials or API keys
|
|
19
|
+
- Secure random session ID generation (`crypto.randomUUID` → `crypto.getRandomValues` → fallback)
|
|
20
|
+
- Input validation on all public APIs
|
|
21
|
+
- XSS prevention on DevTools data export
|
|
22
|
+
- Property-based access control on global objects (`Object.defineProperty` with `enumerable: false`)
|
|
23
|
+
|
|
24
|
+
## OWASP Compliance
|
|
25
|
+
|
|
26
|
+
Addresses OWASP Top 10 (2021):
|
|
27
|
+
- A01:2021 — Broken Access Control (global object protection, property locks)
|
|
28
|
+
- A02:2021 — Cryptographic Failures (crypto.randomUUID for session IDs)
|
|
29
|
+
- A03:2021 — Injection (CSS sanitization in devtools)
|
|
30
|
+
- A05:2021 — Security Misconfiguration (minimal surface area, no bundled secrets)
|
|
31
|
+
- A06:2021 — Vulnerable and Outdated Components (regular npm audit, Socket.dev)
|
|
32
|
+
- A07:2021 — Identification and Authentication Failures (N/A — library, no auth)
|
|
33
|
+
- A08:2021 — Software and Data Integrity Failures (strict tsconfig, lock files)
|
|
34
|
+
- A09:2021 — Security Logging and Monitoring Failures (DevTools inspect, Logger module)
|
|
35
|
+
- A10:2021 — Server-Side Request Forgery (N/A — no network requests)
|
|
36
|
+
|
|
37
|
+
## Reporting Security Issues
|
|
38
|
+
|
|
39
|
+
If you find a security vulnerability:
|
|
40
|
+
|
|
41
|
+
1. Email [Dario Passariello](mailto:dariopassarielloa@gmail.com)
|
|
42
|
+
2. Or visit https://dario.passariello.ca/contact/
|
|
43
|
+
|
|
44
|
+
Do not open public issues for security vulnerabilities.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
*Document version: 2.0 — Last updated: 2026-05-19*
|
|
48
|
+
*Owner: BigLogic Security Team*
|
package/index.cjs
CHANGED
package/index.js
CHANGED
package/llms.txt
ADDED
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# Memorio - LLM Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
**Memorio** is a cross-platform state management library that provides reactive state, persistence, and observation capabilities with zero dependencies. It works in Node.js, Deno, browsers, and edge environments.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
npm i memorio
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Core Concepts
|
|
12
|
+
|
|
13
|
+
Memorio provides 6 storage modules plus utilities:
|
|
14
|
+
|
|
15
|
+
| Module | Purpose | Persistence |
|
|
16
|
+
|--------|---------|-------------|
|
|
17
|
+
| `state` | Reactive, volatile state | In-memory (resets on refresh) |
|
|
18
|
+
| `store` | localStorage persistence | Survives browser refresh |
|
|
19
|
+
| `session` | sessionStorage | Dies with browser tab |
|
|
20
|
+
| `cache` | In-memory cache | Fastest read, no persistence |
|
|
21
|
+
| `idb` | IndexedDB | Structured, async, persistent (browser-only) |
|
|
22
|
+
| `observer` | Object watcher | Legacy |
|
|
23
|
+
| `useObserver` | React hook | Auto-discovery of state paths |
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
import 'memorio'
|
|
29
|
+
|
|
30
|
+
// Set reactive state
|
|
31
|
+
state.user = { name: 'Sara', role: 'admin' }
|
|
32
|
+
state.counter = 0
|
|
33
|
+
|
|
34
|
+
// Observe changes (React hook)
|
|
35
|
+
useObserver(
|
|
36
|
+
() => { console.debug('counter:', state.counter) },
|
|
37
|
+
[state.counter]
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## API Reference
|
|
42
|
+
|
|
43
|
+
### `state` — Reactive State
|
|
44
|
+
|
|
45
|
+
Global, Proxy-based, reactive state management.
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// Set values
|
|
49
|
+
state.user = { name: 'Sara', role: 'admin' }
|
|
50
|
+
state.items = [1, 2, 3]
|
|
51
|
+
state.counter = 0
|
|
52
|
+
|
|
53
|
+
// Get values
|
|
54
|
+
const name = state.user.name // 'Sara'
|
|
55
|
+
|
|
56
|
+
// List all keys
|
|
57
|
+
console.debug(state.list) // ['user', 'items', 'counter']
|
|
58
|
+
|
|
59
|
+
// Remove one key
|
|
60
|
+
state.remove('items')
|
|
61
|
+
|
|
62
|
+
// Clear all
|
|
63
|
+
state.removeAll()
|
|
64
|
+
|
|
65
|
+
// Lock/unlock for frozen objects
|
|
66
|
+
state.lock() // freeze everything
|
|
67
|
+
state.unlock() // unfreeze
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Features:**
|
|
71
|
+
- Automatic path tracking via `__path` property
|
|
72
|
+
- Nested proxy support
|
|
73
|
+
- Lock/unlock per-key or globally
|
|
74
|
+
- Auto-dispatches events on changes
|
|
75
|
+
|
|
76
|
+
### `store` — localStorage Persistence
|
|
77
|
+
|
|
78
|
+
Persistent storage that survives browser refresh.
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
// Set
|
|
82
|
+
store.set('preferences', { theme: 'dark' })
|
|
83
|
+
|
|
84
|
+
// Get
|
|
85
|
+
const prefs = store.get('preferences') // { theme: 'dark' } or null
|
|
86
|
+
|
|
87
|
+
// List all keys
|
|
88
|
+
store.list() // { preferences: { theme: 'dark' } }
|
|
89
|
+
|
|
90
|
+
// Remove
|
|
91
|
+
store.remove('preferences')
|
|
92
|
+
|
|
93
|
+
// Delete (alias for remove)
|
|
94
|
+
store.delete('preferences')
|
|
95
|
+
|
|
96
|
+
// Clear all memorio items
|
|
97
|
+
store.removeAll()
|
|
98
|
+
|
|
99
|
+
// Clear all (alias for removeAll)
|
|
100
|
+
store.clearAll()
|
|
101
|
+
|
|
102
|
+
// Check size
|
|
103
|
+
console.debug(store.size(), 'chars stored')
|
|
104
|
+
|
|
105
|
+
// Check if persistent (real localStorage vs memory fallback)
|
|
106
|
+
console.debug(store.isPersistent) // true → real localStorage
|
|
107
|
+
|
|
108
|
+
// Estimate quota usage (returns [0, 0] for localStorage)
|
|
109
|
+
await store.quota() // [usage, quota] in KB
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `session` — sessionStorage
|
|
113
|
+
|
|
114
|
+
Storage that dies when browser tab closes.
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
// Set
|
|
118
|
+
session.set('token', 'user-abc-123')
|
|
119
|
+
|
|
120
|
+
// Get
|
|
121
|
+
const token = session.get('token') // 'user-abc-123' or null
|
|
122
|
+
|
|
123
|
+
// List all keys
|
|
124
|
+
session.list() // { token: 'user-abc-123' }
|
|
125
|
+
|
|
126
|
+
// Remove
|
|
127
|
+
session.remove('token')
|
|
128
|
+
|
|
129
|
+
// Delete (alias for remove)
|
|
130
|
+
session.delete('token')
|
|
131
|
+
|
|
132
|
+
// Clear all
|
|
133
|
+
session.removeAll()
|
|
134
|
+
|
|
135
|
+
// Clear all (alias for removeAll)
|
|
136
|
+
session.clearAll()
|
|
137
|
+
|
|
138
|
+
// Check size
|
|
139
|
+
console.debug(session.size(), 'chars stored')
|
|
140
|
+
|
|
141
|
+
// Check if persistent
|
|
142
|
+
console.debug(session.isPersistent)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `cache` — In-Memory Cache
|
|
146
|
+
|
|
147
|
+
Fastest possible read, data lost on refresh.
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
// Set
|
|
151
|
+
cache.set('temp', computeExpensiveResult())
|
|
152
|
+
|
|
153
|
+
// Get
|
|
154
|
+
const result = cache.get('temp') // undefined or the value
|
|
155
|
+
|
|
156
|
+
// List all keys
|
|
157
|
+
cache.list() // { temp: <value> }
|
|
158
|
+
|
|
159
|
+
// Remove
|
|
160
|
+
cache.remove('temp')
|
|
161
|
+
|
|
162
|
+
// Clear all
|
|
163
|
+
cache.clear()
|
|
164
|
+
|
|
165
|
+
// Remove all (alias for clear)
|
|
166
|
+
cache.removeAll()
|
|
167
|
+
|
|
168
|
+
// Direct access (also works)
|
|
169
|
+
cache['myKey'] = value
|
|
170
|
+
const value = cache['myKey']
|
|
171
|
+
delete cache['myKey']
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `idb` — IndexedDB
|
|
175
|
+
|
|
176
|
+
Structured, persistent, async database (browser-only).
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// Create database
|
|
180
|
+
await idb.db.create('my-db', 1) // version defaults to 1
|
|
181
|
+
|
|
182
|
+
// Create table (object store)
|
|
183
|
+
await idb.table.create('my-db', 'users')
|
|
184
|
+
|
|
185
|
+
// Set data
|
|
186
|
+
await idb.data.set('my-db', 'users', { id: 1, name: 'Sara' })
|
|
187
|
+
|
|
188
|
+
// Get data by key
|
|
189
|
+
const user = await idb.data.get('my-db', 'users', 1)
|
|
190
|
+
|
|
191
|
+
// Delete data
|
|
192
|
+
await idb.data.delete('my-db', 'users', 1)
|
|
193
|
+
|
|
194
|
+
// List databases
|
|
195
|
+
const dbs = await idb.db.list()
|
|
196
|
+
|
|
197
|
+
// Check if database exists
|
|
198
|
+
const exists = await idb.db.exist('my-db')
|
|
199
|
+
|
|
200
|
+
// Delete database
|
|
201
|
+
await idb.db.delete('my-db')
|
|
202
|
+
|
|
203
|
+
// Get database size
|
|
204
|
+
const size = await idb.db.size('my-db')
|
|
205
|
+
|
|
206
|
+
// Get table size
|
|
207
|
+
const tableSize = await idb.table.size('my-db', 'users')
|
|
208
|
+
|
|
209
|
+
// Check support
|
|
210
|
+
idb.db.support() // true if IndexedDB available
|
|
211
|
+
|
|
212
|
+
// Check quota
|
|
213
|
+
const [usage, quota] = await idb.db.quota()
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Note:** In Node.js/Deno, `idb` is disabled with a warning. Use `store` or `session` instead.
|
|
217
|
+
|
|
218
|
+
### `observer` — Object Watcher
|
|
219
|
+
|
|
220
|
+
Legacy observer API. Use `useObserver` instead.
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
// Listen to state changes
|
|
224
|
+
observer('state.user', (newVal, oldVal) => {
|
|
225
|
+
console.debug('user changed:', newVal, oldVal)
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
// Toggle listening (no callback)
|
|
229
|
+
observer('state.counter')
|
|
230
|
+
|
|
231
|
+
// Remove observer
|
|
232
|
+
observer.remove('state.user')
|
|
233
|
+
|
|
234
|
+
// List all observers
|
|
235
|
+
console.debug(observer.list)
|
|
236
|
+
|
|
237
|
+
// Remove all observers
|
|
238
|
+
observer.removeAll()
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### `useObserver` — React Hook
|
|
242
|
+
|
|
243
|
+
Primary way to observe state changes in React components.
|
|
244
|
+
|
|
245
|
+
```jsx
|
|
246
|
+
import 'memorio'
|
|
247
|
+
import { useReducer } from 'react'
|
|
248
|
+
|
|
249
|
+
function Counter() {
|
|
250
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
251
|
+
|
|
252
|
+
// Auto-discovery mode (no deps)
|
|
253
|
+
useObserver(() => {
|
|
254
|
+
console.debug('counter:', state.counter)
|
|
255
|
+
}, state.counter)
|
|
256
|
+
|
|
257
|
+
// Explicit deps mode
|
|
258
|
+
useObserver(
|
|
259
|
+
() => { console.debug('user:', state.user) },
|
|
260
|
+
[state.user]
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
return <div>Count: {state.counter}</div>
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Features:**
|
|
268
|
+
- Auto-discovery of state paths during render
|
|
269
|
+
- Returns cleanup function to stop monitoring
|
|
270
|
+
- Supports both Proxy objects and string paths
|
|
271
|
+
|
|
272
|
+
### `devtools` — Inspection Tools
|
|
273
|
+
|
|
274
|
+
Inspect all memorio data in console.
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
// Pretty-print state, store, session, cache
|
|
278
|
+
memorio.devtools.inspect()
|
|
279
|
+
|
|
280
|
+
// Get stats
|
|
281
|
+
memorio.devtools.stats() // { stateKeys, storeKeys, sessionKeys, ... }
|
|
282
|
+
|
|
283
|
+
// Clear specific module
|
|
284
|
+
memorio.devtools.clear('state')
|
|
285
|
+
|
|
286
|
+
// Clear all modules
|
|
287
|
+
memorio.devtools.clearAll()
|
|
288
|
+
|
|
289
|
+
// Export all data as JSON
|
|
290
|
+
memorio.devtools.exportData()
|
|
291
|
+
|
|
292
|
+
// Import data from JSON
|
|
293
|
+
memorio.devtools.importData(jsonString)
|
|
294
|
+
|
|
295
|
+
// Show help
|
|
296
|
+
memorio.devtools.help()
|
|
297
|
+
|
|
298
|
+
// Console shortcuts
|
|
299
|
+
$state // same as globalThis.state
|
|
300
|
+
$store // same as globalThis.store
|
|
301
|
+
$session // same as globalThis.session
|
|
302
|
+
$cache // same as globalThis.cache
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### `logger` — Change Tracking
|
|
306
|
+
|
|
307
|
+
Track every state change with timestamps.
|
|
308
|
+
|
|
309
|
+
```javascript
|
|
310
|
+
// Configure logger
|
|
311
|
+
memorio.logger.configure({
|
|
312
|
+
enabled: true,
|
|
313
|
+
logToConsole: true,
|
|
314
|
+
modules: ['state', 'store', 'session', 'cache', 'idb']
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
// Get history
|
|
318
|
+
memorio.logger.getHistory() // [{ timestamp, module, action, path, value }, ...]
|
|
319
|
+
|
|
320
|
+
// Get stats
|
|
321
|
+
memorio.logger.getStats() // { total, state, store, session, cache, idb, set, get, ... }
|
|
322
|
+
|
|
323
|
+
// Clear history
|
|
324
|
+
memorio.logger.clearHistory()
|
|
325
|
+
|
|
326
|
+
// Export logs
|
|
327
|
+
memorio.logger.exportLogs() // JSON string of all history
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Platform Detection
|
|
331
|
+
|
|
332
|
+
Access via `memorio.*` after `import 'memorio'`:
|
|
333
|
+
|
|
334
|
+
```javascript
|
|
335
|
+
memorio.isBrowser() // true in Chrome, Firefox, Safari
|
|
336
|
+
memorio.isNode() // true in Node.js
|
|
337
|
+
memorio.isDeno() // true in Deno
|
|
338
|
+
memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
339
|
+
|
|
340
|
+
const caps = memorio.getCapabilities()
|
|
341
|
+
// { platform: 'browser', hasLocalStorage: true, hasIndexedDB: true, sessionId: 'uuid', ... }
|
|
342
|
+
|
|
343
|
+
// Create isolated context
|
|
344
|
+
memorio.createContext('tenant-name')
|
|
345
|
+
memorio.listContexts()
|
|
346
|
+
memorio.deleteContext('context-id')
|
|
347
|
+
memorio.isolate('tenant-name') // alias for createContext
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Cross-Platform Support
|
|
351
|
+
|
|
352
|
+
| Module | Browser | Node.js | Deno | Edge/Workers |
|
|
353
|
+
|--------|---------|---------|------|--------------|
|
|
354
|
+
| `state` | ✅ | ✅ | ✅ | ✅ |
|
|
355
|
+
| `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
|
|
356
|
+
| `cache` | ✅ | ✅ | ✅ | ✅ |
|
|
357
|
+
| `store` | ✅ localStorage | ⚠️ memory | ⚠️ memory | ✅ localStorage |
|
|
358
|
+
| `session` | ✅ sessionStorage | ⚠️ memory | ⚠️ memory | ✅ sessionStorage |
|
|
359
|
+
| `idb` | ✅ IndexedDB | ❌ | ❌ | ⚠️ |
|
|
360
|
+
| `devtools` | ✅ | ❌ | ❌ | ⚠️ |
|
|
361
|
+
|
|
362
|
+
**Note:** `store` and `session` fall back to in-memory `Map` in Node.js/Deno.
|
|
363
|
+
|
|
364
|
+
## Session Isolation
|
|
365
|
+
|
|
366
|
+
Each browser tab and server request gets an isolated namespace automatically via session IDs.
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
// Create isolated context
|
|
370
|
+
memorio.createContext('tenant-name')
|
|
371
|
+
memorio.listContexts()
|
|
372
|
+
memorio.deleteContext('context-id')
|
|
373
|
+
memorio.isolate('tenant-name') // alias for createContext
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Security
|
|
377
|
+
|
|
378
|
+
- Zero production dependencies
|
|
379
|
+
- NIST & NSA aligned security standards
|
|
380
|
+
- No `eval`, no obfuscation, no hardcoded secrets
|
|
381
|
+
- All inputs validated, keys sanitized
|
|
382
|
+
- Secure random session IDs via `crypto.randomUUID`
|
|
383
|
+
|
|
384
|
+
## License
|
|
385
|
+
|
|
386
|
+
MIT © Dario Passariello (BigLogic Inc Canada)
|
|
387
|
+
|
|
388
|
+
## Utilities
|
|
389
|
+
|
|
390
|
+
### `memorio.dispatch` — Event Dispatch System
|
|
391
|
+
|
|
392
|
+
Internal event system used by state changes.
|
|
393
|
+
|
|
394
|
+
```javascript
|
|
395
|
+
// Dispatch a custom event
|
|
396
|
+
memorio.dispatch.set('custom:event', { detail: { data: 'value' } })
|
|
397
|
+
|
|
398
|
+
// Listen for an event
|
|
399
|
+
memorio.dispatch.listen('custom:event', (e) => {
|
|
400
|
+
console.debug('Event triggered:', e.detail)
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
// Remove listener
|
|
404
|
+
memorio.dispatch.remove('custom:event')
|
|
405
|
+
```
|
package/package.json
CHANGED