sliftutils 1.7.6 → 1.7.7
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/index.d.ts
CHANGED
|
@@ -2423,6 +2423,7 @@ declare module "sliftutils/storage/fileSystemPointer" {
|
|
|
2423
2423
|
handle: FileSystemFileHandle | FileSystemDirectoryHandle;
|
|
2424
2424
|
}): Promise<FileSystemPointer>;
|
|
2425
2425
|
export declare function deleteFileSystemPointer(pointer: FileSystemPointer): Promise<void>;
|
|
2426
|
+
export declare function findGrantedPointerHandle(mode: "read" | "readwrite"): Promise<FileSystemDirectoryHandle | undefined>;
|
|
2426
2427
|
export declare function getFileSystemPointer(config: {
|
|
2427
2428
|
pointer: FileSystemPointer;
|
|
2428
2429
|
}): Promise<{
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import preact from "preact";
|
|
2
|
-
import { getFileSystemPointer, storeFileSystemPointer } from "./fileSystemPointer";
|
|
2
|
+
import { findGrantedPointerHandle, getFileSystemPointer, storeFileSystemPointer } from "./fileSystemPointer";
|
|
3
3
|
import { observable } from "mobx";
|
|
4
4
|
import { observer } from "../render-utils/observer";
|
|
5
5
|
import { cache, lazy } from "socket-function/src/caching";
|
|
@@ -36,6 +36,9 @@ declare global {
|
|
|
36
36
|
// DO NOT enable this is isNode
|
|
37
37
|
const USE_INDEXED_DB = false;
|
|
38
38
|
|
|
39
|
+
// How often a worker rechecks the pointer IndexedDB for a granted handle when none is available yet.
|
|
40
|
+
const WORKER_POLL_INTERVAL_MS = 60 * 1000;
|
|
41
|
+
|
|
39
42
|
// These mirror the subset of the native FileSystemFileHandle / FileSystemDirectoryHandle API we use, so
|
|
40
43
|
// the native browser handles, the Node handles, and the remote handles are all interchangeable — and
|
|
41
44
|
// code written against the native handle (e.g. a recursive walk over `handle.entries()`) works on any of
|
|
@@ -460,6 +463,20 @@ export const getDirectoryHandle = lazy(async function getDirectoryHandle(): Prom
|
|
|
460
463
|
if (storageRootOverride) {
|
|
461
464
|
return storageRootOverride as unknown as DirectoryWrapper;
|
|
462
465
|
}
|
|
466
|
+
// A worker can't show the picker (no DOM / no user activation) and can't read localStorage, but
|
|
467
|
+
// it CAN open the pointer IndexedDB the main-thread picker persists to. Poll it for a handle
|
|
468
|
+
// whose permission is already granted; the owning window may also postMessage a handle in
|
|
469
|
+
// mid-poll (checked each iteration). This has to come before the isNode branch: typesafecss's
|
|
470
|
+
// isNode() returns true in workers (window is undefined), so a worker would otherwise fall into
|
|
471
|
+
// the Node branch and try to use fs/path.
|
|
472
|
+
if ("WorkerGlobalScope" in globalThis) {
|
|
473
|
+
while (true) {
|
|
474
|
+
if (storageRootOverride) return storageRootOverride as unknown as DirectoryWrapper;
|
|
475
|
+
let handle = await findGrantedPointerHandle("readwrite");
|
|
476
|
+
if (handle) return handle as unknown as DirectoryWrapper;
|
|
477
|
+
await new Promise(resolve => setTimeout(resolve, WORKER_POLL_INTERVAL_MS));
|
|
478
|
+
}
|
|
479
|
+
}
|
|
463
480
|
if (isNode()) {
|
|
464
481
|
return new NodeJSDirectoryHandleWrapper(path.resolve("./data/"));
|
|
465
482
|
}
|
|
@@ -4,6 +4,7 @@ export declare function storeFileSystemPointer(config: {
|
|
|
4
4
|
handle: FileSystemFileHandle | FileSystemDirectoryHandle;
|
|
5
5
|
}): Promise<FileSystemPointer>;
|
|
6
6
|
export declare function deleteFileSystemPointer(pointer: FileSystemPointer): Promise<void>;
|
|
7
|
+
export declare function findGrantedPointerHandle(mode: "read" | "readwrite"): Promise<FileSystemDirectoryHandle | undefined>;
|
|
7
8
|
export declare function getFileSystemPointer(config: {
|
|
8
9
|
pointer: FileSystemPointer;
|
|
9
10
|
}): Promise<{
|
|
@@ -55,6 +55,36 @@ export async function deleteFileSystemPointer(pointer: FileSystemPointer) {
|
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// Enumerates every stored pointer handle whose permission is already granted for `mode`, newest first
|
|
59
|
+
// (pointer keys start with Date.now(), which sorts lexicographically). Callable from a Web Worker —
|
|
60
|
+
// unlike getFileSystemPointer's onUserActivation flow, this only uses queryPermission, which does
|
|
61
|
+
// NOT require user activation.
|
|
62
|
+
export async function findGrantedPointerHandle(mode: "read" | "readwrite"): Promise<FileSystemDirectoryHandle | undefined> {
|
|
63
|
+
let database = await db();
|
|
64
|
+
if (!database) return undefined;
|
|
65
|
+
let store = database.transaction(objectStoreName, "readonly").objectStore(objectStoreName);
|
|
66
|
+
let keysReq = store.getAllKeys();
|
|
67
|
+
let valuesReq = store.getAll();
|
|
68
|
+
await new Promise((resolve, reject) => {
|
|
69
|
+
keysReq.addEventListener("success", resolve);
|
|
70
|
+
keysReq.addEventListener("error", reject);
|
|
71
|
+
});
|
|
72
|
+
await new Promise((resolve, reject) => {
|
|
73
|
+
valuesReq.addEventListener("success", resolve);
|
|
74
|
+
valuesReq.addEventListener("error", reject);
|
|
75
|
+
});
|
|
76
|
+
let keys = keysReq.result as string[];
|
|
77
|
+
let values = valuesReq.result as (FileSystemFileHandle | FileSystemDirectoryHandle)[];
|
|
78
|
+
let entries = keys.map((key, i) => ({ key, value: values[i], time: +key.split("_")[0] || 0 }))
|
|
79
|
+
.sort((a, b) => b.time - a.time);
|
|
80
|
+
for (let entry of entries) {
|
|
81
|
+
if (entry.value.kind !== "directory") continue;
|
|
82
|
+
let state = await (entry.value as any).queryPermission({ mode });
|
|
83
|
+
if (state === "granted") return entry.value;
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
58
88
|
export async function getFileSystemPointer(config: {
|
|
59
89
|
pointer: FileSystemPointer;
|
|
60
90
|
}): Promise<{
|