@vielzeug/vault 2.0.1 → 2.2.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.
- package/README.md +42 -6
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js.map +1 -1
- package/dist/adapter-core.cjs +1 -1
- package/dist/adapter-core.cjs.map +1 -1
- package/dist/adapter-core.d.ts +1 -0
- package/dist/adapter-core.d.ts.map +1 -1
- package/dist/adapter-core.js +98 -108
- package/dist/adapter-core.js.map +1 -1
- package/dist/adapters/indexeddb.cjs +1 -1
- package/dist/adapters/indexeddb.cjs.map +1 -1
- package/dist/adapters/indexeddb.d.ts.map +1 -1
- package/dist/adapters/indexeddb.js +114 -113
- package/dist/adapters/indexeddb.js.map +1 -1
- package/dist/adapters/memory.cjs +1 -1
- package/dist/adapters/memory.cjs.map +1 -1
- package/dist/adapters/memory.d.ts.map +1 -1
- package/dist/adapters/memory.js +59 -59
- package/dist/adapters/memory.js.map +1 -1
- package/dist/adapters/sqlite.cjs +42 -0
- package/dist/adapters/sqlite.cjs.map +1 -0
- package/dist/adapters/sqlite.d.ts +43 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +401 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/adapters/webstorage.cjs +1 -1
- package/dist/adapters/webstorage.cjs.map +1 -1
- package/dist/adapters/webstorage.d.ts +1 -1
- package/dist/adapters/webstorage.d.ts.map +1 -1
- package/dist/adapters/webstorage.js +26 -26
- package/dist/adapters/webstorage.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +0 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -4
- package/dist/errors.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -8
- package/dist/indexeddb.cjs +1 -0
- package/dist/indexeddb.d.ts +5 -0
- package/dist/indexeddb.d.ts.map +1 -0
- package/dist/indexeddb.js +3 -0
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/local-storage.cjs +1 -0
- package/dist/local-storage.d.ts +2 -0
- package/dist/local-storage.d.ts.map +1 -0
- package/dist/local-storage.js +2 -0
- package/dist/memory.cjs +1 -0
- package/dist/memory.d.ts +2 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +2 -0
- package/dist/prune.cjs.map +1 -1
- package/dist/prune.d.ts.map +1 -1
- package/dist/prune.js.map +1 -1
- package/dist/session-storage.cjs +1 -0
- package/dist/session-storage.d.ts +2 -0
- package/dist/session-storage.d.ts.map +1 -0
- package/dist/session-storage.js +2 -0
- package/dist/sqlite.cjs +1 -0
- package/dist/sqlite.d.ts +4 -0
- package/dist/sqlite.d.ts.map +1 -0
- package/dist/sqlite.js +2 -0
- package/dist/ttl.cjs.map +1 -1
- package/dist/ttl.d.ts +0 -7
- package/dist/ttl.d.ts.map +1 -1
- package/dist/ttl.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +17 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vault.cjs +1 -1
- package/dist/vault.cjs.map +1 -1
- package/dist/vault.iife.js +1 -1
- package/dist/vault.iife.js.map +1 -1
- package/dist/vault.js +1 -1
- package/dist/vault.js.map +1 -1
- package/package.json +67 -16
- package/dist/streaming.d.ts +0 -2
- package/dist/streaming.d.ts.map +0 -1
- package/dist/versioned-codec.d.ts +0 -2
- package/dist/versioned-codec.d.ts.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VaultError as e, VaultQuotaError as t } from "../errors.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { isExpired as n, parseStored as r } from "../ttl.js";
|
|
3
|
+
import { decodeStorageTableFromKey as i, encodeDbPrefix as a, encodeStorageKey as o, encodeStorageTablePrefix as s, getRecordKey as c } from "../internal.js";
|
|
4
4
|
import { buildAdapterOps as l } from "../adapter-core.js";
|
|
5
5
|
//#region src/adapters/webstorage.ts
|
|
6
6
|
var u = /* @__PURE__ */ new Set(["QuotaExceededError", "NS_ERROR_DOM_QUOTA_REACHED"]);
|
|
@@ -11,7 +11,7 @@ function d(d) {
|
|
|
11
11
|
} catch (t) {
|
|
12
12
|
throw new e(`${v} is not available in this environment (private browsing or sandboxed iframe?)`, { cause: t });
|
|
13
13
|
}
|
|
14
|
-
let x = () => b, S = new Map(Object.keys(_).map((e) => [e,
|
|
14
|
+
let x = () => b, S = new Map(Object.keys(_).map((e) => [e, s(m, e)])), C = (t) => {
|
|
15
15
|
let n = S.get(t);
|
|
16
16
|
if (!n) throw new e(`table "${t}" not in schema`);
|
|
17
17
|
return n;
|
|
@@ -28,17 +28,17 @@ function d(d) {
|
|
|
28
28
|
}
|
|
29
29
|
}, T = /* @__PURE__ */ new Set();
|
|
30
30
|
(() => {
|
|
31
|
-
let e =
|
|
31
|
+
let e = a(m);
|
|
32
32
|
for (let t = 0; t < b.length; t++) {
|
|
33
33
|
let n = b.key(t);
|
|
34
|
-
n
|
|
34
|
+
n?.startsWith(e) && T.add(n);
|
|
35
35
|
}
|
|
36
36
|
})();
|
|
37
37
|
let E = (e) => {
|
|
38
38
|
let t = x().getItem(e);
|
|
39
39
|
if (t) try {
|
|
40
|
-
let e =
|
|
41
|
-
return !e ||
|
|
40
|
+
let e = r(JSON.parse(t));
|
|
41
|
+
return !e || n(e.expiresAt) ? void 0 : e.value;
|
|
42
42
|
} catch {
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
@@ -58,19 +58,19 @@ function d(d) {
|
|
|
58
58
|
return r;
|
|
59
59
|
},
|
|
60
60
|
async delete(e, t) {
|
|
61
|
-
let n =
|
|
61
|
+
let n = o(m, e, t);
|
|
62
62
|
return E(n) === void 0 ? (T.has(n) && D(n), !1) : (D(n), !0);
|
|
63
63
|
},
|
|
64
64
|
async deleteMany(e, t) {
|
|
65
65
|
let n = 0;
|
|
66
66
|
for (let r of t) {
|
|
67
|
-
let t =
|
|
67
|
+
let t = o(m, e, r);
|
|
68
68
|
E(t) === void 0 ? T.has(t) && D(t) : (D(t), n += 1);
|
|
69
69
|
}
|
|
70
70
|
return n;
|
|
71
71
|
},
|
|
72
72
|
async get(e, t) {
|
|
73
|
-
let n =
|
|
73
|
+
let n = o(m, e, t), r = E(n);
|
|
74
74
|
return r === void 0 && T.has(n) && D(n), r;
|
|
75
75
|
},
|
|
76
76
|
async getAll(e) {
|
|
@@ -107,39 +107,39 @@ function d(d) {
|
|
|
107
107
|
return n;
|
|
108
108
|
},
|
|
109
109
|
async has(e, t) {
|
|
110
|
-
let n =
|
|
110
|
+
let n = o(m, e, t), r = E(n);
|
|
111
111
|
return r === void 0 && T.has(n) && D(n), r !== void 0;
|
|
112
112
|
},
|
|
113
113
|
async pruneExpiredInTable(e) {
|
|
114
|
-
let t = C(e),
|
|
114
|
+
let t = C(e), i = [];
|
|
115
115
|
for (let e of T) {
|
|
116
116
|
if (!e.startsWith(t)) continue;
|
|
117
|
-
let
|
|
118
|
-
if (
|
|
119
|
-
|
|
117
|
+
let a = x().getItem(e);
|
|
118
|
+
if (a === null) {
|
|
119
|
+
i.push(e);
|
|
120
120
|
continue;
|
|
121
121
|
}
|
|
122
122
|
try {
|
|
123
|
-
let t =
|
|
124
|
-
(!t ||
|
|
123
|
+
let t = r(JSON.parse(a));
|
|
124
|
+
(!t || n(t.expiresAt)) && i.push(e);
|
|
125
125
|
} catch {
|
|
126
|
-
|
|
126
|
+
i.push(e);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
for (let e of
|
|
130
|
-
return
|
|
129
|
+
for (let e of i) D(e);
|
|
130
|
+
return i.length;
|
|
131
131
|
},
|
|
132
132
|
async put(e, t, n) {
|
|
133
|
-
let r =
|
|
134
|
-
w(e, r,
|
|
135
|
-
expiresAt:
|
|
133
|
+
let r = o(m, e, c(_, e, t)), i = n === void 0 ? void 0 : Date.now() + n;
|
|
134
|
+
w(e, r, i === void 0 ? { value: t } : {
|
|
135
|
+
expiresAt: i,
|
|
136
136
|
value: t
|
|
137
137
|
}), T.add(r);
|
|
138
138
|
},
|
|
139
139
|
async putAll(e, t, n) {
|
|
140
140
|
let r = n === void 0 ? void 0 : Date.now() + n;
|
|
141
141
|
for (let n of t) {
|
|
142
|
-
let t =
|
|
142
|
+
let t = o(m, e, c(_, e, n));
|
|
143
143
|
w(e, t, r === void 0 ? { value: n } : {
|
|
144
144
|
expiresAt: r,
|
|
145
145
|
value: n
|
|
@@ -157,8 +157,8 @@ function d(d) {
|
|
|
157
157
|
for (let t of Object.keys(_)) e(t);
|
|
158
158
|
return;
|
|
159
159
|
}
|
|
160
|
-
let
|
|
161
|
-
|
|
160
|
+
let n = i(m, t.key);
|
|
161
|
+
n && Object.hasOwn(_, n) && (t.newValue === null ? T.delete(t.key) : T.add(t.key), e(n));
|
|
162
162
|
};
|
|
163
163
|
return window.addEventListener("storage", t), () => window.removeEventListener("storage", t);
|
|
164
164
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webstorage.js","names":[],"sources":["../../src/adapters/webstorage.ts"],"sourcesContent":["import type { AnySchema, BaseAdapterOptions, KeyOf, RecordOf, TtlMs, VaultStore } from '../types';\n\nimport { buildAdapterOps, type StorageBackend } from '../adapter-core';\nimport { VaultError, VaultQuotaError } from '../errors';\nimport {\n decodeStorageTableFromKey,\n encodeDbPrefix,\n encodeStorageKey,\n encodeStorageTablePrefix,\n getRecordKey,\n} from '../internal';\nimport { isExpired, parseStored } from '../ttl';\n\n// Firefox historically threw 'NS_ERROR_DOM_QUOTA_REACHED'; modern browsers use the standard name.\nconst QUOTA_ERROR_NAMES = new Set(['QuotaExceededError', 'NS_ERROR_DOM_QUOTA_REACHED']);\n\ntype WebStorageOptions<S extends AnySchema> = BaseAdapterOptions<S> & {\n name: string;\n /**\n * Called when localStorage/sessionStorage quota is exceeded on a write.\n * Return `'ignore'` to silently drop the write, or `'throw'` (default) to rethrow the error.\n */\n onQuotaExceeded?: (table: keyof S, error: VaultQuotaError) => 'ignore' | 'throw';\n};\n\nfunction createWebStorageAdapter<S extends AnySchema>(\n options: WebStorageOptions<S> & {\n getStorage: () => Storage;\n storageLabel: string;\n },\n): VaultStore<S> {\n const { getStorage, logger, name, onMetrics, onQuotaExceeded, schema, storageLabel, validators } = options;\n\n let resolvedStorage: Storage;\n\n try {\n resolvedStorage = getStorage();\n } catch (cause) {\n throw new VaultError(\n `${storageLabel} is not available in this environment (private browsing or sandboxed iframe?)`,\n {\n cause,\n },\n );\n }\n\n const storage = (): Storage => resolvedStorage;\n\n const prefixMap = new Map(Object.keys(schema).map((table) => [table, encodeStorageTablePrefix(name, table)]));\n const getPrefix = (table: string): string => {\n const cached = prefixMap.get(table);\n\n if (!cached) throw new VaultError(`table \"${table}\" not in schema`);\n\n return cached;\n };\n\n const writeItem = (table: keyof S, storageKey: string, value: unknown): void => {\n try {\n storage().setItem(storageKey, JSON.stringify(value));\n } catch (error) {\n if (error instanceof DOMException && QUOTA_ERROR_NAMES.has(error.name)) {\n const wrappedError = new VaultQuotaError(`${storageLabel} quota exceeded while writing record`, {\n cause: error,\n });\n\n if (onQuotaExceeded?.(table, wrappedError) === 'ignore') return;\n\n throw wrappedError;\n }\n\n throw error;\n }\n };\n\n // Per-instance registry of all storage keys owned by this adapter instance.\n // Populated once at construction; kept current by every mutation.\n const ownedKeys = new Set<string>();\n\n const initOwnedKeys = (): void => {\n const dbPrefix = encodeDbPrefix(name);\n\n for (let i = 0; i < resolvedStorage.length; i++) {\n const key = resolvedStorage.key(i);\n\n if (key !== null && key.startsWith(dbPrefix)) ownedKeys.add(key);\n }\n };\n\n initOwnedKeys();\n\n /**\n * Reads a single entry without side effects. Returns the live value,\n * or `undefined` if missing/expired/corrupt.\n *\n * Callers that want to evict stale entries must call `evict(storageKey)` explicitly.\n * This design avoids the `{ cleanup?: boolean }` flag that required callers to remember\n * to pass `{ cleanup: false }` inside loops.\n */\n const parseEntry = <T extends object>(storageKey: string): T | undefined => {\n const raw = storage().getItem(storageKey);\n\n if (!raw) return undefined;\n\n try {\n const stored = parseStored<T>(JSON.parse(raw) as unknown);\n\n if (!stored || isExpired(stored.expiresAt)) return undefined;\n\n return stored.value;\n } catch {\n return undefined;\n }\n };\n\n /** Removes a stale/expired/corrupt entry from storage and the owned-keys registry. */\n const evict = (storageKey: string): void => {\n storage().removeItem(storageKey);\n ownedKeys.delete(storageKey);\n };\n\n const core: StorageBackend<S> = {\n async clear<K extends keyof S & string>(table: K): Promise<void> {\n const target = storage();\n const prefix = getPrefix(table);\n const toRemove: string[] = [];\n\n for (const key of ownedKeys) {\n if (key.startsWith(prefix)) toRemove.push(key);\n }\n\n for (const key of toRemove) {\n target.removeItem(key);\n ownedKeys.delete(key);\n }\n },\n\n async count<K extends keyof S & string>(table: K): Promise<number> {\n const prefix = getPrefix(table);\n const expiredKeys: string[] = [];\n let liveCount = 0;\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredKeys.push(storageKey);\n } else {\n liveCount += 1;\n }\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return liveCount;\n },\n\n async delete<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value !== undefined) {\n evict(storageKey);\n\n return true;\n }\n\n if (ownedKeys.has(storageKey)) evict(storageKey);\n\n return false;\n },\n\n async deleteMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<number> {\n let deleted = 0;\n\n for (const key of keys) {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value !== undefined) {\n evict(storageKey);\n deleted += 1;\n } else if (ownedKeys.has(storageKey)) {\n evict(storageKey);\n }\n }\n\n return deleted;\n },\n\n async get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined && ownedKeys.has(storageKey)) evict(storageKey);\n\n return value;\n },\n\n async getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]> {\n const records: RecordOf<S, K>[] = [];\n const expiredKeys: string[] = [];\n const prefix = getPrefix(table);\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredKeys.push(storageKey);\n continue;\n }\n\n records.push(value);\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return records;\n },\n\n async getAllKeys<K extends keyof S & string>(table: K): Promise<KeyOf<S, K>[]> {\n const prefix = getPrefix(table);\n const keys: KeyOf<S, K>[] = [];\n const expiredStorageKeys: string[] = [];\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredStorageKeys.push(storageKey);\n continue;\n }\n\n // Extract the record key from the already-decoded value (avoids a second parse).\n keys.push((value as Record<string, unknown>)[schema[table].key] as KeyOf<S, K>);\n }\n\n for (const storageKey of expiredStorageKeys) {\n evict(storageKey);\n }\n\n return keys;\n },\n\n async getRawCount<K extends keyof S & string>(table: K): Promise<number> {\n const prefix = getPrefix(table);\n let count = 0;\n\n for (const key of ownedKeys) {\n if (key.startsWith(prefix)) count += 1;\n }\n\n return count;\n },\n\n async has<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined && ownedKeys.has(storageKey)) evict(storageKey);\n\n return value !== undefined;\n },\n\n async pruneExpiredInTable<K extends keyof S & string>(table: K): Promise<number> {\n const prefix = getPrefix(table);\n const expiredKeys: string[] = [];\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const raw = storage().getItem(storageKey);\n\n if (raw === null) {\n expiredKeys.push(storageKey);\n continue;\n }\n\n try {\n const stored = parseStored(JSON.parse(raw) as unknown);\n\n if (!stored || isExpired(stored.expiresAt)) {\n expiredKeys.push(storageKey);\n }\n } catch {\n expiredKeys.push(storageKey);\n }\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return expiredKeys.length;\n },\n\n async put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: TtlMs): Promise<void> {\n const storageKey = encodeStorageKey(name, table, getRecordKey(schema, table, value));\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n\n writeItem(table, storageKey, expiresAt === undefined ? { value } : { expiresAt, value });\n ownedKeys.add(storageKey);\n },\n\n async putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: TtlMs): Promise<void> {\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n\n for (const value of values) {\n const storageKey = encodeStorageKey(name, table, getRecordKey(schema, table, value));\n\n writeItem(table, storageKey, expiresAt === undefined ? { value } : { expiresAt, value });\n ownedKeys.add(storageKey);\n }\n },\n };\n\n return buildAdapterOps(schema, core, {\n logger,\n onCrossTabMessage(notify) {\n if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') {\n return undefined;\n }\n\n const listener = (event: StorageEvent) => {\n if (event.storageArea && event.storageArea !== resolvedStorage) return;\n\n if (event.key === null) {\n // storage.clear() from another tab — all keys are gone; purge ownedKeys\n ownedKeys.clear();\n\n for (const table of Object.keys(schema)) {\n notify(table as keyof S & string);\n }\n\n return;\n }\n\n const tableName = decodeStorageTableFromKey(name, event.key);\n\n if (tableName && Object.hasOwn(schema, tableName)) {\n if (event.newValue === null) {\n ownedKeys.delete(event.key);\n } else {\n ownedKeys.add(event.key);\n }\n\n notify(tableName as keyof S & string);\n }\n };\n\n window.addEventListener('storage', listener);\n\n return () => window.removeEventListener('storage', listener);\n },\n onMetrics,\n schema,\n validators,\n });\n}\n\nexport function createLocalStorage<S extends AnySchema>(options: WebStorageOptions<S>): VaultStore<S> {\n return createWebStorageAdapter({\n ...options,\n getStorage: () => (typeof window !== 'undefined' ? window.localStorage : localStorage),\n storageLabel: 'localStorage',\n });\n}\n\nexport function createSessionStorage<S extends AnySchema>(options: WebStorageOptions<S>): VaultStore<S> {\n return createWebStorageAdapter({\n ...options,\n getStorage: () => (typeof window !== 'undefined' ? window.sessionStorage : sessionStorage),\n storageLabel: 'sessionStorage',\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"webstorage.js","names":[],"sources":["../../src/adapters/webstorage.ts"],"sourcesContent":["import { buildAdapterOps, type StorageBackend } from '../adapter-core';\nimport { VaultError, VaultQuotaError } from '../errors';\nimport {\n decodeStorageTableFromKey,\n encodeDbPrefix,\n encodeStorageKey,\n encodeStorageTablePrefix,\n getRecordKey,\n} from '../internal';\nimport { isExpired, parseStored } from '../ttl';\nimport type { AnySchema, BaseAdapterOptions, KeyOf, RecordOf, TtlMs, VaultStore } from '../types';\n\n// Firefox historically threw 'NS_ERROR_DOM_QUOTA_REACHED'; modern browsers use the standard name.\nconst QUOTA_ERROR_NAMES = new Set(['QuotaExceededError', 'NS_ERROR_DOM_QUOTA_REACHED']);\n\ntype WebStorageOptions<S extends AnySchema> = BaseAdapterOptions<S> & {\n name: string;\n /**\n * Called when localStorage/sessionStorage quota is exceeded on a write.\n * Return `'ignore'` to silently drop the write, or `'throw'` (default) to rethrow the error.\n */\n onQuotaExceeded?: (table: keyof S, error: VaultQuotaError) => 'ignore' | 'throw';\n};\n\nfunction createWebStorageAdapter<S extends AnySchema>(\n options: WebStorageOptions<S> & {\n getStorage: () => Storage;\n storageLabel: string;\n },\n): VaultStore<S> {\n const { getStorage, logger, name, onMetrics, onQuotaExceeded, schema, storageLabel, validators } = options;\n\n let resolvedStorage: Storage;\n\n try {\n resolvedStorage = getStorage();\n } catch (cause) {\n throw new VaultError(\n `${storageLabel} is not available in this environment (private browsing or sandboxed iframe?)`,\n {\n cause,\n },\n );\n }\n\n const storage = (): Storage => resolvedStorage;\n\n const prefixMap = new Map(Object.keys(schema).map((table) => [table, encodeStorageTablePrefix(name, table)]));\n const getPrefix = (table: string): string => {\n const cached = prefixMap.get(table);\n\n if (!cached) throw new VaultError(`table \"${table}\" not in schema`);\n\n return cached;\n };\n\n const writeItem = (table: keyof S, storageKey: string, value: unknown): void => {\n try {\n storage().setItem(storageKey, JSON.stringify(value));\n } catch (error) {\n if (error instanceof DOMException && QUOTA_ERROR_NAMES.has(error.name)) {\n const wrappedError = new VaultQuotaError(`${storageLabel} quota exceeded while writing record`, {\n cause: error,\n });\n\n if (onQuotaExceeded?.(table, wrappedError) === 'ignore') return;\n\n throw wrappedError;\n }\n\n throw error;\n }\n };\n\n // Per-instance registry of all storage keys owned by this adapter instance.\n // Populated once at construction; kept current by every mutation.\n const ownedKeys = new Set<string>();\n\n const initOwnedKeys = (): void => {\n const dbPrefix = encodeDbPrefix(name);\n\n for (let i = 0; i < resolvedStorage.length; i++) {\n const key = resolvedStorage.key(i);\n\n if (key?.startsWith(dbPrefix)) ownedKeys.add(key);\n }\n };\n\n initOwnedKeys();\n\n /**\n * Reads a single entry without side effects. Returns the live value,\n * or `undefined` if missing/expired/corrupt.\n *\n * Callers that want to evict stale entries must call `evict(storageKey)` explicitly.\n * This design avoids the `{ cleanup?: boolean }` flag that required callers to remember\n * to pass `{ cleanup: false }` inside loops.\n */\n const parseEntry = <T extends object>(storageKey: string): T | undefined => {\n const raw = storage().getItem(storageKey);\n\n if (!raw) return undefined;\n\n try {\n const stored = parseStored<T>(JSON.parse(raw) as unknown);\n\n if (!stored || isExpired(stored.expiresAt)) return undefined;\n\n return stored.value;\n } catch {\n return undefined;\n }\n };\n\n /** Removes a stale/expired/corrupt entry from storage and the owned-keys registry. */\n const evict = (storageKey: string): void => {\n storage().removeItem(storageKey);\n ownedKeys.delete(storageKey);\n };\n\n const core: StorageBackend<S> = {\n async clear<K extends keyof S & string>(table: K): Promise<void> {\n const target = storage();\n const prefix = getPrefix(table);\n const toRemove: string[] = [];\n\n for (const key of ownedKeys) {\n if (key.startsWith(prefix)) toRemove.push(key);\n }\n\n for (const key of toRemove) {\n target.removeItem(key);\n ownedKeys.delete(key);\n }\n },\n\n async count<K extends keyof S & string>(table: K): Promise<number> {\n const prefix = getPrefix(table);\n const expiredKeys: string[] = [];\n let liveCount = 0;\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredKeys.push(storageKey);\n } else {\n liveCount += 1;\n }\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return liveCount;\n },\n\n async delete<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value !== undefined) {\n evict(storageKey);\n\n return true;\n }\n\n if (ownedKeys.has(storageKey)) evict(storageKey);\n\n return false;\n },\n\n async deleteMany<K extends keyof S & string>(table: K, keys: KeyOf<S, K>[]): Promise<number> {\n let deleted = 0;\n\n for (const key of keys) {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value !== undefined) {\n evict(storageKey);\n deleted += 1;\n } else if (ownedKeys.has(storageKey)) {\n evict(storageKey);\n }\n }\n\n return deleted;\n },\n\n async get<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<RecordOf<S, K> | undefined> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined && ownedKeys.has(storageKey)) evict(storageKey);\n\n return value;\n },\n\n async getAll<K extends keyof S & string>(table: K): Promise<RecordOf<S, K>[]> {\n const records: RecordOf<S, K>[] = [];\n const expiredKeys: string[] = [];\n const prefix = getPrefix(table);\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredKeys.push(storageKey);\n continue;\n }\n\n records.push(value);\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return records;\n },\n\n async getAllKeys<K extends keyof S & string>(table: K): Promise<KeyOf<S, K>[]> {\n const prefix = getPrefix(table);\n const keys: KeyOf<S, K>[] = [];\n const expiredStorageKeys: string[] = [];\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined) {\n expiredStorageKeys.push(storageKey);\n continue;\n }\n\n // Extract the record key from the already-decoded value (avoids a second parse).\n keys.push((value as Record<string, unknown>)[schema[table].key] as KeyOf<S, K>);\n }\n\n for (const storageKey of expiredStorageKeys) {\n evict(storageKey);\n }\n\n return keys;\n },\n\n async getRawCount<K extends keyof S & string>(table: K): Promise<number> {\n const prefix = getPrefix(table);\n let count = 0;\n\n for (const key of ownedKeys) {\n if (key.startsWith(prefix)) count += 1;\n }\n\n return count;\n },\n\n async has<K extends keyof S & string>(table: K, key: KeyOf<S, K>): Promise<boolean> {\n const storageKey = encodeStorageKey(name, table, key);\n const value = parseEntry<RecordOf<S, K>>(storageKey);\n\n if (value === undefined && ownedKeys.has(storageKey)) evict(storageKey);\n\n return value !== undefined;\n },\n\n async pruneExpiredInTable<K extends keyof S & string>(table: K): Promise<number> {\n const prefix = getPrefix(table);\n const expiredKeys: string[] = [];\n\n for (const storageKey of ownedKeys) {\n if (!storageKey.startsWith(prefix)) continue;\n\n const raw = storage().getItem(storageKey);\n\n if (raw === null) {\n expiredKeys.push(storageKey);\n continue;\n }\n\n try {\n const stored = parseStored(JSON.parse(raw) as unknown);\n\n if (!stored || isExpired(stored.expiresAt)) {\n expiredKeys.push(storageKey);\n }\n } catch {\n expiredKeys.push(storageKey);\n }\n }\n\n for (const storageKey of expiredKeys) {\n evict(storageKey);\n }\n\n return expiredKeys.length;\n },\n\n async put<K extends keyof S & string>(table: K, value: RecordOf<S, K>, ttl?: TtlMs): Promise<void> {\n const storageKey = encodeStorageKey(name, table, getRecordKey(schema, table, value));\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n\n writeItem(table, storageKey, expiresAt === undefined ? { value } : { expiresAt, value });\n ownedKeys.add(storageKey);\n },\n\n async putAll<K extends keyof S & string>(table: K, values: RecordOf<S, K>[], ttl?: TtlMs): Promise<void> {\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n\n for (const value of values) {\n const storageKey = encodeStorageKey(name, table, getRecordKey(schema, table, value));\n\n writeItem(table, storageKey, expiresAt === undefined ? { value } : { expiresAt, value });\n ownedKeys.add(storageKey);\n }\n },\n };\n\n return buildAdapterOps(schema, core, {\n logger,\n onCrossTabMessage(notify) {\n if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') {\n return undefined;\n }\n\n const listener = (event: StorageEvent) => {\n if (event.storageArea && event.storageArea !== resolvedStorage) return;\n\n if (event.key === null) {\n // storage.clear() from another tab — all keys are gone; purge ownedKeys\n ownedKeys.clear();\n\n for (const table of Object.keys(schema)) {\n notify(table as keyof S & string);\n }\n\n return;\n }\n\n const tableName = decodeStorageTableFromKey(name, event.key);\n\n if (tableName && Object.hasOwn(schema, tableName)) {\n if (event.newValue === null) {\n ownedKeys.delete(event.key);\n } else {\n ownedKeys.add(event.key);\n }\n\n notify(tableName as keyof S & string);\n }\n };\n\n window.addEventListener('storage', listener);\n\n return () => window.removeEventListener('storage', listener);\n },\n onMetrics,\n schema,\n validators,\n });\n}\n\nexport function createLocalStorage<S extends AnySchema>(options: WebStorageOptions<S>): VaultStore<S> {\n return createWebStorageAdapter({\n ...options,\n getStorage: () => (typeof window !== 'undefined' ? window.localStorage : localStorage),\n storageLabel: 'localStorage',\n });\n}\n\nexport function createSessionStorage<S extends AnySchema>(options: WebStorageOptions<S>): VaultStore<S> {\n return createWebStorageAdapter({\n ...options,\n getStorage: () => (typeof window !== 'undefined' ? window.sessionStorage : sessionStorage),\n storageLabel: 'sessionStorage',\n });\n}\n"],"mappings":"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"}
|
package/dist/errors.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=class
|
|
1
|
+
var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{constructor(e=`adapter is disposed`,t){super(e,t)}},n=class extends e{},r=class extends e{},i=class extends e{};exports.VaultDisposedError=t,exports.VaultError=e,exports.VaultMigrationError=i,exports.VaultQuotaError=r,exports.VaultScopeError=n;
|
|
2
2
|
//# sourceMappingURL=errors.cjs.map
|
package/dist/errors.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all vault errors. Catch with `instanceof VaultError` to\n * handle any vault-originated error regardless of its specific subtype.\n */\nexport class VaultError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n // Ensures `instanceof` works correctly when transpiled to ES5.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n
|
|
1
|
+
{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all vault errors. Catch with `instanceof VaultError` to\n * handle any vault-originated error regardless of its specific subtype.\n */\nexport class VaultError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n // Ensures `instanceof` works correctly when transpiled to ES5.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed adapter or observer hub. */\nexport class VaultDisposedError extends VaultError {\n constructor(message = 'adapter is disposed', opts?: ErrorOptions) {\n super(message, opts);\n }\n}\n\n/** Thrown when a `batch()` callback accesses a table not declared in the scope. */\nexport class VaultScopeError extends VaultError {}\n\n/** Thrown when a WebStorage write exceeds the storage quota. */\nexport class VaultQuotaError extends VaultError {}\n\n/** Thrown when an IndexedDB `onupgradeneeded` migration callback throws. */\nexport class VaultMigrationError extends VaultError {}\n"],"mappings":"AAIA,IAAa,EAAb,cAAgC,KAAM,CACpC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KAEvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAGa,EAAb,cAAwC,CAAW,CACjD,YAAY,EAAU,sBAAuB,EAAqB,CAChE,MAAM,EAAS,CAAI,CACrB,CACF,EAGa,EAAb,cAAqC,CAAW,CAAC,EAGpC,EAAb,cAAqC,CAAW,CAAC,EAGpC,EAAb,cAAyC,CAAW,CAAC"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare class VaultError extends Error {
|
|
6
6
|
constructor(message: string, opts?: ErrorOptions);
|
|
7
|
-
static is(err: unknown): err is VaultError;
|
|
8
7
|
}
|
|
9
8
|
/** Thrown when an operation is attempted on a disposed adapter or observer hub. */
|
|
10
9
|
export declare class VaultDisposedError extends VaultError {
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;CAMjD;AAED,mFAAmF;AACnF,qBAAa,kBAAmB,SAAQ,UAAU;gBACpC,OAAO,SAAwB,EAAE,IAAI,CAAC,EAAE,YAAY;CAGjE;AAED,mFAAmF;AACnF,qBAAa,eAAgB,SAAQ,UAAU;CAAG;AAElD,gEAAgE;AAChE,qBAAa,eAAgB,SAAQ,UAAU;CAAG;AAElD,4EAA4E;AAC5E,qBAAa,mBAAoB,SAAQ,UAAU;CAAG"}
|
package/dist/errors.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
//#region src/errors.ts
|
|
2
|
-
var e = class
|
|
2
|
+
var e = class extends Error {
|
|
3
3
|
constructor(e, t) {
|
|
4
4
|
super(e, t), this.name = new.target.name, Object.setPrototypeOf(this, new.target.prototype);
|
|
5
5
|
}
|
|
6
|
-
static is(t) {
|
|
7
|
-
return t instanceof e;
|
|
8
|
-
}
|
|
9
6
|
}, t = class extends e {
|
|
10
7
|
constructor(e = "adapter is disposed", t) {
|
|
11
8
|
super(e, t);
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all vault errors. Catch with `instanceof VaultError` to\n * handle any vault-originated error regardless of its specific subtype.\n */\nexport class VaultError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n // Ensures `instanceof` works correctly when transpiled to ES5.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Base class for all vault errors. Catch with `instanceof VaultError` to\n * handle any vault-originated error regardless of its specific subtype.\n */\nexport class VaultError extends Error {\n constructor(message: string, opts?: ErrorOptions) {\n super(message, opts);\n this.name = new.target.name;\n // Ensures `instanceof` works correctly when transpiled to ES5.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when an operation is attempted on a disposed adapter or observer hub. */\nexport class VaultDisposedError extends VaultError {\n constructor(message = 'adapter is disposed', opts?: ErrorOptions) {\n super(message, opts);\n }\n}\n\n/** Thrown when a `batch()` callback accesses a table not declared in the scope. */\nexport class VaultScopeError extends VaultError {}\n\n/** Thrown when a WebStorage write exceeds the storage quota. */\nexport class VaultQuotaError extends VaultError {}\n\n/** Thrown when an IndexedDB `onupgradeneeded` migration callback throws. */\nexport class VaultMigrationError extends VaultError {}\n"],"mappings":";AAIA,IAAa,IAAb,cAAgC,MAAM;CACpC,YAAY,GAAiB,GAAqB;EAIhD,AAHA,MAAM,GAAS,CAAI,GACnB,KAAK,OAAO,WAAW,MAEvB,OAAO,eAAe,MAAM,WAAW,SAAS;CAClD;AACF,GAGa,IAAb,cAAwC,EAAW;CACjD,YAAY,IAAU,uBAAuB,GAAqB;EAChE,MAAM,GAAS,CAAI;CACrB;AACF,GAGa,IAAb,cAAqC,EAAW,CAAC,GAGpC,IAAb,cAAqC,EAAW,CAAC,GAGpC,IAAb,cAAyC,EAAW,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./prune.cjs"),n=require("./ttl.cjs"),r=require("./types.cjs");exports.VaultDisposedError=e.VaultDisposedError,exports.VaultError=e.VaultError,exports.VaultMigrationError=e.VaultMigrationError,exports.VaultQuotaError=e.VaultQuotaError,exports.VaultScopeError=e.VaultScopeError,exports.isExpired=n.isExpired,exports.scheduleExpiredPrune=t.scheduleExpiredPrune,exports.table=r.table,exports.ttl=n.ttl;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
export { createIndexedDB } from './adapters/indexeddb';
|
|
2
|
-
export { createMemory } from './adapters/memory';
|
|
3
|
-
export { createLocalStorage, createSessionStorage } from './adapters/webstorage';
|
|
4
1
|
export { VaultDisposedError, VaultError, VaultMigrationError, VaultQuotaError, VaultScopeError } from './errors';
|
|
5
|
-
export { defineMigration } from './migration';
|
|
6
|
-
export type { MigrationStep } from './migration';
|
|
7
|
-
export type { QueryBuilder } from './query';
|
|
8
2
|
export { scheduleExpiredPrune } from './prune';
|
|
3
|
+
export type { QueryBuilder } from './query';
|
|
9
4
|
export { isExpired, ttl } from './ttl';
|
|
5
|
+
export type { AnySchema, BaseAdapterOptions, DebugInfo, DebugStats, IterableVaultStore, KeyOf, MetricsEvent, Observer, RecordOf, RecordValidator, SchemaEntry, TableBuilder, TableValidators, TransactionalVaultStore, TtlMs, Unsubscribe, VaultKey, VaultLogger, VaultStore, } from './types';
|
|
10
6
|
export { table } from './types';
|
|
11
|
-
export type { AnySchema, BaseAdapterOptions, DebugInfo, DebugStats, IndexedDbVaultStore, KeyOf, MetricsEvent, MigrationContext, MigrationFn, Observer, RecordOf, RecordValidator, SchemaEntry, TableBuilder, TableValidators, TransactionContext, TtlMs, Unsubscribe, VaultKey, VaultLogger, VaultStore, } from './types';
|
|
12
7
|
//# 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,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,mBAAmB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AACjH,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AACvC,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,KAAK,EACL,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,WAAW,EACX,YAAY,EACZ,eAAe,EACf,uBAAuB,EACvB,KAAK,EACL,WAAW,EACX,QAAQ,EACR,WAAW,EACX,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { VaultDisposedError as e, VaultError as t, VaultMigrationError as n, VaultQuotaError as r, VaultScopeError as i } from "./errors.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import { defineMigration as d } from "./migration.js";
|
|
7
|
-
import { scheduleExpiredPrune as f } from "./prune.js";
|
|
8
|
-
import { table as p } from "./types.js";
|
|
9
|
-
export { e as VaultDisposedError, t as VaultError, n as VaultMigrationError, r as VaultQuotaError, i as VaultScopeError, s as createIndexedDB, l as createLocalStorage, c as createMemory, u as createSessionStorage, d as defineMigration, a as isExpired, f as scheduleExpiredPrune, p as table, o as ttl };
|
|
2
|
+
import { scheduleExpiredPrune as a } from "./prune.js";
|
|
3
|
+
import { isExpired as o, ttl as s } from "./ttl.js";
|
|
4
|
+
import { table as c } from "./types.js";
|
|
5
|
+
export { e as VaultDisposedError, t as VaultError, n as VaultMigrationError, r as VaultQuotaError, i as VaultScopeError, o as isExpired, a as scheduleExpiredPrune, c as table, s as ttl };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/indexeddb.cjs"),t=require("./migration.cjs");exports.createIndexedDB=e.createIndexedDB,exports.defineMigration=t.defineMigration;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createIndexedDB } from './adapters/indexeddb';
|
|
2
|
+
export type { MigrationStep } from './migration';
|
|
3
|
+
export { defineMigration } from './migration';
|
|
4
|
+
export type { IndexedDbVaultStore, MigrationContext, MigrationFn, TransactionContext } from './types';
|
|
5
|
+
//# sourceMappingURL=indexeddb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexeddb.d.ts","sourceRoot":"","sources":["../src/indexeddb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/internal.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.cjs","names":[],"sources":["../src/internal.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"internal.cjs","names":[],"sources":["../src/internal.ts"],"sourcesContent":["import { error as logError } from './_dev';\nimport { VaultDisposedError, VaultError } from './errors';\nimport type { AnySchema, KeyOf, RecordOf, VaultKey } from './types';\n\ntype ObserverListener<T> = (records: T[]) => void;\n\nconst SEP = '\\x00';\n\n/**\n * Type-tagged keys make `1` and `'1'` distinct in string-keyed adapters while\n * keeping the same portable primary-key contract as IndexedDB.\n */\nexport function encodeVaultKey(key: VaultKey): string {\n if (typeof key === 'number') {\n if (!Number.isFinite(key)) throw new VaultError(`primary key must be a finite number, received ${String(key)}`);\n\n return `n:${String(key)}`;\n }\n\n return `s:${encodeURIComponent(key)}`;\n}\n\nexport function encodeDbPrefix(dbName: string): string {\n return `${encodeURIComponent(dbName)}${SEP}`;\n}\n\nexport function encodeStorageKey(dbName: string, table: string, key: VaultKey): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}${encodeVaultKey(key)}`;\n}\n\nexport function encodeStorageTablePrefix(dbName: string, table: string): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}`;\n}\n\nexport function decodeStorageTableFromKey(dbName: string, storageKey: string | null): string | undefined {\n if (!storageKey) return undefined;\n\n const prefix = encodeDbPrefix(dbName);\n\n if (!storageKey.startsWith(prefix)) return undefined;\n\n const tail = storageKey.slice(prefix.length);\n const end = tail.indexOf(SEP);\n\n if (end === -1) return undefined;\n\n try {\n return decodeURIComponent(tail.slice(0, end));\n } catch {\n return undefined;\n }\n}\n\n/** `observe()` is Vault's single reactivity primitive: a snapshot now, then on mutations. */\nexport function createObserverHub<S extends AnySchema>(\n getAll: <K extends keyof S & string>(table: K) => Promise<RecordOf<S, K>[]>,\n onError?: (error: unknown) => void,\n) {\n const observers = new Map<string, Set<ObserverListener<unknown>>>();\n let disposed = false;\n\n const reportObserverError = (error: unknown): void => {\n if (onError) onError(error);\n else logError('observer notification failed', error);\n };\n\n const notify = <K extends keyof S & string>(table: K): void => {\n if (disposed) return;\n\n const listeners = observers.get(table);\n\n if (!listeners || listeners.size === 0) return;\n\n void getAll(table)\n .then((records) => {\n if (disposed) return;\n\n const current = observers.get(table);\n\n if (!current || current.size === 0) return;\n\n for (const listener of current) {\n try {\n listener(records as unknown[]);\n } catch (error) {\n reportObserverError(error);\n }\n }\n })\n .catch(reportObserverError);\n };\n\n const observe = <K extends keyof S & string>(\n table: K,\n listener: (records: RecordOf<S, K>[]) => void,\n { immediate = true, signal }: { immediate?: boolean; signal?: AbortSignal } = {},\n ): (() => void) => {\n if (disposed) throw new VaultDisposedError('observer hub is disposed');\n\n if (signal?.aborted) return () => {};\n\n const wrapped = listener as ObserverListener<unknown>;\n const listeners = observers.get(table) ?? new Set<ObserverListener<unknown>>();\n\n observers.set(table, listeners);\n listeners.add(wrapped);\n\n if (immediate) notify(table);\n\n const stop = (): void => {\n const current = observers.get(table);\n\n if (!current) return;\n\n current.delete(wrapped);\n\n if (current.size === 0) observers.delete(table);\n };\n\n signal?.addEventListener('abort', stop, { once: true });\n\n return stop;\n };\n\n return {\n dispose: () => {\n disposed = true;\n observers.clear();\n },\n notify,\n observe,\n };\n}\n\nexport function getRecordKey<S extends AnySchema, K extends keyof S>(\n schema: S,\n table: K,\n value: RecordOf<S, K>,\n): KeyOf<S, K> {\n const keyField = String(schema[table].key);\n const keyValue = (value as Record<string, unknown>)[keyField];\n\n if (typeof keyValue !== 'number' && typeof keyValue !== 'string') {\n throw new VaultError(`record in table \"${String(table)}\" must have a string or finite-number key at \"${keyField}\"`);\n }\n\n if (typeof keyValue === 'number' && !Number.isFinite(keyValue)) {\n throw new VaultError(`record in table \"${String(table)}\" must have a finite-number key at \"${keyField}\"`);\n }\n\n return keyValue as KeyOf<S, K>;\n}\n"],"mappings":"sDAMA,IAAM,EAAM,KAMZ,SAAgB,EAAe,EAAuB,CACpD,GAAI,OAAO,GAAQ,SAAU,CAC3B,GAAI,CAAC,OAAO,SAAS,CAAG,EAAG,MAAM,IAAI,EAAA,WAAW,iDAAiD,OAAO,CAAG,GAAG,EAE9G,MAAO,KAAK,OAAO,CAAG,GACxB,CAEA,MAAO,KAAK,mBAAmB,CAAG,GACpC,CAEA,SAAgB,EAAe,EAAwB,CACrD,MAAO,GAAG,mBAAmB,CAAM,IAAI,GACzC,CAEA,SAAgB,EAAiB,EAAgB,EAAe,EAAuB,CACrF,MAAO,GAAG,mBAAmB,CAAM,IAAI,IAAM,mBAAmB,CAAK,IAAI,IAAM,EAAe,CAAG,GACnG,CAEA,SAAgB,EAAyB,EAAgB,EAAuB,CAC9E,MAAO,GAAG,mBAAmB,CAAM,IAAI,IAAM,mBAAmB,CAAK,IAAI,GAC3E,CAEA,SAAgB,EAA0B,EAAgB,EAA+C,CACvG,GAAI,CAAC,EAAY,OAEjB,IAAM,EAAS,EAAe,CAAM,EAEpC,GAAI,CAAC,EAAW,WAAW,CAAM,EAAG,OAEpC,IAAM,EAAO,EAAW,MAAM,EAAO,MAAM,EACrC,EAAM,EAAK,QAAQ,CAAG,EAExB,OAAQ,GAEZ,GAAI,CACF,OAAO,mBAAmB,EAAK,MAAM,EAAG,CAAG,CAAC,CAC9C,MAAQ,CACN,MACF,CACF,CAGA,SAAgB,EACd,EACA,EACA,CACA,IAAM,EAAY,IAAI,IAClB,EAAW,GAET,EAAuB,GAAyB,CAChD,GAAS,EAAQ,CAAK,CAE5B,EAEM,EAAsC,GAAmB,CAC7D,GAAI,EAAU,OAEd,IAAM,EAAY,EAAU,IAAI,CAAK,EAEjC,CAAC,GAAa,EAAU,OAAS,GAErC,EAAY,CAAK,CAAC,CACf,KAAM,GAAY,CACjB,GAAI,EAAU,OAEd,IAAM,EAAU,EAAU,IAAI,CAAK,EAE/B,MAAC,GAAW,EAAQ,OAAS,GAEjC,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,EAAS,CAAoB,CAC/B,OAAS,EAAO,CACd,EAAoB,CAAK,CAC3B,CAEJ,CAAC,CAAC,CACD,MAAM,CAAmB,CAC9B,EAkCA,MAAO,CACL,YAAe,CACb,EAAW,GACX,EAAU,MAAM,CAClB,EACA,SACA,SArCA,EACA,EACA,CAAE,YAAY,GAAM,UAA0D,CAAC,IAC9D,CACjB,GAAI,EAAU,MAAM,IAAI,EAAA,mBAAmB,0BAA0B,EAErE,GAAI,GAAQ,QAAS,UAAa,CAAC,EAEnC,IAAM,EAAU,EACV,EAAY,EAAU,IAAI,CAAK,GAAK,IAAI,IAE9C,EAAU,IAAI,EAAO,CAAS,EAC9B,EAAU,IAAI,CAAO,EAEjB,GAAW,EAAO,CAAK,EAE3B,IAAM,MAAmB,CACvB,IAAM,EAAU,EAAU,IAAI,CAAK,EAE9B,IAEL,EAAQ,OAAO,CAAO,EAElB,EAAQ,OAAS,GAAG,EAAU,OAAO,CAAK,EAChD,EAIA,OAFA,GAAQ,iBAAiB,QAAS,EAAM,CAAE,KAAM,EAAK,CAAC,EAE/C,CACT,CASA,CACF,CAEA,SAAgB,EACd,EACA,EACA,EACa,CACb,IAAM,EAAW,OAAO,EAAO,EAAM,CAAC,GAAG,EACnC,EAAY,EAAkC,GAEpD,GAAI,OAAO,GAAa,UAAY,OAAO,GAAa,SACtD,MAAM,IAAI,EAAA,WAAW,oBAAoB,OAAO,CAAK,EAAE,gDAAgD,EAAS,EAAE,EAGpH,GAAI,OAAO,GAAa,UAAY,CAAC,OAAO,SAAS,CAAQ,EAC3D,MAAM,IAAI,EAAA,WAAW,oBAAoB,OAAO,CAAK,EAAE,sCAAsC,EAAS,EAAE,EAG1G,OAAO,CACT"}
|
package/dist/internal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAMpE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAQpD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAG,MAAM,CAErF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAiBvG;AAED,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EACnD,MAAM,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAC3E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;;aAUlB,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,KAAG,IAAI;cA0B1C,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,SAClC,CAAC,YACE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,IAAI,0BACf;QAAE,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAC1E,CAAC,MAAM,IAAI,CAAC;EAoChB;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,SAAS,MAAM,CAAC,EACjE,MAAM,EAAE,CAAC,EACT,KAAK,EAAE,CAAC,EACR,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,GACpB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAab"}
|
package/dist/internal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.js","names":[],"sources":["../src/internal.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"internal.js","names":[],"sources":["../src/internal.ts"],"sourcesContent":["import { error as logError } from './_dev';\nimport { VaultDisposedError, VaultError } from './errors';\nimport type { AnySchema, KeyOf, RecordOf, VaultKey } from './types';\n\ntype ObserverListener<T> = (records: T[]) => void;\n\nconst SEP = '\\x00';\n\n/**\n * Type-tagged keys make `1` and `'1'` distinct in string-keyed adapters while\n * keeping the same portable primary-key contract as IndexedDB.\n */\nexport function encodeVaultKey(key: VaultKey): string {\n if (typeof key === 'number') {\n if (!Number.isFinite(key)) throw new VaultError(`primary key must be a finite number, received ${String(key)}`);\n\n return `n:${String(key)}`;\n }\n\n return `s:${encodeURIComponent(key)}`;\n}\n\nexport function encodeDbPrefix(dbName: string): string {\n return `${encodeURIComponent(dbName)}${SEP}`;\n}\n\nexport function encodeStorageKey(dbName: string, table: string, key: VaultKey): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}${encodeVaultKey(key)}`;\n}\n\nexport function encodeStorageTablePrefix(dbName: string, table: string): string {\n return `${encodeURIComponent(dbName)}${SEP}${encodeURIComponent(table)}${SEP}`;\n}\n\nexport function decodeStorageTableFromKey(dbName: string, storageKey: string | null): string | undefined {\n if (!storageKey) return undefined;\n\n const prefix = encodeDbPrefix(dbName);\n\n if (!storageKey.startsWith(prefix)) return undefined;\n\n const tail = storageKey.slice(prefix.length);\n const end = tail.indexOf(SEP);\n\n if (end === -1) return undefined;\n\n try {\n return decodeURIComponent(tail.slice(0, end));\n } catch {\n return undefined;\n }\n}\n\n/** `observe()` is Vault's single reactivity primitive: a snapshot now, then on mutations. */\nexport function createObserverHub<S extends AnySchema>(\n getAll: <K extends keyof S & string>(table: K) => Promise<RecordOf<S, K>[]>,\n onError?: (error: unknown) => void,\n) {\n const observers = new Map<string, Set<ObserverListener<unknown>>>();\n let disposed = false;\n\n const reportObserverError = (error: unknown): void => {\n if (onError) onError(error);\n else logError('observer notification failed', error);\n };\n\n const notify = <K extends keyof S & string>(table: K): void => {\n if (disposed) return;\n\n const listeners = observers.get(table);\n\n if (!listeners || listeners.size === 0) return;\n\n void getAll(table)\n .then((records) => {\n if (disposed) return;\n\n const current = observers.get(table);\n\n if (!current || current.size === 0) return;\n\n for (const listener of current) {\n try {\n listener(records as unknown[]);\n } catch (error) {\n reportObserverError(error);\n }\n }\n })\n .catch(reportObserverError);\n };\n\n const observe = <K extends keyof S & string>(\n table: K,\n listener: (records: RecordOf<S, K>[]) => void,\n { immediate = true, signal }: { immediate?: boolean; signal?: AbortSignal } = {},\n ): (() => void) => {\n if (disposed) throw new VaultDisposedError('observer hub is disposed');\n\n if (signal?.aborted) return () => {};\n\n const wrapped = listener as ObserverListener<unknown>;\n const listeners = observers.get(table) ?? new Set<ObserverListener<unknown>>();\n\n observers.set(table, listeners);\n listeners.add(wrapped);\n\n if (immediate) notify(table);\n\n const stop = (): void => {\n const current = observers.get(table);\n\n if (!current) return;\n\n current.delete(wrapped);\n\n if (current.size === 0) observers.delete(table);\n };\n\n signal?.addEventListener('abort', stop, { once: true });\n\n return stop;\n };\n\n return {\n dispose: () => {\n disposed = true;\n observers.clear();\n },\n notify,\n observe,\n };\n}\n\nexport function getRecordKey<S extends AnySchema, K extends keyof S>(\n schema: S,\n table: K,\n value: RecordOf<S, K>,\n): KeyOf<S, K> {\n const keyField = String(schema[table].key);\n const keyValue = (value as Record<string, unknown>)[keyField];\n\n if (typeof keyValue !== 'number' && typeof keyValue !== 'string') {\n throw new VaultError(`record in table \"${String(table)}\" must have a string or finite-number key at \"${keyField}\"`);\n }\n\n if (typeof keyValue === 'number' && !Number.isFinite(keyValue)) {\n throw new VaultError(`record in table \"${String(table)}\" must have a finite-number key at \"${keyField}\"`);\n }\n\n return keyValue as KeyOf<S, K>;\n}\n"],"mappings":";;;AAMA,IAAM,IAAM;AAMZ,SAAgB,EAAe,GAAuB;CACpD,IAAI,OAAO,KAAQ,UAAU;EAC3B,IAAI,CAAC,OAAO,SAAS,CAAG,GAAG,MAAM,IAAI,EAAW,iDAAiD,OAAO,CAAG,GAAG;EAE9G,OAAO,KAAK,OAAO,CAAG;CACxB;CAEA,OAAO,KAAK,mBAAmB,CAAG;AACpC;AAEA,SAAgB,EAAe,GAAwB;CACrD,OAAO,GAAG,mBAAmB,CAAM,IAAI;AACzC;AAEA,SAAgB,EAAiB,GAAgB,GAAe,GAAuB;CACrF,OAAO,GAAG,mBAAmB,CAAM,IAAI,IAAM,mBAAmB,CAAK,IAAI,IAAM,EAAe,CAAG;AACnG;AAEA,SAAgB,EAAyB,GAAgB,GAAuB;CAC9E,OAAO,GAAG,mBAAmB,CAAM,IAAI,IAAM,mBAAmB,CAAK,IAAI;AAC3E;AAEA,SAAgB,EAA0B,GAAgB,GAA+C;CACvG,IAAI,CAAC,GAAY;CAEjB,IAAM,IAAS,EAAe,CAAM;CAEpC,IAAI,CAAC,EAAW,WAAW,CAAM,GAAG;CAEpC,IAAM,IAAO,EAAW,MAAM,EAAO,MAAM,GACrC,IAAM,EAAK,QAAQ,CAAG;CAExB,UAAQ,IAEZ,IAAI;EACF,OAAO,mBAAmB,EAAK,MAAM,GAAG,CAAG,CAAC;CAC9C,QAAQ;EACN;CACF;AACF;AAGA,SAAgB,EACd,GACA,GACA;CACA,IAAM,oBAAY,IAAI,IAA4C,GAC9D,IAAW,IAET,KAAuB,MAAyB;EACpD,AAAI,KAAS,EAAQ,CAAK;CAE5B,GAEM,KAAsC,MAAmB;EAC7D,IAAI,GAAU;EAEd,IAAM,IAAY,EAAU,IAAI,CAAK;EAEjC,CAAC,KAAa,EAAU,SAAS,KAErC,EAAY,CAAK,CAAC,CACf,MAAM,MAAY;GACjB,IAAI,GAAU;GAEd,IAAM,IAAU,EAAU,IAAI,CAAK;GAE/B,OAAC,KAAW,EAAQ,SAAS,IAEjC,KAAK,IAAM,KAAY,GACrB,IAAI;IACF,EAAS,CAAoB;GAC/B,SAAS,GAAO;IACd,EAAoB,CAAK;GAC3B;EAEJ,CAAC,CAAC,CACD,MAAM,CAAmB;CAC9B;CAkCA,OAAO;EACL,eAAe;GAEb,AADA,IAAW,IACX,EAAU,MAAM;EAClB;EACA;EACA,UArCA,GACA,GACA,EAAE,eAAY,IAAM,cAA0D,CAAC,MAC9D;GACjB,IAAI,GAAU,MAAM,IAAI,EAAmB,0BAA0B;GAErE,IAAI,GAAQ,SAAS,aAAa,CAAC;GAEnC,IAAM,IAAU,GACV,IAAY,EAAU,IAAI,CAAK,qBAAK,IAAI,IAA+B;GAK7E,AAHA,EAAU,IAAI,GAAO,CAAS,GAC9B,EAAU,IAAI,CAAO,GAEjB,KAAW,EAAO,CAAK;GAE3B,IAAM,UAAmB;IACvB,IAAM,IAAU,EAAU,IAAI,CAAK;IAE9B,MAEL,EAAQ,OAAO,CAAO,GAElB,EAAQ,SAAS,KAAG,EAAU,OAAO,CAAK;GAChD;GAIA,OAFA,GAAQ,iBAAiB,SAAS,GAAM,EAAE,MAAM,GAAK,CAAC,GAE/C;EACT;CASA;AACF;AAEA,SAAgB,EACd,GACA,GACA,GACa;CACb,IAAM,IAAW,OAAO,EAAO,EAAM,CAAC,GAAG,GACnC,IAAY,EAAkC;CAEpD,IAAI,OAAO,KAAa,YAAY,OAAO,KAAa,UACtD,MAAM,IAAI,EAAW,oBAAoB,OAAO,CAAK,EAAE,gDAAgD,EAAS,EAAE;CAGpH,IAAI,OAAO,KAAa,YAAY,CAAC,OAAO,SAAS,CAAQ,GAC3D,MAAM,IAAI,EAAW,oBAAoB,OAAO,CAAK,EAAE,sCAAsC,EAAS,EAAE;CAG1G,OAAO;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/webstorage.cjs");exports.createLocalStorage=e.createLocalStorage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-storage.d.ts","sourceRoot":"","sources":["../src/local-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/memory.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/memory.cjs");exports.createMemory=e.createMemory;
|
package/dist/memory.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/memory.js
ADDED
package/dist/prune.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prune.cjs","names":[],"sources":["../src/prune.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"prune.cjs","names":[],"sources":["../src/prune.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { VaultDisposedError, VaultError } from './errors';\nimport type { AnySchema, VaultStore } from './types';\n\n/**\n * Schedules periodic calls to `adapter.pruneExpired()` using `setInterval`.\n * Returns a `stop` function to cancel the schedule.\n *\n * The schedule auto-cancels if the adapter is disposed — no need to call `stop()`\n * in a dispose handler when the adapter lifetime matches the schedule lifetime.\n *\n * ```ts\n * const stopPrune = scheduleExpiredPrune(db, { interval: ttl.hours(1) });\n * // later...\n * stopPrune();\n * ```\n */\nexport function scheduleExpiredPrune<S extends AnySchema>(\n adapter: Pick<VaultStore<S>, 'pruneExpired'>,\n options: {\n interval: number;\n /**\n * Called when `pruneExpired()` throws an error that is NOT a `VaultDisposedError`.\n * `VaultDisposedError` always stops the schedule automatically.\n * Without this callback, non-disposal errors are silently swallowed.\n */\n onError?: (err: unknown) => void;\n /**\n * When aborted, stops the schedule. Useful for tying the schedule lifetime\n * to an adapter's `disposalSignal`:\n * ```ts\n * scheduleExpiredPrune(db, { interval: ttl.hours(1), signal: db.disposalSignal });\n * ```\n */\n signal?: AbortSignal;\n },\n): () => void {\n if (!Number.isFinite(options.interval) || options.interval <= 0) {\n throw new VaultError('scheduleExpiredPrune: interval must be a finite positive number');\n }\n\n let active = true;\n\n const stop = (): void => {\n active = false;\n clearInterval(id);\n };\n\n options.signal?.addEventListener('abort', stop, { once: true });\n\n const id = setInterval(() => {\n if (!active) return;\n\n void adapter.pruneExpired().catch((err) => {\n if (err instanceof VaultDisposedError) {\n active = false;\n clearInterval(id);\n } else if (options.onError) {\n options.onError(err);\n } else {\n warn(`scheduleExpiredPrune: pruneExpired() threw — pass onError to handle this. ${String(err)}`);\n }\n });\n }, options.interval);\n\n return stop;\n}\n"],"mappings":"sDAiBA,SAAgB,EACd,EACA,EAiBY,CACZ,GAAI,CAAC,OAAO,SAAS,EAAQ,QAAQ,GAAK,EAAQ,UAAY,EAC5D,MAAM,IAAI,EAAA,WAAW,iEAAiE,EAGxF,IAAI,EAAS,GAEP,MAAmB,CACvB,EAAS,GACT,cAAc,CAAE,CAClB,EAEA,EAAQ,QAAQ,iBAAiB,QAAS,EAAM,CAAE,KAAM,EAAK,CAAC,EAE9D,IAAM,EAAK,gBAAkB,CACtB,GAEL,EAAa,aAAa,CAAC,CAAC,MAAO,GAAQ,CACrC,aAAe,EAAA,oBACjB,EAAS,GACT,cAAc,CAAE,GACP,EAAQ,QACjB,EAAQ,QAAQ,CAAG,EAEd,GAA6E,OAAO,CAAG,EAAvF,CAET,CAAC,CACH,EAAG,EAAQ,QAAQ,EAEnB,OAAO,CACT"}
|
package/dist/prune.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../src/prune.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prune.d.ts","sourceRoot":"","sources":["../src/prune.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,SAAS,EACtD,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,EAC5C,OAAO,EAAE;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACjC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,GACA,MAAM,IAAI,CA8BZ"}
|
package/dist/prune.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prune.js","names":[],"sources":["../src/prune.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"prune.js","names":[],"sources":["../src/prune.ts"],"sourcesContent":["import { warn } from './_dev';\nimport { VaultDisposedError, VaultError } from './errors';\nimport type { AnySchema, VaultStore } from './types';\n\n/**\n * Schedules periodic calls to `adapter.pruneExpired()` using `setInterval`.\n * Returns a `stop` function to cancel the schedule.\n *\n * The schedule auto-cancels if the adapter is disposed — no need to call `stop()`\n * in a dispose handler when the adapter lifetime matches the schedule lifetime.\n *\n * ```ts\n * const stopPrune = scheduleExpiredPrune(db, { interval: ttl.hours(1) });\n * // later...\n * stopPrune();\n * ```\n */\nexport function scheduleExpiredPrune<S extends AnySchema>(\n adapter: Pick<VaultStore<S>, 'pruneExpired'>,\n options: {\n interval: number;\n /**\n * Called when `pruneExpired()` throws an error that is NOT a `VaultDisposedError`.\n * `VaultDisposedError` always stops the schedule automatically.\n * Without this callback, non-disposal errors are silently swallowed.\n */\n onError?: (err: unknown) => void;\n /**\n * When aborted, stops the schedule. Useful for tying the schedule lifetime\n * to an adapter's `disposalSignal`:\n * ```ts\n * scheduleExpiredPrune(db, { interval: ttl.hours(1), signal: db.disposalSignal });\n * ```\n */\n signal?: AbortSignal;\n },\n): () => void {\n if (!Number.isFinite(options.interval) || options.interval <= 0) {\n throw new VaultError('scheduleExpiredPrune: interval must be a finite positive number');\n }\n\n let active = true;\n\n const stop = (): void => {\n active = false;\n clearInterval(id);\n };\n\n options.signal?.addEventListener('abort', stop, { once: true });\n\n const id = setInterval(() => {\n if (!active) return;\n\n void adapter.pruneExpired().catch((err) => {\n if (err instanceof VaultDisposedError) {\n active = false;\n clearInterval(id);\n } else if (options.onError) {\n options.onError(err);\n } else {\n warn(`scheduleExpiredPrune: pruneExpired() threw — pass onError to handle this. ${String(err)}`);\n }\n });\n }, options.interval);\n\n return stop;\n}\n"],"mappings":";;;AAiBA,SAAgB,EACd,GACA,GAiBY;CACZ,IAAI,CAAC,OAAO,SAAS,EAAQ,QAAQ,KAAK,EAAQ,YAAY,GAC5D,MAAM,IAAI,EAAW,iEAAiE;CAGxF,IAAI,IAAS,IAEP,UAAmB;EAEvB,AADA,IAAS,IACT,cAAc,CAAE;CAClB;CAEA,EAAQ,QAAQ,iBAAiB,SAAS,GAAM,EAAE,MAAM,GAAK,CAAC;CAE9D,IAAM,IAAK,kBAAkB;EACtB,KAEL,EAAa,aAAa,CAAC,CAAC,OAAO,MAAQ;GACzC,AAAI,aAAe,KACjB,IAAS,IACT,cAAc,CAAE,KACP,EAAQ,UACjB,EAAQ,QAAQ,CAAG,IAEd,GAA6E,OAAO,CAAG,EAAvF;EAET,CAAC;CACH,GAAG,EAAQ,QAAQ;CAEnB,OAAO;AACT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/webstorage.cjs");exports.createSessionStorage=e.createSessionStorage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-storage.d.ts","sourceRoot":"","sources":["../src/session-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/sqlite.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/sqlite.cjs");exports.createSQLite=e.createSQLite;
|
package/dist/sqlite.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/sqlite.js
ADDED
package/dist/ttl.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ttl.cjs","names":[],"sources":["../src/ttl.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ndeclare const ttlMsBrand: unique symbol;\n/** A duration in milliseconds, produced by the `ttl.*` helpers. */\nexport type TtlMs = number & { readonly [ttlMsBrand]: never };\n\nexport const ttl = {\n days: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.days') * 86_400_000, 'ttl.days (result)'),\n hours: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.hours') * 3_600_000, 'ttl.hours (result)'),\n minutes: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.minutes') * 60_000, 'ttl.minutes (result)'),\n ms: (n: number) => assertTtlMs(n, 'ttl.ms'),\n seconds: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.seconds') * 1000, 'ttl.seconds (result)'),\n} as const;\n\n/** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */\nexport type StoredRecord<T> = { expiresAt?: number; value: T };\n\nexport function isExpired(expiresAt: number | undefined): boolean {\n return expiresAt !== undefined && Date.now() >= expiresAt;\n}\n\nexport function assertTtlMs(ttlMs: number, source: string): TtlMs {\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new VaultError(`${source} expected a finite positive number, received ${String(ttlMs)}`);\n }\n\n return ttlMs as TtlMs;\n}\n\nexport function
|
|
1
|
+
{"version":3,"file":"ttl.cjs","names":[],"sources":["../src/ttl.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ndeclare const ttlMsBrand: unique symbol;\n/** A duration in milliseconds, produced by the `ttl.*` helpers. */\nexport type TtlMs = number & { readonly [ttlMsBrand]: never };\n\nexport const ttl = {\n days: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.days') * 86_400_000, 'ttl.days (result)'),\n hours: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.hours') * 3_600_000, 'ttl.hours (result)'),\n minutes: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.minutes') * 60_000, 'ttl.minutes (result)'),\n ms: (n: number) => assertTtlMs(n, 'ttl.ms'),\n seconds: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.seconds') * 1000, 'ttl.seconds (result)'),\n} as const;\n\n/** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */\nexport type StoredRecord<T> = { expiresAt?: number; value: T };\n\nexport function isExpired(expiresAt: number | undefined): boolean {\n return expiresAt !== undefined && Date.now() >= expiresAt;\n}\n\nexport function assertTtlMs(ttlMs: number, source: string): TtlMs {\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new VaultError(`${source} expected a finite positive number, received ${String(ttlMs)}`);\n }\n\n return ttlMs as TtlMs;\n}\n\nexport function parseStored<T>(raw: unknown): StoredRecord<T> | undefined {\n if (typeof raw !== 'object' || raw === null || !('value' in raw)) return undefined;\n\n const record = raw as { expiresAt?: unknown; value: unknown };\n\n if (record.expiresAt !== undefined && (typeof record.expiresAt !== 'number' || !Number.isFinite(record.expiresAt))) {\n return undefined;\n }\n\n return record as StoredRecord<T>;\n}\n"],"mappings":"gCAMA,IAAa,EAAM,CACjB,KAAO,GAAc,EAAY,EAAY,EAAG,UAAU,EAAI,MAAY,mBAAmB,EAC7F,MAAQ,GAAc,EAAY,EAAY,EAAG,WAAW,EAAI,KAAW,oBAAoB,EAC/F,QAAU,GAAc,EAAY,EAAY,EAAG,aAAa,EAAI,IAAQ,sBAAsB,EAClG,GAAK,GAAc,EAAY,EAAG,QAAQ,EAC1C,QAAU,GAAc,EAAY,EAAY,EAAG,aAAa,EAAI,IAAM,sBAAsB,CAClG,EAKA,SAAgB,EAAU,EAAwC,CAChE,OAAO,IAAc,IAAA,IAAa,KAAK,IAAI,GAAK,CAClD,CAEA,SAAgB,EAAY,EAAe,EAAuB,CAChE,GAAI,CAAC,OAAO,SAAS,CAAK,GAAK,GAAS,EACtC,MAAM,IAAI,EAAA,WAAW,GAAG,EAAO,+CAA+C,OAAO,CAAK,GAAG,EAG/F,OAAO,CACT,CAEA,SAAgB,EAAe,EAA2C,CACxE,GAAI,OAAO,GAAQ,WAAY,GAAgB,EAAE,UAAW,GAAM,OAElE,IAAM,EAAS,EAEX,OAAO,YAAc,IAAA,KAAc,OAAO,EAAO,WAAc,UAAY,CAAC,OAAO,SAAS,EAAO,SAAS,IAIhH,OAAO,CACT"}
|
package/dist/ttl.d.ts
CHANGED
|
@@ -17,13 +17,6 @@ export type StoredRecord<T> = {
|
|
|
17
17
|
};
|
|
18
18
|
export declare function isExpired(expiresAt: number | undefined): boolean;
|
|
19
19
|
export declare function assertTtlMs(ttlMs: number, source: string): TtlMs;
|
|
20
|
-
export declare function wrapStored<T>(value: T, ttlMs?: TtlMs): StoredRecord<T>;
|
|
21
|
-
export declare function unwrapStored<T>(raw: StoredRecord<T>): T | undefined;
|
|
22
20
|
export declare function parseStored<T>(raw: unknown): StoredRecord<T> | undefined;
|
|
23
|
-
export declare function readWithTtl<T>(raw: unknown): {
|
|
24
|
-
expired: boolean;
|
|
25
|
-
found: boolean;
|
|
26
|
-
value: T | undefined;
|
|
27
|
-
};
|
|
28
21
|
export {};
|
|
29
22
|
//# sourceMappingURL=ttl.d.ts.map
|
package/dist/ttl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../src/ttl.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC;AACxC,mEAAmE;AACnE,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAE9D,eAAO,MAAM,GAAG;uBACJ,MAAM;wBACL,MAAM;0BACJ,MAAM;qBACX,MAAM;0BACD,MAAM;CACX,CAAC;AAEX,yFAAyF;AACzF,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE/D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEhE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAMhE;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"ttl.d.ts","sourceRoot":"","sources":["../src/ttl.ts"],"names":[],"mappings":"AAEA,OAAO,CAAC,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC;AACxC,mEAAmE;AACnE,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAE9D,eAAO,MAAM,GAAG;uBACJ,MAAM;wBACL,MAAM;0BACJ,MAAM;qBACX,MAAM;0BACD,MAAM;CACX,CAAC;AAEX,yFAAyF;AACzF,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE/D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEhE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAMhE;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAUxE"}
|
package/dist/ttl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ttl.js","names":[],"sources":["../src/ttl.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ndeclare const ttlMsBrand: unique symbol;\n/** A duration in milliseconds, produced by the `ttl.*` helpers. */\nexport type TtlMs = number & { readonly [ttlMsBrand]: never };\n\nexport const ttl = {\n days: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.days') * 86_400_000, 'ttl.days (result)'),\n hours: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.hours') * 3_600_000, 'ttl.hours (result)'),\n minutes: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.minutes') * 60_000, 'ttl.minutes (result)'),\n ms: (n: number) => assertTtlMs(n, 'ttl.ms'),\n seconds: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.seconds') * 1000, 'ttl.seconds (result)'),\n} as const;\n\n/** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */\nexport type StoredRecord<T> = { expiresAt?: number; value: T };\n\nexport function isExpired(expiresAt: number | undefined): boolean {\n return expiresAt !== undefined && Date.now() >= expiresAt;\n}\n\nexport function assertTtlMs(ttlMs: number, source: string): TtlMs {\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new VaultError(`${source} expected a finite positive number, received ${String(ttlMs)}`);\n }\n\n return ttlMs as TtlMs;\n}\n\nexport function
|
|
1
|
+
{"version":3,"file":"ttl.js","names":[],"sources":["../src/ttl.ts"],"sourcesContent":["import { VaultError } from './errors';\n\ndeclare const ttlMsBrand: unique symbol;\n/** A duration in milliseconds, produced by the `ttl.*` helpers. */\nexport type TtlMs = number & { readonly [ttlMsBrand]: never };\n\nexport const ttl = {\n days: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.days') * 86_400_000, 'ttl.days (result)'),\n hours: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.hours') * 3_600_000, 'ttl.hours (result)'),\n minutes: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.minutes') * 60_000, 'ttl.minutes (result)'),\n ms: (n: number) => assertTtlMs(n, 'ttl.ms'),\n seconds: (n: number) => assertTtlMs(assertTtlMs(n, 'ttl.seconds') * 1000, 'ttl.seconds (result)'),\n} as const;\n\n/** Fixed storage envelope shared by every adapter, so data and indexes stay portable. */\nexport type StoredRecord<T> = { expiresAt?: number; value: T };\n\nexport function isExpired(expiresAt: number | undefined): boolean {\n return expiresAt !== undefined && Date.now() >= expiresAt;\n}\n\nexport function assertTtlMs(ttlMs: number, source: string): TtlMs {\n if (!Number.isFinite(ttlMs) || ttlMs <= 0) {\n throw new VaultError(`${source} expected a finite positive number, received ${String(ttlMs)}`);\n }\n\n return ttlMs as TtlMs;\n}\n\nexport function parseStored<T>(raw: unknown): StoredRecord<T> | undefined {\n if (typeof raw !== 'object' || raw === null || !('value' in raw)) return undefined;\n\n const record = raw as { expiresAt?: unknown; value: unknown };\n\n if (record.expiresAt !== undefined && (typeof record.expiresAt !== 'number' || !Number.isFinite(record.expiresAt))) {\n return undefined;\n }\n\n return record as StoredRecord<T>;\n}\n"],"mappings":";;AAMA,IAAa,IAAM;CACjB,OAAO,MAAc,EAAY,EAAY,GAAG,UAAU,IAAI,OAAY,mBAAmB;CAC7F,QAAQ,MAAc,EAAY,EAAY,GAAG,WAAW,IAAI,MAAW,oBAAoB;CAC/F,UAAU,MAAc,EAAY,EAAY,GAAG,aAAa,IAAI,KAAQ,sBAAsB;CAClG,KAAK,MAAc,EAAY,GAAG,QAAQ;CAC1C,UAAU,MAAc,EAAY,EAAY,GAAG,aAAa,IAAI,KAAM,sBAAsB;AAClG;AAKA,SAAgB,EAAU,GAAwC;CAChE,OAAO,MAAc,KAAA,KAAa,KAAK,IAAI,KAAK;AAClD;AAEA,SAAgB,EAAY,GAAe,GAAuB;CAChE,IAAI,CAAC,OAAO,SAAS,CAAK,KAAK,KAAS,GACtC,MAAM,IAAI,EAAW,GAAG,EAAO,+CAA+C,OAAO,CAAK,GAAG;CAG/F,OAAO;AACT;AAEA,SAAgB,EAAe,GAA2C;CACxE,IAAI,OAAO,KAAQ,aAAY,KAAgB,EAAE,WAAW,IAAM;CAElE,IAAM,IAAS;CAEX,QAAO,cAAc,KAAA,MAAc,OAAO,EAAO,aAAc,YAAY,CAAC,OAAO,SAAS,EAAO,SAAS,KAIhH,OAAO;AACT"}
|