@xnetjs/sqlite 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adapter-I7yAV6iu.d.ts → adapter-t2aqQ__n.d.ts} +27 -1
- package/dist/adapters/electron.d.ts +7 -3
- package/dist/adapters/electron.js +50 -6
- package/dist/adapters/expo.d.ts +2 -2
- package/dist/adapters/expo.js +27 -6
- package/dist/adapters/memory.d.ts +2 -2
- package/dist/adapters/memory.js +1 -1
- package/dist/adapters/web-proxy.d.ts +19 -3
- package/dist/adapters/web-proxy.js +118 -6
- package/dist/adapters/web-worker.d.ts +12 -1
- package/dist/adapters/web-worker.js +27 -3
- package/dist/adapters/web.d.ts +11 -3
- package/dist/adapters/web.js +7 -4
- package/dist/browser-support.d.ts +56 -1
- package/dist/browser-support.js +11 -3
- package/dist/{chunk-ZRR5D2OD.js → chunk-2OK46ZBU.js} +118 -0
- package/dist/chunk-CBU263LI.js +30 -0
- package/dist/chunk-DCY4LAUD.js +494 -0
- package/dist/chunk-NVD7G7DZ.js +406 -0
- package/dist/index.d.ts +26 -7
- package/dist/index.js +188 -128
- package/dist/schema-BEgIA-rZ.d.ts +35 -0
- package/dist/types-DMrj3K4o.d.ts +132 -0
- package/package.json +1 -1
- package/dist/chunk-BXYZU3OL.js +0 -245
- package/dist/chunk-HIREU5S5.js +0 -193
- package/dist/schema-CjkXTqxn.d.ts +0 -35
- package/dist/types-C_aHfRDF.d.ts +0 -42
|
@@ -16,6 +16,30 @@ interface BrowserSupport {
|
|
|
16
16
|
/** Warning message for soft failures (app can still work with fallback) */
|
|
17
17
|
warning?: string;
|
|
18
18
|
}
|
|
19
|
+
interface PersistentStorageStatus {
|
|
20
|
+
/** Browser exposes persistence APIs. */
|
|
21
|
+
supported: boolean;
|
|
22
|
+
/** Whether the site is currently persisted. */
|
|
23
|
+
persisted: boolean | null;
|
|
24
|
+
/** Whether the explicit persistence request was granted. */
|
|
25
|
+
granted: boolean | null;
|
|
26
|
+
/** Whether this status was produced by an explicit persistence request. */
|
|
27
|
+
requested: boolean;
|
|
28
|
+
/** Whether the app can present a user action to request persistence. */
|
|
29
|
+
requestable: boolean;
|
|
30
|
+
/** Durable-storage state for UI and diagnostics. */
|
|
31
|
+
state: 'granted' | 'not-granted' | 'unsupported' | 'error';
|
|
32
|
+
/** User-facing explanation of the result. */
|
|
33
|
+
message: string;
|
|
34
|
+
/** Optional usage estimate in bytes. */
|
|
35
|
+
usageBytes?: number;
|
|
36
|
+
/** Optional quota estimate in bytes. */
|
|
37
|
+
quotaBytes?: number;
|
|
38
|
+
}
|
|
39
|
+
interface PersistentStorageRequestOptions {
|
|
40
|
+
/** Request persistent mode instead of only checking current state. */
|
|
41
|
+
request?: boolean;
|
|
42
|
+
}
|
|
19
43
|
/**
|
|
20
44
|
* Check if the current browser supports SQLite-WASM with OPFS.
|
|
21
45
|
*
|
|
@@ -46,6 +70,37 @@ interface BrowserSupport {
|
|
|
46
70
|
* ```
|
|
47
71
|
*/
|
|
48
72
|
declare function checkBrowserSupport(): Promise<BrowserSupport>;
|
|
73
|
+
/**
|
|
74
|
+
* Check whether persistent storage is already enabled without prompting or
|
|
75
|
+
* spending a browser heuristic-based permission request during startup.
|
|
76
|
+
*/
|
|
77
|
+
declare function checkPersistentStorage(): Promise<PersistentStorageStatus>;
|
|
78
|
+
/**
|
|
79
|
+
* Whether `navigator.storage.persist()` can be called without showing the
|
|
80
|
+
* user a permission prompt.
|
|
81
|
+
*
|
|
82
|
+
* Chromium and WebKit decide the request silently from heuristics (install,
|
|
83
|
+
* notification permission, engagement) and re-evaluate it fresh on every
|
|
84
|
+
* call, so requesting at startup is free. Gecko (desktop Firefox) shows a
|
|
85
|
+
* modal doorhanger, so requests there must stay behind a user gesture.
|
|
86
|
+
* Firefox on iOS (FxiOS) runs WebKit, but we treat anything Firefox-branded
|
|
87
|
+
* as prompt-capable — the worst case is skipping a free request.
|
|
88
|
+
*/
|
|
89
|
+
declare function isSilentPersistRequestSafe(): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Watch the `persistent-storage` permission for changes (e.g. a grant that
|
|
92
|
+
* lands mid-session after the user enables notifications or installs the
|
|
93
|
+
* app). Querying is free — it never spends or triggers a request.
|
|
94
|
+
*
|
|
95
|
+
* Calls `onChange` with the new state whenever the browser reports a
|
|
96
|
+
* change. No-op on browsers without the Permissions API or the
|
|
97
|
+
* `persistent-storage` permission name. Returns an unsubscribe function.
|
|
98
|
+
*/
|
|
99
|
+
declare function watchPersistentStoragePermission(onChange: (state: PermissionState) => void): () => void;
|
|
100
|
+
/**
|
|
101
|
+
* Request persistent storage where supported and summarize the result.
|
|
102
|
+
*/
|
|
103
|
+
declare function requestPersistentStorage(options?: PersistentStorageRequestOptions): Promise<PersistentStorageStatus>;
|
|
49
104
|
/**
|
|
50
105
|
* Show an unsupported browser message to the user.
|
|
51
106
|
*
|
|
@@ -64,4 +119,4 @@ declare function checkBrowserSupport(): Promise<BrowserSupport>;
|
|
|
64
119
|
*/
|
|
65
120
|
declare function showUnsupportedBrowserMessage(reason: string): void;
|
|
66
121
|
|
|
67
|
-
export { type BrowserSupport, checkBrowserSupport, showUnsupportedBrowserMessage };
|
|
122
|
+
export { type BrowserSupport, type PersistentStorageRequestOptions, type PersistentStorageStatus, checkBrowserSupport, checkPersistentStorage, isSilentPersistRequestSafe, requestPersistentStorage, showUnsupportedBrowserMessage, watchPersistentStoragePermission };
|
package/dist/browser-support.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
checkBrowserSupport,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
checkPersistentStorage,
|
|
4
|
+
isSilentPersistRequestSafe,
|
|
5
|
+
requestPersistentStorage,
|
|
6
|
+
showUnsupportedBrowserMessage,
|
|
7
|
+
watchPersistentStoragePermission
|
|
8
|
+
} from "./chunk-2OK46ZBU.js";
|
|
5
9
|
export {
|
|
6
10
|
checkBrowserSupport,
|
|
7
|
-
|
|
11
|
+
checkPersistentStorage,
|
|
12
|
+
isSilentPersistRequestSafe,
|
|
13
|
+
requestPersistentStorage,
|
|
14
|
+
showUnsupportedBrowserMessage,
|
|
15
|
+
watchPersistentStoragePermission
|
|
8
16
|
};
|
|
@@ -55,6 +55,120 @@ async function checkBrowserSupport() {
|
|
|
55
55
|
}
|
|
56
56
|
return result;
|
|
57
57
|
}
|
|
58
|
+
async function readStorageEstimate() {
|
|
59
|
+
const estimate = await navigator.storage.estimate?.().catch(() => void 0);
|
|
60
|
+
return {
|
|
61
|
+
usageBytes: estimate?.usage,
|
|
62
|
+
quotaBytes: estimate?.quota
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function getPersistenceMessage(input) {
|
|
66
|
+
const { persisted, requested, granted } = input;
|
|
67
|
+
if (persisted) {
|
|
68
|
+
return "Durable local storage is enabled. This browser agreed to keep your xNet workspace unless you explicitly clear site data.";
|
|
69
|
+
}
|
|
70
|
+
if (!requested) {
|
|
71
|
+
return "Durable storage is not enabled yet. xNet can request stronger local-storage protection when you choose to enable it.";
|
|
72
|
+
}
|
|
73
|
+
if (granted === false) {
|
|
74
|
+
return "This browser declined durable storage for now. xNet keeps working, and browsers re-evaluate the request as install, notification, and usage signals change.";
|
|
75
|
+
}
|
|
76
|
+
return "This browser did not confirm durable storage. xNet will keep working, but local data may be evicted under storage pressure or aggressive cleanup.";
|
|
77
|
+
}
|
|
78
|
+
async function checkPersistentStorage() {
|
|
79
|
+
return requestPersistentStorage({ request: false });
|
|
80
|
+
}
|
|
81
|
+
function isSilentPersistRequestSafe() {
|
|
82
|
+
if (typeof navigator === "undefined") return false;
|
|
83
|
+
return !/Firefox|FxiOS/i.test(navigator.userAgent);
|
|
84
|
+
}
|
|
85
|
+
function watchPersistentStoragePermission(onChange) {
|
|
86
|
+
let active = true;
|
|
87
|
+
let detach = null;
|
|
88
|
+
void (async () => {
|
|
89
|
+
try {
|
|
90
|
+
const status = await navigator.permissions.query({
|
|
91
|
+
name: "persistent-storage"
|
|
92
|
+
});
|
|
93
|
+
if (!active) return;
|
|
94
|
+
const listener = () => onChange(status.state);
|
|
95
|
+
status.addEventListener("change", listener);
|
|
96
|
+
detach = () => status.removeEventListener("change", listener);
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
|
99
|
+
})();
|
|
100
|
+
return () => {
|
|
101
|
+
active = false;
|
|
102
|
+
detach?.();
|
|
103
|
+
detach = null;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async function requestPersistentStorage(options = { request: true }) {
|
|
107
|
+
const requested = options.request ?? true;
|
|
108
|
+
if (typeof navigator === "undefined" || !navigator.storage) {
|
|
109
|
+
return {
|
|
110
|
+
supported: false,
|
|
111
|
+
persisted: null,
|
|
112
|
+
granted: null,
|
|
113
|
+
requested,
|
|
114
|
+
requestable: false,
|
|
115
|
+
state: "unsupported",
|
|
116
|
+
message: "This browser does not expose storage persistence APIs. Local data can still work, but the browser may evict it under storage pressure."
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const estimate = await readStorageEstimate();
|
|
120
|
+
if (!navigator.storage.persist || !navigator.storage.persisted) {
|
|
121
|
+
return {
|
|
122
|
+
supported: false,
|
|
123
|
+
persisted: null,
|
|
124
|
+
granted: null,
|
|
125
|
+
requested,
|
|
126
|
+
requestable: false,
|
|
127
|
+
state: "unsupported",
|
|
128
|
+
message: "This browser cannot explicitly request durable storage. Local data can still work, but the browser may evict it under storage pressure.",
|
|
129
|
+
...estimate
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const alreadyPersisted = await navigator.storage.persisted();
|
|
134
|
+
const granted = alreadyPersisted ? true : requested ? await navigator.storage.persist() : null;
|
|
135
|
+
const persisted = granted ? true : await navigator.storage.persisted();
|
|
136
|
+
if (persisted) {
|
|
137
|
+
return {
|
|
138
|
+
supported: true,
|
|
139
|
+
persisted,
|
|
140
|
+
granted,
|
|
141
|
+
requested,
|
|
142
|
+
requestable: false,
|
|
143
|
+
state: "granted",
|
|
144
|
+
message: getPersistenceMessage({ persisted, requested, granted }),
|
|
145
|
+
...estimate
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
supported: true,
|
|
150
|
+
persisted,
|
|
151
|
+
granted,
|
|
152
|
+
requested,
|
|
153
|
+
requestable: true,
|
|
154
|
+
state: "not-granted",
|
|
155
|
+
message: getPersistenceMessage({ persisted, requested, granted }),
|
|
156
|
+
...estimate
|
|
157
|
+
};
|
|
158
|
+
} catch (err) {
|
|
159
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
160
|
+
return {
|
|
161
|
+
supported: true,
|
|
162
|
+
persisted: null,
|
|
163
|
+
granted: null,
|
|
164
|
+
requested,
|
|
165
|
+
requestable: true,
|
|
166
|
+
state: "error",
|
|
167
|
+
message: `xNet could not confirm durable storage (${reason}). Local data may still work, but persistence guarantees are unclear.`,
|
|
168
|
+
...estimate
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
58
172
|
function showUnsupportedBrowserMessage(reason) {
|
|
59
173
|
const container = document.getElementById("app") ?? document.body;
|
|
60
174
|
container.innerHTML = `
|
|
@@ -136,5 +250,9 @@ function escapeHtml(text) {
|
|
|
136
250
|
|
|
137
251
|
export {
|
|
138
252
|
checkBrowserSupport,
|
|
253
|
+
checkPersistentStorage,
|
|
254
|
+
isSilentPersistRequestSafe,
|
|
255
|
+
watchPersistentStoragePermission,
|
|
256
|
+
requestPersistentStorage,
|
|
139
257
|
showUnsupportedBrowserMessage
|
|
140
258
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var SQLITE_CORRUPT_RESULT_CODE = 11;
|
|
3
|
+
var SQLITE_NOTADB_RESULT_CODE = 26;
|
|
4
|
+
function toErrorLike(error) {
|
|
5
|
+
if (!error || typeof error !== "object") {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
return error;
|
|
9
|
+
}
|
|
10
|
+
function isSQLiteCorruptionError(error) {
|
|
11
|
+
return isSQLiteCorruptionErrorInternal(error, /* @__PURE__ */ new Set());
|
|
12
|
+
}
|
|
13
|
+
function isSQLiteCorruptionErrorInternal(error, seen) {
|
|
14
|
+
const current = toErrorLike(error);
|
|
15
|
+
if (!current) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
if (seen.has(error)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
seen.add(error);
|
|
22
|
+
const message = typeof current.message === "string" ? current.message.toLowerCase() : String(current.message);
|
|
23
|
+
const code = typeof current.code === "string" ? current.code.toUpperCase() : "";
|
|
24
|
+
const resultCode = typeof current.resultCode === "number" ? current.resultCode : null;
|
|
25
|
+
return resultCode === SQLITE_CORRUPT_RESULT_CODE || resultCode === SQLITE_NOTADB_RESULT_CODE || code === "SQLITE_CORRUPT" || code === "SQLITE_NOTADB" || message.includes("sqlite_corrupt") || message.includes("sqlite_notadb") || message.includes("database disk image is malformed") || message.includes("file is not a database") || isSQLiteCorruptionErrorInternal(current.cause, seen);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
isSQLiteCorruptionError
|
|
30
|
+
};
|