@hardlydifficult/state-tracker 2.0.11 → 2.0.13
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 +169 -14
- package/dist/StateTracker.d.ts +26 -0
- package/dist/StateTracker.d.ts.map +1 -1
- package/dist/StateTracker.js +98 -37
- package/dist/StateTracker.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @hardlydifficult/state-tracker
|
|
2
2
|
|
|
3
|
-
Atomic JSON state persistence with sync/async APIs, auto-save debouncing, and graceful
|
|
3
|
+
Atomic JSON state persistence with sync/async APIs, auto-save debouncing, typed migrations, key sanitization, and graceful fallback to in-memory mode.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -13,28 +13,119 @@ npm install @hardlydifficult/state-tracker
|
|
|
13
13
|
```typescript
|
|
14
14
|
import { StateTracker } from "@hardlydifficult/state-tracker";
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
interface AppConfig {
|
|
17
|
+
version: string;
|
|
18
|
+
theme: "light" | "dark";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const tracker = new StateTracker<AppConfig>({
|
|
22
|
+
key: "app-config",
|
|
23
|
+
default: { version: "1.0.0", theme: "light" },
|
|
19
24
|
autoSaveMs: 1000,
|
|
20
25
|
});
|
|
21
26
|
|
|
22
|
-
//
|
|
23
|
-
tracker.
|
|
27
|
+
await tracker.loadAsync(); // Loads from disk, enables isPersistent tracking
|
|
28
|
+
tracker.update({ theme: "dark" }); // Auto-saves after 1s of inactivity
|
|
29
|
+
console.log(tracker.state); // { version: "1.0.0", theme: "dark" }
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Core Features
|
|
33
|
+
|
|
34
|
+
### State Persistence
|
|
35
|
+
|
|
36
|
+
The `StateTracker` class provides atomic JSON-based state persistence with auto-save support.
|
|
37
|
+
|
|
38
|
+
| Option | Type | Description |
|
|
39
|
+
|--------|------|-------------|
|
|
40
|
+
| `key` | `string` | Unique identifier for the state file (alphanumeric, hyphens, underscores only) |
|
|
41
|
+
| `default` | `T` | Default state if no persisted data exists |
|
|
42
|
+
| `stateDirectory` | `string` (default: `~/.app-state` or `$STATE_TRACKER_DIR`) | Directory to store state files |
|
|
43
|
+
| `autoSaveMs` | `number` (default: `0`) | Debounce delay in ms for auto-save |
|
|
44
|
+
| `migration` | `Migration<T>` (deprecated) | Optional migration function (use `loadOrDefault()` with `defineStateMigration` instead) |
|
|
45
|
+
| `onEvent` | `(event: StateTrackerEvent) => void` | Callback for internal events (debug/info/warn/error) |
|
|
24
46
|
|
|
25
|
-
|
|
26
|
-
tracker.update({ theme: "dark" });
|
|
27
|
-
// State is saved automatically after 1 second of inactivity
|
|
47
|
+
#### Async vs Sync Persistence
|
|
28
48
|
|
|
29
|
-
|
|
30
|
-
|
|
49
|
+
```typescript
|
|
50
|
+
// Async (recommended for production)
|
|
51
|
+
await tracker.loadAsync();
|
|
52
|
+
await tracker.saveAsync();
|
|
53
|
+
|
|
54
|
+
// Sync fallback (throws if file access fails)
|
|
55
|
+
tracker.load();
|
|
56
|
+
tracker.save({ theme: "dark" });
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Key Sanitization
|
|
60
|
+
|
|
61
|
+
Invalid keys (including `__proto__`, `constructor`, `prototype`) are sanitized automatically to prevent prototype pollution and path traversal.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
tracker.set("__proto__", { malicious: true }); // ignored
|
|
65
|
+
tracker.set("normalKey", "value"); // works as expected
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Typed Migrations
|
|
69
|
+
|
|
70
|
+
Support for typed migrations from older state formats using `loadOrDefault()` and `defineStateMigration()`.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { defineStateMigration } from "@hardlydifficult/state-tracker";
|
|
74
|
+
|
|
75
|
+
interface LegacyConfig {
|
|
76
|
+
theme: "light" | "dark";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface Config {
|
|
80
|
+
version: string;
|
|
81
|
+
theme: "light" | "dark";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const legacyMigration = defineStateMigration<Config, LegacyConfig>({
|
|
85
|
+
name: "legacy-config",
|
|
86
|
+
isLegacy(input): input is LegacyConfig {
|
|
87
|
+
return (
|
|
88
|
+
typeof input === "object" &&
|
|
89
|
+
input !== null &&
|
|
90
|
+
!Array.isArray(input) &&
|
|
91
|
+
"theme" in input &&
|
|
92
|
+
!("version" in input)
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
migrate(legacy) {
|
|
96
|
+
return { version: "1.0.0", ...legacy };
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const tracker = new StateTracker<Config>({
|
|
101
|
+
key: "config",
|
|
102
|
+
default: { version: "1.1.0", theme: "dark" },
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const state = tracker.loadOrDefault({ migrations: [legacyMigration] });
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Graceful Degradation
|
|
109
|
+
|
|
110
|
+
If persistent storage fails (e.g., due to permissions or path issues), the tracker falls back to in-memory mode without throwing errors.
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
const tracker = new StateTracker<AppConfig>({
|
|
114
|
+
key: "config",
|
|
115
|
+
default: { version: "1.0.0", theme: "light" },
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
await tracker.loadAsync();
|
|
119
|
+
if (!tracker.isPersistent) {
|
|
120
|
+
console.warn("Running in-memory mode");
|
|
121
|
+
}
|
|
31
122
|
```
|
|
32
123
|
|
|
33
124
|
## State Management
|
|
34
125
|
|
|
35
126
|
The `StateTracker` class provides a robust interface for managing persistent application state.
|
|
36
127
|
|
|
37
|
-
### Constructor
|
|
128
|
+
### Constructor Options
|
|
38
129
|
|
|
39
130
|
| Option | Type | Default | Description |
|
|
40
131
|
|--------|------|---------|-------------|
|
|
@@ -42,6 +133,7 @@ The `StateTracker` class provides a robust interface for managing persistent app
|
|
|
42
133
|
| `default` | `T` | — | Default state value used if no persisted state exists |
|
|
43
134
|
| `stateDirectory` | `string` | `~/.app-state` or `$STATE_TRACKER_DIR` | Directory to store state files |
|
|
44
135
|
| `autoSaveMs` | `number` | `0` | Debounce delay (ms) for auto-save after state changes |
|
|
136
|
+
| `migration` | `Migration<T>` | — | **Deprecated:** Use `defineStateMigration` with `loadOrDefault` instead |
|
|
45
137
|
| `onEvent` | `(event: StateTrackerEvent) => void` | `undefined` | Callback for internal events (debug/info/warn/error) |
|
|
46
138
|
|
|
47
139
|
### State Accessors
|
|
@@ -74,6 +166,44 @@ const tracker = new StateTracker({
|
|
|
74
166
|
const config = tracker.load(); // Loads from disk or uses default
|
|
75
167
|
```
|
|
76
168
|
|
|
169
|
+
#### `loadOrDefault(options?): T`
|
|
170
|
+
Explicit "safe load" convenience. Behaves like `load()` and supports typed legacy migrations.
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
import { defineStateMigration, StateTracker } from "@hardlydifficult/state-tracker";
|
|
174
|
+
|
|
175
|
+
interface LegacySyncState {
|
|
176
|
+
offset: number;
|
|
177
|
+
completedIds: string[];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const tracker = new StateTracker({
|
|
181
|
+
key: "sync-state",
|
|
182
|
+
default: { cursor: 0, done: [] as string[] },
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const legacyMigration = defineStateMigration<
|
|
186
|
+
{ cursor: number; done: string[] },
|
|
187
|
+
LegacySyncState
|
|
188
|
+
>({
|
|
189
|
+
name: "sync-state-v0",
|
|
190
|
+
isLegacy(input): input is LegacySyncState {
|
|
191
|
+
return (
|
|
192
|
+
input !== null &&
|
|
193
|
+
typeof input === "object" &&
|
|
194
|
+
!Array.isArray(input) &&
|
|
195
|
+
typeof (input as Record<string, unknown>).offset === "number" &&
|
|
196
|
+
Array.isArray((input as Record<string, unknown>).completedIds)
|
|
197
|
+
);
|
|
198
|
+
},
|
|
199
|
+
migrate(legacy) {
|
|
200
|
+
return { cursor: legacy.offset, done: legacy.completedIds };
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const state = tracker.loadOrDefault({ migrations: [legacyMigration] });
|
|
205
|
+
```
|
|
206
|
+
|
|
77
207
|
#### `save(value: T): void`
|
|
78
208
|
Synchronous atomic save using temp file + rename.
|
|
79
209
|
|
|
@@ -82,6 +212,16 @@ tracker.save({ version: 2 });
|
|
|
82
212
|
// File is updated atomically; previous state preserved if crash occurs mid-write
|
|
83
213
|
```
|
|
84
214
|
|
|
215
|
+
#### `saveWithMeta(value: T, meta?: Record<string, unknown>): void`
|
|
216
|
+
Synchronous atomic save with optional metadata in the envelope.
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
tracker.saveWithMeta(
|
|
220
|
+
{ version: 3 },
|
|
221
|
+
{ source: "sync-script", reason: "manual-run" }
|
|
222
|
+
);
|
|
223
|
+
```
|
|
224
|
+
|
|
85
225
|
#### `loadAsync(): Promise<void>`
|
|
86
226
|
Async state load with graceful degradation. Sets `isPersistent = false` on failure instead of throwing.
|
|
87
227
|
|
|
@@ -170,7 +310,8 @@ await tracker.loadAsync();
|
|
|
170
310
|
```json
|
|
171
311
|
{
|
|
172
312
|
"value": { "theme": "dark", "notifications": true },
|
|
173
|
-
"lastUpdated": "2024-05-01T12:00:00.000Z"
|
|
313
|
+
"lastUpdated": "2024-05-01T12:00:00.000Z",
|
|
314
|
+
"meta": { "source": "sync-script" }
|
|
174
315
|
}
|
|
175
316
|
```
|
|
176
317
|
|
|
@@ -185,6 +326,9 @@ The tracker automatically detects and merges legacy raw JSON objects with defaul
|
|
|
185
326
|
|
|
186
327
|
After the first `saveAsync()`, files are rewritten in the v2 envelope format.
|
|
187
328
|
|
|
329
|
+
For custom legacy formats, use typed migrations with `defineStateMigration(...)`
|
|
330
|
+
and pass them to `loadOrDefault({ migrations })`.
|
|
331
|
+
|
|
188
332
|
## Auto-Save Behavior
|
|
189
333
|
|
|
190
334
|
When `autoSaveMs > 0`, state changes are debounced:
|
|
@@ -237,4 +381,15 @@ STATE_TRACKER_DIR=/custom/path npm start
|
|
|
237
381
|
- **Key sanitization** to prevent path traversal (alphanumeric, hyphens, underscores only)
|
|
238
382
|
- **Graceful degradation** — runs in-memory when disk is unavailable
|
|
239
383
|
- **Auto-save** — debounced saves after state mutations
|
|
240
|
-
- **Legacy format support** — reads both v1 envelope format and legacy PersistentStore formats
|
|
384
|
+
- **Legacy format support** — reads both v1 envelope format and legacy PersistentStore formats
|
|
385
|
+
- **Typed migration helper** — declarative migration rules for old JSON shapes
|
|
386
|
+
- **Optional save metadata** — annotate saved state with `saveWithMeta(...)`
|
|
387
|
+
- **API consistency** — all operations work seamlessly across sync/async modes
|
|
388
|
+
|
|
389
|
+
## Appendix: Platform Behavior
|
|
390
|
+
|
|
391
|
+
| Environment | Persistence | Fallback Behavior |
|
|
392
|
+
|-------------|-------------|-------------------|
|
|
393
|
+
| Node.js | ✅ File system access | Falls back to memory on errors |
|
|
394
|
+
| Browser | ❌ No file system access | Always in-memory only |
|
|
395
|
+
| Bun/Deno | ⚠️ Experimental support | Depends on environment capabilities |
|
package/dist/StateTracker.d.ts
CHANGED
|
@@ -11,6 +11,19 @@ export interface StateTrackerOptions<T> {
|
|
|
11
11
|
autoSaveMs?: number;
|
|
12
12
|
onEvent?: (event: StateTrackerEvent) => void;
|
|
13
13
|
}
|
|
14
|
+
export interface StateTrackerMigration<TCurrent, TLegacy = unknown> {
|
|
15
|
+
readonly name?: string;
|
|
16
|
+
isLegacy(input: unknown): input is TLegacy;
|
|
17
|
+
migrate(legacy: TLegacy): TCurrent;
|
|
18
|
+
}
|
|
19
|
+
export interface StateTrackerLoadOrDefaultOptions<T> {
|
|
20
|
+
migrations?: readonly StateTrackerMigration<T>[];
|
|
21
|
+
}
|
|
22
|
+
export type StateTrackerSaveMeta = Record<string, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
export declare function defineStateMigration<TCurrent, TLegacy>(migration: StateTrackerMigration<TCurrent, TLegacy>): StateTrackerMigration<TCurrent, TLegacy>;
|
|
14
27
|
/** Atomic JSON state persistence with file-based storage, auto-save, and graceful degradation to in-memory mode. */
|
|
15
28
|
export declare class StateTracker<T> {
|
|
16
29
|
private readonly filePath;
|
|
@@ -29,6 +42,11 @@ export declare class StateTracker<T> {
|
|
|
29
42
|
/** Whether storage is working */
|
|
30
43
|
get isPersistent(): boolean;
|
|
31
44
|
private emit;
|
|
45
|
+
private buildEnvelope;
|
|
46
|
+
private writeEnvelopeSync;
|
|
47
|
+
private mergeWithDefaults;
|
|
48
|
+
private extractMigrationCandidate;
|
|
49
|
+
private tryApplyMigrations;
|
|
32
50
|
/**
|
|
33
51
|
* Extract value from parsed JSON content.
|
|
34
52
|
* Handles v1 envelope format ({value, lastUpdated}) and legacy
|
|
@@ -37,8 +55,16 @@ export declare class StateTracker<T> {
|
|
|
37
55
|
private extractValue;
|
|
38
56
|
/** Sync load — v1 compatible. Also updates internal state cache. */
|
|
39
57
|
load(): T;
|
|
58
|
+
/**
|
|
59
|
+
* Sync load that explicitly falls back to defaults if disk state is missing,
|
|
60
|
+
* unreadable, or invalid. Supports optional typed legacy migrations.
|
|
61
|
+
*/
|
|
62
|
+
loadOrDefault(options?: StateTrackerLoadOrDefaultOptions<T>): T;
|
|
63
|
+
private loadSync;
|
|
40
64
|
/** Sync save — v1 compatible. Also updates internal state cache. */
|
|
41
65
|
save(value: T): void;
|
|
66
|
+
/** Sync save with optional metadata in the JSON envelope. */
|
|
67
|
+
saveWithMeta(value: T, meta?: StateTrackerSaveMeta): void;
|
|
42
68
|
/**
|
|
43
69
|
* Async load with graceful degradation.
|
|
44
70
|
* Sets _storageAvailable false on failure instead of throwing.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StateTracker.d.ts","sourceRoot":"","sources":["../src/StateTracker.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEzE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,CAAC,CAAC;IACX,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC9C;AAED,oHAAoH;AACpH,qBAAa,YAAY,CAAC,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAI;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAqC;IAE9D,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,SAAS,CAA8C;IAE/D,OAAO,CAAC,MAAM,CAAC,WAAW;IAa1B,OAAO,CAAC,MAAM,CAAC,wBAAwB;gBAQ3B,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAoB3C,kDAAkD;IAClD,IAAI,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,CAEvB;IAED,iCAAiC;IACjC,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,OAAO,CAAC,IAAI;IAUZ;;;;OAIG;IACH,OAAO,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"StateTracker.d.ts","sourceRoot":"","sources":["../src/StateTracker.ts"],"names":[],"mappings":"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"}
|
package/dist/StateTracker.js
CHANGED
|
@@ -34,10 +34,17 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.StateTracker = void 0;
|
|
37
|
+
exports.defineStateMigration = defineStateMigration;
|
|
37
38
|
const fs = __importStar(require("fs"));
|
|
38
39
|
const fsPromises = __importStar(require("fs/promises"));
|
|
39
40
|
const os = __importStar(require("os"));
|
|
40
41
|
const path = __importStar(require("path"));
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
*/
|
|
45
|
+
function defineStateMigration(migration) {
|
|
46
|
+
return migration;
|
|
47
|
+
}
|
|
41
48
|
/** Atomic JSON state persistence with file-based storage, auto-save, and graceful degradation to in-memory mode. */
|
|
42
49
|
class StateTracker {
|
|
43
50
|
filePath;
|
|
@@ -96,12 +103,80 @@ class StateTracker {
|
|
|
96
103
|
this.onEvent({ level, message, context });
|
|
97
104
|
}
|
|
98
105
|
}
|
|
106
|
+
buildEnvelope(value, meta) {
|
|
107
|
+
const envelope = {
|
|
108
|
+
value,
|
|
109
|
+
lastUpdated: new Date().toISOString(),
|
|
110
|
+
};
|
|
111
|
+
if (meta !== undefined) {
|
|
112
|
+
envelope.meta = structuredClone(meta);
|
|
113
|
+
}
|
|
114
|
+
return envelope;
|
|
115
|
+
}
|
|
116
|
+
writeEnvelopeSync(envelope) {
|
|
117
|
+
const tempFilePath = `${this.filePath}.tmp`;
|
|
118
|
+
fs.writeFileSync(tempFilePath, JSON.stringify(envelope, null, 2), "utf-8");
|
|
119
|
+
fs.renameSync(tempFilePath, this.filePath);
|
|
120
|
+
}
|
|
121
|
+
mergeWithDefaults(value) {
|
|
122
|
+
if (value !== null &&
|
|
123
|
+
typeof value === "object" &&
|
|
124
|
+
typeof this.defaultValue === "object" &&
|
|
125
|
+
this.defaultValue !== null &&
|
|
126
|
+
!Array.isArray(value)) {
|
|
127
|
+
return {
|
|
128
|
+
...structuredClone(this.defaultValue),
|
|
129
|
+
...value,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return value;
|
|
133
|
+
}
|
|
134
|
+
extractMigrationCandidate(parsed) {
|
|
135
|
+
if (parsed !== null &&
|
|
136
|
+
typeof parsed === "object" &&
|
|
137
|
+
!Array.isArray(parsed) &&
|
|
138
|
+
"value" in parsed) {
|
|
139
|
+
return parsed.value;
|
|
140
|
+
}
|
|
141
|
+
return parsed;
|
|
142
|
+
}
|
|
143
|
+
tryApplyMigrations(parsed, migrations) {
|
|
144
|
+
if (migrations === undefined || migrations.length === 0) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
const candidate = this.extractMigrationCandidate(parsed);
|
|
148
|
+
for (const migration of migrations) {
|
|
149
|
+
if (!migration.isLegacy(candidate)) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const migrated = migration.migrate(candidate);
|
|
154
|
+
this.emit("info", "Migrated legacy state payload", {
|
|
155
|
+
migration: migration.name ?? "anonymous",
|
|
156
|
+
});
|
|
157
|
+
return this.mergeWithDefaults(migrated);
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
161
|
+
this.emit("warn", "Legacy state migration failed", {
|
|
162
|
+
migration: migration.name ?? "anonymous",
|
|
163
|
+
error: errorMessage,
|
|
164
|
+
});
|
|
165
|
+
return structuredClone(this.defaultValue);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
99
170
|
/**
|
|
100
171
|
* Extract value from parsed JSON content.
|
|
101
172
|
* Handles v1 envelope format ({value, lastUpdated}) and legacy
|
|
102
173
|
* PersistentStore format (raw T without envelope, merged with defaults).
|
|
103
174
|
*/
|
|
104
|
-
extractValue(parsed) {
|
|
175
|
+
extractValue(parsed, migrations) {
|
|
176
|
+
const migrated = this.tryApplyMigrations(parsed, migrations);
|
|
177
|
+
if (migrated !== undefined) {
|
|
178
|
+
return migrated;
|
|
179
|
+
}
|
|
105
180
|
if (parsed !== null &&
|
|
106
181
|
typeof parsed === "object" &&
|
|
107
182
|
!Array.isArray(parsed) &&
|
|
@@ -111,17 +186,7 @@ class StateTracker {
|
|
|
111
186
|
if (envelope.value === undefined) {
|
|
112
187
|
return structuredClone(this.defaultValue);
|
|
113
188
|
}
|
|
114
|
-
|
|
115
|
-
typeof envelope.value === "object" &&
|
|
116
|
-
typeof this.defaultValue === "object" &&
|
|
117
|
-
this.defaultValue !== null &&
|
|
118
|
-
!Array.isArray(envelope.value)) {
|
|
119
|
-
return {
|
|
120
|
-
...structuredClone(this.defaultValue),
|
|
121
|
-
...envelope.value,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
return envelope.value;
|
|
189
|
+
return this.mergeWithDefaults(envelope.value);
|
|
125
190
|
}
|
|
126
191
|
// Legacy PersistentStore format: raw T without envelope
|
|
127
192
|
// Only merge if T is an object type
|
|
@@ -130,16 +195,23 @@ class StateTracker {
|
|
|
130
195
|
typeof this.defaultValue === "object" &&
|
|
131
196
|
this.defaultValue !== null &&
|
|
132
197
|
!Array.isArray(parsed)) {
|
|
133
|
-
return
|
|
134
|
-
...structuredClone(this.defaultValue),
|
|
135
|
-
...parsed,
|
|
136
|
-
};
|
|
198
|
+
return this.mergeWithDefaults(parsed);
|
|
137
199
|
}
|
|
138
200
|
// Fallback to defaults
|
|
139
201
|
return structuredClone(this.defaultValue);
|
|
140
202
|
}
|
|
141
203
|
/** Sync load — v1 compatible. Also updates internal state cache. */
|
|
142
204
|
load() {
|
|
205
|
+
return this.loadSync();
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Sync load that explicitly falls back to defaults if disk state is missing,
|
|
209
|
+
* unreadable, or invalid. Supports optional typed legacy migrations.
|
|
210
|
+
*/
|
|
211
|
+
loadOrDefault(options) {
|
|
212
|
+
return this.loadSync(options?.migrations);
|
|
213
|
+
}
|
|
214
|
+
loadSync(migrations) {
|
|
143
215
|
this._loaded = true;
|
|
144
216
|
this._storageAvailable = true;
|
|
145
217
|
if (!fs.existsSync(this.filePath)) {
|
|
@@ -149,7 +221,7 @@ class StateTracker {
|
|
|
149
221
|
try {
|
|
150
222
|
const data = fs.readFileSync(this.filePath, "utf-8");
|
|
151
223
|
const parsed = JSON.parse(data);
|
|
152
|
-
this._state = this.extractValue(parsed);
|
|
224
|
+
this._state = this.extractValue(parsed, migrations);
|
|
153
225
|
return this._state;
|
|
154
226
|
}
|
|
155
227
|
catch {
|
|
@@ -159,15 +231,14 @@ class StateTracker {
|
|
|
159
231
|
}
|
|
160
232
|
/** Sync save — v1 compatible. Also updates internal state cache. */
|
|
161
233
|
save(value) {
|
|
234
|
+
this.saveWithMeta(value);
|
|
235
|
+
}
|
|
236
|
+
/** Sync save with optional metadata in the JSON envelope. */
|
|
237
|
+
saveWithMeta(value, meta) {
|
|
162
238
|
this.cancelPendingSave();
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
lastUpdated: new Date().toISOString(),
|
|
167
|
-
};
|
|
168
|
-
const tempFilePath = `${this.filePath}.tmp`;
|
|
169
|
-
fs.writeFileSync(tempFilePath, JSON.stringify(state, null, 2), "utf-8");
|
|
170
|
-
fs.renameSync(tempFilePath, this.filePath);
|
|
239
|
+
const clonedValue = structuredClone(value);
|
|
240
|
+
this._state = clonedValue;
|
|
241
|
+
this.writeEnvelopeSync(this.buildEnvelope(clonedValue, meta));
|
|
171
242
|
}
|
|
172
243
|
/**
|
|
173
244
|
* Async load with graceful degradation.
|
|
@@ -218,12 +289,8 @@ class StateTracker {
|
|
|
218
289
|
return;
|
|
219
290
|
}
|
|
220
291
|
try {
|
|
221
|
-
const state = {
|
|
222
|
-
value: this._state,
|
|
223
|
-
lastUpdated: new Date().toISOString(),
|
|
224
|
-
};
|
|
225
292
|
const tempFilePath = `${this.filePath}.tmp`;
|
|
226
|
-
await fsPromises.writeFile(tempFilePath, JSON.stringify(
|
|
293
|
+
await fsPromises.writeFile(tempFilePath, JSON.stringify(this.buildEnvelope(this._state), null, 2), "utf-8");
|
|
227
294
|
await fsPromises.rename(tempFilePath, this.filePath);
|
|
228
295
|
this.emit("debug", "Saved state to disk", { path: this.filePath });
|
|
229
296
|
}
|
|
@@ -269,13 +336,7 @@ class StateTracker {
|
|
|
269
336
|
this.saveTimer = null;
|
|
270
337
|
// Use sync save to avoid issues with untracked promises
|
|
271
338
|
try {
|
|
272
|
-
|
|
273
|
-
value: this._state,
|
|
274
|
-
lastUpdated: new Date().toISOString(),
|
|
275
|
-
};
|
|
276
|
-
const tempFilePath = `${this.filePath}.tmp`;
|
|
277
|
-
fs.writeFileSync(tempFilePath, JSON.stringify(state, null, 2), "utf-8");
|
|
278
|
-
fs.renameSync(tempFilePath, this.filePath);
|
|
339
|
+
this.writeEnvelopeSync(this.buildEnvelope(this._state));
|
|
279
340
|
this.emit("debug", "Auto-saved state to disk", {
|
|
280
341
|
path: this.filePath,
|
|
281
342
|
});
|
package/dist/StateTracker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StateTracker.js","sourceRoot":"","sources":["../src/StateTracker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"StateTracker.js","sourceRoot":"","sources":["../src/StateTracker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** Persistent state with auto-save to disk. */
|
|
2
|
-
export { StateTracker, type StateTrackerOptions, type StateTrackerEvent, type StateTrackerEventLevel, } from "./StateTracker";
|
|
2
|
+
export { StateTracker, defineStateMigration, type StateTrackerOptions, type StateTrackerEvent, type StateTrackerEventLevel, type StateTrackerLoadOrDefaultOptions, type StateTrackerMigration, type StateTrackerSaveMeta, } from "./StateTracker";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EACL,YAAY,EACZ,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,gCAAgC,EACrC,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.StateTracker = void 0;
|
|
3
|
+
exports.defineStateMigration = exports.StateTracker = void 0;
|
|
4
4
|
/** Persistent state with auto-save to disk. */
|
|
5
5
|
var StateTracker_1 = require("./StateTracker");
|
|
6
6
|
Object.defineProperty(exports, "StateTracker", { enumerable: true, get: function () { return StateTracker_1.StateTracker; } });
|
|
7
|
+
Object.defineProperty(exports, "defineStateMigration", { enumerable: true, get: function () { return StateTracker_1.defineStateMigration; } });
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+CAA+C;AAC/C,+
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+CAA+C;AAC/C,+CASwB;AARtB,4GAAA,YAAY,OAAA;AACZ,oHAAA,oBAAoB,OAAA"}
|