memorio 4.7.0 → 4.7.1
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/README.md +106 -199
- package/index.cjs +32 -3
- package/index.js +8 -3
- package/llms.txt +75 -91
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🧠 memorio
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|
|
|
5
5
|
[](https://npmjs.com/package/memorio)
|
|
6
6
|
[](https://npmjs.com/package/memorio)
|
|
@@ -13,197 +13,141 @@
|
|
|
13
13
|

|
|
14
14
|

|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
### One import. Global state, persistence, and a IndexedDB layer — done.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
```javascript
|
|
19
|
+
import 'memorio'
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
state.user = { name: 'Sara' } // reactive, everywhere, instantly
|
|
22
|
+
```
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
No provider tree. No reducers. No actions to dispatch before you can change a number. If you've ever set up a global store for an app that just needed *"a value, shared, that updates the UI when it changes,"* memorio is the toolkit for that thirty-second job — and it keeps growing with you: session storage, a cache, typed IndexedDB tables, an observer system, a React hook, devtools, and a change logger, all sharing one mental model.
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
| **Dependencies** | ✅ **Zero** | ❌ Many | ⚠️ Few |
|
|
28
|
-
| **TypeScript** | ✅ Native | ✅ Yes | ✅ Yes |
|
|
29
|
-
| **Binary storage** | ✅ Built-in IDB | ❌ Add-on | ❌ Add-on |
|
|
30
|
-
| **Observer** | ✅ Built-in | ❌ Add-on | ❌ Add-on |
|
|
31
|
-
| **DevTools** | ✅ Built-in + dphelper-manager | ⚠️ Extension | ⚠️ Extension |
|
|
32
|
-
| **Edge runtime** | ✅ Workers, Deno | ❌ Limited | ❌ Limited |
|
|
33
|
-
| **Learning curve** | ✅ **5 minutes** | ❌ Hours | ⚠️ 30 min |
|
|
34
|
-
| **Boilerplate** | ✅ **None** | ❌ Tons | ⚠️ Some |
|
|
35
|
-
| **React support** | ✅ `useObserver` hook | ✅ `connect` | ✅ `useSyncExternalStore` |
|
|
36
|
-
| **Context isolation** | ✅ Multi-tenant | ⚠️ Manual | ⚠️ Manual |
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Table of Contents
|
|
37
29
|
|
|
38
|
-
|
|
30
|
+
1. [Is this for you?](#is-this-for-you)
|
|
31
|
+
2. [Installation](#installation)
|
|
32
|
+
3. [Quick Start](#quick-start)
|
|
33
|
+
4. [API Reference](#api-reference)
|
|
34
|
+
5. [Cross-Platform Behavior](#cross-platform-behavior)
|
|
35
|
+
6. [Context Isolation (multi-tenant)](#context-isolation-multi-tenant)
|
|
36
|
+
7. [Security](#security)
|
|
37
|
+
8. [License](#license)
|
|
39
38
|
|
|
40
39
|
---
|
|
41
40
|
|
|
42
|
-
##
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
| **Platform detection** | `isBrowser`, `isNode`, `isDeno`, `isEdge` |
|
|
58
|
-
|
|
59
|
-
No Zustand. No Redux. No provider boilerplate.
|
|
60
|
-
**Import → assign → done.**
|
|
41
|
+
## Is this for you?
|
|
42
|
+
|
|
43
|
+
memorio is built for speed of thought: you think "I need this value everywhere," you write one line, it works. That's the entire pitch — and it's a real one, not a rewritten complaint about how much Redux boilerplate you've had to write.
|
|
44
|
+
|
|
45
|
+
**Reach for memorio when:**
|
|
46
|
+
- You want state that's simply *there* — no store setup, no provider wrapping your app.
|
|
47
|
+
- You want `localStorage`, `sessionStorage`, and `IndexedDB` behind one consistent API instead of learning three.
|
|
48
|
+
- You're prototyping, building an internal tool, or shipping something small-to-medium where iteration speed matters more than architectural ceremony.
|
|
49
|
+
|
|
50
|
+
**Reach for something else when:**
|
|
51
|
+
- You need every state path statically type-checked against every observer — memorio's `state.foo.bar` and `observer('state.foo.bar', ...)` are connected by a string, not by the compiler, so a rename won't be caught for you.
|
|
52
|
+
- You need Redux-style middleware, action logs, or time-travel debugging as a hard requirement for a large team — those tools exist because that discipline solves real problems at scale, not because their authors enjoy boilerplate.
|
|
53
|
+
- Your isolation requirements are a security boundary, not a convenience — see [Context Isolation](#context-isolation-multi-tenant) before you rely on it for that.
|
|
54
|
+
|
|
55
|
+
Pick the right tool. memorio is at its best when the answer to "how much state architecture do I need here?" is genuinely "not much."
|
|
61
56
|
|
|
62
57
|
---
|
|
63
58
|
|
|
64
|
-
##
|
|
59
|
+
## Installation
|
|
65
60
|
|
|
66
61
|
```bash
|
|
67
|
-
# npm
|
|
68
62
|
npm i memorio
|
|
63
|
+
# pnpm add memorio
|
|
64
|
+
# yarn add memorio
|
|
69
65
|
|
|
70
|
-
#
|
|
71
|
-
pnpm add memorio
|
|
72
|
-
|
|
73
|
-
# yarn
|
|
74
|
-
yarn add memorio
|
|
75
|
-
|
|
76
|
-
# React peer dep (optional, React >= 16.8)
|
|
66
|
+
# Optional — only if you use the React hook
|
|
77
67
|
npm i react react-dom
|
|
78
68
|
```
|
|
79
69
|
|
|
80
70
|
---
|
|
81
71
|
|
|
82
|
-
##
|
|
72
|
+
## Quick Start
|
|
83
73
|
|
|
84
|
-
### Global style
|
|
74
|
+
### Global style — the whole point of memorio
|
|
85
75
|
|
|
86
76
|
```typescript
|
|
87
|
-
|
|
88
|
-
import 'memorio'
|
|
77
|
+
import 'memorio' // once, at your entry point
|
|
89
78
|
|
|
90
|
-
// state is now available everywhere
|
|
91
79
|
state.user = { name: 'Sara', role: 'admin' }
|
|
92
80
|
state.counter++
|
|
93
|
-
state.settings = { theme: 'dark', lang: 'it' }
|
|
94
81
|
|
|
95
|
-
// React - automatic dependency discovery
|
|
96
82
|
useObserver(
|
|
97
|
-
() =>
|
|
83
|
+
() => console.debug('user changed:', state.user),
|
|
98
84
|
[state.user]
|
|
99
85
|
)
|
|
100
|
-
|
|
101
|
-
// Vanilla JS - event system
|
|
102
|
-
memorio.dispatch.listen('state.user', (event) => {
|
|
103
|
-
console.debug('user changed:', event.detail)
|
|
104
|
-
})
|
|
105
86
|
```
|
|
106
87
|
|
|
107
|
-
###
|
|
108
|
-
|
|
109
|
-
Every module is also a named export. Same instances, explicit dependencies.
|
|
88
|
+
### Named imports — same instances, explicit about it
|
|
110
89
|
|
|
111
90
|
```typescript
|
|
112
|
-
|
|
113
|
-
import {
|
|
114
|
-
state,
|
|
115
|
-
store,
|
|
116
|
-
session,
|
|
117
|
-
cache,
|
|
118
|
-
idb,
|
|
119
|
-
observer,
|
|
120
|
-
useObserver,
|
|
121
|
-
dispatch,
|
|
122
|
-
memorio
|
|
123
|
-
} from 'memorio'
|
|
91
|
+
import { state, store, session, cache, idb, observer, useObserver, dispatch, memorio } from 'memorio'
|
|
124
92
|
|
|
125
93
|
state.user = { name: 'Sara' }
|
|
126
94
|
store.set('theme', 'dark')
|
|
127
|
-
|
|
128
|
-
// CJS
|
|
129
|
-
const { state, store, memorio } = require('memorio')
|
|
130
95
|
```
|
|
131
96
|
|
|
132
97
|
```tsx
|
|
133
|
-
// React with named imports
|
|
134
|
-
import { useObserver, state } from 'memorio'
|
|
135
|
-
|
|
136
98
|
function Counter() {
|
|
137
99
|
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
138
|
-
|
|
139
100
|
useObserver(forceUpdate, [state.counter])
|
|
140
|
-
|
|
141
101
|
return <div>Count: {state.counter}</div>
|
|
142
102
|
}
|
|
143
103
|
```
|
|
144
104
|
|
|
145
|
-
|
|
105
|
+
Two styles, one engine underneath — use whichever reads better in your codebase.
|
|
146
106
|
|
|
147
107
|
---
|
|
148
108
|
|
|
149
|
-
##
|
|
150
|
-
|
|
151
|
-
### `state` — Reactive volatile state
|
|
109
|
+
## API Reference
|
|
152
110
|
|
|
153
|
-
|
|
111
|
+
### `state` — reactive, volatile, Proxy-based
|
|
154
112
|
|
|
155
113
|
```javascript
|
|
156
|
-
// Set
|
|
157
114
|
state.user = { name: 'Sara', role: 'admin' }
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
// Get
|
|
161
|
-
const name = state.user.name // 'Sara'
|
|
162
|
-
|
|
163
|
-
// List all keys
|
|
164
|
-
console.debug(state.list) // ['user', 'items']
|
|
115
|
+
const name = state.user.name
|
|
165
116
|
|
|
166
|
-
//
|
|
117
|
+
state.list // ['user', 'items', ...]
|
|
167
118
|
state.remove('items')
|
|
168
|
-
|
|
169
|
-
// Clear all
|
|
170
119
|
state.removeAll()
|
|
171
120
|
|
|
172
|
-
//
|
|
121
|
+
// Freeze a slice of state when you need to stop guessing who mutated it
|
|
173
122
|
state.config = { maxUsers: 100 }
|
|
174
123
|
state.config.lock()
|
|
175
|
-
state.config.maxUsers = 200
|
|
124
|
+
state.config.maxUsers = 200 // throws: state 'config' is locked
|
|
176
125
|
state.config.unlock()
|
|
177
126
|
```
|
|
178
127
|
|
|
179
|
-
### `store` —
|
|
128
|
+
### `store` — the value that survives a refresh
|
|
180
129
|
|
|
181
130
|
```javascript
|
|
182
131
|
store.set('preferences', { theme: 'dark' })
|
|
183
|
-
|
|
184
|
-
store.
|
|
185
|
-
store.removeAll()
|
|
186
|
-
console.debug(store.size(), 'chars stored')
|
|
187
|
-
console.debug(store.isPersistent) // true -> real localStorage
|
|
132
|
+
store.get('preferences') // { theme: 'dark' } or null
|
|
133
|
+
store.isPersistent // true when backed by real localStorage
|
|
188
134
|
```
|
|
189
135
|
|
|
190
|
-
### `session` —
|
|
136
|
+
### `session` — lives as long as the tab does
|
|
191
137
|
|
|
192
138
|
```javascript
|
|
193
139
|
session.set('token', 'user-abc-123')
|
|
194
|
-
|
|
195
|
-
session.removeAll()
|
|
140
|
+
session.get('token')
|
|
196
141
|
```
|
|
197
142
|
|
|
198
|
-
### `cache` —
|
|
143
|
+
### `cache` — the fastest thing you own, gone on refresh
|
|
199
144
|
|
|
200
145
|
```javascript
|
|
201
146
|
cache.set('temp', computeExpensiveResult())
|
|
202
|
-
|
|
203
|
-
cache.clear() // empty it all
|
|
147
|
+
cache.get('temp')
|
|
204
148
|
```
|
|
205
149
|
|
|
206
|
-
### `idb` —
|
|
150
|
+
### `idb` — typed, async, structured tables without the ceremony
|
|
207
151
|
|
|
208
152
|
```javascript
|
|
209
153
|
await idb.db.create('my-db')
|
|
@@ -212,7 +156,9 @@ await idb.data.set('my-db', 'users', { id: 1, name: 'Sara' })
|
|
|
212
156
|
const user = await idb.data.get('my-db', 'users', 1)
|
|
213
157
|
```
|
|
214
158
|
|
|
215
|
-
|
|
159
|
+
> IndexedDB is a browser-only primitive — see [Cross-Platform Behavior](#cross-platform-behavior) for what happens off the browser.
|
|
160
|
+
|
|
161
|
+
### `observer` / `useObserver` — watch a path, react to it
|
|
216
162
|
|
|
217
163
|
```javascript
|
|
218
164
|
observer('state.user', (newVal, oldVal) => {
|
|
@@ -220,133 +166,94 @@ observer('state.user', (newVal, oldVal) => {
|
|
|
220
166
|
})
|
|
221
167
|
```
|
|
222
168
|
|
|
223
|
-
|
|
169
|
+
> Keys here are plain strings, not statically checked against `state`'s shape. Keep the observer near the code that shapes that state, and grep before you rename.
|
|
224
170
|
|
|
225
|
-
|
|
226
|
-
import { useObserver, state } from 'memorio'
|
|
227
|
-
|
|
228
|
-
function Counter() {
|
|
229
|
-
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
230
|
-
|
|
231
|
-
useObserver(forceUpdate, [state.counter])
|
|
232
|
-
|
|
233
|
-
return <div>Count: {state.counter}</div>
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
### `dispatch` — Event system
|
|
171
|
+
### `dispatch` — the event bus underneath it all
|
|
238
172
|
|
|
239
173
|
```javascript
|
|
240
|
-
|
|
241
|
-
memorio.dispatch.
|
|
242
|
-
console.debug('user changed:', event.detail)
|
|
243
|
-
})
|
|
244
|
-
|
|
245
|
-
// Emit
|
|
246
|
-
memorio.dispatch.set('state.user', { detail: { name: 'state.user' } })
|
|
247
|
-
|
|
248
|
-
// Remove
|
|
249
|
-
memorio.dispatch.remove('state.user')
|
|
174
|
+
memorio.dispatch.listen('state.user', (event) => console.debug(event.detail))
|
|
175
|
+
memorio.dispatch.set('state.user', { detail: { name: 'Sara' } })
|
|
250
176
|
```
|
|
251
177
|
|
|
252
|
-
### `devtools` —
|
|
178
|
+
### `devtools` — see everything, instantly
|
|
253
179
|
|
|
254
180
|
```javascript
|
|
255
|
-
memorio.devtools.inspect()
|
|
256
|
-
memorio.devtools.stats()
|
|
257
|
-
memorio.devtools.
|
|
258
|
-
memorio.devtools.exportData() // JSON snapshot
|
|
259
|
-
$state // console shortcut -> globalThis.state
|
|
181
|
+
memorio.devtools.inspect()
|
|
182
|
+
memorio.devtools.stats()
|
|
183
|
+
memorio.devtools.exportData()
|
|
260
184
|
```
|
|
261
185
|
|
|
262
|
-
|
|
186
|
+
Pairs with [dphelper-manager](https://chrome.google.com/webstore/detail/dphelper-manager-dev-tool/oppppldaoknfddeikfloonnialijngbk) for visual, time-travel inspection of your global state straight from devtools.
|
|
263
187
|
|
|
264
|
-
### `logger` —
|
|
188
|
+
### `logger` — a black box for every change
|
|
265
189
|
|
|
266
190
|
```javascript
|
|
267
191
|
memorio.logger.configure({ enabled: true, logToConsole: true })
|
|
268
|
-
memorio.logger.getHistory()
|
|
269
|
-
memorio.logger.getStats() // { total, state, set, get, ... }
|
|
270
|
-
memorio.logger.exportLogs() // JSON string of all history
|
|
192
|
+
memorio.logger.getHistory()
|
|
271
193
|
```
|
|
272
194
|
|
|
195
|
+
> It logs *everything* written to `state`/`store`/`session` — including anything sensitive you put there. Great for debugging, but don't leave it on unconditionally in production if secrets or PII pass through your state. See [Security](#security).
|
|
196
|
+
|
|
273
197
|
---
|
|
274
198
|
|
|
275
|
-
##
|
|
199
|
+
## Cross-Platform Behavior
|
|
200
|
+
|
|
201
|
+
memorio runs everywhere JavaScript does — but "everywhere" means different guarantees in different places, and we'd rather tell you now than have you find out at 2am:
|
|
202
|
+
|
|
203
|
+
| API | Browser | Node.js | Deno | Edge / Workers |
|
|
204
|
+
|---|---|---|---|---|
|
|
205
|
+
| `state` | Proxy in memory | Proxy in memory | Proxy in memory | Proxy in memory |
|
|
206
|
+
| `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
|
|
207
|
+
| `cache` | ✅ in memory | ✅ in memory | ✅ in memory | ✅ in memory |
|
|
208
|
+
| `store` | `localStorage` | `Map` fallback — **not durable across restarts** | `Map` fallback — not durable | `localStorage` where available, else `Map` |
|
|
209
|
+
| `session` | `sessionStorage` | `Map` fallback — not durable | `Map` fallback — not durable | `sessionStorage` where available, else `Map` |
|
|
210
|
+
| `idb` | ✅ `IndexedDB` | ❌ not available | ❌ not available | ⚠️ check `getCapabilities()` |
|
|
211
|
+
| `devtools` | ✅ | ❌ | ❌ | ⚠️ |
|
|
212
|
+
|
|
213
|
+
Same API top to bottom — that's the promise. But if your server code leans on `store.get(...)` surviving a redeploy, know that on Node/Deno it won't; the fallback is an in-memory cache with the same shape, not durable storage.
|
|
276
214
|
|
|
277
215
|
```javascript
|
|
278
|
-
memorio.isBrowser()
|
|
279
|
-
memorio.isNode()
|
|
280
|
-
memorio.isDeno()
|
|
281
|
-
memorio.isEdge()
|
|
216
|
+
memorio.isBrowser()
|
|
217
|
+
memorio.isNode()
|
|
218
|
+
memorio.isDeno()
|
|
219
|
+
memorio.isEdge()
|
|
282
220
|
|
|
283
|
-
|
|
221
|
+
memorio.getCapabilities()
|
|
284
222
|
// { platform: 'browser', hasLocalStorage: true, hasIndexedDB: true, ... }
|
|
285
223
|
```
|
|
286
224
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
```typescript
|
|
290
|
-
import { isBrowser, isNode, getCapabilities } from 'memorio'
|
|
291
|
-
```
|
|
225
|
+
Check `getCapabilities()` before leaning on `idb` or persistent `store`/`session` in code that might run on more than one platform.
|
|
292
226
|
|
|
293
227
|
---
|
|
294
228
|
|
|
295
|
-
##
|
|
229
|
+
## Context Isolation (multi-tenant)
|
|
296
230
|
|
|
297
231
|
```javascript
|
|
298
|
-
// Create isolated context
|
|
299
232
|
const ctx = memorio.createContext('tenant-123')
|
|
300
233
|
|
|
301
|
-
// Use context storage (prefix: 'tenant-123-key')
|
|
302
234
|
ctx.state.user = { name: 'Isolated' }
|
|
303
235
|
ctx.store.set('settings', { theme: 'dark' })
|
|
304
|
-
ctx.session.set('token', 'abc123')
|
|
305
|
-
|
|
306
|
-
// Context is completely isolated from global state
|
|
307
|
-
console.debug(state.user) // undefined
|
|
308
236
|
|
|
309
|
-
//
|
|
310
|
-
memorio.listContexts() // ['tenant-123']
|
|
311
|
-
memorio.deleteContext('tenant-123')
|
|
237
|
+
console.debug(state.user) // undefined — separate namespace
|
|
312
238
|
```
|
|
313
239
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
```typescript
|
|
317
|
-
import { createContext, listContexts, deleteContext, isolate } from 'memorio'
|
|
318
|
-
```
|
|
240
|
+
Handy for keeping per-tenant or per-request state from colliding in the same process. Under the hood it's a key prefix (`tenant-123-key`) inside the same storage — a naming convention, not a hard memory boundary. Great for a browser tab; if you're running this in a shared Node.js process or an edge isolate that might be reused across requests, make sure tenant IDs can't collide or be forged, and don't treat this as your only isolation layer if the stakes are real.
|
|
319
241
|
|
|
320
242
|
---
|
|
321
243
|
|
|
322
|
-
##
|
|
244
|
+
## Security
|
|
323
245
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
| `state` | ✅ | ✅ | ✅ | ✅ |
|
|
329
|
-
| `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
|
|
330
|
-
| `cache` | ✅ | ✅ | ✅ | ✅ |
|
|
331
|
-
| `store` | localStorage | memory | memory | localStorage |
|
|
332
|
-
| `session` | sessionStorage | memory | memory | sessionStorage |
|
|
333
|
-
| `idb` | IndexedDB | ❌ | ❌ | ⚠️ |
|
|
334
|
-
| `devtools` | ✅ | ❌ | ❌ | ⚠️ |
|
|
335
|
-
|
|
336
|
-
> **Why memory fallbacks on the server?** There is no browser. `store` and `session` gracefully fall back to `Map`. You still get the same API. Same `state`, same `cache`, same `useObserver`. No extra config required.
|
|
337
|
-
|
|
338
|
-
---
|
|
246
|
+
- Zero production dependencies.
|
|
247
|
+
- No `eval`, no dynamic code execution, no bundled telemetry.
|
|
248
|
+
- Session IDs generated via `crypto.randomUUID`.
|
|
249
|
+
- Inputs validated, keys sanitized, errors caught at module boundaries.
|
|
339
250
|
|
|
340
|
-
|
|
251
|
+
memorio does **not** encrypt what you put into `store`, `session`, or `idb` — they're thin, fast wrappers over `localStorage`/`sessionStorage`/`IndexedDB`, which store data in the clear on the user's device. Bring your own encryption layer for tokens, secrets, or regulated personal data.
|
|
341
252
|
|
|
342
|
-
-
|
|
343
|
-
- NIST & NSA aligned — enterprise-grade security standards
|
|
344
|
-
- No `eval`, no obfuscation, no hardcoded secrets
|
|
345
|
-
- All inputs validated, keys sanitized, errors caught
|
|
346
|
-
- Secure random session IDs via `crypto.randomUUID`
|
|
253
|
+
We build with recognized engineering guidance (NIST SP 800-53 practices) as an input to how we write code — that's a design discipline, not a compliance certificate, and no third-party audit has been performed. Found an issue? Report it privately — see `SECURITY.md` — rather than opening a public issue.
|
|
347
254
|
|
|
348
255
|
---
|
|
349
256
|
|
|
350
|
-
##
|
|
257
|
+
## License
|
|
351
258
|
|
|
352
259
|
MIT © [Dario Passariello](https://dario.passariello.ca)
|
package/index.cjs
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var g=(e,t)=>()=>(e&&(t=e(e=0)),t);var a=g(()=>{});var y,Ne,be;exports.propertyName=void 0;exports.internal=void 0;var P=g(()=>{a();y={debug:false,tracking:false,trackedPaths:new Set,locked:false,lastAccessedPath:"",stateVersion:0,currentContext:null},Ne={get debug(){return y.debug},set debug(e){y.debug=e;},get tracking(){return y.tracking},set tracking(e){y.tracking=e;},get trackedPaths(){return y.trackedPaths},clearTrackedPaths(){y.trackedPaths.clear();},get locked(){return y.locked},set locked(e){y.locked=e;},get lastAccessedPath(){return y.lastAccessedPath},set lastAccessedPath(e){y.lastAccessedPath=e;},get stateVersion(){return y.stateVersion},bumpStateVersion(){return y.stateVersion=(y.stateVersion||0)+1,y.stateVersion},get currentContext(){return y.currentContext},set currentContext(e){y.currentContext=e;}},be=["list","state","store","idb","observer","useObserver","remove","removeAll","_platform","_capabilities","_sessionId"],exports.propertyName=(e,t)=>String(t!==void 0?t:e).replace("() => ",""),exports.internal=Ne;});exports.message=void 0;var c,b=g(()=>{a();P();exports.message=(...e)=>{exports.internal.debug===true&&console.debug(...e);},c=exports.message;});function K(){let e=globalThis;if(typeof e.crypto<"u"&&e.crypto.randomUUID)return e.crypto.randomUUID();if(typeof e.crypto<"u"&&e.crypto.getRandomValues){let t=new Uint8Array(16);return e.crypto.getRandomValues(t),Array.from(t,r=>r.toString(16).padStart(2,"0")).join("")}return `session_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function z(){let e=globalThis;return e.Deno&&e.Deno.version?"deno":typeof process<"u"&&process.versions&&process.versions.node?"node":typeof globalThis<"u"&&typeof globalThis.ServiceWorkerGlobalScope<"u"?"edge":typeof window<"u"&&typeof document<"u"?"browser":"unknown"}function Q(){return z()==="browser"}function X(){return z()==="node"}function Z(){return z()==="deno"}function ee(){return z()==="edge"}function te(){try{if(typeof sessionStorage<"u"){let e="__memorio_test__";return sessionStorage.setItem(e,"1"),sessionStorage.removeItem(e),sessionStorage}}catch{}return null}function re(){try{if(typeof localStorage<"u"){let e="__memorio_test__";return localStorage.setItem(e,"1"),localStorage.removeItem(e),localStorage}}catch{}return null}function oe(){return typeof indexedDB<"u"}function Le(){return typeof globalThis.dispatchEvent=="function"}function q(){let e=z(),t=typeof globalThis.isSecureContext<"u"?globalThis.isSecureContext:e==="browser";return {platform:e,hasSessionStorage:te()!==null,hasLocalStorage:re()!==null,hasIndexedDB:oe(),hasDispatchEvent:Le(),hasNavigator:typeof navigator<"u",hasProcess:typeof process<"u",isSecureContext:t,sessionId:K()}}function ve(){let e=q(),t=globalThis;e.hasDispatchEvent||(t.dispatchEvent=function(r){return true},typeof CustomEvent>"u"&&(t.CustomEvent=class{type;detail;constructor(s,o={}){this.type=s,this.detail=o;}})),typeof t.addEventListener!="function"&&(t.addEventListener=function(r,s){L.has(r)||L.set(r,[]),L.get(r).push(s);},t.removeEventListener=function(r,s){let o=L.get(r);if(o){let n=o.indexOf(s);n>-1&&o.splice(n,1);}},t.dispatchEvent=function(r){let s=L.get(r.type);return s&&s.forEach(o=>{try{o(r);}catch(n){console.error("Event listener error:",n);}}),true});}function J(e){let t=e||`context_${K()}`;ae(t);let r={state:{},store:new Map,session:new Map,cache:new Map};return se.set(t,r),{id:t,state:r.state,store:{get:s=>{let o=r.store.get(s);return o?JSON.parse(o):null},set:(s,o)=>{r.store.set(s,JSON.stringify(o));},remove:s=>r.store.delete(s),removeAll:()=>r.store.clear(),clearAll:()=>r.store.clear(),size:()=>r.store.size,isPersistent:false},session:{get:s=>{let o=r.session.get(s);return o?JSON.parse(o):null},set:(s,o)=>{r.session.set(s,JSON.stringify(o));},remove:s=>r.session.delete(s),removeAll:()=>r.session.clear(),clearAll:()=>r.session.clear(),size:()=>r.session.size,isPersistent:false},cache:{get:s=>r.cache.get(s),set:(s,o)=>r.cache.set(s,o),remove:s=>r.cache.delete(s),removeAll:()=>r.cache.clear(),clear:()=>r.cache.clear()}}}function ne(){return Array.from(se.keys())}function ie(e){return se.delete(e)}function ae(e){exports.internal.currentContext=e;}var L,se,B=g(()=>{a();P();L=new Map;se=new Map;});var Fe={};var xe=g(()=>{a();x();b();exports.idb.db.create=(e,t=1)=>new Promise((r,s)=>{if(!exports.idb.db.support())return s(new Error("IndexedDB not supported"));let o=globalThis.indexedDB.open(e,t);o.onerror=()=>{c(`IndexedDB error: ${o.error?.message}`),s(o.error);},o.onsuccess=()=>{c(`Database ${e} connected successfully`),r(o.result);},o.onupgradeneeded=()=>{c(`Database ${e} upgrade/creation initiated`);};});});var We={};var we=g(()=>{a();x();exports.idb.db.list=async()=>{if(!("indexedDB"in globalThis)||!indexedDB.databases)return [];try{let e=await indexedDB.databases();return globalThis.idbases=e||[],await exports.idb.db.size(),globalThis.idbases}catch(e){return console.error("Error listing databases:",e),[]}};});var He={};var Se=g(()=>{a();x();exports.idb.db.exist=e=>idbases?.some(t=>t.name===e);});var Ye={};var Pe=g(()=>{a();x();exports.idb.db.quota=()=>navigator.storage.estimate();});var Ge={};var Te=g(()=>{a();x();b();exports.idb.db.delete=e=>new Promise((t,r)=>{c(`Removing database ${e}...`),(()=>{let o=indexedDB.deleteDatabase(e);o.onsuccess=()=>{c(`${e} database removed successfully`),exports.idb.db.list(),t();},o.onerror=()=>{console.error(`Error removing ${e}:`,o.error),r(o.error);},o.onblocked=()=>{console.warn(`Deletion of ${e} is blocked. Please close other tabs.`);};})();});});var Qe={};var Oe=g(()=>{a();x();b();exports.idb.db.size=async()=>{if(!(!idbases||idbases.length===0))for(let e=0;e<idbases.length;e++){let t=idbases[e];try{let r=await exports.idb.db.create(t.name,t.version),s=Array.from(r.objectStoreNames),o=0;for(let n of s){let i=await exports.idb.table.size(r,n);o+=i;}t.size=o,r.close();}catch(r){c(`Could not calculate size for ${t.name}:${r}`);}}};});var Xe={};var Ee=g(()=>{a();x();exports.idb.db.version=e=>{let t=0;for(let r of idbases){r.name===e&&(t=r.version);break}return t};});var Ze={};var De=g(()=>{a();x();b();exports.idb.db.support=()=>{let e="indexedDB"in globalThis;return e||c("Your environment doesn't support IndexedDB"),e};});var et={};var Ce=g(()=>{a();x();b();exports.idb.table.create=(e,t)=>new Promise((r,s)=>{try{let n=(Number(exports.idb.db.version(e))||0)+1,i=indexedDB.open(e,n);i.onupgradeneeded=m=>{let p=m.target.result;if(!p.objectStoreNames.contains(t)){let f=p.createObjectStore(t,{keyPath:"id",autoIncrement:!0});f.createIndex("id","id",{unique:!0}),f.createIndex("data","data",{unique:!1}),c(`Table ${t} created in ${e}`);}},i.onsuccess=()=>{i.result.close(),exports.idb.db.list(),r();},i.onerror=()=>{console.error(`Error creating table ${t}:`,i.error),s(i.error);};}catch(o){console.error("Critical error in table.create:",o),s(o);}});});var tt={};var je=g(()=>{a();x();b();exports.idb.table.size=(e,t)=>new Promise((r,s)=>{if(!e)return s(new Error("Database instance is required"));if(!e.objectStoreNames.contains(t))return r(0);let o=0,n=0,p=e.transaction([t],"readonly").objectStore(t).openCursor();p.onsuccess=async f=>{let O=f.target.result;if(O){try{let M=O.value;o+=JSON.stringify(M).length;}catch(M){c(`Error stringifying IDB value tracking size:${M}`);}n++,n%200===0&&await new Promise(M=>setTimeout(M,0)),O.continue();}else r(o);},p.onerror=()=>{s(p.error);};});});var rt={};var ke=g(()=>{a();x();b();exports.idb.data.delete=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=()=>{let i=n.result;if(!i.objectStoreNames.contains(t))return i.close(),o(new Error(`Table ${t} not found`));let f=i.transaction(t,"readwrite").objectStore(t).delete(r);f.onsuccess=()=>{i.close(),c(`Record ${r} deleted from ${t}`),s();},f.onerror=()=>{i.close(),o(f.error);};},n.onerror=()=>o(n.error);});exports.idb.data.delete.all=(e,t)=>new Promise((r,s)=>{let o=indexedDB.open(e);o.onsuccess=n=>{let i=n.target.result;if(!i.objectStoreNames.contains(t))return i.close(),s(new Error(`Table ${t} not found`));let f=i.transaction(t,"readwrite").objectStore(t).clear();f.onsuccess=()=>{i.close(),c(`All data cleared from ${t}`),r();},f.onerror=()=>{i.close(),s(f.error);};},o.onerror=()=>s(o.error);});});var ot={};var _e=g(()=>{a();x();b();exports.idb.data.set=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=()=>{let i=n.result;if(!i.objectStoreNames.contains(t))return i.close(),o(new Error(`Table ${t} does not exist in ${e}`));let f=i.transaction(t,"readwrite").objectStore(t).put(r);f.onsuccess=()=>{i.close(),c(`Data saved in ${e}.${t}`),s(f.result);},f.onerror=O=>{i.close(),c(`Database insert error: ${f.error?.message}`),o(f.error);};},n.onerror=()=>{o(n.error);};});});var st={};var $e=g(()=>{a();x();exports.idb.data.get=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=i=>{let m=i.target.result;if(!m.objectStoreNames.contains(t))return m.close(),o(new Error(`Table ${t} not found in ${e}`));let O=m.transaction(t,"readonly").objectStore(t).get(r);O.onsuccess=()=>{m.close(),s(O.result);},O.onerror=()=>{m.close(),o(O.error);};},n.onerror=()=>{o(n.error);};});});var nt;exports.idb=void 0;var x=g(()=>{a();B();nt=oe(),exports.idb={db:{},table:{},data:{}};nt?(async()=>(Object.defineProperty(exports.idb,"db",{value:{},writable:true,configurable:true}),Object.defineProperty(exports.idb,"table",{value:{},writable:true,configurable:true}),Object.defineProperty(exports.idb,"data",{value:{},writable:true,configurable:true}),Object.defineProperty(globalThis,"idbases",{value:[],writable:true,configurable:true,enumerable:false}),await Promise.all([Promise.resolve().then(()=>(xe(),Fe)),Promise.resolve().then(()=>(we(),We)),Promise.resolve().then(()=>(Se(),He)),Promise.resolve().then(()=>(Pe(),Ye)),Promise.resolve().then(()=>(Te(),Ge)),Promise.resolve().then(()=>(Oe(),Qe)),Promise.resolve().then(()=>(Ee(),Xe)),Promise.resolve().then(()=>(De(),Ze)),Promise.resolve().then(()=>(Ce(),et)),Promise.resolve().then(()=>(je(),tt)),Promise.resolve().then(()=>(ke(),rt)),Promise.resolve().then(()=>(_e(),ot)),Promise.resolve().then(()=>($e(),st))]),Object.preventExtensions(exports.idb),Object.seal(exports.idb),Object.freeze(exports.idb)))():(exports.idb._disabled=true,exports.idb._warning="IndexedDB is not available in this environment (Node.js/Deno). Use store or session for persistence.",console.warn("Memorio IDB: IndexedDB is not available in this environment. Use store or session for data persistence."));});a();a();P();b();a();var v={set:(e,t={})=>{globalThis.dispatchEvent(new CustomEvent(String(e),t));},listen:(e,t=null,r)=>{if(globalThis.events?.[e])return;let s=t?o=>{let n=o;return globalThis.queueMicrotask?globalThis.queueMicrotask(()=>t(n)):Promise.resolve().then(()=>t(n))}:void 0;s&&globalThis.addEventListener(e,s),s&&(globalThis.events[e]=s);},remove:e=>{let t=globalThis.events?.[e];t&&(globalThis.removeEventListener(e,t),delete globalThis.events[e]);}};var V=Symbol("memorio.target"),pe=new WeakMap,G=(e,t=null)=>{if(e===null||typeof e!="object")return e;if(e[V]!==void 0)return G(e[V],t);if(t){if(t.has(e))return e;t.add(e);}let r=e.constructor?.name;if(r!=="Object"&&r!=="Array")return e;let s=Array.isArray(e)?[]:{};for(let o of Reflect.ownKeys(e))s[o]=G(e[o],t);return s},ye=(e,t,r=".")=>t.concat(e).join(r),he=(e,t,r=[])=>{let s=o=>{try{v.set(o,{detail:{name:o}});}catch{}};return new Proxy(e,{get(o,n){if(n==="__path")return r.length>0?"state."+r.join("."):"state";if(n===V||o[V]!==void 0)return o;if(n==="list")return c('Some state could be hidden when you use "state.list". Use "state" to see the complete list '),JSON.parse(JSON.stringify(o));if(typeof n=="string"){let i=r.length>0?"state."+r.concat(n).join("."):"state."+n;exports.internal.lastAccessedPath=i,exports.internal.tracking&&exports.internal.trackedPaths.add(i);}if(n==="_lastPath")return exports.internal.lastAccessedPath;if(n==="remove")return i=>(delete o[i],true);if(n==="removeAll")return ()=>{try{for(let i in o)typeof o[i]!="function"&&!["list","remove","removeAll","lock","unlock"].includes(i)&&delete o[i];}catch(i){console.error(i);}};if(Object.isFrozen(o[n]))return o[n];if(n==="lock"||n==="unlock"){let i=Reflect.get(o,n);if(i)return i}try{let i=Reflect.get(o,n);if(i&&typeof i=="object"&&["Array","Object"].includes(i.constructor.name)){let m=pe.get(i);return m||(m=he(i,t,r.concat(n)),pe.set(i,m)),m}return i}catch(i){console.error("Error: ",i);return}},set(o,n,i){if(exports.internal.locked)return console.error("Error: state is locked. Use state.unlock() to enable modifications."),false;if(be.includes(n))return console.error("key "+n+" is protected"),false;if(o[n]&&typeof o[n]=="object"&&Object.isFrozen(o[n]))return console.error(`Error: state '${n}' is locked`),false;if(o[n]&&typeof o[n]=="object"&&o[n].__locked)return console.error(`Error: state '${n}' is locked. Use state.${n}.unlock() to enable modifications.`),false;try{let m=ye(n,r),p=G(i);if(t({action:"set",path:m,target:o,newValue:p,previousValue:Reflect.get(o,n)}),s("state."+m),Reflect.set(o,n,p),exports.internal.bumpStateVersion(),o[n]&&typeof o[n]=="object"){let f=o[n];if(f&&typeof f=="object")try{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!1}),Object.defineProperty(f,"lock",{writable:!1,enumerable:!1,configurable:!1,value:()=>{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!0}),c(`State '${n}' is now locked.`);}}),Object.defineProperty(f,"unlock",{writable:!1,enumerable:!1,configurable:!1,value:()=>{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!1}),c(`State '${n}' is now unlocked.`);}});}catch{}}return !0}catch(m){return console.error("Error in set trap:",m),false}},deleteProperty(o,n){try{let i=ye(n,r);return t({action:"delete",path:i,target:o}),Reflect.deleteProperty(o,n)}catch(i){return console.error("Error in deleteProperty trap:",i),false}},ownKeys(o){return Reflect.ownKeys(o)},getOwnPropertyDescriptor(o,n){return Reflect.getOwnPropertyDescriptor(o,n)}})},N=he({},()=>{});N.lock=()=>{exports.internal.locked=true,c("State is now locked. All modifications are blocked.");};N.unlock=()=>{exports.internal.locked=false,c("State is now unlocked. Modifications are allowed.");};a();B();P();b();var w=re(),le=new Map;function $(){let t=exports.internal.currentContext||""||"default";return le.has(t)||le.set(t,new Map),le.get(t)}var _=w!==null;function k(){let e=exports.internal.currentContext||"";return e?`${e}-`:"memorio_store_"}function ce(e){return !e||typeof e!="string"?(console.warn("[memorio store] key is empty or not a string \u2014 operation aborted"),""):e.length>512?(console.warn(`[memorio store] key "${e}" exceeds 512 chars \u2014 operation aborted`),""):k()+e}function ze(e){let t=_?w.getItem(e):$().get(e);return t&&JSON.parse(t)}function qe(e,t){let r=JSON.stringify(t);_?w.setItem(e,r):$().set(e,r);}function Je(e){if(_){if(w.getItem(e))return w.removeItem(e),true}else if($().has(e))return $().delete(e),true;return false}var D=new Proxy({},{});Object.defineProperty(globalThis,"store",{value:D,enumerable:false,configurable:true});Object.defineProperties(D,{get:{value:e=>{if(!e)return console.warn("[memorio store] store.get() called with empty or null key \u2014 returning null"),null;try{return ze(ce(e))}catch(t){exports.message(`Error parsing store item '${e}': ${t}`);}return null}},getMultiple:{value:e=>{let t={};for(let r of e)try{let s=D.get(r);s&&(t[r]=s);}catch(s){console.debug(`[memorio store] getMultiple error for key "${r}":`,s);}return t}},set:{value:(e,t)=>{if(!e)return console.warn("[memorio store] store.set() called with empty or null key \u2014 write aborted"),false;let r=ce(e);if(!r)return false;if(typeof t=="function")return console.warn("[memorio store] functions are not storable \u2014 write aborted for key: "+e),exports.message("Storing functions is not secure and is blocked for safety."),false;try{qe(r,t);}catch(s){return exports.message(`Error setting store item '${e}': ${s}`),false}return true}},remove:{value:e=>{if(!e)return console.debug("[memorio store] store.remove() called with empty or null key \u2014 returning false"),false;let t=ce(e);if(!t)return false;try{return Je(t)}catch(r){exports.message(`Error removing store item '${e}': ${r}`);}return false}},delete:{value:e=>D.remove(e)},removeAll:{value:()=>{if(_){let e=[];for(let t=0;t<w.length;t++){let r=w.key(t);r?.startsWith(k())&&e.push(r);}e.forEach(t=>w.removeItem(t));}else $().clear();return true}},clearAll:{value:()=>(D.removeAll(),true)},quota:{value:async()=>[0,0]},size:{value:()=>{let e=0;return _?Object.keys(w).forEach(t=>{if(t.startsWith(k())){let r=w.getItem(t);r&&(e+=r.length);}}):$().forEach(t=>{e+=t.length;}),e}},isPersistent:{get:()=>_},list:{value:()=>{let e={};try{if(_)for(let t=0;t<w.length;t++){let r=w.key(t);if(r?.startsWith(k())){let s=r.replace(k(),""),o=w.getItem(r);if(o!==null)try{e[s]=JSON.parse(o);}catch{e[s]=o;}}}else $().forEach((t,r)=>{if(r.startsWith(k())){let s=r.replace(k(),"");try{e[s]=JSON.parse(t);}catch{e[s]=t;}}});}catch(t){exports.message(`Error listing store items: ${t}`);}return e}}});Object.freeze(D);a();B();P();b();var S=te(),ue=new Map;function R(){let t=exports.internal.currentContext||""||"default";return ue.has(t)||ue.set(t,new Map),ue.get(t)}var A=S!==null;function I(){let e=exports.internal.currentContext||"";return e?`${e}-`:"memorio_session_"}function fe(e){return !e||typeof e!="string"?(console.warn("[memorio session] key is empty or not a string \u2014 operation aborted"),""):e.length>512?(console.warn(`[memorio session] key "${e}" exceeds 512 chars \u2014 operation aborted`),""):I()+e}function Ue(e){let t=A?S.getItem(e):R().get(e);return t&&JSON.parse(t)}function Ve(e,t){let r=JSON.stringify(t);A?S.setItem(e,r):R().set(e,r);}function Ke(e){if(A){if(S.getItem(e))return S.removeItem(e),true}else if(R().has(e))return R().delete(e),true;return false}var C=new Proxy({},{});Object.defineProperty(globalThis,"session",{value:C,enumerable:false,configurable:true});Object.defineProperties(C,{get:{value:e=>{if(!e)return console.warn("[memorio session] session.get() called with empty or null key \u2014 returning null"),null;try{return Ue(fe(e))}catch(t){exports.message(`Error parsing session item '${e}':${t}`);}return null}},set:{value:(e,t)=>{if(!e)return console.warn("[memorio session] session.set() called with empty or null key \u2014 write aborted"),false;let r=fe(e);if(!r)return false;if(typeof t=="function")return console.warn("[memorio session] functions are not storable \u2014 write aborted for key: "+e),exports.message("It's not secure to session functions."),false;try{Ve(r,t);}catch(s){return exports.message(`Error setting session item '${e}': ${s}`),false}return true}},remove:{value:e=>{if(!e)return console.warn("[memorio session] session.remove() called with empty or null key \u2014 returning false"),false;let t=fe(e);if(!t)return false;try{return Ke(t)}catch(r){exports.message(`Error removing session item '${e}': ${r}`);}return false}},delete:{value:e=>C.remove(e)},removeAll:{value:()=>{if(A){let e=[];for(let t=0;t<S.length;t++){let r=S.key(t);r?.startsWith(I())&&e.push(r);}e.forEach(t=>S.removeItem(t));}else R().clear();return true}},clearAll:{value:()=>(C.removeAll(),true)},quota:{value:async()=>[0,0]},size:{value:()=>{let e=0;return A?Object.keys(S).forEach(t=>{if(t.startsWith(I())){let r=S.getItem(t);r&&(e+=r.length);}}):R().forEach(t=>{e+=t.length;}),e}},isPersistent:{get:()=>A},list:{value:()=>{let e={};try{if(A)for(let t=0;t<S.length;t++){let r=S.key(t);if(r?.startsWith(I())){let s=r.replace(I(),""),o=S.getItem(r);if(o!==null)try{e[s]=JSON.parse(o);}catch{e[s]=o;}}}else R().forEach((t,r)=>{if(r.startsWith(I())){let s=r.replace(I(),"");try{e[s]=JSON.parse(t);}catch{e[s]=t;}}});}catch(t){exports.message(`Error listing session items: ${t}`);}return e}}});Object.freeze(C);a();var T={},F=new Proxy({},{get(e,t){let r=t;return r==="get"?s=>T[s]:r==="set"?(s,o)=>{T[s]=o;}:r==="remove"?s=>(delete T[s],true):r==="removeAll"?()=>(Object.keys(T).forEach(s=>delete T[s]),true):r==="clear"?()=>(Object.keys(T).forEach(s=>delete T[s]),true):r==="list"?()=>({...T}):T[r]},set(e,t,r){return T[t]=r,true},deleteProperty(e,t){return delete T[t],true}});Object.freeze(F);x();a();b();var Ie=false,it=(e,t=null,r=true)=>{Ie||(console.warn('DEPRECATED: "observer" is deprecated and will be removed in future versions. Please use "useObserver" instead.'),Ie=true);let s=n=>typeof n=="string"?n:n&&typeof n=="object"&&n.__path?n.__path:null,o=s(e);if(!e&&!t){console.error("Observer Error: You need to setup observer correctly, Some parameters are missed!");return}if(!e&&t){console.error("Observer Error: You need to declare what state need to be monitored as string like 'state.test'.");return}if(o){let n=o.split(".");if(n[0]!=="state"&&n[0]!=="store"){console.error(`Observer Error: You need to declare 'state.' or 'store.'. The '${o}' string is incorrect!`);return}}if(e&&!t){let n=s(e);if(!n)return;globalThis.observer?.list?.[n]&&v.remove(n),c(`called: ${n}`);return}if(e&&t){let n=s(e);if(!n)return;if(typeof e!="string"&&!(e&&typeof e=="object")){console.error("Observer Error: name of state need to be a 'string' like 'state.test' or a direct state value");return}let i=Array.isArray(t)?t:[t];globalThis.observer?.list?.[n]&&v.remove(n),i.forEach(p=>{typeof p=="function"&&v.listen(n,p,r);});return}},W=it;Object.defineProperties(W,{list:{get:()=>globalThis.events},remove:{value:e=>{e&&(v.remove(e),delete globalThis.events[e]);}},removeAll:{get:()=>{let e=globalThis.observer,t=e?.list;return t&&Object.keys(t).forEach(r=>{e?.remove?.(r);}),true}},has:{value:e=>!!globalThis.observer?.list?.[e]}});a();b();P();globalThis.useObserver||(globalThis.useObserver=null);Object.defineProperty(globalThis,"useObserver",{value:null,writable:true,enumerable:false,configurable:true});var H=((e,t=[])=>{if(!t||typeof e!="function")return ()=>{};let r=[],s=Array.isArray(t)&&!t.__path?t:[t];try{return s.forEach(o=>{let n="";if(typeof o=="function"){let i=exports.propertyName(o);i&&(n=i);}else typeof o=="object"&&o!==null&&(n=o.__path||(typeof o.toString=="function"&&o.toString()!=="[object Object]"?o.toString():""));if(n){n=n.replace(/^(\(\)\s*=>\s*)/,"").replace(/^globalThis\./,"").replace(/^state\./,"");let i=n.startsWith("store.")||n.startsWith("state.")?n:"state."+n;v.listen(i,()=>e()),r.push(i);}else {exports.internal.clearTrackedPaths(),exports.internal.tracking=!0;try{e();}catch{}exports.internal.tracking=!1,exports.internal.trackedPaths.forEach(i=>{r.includes(i)||(c(`useObserver: [Auto-Discovery] -> "${i}"`),v.listen(i,()=>e()),r.push(i));});}}),r.length>0?c(`useObserver: Monitoring ${r.length} paths.`):console.warn("useObserver: No paths resolved for monitoring. Check your dependencies!"),()=>{r.forEach(o=>{typeof v.remove=="function"&&(v.remove(o),c(`useObserver: Stopped monitoring "${o}"`));});}}catch(o){return c(`useObserver Error: ${o}`),()=>{}}});globalThis.useObserver=H;Object.freeze(globalThis.useObserver);b();a();P();function at(){return exports.internal.debug===true}function Ae(){if(!globalThis.store)return {};let e={},t=globalThis.store;if(typeof t.list=="function")try{return t.list()}catch{}if(typeof t.get=="function"){for(let r of Object.keys(t))if(!["get","set","remove","delete","removeAll","clearAll","size","isPersistent","list"].includes(r))try{let s=t.get(r);s!=null&&(e[r]=s);}catch{}}return e}function Re(){if(!globalThis.session)return {};let e={},t=globalThis.session;if(typeof t.list=="function")try{return t.list()}catch{}if(typeof t.get=="function"){for(let r of Object.keys(t))if(!["get","set","remove","delete","removeAll","clearAll","size","isPersistent","list"].includes(r))try{let s=t.get(r);s!=null&&(e[r]=s);}catch{}}return e}var lt=()=>{if(at()){if(globalThis.state){let e=globalThis.state.list,t;typeof e=="function"?t=e():typeof e=="object"&&e!==null?t=e:t=globalThis.state,console.table(t);}if(globalThis.store&&console.table(Ae()),globalThis.session&&console.table(Re()),globalThis.cache){let e=globalThis.cache.list,t;typeof e=="function"?t=e():typeof e=="object"&&e!==null?t=e:t=globalThis.cache,console.table(t);}}},ct=()=>{let e=t=>{if(!t)return 0;if(typeof t.list=="function")try{let r=t.list();return Object.keys(r).length}catch{}return Object.keys(t).length};return {stateKeys:e(globalThis.state),storeKeys:e(globalThis.store),sessionKeys:e(globalThis.session),cacheKeys:e(globalThis.cache),idbDatabases:0,lastUpdate:new Date().toISOString()}},U=e=>{globalThis[e]&&typeof globalThis[e].clear=="function"?globalThis[e].clear():console.error(`Module ${e} not found or does not support clear()`);},ut=()=>{U("state"),U("store"),U("session"),U("cache");},ft=()=>{let e=()=>{if(globalThis.state)try{return typeof globalThis.state.list=="function"?globalThis.state.list():globalThis.state}catch{return}},t=()=>Ae(),r=()=>Re(),s=()=>{if(globalThis.cache)try{return typeof globalThis.cache.list=="function"?globalThis.cache.list():globalThis.cache}catch{return}},o={state:e(),store:t(),session:r(),cache:s(),exportedAt:new Date().toISOString()};return JSON.stringify(o,null,2)},dt=e=>{try{let t=JSON.parse(e);t.state&&Object.entries(t.state).forEach(([r,s])=>{globalThis.state&&r!=="list"&&r!=="remove"&&r!=="removeAll"&&(globalThis.state[r]=s);}),t.store&&globalThis.store&&typeof globalThis.store.set=="function"&&Object.entries(t.store).forEach(([r,s])=>{globalThis.store.set(r,s);}),t.session&&globalThis.session&&typeof globalThis.session.set=="function"&&Object.entries(t.session).forEach(([r,s])=>{globalThis.session.set(r,s);}),t.cache&&globalThis.cache&&Object.entries(t.cache).forEach(([r,s])=>{globalThis.cache&&r!=="get"&&r!=="set"&&r!=="remove"&&r!=="clear"&&(globalThis.cache[r]=s);});}catch(t){console.error("%c\u2717 Import failed:","color: #F44336",t);}},mt=(e,t)=>{if(!globalThis[e]){console.error(`Module ${e} not found`);return}let r=globalThis[e],s=r[t];if(console.debug(`\u{1F441} Watching ${e}.${t} (initial: ${JSON.stringify(s)})`),e==="state"&&globalThis.memorio?.dispatch){let o=n=>{n.detail?.name?.includes(t)&&console.debug(`\u{1F441} Change: ${e}.${t} =`,n.detail.value);};r.addEventListener?.("memorio-change",o);}},gt=()=>{console.debug(`
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var g=(e,t)=>()=>(e&&(t=e(e=0)),t);var a=g(()=>{});var y,Ne,be;exports.propertyName = void 0;exports.internal = void 0;var P=g(()=>{a();y={debug:false,tracking:false,trackedPaths:new Set,locked:false,lastAccessedPath:"",stateVersion:0,currentContext:null},Ne={get debug(){return y.debug},set debug(e){y.debug=e;},get tracking(){return y.tracking},set tracking(e){y.tracking=e;},get trackedPaths(){return y.trackedPaths},clearTrackedPaths(){y.trackedPaths.clear();},get locked(){return y.locked},set locked(e){y.locked=e;},get lastAccessedPath(){return y.lastAccessedPath},set lastAccessedPath(e){y.lastAccessedPath=e;},get stateVersion(){return y.stateVersion},bumpStateVersion(){return y.stateVersion=(y.stateVersion||0)+1,y.stateVersion},get currentContext(){return y.currentContext},set currentContext(e){y.currentContext=e;}},be=["list","state","store","idb","observer","useObserver","remove","removeAll","_platform","_capabilities","_sessionId"],exports.propertyName=(e,t)=>String(t!==void 0?t:e).replace("() => ",""),exports.internal=Ne;});exports.message = void 0;var c,b=g(()=>{a();P();exports.message=(...e)=>{exports.internal.debug===true&&console.debug(...e);},c=exports.message;});function K(){let e=globalThis;if(typeof e.crypto<"u"&&e.crypto.randomUUID)return e.crypto.randomUUID();if(typeof e.crypto<"u"&&e.crypto.getRandomValues){let t=new Uint8Array(16);return e.crypto.getRandomValues(t),Array.from(t,r=>r.toString(16).padStart(2,"0")).join("")}return `session_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function z(){let e=globalThis;return e.Deno&&e.Deno.version?"deno":typeof process<"u"&&process.versions&&process.versions.node?"node":typeof globalThis<"u"&&typeof globalThis.ServiceWorkerGlobalScope<"u"?"edge":typeof window<"u"&&typeof document<"u"?"browser":"unknown"}function Q(){return z()==="browser"}function X(){return z()==="node"}function Z(){return z()==="deno"}function ee(){return z()==="edge"}function te(){try{if(typeof sessionStorage<"u"){let e="__memorio_test__";return sessionStorage.setItem(e,"1"),sessionStorage.removeItem(e),sessionStorage}}catch{}return null}function re(){try{if(typeof localStorage<"u"){let e="__memorio_test__";return localStorage.setItem(e,"1"),localStorage.removeItem(e),localStorage}}catch{}return null}function oe(){return typeof indexedDB<"u"}function Le(){return typeof globalThis.dispatchEvent=="function"}function q(){let e=z(),t=typeof globalThis.isSecureContext<"u"?globalThis.isSecureContext:e==="browser";return {platform:e,hasSessionStorage:te()!==null,hasLocalStorage:re()!==null,hasIndexedDB:oe(),hasDispatchEvent:Le(),hasNavigator:typeof navigator<"u",hasProcess:typeof process<"u",isSecureContext:t,sessionId:K()}}function ve(){let e=q(),t=globalThis;e.hasDispatchEvent||(t.dispatchEvent=function(r){return true},typeof CustomEvent>"u"&&(t.CustomEvent=class{type;detail;constructor(s,o={}){this.type=s,this.detail=o;}})),typeof t.addEventListener!="function"&&(t.addEventListener=function(r,s){L.has(r)||L.set(r,[]),L.get(r).push(s);},t.removeEventListener=function(r,s){let o=L.get(r);if(o){let n=o.indexOf(s);n>-1&&o.splice(n,1);}},t.dispatchEvent=function(r){let s=L.get(r.type);return s&&s.forEach(o=>{try{o(r);}catch(n){console.error("Event listener error:",n);}}),true});}function J(e){let t=e||`context_${K()}`;ae(t);let r={state:{},store:new Map,session:new Map,cache:new Map};return se.set(t,r),{id:t,state:r.state,store:{get:s=>{let o=r.store.get(s);return o?JSON.parse(o):null},set:(s,o)=>{r.store.set(s,JSON.stringify(o));},remove:s=>r.store.delete(s),removeAll:()=>r.store.clear(),clearAll:()=>r.store.clear(),size:()=>r.store.size,isPersistent:false},session:{get:s=>{let o=r.session.get(s);return o?JSON.parse(o):null},set:(s,o)=>{r.session.set(s,JSON.stringify(o));},remove:s=>r.session.delete(s),removeAll:()=>r.session.clear(),clearAll:()=>r.session.clear(),size:()=>r.session.size,isPersistent:false},cache:{get:s=>r.cache.get(s),set:(s,o)=>r.cache.set(s,o),remove:s=>r.cache.delete(s),removeAll:()=>r.cache.clear(),clear:()=>r.cache.clear()}}}function ne(){return Array.from(se.keys())}function ie(e){return se.delete(e)}function ae(e){exports.internal.currentContext=e;}var L,se,B=g(()=>{a();P();L=new Map;se=new Map;});var Fe={};var xe=g(()=>{a();x();b();exports.idb.db.create=(e,t=1)=>new Promise((r,s)=>{if(!exports.idb.db.support())return s(new Error("IndexedDB not supported"));let o=globalThis.indexedDB.open(e,t);o.onerror=()=>{c(`IndexedDB error: ${o.error?.message}`),s(o.error);},o.onsuccess=()=>{c(`Database ${e} connected successfully`),r(o.result);},o.onupgradeneeded=()=>{c(`Database ${e} upgrade/creation initiated`);};});});var We={};var we=g(()=>{a();x();exports.idb.db.list=async()=>{if(!("indexedDB"in globalThis)||!indexedDB.databases)return [];try{let e=await indexedDB.databases();return globalThis.idbases=e||[],await exports.idb.db.size(),globalThis.idbases}catch(e){return console.error("Error listing databases:",e),[]}};});var He={};var Se=g(()=>{a();x();exports.idb.db.exist=e=>idbases?.some(t=>t.name===e);});var Ye={};var Pe=g(()=>{a();x();exports.idb.db.quota=()=>navigator.storage.estimate();});var Ge={};var Te=g(()=>{a();x();b();exports.idb.db.delete=e=>new Promise((t,r)=>{c(`Removing database ${e}...`),(()=>{let o=indexedDB.deleteDatabase(e);o.onsuccess=()=>{c(`${e} database removed successfully`),exports.idb.db.list(),t();},o.onerror=()=>{console.error(`Error removing ${e}:`,o.error),r(o.error);},o.onblocked=()=>{console.warn(`Deletion of ${e} is blocked. Please close other tabs.`);};})();});});var Qe={};var Oe=g(()=>{a();x();b();exports.idb.db.size=async()=>{if(!(!idbases||idbases.length===0))for(let e=0;e<idbases.length;e++){let t=idbases[e];try{let r=await exports.idb.db.create(t.name,t.version),s=Array.from(r.objectStoreNames),o=0;for(let n of s){let i=await exports.idb.table.size(r,n);o+=i;}t.size=o,r.close();}catch(r){c(`Could not calculate size for ${t.name}:${r}`);}}};});var Xe={};var Ee=g(()=>{a();x();exports.idb.db.version=e=>{let t=0;for(let r of idbases){r.name===e&&(t=r.version);break}return t};});var Ze={};var De=g(()=>{a();x();b();exports.idb.db.support=()=>{let e="indexedDB"in globalThis;return e||c("Your environment doesn't support IndexedDB"),e};});var et={};var Ce=g(()=>{a();x();b();exports.idb.table.create=(e,t)=>new Promise((r,s)=>{try{let n=(Number(exports.idb.db.version(e))||0)+1,i=indexedDB.open(e,n);i.onupgradeneeded=m=>{let p=m.target.result;if(!p.objectStoreNames.contains(t)){let f=p.createObjectStore(t,{keyPath:"id",autoIncrement:!0});f.createIndex("id","id",{unique:!0}),f.createIndex("data","data",{unique:!1}),c(`Table ${t} created in ${e}`);}},i.onsuccess=()=>{i.result.close(),exports.idb.db.list(),r();},i.onerror=()=>{console.error(`Error creating table ${t}:`,i.error),s(i.error);};}catch(o){console.error("Critical error in table.create:",o),s(o);}});});var tt={};var je=g(()=>{a();x();b();exports.idb.table.size=(e,t)=>new Promise((r,s)=>{if(!e)return s(new Error("Database instance is required"));if(!e.objectStoreNames.contains(t))return r(0);let o=0,n=0,p=e.transaction([t],"readonly").objectStore(t).openCursor();p.onsuccess=async f=>{let O=f.target.result;if(O){try{let M=O.value;o+=JSON.stringify(M).length;}catch(M){c(`Error stringifying IDB value tracking size:${M}`);}n++,n%200===0&&await new Promise(M=>setTimeout(M,0)),O.continue();}else r(o);},p.onerror=()=>{s(p.error);};});});var rt={};var ke=g(()=>{a();x();b();exports.idb.data.delete=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=()=>{let i=n.result;if(!i.objectStoreNames.contains(t))return i.close(),o(new Error(`Table ${t} not found`));let f=i.transaction(t,"readwrite").objectStore(t).delete(r);f.onsuccess=()=>{i.close(),c(`Record ${r} deleted from ${t}`),s();},f.onerror=()=>{i.close(),o(f.error);};},n.onerror=()=>o(n.error);});exports.idb.data.delete.all=(e,t)=>new Promise((r,s)=>{let o=indexedDB.open(e);o.onsuccess=n=>{let i=n.target.result;if(!i.objectStoreNames.contains(t))return i.close(),s(new Error(`Table ${t} not found`));let f=i.transaction(t,"readwrite").objectStore(t).clear();f.onsuccess=()=>{i.close(),c(`All data cleared from ${t}`),r();},f.onerror=()=>{i.close(),s(f.error);};},o.onerror=()=>s(o.error);});});var ot={};var _e=g(()=>{a();x();b();exports.idb.data.set=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=()=>{let i=n.result;if(!i.objectStoreNames.contains(t))return i.close(),o(new Error(`Table ${t} does not exist in ${e}`));let f=i.transaction(t,"readwrite").objectStore(t).put(r);f.onsuccess=()=>{i.close(),c(`Data saved in ${e}.${t}`),s(f.result);},f.onerror=O=>{i.close(),c(`Database insert error: ${f.error?.message}`),o(f.error);};},n.onerror=()=>{o(n.error);};});});var st={};var $e=g(()=>{a();x();exports.idb.data.get=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=i=>{let m=i.target.result;if(!m.objectStoreNames.contains(t))return m.close(),o(new Error(`Table ${t} not found in ${e}`));let O=m.transaction(t,"readonly").objectStore(t).get(r);O.onsuccess=()=>{m.close(),s(O.result);},O.onerror=()=>{m.close(),o(O.error);};},n.onerror=()=>{o(n.error);};});});var nt;exports.idb = void 0;var x=g(()=>{a();B();nt=oe(),exports.idb={db:{},table:{},data:{}};nt?(async()=>(Object.defineProperty(exports.idb,"db",{value:{},writable:true,configurable:true}),Object.defineProperty(exports.idb,"table",{value:{},writable:true,configurable:true}),Object.defineProperty(exports.idb,"data",{value:{},writable:true,configurable:true}),Object.defineProperty(globalThis,"idbases",{value:[],writable:true,configurable:true,enumerable:false}),await Promise.all([Promise.resolve().then(()=>(xe(),Fe)),Promise.resolve().then(()=>(we(),We)),Promise.resolve().then(()=>(Se(),He)),Promise.resolve().then(()=>(Pe(),Ye)),Promise.resolve().then(()=>(Te(),Ge)),Promise.resolve().then(()=>(Oe(),Qe)),Promise.resolve().then(()=>(Ee(),Xe)),Promise.resolve().then(()=>(De(),Ze)),Promise.resolve().then(()=>(Ce(),et)),Promise.resolve().then(()=>(je(),tt)),Promise.resolve().then(()=>(ke(),rt)),Promise.resolve().then(()=>(_e(),ot)),Promise.resolve().then(()=>($e(),st))]),Object.preventExtensions(exports.idb),Object.seal(exports.idb),Object.freeze(exports.idb)))():(exports.idb._disabled=true,exports.idb._warning="IndexedDB is not available in this environment (Node.js/Deno). Use store or session for persistence.",console.warn("Memorio IDB: IndexedDB is not available in this environment. Use store or session for data persistence."));});a();a();P();b();a();var v={set:(e,t={})=>{globalThis.dispatchEvent(new CustomEvent(String(e),t));},listen:(e,t=null,r)=>{if(globalThis.events?.[e])return;let s=t?o=>{let n=o;return globalThis.queueMicrotask?globalThis.queueMicrotask(()=>t(n)):Promise.resolve().then(()=>t(n))}:void 0;s&&globalThis.addEventListener(e,s),s&&(globalThis.events[e]=s);},remove:e=>{let t=globalThis.events?.[e];t&&(globalThis.removeEventListener(e,t),delete globalThis.events[e]);}};var V=Symbol("memorio.target"),pe=new WeakMap,G=(e,t=null)=>{if(e===null||typeof e!="object")return e;if(e[V]!==void 0)return G(e[V],t);if(t){if(t.has(e))return e;t.add(e);}let r=e.constructor?.name;if(r!=="Object"&&r!=="Array")return e;let s=Array.isArray(e)?[]:{};for(let o of Reflect.ownKeys(e))s[o]=G(e[o],t);return s},ye=(e,t,r=".")=>t.concat(e).join(r),he=(e,t,r=[])=>{let s=o=>{try{v.set(o,{detail:{name:o}});}catch{}};return new Proxy(e,{get(o,n){if(n==="__path")return r.length>0?"state."+r.join("."):"state";if(n===V||o[V]!==void 0)return o;if(n==="list")return c('Some state could be hidden when you use "state.list". Use "state" to see the complete list '),JSON.parse(JSON.stringify(o));if(typeof n=="string"){let i=r.length>0?"state."+r.concat(n).join("."):"state."+n;exports.internal.lastAccessedPath=i,exports.internal.tracking&&exports.internal.trackedPaths.add(i);}if(n==="_lastPath")return exports.internal.lastAccessedPath;if(n==="remove")return i=>(delete o[i],true);if(n==="removeAll")return ()=>{try{for(let i in o)typeof o[i]!="function"&&!["list","remove","removeAll","lock","unlock"].includes(i)&&delete o[i];}catch(i){console.error(i);}};if(Object.isFrozen(o[n]))return o[n];if(n==="lock"||n==="unlock"){let i=Reflect.get(o,n);if(i)return i}try{let i=Reflect.get(o,n);if(i&&typeof i=="object"&&["Array","Object"].includes(i.constructor.name)){let m=pe.get(i);return m||(m=he(i,t,r.concat(n)),pe.set(i,m)),m}return i}catch(i){console.error("Error: ",i);return}},set(o,n,i){if(exports.internal.locked)return console.error("Error: state is locked. Use state.unlock() to enable modifications."),false;if(be.includes(n))return console.error("key "+n+" is protected"),false;if(o[n]&&typeof o[n]=="object"&&Object.isFrozen(o[n]))return console.error(`Error: state '${n}' is locked`),false;if(o[n]&&typeof o[n]=="object"&&o[n].__locked)return console.error(`Error: state '${n}' is locked. Use state.${n}.unlock() to enable modifications.`),false;try{let m=ye(n,r),p=G(i);if(t({action:"set",path:m,target:o,newValue:p,previousValue:Reflect.get(o,n)}),s("state."+m),Reflect.set(o,n,p),exports.internal.bumpStateVersion(),o[n]&&typeof o[n]=="object"){let f=o[n];if(f&&typeof f=="object")try{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!1}),Object.defineProperty(f,"lock",{writable:!1,enumerable:!1,configurable:!1,value:()=>{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!0}),c(`State '${n}' is now locked.`);}}),Object.defineProperty(f,"unlock",{writable:!1,enumerable:!1,configurable:!1,value:()=>{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!1}),c(`State '${n}' is now unlocked.`);}});}catch{}}return !0}catch(m){return console.error("Error in set trap:",m),false}},deleteProperty(o,n){try{let i=ye(n,r);return t({action:"delete",path:i,target:o}),Reflect.deleteProperty(o,n)}catch(i){return console.error("Error in deleteProperty trap:",i),false}},ownKeys(o){return Reflect.ownKeys(o)},getOwnPropertyDescriptor(o,n){return Reflect.getOwnPropertyDescriptor(o,n)}})},N=he({},()=>{});N.lock=()=>{exports.internal.locked=true,c("State is now locked. All modifications are blocked.");};N.unlock=()=>{exports.internal.locked=false,c("State is now unlocked. Modifications are allowed.");};a();B();P();b();var w=re(),le=new Map;function $(){let t=exports.internal.currentContext||""||"default";return le.has(t)||le.set(t,new Map),le.get(t)}var _=w!==null;function k(){let e=exports.internal.currentContext||"";return e?`${e}-`:"memorio_store_"}function ce(e){return !e||typeof e!="string"?(console.warn("[memorio store] key is empty or not a string \u2014 operation aborted"),""):e.length>512?(console.warn(`[memorio store] key "${e}" exceeds 512 chars \u2014 operation aborted`),""):k()+e}function ze(e){let t=_?w.getItem(e):$().get(e);return t&&JSON.parse(t)}function qe(e,t){let r=JSON.stringify(t);_?w.setItem(e,r):$().set(e,r);}function Je(e){if(_){if(w.getItem(e))return w.removeItem(e),true}else if($().has(e))return $().delete(e),true;return false}var D=new Proxy({},{});Object.defineProperty(globalThis,"store",{value:D,enumerable:false,configurable:true});Object.defineProperties(D,{get:{value:e=>{if(!e)return console.warn("[memorio store] store.get() called with empty or null key \u2014 returning null"),null;try{return ze(ce(e))}catch(t){exports.message(`Error parsing store item '${e}': ${t}`);}return null}},getMultiple:{value:e=>{let t={};for(let r of e)try{let s=D.get(r);s&&(t[r]=s);}catch(s){console.debug(`[memorio store] getMultiple error for key "${r}":`,s);}return t}},set:{value:(e,t)=>{if(!e)return console.warn("[memorio store] store.set() called with empty or null key \u2014 write aborted"),false;let r=ce(e);if(!r)return false;if(typeof t=="function")return console.warn("[memorio store] functions are not storable \u2014 write aborted for key: "+e),exports.message("Storing functions is not secure and is blocked for safety."),false;try{qe(r,t);}catch(s){return exports.message(`Error setting store item '${e}': ${s}`),false}return true}},remove:{value:e=>{if(!e)return console.debug("[memorio store] store.remove() called with empty or null key \u2014 returning false"),false;let t=ce(e);if(!t)return false;try{return Je(t)}catch(r){exports.message(`Error removing store item '${e}': ${r}`);}return false}},delete:{value:e=>D.remove(e)},removeAll:{value:()=>{if(_){let e=[];for(let t=0;t<w.length;t++){let r=w.key(t);r?.startsWith(k())&&e.push(r);}e.forEach(t=>w.removeItem(t));}else $().clear();return true}},clearAll:{value:()=>(D.removeAll(),true)},quota:{value:async()=>[0,0]},size:{value:()=>{let e=0;return _?Object.keys(w).forEach(t=>{if(t.startsWith(k())){let r=w.getItem(t);r&&(e+=r.length);}}):$().forEach(t=>{e+=t.length;}),e}},isPersistent:{get:()=>_},list:{value:()=>{let e={};try{if(_)for(let t=0;t<w.length;t++){let r=w.key(t);if(r?.startsWith(k())){let s=r.replace(k(),""),o=w.getItem(r);if(o!==null)try{e[s]=JSON.parse(o);}catch{e[s]=o;}}}else $().forEach((t,r)=>{if(r.startsWith(k())){let s=r.replace(k(),"");try{e[s]=JSON.parse(t);}catch{e[s]=t;}}});}catch(t){exports.message(`Error listing store items: ${t}`);}return e}}});Object.freeze(D);a();B();P();b();var S=te(),ue=new Map;function R(){let t=exports.internal.currentContext||""||"default";return ue.has(t)||ue.set(t,new Map),ue.get(t)}var A=S!==null;function I(){let e=exports.internal.currentContext||"";return e?`${e}-`:"memorio_session_"}function fe(e){return !e||typeof e!="string"?(console.warn("[memorio session] key is empty or not a string \u2014 operation aborted"),""):e.length>512?(console.warn(`[memorio session] key "${e}" exceeds 512 chars \u2014 operation aborted`),""):I()+e}function Ue(e){let t=A?S.getItem(e):R().get(e);return t&&JSON.parse(t)}function Ve(e,t){let r=JSON.stringify(t);A?S.setItem(e,r):R().set(e,r);}function Ke(e){if(A){if(S.getItem(e))return S.removeItem(e),true}else if(R().has(e))return R().delete(e),true;return false}var C=new Proxy({},{});Object.defineProperty(globalThis,"session",{value:C,enumerable:false,configurable:true});Object.defineProperties(C,{get:{value:e=>{if(!e)return console.warn("[memorio session] session.get() called with empty or null key \u2014 returning null"),null;try{return Ue(fe(e))}catch(t){exports.message(`Error parsing session item '${e}':${t}`);}return null}},set:{value:(e,t)=>{if(!e)return console.warn("[memorio session] session.set() called with empty or null key \u2014 write aborted"),false;let r=fe(e);if(!r)return false;if(typeof t=="function")return console.warn("[memorio session] functions are not storable \u2014 write aborted for key: "+e),exports.message("It's not secure to session functions."),false;try{Ve(r,t);}catch(s){return exports.message(`Error setting session item '${e}': ${s}`),false}return true}},remove:{value:e=>{if(!e)return console.warn("[memorio session] session.remove() called with empty or null key \u2014 returning false"),false;let t=fe(e);if(!t)return false;try{return Ke(t)}catch(r){exports.message(`Error removing session item '${e}': ${r}`);}return false}},delete:{value:e=>C.remove(e)},removeAll:{value:()=>{if(A){let e=[];for(let t=0;t<S.length;t++){let r=S.key(t);r?.startsWith(I())&&e.push(r);}e.forEach(t=>S.removeItem(t));}else R().clear();return true}},clearAll:{value:()=>(C.removeAll(),true)},quota:{value:async()=>[0,0]},size:{value:()=>{let e=0;return A?Object.keys(S).forEach(t=>{if(t.startsWith(I())){let r=S.getItem(t);r&&(e+=r.length);}}):R().forEach(t=>{e+=t.length;}),e}},isPersistent:{get:()=>A},list:{value:()=>{let e={};try{if(A)for(let t=0;t<S.length;t++){let r=S.key(t);if(r?.startsWith(I())){let s=r.replace(I(),""),o=S.getItem(r);if(o!==null)try{e[s]=JSON.parse(o);}catch{e[s]=o;}}}else R().forEach((t,r)=>{if(r.startsWith(I())){let s=r.replace(I(),"");try{e[s]=JSON.parse(t);}catch{e[s]=t;}}});}catch(t){exports.message(`Error listing session items: ${t}`);}return e}}});Object.freeze(C);a();var T={},F=new Proxy({},{get(e,t){let r=t;return r==="get"?s=>T[s]:r==="set"?(s,o)=>{T[s]=o;}:r==="remove"?s=>(delete T[s],true):r==="removeAll"?()=>(Object.keys(T).forEach(s=>delete T[s]),true):r==="clear"?()=>(Object.keys(T).forEach(s=>delete T[s]),true):r==="list"?()=>({...T}):T[r]},set(e,t,r){return T[t]=r,true},deleteProperty(e,t){return delete T[t],true}});Object.freeze(F);x();a();b();var Ie=false,it=(e,t=null,r=true)=>{Ie||(console.warn('DEPRECATED: "observer" is deprecated and will be removed in future versions. Please use "useObserver" instead.'),Ie=true);let s=n=>typeof n=="string"?n:n&&typeof n=="object"&&n.__path?n.__path:null,o=s(e);if(!e&&!t){console.error("Observer Error: You need to setup observer correctly, Some parameters are missed!");return}if(!e&&t){console.error("Observer Error: You need to declare what state need to be monitored as string like 'state.test'.");return}if(o){let n=o.split(".");if(n[0]!=="state"&&n[0]!=="store"){console.error(`Observer Error: You need to declare 'state.' or 'store.'. The '${o}' string is incorrect!`);return}}if(e&&!t){let n=s(e);if(!n)return;globalThis.observer?.list?.[n]&&v.remove(n),c(`called: ${n}`);return}if(e&&t){let n=s(e);if(!n)return;if(typeof e!="string"&&!(e&&typeof e=="object")){console.error("Observer Error: name of state need to be a 'string' like 'state.test' or a direct state value");return}let i=Array.isArray(t)?t:[t];globalThis.observer?.list?.[n]&&v.remove(n),i.forEach(p=>{typeof p=="function"&&v.listen(n,p,r);});return}},W=it;Object.defineProperties(W,{list:{get:()=>globalThis.events},remove:{value:e=>{e&&(v.remove(e),delete globalThis.events[e]);}},removeAll:{get:()=>{let e=globalThis.observer,t=e?.list;return t&&Object.keys(t).forEach(r=>{e?.remove?.(r);}),true}},has:{value:e=>!!globalThis.observer?.list?.[e]}});a();b();P();globalThis.useObserver||(globalThis.useObserver=null);Object.defineProperty(globalThis,"useObserver",{value:null,writable:true,enumerable:false,configurable:true});var H=((e,t=[])=>{if(!t||typeof e!="function")return ()=>{};let r=[],s=Array.isArray(t)&&!t.__path?t:[t];try{return s.forEach(o=>{let n="";if(typeof o=="function"){let i=exports.propertyName(o);i&&(n=i);}else typeof o=="object"&&o!==null&&(n=o.__path||(typeof o.toString=="function"&&o.toString()!=="[object Object]"?o.toString():""));if(n){n=n.replace(/^(\(\)\s*=>\s*)/,"").replace(/^globalThis\./,"").replace(/^state\./,"");let i=n.startsWith("store.")||n.startsWith("state.")?n:"state."+n;v.listen(i,()=>e()),r.push(i);}else {exports.internal.clearTrackedPaths(),exports.internal.tracking=!0;try{e();}catch{}exports.internal.tracking=!1,exports.internal.trackedPaths.forEach(i=>{r.includes(i)||(c(`useObserver: [Auto-Discovery] -> "${i}"`),v.listen(i,()=>e()),r.push(i));});}}),r.length>0?c(`useObserver: Monitoring ${r.length} paths.`):console.warn("useObserver: No paths resolved for monitoring. Check your dependencies!"),()=>{r.forEach(o=>{typeof v.remove=="function"&&(v.remove(o),c(`useObserver: Stopped monitoring "${o}"`));});}}catch(o){return c(`useObserver Error: ${o}`),()=>{}}});globalThis.useObserver=H;Object.freeze(globalThis.useObserver);b();a();P();function at(){return exports.internal.debug===true}function Ae(){if(!globalThis.store)return {};let e={},t=globalThis.store;if(typeof t.list=="function")try{return t.list()}catch{}if(typeof t.get=="function"){for(let r of Object.keys(t))if(!["get","set","remove","delete","removeAll","clearAll","size","isPersistent","list"].includes(r))try{let s=t.get(r);s!=null&&(e[r]=s);}catch{}}return e}function Re(){if(!globalThis.session)return {};let e={},t=globalThis.session;if(typeof t.list=="function")try{return t.list()}catch{}if(typeof t.get=="function"){for(let r of Object.keys(t))if(!["get","set","remove","delete","removeAll","clearAll","size","isPersistent","list"].includes(r))try{let s=t.get(r);s!=null&&(e[r]=s);}catch{}}return e}var lt=()=>{if(at()){if(globalThis.state){let e=globalThis.state.list,t;typeof e=="function"?t=e():typeof e=="object"&&e!==null?t=e:t=globalThis.state,console.table(t);}if(globalThis.store&&console.table(Ae()),globalThis.session&&console.table(Re()),globalThis.cache){let e=globalThis.cache.list,t;typeof e=="function"?t=e():typeof e=="object"&&e!==null?t=e:t=globalThis.cache,console.table(t);}}},ct=()=>{let e=t=>{if(!t)return 0;if(typeof t.list=="function")try{let r=t.list();return Object.keys(r).length}catch{}return Object.keys(t).length};return {stateKeys:e(globalThis.state),storeKeys:e(globalThis.store),sessionKeys:e(globalThis.session),cacheKeys:e(globalThis.cache),idbDatabases:0,lastUpdate:new Date().toISOString()}},U=e=>{globalThis[e]&&typeof globalThis[e].clear=="function"?globalThis[e].clear():console.error(`Module ${e} not found or does not support clear()`);},ut=()=>{U("state"),U("store"),U("session"),U("cache");},ft=()=>{let e=()=>{if(globalThis.state)try{return typeof globalThis.state.list=="function"?globalThis.state.list():globalThis.state}catch{return}},t=()=>Ae(),r=()=>Re(),s=()=>{if(globalThis.cache)try{return typeof globalThis.cache.list=="function"?globalThis.cache.list():globalThis.cache}catch{return}},o={state:e(),store:t(),session:r(),cache:s(),exportedAt:new Date().toISOString()};return JSON.stringify(o,null,2)},dt=e=>{try{let t=JSON.parse(e);t.state&&Object.entries(t.state).forEach(([r,s])=>{globalThis.state&&r!=="list"&&r!=="remove"&&r!=="removeAll"&&(globalThis.state[r]=s);}),t.store&&globalThis.store&&typeof globalThis.store.set=="function"&&Object.entries(t.store).forEach(([r,s])=>{globalThis.store.set(r,s);}),t.session&&globalThis.session&&typeof globalThis.session.set=="function"&&Object.entries(t.session).forEach(([r,s])=>{globalThis.session.set(r,s);}),t.cache&&globalThis.cache&&Object.entries(t.cache).forEach(([r,s])=>{globalThis.cache&&r!=="get"&&r!=="set"&&r!=="remove"&&r!=="clear"&&(globalThis.cache[r]=s);});}catch(t){console.error("%c\u2717 Import failed:","color: #F44336",t);}},mt=(e,t)=>{if(!globalThis[e]){console.error(`Module ${e} not found`);return}let r=globalThis[e],s=r[t];if(console.debug(`\u{1F441} Watching ${e}.${t} (initial: ${JSON.stringify(s)})`),e==="state"&&globalThis.memorio?.dispatch){let o=n=>{n.detail?.name?.includes(t)&&console.debug(`\u{1F441} Change: ${e}.${t} =`,n.detail.value);};r.addEventListener?.("memorio-change",o);}},gt=()=>{console.debug(`
|
|
2
6
|
\u{1F9E0} Memorio DevTools Help
|
|
3
7
|
|
|
4
8
|
Available commands:
|
|
@@ -18,7 +22,7 @@ Shortcuts:
|
|
|
18
22
|
cache - globalThis.cache
|
|
19
23
|
`);},de={inspect:lt,stats:ct,clear:U,clearAll:ut,exportData:ft,importData:dt,watch:mt,help:gt};a();P();b();var bt={enabled:true,logToConsole:true,modules:["state","store","session","cache","idb"],maxEntries:1e3};function pt(){return exports.internal.debug===true}var E={...bt},j=[],yt=e=>{E={...E,...e};},ht=()=>{E.enabled=true;},vt=()=>{E.enabled=false;},Be=e=>E.enabled&&E.modules.includes(e),xt=(e,t,r,s,o)=>{if(!Be(e))return;let n={timestamp:new Date().toISOString(),module:e,action:t,path:r,value:s,previousValue:o};if(j.push(n),j.length>E.maxEntries&&j.shift(),E.logToConsole&&pt()){let i=`[Memorio:${e.toUpperCase()}]`,m=wt(e);c(`%c${i}%c ${t} ${r},
|
|
20
24
|
color: ${m}; font-weight: bold,
|
|
21
|
-
color: inherit`),s!==void 0&&c(` \u2192 value:${s}`),o!==void 0&&c(` \u2190 previous:${o}`);}E.customHandler&&E.customHandler(n);},wt=e=>({state:"#4CAF50",store:"#2196F3",session:"#FF9800",cache:"#9C27B0",idb:"#F44336"})[e]||"#888888",St=()=>[...j],Pt=()=>{j.length=0;},Tt=()=>{let e={total:j.length,state:0,store:0,session:0,cache:0,idb:0,set:0,get:0,delete:0,clear:0};for(let t of j)if(t){let r=t.module,s=t.action;r&&typeof e[r]=="number"&&e[r]++,s&&typeof e[s]=="number"&&e[s]++;}return e},Ot=()=>JSON.stringify(j,null,2),me={configure:yt,enable:ht,disable:vt,isEnabled:Be,log:xt,getHistory:St,clearHistory:Pt,getStats:Tt,exportLogs:Ot};P();B();a();B();P();var ge={version:"4.7.
|
|
25
|
+
color: inherit`),s!==void 0&&c(` \u2192 value:${s}`),o!==void 0&&c(` \u2190 previous:${o}`);}E.customHandler&&E.customHandler(n);},wt=e=>({state:"#4CAF50",store:"#2196F3",session:"#FF9800",cache:"#9C27B0",idb:"#F44336"})[e]||"#888888",St=()=>[...j],Pt=()=>{j.length=0;},Tt=()=>{let e={total:j.length,state:0,store:0,session:0,cache:0,idb:0,set:0,get:0,delete:0,clear:0};for(let t of j)if(t){let r=t.module,s=t.action;r&&typeof e[r]=="number"&&e[r]++,s&&typeof e[s]=="number"&&e[s]++;}return e},Ot=()=>JSON.stringify(j,null,2),me={configure:yt,enable:ht,disable:vt,isEnabled:Be,log:xt,getHistory:St,clearHistory:Pt,getStats:Tt,exportLogs:Ot};P();B();a();B();P();var ge={version:"4.7.1"};x();b();Object.defineProperty(globalThis,"memorio",{value:{setProps:()=>{},obj:{},array:[],dispatch:v,message:exports.message,devtools:de,logger:me,setDescription:()=>{}},writable:false,configurable:true,enumerable:false});Object.defineProperty(globalThis,"events",{value:{},writable:true,enumerable:false});Object.defineProperty(memorio,"version",{writable:false,enumerable:false,value:ge.version});Object.defineProperty(memorio,"debug",{get:()=>exports.internal.debug,set:e=>{exports.internal.debug=e;},enumerable:false});var Me=q();Object.defineProperty(memorio,"_platform",{writable:false,enumerable:false,value:Me.platform});Object.defineProperty(memorio,"_capabilities",{writable:false,enumerable:false,value:Me});Object.defineProperty(memorio,"_sessionId",{writable:false,enumerable:false,value:K()});ve();memorio.isBrowser=Q;memorio.isNode=X;memorio.isDeno=Z;memorio.isEdge=ee;memorio.getCapabilities=q;memorio.createContext=J;memorio.listContexts=ne;memorio.deleteContext=ie;memorio.isolate=e=>J(e);Object.defineProperty(globalThis,"state",{value:N,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"store",{value:D,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"session",{value:C,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"cache",{value:F,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"idb",{value:exports.idb,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"observer",{value:W,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"useObserver",{value:H,writable:true,enumerable:false,configurable:true});Object.defineProperty(memorio,"dispatch",{value:v,writable:true,enumerable:false,configurable:true});Object.defineProperty(memorio,"setContext",{writable:false,enumerable:false,value:e=>ae(e)});Object.defineProperty(memorio,"getContext",{writable:false,enumerable:false,value:()=>exports.internal.currentContext});Object.defineProperty(globalThis,"$state",{get:()=>globalThis.state,configurable:true});Object.defineProperty(globalThis,"$store",{get:()=>globalThis.store,configurable:true});Object.defineProperty(globalThis,"$session",{get:()=>globalThis.session,configurable:true});Object.defineProperty(globalThis,"$cache",{get:()=>globalThis.cache,configurable:true});memorio.help=function(){console.debug(`
|
|
22
26
|
\u{1F9E0} Memorio ${ge.version} - Help
|
|
23
27
|
|
|
24
28
|
Core Modules:
|
|
@@ -51,4 +55,29 @@ DevTools:
|
|
|
51
55
|
|
|
52
56
|
Shortcuts:
|
|
53
57
|
state, store, session, cache, idb - direct access to modules
|
|
54
|
-
`);};var Dt=globalThis.memorio,Ao=globalThis.events,Ro=e=>J(e),Bo=globalThis.memorio?.help,Mo=e=>exports.internal.currentContext=e,No=()=>exports.internal.currentContext,Lo=Dt;
|
|
58
|
+
`);};var Dt=globalThis.memorio,Ao=globalThis.events,Ro=e=>J(e),Bo=globalThis.memorio?.help,Mo=e=>exports.internal.currentContext=e,No=()=>exports.internal.currentContext,Lo=Dt;
|
|
59
|
+
|
|
60
|
+
exports.cache = F;
|
|
61
|
+
exports.createContext = J;
|
|
62
|
+
exports.default = Lo;
|
|
63
|
+
exports.deleteContext = ie;
|
|
64
|
+
exports.devtools = de;
|
|
65
|
+
exports.dispatch = v;
|
|
66
|
+
exports.events = Ao;
|
|
67
|
+
exports.getCapabilities = q;
|
|
68
|
+
exports.getContext = No;
|
|
69
|
+
exports.help = Bo;
|
|
70
|
+
exports.isBrowser = Q;
|
|
71
|
+
exports.isDeno = Z;
|
|
72
|
+
exports.isEdge = ee;
|
|
73
|
+
exports.isNode = X;
|
|
74
|
+
exports.isolate = Ro;
|
|
75
|
+
exports.listContexts = ne;
|
|
76
|
+
exports.logger = me;
|
|
77
|
+
exports.memorio = Dt;
|
|
78
|
+
exports.observer = W;
|
|
79
|
+
exports.session = C;
|
|
80
|
+
exports.setContext = Mo;
|
|
81
|
+
exports.state = N;
|
|
82
|
+
exports.store = D;
|
|
83
|
+
exports.useObserver = H;
|
package/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import'path';import'url';var b=(e,t)=>()=>(e&&(t=e(e=0)),t);var a=b(()=>{});var h,Le,pe,G,u,T=b(()=>{a();h={debug:false,tracking:false,trackedPaths:new Set,locked:false,lastAccessedPath:"",stateVersion:0,currentContext:null},Le={get debug(){return h.debug},set debug(e){h.debug=e;},get tracking(){return h.tracking},set tracking(e){h.tracking=e;},get trackedPaths(){return h.trackedPaths},clearTrackedPaths(){h.trackedPaths.clear();},get locked(){return h.locked},set locked(e){h.locked=e;},get lastAccessedPath(){return h.lastAccessedPath},set lastAccessedPath(e){h.lastAccessedPath=e;},get stateVersion(){return h.stateVersion},bumpStateVersion(){return h.stateVersion=(h.stateVersion||0)+1,h.stateVersion},get currentContext(){return h.currentContext},set currentContext(e){h.currentContext=e;}},pe=["list","state","store","idb","observer","useObserver","remove","removeAll","_platform","_capabilities","_sessionId"],G=(e,t)=>String(t!==void 0?t:e).replace("() => ",""),u=Le;});var v,c,p=b(()=>{a();T();v=(...e)=>{u.debug===true&&console.debug(...e);},c=v;});function U(){let e=globalThis;if(typeof e.crypto<"u"&&e.crypto.randomUUID)return e.crypto.randomUUID();if(typeof e.crypto<"u"&&e.crypto.getRandomValues){let t=new Uint8Array(16);return e.crypto.getRandomValues(t),Array.from(t,r=>r.toString(16).padStart(2,"0")).join("")}return `session_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function q(){let e=globalThis;return e.Deno&&e.Deno.version?"deno":typeof process<"u"&&process.versions&&process.versions.node?"node":typeof globalThis<"u"&&typeof globalThis.ServiceWorkerGlobalScope<"u"?"edge":typeof window<"u"&&typeof document<"u"?"browser":"unknown"}function X(){return q()==="browser"}function Z(){return q()==="node"}function ee(){return q()==="deno"}function te(){return q()==="edge"}function re(){try{if(typeof sessionStorage<"u"){let e="__memorio_test__";return sessionStorage.setItem(e,"1"),sessionStorage.removeItem(e),sessionStorage}}catch{}return null}function oe(){try{if(typeof localStorage<"u"){let e="__memorio_test__";return localStorage.setItem(e,"1"),localStorage.removeItem(e),localStorage}}catch{}return null}function se(){return typeof indexedDB<"u"}function ze(){return typeof globalThis.dispatchEvent=="function"}function J(){let e=q(),t=typeof globalThis.isSecureContext<"u"?globalThis.isSecureContext:e==="browser";return {platform:e,hasSessionStorage:re()!==null,hasLocalStorage:oe()!==null,hasIndexedDB:se(),hasDispatchEvent:ze(),hasNavigator:typeof navigator<"u",hasProcess:typeof process<"u",isSecureContext:t,sessionId:U()}}function xe(){let e=J(),t=globalThis;e.hasDispatchEvent||(t.dispatchEvent=function(r){return true},typeof CustomEvent>"u"&&(t.CustomEvent=class{type;detail;constructor(s,o={}){this.type=s,this.detail=o;}})),typeof t.addEventListener!="function"&&(t.addEventListener=function(r,s){z.has(r)||z.set(r,[]),z.get(r).push(s);},t.removeEventListener=function(r,s){let o=z.get(r);if(o){let n=o.indexOf(s);n>-1&&o.splice(n,1);}},t.dispatchEvent=function(r){let s=z.get(r.type);return s&&s.forEach(o=>{try{o(r);}catch(n){console.error("Event listener error:",n);}}),true});}function V(e){let t=e||`context_${U()}`;le(t);let r={state:{},store:new Map,session:new Map,cache:new Map};return ne.set(t,r),{id:t,state:r.state,store:{get:s=>{let o=r.store.get(s);return o?JSON.parse(o):null},set:(s,o)=>{r.store.set(s,JSON.stringify(o));},remove:s=>r.store.delete(s),removeAll:()=>r.store.clear(),clearAll:()=>r.store.clear(),size:()=>r.store.size,isPersistent:false},session:{get:s=>{let o=r.session.get(s);return o?JSON.parse(o):null},set:(s,o)=>{r.session.set(s,JSON.stringify(o));},remove:s=>r.session.delete(s),removeAll:()=>r.session.clear(),clearAll:()=>r.session.clear(),size:()=>r.session.size,isPersistent:false},cache:{get:s=>r.cache.get(s),set:(s,o)=>r.cache.set(s,o),remove:s=>r.cache.delete(s),removeAll:()=>r.cache.clear(),clear:()=>r.cache.clear()}}}function ie(){return Array.from(ne.keys())}function ae(e){return ne.delete(e)}function le(e){u.currentContext=e;}var z,ne,M=b(()=>{a();T();z=new Map;ne=new Map;});var We={};var we=b(()=>{a();w();p();l.db.create=(e,t=1)=>new Promise((r,s)=>{if(!l.db.support())return s(new Error("IndexedDB not supported"));let o=globalThis.indexedDB.open(e,t);o.onerror=()=>{c(`IndexedDB error: ${o.error?.message}`),s(o.error);},o.onsuccess=()=>{c(`Database ${e} connected successfully`),r(o.result);},o.onupgradeneeded=()=>{c(`Database ${e} upgrade/creation initiated`);};});});var He={};var Se=b(()=>{a();w();l.db.list=async()=>{if(!("indexedDB"in globalThis)||!indexedDB.databases)return [];try{let e=await indexedDB.databases();return globalThis.idbases=e||[],await l.db.size(),globalThis.idbases}catch(e){return console.error("Error listing databases:",e),[]}};});var Ye={};var Pe=b(()=>{a();w();l.db.exist=e=>idbases?.some(t=>t.name===e);});var Ge={};var Te=b(()=>{a();w();l.db.quota=()=>navigator.storage.estimate();});var Qe={};var Oe=b(()=>{a();w();p();l.db.delete=e=>new Promise((t,r)=>{c(`Removing database ${e}...`),(()=>{let o=indexedDB.deleteDatabase(e);o.onsuccess=()=>{c(`${e} database removed successfully`),l.db.list(),t();},o.onerror=()=>{console.error(`Error removing ${e}:`,o.error),r(o.error);},o.onblocked=()=>{console.warn(`Deletion of ${e} is blocked. Please close other tabs.`);};})();});});var Xe={};var Ee=b(()=>{a();w();p();l.db.size=async()=>{if(!(!idbases||idbases.length===0))for(let e=0;e<idbases.length;e++){let t=idbases[e];try{let r=await l.db.create(t.name,t.version),s=Array.from(r.objectStoreNames),o=0;for(let n of s){let i=await l.table.size(r,n);o+=i;}t.size=o,r.close();}catch(r){c(`Could not calculate size for ${t.name}:${r}`);}}};});var Ze={};var De=b(()=>{a();w();l.db.version=e=>{let t=0;for(let r of idbases){r.name===e&&(t=r.version);break}return t};});var et={};var je=b(()=>{a();w();p();l.db.support=()=>{let e="indexedDB"in globalThis;return e||c("Your environment doesn't support IndexedDB"),e};});var tt={};var Ce=b(()=>{a();w();p();l.table.create=(e,t)=>new Promise((r,s)=>{try{let n=(Number(l.db.version(e))||0)+1,i=indexedDB.open(e,n);i.onupgradeneeded=g=>{let y=g.target.result;if(!y.objectStoreNames.contains(t)){let f=y.createObjectStore(t,{keyPath:"id",autoIncrement:!0});f.createIndex("id","id",{unique:!0}),f.createIndex("data","data",{unique:!1}),c(`Table ${t} created in ${e}`);}},i.onsuccess=()=>{i.result.close(),l.db.list(),r();},i.onerror=()=>{console.error(`Error creating table ${t}:`,i.error),s(i.error);};}catch(o){console.error("Critical error in table.create:",o),s(o);}});});var rt={};var ke=b(()=>{a();w();p();l.table.size=(e,t)=>new Promise((r,s)=>{if(!e)return s(new Error("Database instance is required"));if(!e.objectStoreNames.contains(t))return r(0);let o=0,n=0,y=e.transaction([t],"readonly").objectStore(t).openCursor();y.onsuccess=async f=>{let E=f.target.result;if(E){try{let N=E.value;o+=JSON.stringify(N).length;}catch(N){c(`Error stringifying IDB value tracking size:${N}`);}n++,n%200===0&&await new Promise(N=>setTimeout(N,0)),E.continue();}else r(o);},y.onerror=()=>{s(y.error);};});});var ot={};var _e=b(()=>{a();w();p();l.data.delete=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=()=>{let i=n.result;if(!i.objectStoreNames.contains(t))return i.close(),o(new Error(`Table ${t} not found`));let f=i.transaction(t,"readwrite").objectStore(t).delete(r);f.onsuccess=()=>{i.close(),c(`Record ${r} deleted from ${t}`),s();},f.onerror=()=>{i.close(),o(f.error);};},n.onerror=()=>o(n.error);});l.data.delete.all=(e,t)=>new Promise((r,s)=>{let o=indexedDB.open(e);o.onsuccess=n=>{let i=n.target.result;if(!i.objectStoreNames.contains(t))return i.close(),s(new Error(`Table ${t} not found`));let f=i.transaction(t,"readwrite").objectStore(t).clear();f.onsuccess=()=>{i.close(),c(`All data cleared from ${t}`),r();},f.onerror=()=>{i.close(),s(f.error);};},o.onerror=()=>s(o.error);});});var st={};var $e=b(()=>{a();w();p();l.data.set=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=()=>{let i=n.result;if(!i.objectStoreNames.contains(t))return i.close(),o(new Error(`Table ${t} does not exist in ${e}`));let f=i.transaction(t,"readwrite").objectStore(t).put(r);f.onsuccess=()=>{i.close(),c(`Data saved in ${e}.${t}`),s(f.result);},f.onerror=E=>{i.close(),c(`Database insert error: ${f.error?.message}`),o(f.error);};},n.onerror=()=>{o(n.error);};});});var nt={};var Ie=b(()=>{a();w();l.data.get=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=i=>{let g=i.target.result;if(!g.objectStoreNames.contains(t))return g.close(),o(new Error(`Table ${t} not found in ${e}`));let E=g.transaction(t,"readonly").objectStore(t).get(r);E.onsuccess=()=>{g.close(),s(E.result);},E.onerror=()=>{g.close(),o(E.error);};},n.onerror=()=>{o(n.error);};});});var it,l,w=b(()=>{a();M();it=se(),l={db:{},table:{},data:{}};it?(async()=>(Object.defineProperty(l,"db",{value:{},writable:true,configurable:true}),Object.defineProperty(l,"table",{value:{},writable:true,configurable:true}),Object.defineProperty(l,"data",{value:{},writable:true,configurable:true}),Object.defineProperty(globalThis,"idbases",{value:[],writable:true,configurable:true,enumerable:false}),await Promise.all([Promise.resolve().then(()=>(we(),We)),Promise.resolve().then(()=>(Se(),He)),Promise.resolve().then(()=>(Pe(),Ye)),Promise.resolve().then(()=>(Te(),Ge)),Promise.resolve().then(()=>(Oe(),Qe)),Promise.resolve().then(()=>(Ee(),Xe)),Promise.resolve().then(()=>(De(),Ze)),Promise.resolve().then(()=>(je(),et)),Promise.resolve().then(()=>(Ce(),tt)),Promise.resolve().then(()=>(ke(),rt)),Promise.resolve().then(()=>(_e(),ot)),Promise.resolve().then(()=>($e(),st)),Promise.resolve().then(()=>(Ie(),nt))]),Object.preventExtensions(l),Object.seal(l),Object.freeze(l)))():(l._disabled=true,l._warning="IndexedDB is not available in this environment (Node.js/Deno). Use store or session for persistence.",console.warn("Memorio IDB: IndexedDB is not available in this environment. Use store or session for data persistence."));});a();a();T();p();a();var x={set:(e,t={})=>{globalThis.dispatchEvent(new CustomEvent(String(e),t));},listen:(e,t=null,r)=>{if(globalThis.events?.[e])return;let s=t?o=>{let n=o;return globalThis.queueMicrotask?globalThis.queueMicrotask(()=>t(n)):Promise.resolve().then(()=>t(n))}:void 0;s&&globalThis.addEventListener(e,s),s&&(globalThis.events[e]=s);},remove:e=>{let t=globalThis.events?.[e];t&&(globalThis.removeEventListener(e,t),delete globalThis.events[e]);}};var F=Symbol("memorio.target"),ye=new WeakMap,Q=(e,t=null)=>{if(e===null||typeof e!="object")return e;if(e[F]!==void 0)return Q(e[F],t);if(t){if(t.has(e))return e;t.add(e);}let r=e.constructor?.name;if(r!=="Object"&&r!=="Array")return e;let s=Array.isArray(e)?[]:{};for(let o of Reflect.ownKeys(e))s[o]=Q(e[o],t);return s},he=(e,t,r=".")=>t.concat(e).join(r),ve=(e,t,r=[])=>{let s=o=>{try{x.set(o,{detail:{name:o}});}catch{}};return new Proxy(e,{get(o,n){if(n==="__path")return r.length>0?"state."+r.join("."):"state";if(n===F||o[F]!==void 0)return o;if(n==="list")return c('Some state could be hidden when you use "state.list". Use "state" to see the complete list '),JSON.parse(JSON.stringify(o));if(typeof n=="string"){let i=r.length>0?"state."+r.concat(n).join("."):"state."+n;u.lastAccessedPath=i,u.tracking&&u.trackedPaths.add(i);}if(n==="_lastPath")return u.lastAccessedPath;if(n==="remove")return i=>(delete o[i],true);if(n==="removeAll")return ()=>{try{for(let i in o)typeof o[i]!="function"&&!["list","remove","removeAll","lock","unlock"].includes(i)&&delete o[i];}catch(i){console.error(i);}};if(Object.isFrozen(o[n]))return o[n];if(n==="lock"||n==="unlock"){let i=Reflect.get(o,n);if(i)return i}try{let i=Reflect.get(o,n);if(i&&typeof i=="object"&&["Array","Object"].includes(i.constructor.name)){let g=ye.get(i);return g||(g=ve(i,t,r.concat(n)),ye.set(i,g)),g}return i}catch(i){console.error("Error: ",i);return}},set(o,n,i){if(u.locked)return console.error("Error: state is locked. Use state.unlock() to enable modifications."),false;if(pe.includes(n))return console.error("key "+n+" is protected"),false;if(o[n]&&typeof o[n]=="object"&&Object.isFrozen(o[n]))return console.error(`Error: state '${n}' is locked`),false;if(o[n]&&typeof o[n]=="object"&&o[n].__locked)return console.error(`Error: state '${n}' is locked. Use state.${n}.unlock() to enable modifications.`),false;try{let g=he(n,r),y=Q(i);if(t({action:"set",path:g,target:o,newValue:y,previousValue:Reflect.get(o,n)}),s("state."+g),Reflect.set(o,n,y),u.bumpStateVersion(),o[n]&&typeof o[n]=="object"){let f=o[n];if(f&&typeof f=="object")try{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!1}),Object.defineProperty(f,"lock",{writable:!1,enumerable:!1,configurable:!1,value:()=>{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!0}),c(`State '${n}' is now locked.`);}}),Object.defineProperty(f,"unlock",{writable:!1,enumerable:!1,configurable:!1,value:()=>{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!1}),c(`State '${n}' is now unlocked.`);}});}catch{}}return !0}catch(g){return console.error("Error in set trap:",g),false}},deleteProperty(o,n){try{let i=he(n,r);return t({action:"delete",path:i,target:o}),Reflect.deleteProperty(o,n)}catch(i){return console.error("Error in deleteProperty trap:",i),false}},ownKeys(o){return Reflect.ownKeys(o)},getOwnPropertyDescriptor(o,n){return Reflect.getOwnPropertyDescriptor(o,n)}})},L=ve({},()=>{});L.lock=()=>{u.locked=true,c("State is now locked. All modifications are blocked.");};L.unlock=()=>{u.locked=false,c("State is now unlocked. Modifications are allowed.");};a();M();T();p();var S=oe(),ce=new Map;function I(){let t=u.currentContext||""||"default";return ce.has(t)||ce.set(t,new Map),ce.get(t)}var $=S!==null;function _(){let e=u.currentContext||"";return e?`${e}-`:"memorio_store_"}function ue(e){return !e||typeof e!="string"?(console.warn("[memorio store] key is empty or not a string \u2014 operation aborted"),""):e.length>512?(console.warn(`[memorio store] key "${e}" exceeds 512 chars \u2014 operation aborted`),""):_()+e}function qe(e){let t=$?S.getItem(e):I().get(e);return t&&JSON.parse(t)}function Je(e,t){let r=JSON.stringify(t);$?S.setItem(e,r):I().set(e,r);}function Ve(e){if($){if(S.getItem(e))return S.removeItem(e),true}else if(I().has(e))return I().delete(e),true;return false}var j=new Proxy({},{});Object.defineProperty(globalThis,"store",{value:j,enumerable:false,configurable:true});Object.defineProperties(j,{get:{value:e=>{if(!e)return console.warn("[memorio store] store.get() called with empty or null key \u2014 returning null"),null;try{return qe(ue(e))}catch(t){v(`Error parsing store item '${e}': ${t}`);}return null}},getMultiple:{value:e=>{let t={};for(let r of e)try{let s=j.get(r);s&&(t[r]=s);}catch(s){console.debug(`[memorio store] getMultiple error for key "${r}":`,s);}return t}},set:{value:(e,t)=>{if(!e)return console.warn("[memorio store] store.set() called with empty or null key \u2014 write aborted"),false;let r=ue(e);if(!r)return false;if(typeof t=="function")return console.warn("[memorio store] functions are not storable \u2014 write aborted for key: "+e),v("Storing functions is not secure and is blocked for safety."),false;try{Je(r,t);}catch(s){return v(`Error setting store item '${e}': ${s}`),false}return true}},remove:{value:e=>{if(!e)return console.debug("[memorio store] store.remove() called with empty or null key \u2014 returning false"),false;let t=ue(e);if(!t)return false;try{return Ve(t)}catch(r){v(`Error removing store item '${e}': ${r}`);}return false}},delete:{value:e=>j.remove(e)},removeAll:{value:()=>{if($){let e=[];for(let t=0;t<S.length;t++){let r=S.key(t);r?.startsWith(_())&&e.push(r);}e.forEach(t=>S.removeItem(t));}else I().clear();return true}},clearAll:{value:()=>(j.removeAll(),true)},quota:{value:async()=>[0,0]},size:{value:()=>{let e=0;return $?Object.keys(S).forEach(t=>{if(t.startsWith(_())){let r=S.getItem(t);r&&(e+=r.length);}}):I().forEach(t=>{e+=t.length;}),e}},isPersistent:{get:()=>$},list:{value:()=>{let e={};try{if($)for(let t=0;t<S.length;t++){let r=S.key(t);if(r?.startsWith(_())){let s=r.replace(_(),""),o=S.getItem(r);if(o!==null)try{e[s]=JSON.parse(o);}catch{e[s]=o;}}}else I().forEach((t,r)=>{if(r.startsWith(_())){let s=r.replace(_(),"");try{e[s]=JSON.parse(t);}catch{e[s]=t;}}});}catch(t){v(`Error listing store items: ${t}`);}return e}}});Object.freeze(j);a();M();T();p();var P=re(),fe=new Map;function R(){let t=u.currentContext||""||"default";return fe.has(t)||fe.set(t,new Map),fe.get(t)}var B=P!==null;function A(){let e=u.currentContext||"";return e?`${e}-`:"memorio_session_"}function me(e){return !e||typeof e!="string"?(console.warn("[memorio session] key is empty or not a string \u2014 operation aborted"),""):e.length>512?(console.warn(`[memorio session] key "${e}" exceeds 512 chars \u2014 operation aborted`),""):A()+e}function Ke(e){let t=B?P.getItem(e):R().get(e);return t&&JSON.parse(t)}function Fe(e,t){let r=JSON.stringify(t);B?P.setItem(e,r):R().set(e,r);}function Ue(e){if(B){if(P.getItem(e))return P.removeItem(e),true}else if(R().has(e))return R().delete(e),true;return false}var C=new Proxy({},{});Object.defineProperty(globalThis,"session",{value:C,enumerable:false,configurable:true});Object.defineProperties(C,{get:{value:e=>{if(!e)return console.warn("[memorio session] session.get() called with empty or null key \u2014 returning null"),null;try{return Ke(me(e))}catch(t){v(`Error parsing session item '${e}':${t}`);}return null}},set:{value:(e,t)=>{if(!e)return console.warn("[memorio session] session.set() called with empty or null key \u2014 write aborted"),false;let r=me(e);if(!r)return false;if(typeof t=="function")return console.warn("[memorio session] functions are not storable \u2014 write aborted for key: "+e),v("It's not secure to session functions."),false;try{Fe(r,t);}catch(s){return v(`Error setting session item '${e}': ${s}`),false}return true}},remove:{value:e=>{if(!e)return console.warn("[memorio session] session.remove() called with empty or null key \u2014 returning false"),false;let t=me(e);if(!t)return false;try{return Ue(t)}catch(r){v(`Error removing session item '${e}': ${r}`);}return false}},delete:{value:e=>C.remove(e)},removeAll:{value:()=>{if(B){let e=[];for(let t=0;t<P.length;t++){let r=P.key(t);r?.startsWith(A())&&e.push(r);}e.forEach(t=>P.removeItem(t));}else R().clear();return true}},clearAll:{value:()=>(C.removeAll(),true)},quota:{value:async()=>[0,0]},size:{value:()=>{let e=0;return B?Object.keys(P).forEach(t=>{if(t.startsWith(A())){let r=P.getItem(t);r&&(e+=r.length);}}):R().forEach(t=>{e+=t.length;}),e}},isPersistent:{get:()=>B},list:{value:()=>{let e={};try{if(B)for(let t=0;t<P.length;t++){let r=P.key(t);if(r?.startsWith(A())){let s=r.replace(A(),""),o=P.getItem(r);if(o!==null)try{e[s]=JSON.parse(o);}catch{e[s]=o;}}}else R().forEach((t,r)=>{if(r.startsWith(A())){let s=r.replace(A(),"");try{e[s]=JSON.parse(t);}catch{e[s]=t;}}});}catch(t){v(`Error listing session items: ${t}`);}return e}}});Object.freeze(C);a();var O={},W=new Proxy({},{get(e,t){let r=t;return r==="get"?s=>O[s]:r==="set"?(s,o)=>{O[s]=o;}:r==="remove"?s=>(delete O[s],true):r==="removeAll"?()=>(Object.keys(O).forEach(s=>delete O[s]),true):r==="clear"?()=>(Object.keys(O).forEach(s=>delete O[s]),true):r==="list"?()=>({...O}):O[r]},set(e,t,r){return O[t]=r,true},deleteProperty(e,t){return delete O[t],true}});Object.freeze(W);w();a();p();var Ae=false,at=(e,t=null,r=true)=>{Ae||(console.warn('DEPRECATED: "observer" is deprecated and will be removed in future versions. Please use "useObserver" instead.'),Ae=true);let s=n=>typeof n=="string"?n:n&&typeof n=="object"&&n.__path?n.__path:null,o=s(e);if(!e&&!t){console.error("Observer Error: You need to setup observer correctly, Some parameters are missed!");return}if(!e&&t){console.error("Observer Error: You need to declare what state need to be monitored as string like 'state.test'.");return}if(o){let n=o.split(".");if(n[0]!=="state"&&n[0]!=="store"){console.error(`Observer Error: You need to declare 'state.' or 'store.'. The '${o}' string is incorrect!`);return}}if(e&&!t){let n=s(e);if(!n)return;globalThis.observer?.list?.[n]&&x.remove(n),c(`called: ${n}`);return}if(e&&t){let n=s(e);if(!n)return;if(typeof e!="string"&&!(e&&typeof e=="object")){console.error("Observer Error: name of state need to be a 'string' like 'state.test' or a direct state value");return}let i=Array.isArray(t)?t:[t];globalThis.observer?.list?.[n]&&x.remove(n),i.forEach(y=>{typeof y=="function"&&x.listen(n,y,r);});return}},H=at;Object.defineProperties(H,{list:{get:()=>globalThis.events},remove:{value:e=>{e&&(x.remove(e),delete globalThis.events[e]);}},removeAll:{get:()=>{let e=globalThis.observer,t=e?.list;return t&&Object.keys(t).forEach(r=>{e?.remove?.(r);}),true}},has:{value:e=>!!globalThis.observer?.list?.[e]}});a();p();T();globalThis.useObserver||(globalThis.useObserver=null);Object.defineProperty(globalThis,"useObserver",{value:null,writable:true,enumerable:false,configurable:true});var Y=((e,t=[])=>{if(!t||typeof e!="function")return ()=>{};let r=[],s=Array.isArray(t)&&!t.__path?t:[t];try{return s.forEach(o=>{let n="";if(typeof o=="function"){let i=G(o);i&&(n=i);}else typeof o=="object"&&o!==null&&(n=o.__path||(typeof o.toString=="function"&&o.toString()!=="[object Object]"?o.toString():""));if(n){n=n.replace(/^(\(\)\s*=>\s*)/,"").replace(/^globalThis\./,"").replace(/^state\./,"");let i=n.startsWith("store.")||n.startsWith("state.")?n:"state."+n;x.listen(i,()=>e()),r.push(i);}else {u.clearTrackedPaths(),u.tracking=!0;try{e();}catch{}u.tracking=!1,u.trackedPaths.forEach(i=>{r.includes(i)||(c(`useObserver: [Auto-Discovery] -> "${i}"`),x.listen(i,()=>e()),r.push(i));});}}),r.length>0?c(`useObserver: Monitoring ${r.length} paths.`):console.warn("useObserver: No paths resolved for monitoring. Check your dependencies!"),()=>{r.forEach(o=>{typeof x.remove=="function"&&(x.remove(o),c(`useObserver: Stopped monitoring "${o}"`));});}}catch(o){return c(`useObserver Error: ${o}`),()=>{}}});globalThis.useObserver=Y;Object.freeze(globalThis.useObserver);p();a();T();function lt(){return u.debug===true}function Be(){if(!globalThis.store)return {};let e={},t=globalThis.store;if(typeof t.list=="function")try{return t.list()}catch{}if(typeof t.get=="function"){for(let r of Object.keys(t))if(!["get","set","remove","delete","removeAll","clearAll","size","isPersistent","list"].includes(r))try{let s=t.get(r);s!=null&&(e[r]=s);}catch{}}return e}function Re(){if(!globalThis.session)return {};let e={},t=globalThis.session;if(typeof t.list=="function")try{return t.list()}catch{}if(typeof t.get=="function"){for(let r of Object.keys(t))if(!["get","set","remove","delete","removeAll","clearAll","size","isPersistent","list"].includes(r))try{let s=t.get(r);s!=null&&(e[r]=s);}catch{}}return e}var ct=()=>{if(lt()){if(globalThis.state){let e=globalThis.state.list,t;typeof e=="function"?t=e():typeof e=="object"&&e!==null?t=e:t=globalThis.state,console.table(t);}if(globalThis.store&&console.table(Be()),globalThis.session&&console.table(Re()),globalThis.cache){let e=globalThis.cache.list,t;typeof e=="function"?t=e():typeof e=="object"&&e!==null?t=e:t=globalThis.cache,console.table(t);}}},ut=()=>{let e=t=>{if(!t)return 0;if(typeof t.list=="function")try{let r=t.list();return Object.keys(r).length}catch{}return Object.keys(t).length};return {stateKeys:e(globalThis.state),storeKeys:e(globalThis.store),sessionKeys:e(globalThis.session),cacheKeys:e(globalThis.cache),idbDatabases:0,lastUpdate:new Date().toISOString()}},K=e=>{globalThis[e]&&typeof globalThis[e].clear=="function"?globalThis[e].clear():console.error(`Module ${e} not found or does not support clear()`);},ft=()=>{K("state"),K("store"),K("session"),K("cache");},mt=()=>{let e=()=>{if(globalThis.state)try{return typeof globalThis.state.list=="function"?globalThis.state.list():globalThis.state}catch{return}},t=()=>Be(),r=()=>Re(),s=()=>{if(globalThis.cache)try{return typeof globalThis.cache.list=="function"?globalThis.cache.list():globalThis.cache}catch{return}},o={state:e(),store:t(),session:r(),cache:s(),exportedAt:new Date().toISOString()};return JSON.stringify(o,null,2)},dt=e=>{try{let t=JSON.parse(e);t.state&&Object.entries(t.state).forEach(([r,s])=>{globalThis.state&&r!=="list"&&r!=="remove"&&r!=="removeAll"&&(globalThis.state[r]=s);}),t.store&&globalThis.store&&typeof globalThis.store.set=="function"&&Object.entries(t.store).forEach(([r,s])=>{globalThis.store.set(r,s);}),t.session&&globalThis.session&&typeof globalThis.session.set=="function"&&Object.entries(t.session).forEach(([r,s])=>{globalThis.session.set(r,s);}),t.cache&&globalThis.cache&&Object.entries(t.cache).forEach(([r,s])=>{globalThis.cache&&r!=="get"&&r!=="set"&&r!=="remove"&&r!=="clear"&&(globalThis.cache[r]=s);});}catch(t){console.error("%c\u2717 Import failed:","color: #F44336",t);}},gt=(e,t)=>{if(!globalThis[e]){console.error(`Module ${e} not found`);return}let r=globalThis[e],s=r[t];if(console.debug(`\u{1F441} Watching ${e}.${t} (initial: ${JSON.stringify(s)})`),e==="state"&&globalThis.memorio?.dispatch){let o=n=>{n.detail?.name?.includes(t)&&console.debug(`\u{1F441} Change: ${e}.${t} =`,n.detail.value);};r.addEventListener?.("memorio-change",o);}},bt=()=>{console.debug(`
|
|
1
|
+
import 'path';
|
|
2
|
+
import 'url';
|
|
3
|
+
|
|
4
|
+
var b=(e,t)=>()=>(e&&(t=e(e=0)),t);var a=b(()=>{});var h,Le,pe,G,u,T=b(()=>{a();h={debug:false,tracking:false,trackedPaths:new Set,locked:false,lastAccessedPath:"",stateVersion:0,currentContext:null},Le={get debug(){return h.debug},set debug(e){h.debug=e;},get tracking(){return h.tracking},set tracking(e){h.tracking=e;},get trackedPaths(){return h.trackedPaths},clearTrackedPaths(){h.trackedPaths.clear();},get locked(){return h.locked},set locked(e){h.locked=e;},get lastAccessedPath(){return h.lastAccessedPath},set lastAccessedPath(e){h.lastAccessedPath=e;},get stateVersion(){return h.stateVersion},bumpStateVersion(){return h.stateVersion=(h.stateVersion||0)+1,h.stateVersion},get currentContext(){return h.currentContext},set currentContext(e){h.currentContext=e;}},pe=["list","state","store","idb","observer","useObserver","remove","removeAll","_platform","_capabilities","_sessionId"],G=(e,t)=>String(t!==void 0?t:e).replace("() => ",""),u=Le;});var v,c,p=b(()=>{a();T();v=(...e)=>{u.debug===true&&console.debug(...e);},c=v;});function U(){let e=globalThis;if(typeof e.crypto<"u"&&e.crypto.randomUUID)return e.crypto.randomUUID();if(typeof e.crypto<"u"&&e.crypto.getRandomValues){let t=new Uint8Array(16);return e.crypto.getRandomValues(t),Array.from(t,r=>r.toString(16).padStart(2,"0")).join("")}return `session_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function q(){let e=globalThis;return e.Deno&&e.Deno.version?"deno":typeof process<"u"&&process.versions&&process.versions.node?"node":typeof globalThis<"u"&&typeof globalThis.ServiceWorkerGlobalScope<"u"?"edge":typeof window<"u"&&typeof document<"u"?"browser":"unknown"}function X(){return q()==="browser"}function Z(){return q()==="node"}function ee(){return q()==="deno"}function te(){return q()==="edge"}function re(){try{if(typeof sessionStorage<"u"){let e="__memorio_test__";return sessionStorage.setItem(e,"1"),sessionStorage.removeItem(e),sessionStorage}}catch{}return null}function oe(){try{if(typeof localStorage<"u"){let e="__memorio_test__";return localStorage.setItem(e,"1"),localStorage.removeItem(e),localStorage}}catch{}return null}function se(){return typeof indexedDB<"u"}function ze(){return typeof globalThis.dispatchEvent=="function"}function J(){let e=q(),t=typeof globalThis.isSecureContext<"u"?globalThis.isSecureContext:e==="browser";return {platform:e,hasSessionStorage:re()!==null,hasLocalStorage:oe()!==null,hasIndexedDB:se(),hasDispatchEvent:ze(),hasNavigator:typeof navigator<"u",hasProcess:typeof process<"u",isSecureContext:t,sessionId:U()}}function xe(){let e=J(),t=globalThis;e.hasDispatchEvent||(t.dispatchEvent=function(r){return true},typeof CustomEvent>"u"&&(t.CustomEvent=class{type;detail;constructor(s,o={}){this.type=s,this.detail=o;}})),typeof t.addEventListener!="function"&&(t.addEventListener=function(r,s){z.has(r)||z.set(r,[]),z.get(r).push(s);},t.removeEventListener=function(r,s){let o=z.get(r);if(o){let n=o.indexOf(s);n>-1&&o.splice(n,1);}},t.dispatchEvent=function(r){let s=z.get(r.type);return s&&s.forEach(o=>{try{o(r);}catch(n){console.error("Event listener error:",n);}}),true});}function V(e){let t=e||`context_${U()}`;le(t);let r={state:{},store:new Map,session:new Map,cache:new Map};return ne.set(t,r),{id:t,state:r.state,store:{get:s=>{let o=r.store.get(s);return o?JSON.parse(o):null},set:(s,o)=>{r.store.set(s,JSON.stringify(o));},remove:s=>r.store.delete(s),removeAll:()=>r.store.clear(),clearAll:()=>r.store.clear(),size:()=>r.store.size,isPersistent:false},session:{get:s=>{let o=r.session.get(s);return o?JSON.parse(o):null},set:(s,o)=>{r.session.set(s,JSON.stringify(o));},remove:s=>r.session.delete(s),removeAll:()=>r.session.clear(),clearAll:()=>r.session.clear(),size:()=>r.session.size,isPersistent:false},cache:{get:s=>r.cache.get(s),set:(s,o)=>r.cache.set(s,o),remove:s=>r.cache.delete(s),removeAll:()=>r.cache.clear(),clear:()=>r.cache.clear()}}}function ie(){return Array.from(ne.keys())}function ae(e){return ne.delete(e)}function le(e){u.currentContext=e;}var z,ne,M=b(()=>{a();T();z=new Map;ne=new Map;});var We={};var we=b(()=>{a();w();p();l.db.create=(e,t=1)=>new Promise((r,s)=>{if(!l.db.support())return s(new Error("IndexedDB not supported"));let o=globalThis.indexedDB.open(e,t);o.onerror=()=>{c(`IndexedDB error: ${o.error?.message}`),s(o.error);},o.onsuccess=()=>{c(`Database ${e} connected successfully`),r(o.result);},o.onupgradeneeded=()=>{c(`Database ${e} upgrade/creation initiated`);};});});var He={};var Se=b(()=>{a();w();l.db.list=async()=>{if(!("indexedDB"in globalThis)||!indexedDB.databases)return [];try{let e=await indexedDB.databases();return globalThis.idbases=e||[],await l.db.size(),globalThis.idbases}catch(e){return console.error("Error listing databases:",e),[]}};});var Ye={};var Pe=b(()=>{a();w();l.db.exist=e=>idbases?.some(t=>t.name===e);});var Ge={};var Te=b(()=>{a();w();l.db.quota=()=>navigator.storage.estimate();});var Qe={};var Oe=b(()=>{a();w();p();l.db.delete=e=>new Promise((t,r)=>{c(`Removing database ${e}...`),(()=>{let o=indexedDB.deleteDatabase(e);o.onsuccess=()=>{c(`${e} database removed successfully`),l.db.list(),t();},o.onerror=()=>{console.error(`Error removing ${e}:`,o.error),r(o.error);},o.onblocked=()=>{console.warn(`Deletion of ${e} is blocked. Please close other tabs.`);};})();});});var Xe={};var Ee=b(()=>{a();w();p();l.db.size=async()=>{if(!(!idbases||idbases.length===0))for(let e=0;e<idbases.length;e++){let t=idbases[e];try{let r=await l.db.create(t.name,t.version),s=Array.from(r.objectStoreNames),o=0;for(let n of s){let i=await l.table.size(r,n);o+=i;}t.size=o,r.close();}catch(r){c(`Could not calculate size for ${t.name}:${r}`);}}};});var Ze={};var De=b(()=>{a();w();l.db.version=e=>{let t=0;for(let r of idbases){r.name===e&&(t=r.version);break}return t};});var et={};var je=b(()=>{a();w();p();l.db.support=()=>{let e="indexedDB"in globalThis;return e||c("Your environment doesn't support IndexedDB"),e};});var tt={};var Ce=b(()=>{a();w();p();l.table.create=(e,t)=>new Promise((r,s)=>{try{let n=(Number(l.db.version(e))||0)+1,i=indexedDB.open(e,n);i.onupgradeneeded=g=>{let y=g.target.result;if(!y.objectStoreNames.contains(t)){let f=y.createObjectStore(t,{keyPath:"id",autoIncrement:!0});f.createIndex("id","id",{unique:!0}),f.createIndex("data","data",{unique:!1}),c(`Table ${t} created in ${e}`);}},i.onsuccess=()=>{i.result.close(),l.db.list(),r();},i.onerror=()=>{console.error(`Error creating table ${t}:`,i.error),s(i.error);};}catch(o){console.error("Critical error in table.create:",o),s(o);}});});var rt={};var ke=b(()=>{a();w();p();l.table.size=(e,t)=>new Promise((r,s)=>{if(!e)return s(new Error("Database instance is required"));if(!e.objectStoreNames.contains(t))return r(0);let o=0,n=0,y=e.transaction([t],"readonly").objectStore(t).openCursor();y.onsuccess=async f=>{let E=f.target.result;if(E){try{let N=E.value;o+=JSON.stringify(N).length;}catch(N){c(`Error stringifying IDB value tracking size:${N}`);}n++,n%200===0&&await new Promise(N=>setTimeout(N,0)),E.continue();}else r(o);},y.onerror=()=>{s(y.error);};});});var ot={};var _e=b(()=>{a();w();p();l.data.delete=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=()=>{let i=n.result;if(!i.objectStoreNames.contains(t))return i.close(),o(new Error(`Table ${t} not found`));let f=i.transaction(t,"readwrite").objectStore(t).delete(r);f.onsuccess=()=>{i.close(),c(`Record ${r} deleted from ${t}`),s();},f.onerror=()=>{i.close(),o(f.error);};},n.onerror=()=>o(n.error);});l.data.delete.all=(e,t)=>new Promise((r,s)=>{let o=indexedDB.open(e);o.onsuccess=n=>{let i=n.target.result;if(!i.objectStoreNames.contains(t))return i.close(),s(new Error(`Table ${t} not found`));let f=i.transaction(t,"readwrite").objectStore(t).clear();f.onsuccess=()=>{i.close(),c(`All data cleared from ${t}`),r();},f.onerror=()=>{i.close(),s(f.error);};},o.onerror=()=>s(o.error);});});var st={};var $e=b(()=>{a();w();p();l.data.set=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=()=>{let i=n.result;if(!i.objectStoreNames.contains(t))return i.close(),o(new Error(`Table ${t} does not exist in ${e}`));let f=i.transaction(t,"readwrite").objectStore(t).put(r);f.onsuccess=()=>{i.close(),c(`Data saved in ${e}.${t}`),s(f.result);},f.onerror=E=>{i.close(),c(`Database insert error: ${f.error?.message}`),o(f.error);};},n.onerror=()=>{o(n.error);};});});var nt={};var Ie=b(()=>{a();w();l.data.get=(e,t,r)=>new Promise((s,o)=>{let n=indexedDB.open(e);n.onsuccess=i=>{let g=i.target.result;if(!g.objectStoreNames.contains(t))return g.close(),o(new Error(`Table ${t} not found in ${e}`));let E=g.transaction(t,"readonly").objectStore(t).get(r);E.onsuccess=()=>{g.close(),s(E.result);},E.onerror=()=>{g.close(),o(E.error);};},n.onerror=()=>{o(n.error);};});});var it,l,w=b(()=>{a();M();it=se(),l={db:{},table:{},data:{}};it?(async()=>(Object.defineProperty(l,"db",{value:{},writable:true,configurable:true}),Object.defineProperty(l,"table",{value:{},writable:true,configurable:true}),Object.defineProperty(l,"data",{value:{},writable:true,configurable:true}),Object.defineProperty(globalThis,"idbases",{value:[],writable:true,configurable:true,enumerable:false}),await Promise.all([Promise.resolve().then(()=>(we(),We)),Promise.resolve().then(()=>(Se(),He)),Promise.resolve().then(()=>(Pe(),Ye)),Promise.resolve().then(()=>(Te(),Ge)),Promise.resolve().then(()=>(Oe(),Qe)),Promise.resolve().then(()=>(Ee(),Xe)),Promise.resolve().then(()=>(De(),Ze)),Promise.resolve().then(()=>(je(),et)),Promise.resolve().then(()=>(Ce(),tt)),Promise.resolve().then(()=>(ke(),rt)),Promise.resolve().then(()=>(_e(),ot)),Promise.resolve().then(()=>($e(),st)),Promise.resolve().then(()=>(Ie(),nt))]),Object.preventExtensions(l),Object.seal(l),Object.freeze(l)))():(l._disabled=true,l._warning="IndexedDB is not available in this environment (Node.js/Deno). Use store or session for persistence.",console.warn("Memorio IDB: IndexedDB is not available in this environment. Use store or session for data persistence."));});a();a();T();p();a();var x={set:(e,t={})=>{globalThis.dispatchEvent(new CustomEvent(String(e),t));},listen:(e,t=null,r)=>{if(globalThis.events?.[e])return;let s=t?o=>{let n=o;return globalThis.queueMicrotask?globalThis.queueMicrotask(()=>t(n)):Promise.resolve().then(()=>t(n))}:void 0;s&&globalThis.addEventListener(e,s),s&&(globalThis.events[e]=s);},remove:e=>{let t=globalThis.events?.[e];t&&(globalThis.removeEventListener(e,t),delete globalThis.events[e]);}};var F=Symbol("memorio.target"),ye=new WeakMap,Q=(e,t=null)=>{if(e===null||typeof e!="object")return e;if(e[F]!==void 0)return Q(e[F],t);if(t){if(t.has(e))return e;t.add(e);}let r=e.constructor?.name;if(r!=="Object"&&r!=="Array")return e;let s=Array.isArray(e)?[]:{};for(let o of Reflect.ownKeys(e))s[o]=Q(e[o],t);return s},he=(e,t,r=".")=>t.concat(e).join(r),ve=(e,t,r=[])=>{let s=o=>{try{x.set(o,{detail:{name:o}});}catch{}};return new Proxy(e,{get(o,n){if(n==="__path")return r.length>0?"state."+r.join("."):"state";if(n===F||o[F]!==void 0)return o;if(n==="list")return c('Some state could be hidden when you use "state.list". Use "state" to see the complete list '),JSON.parse(JSON.stringify(o));if(typeof n=="string"){let i=r.length>0?"state."+r.concat(n).join("."):"state."+n;u.lastAccessedPath=i,u.tracking&&u.trackedPaths.add(i);}if(n==="_lastPath")return u.lastAccessedPath;if(n==="remove")return i=>(delete o[i],true);if(n==="removeAll")return ()=>{try{for(let i in o)typeof o[i]!="function"&&!["list","remove","removeAll","lock","unlock"].includes(i)&&delete o[i];}catch(i){console.error(i);}};if(Object.isFrozen(o[n]))return o[n];if(n==="lock"||n==="unlock"){let i=Reflect.get(o,n);if(i)return i}try{let i=Reflect.get(o,n);if(i&&typeof i=="object"&&["Array","Object"].includes(i.constructor.name)){let g=ye.get(i);return g||(g=ve(i,t,r.concat(n)),ye.set(i,g)),g}return i}catch(i){console.error("Error: ",i);return}},set(o,n,i){if(u.locked)return console.error("Error: state is locked. Use state.unlock() to enable modifications."),false;if(pe.includes(n))return console.error("key "+n+" is protected"),false;if(o[n]&&typeof o[n]=="object"&&Object.isFrozen(o[n]))return console.error(`Error: state '${n}' is locked`),false;if(o[n]&&typeof o[n]=="object"&&o[n].__locked)return console.error(`Error: state '${n}' is locked. Use state.${n}.unlock() to enable modifications.`),false;try{let g=he(n,r),y=Q(i);if(t({action:"set",path:g,target:o,newValue:y,previousValue:Reflect.get(o,n)}),s("state."+g),Reflect.set(o,n,y),u.bumpStateVersion(),o[n]&&typeof o[n]=="object"){let f=o[n];if(f&&typeof f=="object")try{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!1}),Object.defineProperty(f,"lock",{writable:!1,enumerable:!1,configurable:!1,value:()=>{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!0}),c(`State '${n}' is now locked.`);}}),Object.defineProperty(f,"unlock",{writable:!1,enumerable:!1,configurable:!1,value:()=>{Object.defineProperty(f,"__locked",{writable:!0,enumerable:!1,configurable:!1,value:!1}),c(`State '${n}' is now unlocked.`);}});}catch{}}return !0}catch(g){return console.error("Error in set trap:",g),false}},deleteProperty(o,n){try{let i=he(n,r);return t({action:"delete",path:i,target:o}),Reflect.deleteProperty(o,n)}catch(i){return console.error("Error in deleteProperty trap:",i),false}},ownKeys(o){return Reflect.ownKeys(o)},getOwnPropertyDescriptor(o,n){return Reflect.getOwnPropertyDescriptor(o,n)}})},L=ve({},()=>{});L.lock=()=>{u.locked=true,c("State is now locked. All modifications are blocked.");};L.unlock=()=>{u.locked=false,c("State is now unlocked. Modifications are allowed.");};a();M();T();p();var S=oe(),ce=new Map;function I(){let t=u.currentContext||""||"default";return ce.has(t)||ce.set(t,new Map),ce.get(t)}var $=S!==null;function _(){let e=u.currentContext||"";return e?`${e}-`:"memorio_store_"}function ue(e){return !e||typeof e!="string"?(console.warn("[memorio store] key is empty or not a string \u2014 operation aborted"),""):e.length>512?(console.warn(`[memorio store] key "${e}" exceeds 512 chars \u2014 operation aborted`),""):_()+e}function qe(e){let t=$?S.getItem(e):I().get(e);return t&&JSON.parse(t)}function Je(e,t){let r=JSON.stringify(t);$?S.setItem(e,r):I().set(e,r);}function Ve(e){if($){if(S.getItem(e))return S.removeItem(e),true}else if(I().has(e))return I().delete(e),true;return false}var j=new Proxy({},{});Object.defineProperty(globalThis,"store",{value:j,enumerable:false,configurable:true});Object.defineProperties(j,{get:{value:e=>{if(!e)return console.warn("[memorio store] store.get() called with empty or null key \u2014 returning null"),null;try{return qe(ue(e))}catch(t){v(`Error parsing store item '${e}': ${t}`);}return null}},getMultiple:{value:e=>{let t={};for(let r of e)try{let s=j.get(r);s&&(t[r]=s);}catch(s){console.debug(`[memorio store] getMultiple error for key "${r}":`,s);}return t}},set:{value:(e,t)=>{if(!e)return console.warn("[memorio store] store.set() called with empty or null key \u2014 write aborted"),false;let r=ue(e);if(!r)return false;if(typeof t=="function")return console.warn("[memorio store] functions are not storable \u2014 write aborted for key: "+e),v("Storing functions is not secure and is blocked for safety."),false;try{Je(r,t);}catch(s){return v(`Error setting store item '${e}': ${s}`),false}return true}},remove:{value:e=>{if(!e)return console.debug("[memorio store] store.remove() called with empty or null key \u2014 returning false"),false;let t=ue(e);if(!t)return false;try{return Ve(t)}catch(r){v(`Error removing store item '${e}': ${r}`);}return false}},delete:{value:e=>j.remove(e)},removeAll:{value:()=>{if($){let e=[];for(let t=0;t<S.length;t++){let r=S.key(t);r?.startsWith(_())&&e.push(r);}e.forEach(t=>S.removeItem(t));}else I().clear();return true}},clearAll:{value:()=>(j.removeAll(),true)},quota:{value:async()=>[0,0]},size:{value:()=>{let e=0;return $?Object.keys(S).forEach(t=>{if(t.startsWith(_())){let r=S.getItem(t);r&&(e+=r.length);}}):I().forEach(t=>{e+=t.length;}),e}},isPersistent:{get:()=>$},list:{value:()=>{let e={};try{if($)for(let t=0;t<S.length;t++){let r=S.key(t);if(r?.startsWith(_())){let s=r.replace(_(),""),o=S.getItem(r);if(o!==null)try{e[s]=JSON.parse(o);}catch{e[s]=o;}}}else I().forEach((t,r)=>{if(r.startsWith(_())){let s=r.replace(_(),"");try{e[s]=JSON.parse(t);}catch{e[s]=t;}}});}catch(t){v(`Error listing store items: ${t}`);}return e}}});Object.freeze(j);a();M();T();p();var P=re(),fe=new Map;function R(){let t=u.currentContext||""||"default";return fe.has(t)||fe.set(t,new Map),fe.get(t)}var B=P!==null;function A(){let e=u.currentContext||"";return e?`${e}-`:"memorio_session_"}function me(e){return !e||typeof e!="string"?(console.warn("[memorio session] key is empty or not a string \u2014 operation aborted"),""):e.length>512?(console.warn(`[memorio session] key "${e}" exceeds 512 chars \u2014 operation aborted`),""):A()+e}function Ke(e){let t=B?P.getItem(e):R().get(e);return t&&JSON.parse(t)}function Fe(e,t){let r=JSON.stringify(t);B?P.setItem(e,r):R().set(e,r);}function Ue(e){if(B){if(P.getItem(e))return P.removeItem(e),true}else if(R().has(e))return R().delete(e),true;return false}var C=new Proxy({},{});Object.defineProperty(globalThis,"session",{value:C,enumerable:false,configurable:true});Object.defineProperties(C,{get:{value:e=>{if(!e)return console.warn("[memorio session] session.get() called with empty or null key \u2014 returning null"),null;try{return Ke(me(e))}catch(t){v(`Error parsing session item '${e}':${t}`);}return null}},set:{value:(e,t)=>{if(!e)return console.warn("[memorio session] session.set() called with empty or null key \u2014 write aborted"),false;let r=me(e);if(!r)return false;if(typeof t=="function")return console.warn("[memorio session] functions are not storable \u2014 write aborted for key: "+e),v("It's not secure to session functions."),false;try{Fe(r,t);}catch(s){return v(`Error setting session item '${e}': ${s}`),false}return true}},remove:{value:e=>{if(!e)return console.warn("[memorio session] session.remove() called with empty or null key \u2014 returning false"),false;let t=me(e);if(!t)return false;try{return Ue(t)}catch(r){v(`Error removing session item '${e}': ${r}`);}return false}},delete:{value:e=>C.remove(e)},removeAll:{value:()=>{if(B){let e=[];for(let t=0;t<P.length;t++){let r=P.key(t);r?.startsWith(A())&&e.push(r);}e.forEach(t=>P.removeItem(t));}else R().clear();return true}},clearAll:{value:()=>(C.removeAll(),true)},quota:{value:async()=>[0,0]},size:{value:()=>{let e=0;return B?Object.keys(P).forEach(t=>{if(t.startsWith(A())){let r=P.getItem(t);r&&(e+=r.length);}}):R().forEach(t=>{e+=t.length;}),e}},isPersistent:{get:()=>B},list:{value:()=>{let e={};try{if(B)for(let t=0;t<P.length;t++){let r=P.key(t);if(r?.startsWith(A())){let s=r.replace(A(),""),o=P.getItem(r);if(o!==null)try{e[s]=JSON.parse(o);}catch{e[s]=o;}}}else R().forEach((t,r)=>{if(r.startsWith(A())){let s=r.replace(A(),"");try{e[s]=JSON.parse(t);}catch{e[s]=t;}}});}catch(t){v(`Error listing session items: ${t}`);}return e}}});Object.freeze(C);a();var O={},W=new Proxy({},{get(e,t){let r=t;return r==="get"?s=>O[s]:r==="set"?(s,o)=>{O[s]=o;}:r==="remove"?s=>(delete O[s],true):r==="removeAll"?()=>(Object.keys(O).forEach(s=>delete O[s]),true):r==="clear"?()=>(Object.keys(O).forEach(s=>delete O[s]),true):r==="list"?()=>({...O}):O[r]},set(e,t,r){return O[t]=r,true},deleteProperty(e,t){return delete O[t],true}});Object.freeze(W);w();a();p();var Ae=false,at=(e,t=null,r=true)=>{Ae||(console.warn('DEPRECATED: "observer" is deprecated and will be removed in future versions. Please use "useObserver" instead.'),Ae=true);let s=n=>typeof n=="string"?n:n&&typeof n=="object"&&n.__path?n.__path:null,o=s(e);if(!e&&!t){console.error("Observer Error: You need to setup observer correctly, Some parameters are missed!");return}if(!e&&t){console.error("Observer Error: You need to declare what state need to be monitored as string like 'state.test'.");return}if(o){let n=o.split(".");if(n[0]!=="state"&&n[0]!=="store"){console.error(`Observer Error: You need to declare 'state.' or 'store.'. The '${o}' string is incorrect!`);return}}if(e&&!t){let n=s(e);if(!n)return;globalThis.observer?.list?.[n]&&x.remove(n),c(`called: ${n}`);return}if(e&&t){let n=s(e);if(!n)return;if(typeof e!="string"&&!(e&&typeof e=="object")){console.error("Observer Error: name of state need to be a 'string' like 'state.test' or a direct state value");return}let i=Array.isArray(t)?t:[t];globalThis.observer?.list?.[n]&&x.remove(n),i.forEach(y=>{typeof y=="function"&&x.listen(n,y,r);});return}},H=at;Object.defineProperties(H,{list:{get:()=>globalThis.events},remove:{value:e=>{e&&(x.remove(e),delete globalThis.events[e]);}},removeAll:{get:()=>{let e=globalThis.observer,t=e?.list;return t&&Object.keys(t).forEach(r=>{e?.remove?.(r);}),true}},has:{value:e=>!!globalThis.observer?.list?.[e]}});a();p();T();globalThis.useObserver||(globalThis.useObserver=null);Object.defineProperty(globalThis,"useObserver",{value:null,writable:true,enumerable:false,configurable:true});var Y=((e,t=[])=>{if(!t||typeof e!="function")return ()=>{};let r=[],s=Array.isArray(t)&&!t.__path?t:[t];try{return s.forEach(o=>{let n="";if(typeof o=="function"){let i=G(o);i&&(n=i);}else typeof o=="object"&&o!==null&&(n=o.__path||(typeof o.toString=="function"&&o.toString()!=="[object Object]"?o.toString():""));if(n){n=n.replace(/^(\(\)\s*=>\s*)/,"").replace(/^globalThis\./,"").replace(/^state\./,"");let i=n.startsWith("store.")||n.startsWith("state.")?n:"state."+n;x.listen(i,()=>e()),r.push(i);}else {u.clearTrackedPaths(),u.tracking=!0;try{e();}catch{}u.tracking=!1,u.trackedPaths.forEach(i=>{r.includes(i)||(c(`useObserver: [Auto-Discovery] -> "${i}"`),x.listen(i,()=>e()),r.push(i));});}}),r.length>0?c(`useObserver: Monitoring ${r.length} paths.`):console.warn("useObserver: No paths resolved for monitoring. Check your dependencies!"),()=>{r.forEach(o=>{typeof x.remove=="function"&&(x.remove(o),c(`useObserver: Stopped monitoring "${o}"`));});}}catch(o){return c(`useObserver Error: ${o}`),()=>{}}});globalThis.useObserver=Y;Object.freeze(globalThis.useObserver);p();a();T();function lt(){return u.debug===true}function Be(){if(!globalThis.store)return {};let e={},t=globalThis.store;if(typeof t.list=="function")try{return t.list()}catch{}if(typeof t.get=="function"){for(let r of Object.keys(t))if(!["get","set","remove","delete","removeAll","clearAll","size","isPersistent","list"].includes(r))try{let s=t.get(r);s!=null&&(e[r]=s);}catch{}}return e}function Re(){if(!globalThis.session)return {};let e={},t=globalThis.session;if(typeof t.list=="function")try{return t.list()}catch{}if(typeof t.get=="function"){for(let r of Object.keys(t))if(!["get","set","remove","delete","removeAll","clearAll","size","isPersistent","list"].includes(r))try{let s=t.get(r);s!=null&&(e[r]=s);}catch{}}return e}var ct=()=>{if(lt()){if(globalThis.state){let e=globalThis.state.list,t;typeof e=="function"?t=e():typeof e=="object"&&e!==null?t=e:t=globalThis.state,console.table(t);}if(globalThis.store&&console.table(Be()),globalThis.session&&console.table(Re()),globalThis.cache){let e=globalThis.cache.list,t;typeof e=="function"?t=e():typeof e=="object"&&e!==null?t=e:t=globalThis.cache,console.table(t);}}},ut=()=>{let e=t=>{if(!t)return 0;if(typeof t.list=="function")try{let r=t.list();return Object.keys(r).length}catch{}return Object.keys(t).length};return {stateKeys:e(globalThis.state),storeKeys:e(globalThis.store),sessionKeys:e(globalThis.session),cacheKeys:e(globalThis.cache),idbDatabases:0,lastUpdate:new Date().toISOString()}},K=e=>{globalThis[e]&&typeof globalThis[e].clear=="function"?globalThis[e].clear():console.error(`Module ${e} not found or does not support clear()`);},ft=()=>{K("state"),K("store"),K("session"),K("cache");},mt=()=>{let e=()=>{if(globalThis.state)try{return typeof globalThis.state.list=="function"?globalThis.state.list():globalThis.state}catch{return}},t=()=>Be(),r=()=>Re(),s=()=>{if(globalThis.cache)try{return typeof globalThis.cache.list=="function"?globalThis.cache.list():globalThis.cache}catch{return}},o={state:e(),store:t(),session:r(),cache:s(),exportedAt:new Date().toISOString()};return JSON.stringify(o,null,2)},dt=e=>{try{let t=JSON.parse(e);t.state&&Object.entries(t.state).forEach(([r,s])=>{globalThis.state&&r!=="list"&&r!=="remove"&&r!=="removeAll"&&(globalThis.state[r]=s);}),t.store&&globalThis.store&&typeof globalThis.store.set=="function"&&Object.entries(t.store).forEach(([r,s])=>{globalThis.store.set(r,s);}),t.session&&globalThis.session&&typeof globalThis.session.set=="function"&&Object.entries(t.session).forEach(([r,s])=>{globalThis.session.set(r,s);}),t.cache&&globalThis.cache&&Object.entries(t.cache).forEach(([r,s])=>{globalThis.cache&&r!=="get"&&r!=="set"&&r!=="remove"&&r!=="clear"&&(globalThis.cache[r]=s);});}catch(t){console.error("%c\u2717 Import failed:","color: #F44336",t);}},gt=(e,t)=>{if(!globalThis[e]){console.error(`Module ${e} not found`);return}let r=globalThis[e],s=r[t];if(console.debug(`\u{1F441} Watching ${e}.${t} (initial: ${JSON.stringify(s)})`),e==="state"&&globalThis.memorio?.dispatch){let o=n=>{n.detail?.name?.includes(t)&&console.debug(`\u{1F441} Change: ${e}.${t} =`,n.detail.value);};r.addEventListener?.("memorio-change",o);}},bt=()=>{console.debug(`
|
|
2
5
|
\u{1F9E0} Memorio DevTools Help
|
|
3
6
|
|
|
4
7
|
Available commands:
|
|
@@ -18,7 +21,7 @@ Shortcuts:
|
|
|
18
21
|
cache - globalThis.cache
|
|
19
22
|
`);},de={inspect:ct,stats:ut,clear:K,clearAll:ft,exportData:mt,importData:dt,watch:gt,help:bt};a();T();p();var pt={enabled:true,logToConsole:true,modules:["state","store","session","cache","idb"],maxEntries:1e3};function yt(){return u.debug===true}var D={...pt},k=[],ht=e=>{D={...D,...e};},vt=()=>{D.enabled=true;},xt=()=>{D.enabled=false;},Me=e=>D.enabled&&D.modules.includes(e),wt=(e,t,r,s,o)=>{if(!Me(e))return;let n={timestamp:new Date().toISOString(),module:e,action:t,path:r,value:s,previousValue:o};if(k.push(n),k.length>D.maxEntries&&k.shift(),D.logToConsole&&yt()){let i=`[Memorio:${e.toUpperCase()}]`,g=St(e);c(`%c${i}%c ${t} ${r},
|
|
20
23
|
color: ${g}; font-weight: bold,
|
|
21
|
-
color: inherit`),s!==void 0&&c(` \u2192 value:${s}`),o!==void 0&&c(` \u2190 previous:${o}`);}D.customHandler&&D.customHandler(n);},St=e=>({state:"#4CAF50",store:"#2196F3",session:"#FF9800",cache:"#9C27B0",idb:"#F44336"})[e]||"#888888",Pt=()=>[...k],Tt=()=>{k.length=0;},Ot=()=>{let e={total:k.length,state:0,store:0,session:0,cache:0,idb:0,set:0,get:0,delete:0,clear:0};for(let t of k)if(t){let r=t.module,s=t.action;r&&typeof e[r]=="number"&&e[r]++,s&&typeof e[s]=="number"&&e[s]++;}return e},Et=()=>JSON.stringify(k,null,2),ge={configure:ht,enable:vt,disable:xt,isEnabled:Me,log:wt,getHistory:Pt,clearHistory:Tt,getStats:Ot,exportLogs:Et};T();M();a();M();T();var be={version:"4.7.
|
|
24
|
+
color: inherit`),s!==void 0&&c(` \u2192 value:${s}`),o!==void 0&&c(` \u2190 previous:${o}`);}D.customHandler&&D.customHandler(n);},St=e=>({state:"#4CAF50",store:"#2196F3",session:"#FF9800",cache:"#9C27B0",idb:"#F44336"})[e]||"#888888",Pt=()=>[...k],Tt=()=>{k.length=0;},Ot=()=>{let e={total:k.length,state:0,store:0,session:0,cache:0,idb:0,set:0,get:0,delete:0,clear:0};for(let t of k)if(t){let r=t.module,s=t.action;r&&typeof e[r]=="number"&&e[r]++,s&&typeof e[s]=="number"&&e[s]++;}return e},Et=()=>JSON.stringify(k,null,2),ge={configure:ht,enable:vt,disable:xt,isEnabled:Me,log:wt,getHistory:Pt,clearHistory:Tt,getStats:Ot,exportLogs:Et};T();M();a();M();T();var be={version:"4.7.1"};w();p();Object.defineProperty(globalThis,"memorio",{value:{setProps:()=>{},obj:{},array:[],dispatch:x,message:v,devtools:de,logger:ge,setDescription:()=>{}},writable:false,configurable:true,enumerable:false});Object.defineProperty(globalThis,"events",{value:{},writable:true,enumerable:false});Object.defineProperty(memorio,"version",{writable:false,enumerable:false,value:be.version});Object.defineProperty(memorio,"debug",{get:()=>u.debug,set:e=>{u.debug=e;},enumerable:false});var Ne=J();Object.defineProperty(memorio,"_platform",{writable:false,enumerable:false,value:Ne.platform});Object.defineProperty(memorio,"_capabilities",{writable:false,enumerable:false,value:Ne});Object.defineProperty(memorio,"_sessionId",{writable:false,enumerable:false,value:U()});xe();memorio.isBrowser=X;memorio.isNode=Z;memorio.isDeno=ee;memorio.isEdge=te;memorio.getCapabilities=J;memorio.createContext=V;memorio.listContexts=ie;memorio.deleteContext=ae;memorio.isolate=e=>V(e);Object.defineProperty(globalThis,"state",{value:L,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"store",{value:j,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"session",{value:C,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"cache",{value:W,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"idb",{value:l,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"observer",{value:H,writable:true,enumerable:false,configurable:true});Object.defineProperty(globalThis,"useObserver",{value:Y,writable:true,enumerable:false,configurable:true});Object.defineProperty(memorio,"dispatch",{value:x,writable:true,enumerable:false,configurable:true});Object.defineProperty(memorio,"setContext",{writable:false,enumerable:false,value:e=>le(e)});Object.defineProperty(memorio,"getContext",{writable:false,enumerable:false,value:()=>u.currentContext});Object.defineProperty(globalThis,"$state",{get:()=>globalThis.state,configurable:true});Object.defineProperty(globalThis,"$store",{get:()=>globalThis.store,configurable:true});Object.defineProperty(globalThis,"$session",{get:()=>globalThis.session,configurable:true});Object.defineProperty(globalThis,"$cache",{get:()=>globalThis.cache,configurable:true});memorio.help=function(){console.debug(`
|
|
22
25
|
\u{1F9E0} Memorio ${be.version} - Help
|
|
23
26
|
|
|
24
27
|
Core Modules:
|
|
@@ -51,4 +54,6 @@ DevTools:
|
|
|
51
54
|
|
|
52
55
|
Shortcuts:
|
|
53
56
|
state, store, session, cache, idb - direct access to modules
|
|
54
|
-
`);};var jt=globalThis.memorio,Lo=globalThis.events,zo=e=>V(e),qo=globalThis.memorio?.help,Jo=e=>u.currentContext=e,Vo=()=>u.currentContext,Ko=jt;
|
|
57
|
+
`);};var jt=globalThis.memorio,Lo=globalThis.events,zo=e=>V(e),qo=globalThis.memorio?.help,Jo=e=>u.currentContext=e,Vo=()=>u.currentContext,Ko=jt;
|
|
58
|
+
|
|
59
|
+
export { W as cache, V as createContext, Ko as default, ae as deleteContext, de as devtools, x as dispatch, Lo as events, J as getCapabilities, Vo as getContext, qo as help, l as idb, u as internal, X as isBrowser, ee as isDeno, te as isEdge, Z as isNode, zo as isolate, ie as listContexts, ge as logger, jt as memorio, v as message, H as observer, G as propertyName, C as session, Jo as setContext, L as state, j as store, Y as useObserver };
|
package/llms.txt
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
npm i memorio
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
> **For AI agents generating code against this library:** default `state` is a shared, global namespace unless a context is explicitly created with `memorio.createContext(id)`. Do not assume per-request or per-tab isolation is automatic — see [Session & Context Isolation](#session--context-isolation) before generating server-side code that handles more than one user/request.
|
|
12
|
+
|
|
11
13
|
## Core Concepts
|
|
12
14
|
|
|
13
15
|
Memorio provides 6 storage modules plus utilities:
|
|
@@ -15,11 +17,11 @@ Memorio provides 6 storage modules plus utilities:
|
|
|
15
17
|
| Module | Purpose | Persistence |
|
|
16
18
|
|--------|---------|-------------|
|
|
17
19
|
| `state` | Reactive, volatile state | In-memory (resets on refresh) |
|
|
18
|
-
| `store` | localStorage persistence | Survives browser refresh |
|
|
19
|
-
| `session` | sessionStorage | Dies with browser tab |
|
|
20
|
+
| `store` | localStorage persistence | Survives browser refresh; falls back to non-durable in-memory `Map` in Node.js/Deno |
|
|
21
|
+
| `session` | sessionStorage | Dies with browser tab; falls back to non-durable in-memory `Map` in Node.js/Deno |
|
|
20
22
|
| `cache` | In-memory cache | Fastest read, no persistence |
|
|
21
|
-
| `idb` | IndexedDB | Structured, async, persistent (browser-only) |
|
|
22
|
-
| `observer` | Object watcher | Legacy |
|
|
23
|
+
| `idb` | IndexedDB | Structured, async, persistent (browser-only — disabled in Node.js/Deno) |
|
|
24
|
+
| `observer` | Object watcher | Legacy; string-based paths, not statically checked against `state`'s shape |
|
|
23
25
|
| `useObserver` | React hook | Auto-discovery of state paths |
|
|
24
26
|
|
|
25
27
|
## Quick Start
|
|
@@ -61,21 +63,23 @@ state.remove('items')
|
|
|
61
63
|
|
|
62
64
|
// Clear all
|
|
63
65
|
state.removeAll()
|
|
64
|
-
|
|
65
|
-
// Lock/unlock for frozen objects
|
|
66
|
-
state.lock() // freeze everything
|
|
67
|
-
state.unlock() // unfreeze
|
|
68
66
|
```
|
|
69
67
|
|
|
68
|
+
**Locking — VERIFY BEFORE PUBLISHING:** this library's own documents currently disagree on scope.
|
|
69
|
+
|
|
70
|
+
- One source describes **per-key** locking: `state.config.lock()` freezes only the `config` key; other keys remain writable.
|
|
71
|
+
- Another source describes **global** locking: `state.lock()` / `state.unlock()` freezing the entire `state` object at once.
|
|
72
|
+
|
|
73
|
+
These are materially different behaviors — confirm against the actual source which one (or both, with distinct method names) is implemented, then replace this note with the real signature(s). Do not ship a docs update, or generate code against this section, until this is resolved.
|
|
74
|
+
|
|
70
75
|
**Features:**
|
|
71
76
|
- Automatic path tracking via `__path` property
|
|
72
77
|
- Nested proxy support
|
|
73
|
-
- Lock/unlock per-key or globally
|
|
74
78
|
- Auto-dispatches events on changes
|
|
75
79
|
|
|
76
80
|
### `store` — localStorage Persistence
|
|
77
81
|
|
|
78
|
-
Persistent storage that survives browser refresh.
|
|
82
|
+
Persistent storage that survives browser refresh. On Node.js/Deno this falls back to an in-memory `Map` that does **not** survive a process restart — treat it as a same-shape cache there, not durable storage.
|
|
79
83
|
|
|
80
84
|
```javascript
|
|
81
85
|
// Set
|
|
@@ -89,15 +93,11 @@ store.list() // { preferences: { theme: 'dark' } }
|
|
|
89
93
|
|
|
90
94
|
// Remove
|
|
91
95
|
store.remove('preferences')
|
|
92
|
-
|
|
93
|
-
// Delete (alias for remove)
|
|
94
|
-
store.delete('preferences')
|
|
96
|
+
store.delete('preferences') // alias
|
|
95
97
|
|
|
96
98
|
// Clear all memorio items
|
|
97
99
|
store.removeAll()
|
|
98
|
-
|
|
99
|
-
// Clear all (alias for removeAll)
|
|
100
|
-
store.clearAll()
|
|
100
|
+
store.clearAll() // alias
|
|
101
101
|
|
|
102
102
|
// Check size
|
|
103
103
|
console.debug(store.size(), 'chars stored')
|
|
@@ -105,13 +105,15 @@ console.debug(store.size(), 'chars stored')
|
|
|
105
105
|
// Check if persistent (real localStorage vs memory fallback)
|
|
106
106
|
console.debug(store.isPersistent) // true → real localStorage
|
|
107
107
|
|
|
108
|
-
// Estimate quota usage
|
|
108
|
+
// Estimate quota usage
|
|
109
109
|
await store.quota() // [usage, quota] in KB
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
+
> **`store.quota()` currently returns `[0, 0]` for the `localStorage` backend** — it is not a real usage reading for that backend, it's a placeholder. Don't use it to make capacity decisions until it's implemented for `localStorage`; it may be meaningful for other backends (e.g. `idb`), but confirm before relying on it there too.
|
|
113
|
+
|
|
112
114
|
### `session` — sessionStorage
|
|
113
115
|
|
|
114
|
-
Storage that dies when browser tab closes.
|
|
116
|
+
Storage that dies when browser tab closes. Same Node.js/Deno `Map` fallback caveat as `store` applies here.
|
|
115
117
|
|
|
116
118
|
```javascript
|
|
117
119
|
// Set
|
|
@@ -125,15 +127,11 @@ session.list() // { token: 'user-abc-123' }
|
|
|
125
127
|
|
|
126
128
|
// Remove
|
|
127
129
|
session.remove('token')
|
|
128
|
-
|
|
129
|
-
// Delete (alias for remove)
|
|
130
|
-
session.delete('token')
|
|
130
|
+
session.delete('token') // alias
|
|
131
131
|
|
|
132
132
|
// Clear all
|
|
133
133
|
session.removeAll()
|
|
134
|
-
|
|
135
|
-
// Clear all (alias for removeAll)
|
|
136
|
-
session.clearAll()
|
|
134
|
+
session.clearAll() // alias
|
|
137
135
|
|
|
138
136
|
// Check size
|
|
139
137
|
console.debug(session.size(), 'chars stored')
|
|
@@ -161,9 +159,7 @@ cache.remove('temp')
|
|
|
161
159
|
|
|
162
160
|
// Clear all
|
|
163
161
|
cache.clear()
|
|
164
|
-
|
|
165
|
-
// Remove all (alias for clear)
|
|
166
|
-
cache.removeAll()
|
|
162
|
+
cache.removeAll() // alias
|
|
167
163
|
|
|
168
164
|
// Direct access (also works)
|
|
169
165
|
cache['myKey'] = value
|
|
@@ -173,7 +169,7 @@ delete cache['myKey']
|
|
|
173
169
|
|
|
174
170
|
### `idb` — IndexedDB
|
|
175
171
|
|
|
176
|
-
Structured, persistent, async database (browser-only).
|
|
172
|
+
Structured, persistent, async database (browser-only). **Disabled in Node.js/Deno** — calls will warn and no-op; use `store` or `session` there instead.
|
|
177
173
|
|
|
178
174
|
```javascript
|
|
179
175
|
// Create database
|
|
@@ -200,24 +196,21 @@ const exists = await idb.db.exist('my-db')
|
|
|
200
196
|
// Delete database
|
|
201
197
|
await idb.db.delete('my-db')
|
|
202
198
|
|
|
203
|
-
// Get database size
|
|
199
|
+
// Get database / table size
|
|
204
200
|
const size = await idb.db.size('my-db')
|
|
205
|
-
|
|
206
|
-
// Get table size
|
|
207
201
|
const tableSize = await idb.table.size('my-db', 'users')
|
|
208
202
|
|
|
209
|
-
// Check support
|
|
210
|
-
idb.db.support()
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const [usage, quota] = await idb.db.quota()
|
|
203
|
+
// Check support before calling anything else
|
|
204
|
+
if (idb.db.support()) {
|
|
205
|
+
const [usage, quota] = await idb.db.quota()
|
|
206
|
+
}
|
|
214
207
|
```
|
|
215
208
|
|
|
216
|
-
|
|
209
|
+
Always guard `idb` calls with `idb.db.support()` (or `memorio.getCapabilities().hasIndexedDB`) in code that might run outside a browser — don't rely on the no-op warning alone.
|
|
217
210
|
|
|
218
211
|
### `observer` — Object Watcher
|
|
219
212
|
|
|
220
|
-
Legacy observer API.
|
|
213
|
+
Legacy observer API. Prefer `useObserver` in React code.
|
|
221
214
|
|
|
222
215
|
```javascript
|
|
223
216
|
// Listen to state changes
|
|
@@ -238,6 +231,8 @@ console.debug(observer.list)
|
|
|
238
231
|
observer.removeAll()
|
|
239
232
|
```
|
|
240
233
|
|
|
234
|
+
> Paths are plain strings and are not checked against `state`'s actual shape at compile time or at registration time. A typo or a later rename of the corresponding `state` key will fail silently — the observer simply never fires again.
|
|
235
|
+
|
|
241
236
|
### `useObserver` — React Hook
|
|
242
237
|
|
|
243
238
|
Primary way to observe state changes in React components.
|
|
@@ -266,67 +261,48 @@ function Counter() {
|
|
|
266
261
|
|
|
267
262
|
**Features:**
|
|
268
263
|
- Auto-discovery of state paths during render
|
|
269
|
-
- Returns cleanup function to stop monitoring
|
|
264
|
+
- Returns a cleanup function to stop monitoring
|
|
270
265
|
- Supports both Proxy objects and string paths
|
|
271
266
|
|
|
272
267
|
### `devtools` — Inspection Tools
|
|
273
268
|
|
|
274
|
-
|
|
269
|
+
Browser-only (see [Cross-Platform Support](#cross-platform-support)); no-ops or unavailable in Node.js/Deno.
|
|
275
270
|
|
|
276
271
|
```javascript
|
|
277
|
-
//
|
|
278
|
-
memorio.devtools.
|
|
279
|
-
|
|
280
|
-
// Get stats
|
|
281
|
-
memorio.devtools.stats() // { stateKeys, storeKeys, sessionKeys, ... }
|
|
282
|
-
|
|
283
|
-
// Clear specific module
|
|
272
|
+
memorio.devtools.inspect() // pretty-print state, store, session, cache
|
|
273
|
+
memorio.devtools.stats() // { stateKeys, storeKeys, sessionKeys, ... }
|
|
284
274
|
memorio.devtools.clear('state')
|
|
285
|
-
|
|
286
|
-
// Clear all modules
|
|
287
275
|
memorio.devtools.clearAll()
|
|
288
|
-
|
|
289
|
-
// Export all data as JSON
|
|
290
276
|
memorio.devtools.exportData()
|
|
291
|
-
|
|
292
|
-
// Import data from JSON
|
|
293
277
|
memorio.devtools.importData(jsonString)
|
|
294
|
-
|
|
295
|
-
// Show help
|
|
296
278
|
memorio.devtools.help()
|
|
297
279
|
|
|
298
280
|
// Console shortcuts
|
|
299
|
-
$state //
|
|
300
|
-
$store //
|
|
301
|
-
$session //
|
|
302
|
-
$cache //
|
|
281
|
+
$state // globalThis.state
|
|
282
|
+
$store // globalThis.store
|
|
283
|
+
$session // globalThis.session
|
|
284
|
+
$cache // globalThis.cache
|
|
303
285
|
```
|
|
304
286
|
|
|
305
287
|
### `logger` — Change Tracking
|
|
306
288
|
|
|
307
|
-
|
|
289
|
+
Records every write it's configured to track, with timestamps — including whatever values you pass in.
|
|
308
290
|
|
|
309
291
|
```javascript
|
|
310
|
-
// Configure logger
|
|
311
292
|
memorio.logger.configure({
|
|
312
293
|
enabled: true,
|
|
313
294
|
logToConsole: true,
|
|
314
295
|
modules: ['state', 'store', 'session', 'cache', 'idb']
|
|
315
296
|
})
|
|
316
297
|
|
|
317
|
-
//
|
|
318
|
-
memorio.logger.
|
|
319
|
-
|
|
320
|
-
// Get stats
|
|
321
|
-
memorio.logger.getStats() // { total, state, store, session, cache, idb, set, get, ... }
|
|
322
|
-
|
|
323
|
-
// Clear history
|
|
298
|
+
memorio.logger.getHistory() // [{ timestamp, module, action, path, value }, ...]
|
|
299
|
+
memorio.logger.getStats() // { total, state, store, session, cache, idb, set, get, ... }
|
|
324
300
|
memorio.logger.clearHistory()
|
|
325
|
-
|
|
326
|
-
// Export logs
|
|
327
|
-
memorio.logger.exportLogs() // JSON string of all history
|
|
301
|
+
memorio.logger.exportLogs() // JSON string of all history
|
|
328
302
|
```
|
|
329
303
|
|
|
304
|
+
> The `value` field in each history entry is whatever was written — tokens, PII, anything. Don't enable `logger` unconditionally in production paths that handle sensitive data, and don't wire `exportLogs()` output anywhere it could leak (analytics, error reporters, support tooling) without redaction.
|
|
305
|
+
|
|
330
306
|
## Platform Detection
|
|
331
307
|
|
|
332
308
|
Access via `memorio.*` after `import 'memorio'`:
|
|
@@ -339,14 +315,10 @@ memorio.isEdge() // true in Cloudflare Workers, Vercel Edge
|
|
|
339
315
|
|
|
340
316
|
const caps = memorio.getCapabilities()
|
|
341
317
|
// { 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
318
|
```
|
|
349
319
|
|
|
320
|
+
Prefer checking `getCapabilities()` over assuming a platform from context — especially before calling `idb` or relying on `store`/`session` durability.
|
|
321
|
+
|
|
350
322
|
## Cross-Platform Support
|
|
351
323
|
|
|
352
324
|
| Module | Browser | Node.js | Deno | Edge/Workers |
|
|
@@ -354,32 +326,44 @@ memorio.isolate('tenant-name') // alias for createContext
|
|
|
354
326
|
| `state` | ✅ | ✅ | ✅ | ✅ |
|
|
355
327
|
| `observer` / `useObserver` | ✅ | ✅ | ✅ | ✅ |
|
|
356
328
|
| `cache` | ✅ | ✅ | ✅ | ✅ |
|
|
357
|
-
| `store` | ✅ localStorage | ⚠️
|
|
358
|
-
| `session` | ✅ sessionStorage | ⚠️
|
|
359
|
-
| `idb` | ✅ IndexedDB | ❌ | ❌ | ⚠️ |
|
|
329
|
+
| `store` | ✅ `localStorage` | ⚠️ `Map`, not durable | ⚠️ `Map`, not durable | ✅ `localStorage` where available, else `Map` |
|
|
330
|
+
| `session` | ✅ `sessionStorage` | ⚠️ `Map`, not durable | ⚠️ `Map`, not durable | ✅ `sessionStorage` where available, else `Map` |
|
|
331
|
+
| `idb` | ✅ `IndexedDB` | ❌ disabled | ❌ disabled | ⚠️ check `getCapabilities()` |
|
|
360
332
|
| `devtools` | ✅ | ❌ | ❌ | ⚠️ |
|
|
361
333
|
|
|
362
|
-
|
|
334
|
+
## Session & Context Isolation
|
|
363
335
|
|
|
364
|
-
|
|
336
|
+
By default, `state` is a **shared global namespace** — a value set in one place is visible everywhere else that reads `state` in the same process. There is no automatic per-tab or per-request isolation of `state` itself.
|
|
365
337
|
|
|
366
|
-
|
|
338
|
+
To isolate a slice of state (e.g. per tenant, per request), create an explicit context:
|
|
367
339
|
|
|
368
340
|
```javascript
|
|
369
|
-
|
|
370
|
-
|
|
341
|
+
const ctx = memorio.createContext('tenant-name')
|
|
342
|
+
ctx.state.user = { name: 'Isolated' }
|
|
343
|
+
|
|
344
|
+
console.debug(state.user) // undefined — separate namespace from ctx.state
|
|
345
|
+
|
|
371
346
|
memorio.listContexts()
|
|
372
347
|
memorio.deleteContext('context-id')
|
|
373
348
|
memorio.isolate('tenant-name') // alias for createContext
|
|
374
349
|
```
|
|
375
350
|
|
|
351
|
+
Isolation is implemented as a **key-prefix convention** inside the same underlying storage, not a hard memory or process boundary. In a shared Node.js process or an edge isolate that may be reused across requests:
|
|
352
|
+
|
|
353
|
+
- generate context IDs from trusted server-side data, never directly from client-controlled input, to prevent collisions or spoofing;
|
|
354
|
+
- don't treat this as your only isolation layer for data that must not cross tenants — enforce that at the process/request level as well.
|
|
355
|
+
|
|
356
|
+
`getCapabilities().sessionId` provides a per-session identifier for browser contexts but is not itself an isolation mechanism — use `createContext` for that.
|
|
357
|
+
|
|
376
358
|
## Security
|
|
377
359
|
|
|
378
|
-
- Zero production dependencies
|
|
379
|
-
-
|
|
380
|
-
-
|
|
381
|
-
-
|
|
382
|
-
-
|
|
360
|
+
- Zero production dependencies.
|
|
361
|
+
- No `eval`, no dynamic code execution, no obfuscation, no hardcoded secrets.
|
|
362
|
+
- Inputs validated, keys sanitized before use.
|
|
363
|
+
- Secure random session IDs via `crypto.randomUUID`.
|
|
364
|
+
- Data in `store`, `session`, and `idb` is **not encrypted** — these are thin wrappers over browser storage APIs that persist data in the clear on the user's device. Add your own encryption layer before storing tokens, secrets, or regulated personal data there.
|
|
365
|
+
|
|
366
|
+
Engineering practices are informed by recognized guidance (e.g. NIST SP 800-53 practices) as a design input — this is a statement about how the library is built, not a compliance certification, and no third-party audit has been performed. Report security issues privately (see `SECURITY.md`) rather than in a public issue.
|
|
383
367
|
|
|
384
368
|
## License
|
|
385
369
|
|
|
@@ -389,7 +373,7 @@ MIT © Dario Passariello (BigLogic Inc Canada)
|
|
|
389
373
|
|
|
390
374
|
### `memorio.dispatch` — Event Dispatch System
|
|
391
375
|
|
|
392
|
-
Internal event system used by state changes.
|
|
376
|
+
Internal event system used by state changes; also usable directly for custom events.
|
|
393
377
|
|
|
394
378
|
```javascript
|
|
395
379
|
// Dispatch a custom event
|
package/package.json
CHANGED