one
Version:
One is a React framework for web, iOS, and Android apps.
139 lines (138 loc) • 4.5 kB
JavaScript
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;
}