memorio 4.9.31 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +327 -330
  3. package/SECURITY.md +17 -1
  4. package/SUMMARY.md +59 -45
  5. package/adr/001-state-proxy-model.md +96 -0
  6. package/adr/002-observer-semantics.md +180 -0
  7. package/adr/003-deep-mutation-semantics.md +129 -0
  8. package/adr/004-array-mutation-semantics.md +128 -0
  9. package/adr/005-scheduler-contract.md +149 -0
  10. package/adr/006-context-isolation.md +92 -0
  11. package/adr/007-mutation-records.md +118 -0
  12. package/adr/008-transactions.md +106 -0
  13. package/adr/009-history-model.md +110 -0
  14. package/adr/README.md +46 -0
  15. package/adr/template.md +49 -0
  16. package/examples/basic.ts +115 -115
  17. package/examples/browser-vanilla.html +358 -358
  18. package/examples/cache.ts +72 -72
  19. package/examples/cross-platform-guards.ts +57 -57
  20. package/examples/history.ts +104 -0
  21. package/examples/idb.ts +109 -109
  22. package/examples/multi-tenant-context.ts +44 -44
  23. package/examples/node-server.ts +308 -308
  24. package/examples/observer.ts +60 -60
  25. package/examples/platform.ts +115 -115
  26. package/examples/react-app.tsx +362 -362
  27. package/examples/react-observer.tsx +63 -63
  28. package/examples/semantic-memory.ts +60 -60
  29. package/examples/session-advanced.ts +91 -91
  30. package/examples/sqlite-batched-writes.ts +57 -57
  31. package/examples/state-advanced.ts +89 -89
  32. package/examples/store-advanced.ts +117 -117
  33. package/examples/sync.ts +90 -0
  34. package/examples/typed-and-schema.ts +102 -100
  35. package/examples/useObserver.tsx +140 -141
  36. package/global.cjs +4594 -0
  37. package/global.d.ts +8 -0
  38. package/global.js +4532 -0
  39. package/index.cjs +706 -649
  40. package/index.d.ts +1 -0
  41. package/index.js +686 -648
  42. package/llms.txt +72 -4
  43. package/markdown/AUDIT-REPORT.md +135 -0
  44. package/markdown/CACHE.md +100 -0
  45. package/markdown/CHANGELOG.md +243 -0
  46. package/markdown/DEVTOOLS.md +129 -0
  47. package/markdown/DISPATCH.md +177 -0
  48. package/markdown/HISTORY.md +199 -0
  49. package/markdown/IDB.md +178 -0
  50. package/markdown/IMPORT.md +153 -0
  51. package/markdown/INSPECT.md +123 -0
  52. package/markdown/LOGGER.md +154 -0
  53. package/markdown/MEMORY-ATTACHMENT.md +96 -0
  54. package/markdown/MEMORY.md +162 -0
  55. package/markdown/OBSERVER.md +209 -0
  56. package/markdown/PLATFORM.md +271 -0
  57. package/markdown/PROJECT.md +311 -0
  58. package/markdown/SCHEMA.md +176 -0
  59. package/markdown/SECURITY.md +330 -0
  60. package/markdown/SESSION.md +165 -0
  61. package/markdown/SQLITE.md +190 -0
  62. package/markdown/STATE.md +160 -0
  63. package/markdown/STORE.md +171 -0
  64. package/markdown/SYNC.md +319 -0
  65. package/markdown/TYPED.md +165 -0
  66. package/markdown/USEOBSERVER.md +257 -0
  67. package/modules/redux.cjs +561 -374
  68. package/modules/redux.cjs.map +1 -1
  69. package/modules/redux.js +561 -374
  70. package/modules/redux.js.map +1 -1
  71. package/package.json +13 -3
  72. package/types/env.d.ts +19 -9
  73. package/types/exports.d.ts +20 -0
  74. package/types/history.d.ts +13 -1
  75. package/types/memorio.d.ts +17 -5
  76. package/types/mutation.d.ts +75 -0
