@braidlabs/skew 0.1.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.
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Why a result type rather than exceptions or `null`.
3
+ *
4
+ * Reading versioned data has several distinct failure modes, and they demand
5
+ * *different* remedies:
6
+ *
7
+ * - `ahead` — the data was written by a newer build than the one reading it,
8
+ * and no down-migration path is available. Refetch, resolve the
9
+ * contract, or force the client to update.
10
+ * - `gap` — a migration step is missing from the chain. A programming error,
11
+ * and one that must be loud rather than silently dropping data.
12
+ * - `invalid` — the payload does not match the shape its version claims, or the
13
+ * envelope belongs to a different contract entirely.
14
+ * - `threw` — a migration function itself failed.
15
+ * - `retired` — the data is older than the schema's declared base version
16
+ * (see `VersionedOptions.base`) and no loaded bundle or resolved
17
+ * contract supplies the missing steps. Unlike `gap`, this is a
18
+ * *policy* outcome, not a bug: the steps were deliberately
19
+ * deleted after telemetry showed the version idle. Remedy:
20
+ * discard and refetch, or offer the user a reset.
21
+ *
22
+ * Collapsing these into `null` (or a thrown `Error`) forces every caller to
23
+ * guess, and the guess is usually "discard it" — which is data loss for the
24
+ * `ahead` case, where the data is perfectly good and merely from the future.
25
+ */
26
+ /** Discriminated failure reasons for a versioned read. */
27
+ export type SkewFailureReason = 'ahead' | 'gap' | 'invalid' | 'threw' | 'retired';
28
+ export interface SkewOk<T> {
29
+ readonly ok: true;
30
+ readonly value: T;
31
+ /**
32
+ * The version the data was written under when it was *older* than the
33
+ * reader and was migrated forward. `null` when the data was already current
34
+ * or was downgraded instead.
35
+ */
36
+ readonly migratedFrom: number | null;
37
+ /**
38
+ * The version the data was written under when it was *newer* than the
39
+ * reader and was migrated **down** to the reader's version. `null` when the
40
+ * data was current or older. A non-null value means `value` is an honest
41
+ * but lossy projection — see {@link SkewOk.lossyPaths}.
42
+ */
43
+ readonly downgradedFrom: number | null;
44
+ /**
45
+ * Dot-paths whose values are the migration's *guesses* rather than data the
46
+ * writer actually recorded — fields filled with defaults, placeholder
47
+ * constants, or clock-derived values. Anything downstream that treats a
48
+ * derived value as a reported one is trusting a guess; this list is how it
49
+ * can tell.
50
+ */
51
+ readonly derivedPaths: readonly string[];
52
+ /**
53
+ * Dot-paths the newer shape carried that a down-migration had to discard.
54
+ * Only ever non-empty when {@link SkewOk.downgradedFrom} is set.
55
+ */
56
+ readonly lossyPaths: readonly string[];
57
+ }
58
+ export interface SkewErr {
59
+ readonly ok: false;
60
+ readonly reason: SkewFailureReason;
61
+ /** Version found on the data (0 when un-enveloped legacy data). */
62
+ readonly found: number;
63
+ /** Version the reader expected. */
64
+ readonly expected: number;
65
+ /**
66
+ * The schema's base version — set only on `retired` failures, so telemetry
67
+ * can report how far below the floor the data was.
68
+ */
69
+ readonly floor?: number;
70
+ readonly message: string;
71
+ readonly cause?: unknown;
72
+ }
73
+ export type SkewResult<T> = SkewOk<T> | SkewErr;
74
+ /** Optional success metadata — see the matching fields on {@link SkewOk}. */
75
+ export interface SkewOkMeta {
76
+ readonly migratedFrom?: number | null;
77
+ readonly downgradedFrom?: number | null;
78
+ readonly derivedPaths?: readonly string[];
79
+ readonly lossyPaths?: readonly string[];
80
+ }
81
+ export declare function ok<T>(value: T, meta?: SkewOkMeta | number | null): SkewOk<T>;
82
+ export declare function err(reason: SkewFailureReason, found: number, expected: number, message: string, cause?: unknown): SkewErr;
83
+ /**
84
+ * Narrowing helper, useful at call sites that only care about success.
85
+ *
86
+ * ```ts
87
+ * if (isOk(result)) use(result.value);
88
+ * ```
89
+ */
90
+ export declare function isOk<T>(r: SkewResult<T>): r is SkewOk<T>;
91
+ export declare function isErr<T>(r: SkewResult<T>): r is SkewErr;
92
+ /**
93
+ * Unwraps a result, substituting a fallback on failure.
94
+ *
95
+ * Deliberately requires the fallback to be explicit — there is no `unwrap()`
96
+ * that throws, because throwing on stale data is almost never what an
97
+ * application wants at a read site.
98
+ */
99
+ export declare function valueOr<T>(r: SkewResult<T>, fallback: T): T;
100
+ /**
101
+ * Maps the success value, preserving all migration metadata.
102
+ */
103
+ export declare function mapResult<T, U>(r: SkewResult<T>, fn: (value: T) => U): SkewResult<U>;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Why a result type rather than exceptions or `null`.
3
+ *
4
+ * Reading versioned data has several distinct failure modes, and they demand
5
+ * *different* remedies:
6
+ *
7
+ * - `ahead` — the data was written by a newer build than the one reading it,
8
+ * and no down-migration path is available. Refetch, resolve the
9
+ * contract, or force the client to update.
10
+ * - `gap` — a migration step is missing from the chain. A programming error,
11
+ * and one that must be loud rather than silently dropping data.
12
+ * - `invalid` — the payload does not match the shape its version claims, or the
13
+ * envelope belongs to a different contract entirely.
14
+ * - `threw` — a migration function itself failed.
15
+ * - `retired` — the data is older than the schema's declared base version
16
+ * (see `VersionedOptions.base`) and no loaded bundle or resolved
17
+ * contract supplies the missing steps. Unlike `gap`, this is a
18
+ * *policy* outcome, not a bug: the steps were deliberately
19
+ * deleted after telemetry showed the version idle. Remedy:
20
+ * discard and refetch, or offer the user a reset.
21
+ *
22
+ * Collapsing these into `null` (or a thrown `Error`) forces every caller to
23
+ * guess, and the guess is usually "discard it" — which is data loss for the
24
+ * `ahead` case, where the data is perfectly good and merely from the future.
25
+ */
26
+ const NO_PATHS = Object.freeze([]);
27
+ export function ok(value, meta = null) {
28
+ var _a, _b, _c, _d;
29
+ const normalized = typeof meta === 'number' || meta === null ? { migratedFrom: meta } : meta;
30
+ return {
31
+ ok: true,
32
+ value,
33
+ migratedFrom: (_a = normalized.migratedFrom) !== null && _a !== void 0 ? _a : null,
34
+ downgradedFrom: (_b = normalized.downgradedFrom) !== null && _b !== void 0 ? _b : null,
35
+ derivedPaths: (_c = normalized.derivedPaths) !== null && _c !== void 0 ? _c : NO_PATHS,
36
+ lossyPaths: (_d = normalized.lossyPaths) !== null && _d !== void 0 ? _d : NO_PATHS,
37
+ };
38
+ }
39
+ export function err(reason, found, expected, message, cause) {
40
+ return { ok: false, reason, found, expected, message, cause };
41
+ }
42
+ /**
43
+ * Narrowing helper, useful at call sites that only care about success.
44
+ *
45
+ * ```ts
46
+ * if (isOk(result)) use(result.value);
47
+ * ```
48
+ */
49
+ export function isOk(r) {
50
+ return r.ok;
51
+ }
52
+ export function isErr(r) {
53
+ return !r.ok;
54
+ }
55
+ /**
56
+ * Unwraps a result, substituting a fallback on failure.
57
+ *
58
+ * Deliberately requires the fallback to be explicit — there is no `unwrap()`
59
+ * that throws, because throwing on stale data is almost never what an
60
+ * application wants at a read site.
61
+ */
62
+ export function valueOr(r, fallback) {
63
+ return r.ok ? r.value : fallback;
64
+ }
65
+ /**
66
+ * Maps the success value, preserving all migration metadata.
67
+ */
68
+ export function mapResult(r, fn) {
69
+ return r.ok
70
+ ? ok(fn(r.value), {
71
+ migratedFrom: r.migratedFrom,
72
+ downgradedFrom: r.downgradedFrom,
73
+ derivedPaths: r.derivedPaths,
74
+ lossyPaths: r.lossyPaths,
75
+ })
76
+ : r;
77
+ }
78
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../../../../libs/skew/src/lib/result.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAmEH,MAAM,QAAQ,GAAsB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAEtD,MAAM,UAAU,EAAE,CAChB,KAAQ,EACR,OAAmC,IAAI;;IAEvC,MAAM,UAAU,GACd,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,OAAO;QACL,EAAE,EAAE,IAAI;QACR,KAAK;QACL,YAAY,EAAE,MAAA,UAAU,CAAC,YAAY,mCAAI,IAAI;QAC7C,cAAc,EAAE,MAAA,UAAU,CAAC,cAAc,mCAAI,IAAI;QACjD,YAAY,EAAE,MAAA,UAAU,CAAC,YAAY,mCAAI,QAAQ;QACjD,UAAU,EAAE,MAAA,UAAU,CAAC,UAAU,mCAAI,QAAQ;KAC9C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,GAAG,CACjB,MAAyB,EACzB,KAAa,EACb,QAAgB,EAChB,OAAe,EACf,KAAe;IAEf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAAI,CAAgB;IACtC,OAAO,CAAC,CAAC,EAAE,CAAC;AACd,CAAC;AAED,MAAM,UAAU,KAAK,CAAI,CAAgB;IACvC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CAAI,CAAgB,EAAE,QAAW;IACtD,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,CAAgB,EAChB,EAAmB;IAEnB,OAAO,CAAC,CAAC,EAAE;QACT,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;YACd,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,cAAc,EAAE,CAAC,CAAC,cAAc;YAChC,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC;QACJ,CAAC,CAAC,CAAC,CAAC;AACR,CAAC"}
@@ -0,0 +1,86 @@
1
+ import { SkewResult } from './result.js';
2
+ import { VersionedSchema } from './versioned.js';
3
+ /**
4
+ * Versioned persistence.
5
+ *
6
+ * The failure this exists to prevent is the quiet one. A service that does
7
+ * `JSON.parse(raw) as T` is asserting a shape it has not checked; the moment
8
+ * the model changes, every cached record on every user's machine has the old
9
+ * shape while being typed as the new one. You get `undefined` deep inside a
10
+ * renderer rather than a clean failure at the boundary.
11
+ */
12
+ /** Minimal key/value contract. Sync drivers may return values directly. */
13
+ export interface StorageDriver {
14
+ readonly sync: boolean;
15
+ get(key: string): string | null | Promise<string | null>;
16
+ set(key: string, value: string): void | Promise<void>;
17
+ remove(key: string): void | Promise<void>;
18
+ keys?(): string[] | Promise<string[]>;
19
+ }
20
+ export interface VersionedStoreOptions {
21
+ readonly driver: StorageDriver;
22
+ /** Namespace for keys. Defaults to the schema name. */
23
+ readonly keyPrefix?: string;
24
+ /** Stamped onto envelopes so a bad record can be attributed to a deployment. */
25
+ readonly buildId?: string;
26
+ /**
27
+ * Called whenever a read fails. The default is silence — callers inspect the
28
+ * returned result — but wiring this to telemetry is how you discover that a
29
+ * migration is wrong before users report it.
30
+ */
31
+ readonly onReadFailure?: (key: string, failure: Extract<SkewResult<never>, {
32
+ ok: false;
33
+ }>) => void;
34
+ /**
35
+ * Write records back at the current version after a successful *migrated*
36
+ * read ("read-repair"). Each old record then pays its migration once
37
+ * instead of on every read — and stops appearing in `migratedFrom`
38
+ * telemetry, which is what makes eventually retiring its steps (see
39
+ * `VersionedOptions.base`) provable rather than hopeful.
40
+ *
41
+ * Downgraded reads (`downgradedFrom` set) are never written back:
42
+ * persisting the lossy projection would overwrite the newer record a
43
+ * newer build still needs.
44
+ */
45
+ readonly rewriteOnRead?: boolean;
46
+ }
47
+ export interface VersionedStore<T> {
48
+ /** Reads and migrates. Returns a result — never throws on stale data. */
49
+ get(key: string): Promise<SkewResult<T>>;
50
+ /**
51
+ * Synchronous read, available only on sync drivers (localStorage, memory).
52
+ * Returns `null` on an async driver rather than lying about it.
53
+ *
54
+ * Exists because a signal or hook initialiser reading from localStorage
55
+ * should not have to flash empty state through a microtask.
56
+ */
57
+ peek(key: string): SkewResult<T> | null;
58
+ set(key: string, value: T): Promise<void>;
59
+ remove(key: string): Promise<void>;
60
+ /** Fully-qualified storage key, exposed for debugging and cache-busting. */
61
+ keyFor(key: string): string;
62
+ }
63
+ export declare function createVersionedStore<T>(schema: VersionedSchema<T>, options: VersionedStoreOptions): VersionedStore<T>;
64
+ /** In-memory driver. The default in tests and on the server. */
65
+ export declare function memoryDriver(seed?: Map<string, string>): StorageDriver;
66
+ /**
67
+ * Web Storage driver. Degrades to memory when storage is unavailable —
68
+ * Safari private mode, disabled cookies, or SSR — so a read never throws in a
69
+ * place the caller cannot reasonably handle it.
70
+ */
71
+ export declare function webStorageDriver(kind?: 'local' | 'session', win?: {
72
+ localStorage?: Storage;
73
+ sessionStorage?: Storage;
74
+ } | undefined): StorageDriver;
75
+ /** Configuration options for the IndexedDB driver. */
76
+ export interface IndexedDbDriverOptions {
77
+ /** The name of the IndexedDB database. Defaults to "skew-store". */
78
+ readonly dbName?: string;
79
+ /** The name of the object store. Defaults to "keyval". */
80
+ readonly storeName?: string;
81
+ }
82
+ /**
83
+ * IndexedDB driver for async, large-capacity storage.
84
+ * Degrades gracefully on failure (e.g. if IndexedDB is blocked).
85
+ */
86
+ export declare function indexedDbDriver(options?: IndexedDbDriverOptions): StorageDriver;
@@ -0,0 +1,190 @@
1
+ import { __awaiter } from "tslib";
2
+ import { err } from './result.js';
3
+ import { isSkewDisabled } from './disabled.js';
4
+ export function createVersionedStore(schema, options) {
5
+ const { driver, keyPrefix = schema.name, buildId, onReadFailure, rewriteOnRead = false, } = options;
6
+ const keyFor = (key) => `${keyPrefix}:${key}`;
7
+ function parse(key, raw) {
8
+ if (raw === null) {
9
+ return err('invalid', 0, schema.version, `[${schema.name}] nothing stored at "${key}"`);
10
+ }
11
+ let decoded;
12
+ try {
13
+ decoded = JSON.parse(raw);
14
+ }
15
+ catch (cause) {
16
+ return err('invalid', 0, schema.version, `[${schema.name}] stored value is not JSON`, cause);
17
+ }
18
+ const result = schema.read(decoded);
19
+ if (!result.ok)
20
+ onReadFailure === null || onReadFailure === void 0 ? void 0 : onReadFailure(key, result);
21
+ else if (rewriteOnRead &&
22
+ result.migratedFrom !== null &&
23
+ !isSkewDisabled()) {
24
+ // Read-repair: persist the migrated record at the current version.
25
+ // Only for *upward* migrations — a downgraded read is a lossy
26
+ // projection of a newer record, and writing it back would destroy data.
27
+ try {
28
+ void driver.set(keyFor(key), JSON.stringify(schema.write(result.value, buildId)));
29
+ }
30
+ catch (_a) {
31
+ // A failing repair is a cache-write failure; the read still succeeded.
32
+ }
33
+ }
34
+ return result;
35
+ }
36
+ return {
37
+ keyFor,
38
+ get(key) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ const raw = yield driver.get(keyFor(key));
41
+ return parse(key, raw);
42
+ });
43
+ },
44
+ peek(key) {
45
+ if (!driver.sync)
46
+ return null;
47
+ const raw = driver.get(keyFor(key));
48
+ return parse(key, raw);
49
+ },
50
+ set(key, value) {
51
+ return __awaiter(this, void 0, void 0, function* () {
52
+ // Not public API — see `disabled.ts`. Writing the bare value is what a
53
+ // codebase without envelopes does, and it is the write side of the
54
+ // problem: nothing in the record says which build authored it, so no
55
+ // future reader can tell.
56
+ const stored = isSkewDisabled() ? value : schema.write(value, buildId);
57
+ yield driver.set(keyFor(key), JSON.stringify(stored));
58
+ });
59
+ },
60
+ remove(key) {
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ yield driver.remove(keyFor(key));
63
+ });
64
+ },
65
+ };
66
+ }
67
+ // --- drivers ---------------------------------------------------------------
68
+ /** In-memory driver. The default in tests and on the server. */
69
+ export function memoryDriver(seed) {
70
+ const map = seed !== null && seed !== void 0 ? seed : new Map();
71
+ return {
72
+ sync: true,
73
+ get: (k) => { var _a; return (_a = map.get(k)) !== null && _a !== void 0 ? _a : null; },
74
+ set: (k, v) => void map.set(k, v),
75
+ remove: (k) => void map.delete(k),
76
+ keys: () => [...map.keys()],
77
+ };
78
+ }
79
+ /**
80
+ * Web Storage driver. Degrades to memory when storage is unavailable —
81
+ * Safari private mode, disabled cookies, or SSR — so a read never throws in a
82
+ * place the caller cannot reasonably handle it.
83
+ */
84
+ export function webStorageDriver(kind = 'local', win = globalThis) {
85
+ const store = kind === 'local' ? win === null || win === void 0 ? void 0 : win.localStorage : win === null || win === void 0 ? void 0 : win.sessionStorage;
86
+ if (!store || !isUsable(store))
87
+ return memoryDriver();
88
+ return {
89
+ sync: true,
90
+ get: (k) => store.getItem(k),
91
+ set: (k, v) => {
92
+ try {
93
+ store.setItem(k, v);
94
+ }
95
+ catch (_a) {
96
+ // Quota exceeded. A cache write failing is not worth breaking a save
97
+ // the user asked for; the next read simply misses.
98
+ }
99
+ },
100
+ remove: (k) => store.removeItem(k),
101
+ keys: () => Object.keys(store),
102
+ };
103
+ }
104
+ function isUsable(store) {
105
+ const probe = '__skew_probe__';
106
+ try {
107
+ store.setItem(probe, '1');
108
+ store.removeItem(probe);
109
+ return true;
110
+ }
111
+ catch (_a) {
112
+ return false;
113
+ }
114
+ }
115
+ /**
116
+ * IndexedDB driver for async, large-capacity storage.
117
+ * Degrades gracefully on failure (e.g. if IndexedDB is blocked).
118
+ */
119
+ export function indexedDbDriver(options = {}) {
120
+ const { dbName = 'skew-store', storeName = 'keyval' } = options;
121
+ let dbPromise = null;
122
+ function getDb() {
123
+ if (dbPromise)
124
+ return dbPromise;
125
+ if (typeof indexedDB === 'undefined') {
126
+ return Promise.reject(new Error('IndexedDB is not available'));
127
+ }
128
+ dbPromise = new Promise((resolve, reject) => {
129
+ const req = indexedDB.open(dbName, 1);
130
+ req.onupgradeneeded = () => {
131
+ const db = req.result;
132
+ if (!db.objectStoreNames.contains(storeName)) {
133
+ db.createObjectStore(storeName);
134
+ }
135
+ };
136
+ req.onsuccess = () => resolve(req.result);
137
+ req.onerror = () => {
138
+ dbPromise = null;
139
+ reject(req.error);
140
+ };
141
+ });
142
+ return dbPromise;
143
+ }
144
+ function run(mode, callback) {
145
+ return getDb().then((db) => new Promise((resolve, reject) => {
146
+ const tx = db.transaction(storeName, mode);
147
+ const store = tx.objectStore(storeName);
148
+ const req = callback(store);
149
+ req.onsuccess = () => resolve(req.result);
150
+ req.onerror = () => reject(req.error);
151
+ }));
152
+ }
153
+ return {
154
+ sync: false,
155
+ get: (key) => __awaiter(this, void 0, void 0, function* () {
156
+ try {
157
+ const val = yield run('readonly', (store) => store.get(key));
158
+ return val !== null && val !== void 0 ? val : null;
159
+ }
160
+ catch (_a) {
161
+ return null;
162
+ }
163
+ }),
164
+ set: (key, value) => __awaiter(this, void 0, void 0, function* () {
165
+ try {
166
+ yield run('readwrite', (store) => store.put(value, key));
167
+ }
168
+ catch (_a) {
169
+ // Fail silently on quota exceeded or other errors
170
+ }
171
+ }),
172
+ remove: (key) => __awaiter(this, void 0, void 0, function* () {
173
+ try {
174
+ yield run('readwrite', (store) => store.delete(key));
175
+ }
176
+ catch (_a) {
177
+ // A failed cache delete is a smaller problem than the throw would be.
178
+ }
179
+ }),
180
+ keys: () => __awaiter(this, void 0, void 0, function* () {
181
+ try {
182
+ return yield run('readonly', (store) => store.getAllKeys());
183
+ }
184
+ catch (_a) {
185
+ return [];
186
+ }
187
+ }),
188
+ };
189
+ }
190
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../../../libs/skew/src/lib/storage.ts"],"names":[],"mappings":"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"}