UNPKG

opencoder

Version:
551 lines (544 loc) 18.7 kB
import { existsSync, promises } from "node:fs"; import { dirname, join, resolve } from "node:path"; //#region node_modules/destr/dist/index.mjs const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/; const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/; const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/; function jsonParseTransform(key, value) { if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) { warnKeyDropped(key); return; } return value; } function warnKeyDropped(key) { console.warn(`[destr] Dropping "${key}" key to prevent prototype pollution.`); } function destr(value, options = {}) { if (typeof value !== "string") return value; const _value = value.trim(); if (value[0] === "\"" && value.endsWith("\"") && !value.includes("\\")) return _value.slice(1, -1); if (_value.length <= 9) { const _lval = _value.toLowerCase(); if (_lval === "true") return true; if (_lval === "false") return false; if (_lval === "undefined") return void 0; if (_lval === "null") return null; if (_lval === "nan") return Number.NaN; if (_lval === "infinity") return Number.POSITIVE_INFINITY; if (_lval === "-infinity") return Number.NEGATIVE_INFINITY; } if (!JsonSigRx.test(value)) { if (options.strict) throw new SyntaxError("[destr] Invalid JSON"); return value; } try { if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) { if (options.strict) throw new Error("[destr] Possible prototype pollution"); return JSON.parse(value, jsonParseTransform); } return JSON.parse(value); } catch (error) { if (options.strict) throw error; return value; } } //#endregion //#region node_modules/unstorage/dist/shared/unstorage.mNKHTF5Y.mjs function wrapToPromise(value) { if (!value || typeof value.then !== "function") return Promise.resolve(value); return value; } function asyncCall(function_, ...arguments_) { try { return wrapToPromise(function_(...arguments_)); } catch (error) { return Promise.reject(error); } } function isPrimitive(value) { const type = typeof value; return value === null || type !== "object" && type !== "function"; } function isPureObject(value) { const proto = Object.getPrototypeOf(value); return !proto || proto.isPrototypeOf(Object); } function stringify(value) { if (isPrimitive(value)) return String(value); if (isPureObject(value) || Array.isArray(value)) return JSON.stringify(value); if (typeof value.toJSON === "function") return stringify(value.toJSON()); throw new Error("[unstorage] Cannot stringify value!"); } const BASE64_PREFIX = "base64:"; function serializeRaw(value) { if (typeof value === "string") return value; return BASE64_PREFIX + base64Encode(value); } function deserializeRaw(value) { if (typeof value !== "string") return value; if (!value.startsWith(BASE64_PREFIX)) return value; return base64Decode(value.slice(BASE64_PREFIX.length)); } function base64Decode(input) { if (globalThis.Buffer) return Buffer.from(input, "base64"); return Uint8Array.from(globalThis.atob(input), (c) => c.codePointAt(0)); } function base64Encode(input) { if (globalThis.Buffer) return Buffer.from(input).toString("base64"); return globalThis.btoa(String.fromCodePoint(...input)); } function normalizeKey(key) { if (!key) return ""; return key.split("?")[0]?.replace(/[/\\]/g, ":").replace(/:+/g, ":").replace(/^:|:$/g, "") || ""; } function joinKeys(...keys) { return normalizeKey(keys.join(":")); } function normalizeBaseKey(base) { base = normalizeKey(base); return base ? base + ":" : ""; } function filterKeyByDepth(key, depth) { if (depth === void 0) return true; let substrCount = 0; let index = key.indexOf(":"); while (index > -1) { substrCount++; index = key.indexOf(":", index + 1); } return substrCount <= depth; } function filterKeyByBase(key, base) { if (base) return key.startsWith(base) && key[key.length - 1] !== "$"; return key[key.length - 1] !== "$"; } //#endregion //#region node_modules/unstorage/dist/index.mjs function defineDriver$1(factory) { return factory; } const DRIVER_NAME$1 = "memory"; const memory = defineDriver$1(() => { const data = /* @__PURE__ */ new Map(); return { name: DRIVER_NAME$1, getInstance: () => data, hasItem(key) { return data.has(key); }, getItem(key) { return data.get(key) ?? null; }, getItemRaw(key) { return data.get(key) ?? null; }, setItem(key, value) { data.set(key, value); }, setItemRaw(key, value) { data.set(key, value); }, removeItem(key) { data.delete(key); }, getKeys() { return [...data.keys()]; }, clear() { data.clear(); }, dispose() { data.clear(); } }; }); function createStorage(options = {}) { const context = { mounts: { "": options.driver || memory() }, mountpoints: [""], watching: false, watchListeners: [], unwatch: {} }; const getMount = (key) => { for (const base of context.mountpoints) if (key.startsWith(base)) return { base, relativeKey: key.slice(base.length), driver: context.mounts[base] }; return { base: "", relativeKey: key, driver: context.mounts[""] }; }; const getMounts = (base, includeParent) => { return context.mountpoints.filter((mountpoint) => mountpoint.startsWith(base) || includeParent && base.startsWith(mountpoint)).map((mountpoint) => ({ relativeBase: base.length > mountpoint.length ? base.slice(mountpoint.length) : void 0, mountpoint, driver: context.mounts[mountpoint] })); }; const onChange = (event, key) => { if (!context.watching) return; key = normalizeKey(key); for (const listener of context.watchListeners) listener(event, key); }; const startWatch = async () => { if (context.watching) return; context.watching = true; for (const mountpoint in context.mounts) context.unwatch[mountpoint] = await watch(context.mounts[mountpoint], onChange, mountpoint); }; const stopWatch = async () => { if (!context.watching) return; for (const mountpoint in context.unwatch) await context.unwatch[mountpoint](); context.unwatch = {}; context.watching = false; }; const runBatch = (items, commonOptions, cb) => { const batches = /* @__PURE__ */ new Map(); const getBatch = (mount) => { let batch = batches.get(mount.base); if (!batch) { batch = { driver: mount.driver, base: mount.base, items: [] }; batches.set(mount.base, batch); } return batch; }; for (const item of items) { const isStringItem = typeof item === "string"; const key = normalizeKey(isStringItem ? item : item.key); const value = isStringItem ? void 0 : item.value; const options2 = isStringItem || !item.options ? commonOptions : { ...commonOptions, ...item.options }; const mount = getMount(key); getBatch(mount).items.push({ key, value, relativeKey: mount.relativeKey, options: options2 }); } return Promise.all([...batches.values()].map((batch) => cb(batch))).then((r) => r.flat()); }; const storage = { hasItem(key, opts = {}) { key = normalizeKey(key); const { relativeKey, driver } = getMount(key); return asyncCall(driver.hasItem, relativeKey, opts); }, getItem(key, opts = {}) { key = normalizeKey(key); const { relativeKey, driver } = getMount(key); return asyncCall(driver.getItem, relativeKey, opts).then((value) => destr(value)); }, getItems(items, commonOptions = {}) { return runBatch(items, commonOptions, (batch) => { if (batch.driver.getItems) return asyncCall(batch.driver.getItems, batch.items.map((item) => ({ key: item.relativeKey, options: item.options })), commonOptions).then((r) => r.map((item) => ({ key: joinKeys(batch.base, item.key), value: destr(item.value) }))); return Promise.all(batch.items.map((item) => { return asyncCall(batch.driver.getItem, item.relativeKey, item.options).then((value) => ({ key: item.key, value: destr(value) })); })); }); }, getItemRaw(key, opts = {}) { key = normalizeKey(key); const { relativeKey, driver } = getMount(key); if (driver.getItemRaw) return asyncCall(driver.getItemRaw, relativeKey, opts); return asyncCall(driver.getItem, relativeKey, opts).then((value) => deserializeRaw(value)); }, async setItem(key, value, opts = {}) { if (value === void 0) return storage.removeItem(key); key = normalizeKey(key); const { relativeKey, driver } = getMount(key); if (!driver.setItem) return; await asyncCall(driver.setItem, relativeKey, stringify(value), opts); if (!driver.watch) onChange("update", key); }, async setItems(items, commonOptions) { await runBatch(items, commonOptions, async (batch) => { if (batch.driver.setItems) return asyncCall(batch.driver.setItems, batch.items.map((item) => ({ key: item.relativeKey, value: stringify(item.value), options: item.options })), commonOptions); if (!batch.driver.setItem) return; await Promise.all(batch.items.map((item) => { return asyncCall(batch.driver.setItem, item.relativeKey, stringify(item.value), item.options); })); }); }, async setItemRaw(key, value, opts = {}) { if (value === void 0) return storage.removeItem(key, opts); key = normalizeKey(key); const { relativeKey, driver } = getMount(key); if (driver.setItemRaw) await asyncCall(driver.setItemRaw, relativeKey, value, opts); else if (driver.setItem) await asyncCall(driver.setItem, relativeKey, serializeRaw(value), opts); else return; if (!driver.watch) onChange("update", key); }, async removeItem(key, opts = {}) { if (typeof opts === "boolean") opts = { removeMeta: opts }; key = normalizeKey(key); const { relativeKey, driver } = getMount(key); if (!driver.removeItem) return; await asyncCall(driver.removeItem, relativeKey, opts); if (opts.removeMeta || opts.removeMata) await asyncCall(driver.removeItem, relativeKey + "$", opts); if (!driver.watch) onChange("remove", key); }, async getMeta(key, opts = {}) { if (typeof opts === "boolean") opts = { nativeOnly: opts }; key = normalizeKey(key); const { relativeKey, driver } = getMount(key); const meta = /* @__PURE__ */ Object.create(null); if (driver.getMeta) Object.assign(meta, await asyncCall(driver.getMeta, relativeKey, opts)); if (!opts.nativeOnly) { const value = await asyncCall(driver.getItem, relativeKey + "$", opts).then((value_) => destr(value_)); if (value && typeof value === "object") { if (typeof value.atime === "string") value.atime = new Date(value.atime); if (typeof value.mtime === "string") value.mtime = new Date(value.mtime); Object.assign(meta, value); } } return meta; }, setMeta(key, value, opts = {}) { return this.setItem(key + "$", value, opts); }, removeMeta(key, opts = {}) { return this.removeItem(key + "$", opts); }, async getKeys(base, opts = {}) { base = normalizeBaseKey(base); const mounts = getMounts(base, true); let maskedMounts = []; const allKeys = []; let allMountsSupportMaxDepth = true; for (const mount of mounts) { if (!mount.driver.flags?.maxDepth) allMountsSupportMaxDepth = false; const rawKeys = await asyncCall(mount.driver.getKeys, mount.relativeBase, opts); for (const key of rawKeys) { const fullKey = mount.mountpoint + normalizeKey(key); if (!maskedMounts.some((p) => fullKey.startsWith(p))) allKeys.push(fullKey); } maskedMounts = [mount.mountpoint, ...maskedMounts.filter((p) => !p.startsWith(mount.mountpoint))]; } const shouldFilterByDepth = opts.maxDepth !== void 0 && !allMountsSupportMaxDepth; return allKeys.filter((key) => (!shouldFilterByDepth || filterKeyByDepth(key, opts.maxDepth)) && filterKeyByBase(key, base)); }, async clear(base, opts = {}) { base = normalizeBaseKey(base); await Promise.all(getMounts(base, false).map(async (m) => { if (m.driver.clear) return asyncCall(m.driver.clear, m.relativeBase, opts); if (m.driver.removeItem) { const keys = await m.driver.getKeys(m.relativeBase || "", opts); return Promise.all(keys.map((key) => m.driver.removeItem(key, opts))); } })); }, async dispose() { await Promise.all(Object.values(context.mounts).map((driver) => dispose(driver))); }, async watch(callback) { await startWatch(); context.watchListeners.push(callback); return async () => { context.watchListeners = context.watchListeners.filter((listener) => listener !== callback); if (context.watchListeners.length === 0) await stopWatch(); }; }, async unwatch() { context.watchListeners = []; await stopWatch(); }, mount(base, driver) { base = normalizeBaseKey(base); if (base && context.mounts[base]) throw new Error(`already mounted at ${base}`); if (base) { context.mountpoints.push(base); context.mountpoints.sort((a, b) => b.length - a.length); } context.mounts[base] = driver; if (context.watching) Promise.resolve(watch(driver, onChange, base)).then((unwatcher) => { context.unwatch[base] = unwatcher; }).catch(console.error); return storage; }, async unmount(base, _dispose = true) { base = normalizeBaseKey(base); if (!base || !context.mounts[base]) return; if (context.watching && base in context.unwatch) { context.unwatch[base]?.(); delete context.unwatch[base]; } if (_dispose) await dispose(context.mounts[base]); context.mountpoints = context.mountpoints.filter((key) => key !== base); delete context.mounts[base]; }, getMount(key = "") { key = normalizeKey(key) + ":"; const m = getMount(key); return { driver: m.driver, base: m.base }; }, getMounts(base = "", opts = {}) { base = normalizeKey(base); const mounts = getMounts(base, opts.parents); return mounts.map((m) => ({ driver: m.driver, base: m.mountpoint })); }, keys: (base, opts = {}) => storage.getKeys(base, opts), get: (key, opts = {}) => storage.getItem(key, opts), set: (key, value, opts = {}) => storage.setItem(key, value, opts), has: (key, opts = {}) => storage.hasItem(key, opts), del: (key, opts = {}) => storage.removeItem(key, opts), remove: (key, opts = {}) => storage.removeItem(key, opts) }; return storage; } function watch(driver, onChange, base) { return driver.watch ? driver.watch((event, key) => onChange(event, base + key)) : () => {}; } async function dispose(driver) { if (typeof driver.dispose === "function") await asyncCall(driver.dispose); } //#endregion //#region node_modules/unstorage/drivers/utils/index.mjs function defineDriver(factory) { return factory; } function createError(driver, message, opts) { const err = new Error(`[unstorage] [${driver}] ${message}`, opts); if (Error.captureStackTrace) Error.captureStackTrace(err, createError); return err; } function createRequiredError(driver, name) { if (Array.isArray(name)) return createError(driver, `Missing some of the required options ${name.map((n) => "`" + n + "`").join(", ")}`); return createError(driver, `Missing required option \`${name}\`.`); } //#endregion //#region node_modules/unstorage/drivers/utils/node-fs.mjs function ignoreNotfound(err) { return err.code === "ENOENT" || err.code === "EISDIR" ? null : err; } function ignoreExists(err) { return err.code === "EEXIST" ? null : err; } async function writeFile(path$1, data, encoding) { await ensuredir(dirname(path$1)); return promises.writeFile(path$1, data, encoding); } function readFile(path$1, encoding) { return promises.readFile(path$1, encoding).catch(ignoreNotfound); } function unlink(path$1) { return promises.unlink(path$1).catch(ignoreNotfound); } function readdir(dir) { return promises.readdir(dir, { withFileTypes: true }).catch(ignoreNotfound).then((r) => r || []); } async function ensuredir(dir) { if (existsSync(dir)) return; await ensuredir(dirname(dir)).catch(ignoreExists); await promises.mkdir(dir).catch(ignoreExists); } async function readdirRecursive(dir, ignore, maxDepth) { if (ignore && ignore(dir)) return []; const entries = await readdir(dir); const files = []; await Promise.all(entries.map(async (entry) => { const entryPath = resolve(dir, entry.name); if (entry.isDirectory()) { if (maxDepth === void 0 || maxDepth > 0) { const dirFiles = await readdirRecursive(entryPath, ignore, maxDepth === void 0 ? void 0 : maxDepth - 1); files.push(...dirFiles.map((f) => entry.name + "/" + f)); } } else if (!(ignore && ignore(entry.name))) files.push(entry.name); })); return files; } async function rmRecursive(dir) { const entries = await readdir(dir); await Promise.all(entries.map((entry) => { const entryPath = resolve(dir, entry.name); if (entry.isDirectory()) return rmRecursive(entryPath).then(() => promises.rmdir(entryPath)); else return promises.unlink(entryPath); })); } //#endregion //#region node_modules/unstorage/drivers/fs-lite.mjs const PATH_TRAVERSE_RE = /\.\.:|\.\.$/; const DRIVER_NAME = "fs-lite"; var fs_lite_default = defineDriver((opts = {}) => { if (!opts.base) throw createRequiredError(DRIVER_NAME, "base"); opts.base = resolve(opts.base); const r = (key) => { if (PATH_TRAVERSE_RE.test(key)) throw createError(DRIVER_NAME, `Invalid key: ${JSON.stringify(key)}. It should not contain .. segments`); const resolved = join(opts.base, key.replace(/:/g, "/")); return resolved; }; return { name: DRIVER_NAME, options: opts, flags: { maxDepth: true }, hasItem(key) { return existsSync(r(key)); }, getItem(key) { return readFile(r(key), "utf8"); }, getItemRaw(key) { return readFile(r(key)); }, async getMeta(key) { const { atime, mtime, size, birthtime, ctime } = await promises.stat(r(key)).catch(() => ({})); return { atime, mtime, size, birthtime, ctime }; }, setItem(key, value) { if (opts.readOnly) return; return writeFile(r(key), value, "utf8"); }, setItemRaw(key, value) { if (opts.readOnly) return; return writeFile(r(key), value); }, removeItem(key) { if (opts.readOnly) return; return unlink(r(key)); }, getKeys(_base, topts) { return readdirRecursive(r("."), opts.ignore, topts?.maxDepth); }, async clear() { if (opts.readOnly || opts.noClear) return; await rmRecursive(r(".")); } }; }); //#endregion export { createStorage, fs_lite_default };