@@ -0,0 +1,311 @@
1
+ > **Status:** Published
2
+ > **Date:** 2026-09-12
3
+ > **Deciders:** Memorio 5.x Core Team, BigLogic
4
+ > **Scope**: Project Documentation
5
+ > **Standard**: Memorio Documentation Standard v5
6
+ >
7
+ ---
8
+ # Memorio - NPM Package
9
+
10
+ ## Versione
11
+
12
+ **4.9.5** - Current: `4.9.5` branch
13
+
14
+ ## Chi Siamo
15
+
16
+ - **Jo**: AI assistant, amico di Dario, professionale e diretto
17
+ - **Dario Passariello**: CTO e fondatore di BigLogic
18
+ - **BigLogic**: Azienda specializzata in soluzioni SaaS artigianali, AI e design ad alta precisione
19
+
20
+ ## Progetto Attuale
21
+
22
+ **Memorio** è un NPM package leggero e semplice per piccoli progetti dove servono soluzioni veloci senza complessità enterprise:
23
+
24
+ - **State** - memoria volatile reattiva (Proxy-based)
25
+ - **Store** - localStorage persistenza
26
+ - **Session** - sessionStorage
27
+ - **IDB** - IndexedDB storage strutturato
28
+ - **Cache** - in-memory cache
29
+ - **Observer** - pattern observer per vanilla JS
30
+ - **UseObserver** - React hook per observer
31
+ - **DevTools** - Browser console debugging tools
32
+ - **Logger** - utility di logging
33
+ - **Dispatch** - vanilla JS event system
34
+ - **Schema** - runtime validation per state paths
35
+ - **Typed** - compile-time type safety su state proxy
36
+ - **History** - time-travel (undo/redo/snapshot/diff/trace)
37
+ - **Inspect** - introspection utilities
38
+ - **Memory** - AI memory system con persistence e TTL
39
+
40
+ **Target**: Progetti piccoli/medi
41
+ **Confronto**: @Biglogic/rgs = enterprise, Memorio = piccoli progetti
42
+
43
+ ## Stack Tecnologico
44
+
45
+ - TypeScript 6.0.3 (strict mode)
46
+ - tsup 8.5.1 per build (ESM + CJS)
47
+ - ES2022 target
48
+ - ESM (`"type": "module"`)
49
+ - vitest per test (browser + node)
50
+ - Playwright per test end-to-end
51
+ - Peer dependencies: React >=16.8.0 (opzionale)
52
+ - Nessuna UI (è una libreria)
53
+ - Production: dependency-free (zero runtime dependencies)
54
+
55
+ ## Struttura File
56
+
57
+ ```
58
+ memorio/
59
+ ├── index.ts # Entry point (named exports + memorio namespace)
60
+ ├── core/ # Core modules (bootstrap, platform, internal)
61
+ │ ├── global.ts # Bootstrap: publishes to globalThis
62
+ │ ├── env.ts # Runtime DEV/PROD detection
63
+ │ ├── internal.ts # Module-local internal state singleton
64
+ │ ├── platform.ts # Browser/Node/Deno/Edge detection
65
+ │ ├── dispatch.ts # Event dispatch system
66
+ │ ├── hlc.ts # Hybrid Logical Clock
67
+ │ └── fractional.ts # Fractional indexing
68
+ ├── types/ # TypeScript declarations
69
+ │ └── memorio.d.ts
70
+ ├── functions/ # Feature modules
71
+ │ ├── state/ # Reactive state (Proxy)
72
+ │ ├── store/ # LocalStorage
73
+ │ ├── session/ # SessionStorage
74
+ │ ├── cache/ # In-memory cache
75
+ │ ├── idb/ # IndexedDB (browser)
76
+ │ ├── sqlite/ # SQLite (sql.js, optional)
77
+ │ ├── observer/ # Observer pattern
78
+ │ ├── useObserver/ # React hook
79
+ │ ├── logger/ # Logging
80
+ │ ├── devtools/ # DevTools (dev-only)
81
+ │ ├── schema/ # Runtime validation
82
+ │ ├── typed/ # Type-safe state views
83
+ │ ├── history/ # Time-travel undo/redo
84
+ │ ├── inspect/ # Introspection
85
+ │ ├── memory/ # AI memory system
86
+ │ ├── message/ # User messages
87
+ │ └── dispatch/ # Event dispatch
88
+ ├── tests/ # Vitest + Playwright tests
89
+ │ ├── vitest/ # Vitest config + test files
90
+ │ └── playwright/ # E2E test specs
91
+ ├── .project/markdown/ # Project context & documentation
92
+ │ ├── CHANGELOG.md
93
+ │ ├── PROJECT.md
94
+ │ └── ... (module docs)
95
+ ├── docs/ # Published documentation
96
+ ├── package.json
97
+ ├── tsconfig.json
98
+ ├── tsup.config.ts
99
+ └── .kilo/ # Kilo AI agent memory
100
+ ```
101
+
102
+ ## API Pubbliche
103
+
104
+ ### Core Namespace
105
+
106
+ ```typescript
107
+ import memorio, { state, store, session, cache, idb, sqlite, observer, useObserver, dispatch, message } from 'memorio'
108
+ // or for global access:
109
+ // import 'memorio/global'
110
+
111
+ // Runtime environment detection
112
+ memorio.env.isDev // true in development, false in production
113
+ memorio.env.isProd // inverse of isDev
114
+
115
+ // Global API (opt-in via memorio/global entry)
116
+ memorio.global() // Force-expose dev globals on globalThis (idempotent)
117
+ ```
118
+
119
+ ### State
120
+
121
+ ```typescript
122
+ // Via named import (or global entrypoint if opted in)
123
+ state.key = 'value' // Set
124
+ state.key // Get (reactive)
125
+ state.remove('key') // Delete
126
+ state.removeAll() // Clear all
127
+ state.lock() // Lock all modifications
128
+ state.unlock() // Unlock
129
+ state.list // Deep clone of all state
130
+ state.typed<T>() // Type-safe view
131
+ ```
132
+
133
+ ### Store (localStorage)
134
+
135
+ ```typescript
136
+ store.set('key', { value: 42 })
137
+ store.get('key') // { value: 42 }
138
+ store.remove('key')
139
+ store.removeAll()
140
+ store.isPersistent // boolean
141
+ store.size() // character count
142
+ store.quota() // [used, quota]
143
+ store.list() // all memorio keys
144
+ ```
145
+
146
+ ### Session (sessionStorage)
147
+
148
+ ```typescript
149
+ session.set('key', 'value')
150
+ session.get('key')
151
+ session.remove('key')
152
+ session.removeAll()
153
+ session.isPersistent
154
+ ```
155
+
156
+ ### Cache (in-memory)
157
+
158
+ ```typescript
159
+ cache.set('key', 'value')
160
+ cache.get('key')
161
+ cache.remove('key')
162
+ cache.list() // all cached items
163
+ cache.clear() // alias for removeAll
164
+ ```
165
+
166
+ ### Schema Validation
167
+
168
+ ```typescript
169
+ memorio.registerSchema('user.name', {
170
+ type: 'string',
171
+ required: true,
172
+ min: 1,
173
+ pattern: /^[a-zA-Z]+$/
174
+ })
175
+
176
+ memorio.validate('user.name', 'Jo') // { valid: true, errors: [] }
177
+ memorio.listSchemas() // registered paths
178
+ memorio.unregisterSchema('user.name')
179
+ ```
180
+
181
+ ### History / Time Travel
182
+
183
+ ```typescript
184
+ memorio.enableHistory() // Start tracking mutations
185
+ const snap = memorio.snapshot() // Deep clone of state
186
+ memorio.undo() // Revert last mutation
187
+ memorio.redo() // Re-apply
188
+ memorio.canUndo() // boolean
189
+ memorio.canRedo() // boolean
190
+ memorio.rollback(snap) // Restore to snapshot
191
+ memorio.trace() // List all mutations
192
+ memorio.clearHistory() // Clear undo/redo/trace
193
+ ```
194
+
195
+ ### Platform Detection
196
+
197
+ ```typescript
198
+ memorio.isBrowser() // boolean
199
+ memorio.isNode() // boolean
200
+ memorio.isDeno() // boolean
201
+ memorio.isEdge() // boolean
202
+ memorio.getCapabilities() // { platform, hasLocalStorage, hasIndexedDB, ... }
203
+ ```
204
+
205
+ ### Context (multi-tenant)
206
+
207
+ ```typescript
208
+ memorio.createContext('tenant-name') // Isolate state by context
209
+ memorio.listContexts() // List all contexts
210
+ memorio.deleteContext('context-id') // Delete a context
211
+ memorio.isolate('tenant-name') // Shorthand for createContext
212
+ ```
213
+
214
+ ## NPM Scripts
215
+
216
+ | Comando | Descrizione |
217
+ |---------|-------------|
218
+ | `npm run build` | Build con tsup (ESM + CJS) |
219
+ | `npm run watch` | Watch mode con tsup |
220
+ | `npm test` | Esegui vitest test suite |
221
+ | `npm run lint` | Lint con oxlint |
222
+ | `npm run tsc` | TypeScript type check |
223
+
224
+ ## Test Suite
225
+
226
+ | Suite | Tests | Stato |
227
+ |-------|-------|-------|
228
+ | State | 24 | ✅ |
229
+ | Store | 17 | ✅ |
230
+ | Session | 12 | ✅ |
231
+ | Cache | 5 | ✅ |
232
+ | Observer | 12 | ✅ |
233
+ | useObserver | 12 | ✅ |
234
+ | DevTools | 8 | ✅ |
235
+ | Schema | 10 | ✅ |
236
+ | History | 8 | ✅ |
237
+ | Inspect | 6 | ✅ |
238
+ | ID | 3 | ✅ |
239
+ | Dispatch | 5 | ✅ |
240
+ | Message | 4 | ✅ |
241
+ | Logger | 3 | ✅ |
242
+ | Memory | 5 | ✅ |
243
+ | **Totale** | **~120+** | ✅ |
244
+
245
+ ## Regole Importanti
246
+
247
+ 1. Documentazione in `.project/markdown/`, non nella root
248
+ 2. Usare `console.debug()` per il debugging
249
+ - Nei blocchi `catch` e codice di gestione errori operativi è consentito `console.error()` e `console.warn`
250
+ 3. Arrow functions obbligatorie
251
+ 4. JSDoc obbligatorio su tutte le funzioni pubbliche
252
+ 5. Peer dependency React >=16.8.0 opzionale
253
+ 6. Nessuno stile CSS/SCSS (è una libreria)
254
+ 7. Nessun database embedded
255
+ 8. Tutti i moduli usano singleton keys su `globalThis` per prevenire module duplication
256
+
257
+ ## Dipendenze
258
+
259
+ ### Produzione
260
+ - Nessuna (dependency-free)
261
+
262
+ ### Sviluppo
263
+ - `typescript: 6.0.3`
264
+ - `tsup: 8.5.1`
265
+ - `vitest: 5.0.0`
266
+ - `playwright: chromium`
267
+ - `@types/node: ^25.9.1`
268
+ - `react: ^19.2.6` (peer)
269
+ - `react-dom: ^19.2.6` (peer)
270
+
271
+ ### Peer
272
+ - `react: >=16.8.0` (opzionale)
273
+ - `react-dom: >=16.8.0` (opzionale)
274
+
275
+ ## Module Duplication Strategy
276
+
277
+ Memorio can be imported via multiple paths (ESM `dist/index.js`, CJS `dist/index.cjs`, package name `memorio`). Each path may resolve to a separate module instance in the bundler. To prevent duplicate proxies:
278
+
279
+ | Module | Singleton Key |
280
+ |--------|--------------|
281
+ | `state` | `__memorio_state_instance__` |
282
+ | `store` | `__memorio_store_instance__` |
283
+ | `session` | `__memorio_session_instance__` |
284
+ | `cache` | `__memorio_cache_instance__` |
285
+ | internal state | `__memorio_internal_state` |
286
+
287
+ The first import path to execute creates the instance and stores it on `globalThis`. Subsequent imports find the existing instance and reuse it - guaranteeing all named exports point to the **same** proxy object.
288
+
289
+ ## Valutazione Attuale
290
+
291
+ ### Punti di Forza
292
+
293
+ - Struttura NPM corretta
294
+ - Build con tsup moderno (ESM + CJS)
295
+ - Testing setup (vitest + Playwright)
296
+ - Auto-detection React per reattività
297
+ - Multi-storage support (state, store, session, idb, cache, sqlite, devtools, logger)
298
+ - Totalmente dependency-free in produzione
299
+ - Cross-platform: Browser, Node.js, Deno, Edge Workers
300
+ - Session isolation e Context system per multi-tenant
301
+ - Module duplication protection via singleton keys
302
+ - Schema validation e typed stores per type safety
303
+
304
+ ### Critica
305
+
306
+ - Coverage test non verificato
307
+ - Socket.dev Supply Chain Security da monitorare
308
+
309
+ ---
310
+
311
+ *Ultimo aggiornamento: 2026-09-06*
@@ -0,0 +1,176 @@
1
+ > **Status:** Published
2
+ > **Date:** 2026-09-12
3
+ > **Deciders:** Memorio 5.x Core Team
4
+ > **Scope**: API Reference
5
+ > **Standard**: Memorio API Specification v5
6
+ >
7
+ ---
8
+ # Schema Validation - Memorio
9
+
10
+ > ✅ **Universal**: Works in Browser, Node.js, Deno, and Edge Workers
11
+
12
+ Schema validation guards your `state` against invalid writes. It runs inside the state proxy's `set` trap, so any `state.somePath = value` that violates a registered schema is rejected at runtime - before the value is ever stored.
13
+
14
+ Schema validation is **opt-in** and **zero-dependency**.
15
+
16
+ ---
17
+
18
+ ## Quick Start
19
+
20
+ ```javascript
21
+ import { memorio, state } from 'memorio'
22
+
23
+ // Register a validator for a top-level state key
24
+ memorio.registerSchema('user', {
25
+ type: 'object',
26
+ required: ['name', 'email'],
27
+ properties: {
28
+ name: { type: 'string', min: 1 },
29
+ email: { type: 'string', pattern: /^[^@]+@[^@]+$/ },
30
+ age: { type: 'number', min: 0, max: 150 }
31
+ }
32
+ })
33
+
34
+ // Valid write - accepted
35
+ state.user = { name: 'Sara', email: 'sara@test.com', age: 30 }
36
+
37
+ // Invalid write - rejected, returns false
38
+ state.user = { name: 'Sara' } // missing 'email'
39
+ state.user = { name: 42, email: 'x' } // wrong type for 'name'
40
+ state.user = { age: -5 } // out of range
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Schema Definition
46
+
47
+ A `Schema` object supports the following fields:
48
+
49
+ | Field | Type | Description |
50
+ |-------|------|-------------|
51
+ | `type` | `'string' \| 'number' \| 'boolean' \| 'object' \| 'array' \| 'any'` | Runtime type check |
52
+ | `required` | `string[]` | Property names that must exist (objects only) |
53
+ | `properties` | `Record<string, Schema>` | Nested property schemas (validated recursively) |
54
+ | `min` | `number` | Number: minimum value. String: minimum length |
55
+ | `max` | `number` | Number: maximum value. String: maximum length |
56
+ | `pattern` | `RegExp` | Regex the string value must match |
57
+ | `enum` | `any[]` | Whitelist of allowed values |
58
+ | `validator` | `(value) => boolean \| string` | Custom validator function |
59
+
60
+ ### Custom validator functions
61
+
62
+ For logic that's hard to express declaratively, pass a function instead of a schema object:
63
+
64
+ ```javascript
65
+ memorio.registerSchema('counter', (value) => {
66
+ if (typeof value !== 'number') return 'counter must be a number'
67
+ if (value < 0) return 'counter must be >= 0'
68
+ return true
69
+ })
70
+ ```
71
+
72
+ A custom validator receives the raw value. Return `true` to accept, or a **string** describing the error to reject.
73
+
74
+ ---
75
+
76
+ ## Path-based registration
77
+
78
+ Schemas are keyed by their **state path**, relative to `state`:
79
+
80
+ | API call | Catches |
81
+ |----------|---------|
82
+ | `registerSchema('user', schema)` | `state.user = value` |
83
+ | `registerSchema('user.age', schema)` | `state.user.age = value` |
84
+ | `registerSchema('items', schema)` | `state.items = value` |
85
+
86
+ The full dotted path is constructed from the proxy's tree depth. Nested sets propagate the full path automatically.
87
+
88
+ ---
89
+
90
+ ## Manual validation
91
+
92
+ You can validate a value without writing it to state:
93
+
94
+ ```javascript
95
+ memorio.validate('user', { name: 'Sara', email: 'sara@test.com' })
96
+ // { valid: true }
97
+
98
+ memorio.validate('user', { name: 'Sara' })
99
+ // { valid: false, errors: ["user: missing required property 'email'"] }
100
+ ```
101
+
102
+ When no schema is registered for a path, `validate` returns `{ valid: true }`.
103
+
104
+ ---
105
+
106
+ ## Schema management
107
+
108
+ ```javascript
109
+ memorio.listSchemas() // ['user', 'theme', 'items', 'counter']
110
+ memorio.unregisterSchema('counter') // removes the schema
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Full API
116
+
117
+ | Method | Parameters | Returns | Description |
118
+ |--------|-----------|---------|-------------|
119
+ | `memorio.registerSchema(path, schema)` | `string`, `Schema \| fn` | `void` | Register a validator |
120
+ | `memorio.validate(path, value)` | `string`, `any` | `{ valid, errors? }` | Manually validate a value |
121
+ | `memorio.unregisterSchema(path)` | `string` | `boolean` | Remove a registered schema |
122
+ | `memorio.listSchemas()` | none | `string[]` | List all registered paths |
123
+ | `memorio.registerSchema()` is also importable | `registerSchema` | named export | same function |
124
+
125
+ ---
126
+
127
+ ## Combine with Typed Stores
128
+
129
+ Schema validation gives you **runtime** safety; typed stores give you **compile-time** safety. Use both for full coverage:
130
+
131
+ ```typescript
132
+ import { memorio, state } from 'memorio'
133
+
134
+ interface AppState {
135
+ user: { name: string; email: string; age: number }
136
+ theme: 'light' | 'dark'
137
+ }
138
+
139
+ const app = memorio.typed<AppState>()
140
+
141
+ memorio.registerSchema('user', {
142
+ type: 'object',
143
+ required: ['name', 'email'],
144
+ properties: {
145
+ name: { type: 'string', min: 1 },
146
+ email: { type: 'string', pattern: /^[^@]+@[^@]+$/ },
147
+ age: { type: 'number', min: 0, max: 150 }
148
+ }
149
+ })
150
+
151
+ app.user = { name: '', email: 'bad' } // ❌ TypeScript: age missing
152
+ // ❌ Runtime: missing required fields
153
+ app.user = { name: 'Sara', email: 'ok', age: 30 } // ✅ both checks pass
154
+ ```
155
+
156
+ See [Typed Stores](TYPED.md) for compile-time type safety.
157
+
158
+ ---
159
+
160
+ ## How it works
161
+
162
+ 1. When you call `registerSchema(path, schema)`, the schema is stored in an internal `Map`.
163
+ 2. On every `state.set` operation, the proxy's `set` trap computes the full path (e.g. `'user.name'`).
164
+ 3. If a schema is registered for that path, the value is validated.
165
+ 4. If validation fails, the write is rejected (`return false`), and an error is logged via `console.error` (when `memorio.debug = true`) or `console.debug` (via the internal `message` helper).
166
+ 5. If no schema is registered, the write proceeds normally.
167
+
168
+ The validation adds negligible overhead when no schemas are registered (a single `Map` lookup that returns `undefined`).
169
+
170
+ ---
171
+
172
+ ## Limitations
173
+
174
+ - Schema validation hooks into the `state` proxy only. `store`, `session`, and `cache` are not validated (they use separate storage). Use `validate()` before writing to other modules.
175
+ - Path matching is **exact**: `registerSchema('user')` guards `state.user = ...`, but does **not** recursively validate `state.user.name = 'new'`. Register schemas at each path you need to guard.
176
+ - The schema system is not a replacement for server-side validation. It protects against accidental misuse and provides defense-in-depth in the browser.