UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

139 lines (138 loc) • 4.5 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var opfs_exports = {}; __export(opfs_exports, { directories: () => directories, entry: () => entry, folders: () => folders, info: () => info, parent: () => parent, parts: () => parts, root: () => root, serial: () => serial, transfer: () => transfer, write: () => write }); module.exports = __toCommonJS(opfs_exports); const folders = [ "documents", "cache", "applicationSupport", "temporary" ]; const directories = Object.fromEntries(folders.map((name) => [name, `opfs://one/${name}/`])); function parts(uri) { const url = new URL(uri); if (url.protocol !== "opfs:" || url.host !== "one" || url.search || url.hash) { throw new Error("FileSystem: expected an opfs://one/ URI"); } const names = url.pathname.split("/").filter(Boolean).map(decodeURIComponent); if (!folders.includes(names[0]) || names.some((name) => name === "." || name === ".." || /[/\\\0]/.test(name))) { throw new Error("FileSystem: invalid path"); } return names; } async function root() { if (!navigator.storage?.getDirectory) throw new Error("FileSystem: Origin Private File System is unavailable"); const handle = await navigator.storage.getDirectory(); for (const name of folders) await handle.getDirectoryHandle(name, { create: true }); return handle; } async function parent(names, create = false) { let handle = await root(); for (const name of names.slice(0, -1)) handle = await handle.getDirectoryHandle(name, { create }); return handle; } async function entry(names) { const handle = await parent(names); const name = names.at(-1); try { return await handle.getFileHandle(name); } catch (error) { if (error.name !== "TypeMismatchError") throw error; return handle.getDirectoryHandle(name); } } async function info(uri) { const names = parts(uri); try { const handle = await entry(names); if (handle.kind === "directory") return { uri, exists: true, isDirectory: true }; const file = await handle.getFile(); return { uri, exists: true, isDirectory: false, size: file.size, modifiedAt: file.lastModified }; } catch (error) { if (error.name !== "NotFoundError") throw error; return { uri, exists: false, isDirectory: false }; } } async function write(handle, data) { const writable = await handle.createWritable(); try { await writable.write(data); await writable.close(); } catch (error) { await writable.abort().catch(() => {}); throw error; } } async function copyEntry(source, target, name) { if (source.kind === "file") { await write(await target.getFileHandle(name, { create: true }), await source.getFile()); } else { const directory = await target.getDirectoryHandle(name, { create: true }); for await (const [childName, child] of source.entries()) await copyEntry(child, directory, childName); } } async function transfer(fromUri, toUri, move) { const from = parts(fromUri), to = parts(toUri); if (move && from.length === 1) throw new Error("FileSystem: app root directories are protected"); if (to.length <= from.length && to.every((name, i) => name === from[i]) || from.every((name, i) => name === to[i])) throw new Error("FileSystem: overlapping paths"); const source = await entry(from); if ((await info(toUri)).exists) throw new Error("FileSystem: destination already exists"); const destination = await parent(to); try { await copyEntry(source, destination, to.at(-1)); } catch (error) { await destination.removeEntry(to.at(-1), { recursive: true }).catch(() => {}); throw error; } if (move) await (await parent(from)).removeEntry(from.at(-1), { recursive: true }); } let tail = Promise.resolve(); function serial(work) { const next = tail.then(work); tail = next.catch(() => {}); return next; }