attaform 0.0.1 → 0.14.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/LICENSE +21 -0
- package/README.md +142 -2
- package/dist/chunks/devtools.cjs +179 -0
- package/dist/chunks/devtools.cjs.map +1 -0
- package/dist/chunks/devtools.mjs +177 -0
- package/dist/chunks/devtools.mjs.map +1 -0
- package/dist/chunks/indexeddb.cjs +119 -0
- package/dist/chunks/indexeddb.cjs.map +1 -0
- package/dist/chunks/indexeddb.mjs +117 -0
- package/dist/chunks/indexeddb.mjs.map +1 -0
- package/dist/chunks/local-storage.cjs +58 -0
- package/dist/chunks/local-storage.cjs.map +1 -0
- package/dist/chunks/local-storage.mjs +56 -0
- package/dist/chunks/local-storage.mjs.map +1 -0
- package/dist/chunks/session-storage.cjs +58 -0
- package/dist/chunks/session-storage.cjs.map +1 -0
- package/dist/chunks/session-storage.mjs +56 -0
- package/dist/chunks/session-storage.mjs.map +1 -0
- package/dist/index.cjs +173 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +493 -0
- package/dist/index.d.mts +493 -0
- package/dist/index.d.ts +493 -0
- package/dist/index.mjs +141 -0
- package/dist/index.mjs.map +1 -0
- package/dist/nuxt.cjs +97 -0
- package/dist/nuxt.cjs.map +1 -0
- package/dist/nuxt.d.cts +38 -0
- package/dist/nuxt.d.mts +38 -0
- package/dist/nuxt.d.ts +38 -0
- package/dist/nuxt.mjs +94 -0
- package/dist/nuxt.mjs.map +1 -0
- package/dist/runtime/plugins/attaform.cjs +32 -0
- package/dist/runtime/plugins/attaform.cjs.map +1 -0
- package/dist/runtime/plugins/attaform.d.cts +5 -0
- package/dist/runtime/plugins/attaform.d.mts +5 -0
- package/dist/runtime/plugins/attaform.d.ts +5 -0
- package/dist/runtime/plugins/attaform.mjs +30 -0
- package/dist/runtime/plugins/attaform.mjs.map +1 -0
- package/dist/shared/attaform.B5GWYl76.cjs +386 -0
- package/dist/shared/attaform.B5GWYl76.cjs.map +1 -0
- package/dist/shared/attaform.BRTxpA3q.mjs +3283 -0
- package/dist/shared/attaform.BRTxpA3q.mjs.map +1 -0
- package/dist/shared/attaform.BYc9kugA.d.ts +124 -0
- package/dist/shared/attaform.Bubm_slq.cjs +622 -0
- package/dist/shared/attaform.Bubm_slq.cjs.map +1 -0
- package/dist/shared/attaform.BwaYWtMs.d.cts +126 -0
- package/dist/shared/attaform.BwaYWtMs.d.mts +126 -0
- package/dist/shared/attaform.BwaYWtMs.d.ts +126 -0
- package/dist/shared/attaform.CNJO3mME.cjs +3295 -0
- package/dist/shared/attaform.CNJO3mME.cjs.map +1 -0
- package/dist/shared/attaform.CRgix6_n.cjs +796 -0
- package/dist/shared/attaform.CRgix6_n.cjs.map +1 -0
- package/dist/shared/attaform.CXZgUECn.d.cts +124 -0
- package/dist/shared/attaform.CXpzmj38.mjs +617 -0
- package/dist/shared/attaform.CXpzmj38.mjs.map +1 -0
- package/dist/shared/attaform.Cc93zNzD.mjs +83 -0
- package/dist/shared/attaform.Cc93zNzD.mjs.map +1 -0
- package/dist/shared/attaform.DDXrY-1Q.d.cts +2568 -0
- package/dist/shared/attaform.DDXrY-1Q.d.mts +2568 -0
- package/dist/shared/attaform.DDXrY-1Q.d.ts +2568 -0
- package/dist/shared/attaform.DOKOyb3Y.d.mts +124 -0
- package/dist/shared/attaform.DlgKK10S.mjs +789 -0
- package/dist/shared/attaform.DlgKK10S.mjs.map +1 -0
- package/dist/shared/attaform.al_rpt7_.mjs +361 -0
- package/dist/shared/attaform.al_rpt7_.mjs.map +1 -0
- package/dist/shared/attaform.xKWYHMdq.cjs +89 -0
- package/dist/shared/attaform.xKWYHMdq.cjs.map +1 -0
- package/dist/transforms.cjs +11 -0
- package/dist/transforms.cjs.map +1 -0
- package/dist/transforms.d.cts +49 -0
- package/dist/transforms.d.mts +49 -0
- package/dist/transforms.d.ts +49 -0
- package/dist/transforms.mjs +2 -0
- package/dist/transforms.mjs.map +1 -0
- package/dist/vite.cjs +39 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.cts +53 -0
- package/dist/vite.d.mts +53 -0
- package/dist/vite.d.ts +53 -0
- package/dist/vite.mjs +37 -0
- package/dist/vite.mjs.map +1 -0
- package/dist/zod-v3.cjs +1511 -0
- package/dist/zod-v3.cjs.map +1 -0
- package/dist/zod-v3.d.cts +164 -0
- package/dist/zod-v3.d.mts +164 -0
- package/dist/zod-v3.d.ts +164 -0
- package/dist/zod-v3.mjs +1504 -0
- package/dist/zod-v3.mjs.map +1 -0
- package/dist/zod.cjs +1548 -0
- package/dist/zod.cjs.map +1 -0
- package/dist/zod.d.cts +67 -0
- package/dist/zod.d.mts +67 -0
- package/dist/zod.d.ts +67 -0
- package/dist/zod.mjs +1541 -0
- package/dist/zod.mjs.map +1 -0
- package/package.json +182 -6
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const sensitiveNames = require('../shared/attaform.B5GWYl76.cjs');
|
|
4
|
+
|
|
5
|
+
const DB_NAME = "attaform";
|
|
6
|
+
const STORE_NAME = "kv";
|
|
7
|
+
const DB_VERSION = 1;
|
|
8
|
+
let dbPromise = null;
|
|
9
|
+
let warnedOnOpenFailure = false;
|
|
10
|
+
let warnedOnWriteFailure = false;
|
|
11
|
+
function openDb() {
|
|
12
|
+
if (dbPromise !== null) return dbPromise;
|
|
13
|
+
if (typeof indexedDB === "undefined") {
|
|
14
|
+
dbPromise = Promise.resolve(null);
|
|
15
|
+
return dbPromise;
|
|
16
|
+
}
|
|
17
|
+
dbPromise = new Promise((resolve) => {
|
|
18
|
+
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
19
|
+
request.onupgradeneeded = () => {
|
|
20
|
+
const db = request.result;
|
|
21
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
22
|
+
db.createObjectStore(STORE_NAME);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
request.onsuccess = () => resolve(request.result);
|
|
26
|
+
request.onerror = () => {
|
|
27
|
+
if (sensitiveNames.__DEV__ && !warnedOnOpenFailure) {
|
|
28
|
+
warnedOnOpenFailure = true;
|
|
29
|
+
console.warn(
|
|
30
|
+
"[attaform] IndexedDB open failed; persistence disabled. Common causes: private-mode disabled IDB, browser quota policy.",
|
|
31
|
+
request.error
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
resolve(null);
|
|
35
|
+
};
|
|
36
|
+
request.onblocked = () => {
|
|
37
|
+
if (sensitiveNames.__DEV__ && !warnedOnOpenFailure) {
|
|
38
|
+
warnedOnOpenFailure = true;
|
|
39
|
+
console.warn(
|
|
40
|
+
"[attaform] IndexedDB open blocked (another tab holds an older version); persistence disabled until the conflict resolves."
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
dbPromise = null;
|
|
44
|
+
resolve(null);
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
return dbPromise;
|
|
48
|
+
}
|
|
49
|
+
function runReadOp(fn) {
|
|
50
|
+
return openDb().then(
|
|
51
|
+
(db) => new Promise((resolve) => {
|
|
52
|
+
if (db === null) return resolve(void 0);
|
|
53
|
+
let tx;
|
|
54
|
+
try {
|
|
55
|
+
tx = db.transaction(STORE_NAME, "readonly");
|
|
56
|
+
} catch {
|
|
57
|
+
return resolve(void 0);
|
|
58
|
+
}
|
|
59
|
+
const store = tx.objectStore(STORE_NAME);
|
|
60
|
+
const request = fn(store);
|
|
61
|
+
request.onsuccess = () => resolve(request.result);
|
|
62
|
+
request.onerror = () => resolve(void 0);
|
|
63
|
+
tx.onerror = () => resolve(void 0);
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
function runWriteOp(fn) {
|
|
68
|
+
return openDb().then(
|
|
69
|
+
(db) => new Promise((resolve) => {
|
|
70
|
+
if (db === null) return resolve();
|
|
71
|
+
let tx;
|
|
72
|
+
try {
|
|
73
|
+
tx = db.transaction(STORE_NAME, "readwrite");
|
|
74
|
+
} catch {
|
|
75
|
+
return resolve();
|
|
76
|
+
}
|
|
77
|
+
fn(tx.objectStore(STORE_NAME));
|
|
78
|
+
tx.oncomplete = () => resolve();
|
|
79
|
+
tx.onabort = () => {
|
|
80
|
+
if (sensitiveNames.__DEV__ && !warnedOnWriteFailure) {
|
|
81
|
+
warnedOnWriteFailure = true;
|
|
82
|
+
console.warn(
|
|
83
|
+
"[attaform] IndexedDB transaction aborted; subsequent writes will silently no-op. Common cause: storage quota exceeded.",
|
|
84
|
+
tx.error
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
resolve();
|
|
88
|
+
};
|
|
89
|
+
tx.onerror = () => resolve();
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
function createIndexedDbAdapter() {
|
|
94
|
+
return {
|
|
95
|
+
async getItem(key) {
|
|
96
|
+
return await runReadOp((store) => store.get(key));
|
|
97
|
+
},
|
|
98
|
+
async setItem(key, value) {
|
|
99
|
+
await runWriteOp((store) => void store.put(value, key));
|
|
100
|
+
},
|
|
101
|
+
async removeItem(key) {
|
|
102
|
+
await runWriteOp((store) => void store.delete(key));
|
|
103
|
+
},
|
|
104
|
+
async listKeys(prefix) {
|
|
105
|
+
const all = await runReadOp(
|
|
106
|
+
(store) => store.getAllKeys()
|
|
107
|
+
);
|
|
108
|
+
if (all === void 0) return [];
|
|
109
|
+
const out = [];
|
|
110
|
+
for (const k of all) {
|
|
111
|
+
if (typeof k === "string" && k.startsWith(prefix)) out.push(k);
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
exports.createIndexedDbAdapter = createIndexedDbAdapter;
|
|
119
|
+
//# sourceMappingURL=indexeddb.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexeddb.cjs","sources":["../../src/runtime/core/persistence/indexeddb.ts"],"sourcesContent":["import { __DEV__ } from '../dev'\nimport type { FormStorage } from '../../types/types-api'\n\n/**\n * Zero-dependency IndexedDB adapter. A single shared DB\n * (`attaform`) with a single object store (`kv`). Entries are\n * structured-cloned on write, so `Date` / `Map` / `Set` / typed\n * arrays / nested arrays round-trip without JSON flattening.\n *\n * Size budget: ≤1 KB gzip (verified via size-limit). Consumers who\n * want richer IDB features (indexes, cursors, transactions) should\n * roll their own `FormStorage`.\n *\n * Open failures (private mode, blocked DB, unsupported environment)\n * resolve `dbPromise` to `null`; subsequent reads/writes silently\n * no-op so the form stays usable. A one-shot dev warning surfaces\n * the degradation so the developer notices.\n */\n\nconst DB_NAME = 'attaform'\nconst STORE_NAME = 'kv'\nconst DB_VERSION = 1\n\nlet dbPromise: Promise<IDBDatabase | null> | null = null\n// One-shot dev-warn flags for adapter-level failures. Module-scoped\n// so the warning only fires once per process — re-opening the DB\n// after `__resetIndexedDbForTests` clears `dbPromise` but leaves\n// these flags alone (tests that want a fresh warn-state should\n// reset them via the test hook below).\nlet warnedOnOpenFailure = false\nlet warnedOnWriteFailure = false\n\nfunction openDb(): Promise<IDBDatabase | null> {\n if (dbPromise !== null) return dbPromise\n if (typeof indexedDB === 'undefined') {\n dbPromise = Promise.resolve(null)\n return dbPromise\n }\n dbPromise = new Promise<IDBDatabase | null>((resolve) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION)\n request.onupgradeneeded = () => {\n const db = request.result\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME)\n }\n }\n request.onsuccess = () => resolve(request.result)\n request.onerror = () => {\n // Drop to null so subsequent calls don't retry a broken open —\n // the form just runs without persistence.\n if (__DEV__ && !warnedOnOpenFailure) {\n warnedOnOpenFailure = true\n console.warn(\n '[attaform] IndexedDB open failed; persistence disabled. ' +\n 'Common causes: private-mode disabled IDB, browser quota policy.',\n request.error\n )\n }\n resolve(null)\n }\n request.onblocked = () => {\n if (__DEV__ && !warnedOnOpenFailure) {\n warnedOnOpenFailure = true\n console.warn(\n '[attaform] IndexedDB open blocked (another tab holds an older version); persistence disabled until the conflict resolves.'\n )\n }\n // `onblocked` is transient — the holding tab can close at any\n // moment. Clear the cache so the next persistence call retries\n // the open instead of permanently no-opping.\n dbPromise = null\n resolve(null)\n }\n })\n return dbPromise\n}\n\n/**\n * Read path: resolve on `request.onsuccess` with the fetched value.\n * `readonly` transactions are atomic by nature — there's no commit\n * phase to worry about, so waiting for the transaction's\n * `oncomplete` would be redundant.\n */\nfunction runReadOp<T>(fn: (store: IDBObjectStore) => IDBRequest<T>): Promise<T | undefined> {\n return openDb().then(\n (db) =>\n new Promise<T | undefined>((resolve) => {\n if (db === null) return resolve(undefined)\n let tx: IDBTransaction\n try {\n tx = db.transaction(STORE_NAME, 'readonly')\n } catch {\n return resolve(undefined)\n }\n const store = tx.objectStore(STORE_NAME)\n const request = fn(store)\n request.onsuccess = () => resolve(request.result)\n request.onerror = () => resolve(undefined)\n tx.onerror = () => resolve(undefined)\n })\n )\n}\n\n/**\n * Write path: resolve on `tx.oncomplete` (the spec-defined commit\n * signal), NOT on `request.onsuccess` (which fires per-request,\n * before the transaction commits).\n *\n * Resolving on `onsuccess` means a tab close, power loss, or\n * browser crash between the request succeeding and the transaction\n * committing silently loses the write — the Promise already\n * resolved successfully. Aborts (quota exceeded, version change,\n * constraint violation) likewise roll back after `onsuccess` fired.\n *\n * Resolving on `oncomplete` makes durability a precondition for\n * the Promise settlement; `onabort` catches the failure cases so\n * the Promise resolves to `undefined` instead of hanging.\n */\nfunction runWriteOp(fn: (store: IDBObjectStore) => void): Promise<void> {\n return openDb().then(\n (db) =>\n new Promise<void>((resolve) => {\n if (db === null) return resolve()\n let tx: IDBTransaction\n try {\n tx = db.transaction(STORE_NAME, 'readwrite')\n } catch {\n return resolve()\n }\n fn(tx.objectStore(STORE_NAME))\n tx.oncomplete = () => resolve()\n tx.onabort = () => {\n // QuotaExceededError, version-change, constraint violation\n // — all surface as a transaction abort. One-shot dev warn so\n // the developer notices instead of silently losing writes.\n if (__DEV__ && !warnedOnWriteFailure) {\n warnedOnWriteFailure = true\n console.warn(\n '[attaform] IndexedDB transaction aborted; subsequent writes will silently no-op. ' +\n 'Common cause: storage quota exceeded.',\n tx.error\n )\n }\n resolve()\n }\n tx.onerror = () => resolve()\n })\n )\n}\n\nexport function createIndexedDbAdapter(): FormStorage {\n return {\n async getItem(key) {\n return await runReadOp<unknown>((store) => store.get(key) as IDBRequest<unknown>)\n },\n async setItem(key, value) {\n await runWriteOp((store) => void store.put(value, key))\n },\n async removeItem(key) {\n await runWriteOp((store) => void store.delete(key))\n },\n async listKeys(prefix) {\n // `IDBKeyRange.bound(prefix, prefix + '')` would skip attaform\n // keys that contain the U+FFFF code unit; safer to fetch all\n // keys and filter in-process. The attaform-managed key namespace is\n // tiny in practice, so the cost is negligible.\n const all = await runReadOp<IDBValidKey[]>(\n (store) => store.getAllKeys() as IDBRequest<IDBValidKey[]>\n )\n if (all === undefined) return []\n const out: string[] = []\n for (const k of all) {\n if (typeof k === 'string' && k.startsWith(prefix)) out.push(k)\n }\n return out\n },\n }\n}\n\n/**\n * Test hook: reset the cached DB promise so a subsequent call re-\n * opens the database. Production code should never call this —\n * exposed for `fake-indexeddb`-backed tests that tear down the\n * in-memory DB between cases.\n */\nexport function __resetIndexedDbForTests(): void {\n dbPromise = null\n warnedOnOpenFailure = false\n warnedOnWriteFailure = false\n}\n"],"names":["__DEV__"],"mappings":"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"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { _ as __DEV__ } from '../shared/attaform.al_rpt7_.mjs';
|
|
2
|
+
|
|
3
|
+
const DB_NAME = "attaform";
|
|
4
|
+
const STORE_NAME = "kv";
|
|
5
|
+
const DB_VERSION = 1;
|
|
6
|
+
let dbPromise = null;
|
|
7
|
+
let warnedOnOpenFailure = false;
|
|
8
|
+
let warnedOnWriteFailure = false;
|
|
9
|
+
function openDb() {
|
|
10
|
+
if (dbPromise !== null) return dbPromise;
|
|
11
|
+
if (typeof indexedDB === "undefined") {
|
|
12
|
+
dbPromise = Promise.resolve(null);
|
|
13
|
+
return dbPromise;
|
|
14
|
+
}
|
|
15
|
+
dbPromise = new Promise((resolve) => {
|
|
16
|
+
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
17
|
+
request.onupgradeneeded = () => {
|
|
18
|
+
const db = request.result;
|
|
19
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
20
|
+
db.createObjectStore(STORE_NAME);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
request.onsuccess = () => resolve(request.result);
|
|
24
|
+
request.onerror = () => {
|
|
25
|
+
if (__DEV__ && !warnedOnOpenFailure) {
|
|
26
|
+
warnedOnOpenFailure = true;
|
|
27
|
+
console.warn(
|
|
28
|
+
"[attaform] IndexedDB open failed; persistence disabled. Common causes: private-mode disabled IDB, browser quota policy.",
|
|
29
|
+
request.error
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
resolve(null);
|
|
33
|
+
};
|
|
34
|
+
request.onblocked = () => {
|
|
35
|
+
if (__DEV__ && !warnedOnOpenFailure) {
|
|
36
|
+
warnedOnOpenFailure = true;
|
|
37
|
+
console.warn(
|
|
38
|
+
"[attaform] IndexedDB open blocked (another tab holds an older version); persistence disabled until the conflict resolves."
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
dbPromise = null;
|
|
42
|
+
resolve(null);
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
return dbPromise;
|
|
46
|
+
}
|
|
47
|
+
function runReadOp(fn) {
|
|
48
|
+
return openDb().then(
|
|
49
|
+
(db) => new Promise((resolve) => {
|
|
50
|
+
if (db === null) return resolve(void 0);
|
|
51
|
+
let tx;
|
|
52
|
+
try {
|
|
53
|
+
tx = db.transaction(STORE_NAME, "readonly");
|
|
54
|
+
} catch {
|
|
55
|
+
return resolve(void 0);
|
|
56
|
+
}
|
|
57
|
+
const store = tx.objectStore(STORE_NAME);
|
|
58
|
+
const request = fn(store);
|
|
59
|
+
request.onsuccess = () => resolve(request.result);
|
|
60
|
+
request.onerror = () => resolve(void 0);
|
|
61
|
+
tx.onerror = () => resolve(void 0);
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function runWriteOp(fn) {
|
|
66
|
+
return openDb().then(
|
|
67
|
+
(db) => new Promise((resolve) => {
|
|
68
|
+
if (db === null) return resolve();
|
|
69
|
+
let tx;
|
|
70
|
+
try {
|
|
71
|
+
tx = db.transaction(STORE_NAME, "readwrite");
|
|
72
|
+
} catch {
|
|
73
|
+
return resolve();
|
|
74
|
+
}
|
|
75
|
+
fn(tx.objectStore(STORE_NAME));
|
|
76
|
+
tx.oncomplete = () => resolve();
|
|
77
|
+
tx.onabort = () => {
|
|
78
|
+
if (__DEV__ && !warnedOnWriteFailure) {
|
|
79
|
+
warnedOnWriteFailure = true;
|
|
80
|
+
console.warn(
|
|
81
|
+
"[attaform] IndexedDB transaction aborted; subsequent writes will silently no-op. Common cause: storage quota exceeded.",
|
|
82
|
+
tx.error
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
resolve();
|
|
86
|
+
};
|
|
87
|
+
tx.onerror = () => resolve();
|
|
88
|
+
})
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
function createIndexedDbAdapter() {
|
|
92
|
+
return {
|
|
93
|
+
async getItem(key) {
|
|
94
|
+
return await runReadOp((store) => store.get(key));
|
|
95
|
+
},
|
|
96
|
+
async setItem(key, value) {
|
|
97
|
+
await runWriteOp((store) => void store.put(value, key));
|
|
98
|
+
},
|
|
99
|
+
async removeItem(key) {
|
|
100
|
+
await runWriteOp((store) => void store.delete(key));
|
|
101
|
+
},
|
|
102
|
+
async listKeys(prefix) {
|
|
103
|
+
const all = await runReadOp(
|
|
104
|
+
(store) => store.getAllKeys()
|
|
105
|
+
);
|
|
106
|
+
if (all === void 0) return [];
|
|
107
|
+
const out = [];
|
|
108
|
+
for (const k of all) {
|
|
109
|
+
if (typeof k === "string" && k.startsWith(prefix)) out.push(k);
|
|
110
|
+
}
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export { createIndexedDbAdapter };
|
|
117
|
+
//# sourceMappingURL=indexeddb.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexeddb.mjs","sources":["../../src/runtime/core/persistence/indexeddb.ts"],"sourcesContent":["import { __DEV__ } from '../dev'\nimport type { FormStorage } from '../../types/types-api'\n\n/**\n * Zero-dependency IndexedDB adapter. A single shared DB\n * (`attaform`) with a single object store (`kv`). Entries are\n * structured-cloned on write, so `Date` / `Map` / `Set` / typed\n * arrays / nested arrays round-trip without JSON flattening.\n *\n * Size budget: ≤1 KB gzip (verified via size-limit). Consumers who\n * want richer IDB features (indexes, cursors, transactions) should\n * roll their own `FormStorage`.\n *\n * Open failures (private mode, blocked DB, unsupported environment)\n * resolve `dbPromise` to `null`; subsequent reads/writes silently\n * no-op so the form stays usable. A one-shot dev warning surfaces\n * the degradation so the developer notices.\n */\n\nconst DB_NAME = 'attaform'\nconst STORE_NAME = 'kv'\nconst DB_VERSION = 1\n\nlet dbPromise: Promise<IDBDatabase | null> | null = null\n// One-shot dev-warn flags for adapter-level failures. Module-scoped\n// so the warning only fires once per process — re-opening the DB\n// after `__resetIndexedDbForTests` clears `dbPromise` but leaves\n// these flags alone (tests that want a fresh warn-state should\n// reset them via the test hook below).\nlet warnedOnOpenFailure = false\nlet warnedOnWriteFailure = false\n\nfunction openDb(): Promise<IDBDatabase | null> {\n if (dbPromise !== null) return dbPromise\n if (typeof indexedDB === 'undefined') {\n dbPromise = Promise.resolve(null)\n return dbPromise\n }\n dbPromise = new Promise<IDBDatabase | null>((resolve) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION)\n request.onupgradeneeded = () => {\n const db = request.result\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME)\n }\n }\n request.onsuccess = () => resolve(request.result)\n request.onerror = () => {\n // Drop to null so subsequent calls don't retry a broken open —\n // the form just runs without persistence.\n if (__DEV__ && !warnedOnOpenFailure) {\n warnedOnOpenFailure = true\n console.warn(\n '[attaform] IndexedDB open failed; persistence disabled. ' +\n 'Common causes: private-mode disabled IDB, browser quota policy.',\n request.error\n )\n }\n resolve(null)\n }\n request.onblocked = () => {\n if (__DEV__ && !warnedOnOpenFailure) {\n warnedOnOpenFailure = true\n console.warn(\n '[attaform] IndexedDB open blocked (another tab holds an older version); persistence disabled until the conflict resolves.'\n )\n }\n // `onblocked` is transient — the holding tab can close at any\n // moment. Clear the cache so the next persistence call retries\n // the open instead of permanently no-opping.\n dbPromise = null\n resolve(null)\n }\n })\n return dbPromise\n}\n\n/**\n * Read path: resolve on `request.onsuccess` with the fetched value.\n * `readonly` transactions are atomic by nature — there's no commit\n * phase to worry about, so waiting for the transaction's\n * `oncomplete` would be redundant.\n */\nfunction runReadOp<T>(fn: (store: IDBObjectStore) => IDBRequest<T>): Promise<T | undefined> {\n return openDb().then(\n (db) =>\n new Promise<T | undefined>((resolve) => {\n if (db === null) return resolve(undefined)\n let tx: IDBTransaction\n try {\n tx = db.transaction(STORE_NAME, 'readonly')\n } catch {\n return resolve(undefined)\n }\n const store = tx.objectStore(STORE_NAME)\n const request = fn(store)\n request.onsuccess = () => resolve(request.result)\n request.onerror = () => resolve(undefined)\n tx.onerror = () => resolve(undefined)\n })\n )\n}\n\n/**\n * Write path: resolve on `tx.oncomplete` (the spec-defined commit\n * signal), NOT on `request.onsuccess` (which fires per-request,\n * before the transaction commits).\n *\n * Resolving on `onsuccess` means a tab close, power loss, or\n * browser crash between the request succeeding and the transaction\n * committing silently loses the write — the Promise already\n * resolved successfully. Aborts (quota exceeded, version change,\n * constraint violation) likewise roll back after `onsuccess` fired.\n *\n * Resolving on `oncomplete` makes durability a precondition for\n * the Promise settlement; `onabort` catches the failure cases so\n * the Promise resolves to `undefined` instead of hanging.\n */\nfunction runWriteOp(fn: (store: IDBObjectStore) => void): Promise<void> {\n return openDb().then(\n (db) =>\n new Promise<void>((resolve) => {\n if (db === null) return resolve()\n let tx: IDBTransaction\n try {\n tx = db.transaction(STORE_NAME, 'readwrite')\n } catch {\n return resolve()\n }\n fn(tx.objectStore(STORE_NAME))\n tx.oncomplete = () => resolve()\n tx.onabort = () => {\n // QuotaExceededError, version-change, constraint violation\n // — all surface as a transaction abort. One-shot dev warn so\n // the developer notices instead of silently losing writes.\n if (__DEV__ && !warnedOnWriteFailure) {\n warnedOnWriteFailure = true\n console.warn(\n '[attaform] IndexedDB transaction aborted; subsequent writes will silently no-op. ' +\n 'Common cause: storage quota exceeded.',\n tx.error\n )\n }\n resolve()\n }\n tx.onerror = () => resolve()\n })\n )\n}\n\nexport function createIndexedDbAdapter(): FormStorage {\n return {\n async getItem(key) {\n return await runReadOp<unknown>((store) => store.get(key) as IDBRequest<unknown>)\n },\n async setItem(key, value) {\n await runWriteOp((store) => void store.put(value, key))\n },\n async removeItem(key) {\n await runWriteOp((store) => void store.delete(key))\n },\n async listKeys(prefix) {\n // `IDBKeyRange.bound(prefix, prefix + '')` would skip attaform\n // keys that contain the U+FFFF code unit; safer to fetch all\n // keys and filter in-process. The attaform-managed key namespace is\n // tiny in practice, so the cost is negligible.\n const all = await runReadOp<IDBValidKey[]>(\n (store) => store.getAllKeys() as IDBRequest<IDBValidKey[]>\n )\n if (all === undefined) return []\n const out: string[] = []\n for (const k of all) {\n if (typeof k === 'string' && k.startsWith(prefix)) out.push(k)\n }\n return out\n },\n }\n}\n\n/**\n * Test hook: reset the cached DB promise so a subsequent call re-\n * opens the database. Production code should never call this —\n * exposed for `fake-indexeddb`-backed tests that tear down the\n * in-memory DB between cases.\n */\nexport function __resetIndexedDbForTests(): void {\n dbPromise = null\n warnedOnOpenFailure = false\n warnedOnWriteFailure = false\n}\n"],"names":[],"mappings":";;AAmBA,MAAM,OAAA,GAAU,UAAA;AAChB,MAAM,UAAA,GAAa,IAAA;AACnB,MAAM,UAAA,GAAa,CAAA;AAEnB,IAAI,SAAA,GAAgD,IAAA;AAMpD,IAAI,mBAAA,GAAsB,KAAA;AAC1B,IAAI,oBAAA,GAAuB,KAAA;AAE3B,SAAS,MAAA,GAAsC;AAC7C,EAAA,IAAI,SAAA,KAAc,MAAM,OAAO,SAAA;AAC/B,EAAA,IAAI,OAAO,cAAc,WAAA,EAAa;AACpC,IAAA,SAAA,GAAY,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAChC,IAAA,OAAO,SAAA;AAAA,EACT;AACA,EAAA,SAAA,GAAY,IAAI,OAAA,CAA4B,CAAC,OAAA,KAAY;AACvD,IAAA,MAAM,OAAA,GAAU,SAAA,CAAU,IAAA,CAAK,OAAA,EAAS,UAAU,CAAA;AAClD,IAAA,OAAA,CAAQ,kBAAkB,MAAM;AAC9B,MAAA,MAAM,KAAK,OAAA,CAAQ,MAAA;AACnB,MAAA,IAAI,CAAC,EAAA,CAAG,gBAAA,CAAiB,QAAA,CAAS,UAAU,CAAA,EAAG;AAC7C,QAAA,EAAA,CAAG,kBAAkB,UAAU,CAAA;AAAA,MACjC;AAAA,IACF,CAAA;AACA,IAAA,OAAA,CAAQ,SAAA,GAAY,MAAM,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA;AAChD,IAAA,OAAA,CAAQ,UAAU,MAAM;AAGtB,MAAA,IAAI,OAAA,IAAW,CAAC,mBAAA,EAAqB;AACnC,QAAA,mBAAA,GAAsB,IAAA;AACtB,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,yHAAA;AAAA,UAEA,OAAA,CAAQ;AAAA,SACV;AAAA,MACF;AACA,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IACd,CAAA;AACA,IAAA,OAAA,CAAQ,YAAY,MAAM;AACxB,MAAA,IAAI,OAAA,IAAW,CAAC,mBAAA,EAAqB;AACnC,QAAA,mBAAA,GAAsB,IAAA;AACtB,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN;AAAA,SACF;AAAA,MACF;AAIA,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IACd,CAAA;AAAA,EACF,CAAC,CAAA;AACD,EAAA,OAAO,SAAA;AACT;AAQA,SAAS,UAAa,EAAA,EAAsE;AAC1F,EAAA,OAAO,QAAO,CAAE,IAAA;AAAA,IACd,CAAC,EAAA,KACC,IAAI,OAAA,CAAuB,CAAC,OAAA,KAAY;AACtC,MAAA,IAAI,EAAA,KAAO,IAAA,EAAM,OAAO,OAAA,CAAQ,MAAS,CAAA;AACzC,MAAA,IAAI,EAAA;AACJ,MAAA,IAAI;AACF,QAAA,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,UAAA,EAAY,UAAU,CAAA;AAAA,MAC5C,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,QAAQ,MAAS,CAAA;AAAA,MAC1B;AACA,MAAA,MAAM,KAAA,GAAQ,EAAA,CAAG,WAAA,CAAY,UAAU,CAAA;AACvC,MAAA,MAAM,OAAA,GAAU,GAAG,KAAK,CAAA;AACxB,MAAA,OAAA,CAAQ,SAAA,GAAY,MAAM,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA;AAChD,MAAA,OAAA,CAAQ,OAAA,GAAU,MAAM,OAAA,CAAQ,MAAS,CAAA;AACzC,MAAA,EAAA,CAAG,OAAA,GAAU,MAAM,OAAA,CAAQ,MAAS,CAAA;AAAA,IACtC,CAAC;AAAA,GACL;AACF;AAiBA,SAAS,WAAW,EAAA,EAAoD;AACtE,EAAA,OAAO,QAAO,CAAE,IAAA;AAAA,IACd,CAAC,EAAA,KACC,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AAC7B,MAAA,IAAI,EAAA,KAAO,IAAA,EAAM,OAAO,OAAA,EAAQ;AAChC,MAAA,IAAI,EAAA;AACJ,MAAA,IAAI;AACF,QAAA,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,UAAA,EAAY,WAAW,CAAA;AAAA,MAC7C,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,OAAA,EAAQ;AAAA,MACjB;AACA,MAAA,EAAA,CAAG,EAAA,CAAG,WAAA,CAAY,UAAU,CAAC,CAAA;AAC7B,MAAA,EAAA,CAAG,UAAA,GAAa,MAAM,OAAA,EAAQ;AAC9B,MAAA,EAAA,CAAG,UAAU,MAAM;AAIjB,QAAA,IAAI,OAAA,IAAW,CAAC,oBAAA,EAAsB;AACpC,UAAA,oBAAA,GAAuB,IAAA;AACvB,UAAA,OAAA,CAAQ,IAAA;AAAA,YACN,wHAAA;AAAA,YAEA,EAAA,CAAG;AAAA,WACL;AAAA,QACF;AACA,QAAA,OAAA,EAAQ;AAAA,MACV,CAAA;AACA,MAAA,EAAA,CAAG,OAAA,GAAU,MAAM,OAAA,EAAQ;AAAA,IAC7B,CAAC;AAAA,GACL;AACF;AAEO,SAAS,sBAAA,GAAsC;AACpD,EAAA,OAAO;AAAA,IACL,MAAM,QAAQ,GAAA,EAAK;AACjB,MAAA,OAAO,MAAM,SAAA,CAAmB,CAAC,UAAU,KAAA,CAAM,GAAA,CAAI,GAAG,CAAwB,CAAA;AAAA,IAClF,CAAA;AAAA,IACA,MAAM,OAAA,CAAQ,GAAA,EAAK,KAAA,EAAO;AACxB,MAAA,MAAM,UAAA,CAAW,CAAC,KAAA,KAAU,KAAK,MAAM,GAAA,CAAI,KAAA,EAAO,GAAG,CAAC,CAAA;AAAA,IACxD,CAAA;AAAA,IACA,MAAM,WAAW,GAAA,EAAK;AACpB,MAAA,MAAM,WAAW,CAAC,KAAA,KAAU,KAAK,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,IACpD,CAAA;AAAA,IACA,MAAM,SAAS,MAAA,EAAQ;AAKrB,MAAA,MAAM,MAAM,MAAM,SAAA;AAAA,QAChB,CAAC,KAAA,KAAU,KAAA,CAAM,UAAA;AAAW,OAC9B;AACA,MAAA,IAAI,GAAA,KAAQ,MAAA,EAAW,OAAO,EAAC;AAC/B,MAAA,MAAM,MAAgB,EAAC;AACvB,MAAA,KAAA,MAAW,KAAK,GAAA,EAAK;AACnB,QAAA,IAAI,OAAO,MAAM,QAAA,IAAY,CAAA,CAAE,WAAW,MAAM,CAAA,EAAG,GAAA,CAAI,IAAA,CAAK,CAAC,CAAA;AAAA,MAC/D;AACA,MAAA,OAAO,GAAA;AAAA,IACT;AAAA,GACF;AACF;;;;"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const sensitiveNames = require('../shared/attaform.B5GWYl76.cjs');
|
|
4
|
+
|
|
5
|
+
function createLocalStorageAdapter() {
|
|
6
|
+
const available = typeof localStorage !== "undefined";
|
|
7
|
+
let warnedOnFailure = false;
|
|
8
|
+
return {
|
|
9
|
+
getItem(key) {
|
|
10
|
+
if (!available) return Promise.resolve(void 0);
|
|
11
|
+
try {
|
|
12
|
+
const raw = localStorage.getItem(key);
|
|
13
|
+
if (raw === null) return Promise.resolve(void 0);
|
|
14
|
+
return Promise.resolve(JSON.parse(raw));
|
|
15
|
+
} catch {
|
|
16
|
+
return Promise.resolve(void 0);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
setItem(key, value) {
|
|
20
|
+
if (!available) return Promise.resolve();
|
|
21
|
+
try {
|
|
22
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
23
|
+
} catch (err) {
|
|
24
|
+
if (sensitiveNames.__DEV__ && !warnedOnFailure) {
|
|
25
|
+
warnedOnFailure = true;
|
|
26
|
+
console.warn(
|
|
27
|
+
'[attaform] localStorage write failed; subsequent writes will silently no-op for this form. Common causes: quota exceeded, private-mode storage lock. Switch to `persist: "indexeddb"` for larger payloads.',
|
|
28
|
+
err
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return Promise.resolve();
|
|
33
|
+
},
|
|
34
|
+
removeItem(key) {
|
|
35
|
+
if (!available) return Promise.resolve();
|
|
36
|
+
try {
|
|
37
|
+
localStorage.removeItem(key);
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
return Promise.resolve();
|
|
41
|
+
},
|
|
42
|
+
listKeys(prefix) {
|
|
43
|
+
if (!available) return Promise.resolve([]);
|
|
44
|
+
const out = [];
|
|
45
|
+
try {
|
|
46
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
47
|
+
const k = localStorage.key(i);
|
|
48
|
+
if (k !== null && k.startsWith(prefix) === true) out.push(k);
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
return Promise.resolve(out);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.createLocalStorageAdapter = createLocalStorageAdapter;
|
|
58
|
+
//# sourceMappingURL=local-storage.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-storage.cjs","sources":["../../src/runtime/core/persistence/local-storage.ts"],"sourcesContent":["import { __DEV__ } from '../dev'\nimport type { FormStorage } from '../../types/types-api'\n\n/**\n * `localStorage` adapter for `FormStorage`. Wraps the sync Web Storage\n * API in `async` functions — the extra microtask is negligible and the\n * uniform Promise contract means every caller handles backends the same\n * way.\n *\n * Serialises payloads with `JSON.stringify`. Callers pass plain data;\n * non-JSON values (`Date` / `Map` / `Set` / typed arrays) round-trip as\n * strings / objects. Switch to the `indexeddb` backend if you need\n * structured-clone fidelity.\n *\n * Missing / unavailable `localStorage` (Node, Safari private mode in\n * older versions, disabled by the user) is handled by a `typeof` gate;\n * every method becomes a no-op so the form stays usable.\n *\n * On the FIRST `setItem` failure (quota exceeded, security error in\n * private mode), the adapter logs a one-shot dev warning so the\n * developer notices instead of silently losing data. Subsequent\n * failures stay silent — bouncing a warning per keystroke would be\n * worse than the original silent-fail behavior.\n */\nexport function createLocalStorageAdapter(): FormStorage {\n const available = typeof localStorage !== 'undefined'\n // Per-adapter flag: trips on the first setItem failure and stays\n // tripped for the lifetime of the adapter instance.\n let warnedOnFailure = false\n return {\n getItem(key) {\n if (!available) return Promise.resolve(undefined)\n try {\n const raw = localStorage.getItem(key)\n if (raw === null) return Promise.resolve(undefined)\n return Promise.resolve(JSON.parse(raw) as unknown)\n } catch {\n // JSON.parse failure or SecurityError — drop the stale entry so\n // the next write can replace it. Caller handles undefined as\n // \"no persisted state\".\n return Promise.resolve(undefined)\n }\n },\n setItem(key, value) {\n if (!available) return Promise.resolve()\n try {\n localStorage.setItem(key, JSON.stringify(value))\n } catch (err) {\n // Quota-exceeded or SecurityError — swallow at runtime. In dev,\n // surface the first failure so the developer knows persistence\n // has degraded. Silent on subsequent failures (debounced writes\n // would otherwise spam the console once per keystroke).\n if (__DEV__ && !warnedOnFailure) {\n warnedOnFailure = true\n console.warn(\n '[attaform] localStorage write failed; subsequent writes will silently no-op for this form. ' +\n 'Common causes: quota exceeded, private-mode storage lock. ' +\n 'Switch to `persist: \"indexeddb\"` for larger payloads.',\n err\n )\n }\n }\n return Promise.resolve()\n },\n removeItem(key) {\n if (!available) return Promise.resolve()\n try {\n localStorage.removeItem(key)\n } catch {\n // Private-mode write guards occasionally throw here too.\n }\n return Promise.resolve()\n },\n listKeys(prefix) {\n if (!available) return Promise.resolve([])\n const out: string[] = []\n try {\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i)\n if (k !== null && k.startsWith(prefix) === true) out.push(k)\n }\n } catch {\n // SecurityError under private-mode locks.\n }\n return Promise.resolve(out)\n },\n }\n}\n"],"names":["__DEV__"],"mappings":";;;;AAwBO,SAAS,yBAAA,GAAyC;AACvD,EAAA,MAAM,SAAA,GAAY,OAAO,YAAA,KAAiB,WAAA;AAG1C,EAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,EAAK;AACX,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAChD,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,GAAG,CAAA;AACpC,QAAA,IAAI,GAAA,KAAQ,IAAA,EAAM,OAAO,OAAA,CAAQ,QAAQ,KAAA,CAAS,CAAA;AAClD,QAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAY,CAAA;AAAA,MACnD,CAAA,CAAA,MAAQ;AAIN,QAAA,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAAA,MAClC;AAAA,IACF,CAAA;AAAA,IACA,OAAA,CAAQ,KAAK,KAAA,EAAO;AAClB,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,EAAQ;AACvC,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,OAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,MACjD,SAAS,GAAA,EAAK;AAKZ,QAAA,IAAIA,sBAAA,IAAW,CAAC,eAAA,EAAiB;AAC/B,UAAA,eAAA,GAAkB,IAAA;AAClB,UAAA,OAAA,CAAQ,IAAA;AAAA,YACN,4MAAA;AAAA,YAGA;AAAA,WACF;AAAA,QACF;AAAA,MACF;AACA,MAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,IACzB,CAAA;AAAA,IACA,WAAW,GAAA,EAAK;AACd,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,EAAQ;AACvC,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,MAC7B,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,IACzB,CAAA;AAAA,IACA,SAAS,MAAA,EAAQ;AACf,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,CAAQ,EAAE,CAAA;AACzC,MAAA,MAAM,MAAgB,EAAC;AACvB,MAAA,IAAI;AACF,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK;AAC5C,UAAA,MAAM,CAAA,GAAI,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA;AAC5B,UAAA,IAAI,CAAA,KAAM,QAAQ,CAAA,CAAE,UAAA,CAAW,MAAM,CAAA,KAAM,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAA;AAAA,QAC7D;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,IAC5B;AAAA,GACF;AACF;;;;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { _ as __DEV__ } from '../shared/attaform.al_rpt7_.mjs';
|
|
2
|
+
|
|
3
|
+
function createLocalStorageAdapter() {
|
|
4
|
+
const available = typeof localStorage !== "undefined";
|
|
5
|
+
let warnedOnFailure = false;
|
|
6
|
+
return {
|
|
7
|
+
getItem(key) {
|
|
8
|
+
if (!available) return Promise.resolve(void 0);
|
|
9
|
+
try {
|
|
10
|
+
const raw = localStorage.getItem(key);
|
|
11
|
+
if (raw === null) return Promise.resolve(void 0);
|
|
12
|
+
return Promise.resolve(JSON.parse(raw));
|
|
13
|
+
} catch {
|
|
14
|
+
return Promise.resolve(void 0);
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
setItem(key, value) {
|
|
18
|
+
if (!available) return Promise.resolve();
|
|
19
|
+
try {
|
|
20
|
+
localStorage.setItem(key, JSON.stringify(value));
|
|
21
|
+
} catch (err) {
|
|
22
|
+
if (__DEV__ && !warnedOnFailure) {
|
|
23
|
+
warnedOnFailure = true;
|
|
24
|
+
console.warn(
|
|
25
|
+
'[attaform] localStorage write failed; subsequent writes will silently no-op for this form. Common causes: quota exceeded, private-mode storage lock. Switch to `persist: "indexeddb"` for larger payloads.',
|
|
26
|
+
err
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return Promise.resolve();
|
|
31
|
+
},
|
|
32
|
+
removeItem(key) {
|
|
33
|
+
if (!available) return Promise.resolve();
|
|
34
|
+
try {
|
|
35
|
+
localStorage.removeItem(key);
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
return Promise.resolve();
|
|
39
|
+
},
|
|
40
|
+
listKeys(prefix) {
|
|
41
|
+
if (!available) return Promise.resolve([]);
|
|
42
|
+
const out = [];
|
|
43
|
+
try {
|
|
44
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
45
|
+
const k = localStorage.key(i);
|
|
46
|
+
if (k !== null && k.startsWith(prefix) === true) out.push(k);
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
return Promise.resolve(out);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { createLocalStorageAdapter };
|
|
56
|
+
//# sourceMappingURL=local-storage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-storage.mjs","sources":["../../src/runtime/core/persistence/local-storage.ts"],"sourcesContent":["import { __DEV__ } from '../dev'\nimport type { FormStorage } from '../../types/types-api'\n\n/**\n * `localStorage` adapter for `FormStorage`. Wraps the sync Web Storage\n * API in `async` functions — the extra microtask is negligible and the\n * uniform Promise contract means every caller handles backends the same\n * way.\n *\n * Serialises payloads with `JSON.stringify`. Callers pass plain data;\n * non-JSON values (`Date` / `Map` / `Set` / typed arrays) round-trip as\n * strings / objects. Switch to the `indexeddb` backend if you need\n * structured-clone fidelity.\n *\n * Missing / unavailable `localStorage` (Node, Safari private mode in\n * older versions, disabled by the user) is handled by a `typeof` gate;\n * every method becomes a no-op so the form stays usable.\n *\n * On the FIRST `setItem` failure (quota exceeded, security error in\n * private mode), the adapter logs a one-shot dev warning so the\n * developer notices instead of silently losing data. Subsequent\n * failures stay silent — bouncing a warning per keystroke would be\n * worse than the original silent-fail behavior.\n */\nexport function createLocalStorageAdapter(): FormStorage {\n const available = typeof localStorage !== 'undefined'\n // Per-adapter flag: trips on the first setItem failure and stays\n // tripped for the lifetime of the adapter instance.\n let warnedOnFailure = false\n return {\n getItem(key) {\n if (!available) return Promise.resolve(undefined)\n try {\n const raw = localStorage.getItem(key)\n if (raw === null) return Promise.resolve(undefined)\n return Promise.resolve(JSON.parse(raw) as unknown)\n } catch {\n // JSON.parse failure or SecurityError — drop the stale entry so\n // the next write can replace it. Caller handles undefined as\n // \"no persisted state\".\n return Promise.resolve(undefined)\n }\n },\n setItem(key, value) {\n if (!available) return Promise.resolve()\n try {\n localStorage.setItem(key, JSON.stringify(value))\n } catch (err) {\n // Quota-exceeded or SecurityError — swallow at runtime. In dev,\n // surface the first failure so the developer knows persistence\n // has degraded. Silent on subsequent failures (debounced writes\n // would otherwise spam the console once per keystroke).\n if (__DEV__ && !warnedOnFailure) {\n warnedOnFailure = true\n console.warn(\n '[attaform] localStorage write failed; subsequent writes will silently no-op for this form. ' +\n 'Common causes: quota exceeded, private-mode storage lock. ' +\n 'Switch to `persist: \"indexeddb\"` for larger payloads.',\n err\n )\n }\n }\n return Promise.resolve()\n },\n removeItem(key) {\n if (!available) return Promise.resolve()\n try {\n localStorage.removeItem(key)\n } catch {\n // Private-mode write guards occasionally throw here too.\n }\n return Promise.resolve()\n },\n listKeys(prefix) {\n if (!available) return Promise.resolve([])\n const out: string[] = []\n try {\n for (let i = 0; i < localStorage.length; i++) {\n const k = localStorage.key(i)\n if (k !== null && k.startsWith(prefix) === true) out.push(k)\n }\n } catch {\n // SecurityError under private-mode locks.\n }\n return Promise.resolve(out)\n },\n }\n}\n"],"names":[],"mappings":";;AAwBO,SAAS,yBAAA,GAAyC;AACvD,EAAA,MAAM,SAAA,GAAY,OAAO,YAAA,KAAiB,WAAA;AAG1C,EAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,EAAK;AACX,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAChD,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,GAAG,CAAA;AACpC,QAAA,IAAI,GAAA,KAAQ,IAAA,EAAM,OAAO,OAAA,CAAQ,QAAQ,KAAA,CAAS,CAAA;AAClD,QAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAY,CAAA;AAAA,MACnD,CAAA,CAAA,MAAQ;AAIN,QAAA,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAAA,MAClC;AAAA,IACF,CAAA;AAAA,IACA,OAAA,CAAQ,KAAK,KAAA,EAAO;AAClB,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,EAAQ;AACvC,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,OAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,MACjD,SAAS,GAAA,EAAK;AAKZ,QAAA,IAAI,OAAA,IAAW,CAAC,eAAA,EAAiB;AAC/B,UAAA,eAAA,GAAkB,IAAA;AAClB,UAAA,OAAA,CAAQ,IAAA;AAAA,YACN,4MAAA;AAAA,YAGA;AAAA,WACF;AAAA,QACF;AAAA,MACF;AACA,MAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,IACzB,CAAA;AAAA,IACA,WAAW,GAAA,EAAK;AACd,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,EAAQ;AACvC,MAAA,IAAI;AACF,QAAA,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,MAC7B,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,IACzB,CAAA;AAAA,IACA,SAAS,MAAA,EAAQ;AACf,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,CAAQ,EAAE,CAAA;AACzC,MAAA,MAAM,MAAgB,EAAC;AACvB,MAAA,IAAI;AACF,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK;AAC5C,UAAA,MAAM,CAAA,GAAI,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA;AAC5B,UAAA,IAAI,CAAA,KAAM,QAAQ,CAAA,CAAE,UAAA,CAAW,MAAM,CAAA,KAAM,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAA;AAAA,QAC7D;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,IAC5B;AAAA,GACF;AACF;;;;"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const sensitiveNames = require('../shared/attaform.B5GWYl76.cjs');
|
|
4
|
+
|
|
5
|
+
function createSessionStorageAdapter() {
|
|
6
|
+
const available = typeof sessionStorage !== "undefined";
|
|
7
|
+
let warnedOnFailure = false;
|
|
8
|
+
return {
|
|
9
|
+
getItem(key) {
|
|
10
|
+
if (!available) return Promise.resolve(void 0);
|
|
11
|
+
try {
|
|
12
|
+
const raw = sessionStorage.getItem(key);
|
|
13
|
+
if (raw === null) return Promise.resolve(void 0);
|
|
14
|
+
return Promise.resolve(JSON.parse(raw));
|
|
15
|
+
} catch {
|
|
16
|
+
return Promise.resolve(void 0);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
setItem(key, value) {
|
|
20
|
+
if (!available) return Promise.resolve();
|
|
21
|
+
try {
|
|
22
|
+
sessionStorage.setItem(key, JSON.stringify(value));
|
|
23
|
+
} catch (err) {
|
|
24
|
+
if (sensitiveNames.__DEV__ && !warnedOnFailure) {
|
|
25
|
+
warnedOnFailure = true;
|
|
26
|
+
console.warn(
|
|
27
|
+
"[attaform] sessionStorage write failed; subsequent writes will silently no-op for this form. Common causes: quota exceeded, private-mode storage lock.",
|
|
28
|
+
err
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return Promise.resolve();
|
|
33
|
+
},
|
|
34
|
+
removeItem(key) {
|
|
35
|
+
if (!available) return Promise.resolve();
|
|
36
|
+
try {
|
|
37
|
+
sessionStorage.removeItem(key);
|
|
38
|
+
} catch {
|
|
39
|
+
}
|
|
40
|
+
return Promise.resolve();
|
|
41
|
+
},
|
|
42
|
+
listKeys(prefix) {
|
|
43
|
+
if (!available) return Promise.resolve([]);
|
|
44
|
+
const out = [];
|
|
45
|
+
try {
|
|
46
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
47
|
+
const k = sessionStorage.key(i);
|
|
48
|
+
if (k !== null && k.startsWith(prefix) === true) out.push(k);
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
return Promise.resolve(out);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.createSessionStorageAdapter = createSessionStorageAdapter;
|
|
58
|
+
//# sourceMappingURL=session-storage.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-storage.cjs","sources":["../../src/runtime/core/persistence/session-storage.ts"],"sourcesContent":["import { __DEV__ } from '../dev'\nimport type { FormStorage } from '../../types/types-api'\n\n/**\n * `sessionStorage` adapter — identical shape to the `localStorage`\n * adapter, different backing store. Tab-scoped: closing the tab\n * drops the entry. Useful for multi-step flows where the user\n * shouldn't see last-session state on a fresh open.\n *\n * Same one-shot dev-warn semantic on setItem failure as the\n * localStorage adapter — see that file's header for rationale.\n */\nexport function createSessionStorageAdapter(): FormStorage {\n const available = typeof sessionStorage !== 'undefined'\n let warnedOnFailure = false\n return {\n getItem(key) {\n if (!available) return Promise.resolve(undefined)\n try {\n const raw = sessionStorage.getItem(key)\n if (raw === null) return Promise.resolve(undefined)\n return Promise.resolve(JSON.parse(raw) as unknown)\n } catch {\n return Promise.resolve(undefined)\n }\n },\n setItem(key, value) {\n if (!available) return Promise.resolve()\n try {\n sessionStorage.setItem(key, JSON.stringify(value))\n } catch (err) {\n if (__DEV__ && !warnedOnFailure) {\n warnedOnFailure = true\n console.warn(\n '[attaform] sessionStorage write failed; subsequent writes will silently no-op for this form. ' +\n 'Common causes: quota exceeded, private-mode storage lock.',\n err\n )\n }\n }\n return Promise.resolve()\n },\n removeItem(key) {\n if (!available) return Promise.resolve()\n try {\n sessionStorage.removeItem(key)\n } catch {\n // SecurityError in private mode — swallow.\n }\n return Promise.resolve()\n },\n listKeys(prefix) {\n if (!available) return Promise.resolve([])\n const out: string[] = []\n try {\n for (let i = 0; i < sessionStorage.length; i++) {\n const k = sessionStorage.key(i)\n if (k !== null && k.startsWith(prefix) === true) out.push(k)\n }\n } catch {\n // SecurityError under private-mode locks.\n }\n return Promise.resolve(out)\n },\n }\n}\n"],"names":["__DEV__"],"mappings":";;;;AAYO,SAAS,2BAAA,GAA2C;AACzD,EAAA,MAAM,SAAA,GAAY,OAAO,cAAA,KAAmB,WAAA;AAC5C,EAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,EAAK;AACX,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAChD,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,cAAA,CAAe,OAAA,CAAQ,GAAG,CAAA;AACtC,QAAA,IAAI,GAAA,KAAQ,IAAA,EAAM,OAAO,OAAA,CAAQ,QAAQ,KAAA,CAAS,CAAA;AAClD,QAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAY,CAAA;AAAA,MACnD,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAAA,MAClC;AAAA,IACF,CAAA;AAAA,IACA,OAAA,CAAQ,KAAK,KAAA,EAAO;AAClB,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,EAAQ;AACvC,MAAA,IAAI;AACF,QAAA,cAAA,CAAe,OAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,MACnD,SAAS,GAAA,EAAK;AACZ,QAAA,IAAIA,sBAAA,IAAW,CAAC,eAAA,EAAiB;AAC/B,UAAA,eAAA,GAAkB,IAAA;AAClB,UAAA,OAAA,CAAQ,IAAA;AAAA,YACN,wJAAA;AAAA,YAEA;AAAA,WACF;AAAA,QACF;AAAA,MACF;AACA,MAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,IACzB,CAAA;AAAA,IACA,WAAW,GAAA,EAAK;AACd,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,EAAQ;AACvC,MAAA,IAAI;AACF,QAAA,cAAA,CAAe,WAAW,GAAG,CAAA;AAAA,MAC/B,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,IACzB,CAAA;AAAA,IACA,SAAS,MAAA,EAAQ;AACf,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,CAAQ,EAAE,CAAA;AACzC,MAAA,MAAM,MAAgB,EAAC;AACvB,MAAA,IAAI;AACF,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,cAAA,CAAe,QAAQ,CAAA,EAAA,EAAK;AAC9C,UAAA,MAAM,CAAA,GAAI,cAAA,CAAe,GAAA,CAAI,CAAC,CAAA;AAC9B,UAAA,IAAI,CAAA,KAAM,QAAQ,CAAA,CAAE,UAAA,CAAW,MAAM,CAAA,KAAM,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAA;AAAA,QAC7D;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,IAC5B;AAAA,GACF;AACF;;;;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { _ as __DEV__ } from '../shared/attaform.al_rpt7_.mjs';
|
|
2
|
+
|
|
3
|
+
function createSessionStorageAdapter() {
|
|
4
|
+
const available = typeof sessionStorage !== "undefined";
|
|
5
|
+
let warnedOnFailure = false;
|
|
6
|
+
return {
|
|
7
|
+
getItem(key) {
|
|
8
|
+
if (!available) return Promise.resolve(void 0);
|
|
9
|
+
try {
|
|
10
|
+
const raw = sessionStorage.getItem(key);
|
|
11
|
+
if (raw === null) return Promise.resolve(void 0);
|
|
12
|
+
return Promise.resolve(JSON.parse(raw));
|
|
13
|
+
} catch {
|
|
14
|
+
return Promise.resolve(void 0);
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
setItem(key, value) {
|
|
18
|
+
if (!available) return Promise.resolve();
|
|
19
|
+
try {
|
|
20
|
+
sessionStorage.setItem(key, JSON.stringify(value));
|
|
21
|
+
} catch (err) {
|
|
22
|
+
if (__DEV__ && !warnedOnFailure) {
|
|
23
|
+
warnedOnFailure = true;
|
|
24
|
+
console.warn(
|
|
25
|
+
"[attaform] sessionStorage write failed; subsequent writes will silently no-op for this form. Common causes: quota exceeded, private-mode storage lock.",
|
|
26
|
+
err
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return Promise.resolve();
|
|
31
|
+
},
|
|
32
|
+
removeItem(key) {
|
|
33
|
+
if (!available) return Promise.resolve();
|
|
34
|
+
try {
|
|
35
|
+
sessionStorage.removeItem(key);
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
return Promise.resolve();
|
|
39
|
+
},
|
|
40
|
+
listKeys(prefix) {
|
|
41
|
+
if (!available) return Promise.resolve([]);
|
|
42
|
+
const out = [];
|
|
43
|
+
try {
|
|
44
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
45
|
+
const k = sessionStorage.key(i);
|
|
46
|
+
if (k !== null && k.startsWith(prefix) === true) out.push(k);
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
return Promise.resolve(out);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { createSessionStorageAdapter };
|
|
56
|
+
//# sourceMappingURL=session-storage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-storage.mjs","sources":["../../src/runtime/core/persistence/session-storage.ts"],"sourcesContent":["import { __DEV__ } from '../dev'\nimport type { FormStorage } from '../../types/types-api'\n\n/**\n * `sessionStorage` adapter — identical shape to the `localStorage`\n * adapter, different backing store. Tab-scoped: closing the tab\n * drops the entry. Useful for multi-step flows where the user\n * shouldn't see last-session state on a fresh open.\n *\n * Same one-shot dev-warn semantic on setItem failure as the\n * localStorage adapter — see that file's header for rationale.\n */\nexport function createSessionStorageAdapter(): FormStorage {\n const available = typeof sessionStorage !== 'undefined'\n let warnedOnFailure = false\n return {\n getItem(key) {\n if (!available) return Promise.resolve(undefined)\n try {\n const raw = sessionStorage.getItem(key)\n if (raw === null) return Promise.resolve(undefined)\n return Promise.resolve(JSON.parse(raw) as unknown)\n } catch {\n return Promise.resolve(undefined)\n }\n },\n setItem(key, value) {\n if (!available) return Promise.resolve()\n try {\n sessionStorage.setItem(key, JSON.stringify(value))\n } catch (err) {\n if (__DEV__ && !warnedOnFailure) {\n warnedOnFailure = true\n console.warn(\n '[attaform] sessionStorage write failed; subsequent writes will silently no-op for this form. ' +\n 'Common causes: quota exceeded, private-mode storage lock.',\n err\n )\n }\n }\n return Promise.resolve()\n },\n removeItem(key) {\n if (!available) return Promise.resolve()\n try {\n sessionStorage.removeItem(key)\n } catch {\n // SecurityError in private mode — swallow.\n }\n return Promise.resolve()\n },\n listKeys(prefix) {\n if (!available) return Promise.resolve([])\n const out: string[] = []\n try {\n for (let i = 0; i < sessionStorage.length; i++) {\n const k = sessionStorage.key(i)\n if (k !== null && k.startsWith(prefix) === true) out.push(k)\n }\n } catch {\n // SecurityError under private-mode locks.\n }\n return Promise.resolve(out)\n },\n }\n}\n"],"names":[],"mappings":";;AAYO,SAAS,2BAAA,GAA2C;AACzD,EAAA,MAAM,SAAA,GAAY,OAAO,cAAA,KAAmB,WAAA;AAC5C,EAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,EAAA,OAAO;AAAA,IACL,QAAQ,GAAA,EAAK;AACX,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAChD,MAAA,IAAI;AACF,QAAA,MAAM,GAAA,GAAM,cAAA,CAAe,OAAA,CAAQ,GAAG,CAAA;AACtC,QAAA,IAAI,GAAA,KAAQ,IAAA,EAAM,OAAO,OAAA,CAAQ,QAAQ,KAAA,CAAS,CAAA;AAClD,QAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAY,CAAA;AAAA,MACnD,CAAA,CAAA,MAAQ;AACN,QAAA,OAAO,OAAA,CAAQ,QAAQ,MAAS,CAAA;AAAA,MAClC;AAAA,IACF,CAAA;AAAA,IACA,OAAA,CAAQ,KAAK,KAAA,EAAO;AAClB,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,EAAQ;AACvC,MAAA,IAAI;AACF,QAAA,cAAA,CAAe,OAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,MACnD,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,OAAA,IAAW,CAAC,eAAA,EAAiB;AAC/B,UAAA,eAAA,GAAkB,IAAA;AAClB,UAAA,OAAA,CAAQ,IAAA;AAAA,YACN,wJAAA;AAAA,YAEA;AAAA,WACF;AAAA,QACF;AAAA,MACF;AACA,MAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,IACzB,CAAA;AAAA,IACA,WAAW,GAAA,EAAK;AACd,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,EAAQ;AACvC,MAAA,IAAI;AACF,QAAA,cAAA,CAAe,WAAW,GAAG,CAAA;AAAA,MAC/B,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,IACzB,CAAA;AAAA,IACA,SAAS,MAAA,EAAQ;AACf,MAAA,IAAI,CAAC,SAAA,EAAW,OAAO,OAAA,CAAQ,OAAA,CAAQ,EAAE,CAAA;AACzC,MAAA,MAAM,MAAgB,EAAC;AACvB,MAAA,IAAI;AACF,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,cAAA,CAAe,QAAQ,CAAA,EAAA,EAAK;AAC9C,UAAA,MAAM,CAAA,GAAI,cAAA,CAAe,GAAA,CAAI,CAAC,CAAA;AAC9B,UAAA,IAAI,CAAA,KAAM,QAAQ,CAAA,CAAE,UAAA,CAAW,MAAM,CAAA,KAAM,IAAA,EAAM,GAAA,CAAI,IAAA,CAAK,CAAC,CAAA;AAAA,QAC7D;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,OAAO,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,IAC5B;AAAA,GACF;AACF;;;;"}
|