memorio 4.7.1 → 4.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +241 -34
- package/SECURITY.md +10 -10
- package/SUMMARY.md +14 -0
- package/index.cjs +160 -29
- package/index.d.ts +3 -0
- package/index.js +115 -7
- package/llms.txt +119 -28
- package/markdown/CHANGELOG.md +8 -8
- package/markdown/HISTORY.md +192 -0
- package/markdown/INSPECT.md +116 -0
- package/markdown/MEMORY.md +155 -0
- package/markdown/SCHEMA.md +169 -0
- package/markdown/SECURITY.md +1 -1
- package/markdown/TYPED.md +158 -0
- package/package.json +7 -7
- package/types/exports.d.ts +25 -0
- package/types/history.d.ts +27 -0
- package/types/inspect.d.ts +14 -0
- package/types/memorio.d.ts +48 -2
- package/types/memory.d.ts +70 -0
- package/types/schema.d.ts +53 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Typed Stores - Memorio
|
|
2
|
+
|
|
3
|
+
> ✅ **Universal**: Works in Browser, Node.js, Deno, and Edge Workers
|
|
4
|
+
|
|
5
|
+
`memorio.typed<T>()` returns the global `state` proxy cast to a TypeScript type `T`, giving you **compile-time** type safety on every access and mutation.
|
|
6
|
+
|
|
7
|
+
It's a **zero-runtime-cost** wrapper: the returned object is the *exact same* Proxy as `globalThis.state`, just with TypeScript types applied via a generic.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import 'memorio'
|
|
15
|
+
|
|
16
|
+
interface AppState {
|
|
17
|
+
user: { name: string; age: number; email: string }
|
|
18
|
+
theme: 'light' | 'dark'
|
|
19
|
+
items: string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const app = memorio.typed<AppState>()
|
|
23
|
+
|
|
24
|
+
// Type-checked at compile time:
|
|
25
|
+
app.user = { name: 'Sara', age: 30, email: 'sara@test.com' }
|
|
26
|
+
app.theme = 'dark'
|
|
27
|
+
|
|
28
|
+
// TypeScript errors:
|
|
29
|
+
// app.user = { name: 42 } // age missing, name wrong type
|
|
30
|
+
// app.theme = 'purple' // not a valid literal
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Why use typed stores?
|
|
36
|
+
|
|
37
|
+
| Without typed | With `memorio.typed<T>()` |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `state.user = { name: 42 }` — runs silently, bug at runtime | `app.user = { name: 42 }` — TypeScript error at compile time |
|
|
40
|
+
| No autocomplete on `state.user.email` | Full IntelliSense: properties, types, method suggestions |
|
|
41
|
+
| Rename `user` to `profile` — no compiler warning anywhere | Every `app.user` access flagged as an error |
|
|
42
|
+
| AI-generated code lacks guardrails | AI gets autocomplete and type feedback inline |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Combine with Schema Validation
|
|
47
|
+
|
|
48
|
+
Typed stores catch type errors at compile time; schema validation catches invalid values at runtime. Together they form a **defense-in-depth** strategy:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import 'memorio'
|
|
52
|
+
|
|
53
|
+
interface ProfileState {
|
|
54
|
+
profile: { bio: string; avatar?: string }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const app = memorio.typed<ProfileState>()
|
|
58
|
+
|
|
59
|
+
memorio.registerSchema('profile', {
|
|
60
|
+
type: 'object',
|
|
61
|
+
required: ['bio'],
|
|
62
|
+
properties: {
|
|
63
|
+
bio: { type: 'string', min: 1 },
|
|
64
|
+
avatar: { type: 'string' }
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
app.profile = { bio: 'Developer', avatar: 'pic.png' } // ✅ type + schema pass
|
|
69
|
+
app.profile = { avatar: 'pic.png' } // ❌ TypeScript: bio missing
|
|
70
|
+
// ❌ Runtime: bio required
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
See [Schema Validation](SCHEMA.md) for runtime validation details.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Named import variant
|
|
78
|
+
|
|
79
|
+
`typed` is also available as a named export if you prefer explicit dependencies:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { typed } from 'memorio'
|
|
83
|
+
|
|
84
|
+
const app = typed<AppState>()
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The `memorio` namespace object is the same — `import 'memorio'` is the recommended entry, named exports are an alternative.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Full API
|
|
92
|
+
|
|
93
|
+
| Method | Parameters | Returns | Description |
|
|
94
|
+
|--------|-----------|---------|-------------|
|
|
95
|
+
| `memorio.typed<T>()` | Generic type `T` | `T` | Returns the global `state` proxy cast to `T` |
|
|
96
|
+
|
|
97
|
+
The returned object shares the same identity as `globalThis.state`:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const app = memorio.typed<AppState>()
|
|
101
|
+
console.debug(app === state) // true — same Proxy instance
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## React + typed stores
|
|
107
|
+
|
|
108
|
+
Pair with the `useObserver` hook for type-safe, reactive React components:
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
import 'memorio'
|
|
112
|
+
import { useReducer } from 'react'
|
|
113
|
+
|
|
114
|
+
interface AppState {
|
|
115
|
+
user: { name: string; age: number }
|
|
116
|
+
theme: 'light' | 'dark'
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const app = memorio.typed<AppState>()
|
|
120
|
+
|
|
121
|
+
function UserProfile() {
|
|
122
|
+
const [, forceUpdate] = useReducer(x => x + 1, 0)
|
|
123
|
+
|
|
124
|
+
useObserver(forceUpdate, [state.user.name])
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div>
|
|
128
|
+
<h1>{app.user.name}</h1>
|
|
129
|
+
<span>Theme: {app.theme}</span>
|
|
130
|
+
</div>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Best Practices
|
|
138
|
+
|
|
139
|
+
1. **Define your AppState at the root** of your app and import it everywhere:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// types/app-state.ts
|
|
143
|
+
export interface AppState {
|
|
144
|
+
user: { name: string; email: string }
|
|
145
|
+
theme: 'light' | 'dark'
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// anywhere in your app
|
|
151
|
+
import 'memorio'
|
|
152
|
+
import type { AppState } from '../types/app-state'
|
|
153
|
+
const app = memorio.typed<AppState>()
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
2. **Layer schema validation on top** for runtime safety, especially for data coming from APIs or user input.
|
|
157
|
+
|
|
158
|
+
3. **Use alongside `memorio.help()`** to list available globals during development.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "memorio",
|
|
3
3
|
"codeName": "memorio",
|
|
4
|
-
"version": "4.7.
|
|
4
|
+
"version": "4.7.3",
|
|
5
5
|
"description": "Memorio, State + Observer, Store and iDB for an easy life - Cross-platform compatible",
|
|
6
6
|
"main": "./index.cjs",
|
|
7
7
|
"browser": "./index.js",
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
"markdown/**/*",
|
|
53
53
|
"types/**/*",
|
|
54
54
|
"COPYRIGHT.md",
|
|
55
|
-
"index.d.ts",
|
|
56
|
-
"index.cjs",
|
|
57
|
-
"index.js",
|
|
58
|
-
"LICENSE.md",
|
|
59
|
-
"llms.txt",
|
|
60
55
|
"README.md",
|
|
61
56
|
"FUNDING.yml",
|
|
62
57
|
"SECURITY.md",
|
|
63
|
-
"SUMMARY.md"
|
|
58
|
+
"SUMMARY.md",
|
|
59
|
+
"LICENSE.md",
|
|
60
|
+
"index.d.ts",
|
|
61
|
+
"index.cjs",
|
|
62
|
+
"index.js",
|
|
63
|
+
"llms.txt"
|
|
64
64
|
],
|
|
65
65
|
"publishConfig": {
|
|
66
66
|
"access": "public"
|
package/types/exports.d.ts
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
* @see index.ts (runtime re-export)
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
/// <reference path="./schema.d.ts" />
|
|
12
|
+
/// <reference path="./history.d.ts" />
|
|
13
|
+
/// <reference path="./inspect.d.ts" />
|
|
11
14
|
/// <reference path="./memorio.d.ts" />
|
|
12
15
|
/// <reference path="./state.d.ts" />
|
|
13
16
|
/// <reference path="./store.d.ts" />
|
|
@@ -40,6 +43,28 @@ export const isolate: _memorio['isolate']
|
|
|
40
43
|
export const message: (...args: unknown[]) => void
|
|
41
44
|
export const help: () => void
|
|
42
45
|
|
|
46
|
+
export const registerSchema: (path: string, schema: any) => void
|
|
47
|
+
export const validate: (path: string, value: any) => { valid: boolean; errors?: string[] }
|
|
48
|
+
export const unregisterSchema: (path: string) => boolean
|
|
49
|
+
export const listSchemas: () => string[]
|
|
50
|
+
export const typed: <T extends Record<string, any>>() => T
|
|
51
|
+
export const snapshot: () => Record<string, any>
|
|
52
|
+
export const diff: (snap: Record<string, any>) => Array<{ path: string; oldValue: any; newValue: any }>
|
|
53
|
+
export const undo: () => any
|
|
54
|
+
export const redo: () => any
|
|
55
|
+
export const canUndo: () => boolean
|
|
56
|
+
export const canRedo: () => boolean
|
|
57
|
+
export const rollback: (snap: Record<string, any>) => void
|
|
58
|
+
export const trace: () => any[]
|
|
59
|
+
export const enableHistory: (enabled?: boolean) => void
|
|
60
|
+
export const clearHistory: () => void
|
|
61
|
+
export const clearRedo: () => void
|
|
62
|
+
export const stateKeys: () => string[]
|
|
63
|
+
export const pathExists: (path: string) => boolean
|
|
64
|
+
export const stateType: (path: string) => string
|
|
65
|
+
export const stateGet: (path: string) => any
|
|
66
|
+
export const stateSchema: () => Array<{ path: string; type: string; defined: boolean }>
|
|
67
|
+
|
|
43
68
|
export const propertyName: (container: any, object: any) => string | null
|
|
44
69
|
export const internal: {
|
|
45
70
|
debug: boolean
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// MEMORIO HISTORY TYPES
|
|
2
|
+
/// Ambient declarations for the snapshot / undo / redo / trace API.
|
|
3
|
+
|
|
4
|
+
///
|
|
5
|
+
// A single recorded state mutation.
|
|
6
|
+
///
|
|
7
|
+
interface _mutationRecord {
|
|
8
|
+
/** Dotted state path (e.g. 'user.name'). */
|
|
9
|
+
path: string
|
|
10
|
+
/** 'set' or 'delete'. */
|
|
11
|
+
action: 'set' | 'delete'
|
|
12
|
+
/** The new value written (for 'set'), undefined for 'delete'. */
|
|
13
|
+
newValue: any
|
|
14
|
+
/** The previous value before the mutation. */
|
|
15
|
+
previousValue: any
|
|
16
|
+
/** Epoch timestamp (ms) when the mutation occurred. */
|
|
17
|
+
timestamp: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
///
|
|
21
|
+
// Result of diffing a snapshot against current state.
|
|
22
|
+
///
|
|
23
|
+
interface _diffEntry {
|
|
24
|
+
path: string
|
|
25
|
+
oldValue: any
|
|
26
|
+
newValue: any
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// MEMORIO INSPECT TYPES
|
|
2
|
+
/// Ambient declarations for the state introspection API.
|
|
3
|
+
|
|
4
|
+
///
|
|
5
|
+
// Schema report entry describing a single state path.
|
|
6
|
+
///
|
|
7
|
+
interface _stateSchemaEntry {
|
|
8
|
+
/** Dotted path relative to `state`. */
|
|
9
|
+
path: string
|
|
10
|
+
/** Runtime type: 'string', 'number', 'boolean', 'object', 'array', 'undefined'. */
|
|
11
|
+
type: string
|
|
12
|
+
/** Whether the path resolves to a defined value. */
|
|
13
|
+
defined: boolean
|
|
14
|
+
}
|
package/types/memorio.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
MemoryEntry,
|
|
3
|
+
RememberOptions,
|
|
4
|
+
RecallOptions,
|
|
5
|
+
ContextOptions,
|
|
6
|
+
ContextEntry,
|
|
7
|
+
MemoryStats
|
|
8
|
+
} from './memory'
|
|
9
|
+
|
|
1
10
|
/**
|
|
2
11
|
* Environment capabilities
|
|
3
12
|
*/
|
|
@@ -60,10 +69,47 @@ interface _memorio {
|
|
|
60
69
|
session: any
|
|
61
70
|
cache: any
|
|
62
71
|
}
|
|
63
|
-
|
|
72
|
+
help?: () => void
|
|
73
|
+
// Schema validation
|
|
74
|
+
registerSchema?: (path: string, schema: any) => void
|
|
75
|
+
validate?: (path: string, value: any) => { valid: boolean; errors?: string[] }
|
|
76
|
+
unregisterSchema?: (path: string) => boolean
|
|
77
|
+
listSchemas?: () => string[]
|
|
78
|
+
// Typed store
|
|
79
|
+
typed?: <T extends Record<string, any>>() => T
|
|
80
|
+
// History / snapshot / undo / redo / trace
|
|
81
|
+
snapshot?: () => Record<string, any>
|
|
82
|
+
diff?: (snap: Record<string, any>) => Array<{ path: string; oldValue: any; newValue: any }>
|
|
83
|
+
undo?: () => _mutationRecord | undefined
|
|
84
|
+
redo?: () => _mutationRecord | undefined
|
|
85
|
+
canUndo?: () => boolean
|
|
86
|
+
canRedo?: () => boolean
|
|
87
|
+
rollback?: (snap: Record<string, any>) => void
|
|
88
|
+
trace?: () => _mutationRecord[]
|
|
89
|
+
enableHistory?: (enabled?: boolean) => void
|
|
90
|
+
clearHistory?: () => void
|
|
91
|
+
clearRedo?: () => void
|
|
92
|
+
// Introspection
|
|
93
|
+
stateKeys?: () => string[]
|
|
94
|
+
pathExists?: (path: string) => boolean
|
|
95
|
+
stateType?: (path: string) => string
|
|
96
|
+
stateGet?: (path: string) => any
|
|
97
|
+
stateSchema?: () => Array<{ path: string; type: string; defined: boolean }>
|
|
98
|
+
memory?: MemoryAPI
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface MemoryAPI {
|
|
102
|
+
remember<T>(key: string, value: T, opts?: RememberOptions<T>): Promise<void>
|
|
103
|
+
recall<T>(query: string, opts?: RecallOptions): Promise<T | null>
|
|
104
|
+
update(key: string, value: any, opts?: Partial<RememberOptions>): Promise<void>
|
|
105
|
+
forget(key: string): Promise<void>
|
|
106
|
+
context(opts?: ContextOptions): Promise<ContextEntry[]>
|
|
107
|
+
stats(): Promise<MemoryStats>
|
|
108
|
+
forgetExpired(): Promise<number>
|
|
109
|
+
clear(): Promise<void>
|
|
64
110
|
}
|
|
65
111
|
|
|
66
|
-
type memorio = _memorio
|
|
112
|
+
type memorio = _memorio
|
|
67
113
|
declare var memorio: _memorio
|
|
68
114
|
|
|
69
115
|
interface GlobalMemorio {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export type MemoryScope = 'hot' | 'session' | 'local' | 'durable'
|
|
2
|
+
|
|
3
|
+
export type MemoryType =
|
|
4
|
+
| 'fact'
|
|
5
|
+
| 'preference'
|
|
6
|
+
| 'decision'
|
|
7
|
+
| 'task'
|
|
8
|
+
| 'context'
|
|
9
|
+
|
|
10
|
+
export type MemoryStatus = 'active' | 'obsolete' | 'superseded'
|
|
11
|
+
|
|
12
|
+
export interface MemoryEntry<T = any> {
|
|
13
|
+
id: string
|
|
14
|
+
key: string
|
|
15
|
+
value: T
|
|
16
|
+
type: MemoryType
|
|
17
|
+
confidence: number
|
|
18
|
+
scope: MemoryScope
|
|
19
|
+
ttl?: number | null
|
|
20
|
+
tags: string[]
|
|
21
|
+
source?: string
|
|
22
|
+
status: MemoryStatus
|
|
23
|
+
createdAt: number
|
|
24
|
+
lastConfirmedAt: number
|
|
25
|
+
supersededId?: string | null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RememberOptions<T = any> {
|
|
29
|
+
id?: string
|
|
30
|
+
type?: MemoryType
|
|
31
|
+
confidence?: number
|
|
32
|
+
scope?: MemoryScope
|
|
33
|
+
ttl?: number | null
|
|
34
|
+
tags?: string | string[]
|
|
35
|
+
source?: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface RecallOptions {
|
|
39
|
+
type?: MemoryType | MemoryType[]
|
|
40
|
+
tags?: string | string[]
|
|
41
|
+
minConfidence?: number
|
|
42
|
+
includeObsolete?: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ContextOptions {
|
|
46
|
+
tags?: string | string[]
|
|
47
|
+
types?: MemoryType | MemoryType[]
|
|
48
|
+
minConfidence?: number
|
|
49
|
+
maxEntries?: number
|
|
50
|
+
scopes?: MemoryScope[]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ContextEntry {
|
|
54
|
+
key: string
|
|
55
|
+
value: any
|
|
56
|
+
type: MemoryType
|
|
57
|
+
confidence: number
|
|
58
|
+
scope: MemoryScope
|
|
59
|
+
tags: string[]
|
|
60
|
+
age: number
|
|
61
|
+
accessCount: number
|
|
62
|
+
lastAccessedAt: number
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface MemoryStats {
|
|
66
|
+
total: number
|
|
67
|
+
byScope: Record<MemoryScope, number>
|
|
68
|
+
byType: Partial<Record<MemoryType, number>>
|
|
69
|
+
expired: number
|
|
70
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/// MEMORIO SCHEMA TYPES
|
|
2
|
+
/// Ambient declarations for the schema validation system.
|
|
3
|
+
|
|
4
|
+
///
|
|
5
|
+
// Schema type — describes the expected runtime shape of a value.
|
|
6
|
+
///
|
|
7
|
+
interface _schemaDef {
|
|
8
|
+
/** Expected runtime type of the value. */
|
|
9
|
+
type?: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'any'
|
|
10
|
+
/** Required property names when type is 'object'. */
|
|
11
|
+
required?: string[]
|
|
12
|
+
/** Nested property schemas (validated recursively). */
|
|
13
|
+
properties?: Record<string, _schemaDef>
|
|
14
|
+
/** Minimum: value for numbers, length for strings. */
|
|
15
|
+
min?: number
|
|
16
|
+
/** Maximum: value for numbers, length for strings. */
|
|
17
|
+
max?: number
|
|
18
|
+
/** Regex pattern a string value must match. */
|
|
19
|
+
pattern?: RegExp
|
|
20
|
+
/** Whitelist of allowed values. */
|
|
21
|
+
enum?: any[]
|
|
22
|
+
/** Custom validator: return true for pass, or a string describing the error. */
|
|
23
|
+
validator?: (value: any) => boolean | string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
///
|
|
27
|
+
// Result of a validation check.
|
|
28
|
+
///
|
|
29
|
+
interface _validationResult {
|
|
30
|
+
/** Whether the value passed all checks. */
|
|
31
|
+
valid: boolean
|
|
32
|
+
/** Array of human-readable error strings (present when valid is false). */
|
|
33
|
+
errors?: string[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
///
|
|
37
|
+
// Schema namespace — the public `memorio.schema`-style helpers live on `memorio`.
|
|
38
|
+
///
|
|
39
|
+
interface _schemaHelpers {
|
|
40
|
+
/** Registers a schema (or custom validator) for a state path. */
|
|
41
|
+
register: (path: string, schema: _schemaDef | ((value: any) => boolean | string)) => void
|
|
42
|
+
/** Validates a value against a registered schema. */
|
|
43
|
+
validate: (path: string, value: any) => _validationResult
|
|
44
|
+
/** Removes a previously registered schema. */
|
|
45
|
+
unregister: (path: string) => boolean
|
|
46
|
+
/** Lists all registered schema paths. */
|
|
47
|
+
list: () => string[]
|
|
48
|
+
/** Retrieves the schema registered for a path. */
|
|
49
|
+
get: (path: string) => _schemaDef | undefined
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
declare var _schemaDef: _schemaDef
|
|
53
|
+
declare var _validationResult: _validationResult
|