sh, diff/patch, sort, printf, find, test, getfacl/setfacl/xattr), expanded /proc and metrics (process table, syscalls, replication, net, security posture, worker budget, swarm/replication hints), initd DAG supervision metadata and richer restart journal telemetry, synthetic process groups via IPC (assignProcessGroup/signalProcessGroup) mirrored into process_table, optional kernel.ext.d incremental hot reload (BARE_OS_KERNEL_EXT_D_HOT_RELOAD) with reload audit NDJSON, features proc for hyperblobs dedup and systemd subset documentation, vault threat model doc plus posture fields for AEAD, Pear enclave pointer, account rotation continuity, and Ed25519 consistency across boot manifest / extensions / replication. Adds or extends tests and keeps kernel/ and packages/bare-os-seeder/kernel/ in parity; guest init is bundled from kernel/lib/init/init-main.js via bundle-kernel-init.
59345 lines
2.1 MiB
Plaintext
59345 lines
2.1 MiB
Plaintext
var __bare_os_bundle_exports__ = (() => {
|
|
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
}) : x)(function(x) {
|
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
});
|
|
var __esm = (fn, res) => function __init() {
|
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
};
|
|
var __commonJS = (cb, mod) => function __require2() {
|
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
};
|
|
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
// file that has been converted to a CommonJS file using a Babel-
|
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
mod
|
|
));
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// ../../node_modules/which-runtime/index.js
|
|
var require_which_runtime = __commonJS({
|
|
"../../node_modules/which-runtime/index.js"(exports) {
|
|
var { runtime, platform, arch } = typeof Bare !== "undefined" ? { runtime: "bare", platform: global.Bare.platform, arch: global.Bare.arch } : typeof process !== "undefined" ? { runtime: "node", platform: global.process.platform, arch: global.process.arch } : typeof Window !== "undefined" ? { runtime: "browser", platform: "unknown", arch: "unknown" } : { runtime: "unknown", platform: "unknown", arch: "unknown" };
|
|
exports.runtime = runtime;
|
|
exports.platform = platform;
|
|
exports.arch = arch;
|
|
exports.isBare = runtime === "bare";
|
|
exports.isBareKit = exports.isBare && typeof BareKit !== "undefined";
|
|
exports.isPear = typeof Pear !== "undefined";
|
|
exports.isNode = runtime === "node";
|
|
exports.isBrowser = runtime === "browser";
|
|
exports.isWindows = platform === "win32";
|
|
exports.isLinux = platform === "linux";
|
|
exports.isMac = platform === "darwin";
|
|
exports.isIOS = platform === "ios" || platform === "ios-simulator";
|
|
exports.isAndroid = platform === "android";
|
|
exports.isElectron = typeof process !== "undefined" && !!global.process.versions?.electron;
|
|
exports.isElectronRenderer = exports.isElectron && global.process.type === "renderer";
|
|
exports.isElectronWorker = exports.isElectron && global.process.type === "worker";
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-which/lib/executable.js
|
|
var require_executable = __commonJS({
|
|
"../../node_modules/bare-which/lib/executable.js"(exports, module) {
|
|
var fs = __require("fs");
|
|
var process2 = __require("process");
|
|
var { isWindows } = require_which_runtime();
|
|
function isExecutableSync(path, options) {
|
|
try {
|
|
const stat = fs.statSync(path);
|
|
const checker = isWindows ? isWin32Executable : isPosixExecutableSync;
|
|
return stat.isFile() && checker({ path, options });
|
|
} catch (err) {
|
|
if (options.ignoreErrors || ["ENOENT", "EACCES"].includes(err.code)) return false;
|
|
throw err;
|
|
}
|
|
}
|
|
async function isExecutable(path, options) {
|
|
try {
|
|
const stat = await fs.promises.stat(path);
|
|
const checker = isWindows ? isWin32Executable : isPosixExecutable;
|
|
return stat.isFile() && await checker({ path, options });
|
|
} catch (err) {
|
|
if (options.ignoreErrors || ["ENOENT", "EACCES"].includes(err.code)) return false;
|
|
throw err;
|
|
}
|
|
}
|
|
function isWin32Executable({ path, options }) {
|
|
const { pathExt = process2.env.PATHEXT || "" } = options;
|
|
const exts = pathExt.split(";");
|
|
if (exts.includes("")) return true;
|
|
return exts.some((ext) => path.toLowerCase().endsWith(ext.toLowerCase()));
|
|
}
|
|
async function isPosixExecutable({ path }) {
|
|
await fs.promises.access(path, fs.constants.X_OK);
|
|
return true;
|
|
}
|
|
function isPosixExecutableSync({ path }) {
|
|
fs.accessSync(path, fs.constants.X_OK);
|
|
return true;
|
|
}
|
|
isExecutable.sync = isExecutableSync;
|
|
module.exports = isExecutable;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-which/index.js
|
|
var require_bare_which = __commonJS({
|
|
"../../node_modules/bare-which/index.js"(exports, module) {
|
|
var { join, delimiter } = __require("path");
|
|
var process2 = __require("process");
|
|
var { isWindows } = require_which_runtime();
|
|
var isExecutable = require_executable();
|
|
var pathMatcher = isWindows ? /[/\\]/ : /\//;
|
|
var relativePathMatcher = new RegExp(`^\\.${pathMatcher.source}`);
|
|
var isPath = (path) => pathMatcher.test(path);
|
|
var isRelative = (path) => relativePathMatcher.test(path);
|
|
var ErrorNotFound = class extends Error {
|
|
constructor(command) {
|
|
super(`Command not found: ${command}`);
|
|
this.code = "ENOENT";
|
|
}
|
|
};
|
|
function getPathInfo(cmd, {
|
|
path: optPath = process2.env.PATH,
|
|
pathExt: optPathExt = process2.env.PATHEXT,
|
|
delimiter: optDelimiter = delimiter
|
|
}) {
|
|
const pathEnv = !isPath(cmd) ? [...isWindows ? [process2.cwd()] : [], ...(optPath || "").split(optDelimiter)] : [""];
|
|
if (!isWindows) return { pathEnv, pathExt: [""] };
|
|
const pathExtExe = optPathExt || [".EXE", ".CMD", ".BAT", ".COM"].join(optDelimiter);
|
|
const pathExt = pathExtExe.split(optDelimiter).flatMap((item) => [item, item.toLowerCase()]);
|
|
if (cmd.includes(".") && pathExt[0] !== "") pathExt.unshift("");
|
|
return { pathEnv, pathExt, pathExtExe };
|
|
}
|
|
function joinPathCommand(path, cmd) {
|
|
const pathPart = /^".*"$/.test(path) ? path.slice(1, -1) : path;
|
|
const prefix = !pathPart && isRelative(cmd) ? cmd.slice(0, 2) : "";
|
|
return prefix + join(pathPart, cmd);
|
|
}
|
|
function whichSync(cmd, options = {}) {
|
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, options);
|
|
const { all, nothrow } = options;
|
|
const found = [];
|
|
for (const pathEnvPart of pathEnv) {
|
|
const pathCommand = joinPathCommand(pathEnvPart, cmd);
|
|
for (const ext of pathExt) {
|
|
const withExt = pathCommand + ext;
|
|
if (isExecutable.sync(
|
|
withExt,
|
|
{ pathExt: pathExtExe, ignoreErrors: true }
|
|
)) {
|
|
if (!all) return withExt;
|
|
found.push(withExt);
|
|
}
|
|
}
|
|
}
|
|
if (all && found.length) return found;
|
|
if (nothrow) return null;
|
|
throw new ErrorNotFound(cmd);
|
|
}
|
|
async function whichAsync(cmd, options = {}) {
|
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, options);
|
|
const { all, nothrow } = options;
|
|
const foundPromises = [];
|
|
for (const pathEnvPart of pathEnv) {
|
|
const pathCommand = joinPathCommand(pathEnvPart, cmd);
|
|
for (const ext of pathExt) {
|
|
const withExt = pathCommand + ext;
|
|
if (all) {
|
|
foundPromises.push(
|
|
isExecutable(withExt, { pathExt: pathExtExe, ignoreErrors: true }).then((isExec) => isExec ? withExt : null)
|
|
);
|
|
} else if (await isExecutable(
|
|
withExt,
|
|
{ pathExt: pathExtExe, ignoreErrors: true }
|
|
)) return withExt;
|
|
}
|
|
}
|
|
const found = (await Promise.all(foundPromises)).filter((item) => item !== null);
|
|
if (all && found.length > 0) return found;
|
|
if (nothrow) return null;
|
|
throw new ErrorNotFound(cmd);
|
|
}
|
|
whichAsync.sync = whichSync;
|
|
module.exports = whichAsync;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/shared/exec.js
|
|
var require_exec = __commonJS({
|
|
"../../node_modules/bare-dev/lib/shared/exec.js"(exports, module) {
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var childProcess = __require("child_process");
|
|
module.exports = function exec(file, args = [], opts = {}) {
|
|
const {
|
|
env = process2.env,
|
|
cwd = path.resolve("."),
|
|
input,
|
|
quiet = true,
|
|
stdio = [input ? null : "ignore", "pipe", quiet ? "ignore" : "inherit"],
|
|
shell = requiresShell(file),
|
|
verbose = false
|
|
} = opts;
|
|
if (verbose) {
|
|
if (cwd !== path.resolve(".")) process2.stderr.write(`# cd ${cwd}
|
|
`);
|
|
process2.stderr.write(`# ${file} ${args.join(" ")}
|
|
`);
|
|
}
|
|
return childProcess.execFileSync(file, args, {
|
|
encoding: "utf-8",
|
|
stdio,
|
|
env,
|
|
cwd,
|
|
input,
|
|
shell
|
|
});
|
|
};
|
|
function requiresShell(cmd) {
|
|
if (process2.platform !== "win32") return false;
|
|
const ext = path.extname(cmd).toLowerCase();
|
|
return ext === ".bat" || ext === ".cmd";
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/shared/sdk.js
|
|
var require_sdk = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/shared/sdk.js"(exports) {
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var os = __require("os");
|
|
var which = require_bare_which();
|
|
var exec = require_exec();
|
|
exports.path = process2.env.ANDROID_HOME || path.join(os.homedir(), ".android/sdk");
|
|
var manager = exports.manager = function manager2() {
|
|
return which.sync("sdkmanager", {
|
|
path: path.join(exports.path, "cmdline-tools/latest/bin")
|
|
});
|
|
};
|
|
manager.install = function install(pkg, version, opts = {}) {
|
|
if (typeof version === "object") {
|
|
opts = version;
|
|
version = null;
|
|
}
|
|
pkg = Array.isArray(pkg) ? pkg.join(";") : pkg;
|
|
if (version) pkg += `;${version}`;
|
|
exec(manager(), ["--install", pkg], opts);
|
|
};
|
|
manager.uninstall = function install(pkg, version, opts = {}) {
|
|
if (typeof version === "object") {
|
|
opts = version;
|
|
version = null;
|
|
}
|
|
pkg = Array.isArray(pkg) ? pkg.join(";") : pkg;
|
|
if (version) pkg += `;${version}`;
|
|
exec(manager(), ["--uninstall", pkg], opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/shared/avd.js
|
|
var require_avd = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/shared/avd.js"(exports) {
|
|
var os = __require("os");
|
|
var path = __require("path");
|
|
var which = require_bare_which();
|
|
var exec = require_exec();
|
|
var sdk = require_sdk();
|
|
var manager = exports.manager = function manager2() {
|
|
return which.sync("avdmanager", {
|
|
path: path.join(sdk.path, "cmdline-tools/latest/bin")
|
|
});
|
|
};
|
|
manager.create = function create(name, version, opts = {}) {
|
|
const {
|
|
arch = os.arch(),
|
|
tag = "default",
|
|
force
|
|
} = opts;
|
|
const abi = toABI(arch);
|
|
const pkg = ["system-images", `android-${version}`, tag, abi];
|
|
sdk.manager.install(pkg, opts);
|
|
const args = [
|
|
"create",
|
|
"avd",
|
|
"--name",
|
|
name,
|
|
"--package",
|
|
pkg.join(";"),
|
|
"--tag",
|
|
tag,
|
|
"--abi",
|
|
abi
|
|
];
|
|
if (force) args.push("--force");
|
|
exec(manager(), args, { ...opts, input: "no" });
|
|
};
|
|
manager.remove = function remove(name, opts = {}) {
|
|
exec(manager(), ["delete", "avd", "--name", name], opts);
|
|
};
|
|
function toABI(arch) {
|
|
switch (arch) {
|
|
case "arm64":
|
|
return "arm64-v8a";
|
|
case "arm":
|
|
return "armeabi-v7a";
|
|
case "x64":
|
|
return "x86_64";
|
|
case "ia32":
|
|
return "x86";
|
|
}
|
|
throw new Error(`unsupported architecture "${arch}"`);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/device/create.js
|
|
var require_create = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/device/create.js"(exports, module) {
|
|
var avd = require_avd();
|
|
module.exports = function create(name, version, opts) {
|
|
avd.manager.create(name, version, opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/shared/spawn.js
|
|
var require_spawn = __commonJS({
|
|
"../../node_modules/bare-dev/lib/shared/spawn.js"(exports, module) {
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var childProcess = __require("child_process");
|
|
module.exports = function spawn(cmd, args = [], opts = {}) {
|
|
const {
|
|
env = process2.env,
|
|
cwd = path.resolve("."),
|
|
detached = false,
|
|
quiet = true,
|
|
stdio = quiet || detached ? "ignore" : "inherit",
|
|
shell = requiresShell(cmd),
|
|
verbose = false
|
|
} = opts;
|
|
if (verbose) {
|
|
if (cwd !== path.resolve(".")) process2.stderr.write(`# cd ${cwd}
|
|
`);
|
|
process2.stderr.write(`# ${cmd} ${args.join(" ")}
|
|
`);
|
|
}
|
|
let proc;
|
|
if (detached) {
|
|
proc = childProcess.spawn(cmd, args, {
|
|
stdio,
|
|
detached,
|
|
env,
|
|
cwd,
|
|
shell
|
|
});
|
|
proc.unref();
|
|
} else {
|
|
proc = childProcess.spawnSync(cmd, args, {
|
|
stdio,
|
|
env,
|
|
cwd,
|
|
shell
|
|
});
|
|
if (proc.status) throw new Error("spawn() failed");
|
|
}
|
|
return proc;
|
|
};
|
|
function requiresShell(cmd) {
|
|
if (process2.platform !== "win32") return false;
|
|
const ext = path.extname(cmd).toLowerCase();
|
|
return ext === ".bat" || ext === ".cmd";
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/shared/apkanalyzer.js
|
|
var require_apkanalyzer = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/shared/apkanalyzer.js"(exports, module) {
|
|
var path = __require("path");
|
|
var which = require_bare_which();
|
|
var exec = require_exec();
|
|
var sdk = require_sdk();
|
|
var apkanalyzer = module.exports = function apkanalyzer2() {
|
|
return which.sync("apkanalyzer", {
|
|
path: path.join(sdk.path, "cmdline-tools/latest/bin")
|
|
});
|
|
};
|
|
apkanalyzer.manifest = function manifest(apk, key, opts = {}) {
|
|
const {
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
apk = path.resolve(cwd, apk);
|
|
return exec(apkanalyzer(), ["manifest", key, apk], opts).trim();
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/shared/adb.js
|
|
var require_adb = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/shared/adb.js"(exports, module) {
|
|
var path = __require("path");
|
|
var os = __require("os");
|
|
var which = require_bare_which();
|
|
var exec = require_exec();
|
|
var spawn = require_spawn();
|
|
var sdk = require_sdk();
|
|
var apkanalyzer = require_apkanalyzer();
|
|
var adb = module.exports = function adb2() {
|
|
return which.sync("adb", {
|
|
path: path.join(sdk.path, "platform-tools")
|
|
});
|
|
};
|
|
adb.devices = function devices(opts = {}) {
|
|
const lines = exec(adb(), ["devices", "-l"], opts).split(os.EOL).filter(Boolean).slice(1);
|
|
const devices2 = [];
|
|
for (const line of lines) {
|
|
const [id, kind] = line.split(/[\s,]+/).filter(Boolean);
|
|
if (kind !== "device") continue;
|
|
const type = id.startsWith("emulator-") ? "emulator" : "device";
|
|
devices2.push({
|
|
id,
|
|
type,
|
|
name: name(id, { type }),
|
|
state: "booted"
|
|
});
|
|
}
|
|
return devices2;
|
|
};
|
|
adb.install = function install(device, apk, opts = {}) {
|
|
const {
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
if (device === "number") device = `emulator-${device}`;
|
|
apk = path.resolve(cwd, apk);
|
|
spawn(adb(), ["-s", device, "install", "-r", apk], opts);
|
|
};
|
|
adb.start = function start(device, apk, opts = {}) {
|
|
const {
|
|
activity = ".MainActivity",
|
|
waitForDebugger = false
|
|
} = opts;
|
|
if (device === "number") device = `emulator-${device}`;
|
|
const namespace = apkanalyzer.manifest(apk, "application-id", opts);
|
|
const args = [
|
|
"-s",
|
|
device,
|
|
"shell",
|
|
"am",
|
|
"start",
|
|
"-n",
|
|
`${namespace}/${activity}`,
|
|
"-S"
|
|
];
|
|
if (waitForDebugger) args.push("-D");
|
|
spawn(adb(), args, opts);
|
|
};
|
|
adb.wait = function wait(device, opts = {}) {
|
|
const {
|
|
state = "device"
|
|
} = opts;
|
|
if (typeof device === "number") device = `emulator-${device}`;
|
|
spawn(adb(), [
|
|
"-s",
|
|
device,
|
|
`wait-for-${state}`,
|
|
"shell",
|
|
"while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done"
|
|
], opts);
|
|
};
|
|
function name(device, opts = {}) {
|
|
const {
|
|
type = "emulator"
|
|
} = opts;
|
|
if (typeof device === "number") device = `emulator-${device}`;
|
|
let name2;
|
|
switch (type) {
|
|
case "device":
|
|
[name2] = exec(adb(), ["-s", device, "shell", "getprop", "ro.product.model"], opts).split(os.EOL);
|
|
break;
|
|
case "emulator":
|
|
[name2] = exec(adb(), ["-s", device, "emu", "avd", "name"], opts).split(os.EOL);
|
|
}
|
|
return name2.trim();
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/shared/emulator.js
|
|
var require_emulator = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/shared/emulator.js"(exports, module) {
|
|
var path = __require("path");
|
|
var os = __require("os");
|
|
var which = require_bare_which();
|
|
var exec = require_exec();
|
|
var spawn = require_spawn();
|
|
var sdk = require_sdk();
|
|
var adb = require_adb();
|
|
var emulator = module.exports = function emulator2() {
|
|
return which.sync("emulator", {
|
|
path: path.join(sdk.path, "emulator")
|
|
});
|
|
};
|
|
emulator.list = function list(opts) {
|
|
return exec(emulator(), ["-list-avds"], opts).split(os.EOL).filter(Boolean);
|
|
};
|
|
emulator.launch = function launch(device, opts = {}) {
|
|
const {
|
|
port = 5554
|
|
} = opts;
|
|
spawn(emulator(), [`@${device}`, "-port", port], { ...opts, detached: true });
|
|
adb.wait(port, opts);
|
|
return `emulator-${port}`;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/device/list.js
|
|
var require_list = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/device/list.js"(exports, module) {
|
|
var process2 = __require("process");
|
|
var adb = require_adb();
|
|
var emulator = require_emulator();
|
|
module.exports = function list(opts = {}) {
|
|
const {
|
|
separator = "\n",
|
|
quiet = true
|
|
} = opts;
|
|
const devices = adb.devices(opts);
|
|
for (const name of emulator.list(opts)) {
|
|
if (devices.some((device) => device.name === name)) continue;
|
|
devices.push({
|
|
id: null,
|
|
type: "emulator",
|
|
name,
|
|
state: "shutdown"
|
|
});
|
|
}
|
|
if (!quiet) {
|
|
let first = true;
|
|
for (const device of devices) {
|
|
let out = device.name;
|
|
if (/^\s+$/.test(separator)) {
|
|
out += separator;
|
|
} else {
|
|
first ? first = false : out = separator + out;
|
|
}
|
|
process2.stdout.write(out);
|
|
}
|
|
}
|
|
return devices;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/device/launch.js
|
|
var require_launch = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/device/launch.js"(exports, module) {
|
|
var emulator = require_emulator();
|
|
var list = require_list();
|
|
module.exports = function launch(name = null, opts) {
|
|
if (typeof name === "object" && name !== null) {
|
|
opts = name;
|
|
name = null;
|
|
}
|
|
const [device = null] = list().filter((candidate) => name ? candidate.name === name : true);
|
|
if (device === null) {
|
|
throw new Error(`launch() could not find device "${device}"`);
|
|
}
|
|
if (device.state !== "booted") {
|
|
device.id = emulator.launch(device.name, opts);
|
|
}
|
|
return device.id;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/device/remove.js
|
|
var require_remove = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/device/remove.js"(exports, module) {
|
|
var avd = require_avd();
|
|
module.exports = function remove(name, opts) {
|
|
avd.manager.remove(name, opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/device.js
|
|
var require_device = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/device.js"(exports) {
|
|
exports.create = require_create();
|
|
exports.launch = require_launch();
|
|
exports.list = require_list();
|
|
exports.remove = require_remove();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/balanced-match/index.js
|
|
var require_balanced_match = __commonJS({
|
|
"../../node_modules/balanced-match/index.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = balanced;
|
|
function balanced(a, b, str) {
|
|
if (a instanceof RegExp) a = maybeMatch(a, str);
|
|
if (b instanceof RegExp) b = maybeMatch(b, str);
|
|
var r = range(a, b, str);
|
|
return r && {
|
|
start: r[0],
|
|
end: r[1],
|
|
pre: str.slice(0, r[0]),
|
|
body: str.slice(r[0] + a.length, r[1]),
|
|
post: str.slice(r[1] + b.length)
|
|
};
|
|
}
|
|
function maybeMatch(reg, str) {
|
|
var m = str.match(reg);
|
|
return m ? m[0] : null;
|
|
}
|
|
balanced.range = range;
|
|
function range(a, b, str) {
|
|
var begs, beg, left, right, result;
|
|
var ai = str.indexOf(a);
|
|
var bi = str.indexOf(b, ai + 1);
|
|
var i = ai;
|
|
if (ai >= 0 && bi > 0) {
|
|
if (a === b) {
|
|
return [ai, bi];
|
|
}
|
|
begs = [];
|
|
left = str.length;
|
|
while (i >= 0 && !result) {
|
|
if (i == ai) {
|
|
begs.push(i);
|
|
ai = str.indexOf(a, i + 1);
|
|
} else if (begs.length == 1) {
|
|
result = [begs.pop(), bi];
|
|
} else {
|
|
beg = begs.pop();
|
|
if (beg < left) {
|
|
left = beg;
|
|
right = bi;
|
|
}
|
|
bi = str.indexOf(b, i + 1);
|
|
}
|
|
i = ai < bi && ai >= 0 ? ai : bi;
|
|
}
|
|
if (begs.length) {
|
|
result = [left, right];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/brace-expansion/index.js
|
|
var require_brace_expansion = __commonJS({
|
|
"../../node_modules/brace-expansion/index.js"(exports, module) {
|
|
var balanced = require_balanced_match();
|
|
module.exports = expandTop;
|
|
var escSlash = "\0SLASH" + Math.random() + "\0";
|
|
var escOpen = "\0OPEN" + Math.random() + "\0";
|
|
var escClose = "\0CLOSE" + Math.random() + "\0";
|
|
var escComma = "\0COMMA" + Math.random() + "\0";
|
|
var escPeriod = "\0PERIOD" + Math.random() + "\0";
|
|
function numeric(str) {
|
|
return parseInt(str, 10) == str ? parseInt(str, 10) : str.charCodeAt(0);
|
|
}
|
|
function escapeBraces(str) {
|
|
return str.split("\\\\").join(escSlash).split("\\{").join(escOpen).split("\\}").join(escClose).split("\\,").join(escComma).split("\\.").join(escPeriod);
|
|
}
|
|
function unescapeBraces(str) {
|
|
return str.split(escSlash).join("\\").split(escOpen).join("{").split(escClose).join("}").split(escComma).join(",").split(escPeriod).join(".");
|
|
}
|
|
function parseCommaParts(str) {
|
|
if (!str)
|
|
return [""];
|
|
var parts = [];
|
|
var m = balanced("{", "}", str);
|
|
if (!m)
|
|
return str.split(",");
|
|
var pre = m.pre;
|
|
var body = m.body;
|
|
var post = m.post;
|
|
var p = pre.split(",");
|
|
p[p.length - 1] += "{" + body + "}";
|
|
var postParts = parseCommaParts(post);
|
|
if (post.length) {
|
|
p[p.length - 1] += postParts.shift();
|
|
p.push.apply(p, postParts);
|
|
}
|
|
parts.push.apply(parts, p);
|
|
return parts;
|
|
}
|
|
function expandTop(str) {
|
|
if (!str)
|
|
return [];
|
|
if (str.substr(0, 2) === "{}") {
|
|
str = "\\{\\}" + str.substr(2);
|
|
}
|
|
return expand(escapeBraces(str), true).map(unescapeBraces);
|
|
}
|
|
function embrace(str) {
|
|
return "{" + str + "}";
|
|
}
|
|
function isPadded(el) {
|
|
return /^-?0\d/.test(el);
|
|
}
|
|
function lte(i, y) {
|
|
return i <= y;
|
|
}
|
|
function gte(i, y) {
|
|
return i >= y;
|
|
}
|
|
function expand(str, isTop) {
|
|
var expansions = [];
|
|
var m = balanced("{", "}", str);
|
|
if (!m) return [str];
|
|
var pre = m.pre;
|
|
var post = m.post.length ? expand(m.post, false) : [""];
|
|
if (/\$$/.test(m.pre)) {
|
|
for (var k = 0; k < post.length; k++) {
|
|
var expansion = pre + "{" + m.body + "}" + post[k];
|
|
expansions.push(expansion);
|
|
}
|
|
} else {
|
|
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
|
|
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
|
|
var isSequence = isNumericSequence || isAlphaSequence;
|
|
var isOptions = m.body.indexOf(",") >= 0;
|
|
if (!isSequence && !isOptions) {
|
|
if (m.post.match(/,(?!,).*\}/)) {
|
|
str = m.pre + "{" + m.body + escClose + m.post;
|
|
return expand(str);
|
|
}
|
|
return [str];
|
|
}
|
|
var n;
|
|
if (isSequence) {
|
|
n = m.body.split(/\.\./);
|
|
} else {
|
|
n = parseCommaParts(m.body);
|
|
if (n.length === 1) {
|
|
n = expand(n[0], false).map(embrace);
|
|
if (n.length === 1) {
|
|
return post.map(function(p) {
|
|
return m.pre + n[0] + p;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
var N;
|
|
if (isSequence) {
|
|
var x = numeric(n[0]);
|
|
var y = numeric(n[1]);
|
|
var width = Math.max(n[0].length, n[1].length);
|
|
var incr = n.length == 3 ? Math.max(Math.abs(numeric(n[2])), 1) : 1;
|
|
var test = lte;
|
|
var reverse = y < x;
|
|
if (reverse) {
|
|
incr *= -1;
|
|
test = gte;
|
|
}
|
|
var pad = n.some(isPadded);
|
|
N = [];
|
|
for (var i = x; test(i, y); i += incr) {
|
|
var c;
|
|
if (isAlphaSequence) {
|
|
c = String.fromCharCode(i);
|
|
if (c === "\\")
|
|
c = "";
|
|
} else {
|
|
c = String(i);
|
|
if (pad) {
|
|
var need = width - c.length;
|
|
if (need > 0) {
|
|
var z = new Array(need + 1).join("0");
|
|
if (i < 0)
|
|
c = "-" + z + c.slice(1);
|
|
else
|
|
c = z + c;
|
|
}
|
|
}
|
|
}
|
|
N.push(c);
|
|
}
|
|
} else {
|
|
N = [];
|
|
for (var j = 0; j < n.length; j++) {
|
|
N.push.apply(N, expand(n[j], false));
|
|
}
|
|
}
|
|
for (var j = 0; j < N.length; j++) {
|
|
for (var k = 0; k < post.length; k++) {
|
|
var expansion = pre + N[j] + post[k];
|
|
if (!isTop || isSequence || expansion)
|
|
expansions.push(expansion);
|
|
}
|
|
}
|
|
}
|
|
return expansions;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/minimatch/dist/commonjs/assert-valid-pattern.js
|
|
var require_assert_valid_pattern = __commonJS({
|
|
"../../node_modules/minimatch/dist/commonjs/assert-valid-pattern.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.assertValidPattern = void 0;
|
|
var MAX_PATTERN_LENGTH = 1024 * 64;
|
|
var assertValidPattern = (pattern) => {
|
|
if (typeof pattern !== "string") {
|
|
throw new TypeError("invalid pattern");
|
|
}
|
|
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
throw new TypeError("pattern is too long");
|
|
}
|
|
};
|
|
exports.assertValidPattern = assertValidPattern;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/minimatch/dist/commonjs/brace-expressions.js
|
|
var require_brace_expressions = __commonJS({
|
|
"../../node_modules/minimatch/dist/commonjs/brace-expressions.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.parseClass = void 0;
|
|
var posixClasses = {
|
|
"[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true],
|
|
"[:alpha:]": ["\\p{L}\\p{Nl}", true],
|
|
"[:ascii:]": ["\\x00-\\x7f", false],
|
|
"[:blank:]": ["\\p{Zs}\\t", true],
|
|
"[:cntrl:]": ["\\p{Cc}", true],
|
|
"[:digit:]": ["\\p{Nd}", true],
|
|
"[:graph:]": ["\\p{Z}\\p{C}", true, true],
|
|
"[:lower:]": ["\\p{Ll}", true],
|
|
"[:print:]": ["\\p{C}", true],
|
|
"[:punct:]": ["\\p{P}", true],
|
|
"[:space:]": ["\\p{Z}\\t\\r\\n\\v\\f", true],
|
|
"[:upper:]": ["\\p{Lu}", true],
|
|
"[:word:]": ["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}", true],
|
|
"[:xdigit:]": ["A-Fa-f0-9", false]
|
|
};
|
|
var braceEscape = (s) => s.replace(/[[\]\\-]/g, "\\$&");
|
|
var regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
|
var rangesToString = (ranges) => ranges.join("");
|
|
var parseClass = (glob, position) => {
|
|
const pos = position;
|
|
if (glob.charAt(pos) !== "[") {
|
|
throw new Error("not in a brace expression");
|
|
}
|
|
const ranges = [];
|
|
const negs = [];
|
|
let i = pos + 1;
|
|
let sawStart = false;
|
|
let uflag = false;
|
|
let escaping = false;
|
|
let negate = false;
|
|
let endPos = pos;
|
|
let rangeStart = "";
|
|
WHILE: while (i < glob.length) {
|
|
const c = glob.charAt(i);
|
|
if ((c === "!" || c === "^") && i === pos + 1) {
|
|
negate = true;
|
|
i++;
|
|
continue;
|
|
}
|
|
if (c === "]" && sawStart && !escaping) {
|
|
endPos = i + 1;
|
|
break;
|
|
}
|
|
sawStart = true;
|
|
if (c === "\\") {
|
|
if (!escaping) {
|
|
escaping = true;
|
|
i++;
|
|
continue;
|
|
}
|
|
}
|
|
if (c === "[" && !escaping) {
|
|
for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
|
|
if (glob.startsWith(cls, i)) {
|
|
if (rangeStart) {
|
|
return ["$.", false, glob.length - pos, true];
|
|
}
|
|
i += cls.length;
|
|
if (neg)
|
|
negs.push(unip);
|
|
else
|
|
ranges.push(unip);
|
|
uflag = uflag || u;
|
|
continue WHILE;
|
|
}
|
|
}
|
|
}
|
|
escaping = false;
|
|
if (rangeStart) {
|
|
if (c > rangeStart) {
|
|
ranges.push(braceEscape(rangeStart) + "-" + braceEscape(c));
|
|
} else if (c === rangeStart) {
|
|
ranges.push(braceEscape(c));
|
|
}
|
|
rangeStart = "";
|
|
i++;
|
|
continue;
|
|
}
|
|
if (glob.startsWith("-]", i + 1)) {
|
|
ranges.push(braceEscape(c + "-"));
|
|
i += 2;
|
|
continue;
|
|
}
|
|
if (glob.startsWith("-", i + 1)) {
|
|
rangeStart = c;
|
|
i += 2;
|
|
continue;
|
|
}
|
|
ranges.push(braceEscape(c));
|
|
i++;
|
|
}
|
|
if (endPos < i) {
|
|
return ["", false, 0, false];
|
|
}
|
|
if (!ranges.length && !negs.length) {
|
|
return ["$.", false, glob.length - pos, true];
|
|
}
|
|
if (negs.length === 0 && ranges.length === 1 && /^\\?.$/.test(ranges[0]) && !negate) {
|
|
const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
|
|
return [regexpEscape(r), false, endPos - pos, false];
|
|
}
|
|
const sranges = "[" + (negate ? "^" : "") + rangesToString(ranges) + "]";
|
|
const snegs = "[" + (negate ? "" : "^") + rangesToString(negs) + "]";
|
|
const comb = ranges.length && negs.length ? "(" + sranges + "|" + snegs + ")" : ranges.length ? sranges : snegs;
|
|
return [comb, uflag, endPos - pos, true];
|
|
};
|
|
exports.parseClass = parseClass;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/minimatch/dist/commonjs/unescape.js
|
|
var require_unescape = __commonJS({
|
|
"../../node_modules/minimatch/dist/commonjs/unescape.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.unescape = void 0;
|
|
var unescape = (s, { windowsPathsNoEscape = false } = {}) => {
|
|
return windowsPathsNoEscape ? s.replace(/\[([^\/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1");
|
|
};
|
|
exports.unescape = unescape;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/minimatch/dist/commonjs/ast.js
|
|
var require_ast = __commonJS({
|
|
"../../node_modules/minimatch/dist/commonjs/ast.js"(exports) {
|
|
"use strict";
|
|
var _a;
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.AST = void 0;
|
|
var brace_expressions_js_1 = require_brace_expressions();
|
|
var unescape_js_1 = require_unescape();
|
|
var types = /* @__PURE__ */ new Set(["!", "?", "+", "*", "@"]);
|
|
var isExtglobType = (c) => types.has(c);
|
|
var isExtglobAST = (c) => isExtglobType(c.type);
|
|
var adoptionMap = /* @__PURE__ */ new Map([
|
|
["!", ["@"]],
|
|
["?", ["?", "@"]],
|
|
["@", ["@"]],
|
|
["*", ["*", "+", "?", "@"]],
|
|
["+", ["+", "@"]]
|
|
]);
|
|
var adoptionWithSpaceMap = /* @__PURE__ */ new Map([
|
|
["!", ["?"]],
|
|
["@", ["?"]],
|
|
["+", ["?", "*"]]
|
|
]);
|
|
var adoptionAnyMap = /* @__PURE__ */ new Map([
|
|
["!", ["?", "@"]],
|
|
["?", ["?", "@"]],
|
|
["@", ["?", "@"]],
|
|
["*", ["*", "+", "?", "@"]],
|
|
["+", ["+", "@", "?", "*"]]
|
|
]);
|
|
var usurpMap = /* @__PURE__ */ new Map([
|
|
["!", /* @__PURE__ */ new Map([["!", "@"]])],
|
|
["?", /* @__PURE__ */ new Map([["*", "*"], ["+", "*"]])],
|
|
["@", /* @__PURE__ */ new Map([["!", "!"], ["?", "?"], ["@", "@"], ["*", "*"], ["+", "+"]])],
|
|
["+", /* @__PURE__ */ new Map([["?", "*"], ["*", "*"]])]
|
|
]);
|
|
var startNoTraversal = "(?!(?:^|/)\\.\\.?(?:$|/))";
|
|
var startNoDot = "(?!\\.)";
|
|
var addPatternStart = /* @__PURE__ */ new Set(["[", "."]);
|
|
var justDots = /* @__PURE__ */ new Set(["..", "."]);
|
|
var reSpecials = new Set("().*{}+?[]^$\\!");
|
|
var regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
|
var qmark = "[^/]";
|
|
var star = qmark + "*?";
|
|
var starNoEmpty = qmark + "+?";
|
|
var AST = class {
|
|
type;
|
|
#root;
|
|
#hasMagic;
|
|
#uflag = false;
|
|
#parts = [];
|
|
#parent;
|
|
#parentIndex;
|
|
#negs;
|
|
#filledNegs = false;
|
|
#options;
|
|
#toString;
|
|
// set to true if it's an extglob with no children
|
|
// (which really means one child of '')
|
|
#emptyExt = false;
|
|
constructor(type, parent, options = {}) {
|
|
this.type = type;
|
|
if (type)
|
|
this.#hasMagic = true;
|
|
this.#parent = parent;
|
|
this.#root = this.#parent ? this.#parent.#root : this;
|
|
this.#options = this.#root === this ? options : this.#root.#options;
|
|
this.#negs = this.#root === this ? [] : this.#root.#negs;
|
|
if (type === "!" && !this.#root.#filledNegs)
|
|
this.#negs.push(this);
|
|
this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
|
|
}
|
|
get hasMagic() {
|
|
if (this.#hasMagic !== void 0)
|
|
return this.#hasMagic;
|
|
for (const p of this.#parts) {
|
|
if (typeof p === "string")
|
|
continue;
|
|
if (p.type || p.hasMagic)
|
|
return this.#hasMagic = true;
|
|
}
|
|
return this.#hasMagic;
|
|
}
|
|
// reconstructs the pattern
|
|
toString() {
|
|
if (this.#toString !== void 0)
|
|
return this.#toString;
|
|
if (!this.type) {
|
|
return this.#toString = this.#parts.map((p) => String(p)).join("");
|
|
} else {
|
|
return this.#toString = this.type + "(" + this.#parts.map((p) => String(p)).join("|") + ")";
|
|
}
|
|
}
|
|
#fillNegs() {
|
|
if (this !== this.#root)
|
|
throw new Error("should only call on root");
|
|
if (this.#filledNegs)
|
|
return this;
|
|
this.toString();
|
|
this.#filledNegs = true;
|
|
let n;
|
|
while (n = this.#negs.pop()) {
|
|
if (n.type !== "!")
|
|
continue;
|
|
let p = n;
|
|
let pp = p.#parent;
|
|
while (pp) {
|
|
for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) {
|
|
for (const part of n.#parts) {
|
|
if (typeof part === "string") {
|
|
throw new Error("string part in extglob AST??");
|
|
}
|
|
part.copyIn(pp.#parts[i]);
|
|
}
|
|
}
|
|
p = pp;
|
|
pp = p.#parent;
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
push(...parts) {
|
|
for (const p of parts) {
|
|
if (p === "")
|
|
continue;
|
|
if (typeof p !== "string" && !(p instanceof _a && p.#parent === this)) {
|
|
throw new Error("invalid part: " + p);
|
|
}
|
|
this.#parts.push(p);
|
|
}
|
|
}
|
|
toJSON() {
|
|
const ret = this.type === null ? this.#parts.slice().map((p) => typeof p === "string" ? p : p.toJSON()) : [this.type, ...this.#parts.map((p) => p.toJSON())];
|
|
if (this.isStart() && !this.type)
|
|
ret.unshift([]);
|
|
if (this.isEnd() && (this === this.#root || this.#root.#filledNegs && this.#parent?.type === "!")) {
|
|
ret.push({});
|
|
}
|
|
return ret;
|
|
}
|
|
isStart() {
|
|
if (this.#root === this)
|
|
return true;
|
|
if (!this.#parent?.isStart())
|
|
return false;
|
|
if (this.#parentIndex === 0)
|
|
return true;
|
|
const p = this.#parent;
|
|
for (let i = 0; i < this.#parentIndex; i++) {
|
|
const pp = p.#parts[i];
|
|
if (!(pp instanceof _a && pp.type === "!")) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
isEnd() {
|
|
if (this.#root === this)
|
|
return true;
|
|
if (this.#parent?.type === "!")
|
|
return true;
|
|
if (!this.#parent?.isEnd())
|
|
return false;
|
|
if (!this.type)
|
|
return this.#parent?.isEnd();
|
|
const pl = this.#parent ? this.#parent.#parts.length : 0;
|
|
return this.#parentIndex === pl - 1;
|
|
}
|
|
copyIn(part) {
|
|
if (typeof part === "string")
|
|
this.push(part);
|
|
else
|
|
this.push(part.clone(this));
|
|
}
|
|
clone(parent) {
|
|
const c = new _a(this.type, parent);
|
|
for (const p of this.#parts) {
|
|
c.copyIn(p);
|
|
}
|
|
return c;
|
|
}
|
|
static #parseAST(str, ast, pos, opt, extDepth) {
|
|
const maxDepth = opt.maxExtglobRecursion ?? 2;
|
|
let escaping = false;
|
|
let inBrace = false;
|
|
let braceStart = -1;
|
|
let braceNeg = false;
|
|
if (ast.type === null) {
|
|
let i2 = pos;
|
|
let acc2 = "";
|
|
while (i2 < str.length) {
|
|
const c = str.charAt(i2++);
|
|
if (escaping || c === "\\") {
|
|
escaping = !escaping;
|
|
acc2 += c;
|
|
continue;
|
|
}
|
|
if (inBrace) {
|
|
if (i2 === braceStart + 1) {
|
|
if (c === "^" || c === "!") {
|
|
braceNeg = true;
|
|
}
|
|
} else if (c === "]" && !(i2 === braceStart + 2 && braceNeg)) {
|
|
inBrace = false;
|
|
}
|
|
acc2 += c;
|
|
continue;
|
|
} else if (c === "[") {
|
|
inBrace = true;
|
|
braceStart = i2;
|
|
braceNeg = false;
|
|
acc2 += c;
|
|
continue;
|
|
}
|
|
const doRecurse = !opt.noext && isExtglobType(c) && str.charAt(i2) === "(" && extDepth <= maxDepth;
|
|
if (doRecurse) {
|
|
ast.push(acc2);
|
|
acc2 = "";
|
|
const ext = new _a(c, ast);
|
|
i2 = _a.#parseAST(str, ext, i2, opt, extDepth + 1);
|
|
ast.push(ext);
|
|
continue;
|
|
}
|
|
acc2 += c;
|
|
}
|
|
ast.push(acc2);
|
|
return i2;
|
|
}
|
|
let i = pos + 1;
|
|
let part = new _a(null, ast);
|
|
const parts = [];
|
|
let acc = "";
|
|
while (i < str.length) {
|
|
const c = str.charAt(i++);
|
|
if (escaping || c === "\\") {
|
|
escaping = !escaping;
|
|
acc += c;
|
|
continue;
|
|
}
|
|
if (inBrace) {
|
|
if (i === braceStart + 1) {
|
|
if (c === "^" || c === "!") {
|
|
braceNeg = true;
|
|
}
|
|
} else if (c === "]" && !(i === braceStart + 2 && braceNeg)) {
|
|
inBrace = false;
|
|
}
|
|
acc += c;
|
|
continue;
|
|
} else if (c === "[") {
|
|
inBrace = true;
|
|
braceStart = i;
|
|
braceNeg = false;
|
|
acc += c;
|
|
continue;
|
|
}
|
|
const doRecurse = isExtglobType(c) && str.charAt(i) === "(" && /* c8 ignore start - the maxDepth is sufficient here */
|
|
(extDepth <= maxDepth || ast && ast.#canAdoptType(c));
|
|
if (doRecurse) {
|
|
const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1;
|
|
part.push(acc);
|
|
acc = "";
|
|
const ext = new _a(c, part);
|
|
part.push(ext);
|
|
i = _a.#parseAST(str, ext, i, opt, extDepth + depthAdd);
|
|
continue;
|
|
}
|
|
if (c === "|") {
|
|
part.push(acc);
|
|
acc = "";
|
|
parts.push(part);
|
|
part = new _a(null, ast);
|
|
continue;
|
|
}
|
|
if (c === ")") {
|
|
if (acc === "" && ast.#parts.length === 0) {
|
|
ast.#emptyExt = true;
|
|
}
|
|
part.push(acc);
|
|
acc = "";
|
|
ast.push(...parts, part);
|
|
return i;
|
|
}
|
|
acc += c;
|
|
}
|
|
ast.type = null;
|
|
ast.#hasMagic = void 0;
|
|
ast.#parts = [str.substring(pos - 1)];
|
|
return i;
|
|
}
|
|
#canAdoptWithSpace(child) {
|
|
return this.#canAdopt(child, adoptionWithSpaceMap);
|
|
}
|
|
#canAdopt(child, map = adoptionMap) {
|
|
if (!child || typeof child !== "object" || child.type !== null || child.#parts.length !== 1 || this.type === null) {
|
|
return false;
|
|
}
|
|
const gc = child.#parts[0];
|
|
if (!gc || typeof gc !== "object" || gc.type === null) {
|
|
return false;
|
|
}
|
|
return this.#canAdoptType(gc.type, map);
|
|
}
|
|
#canAdoptType(c, map = adoptionAnyMap) {
|
|
return !!map.get(this.type)?.includes(c);
|
|
}
|
|
#adoptWithSpace(child, index) {
|
|
const gc = child.#parts[0];
|
|
const blank = new _a(null, gc, this.options);
|
|
blank.#parts.push("");
|
|
gc.push(blank);
|
|
this.#adopt(child, index);
|
|
}
|
|
#adopt(child, index) {
|
|
const gc = child.#parts[0];
|
|
this.#parts.splice(index, 1, ...gc.#parts);
|
|
for (const p of gc.#parts) {
|
|
if (typeof p === "object")
|
|
p.#parent = this;
|
|
}
|
|
this.#toString = void 0;
|
|
}
|
|
#canUsurpType(c) {
|
|
const m = usurpMap.get(this.type);
|
|
return !!m?.has(c);
|
|
}
|
|
#canUsurp(child) {
|
|
if (!child || typeof child !== "object" || child.type !== null || child.#parts.length !== 1 || this.type === null || this.#parts.length !== 1) {
|
|
return false;
|
|
}
|
|
const gc = child.#parts[0];
|
|
if (!gc || typeof gc !== "object" || gc.type === null) {
|
|
return false;
|
|
}
|
|
return this.#canUsurpType(gc.type);
|
|
}
|
|
#usurp(child) {
|
|
const m = usurpMap.get(this.type);
|
|
const gc = child.#parts[0];
|
|
const nt = m?.get(gc.type);
|
|
if (!nt)
|
|
return false;
|
|
this.#parts = gc.#parts;
|
|
for (const p of this.#parts) {
|
|
if (typeof p === "object")
|
|
p.#parent = this;
|
|
}
|
|
this.type = nt;
|
|
this.#toString = void 0;
|
|
this.#emptyExt = false;
|
|
}
|
|
#flatten() {
|
|
if (!isExtglobAST(this)) {
|
|
for (const p of this.#parts) {
|
|
if (typeof p === "object")
|
|
p.#flatten();
|
|
}
|
|
} else {
|
|
let iterations = 0;
|
|
let done = false;
|
|
do {
|
|
done = true;
|
|
for (let i = 0; i < this.#parts.length; i++) {
|
|
const c = this.#parts[i];
|
|
if (typeof c === "object") {
|
|
c.#flatten();
|
|
if (this.#canAdopt(c)) {
|
|
done = false;
|
|
this.#adopt(c, i);
|
|
} else if (this.#canAdoptWithSpace(c)) {
|
|
done = false;
|
|
this.#adoptWithSpace(c, i);
|
|
} else if (this.#canUsurp(c)) {
|
|
done = false;
|
|
this.#usurp(c);
|
|
}
|
|
}
|
|
}
|
|
} while (!done && ++iterations < 10);
|
|
}
|
|
this.#toString = void 0;
|
|
}
|
|
static fromGlob(pattern, options = {}) {
|
|
const ast = new _a(null, void 0, options);
|
|
_a.#parseAST(pattern, ast, 0, options, 0);
|
|
return ast;
|
|
}
|
|
// returns the regular expression if there's magic, or the unescaped
|
|
// string if not.
|
|
toMMPattern() {
|
|
if (this !== this.#root)
|
|
return this.#root.toMMPattern();
|
|
const glob = this.toString();
|
|
const [re, body, hasMagic, uflag] = this.toRegExpSource();
|
|
const anyMagic = hasMagic || this.#hasMagic || this.#options.nocase && !this.#options.nocaseMagicOnly && glob.toUpperCase() !== glob.toLowerCase();
|
|
if (!anyMagic) {
|
|
return body;
|
|
}
|
|
const flags = (this.#options.nocase ? "i" : "") + (uflag ? "u" : "");
|
|
return Object.assign(new RegExp(`^${re}$`, flags), {
|
|
_src: re,
|
|
_glob: glob
|
|
});
|
|
}
|
|
get options() {
|
|
return this.#options;
|
|
}
|
|
// returns the string match, the regexp source, whether there's magic
|
|
// in the regexp (so a regular expression is required) and whether or
|
|
// not the uflag is needed for the regular expression (for posix classes)
|
|
// NOTE: instead of injecting the start/end at this point, just return
|
|
// the BODY of the regexp, along with the start/end portions suitable
|
|
// for binding the start/end in either a joined full-path makeRe context
|
|
// (where we bind to (^|/), or a standalone matchPart context (where
|
|
// we bind to ^, and not /). Otherwise slashes get duped!
|
|
//
|
|
// In part-matching mode, the start is:
|
|
// - if not isStart: nothing
|
|
// - if traversal possible, but not allowed: ^(?!\.\.?$)
|
|
// - if dots allowed or not possible: ^
|
|
// - if dots possible and not allowed: ^(?!\.)
|
|
// end is:
|
|
// - if not isEnd(): nothing
|
|
// - else: $
|
|
//
|
|
// In full-path matching mode, we put the slash at the START of the
|
|
// pattern, so start is:
|
|
// - if first pattern: same as part-matching mode
|
|
// - if not isStart(): nothing
|
|
// - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
|
|
// - if dots allowed or not possible: /
|
|
// - if dots possible and not allowed: /(?!\.)
|
|
// end is:
|
|
// - if last pattern, same as part-matching mode
|
|
// - else nothing
|
|
//
|
|
// Always put the (?:$|/) on negated tails, though, because that has to be
|
|
// there to bind the end of the negated pattern portion, and it's easier to
|
|
// just stick it in now rather than try to inject it later in the middle of
|
|
// the pattern.
|
|
//
|
|
// We can just always return the same end, and leave it up to the caller
|
|
// to know whether it's going to be used joined or in parts.
|
|
// And, if the start is adjusted slightly, can do the same there:
|
|
// - if not isStart: nothing
|
|
// - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$)
|
|
// - if dots allowed or not possible: (?:/|^)
|
|
// - if dots possible and not allowed: (?:/|^)(?!\.)
|
|
//
|
|
// But it's better to have a simpler binding without a conditional, for
|
|
// performance, so probably better to return both start options.
|
|
//
|
|
// Then the caller just ignores the end if it's not the first pattern,
|
|
// and the start always gets applied.
|
|
//
|
|
// But that's always going to be $ if it's the ending pattern, or nothing,
|
|
// so the caller can just attach $ at the end of the pattern when building.
|
|
//
|
|
// So the next step is:
|
|
// - better detect what kind of start is needed
|
|
// - return both flavors of starting pattern
|
|
// - attach $ at the end of the pattern when creating the actual RegExp
|
|
//
|
|
// Ah, but wait, no, that all only applies to the root when the first pattern
|
|
// is not an extglob. If the first pattern IS an extglob, then we need all
|
|
// that dot prevention biz to live in the extglob portions, because eg
|
|
// +(*|.x*) can match .xy but not .yx.
|
|
//
|
|
// So, return the two flavors if it's #root and the first child is not an
|
|
// AST, otherwise leave it to the child AST to handle it, and there,
|
|
// use the (?:^|/) style of start binding.
|
|
//
|
|
// Even simplified further:
|
|
// - Since the start for a join is eg /(?!\.) and the start for a part
|
|
// is ^(?!\.), we can just prepend (?!\.) to the pattern (either root
|
|
// or start or whatever) and prepend ^ or / at the Regexp construction.
|
|
toRegExpSource(allowDot) {
|
|
const dot = allowDot ?? !!this.#options.dot;
|
|
if (this.#root === this) {
|
|
this.#flatten();
|
|
this.#fillNegs();
|
|
}
|
|
if (!isExtglobAST(this)) {
|
|
const noEmpty = this.isStart() && this.isEnd();
|
|
const src = this.#parts.map((p) => {
|
|
const [re, _, hasMagic, uflag] = typeof p === "string" ? _a.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot);
|
|
this.#hasMagic = this.#hasMagic || hasMagic;
|
|
this.#uflag = this.#uflag || uflag;
|
|
return re;
|
|
}).join("");
|
|
let start2 = "";
|
|
if (this.isStart()) {
|
|
if (typeof this.#parts[0] === "string") {
|
|
const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
|
|
if (!dotTravAllowed) {
|
|
const aps = addPatternStart;
|
|
const needNoTrav = (
|
|
// dots are allowed, and the pattern starts with [ or .
|
|
dot && aps.has(src.charAt(0)) || // the pattern starts with \., and then [ or .
|
|
src.startsWith("\\.") && aps.has(src.charAt(2)) || // the pattern starts with \.\., and then [ or .
|
|
src.startsWith("\\.\\.") && aps.has(src.charAt(4))
|
|
);
|
|
const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
|
|
start2 = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : "";
|
|
}
|
|
}
|
|
}
|
|
let end = "";
|
|
if (this.isEnd() && this.#root.#filledNegs && this.#parent?.type === "!") {
|
|
end = "(?:$|\\/)";
|
|
}
|
|
const final2 = start2 + src + end;
|
|
return [
|
|
final2,
|
|
(0, unescape_js_1.unescape)(src),
|
|
this.#hasMagic = !!this.#hasMagic,
|
|
this.#uflag
|
|
];
|
|
}
|
|
const repeated = this.type === "*" || this.type === "+";
|
|
const start = this.type === "!" ? "(?:(?!(?:" : "(?:";
|
|
let body = this.#partsToRegExp(dot);
|
|
if (this.isStart() && this.isEnd() && !body && this.type !== "!") {
|
|
const s = this.toString();
|
|
const me = this;
|
|
me.#parts = [s];
|
|
me.type = null;
|
|
me.#hasMagic = void 0;
|
|
return [s, (0, unescape_js_1.unescape)(this.toString()), false, false];
|
|
}
|
|
let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot ? "" : this.#partsToRegExp(true);
|
|
if (bodyDotAllowed === body) {
|
|
bodyDotAllowed = "";
|
|
}
|
|
if (bodyDotAllowed) {
|
|
body = `(?:${body})(?:${bodyDotAllowed})*?`;
|
|
}
|
|
let final = "";
|
|
if (this.type === "!" && this.#emptyExt) {
|
|
final = (this.isStart() && !dot ? startNoDot : "") + starNoEmpty;
|
|
} else {
|
|
const close = this.type === "!" ? (
|
|
// !() must match something,but !(x) can match ''
|
|
"))" + (this.isStart() && !dot && !allowDot ? startNoDot : "") + star + ")"
|
|
) : this.type === "@" ? ")" : this.type === "?" ? ")?" : this.type === "+" && bodyDotAllowed ? ")" : this.type === "*" && bodyDotAllowed ? `)?` : `)${this.type}`;
|
|
final = start + body + close;
|
|
}
|
|
return [
|
|
final,
|
|
(0, unescape_js_1.unescape)(body),
|
|
this.#hasMagic = !!this.#hasMagic,
|
|
this.#uflag
|
|
];
|
|
}
|
|
#partsToRegExp(dot) {
|
|
return this.#parts.map((p) => {
|
|
if (typeof p === "string") {
|
|
throw new Error("string type in extglob ast??");
|
|
}
|
|
const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot);
|
|
this.#uflag = this.#uflag || uflag;
|
|
return re;
|
|
}).filter((p) => !(this.isStart() && this.isEnd()) || !!p).join("|");
|
|
}
|
|
static #parseGlob(glob, hasMagic, noEmpty = false) {
|
|
let escaping = false;
|
|
let re = "";
|
|
let uflag = false;
|
|
let inStar = false;
|
|
for (let i = 0; i < glob.length; i++) {
|
|
const c = glob.charAt(i);
|
|
if (escaping) {
|
|
escaping = false;
|
|
re += (reSpecials.has(c) ? "\\" : "") + c;
|
|
inStar = false;
|
|
continue;
|
|
}
|
|
if (c === "\\") {
|
|
if (i === glob.length - 1) {
|
|
re += "\\\\";
|
|
} else {
|
|
escaping = true;
|
|
}
|
|
continue;
|
|
}
|
|
if (c === "[") {
|
|
const [src, needUflag, consumed, magic] = (0, brace_expressions_js_1.parseClass)(glob, i);
|
|
if (consumed) {
|
|
re += src;
|
|
uflag = uflag || needUflag;
|
|
i += consumed - 1;
|
|
hasMagic = hasMagic || magic;
|
|
inStar = false;
|
|
continue;
|
|
}
|
|
}
|
|
if (c === "*") {
|
|
if (inStar)
|
|
continue;
|
|
inStar = true;
|
|
re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star;
|
|
hasMagic = true;
|
|
continue;
|
|
} else {
|
|
inStar = false;
|
|
}
|
|
if (c === "?") {
|
|
re += qmark;
|
|
hasMagic = true;
|
|
continue;
|
|
}
|
|
re += regExpEscape(c);
|
|
}
|
|
return [re, (0, unescape_js_1.unescape)(glob), !!hasMagic, uflag];
|
|
}
|
|
};
|
|
exports.AST = AST;
|
|
_a = AST;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/minimatch/dist/commonjs/escape.js
|
|
var require_escape = __commonJS({
|
|
"../../node_modules/minimatch/dist/commonjs/escape.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.escape = void 0;
|
|
var escape = (s, { windowsPathsNoEscape = false } = {}) => {
|
|
return windowsPathsNoEscape ? s.replace(/[?*()[\]]/g, "[$&]") : s.replace(/[?*()[\]\\]/g, "\\$&");
|
|
};
|
|
exports.escape = escape;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/minimatch/dist/commonjs/index.js
|
|
var require_commonjs = __commonJS({
|
|
"../../node_modules/minimatch/dist/commonjs/index.js"(exports) {
|
|
"use strict";
|
|
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.unescape = exports.escape = exports.AST = exports.Minimatch = exports.match = exports.makeRe = exports.braceExpand = exports.defaults = exports.filter = exports.GLOBSTAR = exports.sep = exports.minimatch = void 0;
|
|
var brace_expansion_1 = __importDefault(require_brace_expansion());
|
|
var assert_valid_pattern_js_1 = require_assert_valid_pattern();
|
|
var ast_js_1 = require_ast();
|
|
var escape_js_1 = require_escape();
|
|
var unescape_js_1 = require_unescape();
|
|
var minimatch = (p, pattern, options = {}) => {
|
|
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
if (!options.nocomment && pattern.charAt(0) === "#") {
|
|
return false;
|
|
}
|
|
return new Minimatch(pattern, options).match(p);
|
|
};
|
|
exports.minimatch = minimatch;
|
|
var starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
|
|
var starDotExtTest = (ext2) => (f) => !f.startsWith(".") && f.endsWith(ext2);
|
|
var starDotExtTestDot = (ext2) => (f) => f.endsWith(ext2);
|
|
var starDotExtTestNocase = (ext2) => {
|
|
ext2 = ext2.toLowerCase();
|
|
return (f) => !f.startsWith(".") && f.toLowerCase().endsWith(ext2);
|
|
};
|
|
var starDotExtTestNocaseDot = (ext2) => {
|
|
ext2 = ext2.toLowerCase();
|
|
return (f) => f.toLowerCase().endsWith(ext2);
|
|
};
|
|
var starDotStarRE = /^\*+\.\*+$/;
|
|
var starDotStarTest = (f) => !f.startsWith(".") && f.includes(".");
|
|
var starDotStarTestDot = (f) => f !== "." && f !== ".." && f.includes(".");
|
|
var dotStarRE = /^\.\*+$/;
|
|
var dotStarTest = (f) => f !== "." && f !== ".." && f.startsWith(".");
|
|
var starRE = /^\*+$/;
|
|
var starTest = (f) => f.length !== 0 && !f.startsWith(".");
|
|
var starTestDot = (f) => f.length !== 0 && f !== "." && f !== "..";
|
|
var qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
|
|
var qmarksTestNocase = ([$0, ext2 = ""]) => {
|
|
const noext = qmarksTestNoExt([$0]);
|
|
if (!ext2)
|
|
return noext;
|
|
ext2 = ext2.toLowerCase();
|
|
return (f) => noext(f) && f.toLowerCase().endsWith(ext2);
|
|
};
|
|
var qmarksTestNocaseDot = ([$0, ext2 = ""]) => {
|
|
const noext = qmarksTestNoExtDot([$0]);
|
|
if (!ext2)
|
|
return noext;
|
|
ext2 = ext2.toLowerCase();
|
|
return (f) => noext(f) && f.toLowerCase().endsWith(ext2);
|
|
};
|
|
var qmarksTestDot = ([$0, ext2 = ""]) => {
|
|
const noext = qmarksTestNoExtDot([$0]);
|
|
return !ext2 ? noext : (f) => noext(f) && f.endsWith(ext2);
|
|
};
|
|
var qmarksTest = ([$0, ext2 = ""]) => {
|
|
const noext = qmarksTestNoExt([$0]);
|
|
return !ext2 ? noext : (f) => noext(f) && f.endsWith(ext2);
|
|
};
|
|
var qmarksTestNoExt = ([$0]) => {
|
|
const len = $0.length;
|
|
return (f) => f.length === len && !f.startsWith(".");
|
|
};
|
|
var qmarksTestNoExtDot = ([$0]) => {
|
|
const len = $0.length;
|
|
return (f) => f.length === len && f !== "." && f !== "..";
|
|
};
|
|
var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
|
|
var path = {
|
|
win32: { sep: "\\" },
|
|
posix: { sep: "/" }
|
|
};
|
|
exports.sep = defaultPlatform === "win32" ? path.win32.sep : path.posix.sep;
|
|
exports.minimatch.sep = exports.sep;
|
|
exports.GLOBSTAR = Symbol("globstar **");
|
|
exports.minimatch.GLOBSTAR = exports.GLOBSTAR;
|
|
var qmark = "[^/]";
|
|
var star = qmark + "*?";
|
|
var twoStarDot = "(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?";
|
|
var twoStarNoDot = "(?:(?!(?:\\/|^)\\.).)*?";
|
|
var filter = (pattern, options = {}) => (p) => (0, exports.minimatch)(p, pattern, options);
|
|
exports.filter = filter;
|
|
exports.minimatch.filter = exports.filter;
|
|
var ext = (a, b = {}) => Object.assign({}, a, b);
|
|
var defaults = (def) => {
|
|
if (!def || typeof def !== "object" || !Object.keys(def).length) {
|
|
return exports.minimatch;
|
|
}
|
|
const orig = exports.minimatch;
|
|
const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
|
|
return Object.assign(m, {
|
|
Minimatch: class Minimatch extends orig.Minimatch {
|
|
constructor(pattern, options = {}) {
|
|
super(pattern, ext(def, options));
|
|
}
|
|
static defaults(options) {
|
|
return orig.defaults(ext(def, options)).Minimatch;
|
|
}
|
|
},
|
|
AST: class AST extends orig.AST {
|
|
/* c8 ignore start */
|
|
constructor(type, parent, options = {}) {
|
|
super(type, parent, ext(def, options));
|
|
}
|
|
/* c8 ignore stop */
|
|
static fromGlob(pattern, options = {}) {
|
|
return orig.AST.fromGlob(pattern, ext(def, options));
|
|
}
|
|
},
|
|
unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
|
|
escape: (s, options = {}) => orig.escape(s, ext(def, options)),
|
|
filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
|
|
defaults: (options) => orig.defaults(ext(def, options)),
|
|
makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
|
|
braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
|
|
match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
|
|
sep: orig.sep,
|
|
GLOBSTAR: exports.GLOBSTAR
|
|
});
|
|
};
|
|
exports.defaults = defaults;
|
|
exports.minimatch.defaults = exports.defaults;
|
|
var braceExpand = (pattern, options = {}) => {
|
|
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
|
|
return [pattern];
|
|
}
|
|
return (0, brace_expansion_1.default)(pattern);
|
|
};
|
|
exports.braceExpand = braceExpand;
|
|
exports.minimatch.braceExpand = exports.braceExpand;
|
|
var makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
|
|
exports.makeRe = makeRe;
|
|
exports.minimatch.makeRe = exports.makeRe;
|
|
var match = (list, pattern, options = {}) => {
|
|
const mm = new Minimatch(pattern, options);
|
|
list = list.filter((f) => mm.match(f));
|
|
if (mm.options.nonull && !list.length) {
|
|
list.push(pattern);
|
|
}
|
|
return list;
|
|
};
|
|
exports.match = match;
|
|
exports.minimatch.match = exports.match;
|
|
var globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
|
|
var regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
|
var Minimatch = class {
|
|
options;
|
|
set;
|
|
pattern;
|
|
windowsPathsNoEscape;
|
|
nonegate;
|
|
negate;
|
|
comment;
|
|
empty;
|
|
preserveMultipleSlashes;
|
|
partial;
|
|
globSet;
|
|
globParts;
|
|
nocase;
|
|
isWindows;
|
|
platform;
|
|
windowsNoMagicRoot;
|
|
maxGlobstarRecursion;
|
|
regexp;
|
|
constructor(pattern, options = {}) {
|
|
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
options = options || {};
|
|
this.options = options;
|
|
this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200;
|
|
this.pattern = pattern;
|
|
this.platform = options.platform || defaultPlatform;
|
|
this.isWindows = this.platform === "win32";
|
|
this.windowsPathsNoEscape = !!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
|
|
if (this.windowsPathsNoEscape) {
|
|
this.pattern = this.pattern.replace(/\\/g, "/");
|
|
}
|
|
this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
|
|
this.regexp = null;
|
|
this.negate = false;
|
|
this.nonegate = !!options.nonegate;
|
|
this.comment = false;
|
|
this.empty = false;
|
|
this.partial = !!options.partial;
|
|
this.nocase = !!this.options.nocase;
|
|
this.windowsNoMagicRoot = options.windowsNoMagicRoot !== void 0 ? options.windowsNoMagicRoot : !!(this.isWindows && this.nocase);
|
|
this.globSet = [];
|
|
this.globParts = [];
|
|
this.set = [];
|
|
this.make();
|
|
}
|
|
hasMagic() {
|
|
if (this.options.magicalBraces && this.set.length > 1) {
|
|
return true;
|
|
}
|
|
for (const pattern of this.set) {
|
|
for (const part of pattern) {
|
|
if (typeof part !== "string")
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
debug(..._) {
|
|
}
|
|
make() {
|
|
const pattern = this.pattern;
|
|
const options = this.options;
|
|
if (!options.nocomment && pattern.charAt(0) === "#") {
|
|
this.comment = true;
|
|
return;
|
|
}
|
|
if (!pattern) {
|
|
this.empty = true;
|
|
return;
|
|
}
|
|
this.parseNegate();
|
|
this.globSet = [...new Set(this.braceExpand())];
|
|
if (options.debug) {
|
|
this.debug = (...args) => console.error(...args);
|
|
}
|
|
this.debug(this.pattern, this.globSet);
|
|
const rawGlobParts = this.globSet.map((s) => this.slashSplit(s));
|
|
this.globParts = this.preprocess(rawGlobParts);
|
|
this.debug(this.pattern, this.globParts);
|
|
let set = this.globParts.map((s, _, __) => {
|
|
if (this.isWindows && this.windowsNoMagicRoot) {
|
|
const isUNC = s[0] === "" && s[1] === "" && (s[2] === "?" || !globMagic.test(s[2])) && !globMagic.test(s[3]);
|
|
const isDrive = /^[a-z]:/i.test(s[0]);
|
|
if (isUNC) {
|
|
return [...s.slice(0, 4), ...s.slice(4).map((ss) => this.parse(ss))];
|
|
} else if (isDrive) {
|
|
return [s[0], ...s.slice(1).map((ss) => this.parse(ss))];
|
|
}
|
|
}
|
|
return s.map((ss) => this.parse(ss));
|
|
});
|
|
this.debug(this.pattern, set);
|
|
this.set = set.filter((s) => s.indexOf(false) === -1);
|
|
if (this.isWindows) {
|
|
for (let i = 0; i < this.set.length; i++) {
|
|
const p = this.set[i];
|
|
if (p[0] === "" && p[1] === "" && this.globParts[i][2] === "?" && typeof p[3] === "string" && /^[a-z]:$/i.test(p[3])) {
|
|
p[2] = "?";
|
|
}
|
|
}
|
|
}
|
|
this.debug(this.pattern, this.set);
|
|
}
|
|
// various transforms to equivalent pattern sets that are
|
|
// faster to process in a filesystem walk. The goal is to
|
|
// eliminate what we can, and push all ** patterns as far
|
|
// to the right as possible, even if it increases the number
|
|
// of patterns that we have to process.
|
|
preprocess(globParts) {
|
|
if (this.options.noglobstar) {
|
|
for (let i = 0; i < globParts.length; i++) {
|
|
for (let j = 0; j < globParts[i].length; j++) {
|
|
if (globParts[i][j] === "**") {
|
|
globParts[i][j] = "*";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const { optimizationLevel = 1 } = this.options;
|
|
if (optimizationLevel >= 2) {
|
|
globParts = this.firstPhasePreProcess(globParts);
|
|
globParts = this.secondPhasePreProcess(globParts);
|
|
} else if (optimizationLevel >= 1) {
|
|
globParts = this.levelOneOptimize(globParts);
|
|
} else {
|
|
globParts = this.adjascentGlobstarOptimize(globParts);
|
|
}
|
|
return globParts;
|
|
}
|
|
// just get rid of adjascent ** portions
|
|
adjascentGlobstarOptimize(globParts) {
|
|
return globParts.map((parts) => {
|
|
let gs = -1;
|
|
while (-1 !== (gs = parts.indexOf("**", gs + 1))) {
|
|
let i = gs;
|
|
while (parts[i + 1] === "**") {
|
|
i++;
|
|
}
|
|
if (i !== gs) {
|
|
parts.splice(gs, i - gs);
|
|
}
|
|
}
|
|
return parts;
|
|
});
|
|
}
|
|
// get rid of adjascent ** and resolve .. portions
|
|
levelOneOptimize(globParts) {
|
|
return globParts.map((parts) => {
|
|
parts = parts.reduce((set, part) => {
|
|
const prev = set[set.length - 1];
|
|
if (part === "**" && prev === "**") {
|
|
return set;
|
|
}
|
|
if (part === "..") {
|
|
if (prev && prev !== ".." && prev !== "." && prev !== "**") {
|
|
set.pop();
|
|
return set;
|
|
}
|
|
}
|
|
set.push(part);
|
|
return set;
|
|
}, []);
|
|
return parts.length === 0 ? [""] : parts;
|
|
});
|
|
}
|
|
levelTwoFileOptimize(parts) {
|
|
if (!Array.isArray(parts)) {
|
|
parts = this.slashSplit(parts);
|
|
}
|
|
let didSomething = false;
|
|
do {
|
|
didSomething = false;
|
|
if (!this.preserveMultipleSlashes) {
|
|
for (let i = 1; i < parts.length - 1; i++) {
|
|
const p = parts[i];
|
|
if (i === 1 && p === "" && parts[0] === "")
|
|
continue;
|
|
if (p === "." || p === "") {
|
|
didSomething = true;
|
|
parts.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) {
|
|
didSomething = true;
|
|
parts.pop();
|
|
}
|
|
}
|
|
let dd = 0;
|
|
while (-1 !== (dd = parts.indexOf("..", dd + 1))) {
|
|
const p = parts[dd - 1];
|
|
if (p && p !== "." && p !== ".." && p !== "**") {
|
|
didSomething = true;
|
|
parts.splice(dd - 1, 2);
|
|
dd -= 2;
|
|
}
|
|
}
|
|
} while (didSomething);
|
|
return parts.length === 0 ? [""] : parts;
|
|
}
|
|
// First phase: single-pattern processing
|
|
// <pre> is 1 or more portions
|
|
// <rest> is 1 or more portions
|
|
// <p> is any portion other than ., .., '', or **
|
|
// <e> is . or ''
|
|
//
|
|
// **/.. is *brutal* for filesystem walking performance, because
|
|
// it effectively resets the recursive walk each time it occurs,
|
|
// and ** cannot be reduced out by a .. pattern part like a regexp
|
|
// or most strings (other than .., ., and '') can be.
|
|
//
|
|
// <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
|
|
// <pre>/<e>/<rest> -> <pre>/<rest>
|
|
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
|
// **/**/<rest> -> **/<rest>
|
|
//
|
|
// **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
|
|
// this WOULD be allowed if ** did follow symlinks, or * didn't
|
|
firstPhasePreProcess(globParts) {
|
|
let didSomething = false;
|
|
do {
|
|
didSomething = false;
|
|
for (let parts of globParts) {
|
|
let gs = -1;
|
|
while (-1 !== (gs = parts.indexOf("**", gs + 1))) {
|
|
let gss = gs;
|
|
while (parts[gss + 1] === "**") {
|
|
gss++;
|
|
}
|
|
if (gss > gs) {
|
|
parts.splice(gs + 1, gss - gs);
|
|
}
|
|
let next = parts[gs + 1];
|
|
const p = parts[gs + 2];
|
|
const p2 = parts[gs + 3];
|
|
if (next !== "..")
|
|
continue;
|
|
if (!p || p === "." || p === ".." || !p2 || p2 === "." || p2 === "..") {
|
|
continue;
|
|
}
|
|
didSomething = true;
|
|
parts.splice(gs, 1);
|
|
const other = parts.slice(0);
|
|
other[gs] = "**";
|
|
globParts.push(other);
|
|
gs--;
|
|
}
|
|
if (!this.preserveMultipleSlashes) {
|
|
for (let i = 1; i < parts.length - 1; i++) {
|
|
const p = parts[i];
|
|
if (i === 1 && p === "" && parts[0] === "")
|
|
continue;
|
|
if (p === "." || p === "") {
|
|
didSomething = true;
|
|
parts.splice(i, 1);
|
|
i--;
|
|
}
|
|
}
|
|
if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) {
|
|
didSomething = true;
|
|
parts.pop();
|
|
}
|
|
}
|
|
let dd = 0;
|
|
while (-1 !== (dd = parts.indexOf("..", dd + 1))) {
|
|
const p = parts[dd - 1];
|
|
if (p && p !== "." && p !== ".." && p !== "**") {
|
|
didSomething = true;
|
|
const needDot = dd === 1 && parts[dd + 1] === "**";
|
|
const splin = needDot ? ["."] : [];
|
|
parts.splice(dd - 1, 2, ...splin);
|
|
if (parts.length === 0)
|
|
parts.push("");
|
|
dd -= 2;
|
|
}
|
|
}
|
|
}
|
|
} while (didSomething);
|
|
return globParts;
|
|
}
|
|
// second phase: multi-pattern dedupes
|
|
// {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
|
|
// {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
|
|
// {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
|
|
//
|
|
// {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
|
|
// ^-- not valid because ** doens't follow symlinks
|
|
secondPhasePreProcess(globParts) {
|
|
for (let i = 0; i < globParts.length - 1; i++) {
|
|
for (let j = i + 1; j < globParts.length; j++) {
|
|
const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
|
|
if (matched) {
|
|
globParts[i] = [];
|
|
globParts[j] = matched;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return globParts.filter((gs) => gs.length);
|
|
}
|
|
partsMatch(a, b, emptyGSMatch = false) {
|
|
let ai = 0;
|
|
let bi = 0;
|
|
let result = [];
|
|
let which = "";
|
|
while (ai < a.length && bi < b.length) {
|
|
if (a[ai] === b[bi]) {
|
|
result.push(which === "b" ? b[bi] : a[ai]);
|
|
ai++;
|
|
bi++;
|
|
} else if (emptyGSMatch && a[ai] === "**" && b[bi] === a[ai + 1]) {
|
|
result.push(a[ai]);
|
|
ai++;
|
|
} else if (emptyGSMatch && b[bi] === "**" && a[ai] === b[bi + 1]) {
|
|
result.push(b[bi]);
|
|
bi++;
|
|
} else if (a[ai] === "*" && b[bi] && (this.options.dot || !b[bi].startsWith(".")) && b[bi] !== "**") {
|
|
if (which === "b")
|
|
return false;
|
|
which = "a";
|
|
result.push(a[ai]);
|
|
ai++;
|
|
bi++;
|
|
} else if (b[bi] === "*" && a[ai] && (this.options.dot || !a[ai].startsWith(".")) && a[ai] !== "**") {
|
|
if (which === "a")
|
|
return false;
|
|
which = "b";
|
|
result.push(b[bi]);
|
|
ai++;
|
|
bi++;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return a.length === b.length && result;
|
|
}
|
|
parseNegate() {
|
|
if (this.nonegate)
|
|
return;
|
|
const pattern = this.pattern;
|
|
let negate = false;
|
|
let negateOffset = 0;
|
|
for (let i = 0; i < pattern.length && pattern.charAt(i) === "!"; i++) {
|
|
negate = !negate;
|
|
negateOffset++;
|
|
}
|
|
if (negateOffset)
|
|
this.pattern = pattern.slice(negateOffset);
|
|
this.negate = negate;
|
|
}
|
|
// set partial to true to test if, for example,
|
|
// "/a/b" matches the start of "/*/b/*/d"
|
|
// Partial means, if you run out of file before you run
|
|
// out of pattern, then that's fine, as long as all
|
|
// the parts match.
|
|
matchOne(file, pattern, partial = false) {
|
|
let fileStartIndex = 0;
|
|
let patternStartIndex = 0;
|
|
if (this.isWindows) {
|
|
const fileDrive = typeof file[0] === "string" && /^[a-z]:$/i.test(file[0]);
|
|
const fileUNC = !fileDrive && file[0] === "" && file[1] === "" && file[2] === "?" && /^[a-z]:$/i.test(file[3]);
|
|
const patternDrive = typeof pattern[0] === "string" && /^[a-z]:$/i.test(pattern[0]);
|
|
const patternUNC = !patternDrive && pattern[0] === "" && pattern[1] === "" && pattern[2] === "?" && typeof pattern[3] === "string" && /^[a-z]:$/i.test(pattern[3]);
|
|
const fdi = fileUNC ? 3 : fileDrive ? 0 : void 0;
|
|
const pdi = patternUNC ? 3 : patternDrive ? 0 : void 0;
|
|
if (typeof fdi === "number" && typeof pdi === "number") {
|
|
const [fd, pd] = [
|
|
file[fdi],
|
|
pattern[pdi]
|
|
];
|
|
if (fd.toLowerCase() === pd.toLowerCase()) {
|
|
pattern[pdi] = fd;
|
|
patternStartIndex = pdi;
|
|
fileStartIndex = fdi;
|
|
}
|
|
}
|
|
}
|
|
const { optimizationLevel = 1 } = this.options;
|
|
if (optimizationLevel >= 2) {
|
|
file = this.levelTwoFileOptimize(file);
|
|
}
|
|
if (pattern.includes(exports.GLOBSTAR)) {
|
|
return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex);
|
|
}
|
|
return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex);
|
|
}
|
|
#matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
|
|
const firstgs = pattern.indexOf(exports.GLOBSTAR, patternIndex);
|
|
const lastgs = pattern.lastIndexOf(exports.GLOBSTAR);
|
|
const [head, body, tail] = partial ? [
|
|
pattern.slice(patternIndex, firstgs),
|
|
pattern.slice(firstgs + 1),
|
|
[]
|
|
] : [
|
|
pattern.slice(patternIndex, firstgs),
|
|
pattern.slice(firstgs + 1, lastgs),
|
|
pattern.slice(lastgs + 1)
|
|
];
|
|
if (head.length) {
|
|
const fileHead = file.slice(fileIndex, fileIndex + head.length);
|
|
if (!this.#matchOne(fileHead, head, partial, 0, 0))
|
|
return false;
|
|
fileIndex += head.length;
|
|
}
|
|
let fileTailMatch = 0;
|
|
if (tail.length) {
|
|
if (tail.length + fileIndex > file.length)
|
|
return false;
|
|
let tailStart = file.length - tail.length;
|
|
if (this.#matchOne(file, tail, partial, tailStart, 0)) {
|
|
fileTailMatch = tail.length;
|
|
} else {
|
|
if (file[file.length - 1] !== "" || fileIndex + tail.length === file.length) {
|
|
return false;
|
|
}
|
|
tailStart--;
|
|
if (!this.#matchOne(file, tail, partial, tailStart, 0))
|
|
return false;
|
|
fileTailMatch = tail.length + 1;
|
|
}
|
|
}
|
|
if (!body.length) {
|
|
let sawSome = !!fileTailMatch;
|
|
for (let i2 = fileIndex; i2 < file.length - fileTailMatch; i2++) {
|
|
const f = String(file[i2]);
|
|
sawSome = true;
|
|
if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) {
|
|
return false;
|
|
}
|
|
}
|
|
return partial || sawSome;
|
|
}
|
|
const bodySegments = [[[], 0]];
|
|
let currentBody = bodySegments[0];
|
|
let nonGsParts = 0;
|
|
const nonGsPartsSums = [0];
|
|
for (const b of body) {
|
|
if (b === exports.GLOBSTAR) {
|
|
nonGsPartsSums.push(nonGsParts);
|
|
currentBody = [[], 0];
|
|
bodySegments.push(currentBody);
|
|
} else {
|
|
currentBody[0].push(b);
|
|
nonGsParts++;
|
|
}
|
|
}
|
|
let i = bodySegments.length - 1;
|
|
const fileLength = file.length - fileTailMatch;
|
|
for (const b of bodySegments) {
|
|
b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length);
|
|
}
|
|
return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
|
|
}
|
|
#matchGlobStarBodySections(file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
|
|
const bs = bodySegments[bodyIndex];
|
|
if (!bs) {
|
|
for (let i = fileIndex; i < file.length; i++) {
|
|
sawTail = true;
|
|
const f = file[i];
|
|
if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) {
|
|
return false;
|
|
}
|
|
}
|
|
return sawTail;
|
|
}
|
|
const [body, after] = bs;
|
|
while (fileIndex <= after) {
|
|
const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
|
|
if (m && globStarDepth < this.maxGlobstarRecursion) {
|
|
const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
|
|
if (sub !== false)
|
|
return sub;
|
|
}
|
|
const f = file[fileIndex];
|
|
if (f === "." || f === ".." || !this.options.dot && f.startsWith(".")) {
|
|
return false;
|
|
}
|
|
fileIndex++;
|
|
}
|
|
return partial || null;
|
|
}
|
|
#matchOne(file, pattern, partial, fileIndex, patternIndex) {
|
|
let fi;
|
|
let pi;
|
|
let pl;
|
|
let fl;
|
|
for (fi = fileIndex, pi = patternIndex, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
|
|
this.debug("matchOne loop");
|
|
let p = pattern[pi];
|
|
let f = file[fi];
|
|
this.debug(pattern, p, f);
|
|
if (p === false || p === exports.GLOBSTAR)
|
|
return false;
|
|
let hit;
|
|
if (typeof p === "string") {
|
|
hit = f === p;
|
|
this.debug("string match", p, f, hit);
|
|
} else {
|
|
hit = p.test(f);
|
|
this.debug("pattern match", p, f, hit);
|
|
}
|
|
if (!hit)
|
|
return false;
|
|
}
|
|
if (fi === fl && pi === pl) {
|
|
return true;
|
|
} else if (fi === fl) {
|
|
return partial;
|
|
} else if (pi === pl) {
|
|
return fi === fl - 1 && file[fi] === "";
|
|
} else {
|
|
throw new Error("wtf?");
|
|
}
|
|
}
|
|
braceExpand() {
|
|
return (0, exports.braceExpand)(this.pattern, this.options);
|
|
}
|
|
parse(pattern) {
|
|
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
const options = this.options;
|
|
if (pattern === "**")
|
|
return exports.GLOBSTAR;
|
|
if (pattern === "")
|
|
return "";
|
|
let m;
|
|
let fastTest = null;
|
|
if (m = pattern.match(starRE)) {
|
|
fastTest = options.dot ? starTestDot : starTest;
|
|
} else if (m = pattern.match(starDotExtRE)) {
|
|
fastTest = (options.nocase ? options.dot ? starDotExtTestNocaseDot : starDotExtTestNocase : options.dot ? starDotExtTestDot : starDotExtTest)(m[1]);
|
|
} else if (m = pattern.match(qmarksRE)) {
|
|
fastTest = (options.nocase ? options.dot ? qmarksTestNocaseDot : qmarksTestNocase : options.dot ? qmarksTestDot : qmarksTest)(m);
|
|
} else if (m = pattern.match(starDotStarRE)) {
|
|
fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
|
|
} else if (m = pattern.match(dotStarRE)) {
|
|
fastTest = dotStarTest;
|
|
}
|
|
const re = ast_js_1.AST.fromGlob(pattern, this.options).toMMPattern();
|
|
if (fastTest && typeof re === "object") {
|
|
Reflect.defineProperty(re, "test", { value: fastTest });
|
|
}
|
|
return re;
|
|
}
|
|
makeRe() {
|
|
if (this.regexp || this.regexp === false)
|
|
return this.regexp;
|
|
const set = this.set;
|
|
if (!set.length) {
|
|
this.regexp = false;
|
|
return this.regexp;
|
|
}
|
|
const options = this.options;
|
|
const twoStar = options.noglobstar ? star : options.dot ? twoStarDot : twoStarNoDot;
|
|
const flags = new Set(options.nocase ? ["i"] : []);
|
|
let re = set.map((pattern) => {
|
|
const pp = pattern.map((p) => {
|
|
if (p instanceof RegExp) {
|
|
for (const f of p.flags.split(""))
|
|
flags.add(f);
|
|
}
|
|
return typeof p === "string" ? regExpEscape(p) : p === exports.GLOBSTAR ? exports.GLOBSTAR : p._src;
|
|
});
|
|
pp.forEach((p, i) => {
|
|
const next = pp[i + 1];
|
|
const prev = pp[i - 1];
|
|
if (p !== exports.GLOBSTAR || prev === exports.GLOBSTAR) {
|
|
return;
|
|
}
|
|
if (prev === void 0) {
|
|
if (next !== void 0 && next !== exports.GLOBSTAR) {
|
|
pp[i + 1] = "(?:\\/|" + twoStar + "\\/)?" + next;
|
|
} else {
|
|
pp[i] = twoStar;
|
|
}
|
|
} else if (next === void 0) {
|
|
pp[i - 1] = prev + "(?:\\/|" + twoStar + ")?";
|
|
} else if (next !== exports.GLOBSTAR) {
|
|
pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + "\\/)" + next;
|
|
pp[i + 1] = exports.GLOBSTAR;
|
|
}
|
|
});
|
|
return pp.filter((p) => p !== exports.GLOBSTAR).join("/");
|
|
}).join("|");
|
|
const [open, close] = set.length > 1 ? ["(?:", ")"] : ["", ""];
|
|
re = "^" + open + re + close + "$";
|
|
if (this.negate)
|
|
re = "^(?!" + re + ").+$";
|
|
try {
|
|
this.regexp = new RegExp(re, [...flags].join(""));
|
|
} catch (ex) {
|
|
this.regexp = false;
|
|
}
|
|
return this.regexp;
|
|
}
|
|
slashSplit(p) {
|
|
if (this.preserveMultipleSlashes) {
|
|
return p.split("/");
|
|
} else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
|
|
return ["", ...p.split(/\/+/)];
|
|
} else {
|
|
return p.split(/\/+/);
|
|
}
|
|
}
|
|
match(f, partial = this.partial) {
|
|
this.debug("match", f, this.pattern);
|
|
if (this.comment) {
|
|
return false;
|
|
}
|
|
if (this.empty) {
|
|
return f === "";
|
|
}
|
|
if (f === "/" && partial) {
|
|
return true;
|
|
}
|
|
const options = this.options;
|
|
if (this.isWindows) {
|
|
f = f.split("\\").join("/");
|
|
}
|
|
const ff = this.slashSplit(f);
|
|
this.debug(this.pattern, "split", ff);
|
|
const set = this.set;
|
|
this.debug(this.pattern, "set", set);
|
|
let filename = ff[ff.length - 1];
|
|
if (!filename) {
|
|
for (let i = ff.length - 2; !filename && i >= 0; i--) {
|
|
filename = ff[i];
|
|
}
|
|
}
|
|
for (let i = 0; i < set.length; i++) {
|
|
const pattern = set[i];
|
|
let file = ff;
|
|
if (options.matchBase && pattern.length === 1) {
|
|
file = [filename];
|
|
}
|
|
const hit = this.matchOne(file, pattern, partial);
|
|
if (hit) {
|
|
if (options.flipNegate) {
|
|
return true;
|
|
}
|
|
return !this.negate;
|
|
}
|
|
}
|
|
if (options.flipNegate) {
|
|
return false;
|
|
}
|
|
return this.negate;
|
|
}
|
|
static defaults(def) {
|
|
return exports.minimatch.defaults(def).Minimatch;
|
|
}
|
|
};
|
|
exports.Minimatch = Minimatch;
|
|
var ast_js_2 = require_ast();
|
|
Object.defineProperty(exports, "AST", { enumerable: true, get: function() {
|
|
return ast_js_2.AST;
|
|
} });
|
|
var escape_js_2 = require_escape();
|
|
Object.defineProperty(exports, "escape", { enumerable: true, get: function() {
|
|
return escape_js_2.escape;
|
|
} });
|
|
var unescape_js_2 = require_unescape();
|
|
Object.defineProperty(exports, "unescape", { enumerable: true, get: function() {
|
|
return unescape_js_2.unescape;
|
|
} });
|
|
exports.minimatch.AST = ast_js_1.AST;
|
|
exports.minimatch.Minimatch = Minimatch;
|
|
exports.minimatch.escape = escape_js_1.escape;
|
|
exports.minimatch.unescape = unescape_js_1.unescape;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/lru-cache/dist/commonjs/index.js
|
|
var require_commonjs2 = __commonJS({
|
|
"../../node_modules/lru-cache/dist/commonjs/index.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.LRUCache = void 0;
|
|
var perf = typeof performance === "object" && performance && typeof performance.now === "function" ? performance : Date;
|
|
var warned = /* @__PURE__ */ new Set();
|
|
var PROCESS = typeof process === "object" && !!process ? process : {};
|
|
var emitWarning = (msg, type, code, fn) => {
|
|
typeof PROCESS.emitWarning === "function" ? PROCESS.emitWarning(msg, type, code, fn) : console.error(`[${code}] ${type}: ${msg}`);
|
|
};
|
|
var AC = globalThis.AbortController;
|
|
var AS = globalThis.AbortSignal;
|
|
if (typeof AC === "undefined") {
|
|
AS = class AbortSignal {
|
|
onabort;
|
|
_onabort = [];
|
|
reason;
|
|
aborted = false;
|
|
addEventListener(_, fn) {
|
|
this._onabort.push(fn);
|
|
}
|
|
};
|
|
AC = class AbortController {
|
|
constructor() {
|
|
warnACPolyfill();
|
|
}
|
|
signal = new AS();
|
|
abort(reason) {
|
|
if (this.signal.aborted)
|
|
return;
|
|
this.signal.reason = reason;
|
|
this.signal.aborted = true;
|
|
for (const fn of this.signal._onabort) {
|
|
fn(reason);
|
|
}
|
|
this.signal.onabort?.(reason);
|
|
}
|
|
};
|
|
let printACPolyfillWarning = PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== "1";
|
|
const warnACPolyfill = () => {
|
|
if (!printACPolyfillWarning)
|
|
return;
|
|
printACPolyfillWarning = false;
|
|
emitWarning("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.", "NO_ABORT_CONTROLLER", "ENOTSUP", warnACPolyfill);
|
|
};
|
|
}
|
|
var shouldWarn = (code) => !warned.has(code);
|
|
var TYPE = Symbol("type");
|
|
var isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
|
|
var getUintArray = (max) => !isPosInt(max) ? null : max <= Math.pow(2, 8) ? Uint8Array : max <= Math.pow(2, 16) ? Uint16Array : max <= Math.pow(2, 32) ? Uint32Array : max <= Number.MAX_SAFE_INTEGER ? ZeroArray : null;
|
|
var ZeroArray = class extends Array {
|
|
constructor(size) {
|
|
super(size);
|
|
this.fill(0);
|
|
}
|
|
};
|
|
var Stack = class _Stack {
|
|
heap;
|
|
length;
|
|
// private constructor
|
|
static #constructing = false;
|
|
static create(max) {
|
|
const HeapCls = getUintArray(max);
|
|
if (!HeapCls)
|
|
return [];
|
|
_Stack.#constructing = true;
|
|
const s = new _Stack(max, HeapCls);
|
|
_Stack.#constructing = false;
|
|
return s;
|
|
}
|
|
constructor(max, HeapCls) {
|
|
if (!_Stack.#constructing) {
|
|
throw new TypeError("instantiate Stack using Stack.create(n)");
|
|
}
|
|
this.heap = new HeapCls(max);
|
|
this.length = 0;
|
|
}
|
|
push(n) {
|
|
this.heap[this.length++] = n;
|
|
}
|
|
pop() {
|
|
return this.heap[--this.length];
|
|
}
|
|
};
|
|
var LRUCache = class _LRUCache {
|
|
// options that cannot be changed without disaster
|
|
#max;
|
|
#maxSize;
|
|
#dispose;
|
|
#disposeAfter;
|
|
#fetchMethod;
|
|
#memoMethod;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.ttl}
|
|
*/
|
|
ttl;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.ttlResolution}
|
|
*/
|
|
ttlResolution;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.ttlAutopurge}
|
|
*/
|
|
ttlAutopurge;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.updateAgeOnGet}
|
|
*/
|
|
updateAgeOnGet;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.updateAgeOnHas}
|
|
*/
|
|
updateAgeOnHas;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.allowStale}
|
|
*/
|
|
allowStale;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.noDisposeOnSet}
|
|
*/
|
|
noDisposeOnSet;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.noUpdateTTL}
|
|
*/
|
|
noUpdateTTL;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.maxEntrySize}
|
|
*/
|
|
maxEntrySize;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.sizeCalculation}
|
|
*/
|
|
sizeCalculation;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}
|
|
*/
|
|
noDeleteOnFetchRejection;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.noDeleteOnStaleGet}
|
|
*/
|
|
noDeleteOnStaleGet;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}
|
|
*/
|
|
allowStaleOnFetchAbort;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}
|
|
*/
|
|
allowStaleOnFetchRejection;
|
|
/**
|
|
* {@link LRUCache.OptionsBase.ignoreFetchAbort}
|
|
*/
|
|
ignoreFetchAbort;
|
|
// computed properties
|
|
#size;
|
|
#calculatedSize;
|
|
#keyMap;
|
|
#keyList;
|
|
#valList;
|
|
#next;
|
|
#prev;
|
|
#head;
|
|
#tail;
|
|
#free;
|
|
#disposed;
|
|
#sizes;
|
|
#starts;
|
|
#ttls;
|
|
#hasDispose;
|
|
#hasFetchMethod;
|
|
#hasDisposeAfter;
|
|
/**
|
|
* Do not call this method unless you need to inspect the
|
|
* inner workings of the cache. If anything returned by this
|
|
* object is modified in any way, strange breakage may occur.
|
|
*
|
|
* These fields are private for a reason!
|
|
*
|
|
* @internal
|
|
*/
|
|
static unsafeExposeInternals(c) {
|
|
return {
|
|
// properties
|
|
starts: c.#starts,
|
|
ttls: c.#ttls,
|
|
sizes: c.#sizes,
|
|
keyMap: c.#keyMap,
|
|
keyList: c.#keyList,
|
|
valList: c.#valList,
|
|
next: c.#next,
|
|
prev: c.#prev,
|
|
get head() {
|
|
return c.#head;
|
|
},
|
|
get tail() {
|
|
return c.#tail;
|
|
},
|
|
free: c.#free,
|
|
// methods
|
|
isBackgroundFetch: (p) => c.#isBackgroundFetch(p),
|
|
backgroundFetch: (k, index, options, context) => c.#backgroundFetch(k, index, options, context),
|
|
moveToTail: (index) => c.#moveToTail(index),
|
|
indexes: (options) => c.#indexes(options),
|
|
rindexes: (options) => c.#rindexes(options),
|
|
isStale: (index) => c.#isStale(index)
|
|
};
|
|
}
|
|
// Protected read-only members
|
|
/**
|
|
* {@link LRUCache.OptionsBase.max} (read-only)
|
|
*/
|
|
get max() {
|
|
return this.#max;
|
|
}
|
|
/**
|
|
* {@link LRUCache.OptionsBase.maxSize} (read-only)
|
|
*/
|
|
get maxSize() {
|
|
return this.#maxSize;
|
|
}
|
|
/**
|
|
* The total computed size of items in the cache (read-only)
|
|
*/
|
|
get calculatedSize() {
|
|
return this.#calculatedSize;
|
|
}
|
|
/**
|
|
* The number of items stored in the cache (read-only)
|
|
*/
|
|
get size() {
|
|
return this.#size;
|
|
}
|
|
/**
|
|
* {@link LRUCache.OptionsBase.fetchMethod} (read-only)
|
|
*/
|
|
get fetchMethod() {
|
|
return this.#fetchMethod;
|
|
}
|
|
get memoMethod() {
|
|
return this.#memoMethod;
|
|
}
|
|
/**
|
|
* {@link LRUCache.OptionsBase.dispose} (read-only)
|
|
*/
|
|
get dispose() {
|
|
return this.#dispose;
|
|
}
|
|
/**
|
|
* {@link LRUCache.OptionsBase.disposeAfter} (read-only)
|
|
*/
|
|
get disposeAfter() {
|
|
return this.#disposeAfter;
|
|
}
|
|
constructor(options) {
|
|
const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, memoMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort } = options;
|
|
if (max !== 0 && !isPosInt(max)) {
|
|
throw new TypeError("max option must be a nonnegative integer");
|
|
}
|
|
const UintArray = max ? getUintArray(max) : Array;
|
|
if (!UintArray) {
|
|
throw new Error("invalid max value: " + max);
|
|
}
|
|
this.#max = max;
|
|
this.#maxSize = maxSize;
|
|
this.maxEntrySize = maxEntrySize || this.#maxSize;
|
|
this.sizeCalculation = sizeCalculation;
|
|
if (this.sizeCalculation) {
|
|
if (!this.#maxSize && !this.maxEntrySize) {
|
|
throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");
|
|
}
|
|
if (typeof this.sizeCalculation !== "function") {
|
|
throw new TypeError("sizeCalculation set to non-function");
|
|
}
|
|
}
|
|
if (memoMethod !== void 0 && typeof memoMethod !== "function") {
|
|
throw new TypeError("memoMethod must be a function if defined");
|
|
}
|
|
this.#memoMethod = memoMethod;
|
|
if (fetchMethod !== void 0 && typeof fetchMethod !== "function") {
|
|
throw new TypeError("fetchMethod must be a function if specified");
|
|
}
|
|
this.#fetchMethod = fetchMethod;
|
|
this.#hasFetchMethod = !!fetchMethod;
|
|
this.#keyMap = /* @__PURE__ */ new Map();
|
|
this.#keyList = new Array(max).fill(void 0);
|
|
this.#valList = new Array(max).fill(void 0);
|
|
this.#next = new UintArray(max);
|
|
this.#prev = new UintArray(max);
|
|
this.#head = 0;
|
|
this.#tail = 0;
|
|
this.#free = Stack.create(max);
|
|
this.#size = 0;
|
|
this.#calculatedSize = 0;
|
|
if (typeof dispose === "function") {
|
|
this.#dispose = dispose;
|
|
}
|
|
if (typeof disposeAfter === "function") {
|
|
this.#disposeAfter = disposeAfter;
|
|
this.#disposed = [];
|
|
} else {
|
|
this.#disposeAfter = void 0;
|
|
this.#disposed = void 0;
|
|
}
|
|
this.#hasDispose = !!this.#dispose;
|
|
this.#hasDisposeAfter = !!this.#disposeAfter;
|
|
this.noDisposeOnSet = !!noDisposeOnSet;
|
|
this.noUpdateTTL = !!noUpdateTTL;
|
|
this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection;
|
|
this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection;
|
|
this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort;
|
|
this.ignoreFetchAbort = !!ignoreFetchAbort;
|
|
if (this.maxEntrySize !== 0) {
|
|
if (this.#maxSize !== 0) {
|
|
if (!isPosInt(this.#maxSize)) {
|
|
throw new TypeError("maxSize must be a positive integer if specified");
|
|
}
|
|
}
|
|
if (!isPosInt(this.maxEntrySize)) {
|
|
throw new TypeError("maxEntrySize must be a positive integer if specified");
|
|
}
|
|
this.#initializeSizeTracking();
|
|
}
|
|
this.allowStale = !!allowStale;
|
|
this.noDeleteOnStaleGet = !!noDeleteOnStaleGet;
|
|
this.updateAgeOnGet = !!updateAgeOnGet;
|
|
this.updateAgeOnHas = !!updateAgeOnHas;
|
|
this.ttlResolution = isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1;
|
|
this.ttlAutopurge = !!ttlAutopurge;
|
|
this.ttl = ttl || 0;
|
|
if (this.ttl) {
|
|
if (!isPosInt(this.ttl)) {
|
|
throw new TypeError("ttl must be a positive integer if specified");
|
|
}
|
|
this.#initializeTTLTracking();
|
|
}
|
|
if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) {
|
|
throw new TypeError("At least one of max, maxSize, or ttl is required");
|
|
}
|
|
if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {
|
|
const code = "LRU_CACHE_UNBOUNDED";
|
|
if (shouldWarn(code)) {
|
|
warned.add(code);
|
|
const msg = "TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.";
|
|
emitWarning(msg, "UnboundedCacheWarning", code, _LRUCache);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Return the number of ms left in the item's TTL. If item is not in cache,
|
|
* returns `0`. Returns `Infinity` if item is in cache without a defined TTL.
|
|
*/
|
|
getRemainingTTL(key) {
|
|
return this.#keyMap.has(key) ? Infinity : 0;
|
|
}
|
|
#initializeTTLTracking() {
|
|
const ttls = new ZeroArray(this.#max);
|
|
const starts = new ZeroArray(this.#max);
|
|
this.#ttls = ttls;
|
|
this.#starts = starts;
|
|
this.#setItemTTL = (index, ttl, start = perf.now()) => {
|
|
starts[index] = ttl !== 0 ? start : 0;
|
|
ttls[index] = ttl;
|
|
if (ttl !== 0 && this.ttlAutopurge) {
|
|
const t = setTimeout(() => {
|
|
if (this.#isStale(index)) {
|
|
this.#delete(this.#keyList[index], "expire");
|
|
}
|
|
}, ttl + 1);
|
|
if (t.unref) {
|
|
t.unref();
|
|
}
|
|
}
|
|
};
|
|
this.#updateItemAge = (index) => {
|
|
starts[index] = ttls[index] !== 0 ? perf.now() : 0;
|
|
};
|
|
this.#statusTTL = (status, index) => {
|
|
if (ttls[index]) {
|
|
const ttl = ttls[index];
|
|
const start = starts[index];
|
|
if (!ttl || !start)
|
|
return;
|
|
status.ttl = ttl;
|
|
status.start = start;
|
|
status.now = cachedNow || getNow();
|
|
const age = status.now - start;
|
|
status.remainingTTL = ttl - age;
|
|
}
|
|
};
|
|
let cachedNow = 0;
|
|
const getNow = () => {
|
|
const n = perf.now();
|
|
if (this.ttlResolution > 0) {
|
|
cachedNow = n;
|
|
const t = setTimeout(() => cachedNow = 0, this.ttlResolution);
|
|
if (t.unref) {
|
|
t.unref();
|
|
}
|
|
}
|
|
return n;
|
|
};
|
|
this.getRemainingTTL = (key) => {
|
|
const index = this.#keyMap.get(key);
|
|
if (index === void 0) {
|
|
return 0;
|
|
}
|
|
const ttl = ttls[index];
|
|
const start = starts[index];
|
|
if (!ttl || !start) {
|
|
return Infinity;
|
|
}
|
|
const age = (cachedNow || getNow()) - start;
|
|
return ttl - age;
|
|
};
|
|
this.#isStale = (index) => {
|
|
const s = starts[index];
|
|
const t = ttls[index];
|
|
return !!t && !!s && (cachedNow || getNow()) - s > t;
|
|
};
|
|
}
|
|
// conditionally set private methods related to TTL
|
|
#updateItemAge = () => {
|
|
};
|
|
#statusTTL = () => {
|
|
};
|
|
#setItemTTL = () => {
|
|
};
|
|
/* c8 ignore stop */
|
|
#isStale = () => false;
|
|
#initializeSizeTracking() {
|
|
const sizes = new ZeroArray(this.#max);
|
|
this.#calculatedSize = 0;
|
|
this.#sizes = sizes;
|
|
this.#removeItemSize = (index) => {
|
|
this.#calculatedSize -= sizes[index];
|
|
sizes[index] = 0;
|
|
};
|
|
this.#requireSize = (k, v, size, sizeCalculation) => {
|
|
if (this.#isBackgroundFetch(v)) {
|
|
return 0;
|
|
}
|
|
if (!isPosInt(size)) {
|
|
if (sizeCalculation) {
|
|
if (typeof sizeCalculation !== "function") {
|
|
throw new TypeError("sizeCalculation must be a function");
|
|
}
|
|
size = sizeCalculation(v, k);
|
|
if (!isPosInt(size)) {
|
|
throw new TypeError("sizeCalculation return invalid (expect positive integer)");
|
|
}
|
|
} else {
|
|
throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");
|
|
}
|
|
}
|
|
return size;
|
|
};
|
|
this.#addItemSize = (index, size, status) => {
|
|
sizes[index] = size;
|
|
if (this.#maxSize) {
|
|
const maxSize = this.#maxSize - sizes[index];
|
|
while (this.#calculatedSize > maxSize) {
|
|
this.#evict(true);
|
|
}
|
|
}
|
|
this.#calculatedSize += sizes[index];
|
|
if (status) {
|
|
status.entrySize = size;
|
|
status.totalCalculatedSize = this.#calculatedSize;
|
|
}
|
|
};
|
|
}
|
|
#removeItemSize = (_i) => {
|
|
};
|
|
#addItemSize = (_i, _s, _st) => {
|
|
};
|
|
#requireSize = (_k, _v, size, sizeCalculation) => {
|
|
if (size || sizeCalculation) {
|
|
throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");
|
|
}
|
|
return 0;
|
|
};
|
|
*#indexes({ allowStale = this.allowStale } = {}) {
|
|
if (this.#size) {
|
|
for (let i = this.#tail; true; ) {
|
|
if (!this.#isValidIndex(i)) {
|
|
break;
|
|
}
|
|
if (allowStale || !this.#isStale(i)) {
|
|
yield i;
|
|
}
|
|
if (i === this.#head) {
|
|
break;
|
|
} else {
|
|
i = this.#prev[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*#rindexes({ allowStale = this.allowStale } = {}) {
|
|
if (this.#size) {
|
|
for (let i = this.#head; true; ) {
|
|
if (!this.#isValidIndex(i)) {
|
|
break;
|
|
}
|
|
if (allowStale || !this.#isStale(i)) {
|
|
yield i;
|
|
}
|
|
if (i === this.#tail) {
|
|
break;
|
|
} else {
|
|
i = this.#next[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#isValidIndex(index) {
|
|
return index !== void 0 && this.#keyMap.get(this.#keyList[index]) === index;
|
|
}
|
|
/**
|
|
* Return a generator yielding `[key, value]` pairs,
|
|
* in order from most recently used to least recently used.
|
|
*/
|
|
*entries() {
|
|
for (const i of this.#indexes()) {
|
|
if (this.#valList[i] !== void 0 && this.#keyList[i] !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
yield [this.#keyList[i], this.#valList[i]];
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Inverse order version of {@link LRUCache.entries}
|
|
*
|
|
* Return a generator yielding `[key, value]` pairs,
|
|
* in order from least recently used to most recently used.
|
|
*/
|
|
*rentries() {
|
|
for (const i of this.#rindexes()) {
|
|
if (this.#valList[i] !== void 0 && this.#keyList[i] !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
yield [this.#keyList[i], this.#valList[i]];
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Return a generator yielding the keys in the cache,
|
|
* in order from most recently used to least recently used.
|
|
*/
|
|
*keys() {
|
|
for (const i of this.#indexes()) {
|
|
const k = this.#keyList[i];
|
|
if (k !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
yield k;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Inverse order version of {@link LRUCache.keys}
|
|
*
|
|
* Return a generator yielding the keys in the cache,
|
|
* in order from least recently used to most recently used.
|
|
*/
|
|
*rkeys() {
|
|
for (const i of this.#rindexes()) {
|
|
const k = this.#keyList[i];
|
|
if (k !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
yield k;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Return a generator yielding the values in the cache,
|
|
* in order from most recently used to least recently used.
|
|
*/
|
|
*values() {
|
|
for (const i of this.#indexes()) {
|
|
const v = this.#valList[i];
|
|
if (v !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
yield this.#valList[i];
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Inverse order version of {@link LRUCache.values}
|
|
*
|
|
* Return a generator yielding the values in the cache,
|
|
* in order from least recently used to most recently used.
|
|
*/
|
|
*rvalues() {
|
|
for (const i of this.#rindexes()) {
|
|
const v = this.#valList[i];
|
|
if (v !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
|
|
yield this.#valList[i];
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Iterating over the cache itself yields the same results as
|
|
* {@link LRUCache.entries}
|
|
*/
|
|
[Symbol.iterator]() {
|
|
return this.entries();
|
|
}
|
|
/**
|
|
* A String value that is used in the creation of the default string
|
|
* description of an object. Called by the built-in method
|
|
* `Object.prototype.toString`.
|
|
*/
|
|
[Symbol.toStringTag] = "LRUCache";
|
|
/**
|
|
* Find a value for which the supplied fn method returns a truthy value,
|
|
* similar to `Array.find()`. fn is called as `fn(value, key, cache)`.
|
|
*/
|
|
find(fn, getOptions = {}) {
|
|
for (const i of this.#indexes()) {
|
|
const v = this.#valList[i];
|
|
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
if (value === void 0)
|
|
continue;
|
|
if (fn(value, this.#keyList[i], this)) {
|
|
return this.get(this.#keyList[i], getOptions);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Call the supplied function on each item in the cache, in order from most
|
|
* recently used to least recently used.
|
|
*
|
|
* `fn` is called as `fn(value, key, cache)`.
|
|
*
|
|
* If `thisp` is provided, function will be called in the `this`-context of
|
|
* the provided object, or the cache if no `thisp` object is provided.
|
|
*
|
|
* Does not update age or recenty of use, or iterate over stale values.
|
|
*/
|
|
forEach(fn, thisp = this) {
|
|
for (const i of this.#indexes()) {
|
|
const v = this.#valList[i];
|
|
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
if (value === void 0)
|
|
continue;
|
|
fn.call(thisp, value, this.#keyList[i], this);
|
|
}
|
|
}
|
|
/**
|
|
* The same as {@link LRUCache.forEach} but items are iterated over in
|
|
* reverse order. (ie, less recently used items are iterated over first.)
|
|
*/
|
|
rforEach(fn, thisp = this) {
|
|
for (const i of this.#rindexes()) {
|
|
const v = this.#valList[i];
|
|
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
if (value === void 0)
|
|
continue;
|
|
fn.call(thisp, value, this.#keyList[i], this);
|
|
}
|
|
}
|
|
/**
|
|
* Delete any stale entries. Returns true if anything was removed,
|
|
* false otherwise.
|
|
*/
|
|
purgeStale() {
|
|
let deleted = false;
|
|
for (const i of this.#rindexes({ allowStale: true })) {
|
|
if (this.#isStale(i)) {
|
|
this.#delete(this.#keyList[i], "expire");
|
|
deleted = true;
|
|
}
|
|
}
|
|
return deleted;
|
|
}
|
|
/**
|
|
* Get the extended info about a given entry, to get its value, size, and
|
|
* TTL info simultaneously. Returns `undefined` if the key is not present.
|
|
*
|
|
* Unlike {@link LRUCache#dump}, which is designed to be portable and survive
|
|
* serialization, the `start` value is always the current timestamp, and the
|
|
* `ttl` is a calculated remaining time to live (negative if expired).
|
|
*
|
|
* Always returns stale values, if their info is found in the cache, so be
|
|
* sure to check for expirations (ie, a negative {@link LRUCache.Entry#ttl})
|
|
* if relevant.
|
|
*/
|
|
info(key) {
|
|
const i = this.#keyMap.get(key);
|
|
if (i === void 0)
|
|
return void 0;
|
|
const v = this.#valList[i];
|
|
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
if (value === void 0)
|
|
return void 0;
|
|
const entry = { value };
|
|
if (this.#ttls && this.#starts) {
|
|
const ttl = this.#ttls[i];
|
|
const start = this.#starts[i];
|
|
if (ttl && start) {
|
|
const remain = ttl - (perf.now() - start);
|
|
entry.ttl = remain;
|
|
entry.start = Date.now();
|
|
}
|
|
}
|
|
if (this.#sizes) {
|
|
entry.size = this.#sizes[i];
|
|
}
|
|
return entry;
|
|
}
|
|
/**
|
|
* Return an array of [key, {@link LRUCache.Entry}] tuples which can be
|
|
* passed to {@link LRLUCache#load}.
|
|
*
|
|
* The `start` fields are calculated relative to a portable `Date.now()`
|
|
* timestamp, even if `performance.now()` is available.
|
|
*
|
|
* Stale entries are always included in the `dump`, even if
|
|
* {@link LRUCache.OptionsBase.allowStale} is false.
|
|
*
|
|
* Note: this returns an actual array, not a generator, so it can be more
|
|
* easily passed around.
|
|
*/
|
|
dump() {
|
|
const arr = [];
|
|
for (const i of this.#indexes({ allowStale: true })) {
|
|
const key = this.#keyList[i];
|
|
const v = this.#valList[i];
|
|
const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
if (value === void 0 || key === void 0)
|
|
continue;
|
|
const entry = { value };
|
|
if (this.#ttls && this.#starts) {
|
|
entry.ttl = this.#ttls[i];
|
|
const age = perf.now() - this.#starts[i];
|
|
entry.start = Math.floor(Date.now() - age);
|
|
}
|
|
if (this.#sizes) {
|
|
entry.size = this.#sizes[i];
|
|
}
|
|
arr.unshift([key, entry]);
|
|
}
|
|
return arr;
|
|
}
|
|
/**
|
|
* Reset the cache and load in the items in entries in the order listed.
|
|
*
|
|
* The shape of the resulting cache may be different if the same options are
|
|
* not used in both caches.
|
|
*
|
|
* The `start` fields are assumed to be calculated relative to a portable
|
|
* `Date.now()` timestamp, even if `performance.now()` is available.
|
|
*/
|
|
load(arr) {
|
|
this.clear();
|
|
for (const [key, entry] of arr) {
|
|
if (entry.start) {
|
|
const age = Date.now() - entry.start;
|
|
entry.start = perf.now() - age;
|
|
}
|
|
this.set(key, entry.value, entry);
|
|
}
|
|
}
|
|
/**
|
|
* Add a value to the cache.
|
|
*
|
|
* Note: if `undefined` is specified as a value, this is an alias for
|
|
* {@link LRUCache#delete}
|
|
*
|
|
* Fields on the {@link LRUCache.SetOptions} options param will override
|
|
* their corresponding values in the constructor options for the scope
|
|
* of this single `set()` operation.
|
|
*
|
|
* If `start` is provided, then that will set the effective start
|
|
* time for the TTL calculation. Note that this must be a previous
|
|
* value of `performance.now()` if supported, or a previous value of
|
|
* `Date.now()` if not.
|
|
*
|
|
* Options object may also include `size`, which will prevent
|
|
* calling the `sizeCalculation` function and just use the specified
|
|
* number if it is a positive integer, and `noDisposeOnSet` which
|
|
* will prevent calling a `dispose` function in the case of
|
|
* overwrites.
|
|
*
|
|
* If the `size` (or return value of `sizeCalculation`) for a given
|
|
* entry is greater than `maxEntrySize`, then the item will not be
|
|
* added to the cache.
|
|
*
|
|
* Will update the recency of the entry.
|
|
*
|
|
* If the value is `undefined`, then this is an alias for
|
|
* `cache.delete(key)`. `undefined` is never stored in the cache.
|
|
*/
|
|
set(k, v, setOptions = {}) {
|
|
if (v === void 0) {
|
|
this.delete(k);
|
|
return this;
|
|
}
|
|
const { ttl = this.ttl, start, noDisposeOnSet = this.noDisposeOnSet, sizeCalculation = this.sizeCalculation, status } = setOptions;
|
|
let { noUpdateTTL = this.noUpdateTTL } = setOptions;
|
|
const size = this.#requireSize(k, v, setOptions.size || 0, sizeCalculation);
|
|
if (this.maxEntrySize && size > this.maxEntrySize) {
|
|
if (status) {
|
|
status.set = "miss";
|
|
status.maxEntrySizeExceeded = true;
|
|
}
|
|
this.#delete(k, "set");
|
|
return this;
|
|
}
|
|
let index = this.#size === 0 ? void 0 : this.#keyMap.get(k);
|
|
if (index === void 0) {
|
|
index = this.#size === 0 ? this.#tail : this.#free.length !== 0 ? this.#free.pop() : this.#size === this.#max ? this.#evict(false) : this.#size;
|
|
this.#keyList[index] = k;
|
|
this.#valList[index] = v;
|
|
this.#keyMap.set(k, index);
|
|
this.#next[this.#tail] = index;
|
|
this.#prev[index] = this.#tail;
|
|
this.#tail = index;
|
|
this.#size++;
|
|
this.#addItemSize(index, size, status);
|
|
if (status)
|
|
status.set = "add";
|
|
noUpdateTTL = false;
|
|
} else {
|
|
this.#moveToTail(index);
|
|
const oldVal = this.#valList[index];
|
|
if (v !== oldVal) {
|
|
if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {
|
|
oldVal.__abortController.abort(new Error("replaced"));
|
|
const { __staleWhileFetching: s } = oldVal;
|
|
if (s !== void 0 && !noDisposeOnSet) {
|
|
if (this.#hasDispose) {
|
|
this.#dispose?.(s, k, "set");
|
|
}
|
|
if (this.#hasDisposeAfter) {
|
|
this.#disposed?.push([s, k, "set"]);
|
|
}
|
|
}
|
|
} else if (!noDisposeOnSet) {
|
|
if (this.#hasDispose) {
|
|
this.#dispose?.(oldVal, k, "set");
|
|
}
|
|
if (this.#hasDisposeAfter) {
|
|
this.#disposed?.push([oldVal, k, "set"]);
|
|
}
|
|
}
|
|
this.#removeItemSize(index);
|
|
this.#addItemSize(index, size, status);
|
|
this.#valList[index] = v;
|
|
if (status) {
|
|
status.set = "replace";
|
|
const oldValue = oldVal && this.#isBackgroundFetch(oldVal) ? oldVal.__staleWhileFetching : oldVal;
|
|
if (oldValue !== void 0)
|
|
status.oldValue = oldValue;
|
|
}
|
|
} else if (status) {
|
|
status.set = "update";
|
|
}
|
|
}
|
|
if (ttl !== 0 && !this.#ttls) {
|
|
this.#initializeTTLTracking();
|
|
}
|
|
if (this.#ttls) {
|
|
if (!noUpdateTTL) {
|
|
this.#setItemTTL(index, ttl, start);
|
|
}
|
|
if (status)
|
|
this.#statusTTL(status, index);
|
|
}
|
|
if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {
|
|
const dt = this.#disposed;
|
|
let task;
|
|
while (task = dt?.shift()) {
|
|
this.#disposeAfter?.(...task);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
/**
|
|
* Evict the least recently used item, returning its value or
|
|
* `undefined` if cache is empty.
|
|
*/
|
|
pop() {
|
|
try {
|
|
while (this.#size) {
|
|
const val = this.#valList[this.#head];
|
|
this.#evict(true);
|
|
if (this.#isBackgroundFetch(val)) {
|
|
if (val.__staleWhileFetching) {
|
|
return val.__staleWhileFetching;
|
|
}
|
|
} else if (val !== void 0) {
|
|
return val;
|
|
}
|
|
}
|
|
} finally {
|
|
if (this.#hasDisposeAfter && this.#disposed) {
|
|
const dt = this.#disposed;
|
|
let task;
|
|
while (task = dt?.shift()) {
|
|
this.#disposeAfter?.(...task);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#evict(free) {
|
|
const head = this.#head;
|
|
const k = this.#keyList[head];
|
|
const v = this.#valList[head];
|
|
if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) {
|
|
v.__abortController.abort(new Error("evicted"));
|
|
} else if (this.#hasDispose || this.#hasDisposeAfter) {
|
|
if (this.#hasDispose) {
|
|
this.#dispose?.(v, k, "evict");
|
|
}
|
|
if (this.#hasDisposeAfter) {
|
|
this.#disposed?.push([v, k, "evict"]);
|
|
}
|
|
}
|
|
this.#removeItemSize(head);
|
|
if (free) {
|
|
this.#keyList[head] = void 0;
|
|
this.#valList[head] = void 0;
|
|
this.#free.push(head);
|
|
}
|
|
if (this.#size === 1) {
|
|
this.#head = this.#tail = 0;
|
|
this.#free.length = 0;
|
|
} else {
|
|
this.#head = this.#next[head];
|
|
}
|
|
this.#keyMap.delete(k);
|
|
this.#size--;
|
|
return head;
|
|
}
|
|
/**
|
|
* Check if a key is in the cache, without updating the recency of use.
|
|
* Will return false if the item is stale, even though it is technically
|
|
* in the cache.
|
|
*
|
|
* Check if a key is in the cache, without updating the recency of
|
|
* use. Age is updated if {@link LRUCache.OptionsBase.updateAgeOnHas} is set
|
|
* to `true` in either the options or the constructor.
|
|
*
|
|
* Will return `false` if the item is stale, even though it is technically in
|
|
* the cache. The difference can be determined (if it matters) by using a
|
|
* `status` argument, and inspecting the `has` field.
|
|
*
|
|
* Will not update item age unless
|
|
* {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
|
|
*/
|
|
has(k, hasOptions = {}) {
|
|
const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions;
|
|
const index = this.#keyMap.get(k);
|
|
if (index !== void 0) {
|
|
const v = this.#valList[index];
|
|
if (this.#isBackgroundFetch(v) && v.__staleWhileFetching === void 0) {
|
|
return false;
|
|
}
|
|
if (!this.#isStale(index)) {
|
|
if (updateAgeOnHas) {
|
|
this.#updateItemAge(index);
|
|
}
|
|
if (status) {
|
|
status.has = "hit";
|
|
this.#statusTTL(status, index);
|
|
}
|
|
return true;
|
|
} else if (status) {
|
|
status.has = "stale";
|
|
this.#statusTTL(status, index);
|
|
}
|
|
} else if (status) {
|
|
status.has = "miss";
|
|
}
|
|
return false;
|
|
}
|
|
/**
|
|
* Like {@link LRUCache#get} but doesn't update recency or delete stale
|
|
* items.
|
|
*
|
|
* Returns `undefined` if the item is stale, unless
|
|
* {@link LRUCache.OptionsBase.allowStale} is set.
|
|
*/
|
|
peek(k, peekOptions = {}) {
|
|
const { allowStale = this.allowStale } = peekOptions;
|
|
const index = this.#keyMap.get(k);
|
|
if (index === void 0 || !allowStale && this.#isStale(index)) {
|
|
return;
|
|
}
|
|
const v = this.#valList[index];
|
|
return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
|
}
|
|
#backgroundFetch(k, index, options, context) {
|
|
const v = index === void 0 ? void 0 : this.#valList[index];
|
|
if (this.#isBackgroundFetch(v)) {
|
|
return v;
|
|
}
|
|
const ac = new AC();
|
|
const { signal } = options;
|
|
signal?.addEventListener("abort", () => ac.abort(signal.reason), {
|
|
signal: ac.signal
|
|
});
|
|
const fetchOpts = {
|
|
signal: ac.signal,
|
|
options,
|
|
context
|
|
};
|
|
const cb = (v2, updateCache = false) => {
|
|
const { aborted } = ac.signal;
|
|
const ignoreAbort = options.ignoreFetchAbort && v2 !== void 0;
|
|
if (options.status) {
|
|
if (aborted && !updateCache) {
|
|
options.status.fetchAborted = true;
|
|
options.status.fetchError = ac.signal.reason;
|
|
if (ignoreAbort)
|
|
options.status.fetchAbortIgnored = true;
|
|
} else {
|
|
options.status.fetchResolved = true;
|
|
}
|
|
}
|
|
if (aborted && !ignoreAbort && !updateCache) {
|
|
return fetchFail(ac.signal.reason);
|
|
}
|
|
const bf2 = p;
|
|
if (this.#valList[index] === p) {
|
|
if (v2 === void 0) {
|
|
if (bf2.__staleWhileFetching) {
|
|
this.#valList[index] = bf2.__staleWhileFetching;
|
|
} else {
|
|
this.#delete(k, "fetch");
|
|
}
|
|
} else {
|
|
if (options.status)
|
|
options.status.fetchUpdated = true;
|
|
this.set(k, v2, fetchOpts.options);
|
|
}
|
|
}
|
|
return v2;
|
|
};
|
|
const eb = (er) => {
|
|
if (options.status) {
|
|
options.status.fetchRejected = true;
|
|
options.status.fetchError = er;
|
|
}
|
|
return fetchFail(er);
|
|
};
|
|
const fetchFail = (er) => {
|
|
const { aborted } = ac.signal;
|
|
const allowStaleAborted = aborted && options.allowStaleOnFetchAbort;
|
|
const allowStale = allowStaleAborted || options.allowStaleOnFetchRejection;
|
|
const noDelete = allowStale || options.noDeleteOnFetchRejection;
|
|
const bf2 = p;
|
|
if (this.#valList[index] === p) {
|
|
const del = !noDelete || bf2.__staleWhileFetching === void 0;
|
|
if (del) {
|
|
this.#delete(k, "fetch");
|
|
} else if (!allowStaleAborted) {
|
|
this.#valList[index] = bf2.__staleWhileFetching;
|
|
}
|
|
}
|
|
if (allowStale) {
|
|
if (options.status && bf2.__staleWhileFetching !== void 0) {
|
|
options.status.returnedStale = true;
|
|
}
|
|
return bf2.__staleWhileFetching;
|
|
} else if (bf2.__returned === bf2) {
|
|
throw er;
|
|
}
|
|
};
|
|
const pcall = (res, rej) => {
|
|
const fmp = this.#fetchMethod?.(k, v, fetchOpts);
|
|
if (fmp && fmp instanceof Promise) {
|
|
fmp.then((v2) => res(v2 === void 0 ? void 0 : v2), rej);
|
|
}
|
|
ac.signal.addEventListener("abort", () => {
|
|
if (!options.ignoreFetchAbort || options.allowStaleOnFetchAbort) {
|
|
res(void 0);
|
|
if (options.allowStaleOnFetchAbort) {
|
|
res = (v2) => cb(v2, true);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
if (options.status)
|
|
options.status.fetchDispatched = true;
|
|
const p = new Promise(pcall).then(cb, eb);
|
|
const bf = Object.assign(p, {
|
|
__abortController: ac,
|
|
__staleWhileFetching: v,
|
|
__returned: void 0
|
|
});
|
|
if (index === void 0) {
|
|
this.set(k, bf, { ...fetchOpts.options, status: void 0 });
|
|
index = this.#keyMap.get(k);
|
|
} else {
|
|
this.#valList[index] = bf;
|
|
}
|
|
return bf;
|
|
}
|
|
#isBackgroundFetch(p) {
|
|
if (!this.#hasFetchMethod)
|
|
return false;
|
|
const b = p;
|
|
return !!b && b instanceof Promise && b.hasOwnProperty("__staleWhileFetching") && b.__abortController instanceof AC;
|
|
}
|
|
async fetch(k, fetchOptions = {}) {
|
|
const {
|
|
// get options
|
|
allowStale = this.allowStale,
|
|
updateAgeOnGet = this.updateAgeOnGet,
|
|
noDeleteOnStaleGet = this.noDeleteOnStaleGet,
|
|
// set options
|
|
ttl = this.ttl,
|
|
noDisposeOnSet = this.noDisposeOnSet,
|
|
size = 0,
|
|
sizeCalculation = this.sizeCalculation,
|
|
noUpdateTTL = this.noUpdateTTL,
|
|
// fetch exclusive options
|
|
noDeleteOnFetchRejection = this.noDeleteOnFetchRejection,
|
|
allowStaleOnFetchRejection = this.allowStaleOnFetchRejection,
|
|
ignoreFetchAbort = this.ignoreFetchAbort,
|
|
allowStaleOnFetchAbort = this.allowStaleOnFetchAbort,
|
|
context,
|
|
forceRefresh = false,
|
|
status,
|
|
signal
|
|
} = fetchOptions;
|
|
if (!this.#hasFetchMethod) {
|
|
if (status)
|
|
status.fetch = "get";
|
|
return this.get(k, {
|
|
allowStale,
|
|
updateAgeOnGet,
|
|
noDeleteOnStaleGet,
|
|
status
|
|
});
|
|
}
|
|
const options = {
|
|
allowStale,
|
|
updateAgeOnGet,
|
|
noDeleteOnStaleGet,
|
|
ttl,
|
|
noDisposeOnSet,
|
|
size,
|
|
sizeCalculation,
|
|
noUpdateTTL,
|
|
noDeleteOnFetchRejection,
|
|
allowStaleOnFetchRejection,
|
|
allowStaleOnFetchAbort,
|
|
ignoreFetchAbort,
|
|
status,
|
|
signal
|
|
};
|
|
let index = this.#keyMap.get(k);
|
|
if (index === void 0) {
|
|
if (status)
|
|
status.fetch = "miss";
|
|
const p = this.#backgroundFetch(k, index, options, context);
|
|
return p.__returned = p;
|
|
} else {
|
|
const v = this.#valList[index];
|
|
if (this.#isBackgroundFetch(v)) {
|
|
const stale = allowStale && v.__staleWhileFetching !== void 0;
|
|
if (status) {
|
|
status.fetch = "inflight";
|
|
if (stale)
|
|
status.returnedStale = true;
|
|
}
|
|
return stale ? v.__staleWhileFetching : v.__returned = v;
|
|
}
|
|
const isStale = this.#isStale(index);
|
|
if (!forceRefresh && !isStale) {
|
|
if (status)
|
|
status.fetch = "hit";
|
|
this.#moveToTail(index);
|
|
if (updateAgeOnGet) {
|
|
this.#updateItemAge(index);
|
|
}
|
|
if (status)
|
|
this.#statusTTL(status, index);
|
|
return v;
|
|
}
|
|
const p = this.#backgroundFetch(k, index, options, context);
|
|
const hasStale = p.__staleWhileFetching !== void 0;
|
|
const staleVal = hasStale && allowStale;
|
|
if (status) {
|
|
status.fetch = isStale ? "stale" : "refresh";
|
|
if (staleVal && isStale)
|
|
status.returnedStale = true;
|
|
}
|
|
return staleVal ? p.__staleWhileFetching : p.__returned = p;
|
|
}
|
|
}
|
|
async forceFetch(k, fetchOptions = {}) {
|
|
const v = await this.fetch(k, fetchOptions);
|
|
if (v === void 0)
|
|
throw new Error("fetch() returned undefined");
|
|
return v;
|
|
}
|
|
memo(k, memoOptions = {}) {
|
|
const memoMethod = this.#memoMethod;
|
|
if (!memoMethod) {
|
|
throw new Error("no memoMethod provided to constructor");
|
|
}
|
|
const { context, forceRefresh, ...options } = memoOptions;
|
|
const v = this.get(k, options);
|
|
if (!forceRefresh && v !== void 0)
|
|
return v;
|
|
const vv = memoMethod(k, v, {
|
|
options,
|
|
context
|
|
});
|
|
this.set(k, vv, options);
|
|
return vv;
|
|
}
|
|
/**
|
|
* Return a value from the cache. Will update the recency of the cache
|
|
* entry found.
|
|
*
|
|
* If the key is not found, get() will return `undefined`.
|
|
*/
|
|
get(k, getOptions = {}) {
|
|
const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, status } = getOptions;
|
|
const index = this.#keyMap.get(k);
|
|
if (index !== void 0) {
|
|
const value = this.#valList[index];
|
|
const fetching = this.#isBackgroundFetch(value);
|
|
if (status)
|
|
this.#statusTTL(status, index);
|
|
if (this.#isStale(index)) {
|
|
if (status)
|
|
status.get = "stale";
|
|
if (!fetching) {
|
|
if (!noDeleteOnStaleGet) {
|
|
this.#delete(k, "expire");
|
|
}
|
|
if (status && allowStale)
|
|
status.returnedStale = true;
|
|
return allowStale ? value : void 0;
|
|
} else {
|
|
if (status && allowStale && value.__staleWhileFetching !== void 0) {
|
|
status.returnedStale = true;
|
|
}
|
|
return allowStale ? value.__staleWhileFetching : void 0;
|
|
}
|
|
} else {
|
|
if (status)
|
|
status.get = "hit";
|
|
if (fetching) {
|
|
return value.__staleWhileFetching;
|
|
}
|
|
this.#moveToTail(index);
|
|
if (updateAgeOnGet) {
|
|
this.#updateItemAge(index);
|
|
}
|
|
return value;
|
|
}
|
|
} else if (status) {
|
|
status.get = "miss";
|
|
}
|
|
}
|
|
#connect(p, n) {
|
|
this.#prev[n] = p;
|
|
this.#next[p] = n;
|
|
}
|
|
#moveToTail(index) {
|
|
if (index !== this.#tail) {
|
|
if (index === this.#head) {
|
|
this.#head = this.#next[index];
|
|
} else {
|
|
this.#connect(this.#prev[index], this.#next[index]);
|
|
}
|
|
this.#connect(this.#tail, index);
|
|
this.#tail = index;
|
|
}
|
|
}
|
|
/**
|
|
* Deletes a key out of the cache.
|
|
*
|
|
* Returns true if the key was deleted, false otherwise.
|
|
*/
|
|
delete(k) {
|
|
return this.#delete(k, "delete");
|
|
}
|
|
#delete(k, reason) {
|
|
let deleted = false;
|
|
if (this.#size !== 0) {
|
|
const index = this.#keyMap.get(k);
|
|
if (index !== void 0) {
|
|
deleted = true;
|
|
if (this.#size === 1) {
|
|
this.#clear(reason);
|
|
} else {
|
|
this.#removeItemSize(index);
|
|
const v = this.#valList[index];
|
|
if (this.#isBackgroundFetch(v)) {
|
|
v.__abortController.abort(new Error("deleted"));
|
|
} else if (this.#hasDispose || this.#hasDisposeAfter) {
|
|
if (this.#hasDispose) {
|
|
this.#dispose?.(v, k, reason);
|
|
}
|
|
if (this.#hasDisposeAfter) {
|
|
this.#disposed?.push([v, k, reason]);
|
|
}
|
|
}
|
|
this.#keyMap.delete(k);
|
|
this.#keyList[index] = void 0;
|
|
this.#valList[index] = void 0;
|
|
if (index === this.#tail) {
|
|
this.#tail = this.#prev[index];
|
|
} else if (index === this.#head) {
|
|
this.#head = this.#next[index];
|
|
} else {
|
|
const pi = this.#prev[index];
|
|
this.#next[pi] = this.#next[index];
|
|
const ni = this.#next[index];
|
|
this.#prev[ni] = this.#prev[index];
|
|
}
|
|
this.#size--;
|
|
this.#free.push(index);
|
|
}
|
|
}
|
|
}
|
|
if (this.#hasDisposeAfter && this.#disposed?.length) {
|
|
const dt = this.#disposed;
|
|
let task;
|
|
while (task = dt?.shift()) {
|
|
this.#disposeAfter?.(...task);
|
|
}
|
|
}
|
|
return deleted;
|
|
}
|
|
/**
|
|
* Clear the cache entirely, throwing away all values.
|
|
*/
|
|
clear() {
|
|
return this.#clear("delete");
|
|
}
|
|
#clear(reason) {
|
|
for (const index of this.#rindexes({ allowStale: true })) {
|
|
const v = this.#valList[index];
|
|
if (this.#isBackgroundFetch(v)) {
|
|
v.__abortController.abort(new Error("deleted"));
|
|
} else {
|
|
const k = this.#keyList[index];
|
|
if (this.#hasDispose) {
|
|
this.#dispose?.(v, k, reason);
|
|
}
|
|
if (this.#hasDisposeAfter) {
|
|
this.#disposed?.push([v, k, reason]);
|
|
}
|
|
}
|
|
}
|
|
this.#keyMap.clear();
|
|
this.#valList.fill(void 0);
|
|
this.#keyList.fill(void 0);
|
|
if (this.#ttls && this.#starts) {
|
|
this.#ttls.fill(0);
|
|
this.#starts.fill(0);
|
|
}
|
|
if (this.#sizes) {
|
|
this.#sizes.fill(0);
|
|
}
|
|
this.#head = 0;
|
|
this.#tail = 0;
|
|
this.#free.length = 0;
|
|
this.#calculatedSize = 0;
|
|
this.#size = 0;
|
|
if (this.#hasDisposeAfter && this.#disposed) {
|
|
const dt = this.#disposed;
|
|
let task;
|
|
while (task = dt?.shift()) {
|
|
this.#disposeAfter?.(...task);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
exports.LRUCache = LRUCache;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/minipass/dist/commonjs/index.js
|
|
var require_commonjs3 = __commonJS({
|
|
"../../node_modules/minipass/dist/commonjs/index.js"(exports) {
|
|
"use strict";
|
|
var __importDefault = exports && exports.__importDefault || function(mod) {
|
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Minipass = exports.isWritable = exports.isReadable = exports.isStream = void 0;
|
|
var proc = typeof process === "object" && process ? process : {
|
|
stdout: null,
|
|
stderr: null
|
|
};
|
|
var node_events_1 = __require("bare-events");
|
|
var node_stream_1 = __importDefault(__require("bare-stream"));
|
|
var node_string_decoder_1 = __require("bare-string-decoder");
|
|
var isStream = (s) => !!s && typeof s === "object" && (s instanceof Minipass || s instanceof node_stream_1.default || (0, exports.isReadable)(s) || (0, exports.isWritable)(s));
|
|
exports.isStream = isStream;
|
|
var isReadable = (s) => !!s && typeof s === "object" && s instanceof node_events_1.EventEmitter && typeof s.pipe === "function" && // node core Writable streams have a pipe() method, but it throws
|
|
s.pipe !== node_stream_1.default.Writable.prototype.pipe;
|
|
exports.isReadable = isReadable;
|
|
var isWritable = (s) => !!s && typeof s === "object" && s instanceof node_events_1.EventEmitter && typeof s.write === "function" && typeof s.end === "function";
|
|
exports.isWritable = isWritable;
|
|
var EOF = Symbol("EOF");
|
|
var MAYBE_EMIT_END = Symbol("maybeEmitEnd");
|
|
var EMITTED_END = Symbol("emittedEnd");
|
|
var EMITTING_END = Symbol("emittingEnd");
|
|
var EMITTED_ERROR = Symbol("emittedError");
|
|
var CLOSED = Symbol("closed");
|
|
var READ = Symbol("read");
|
|
var FLUSH = Symbol("flush");
|
|
var FLUSHCHUNK = Symbol("flushChunk");
|
|
var ENCODING = Symbol("encoding");
|
|
var DECODER = Symbol("decoder");
|
|
var FLOWING = Symbol("flowing");
|
|
var PAUSED = Symbol("paused");
|
|
var RESUME = Symbol("resume");
|
|
var BUFFER = Symbol("buffer");
|
|
var PIPES = Symbol("pipes");
|
|
var BUFFERLENGTH = Symbol("bufferLength");
|
|
var BUFFERPUSH = Symbol("bufferPush");
|
|
var BUFFERSHIFT = Symbol("bufferShift");
|
|
var OBJECTMODE = Symbol("objectMode");
|
|
var DESTROYED = Symbol("destroyed");
|
|
var ERROR = Symbol("error");
|
|
var EMITDATA = Symbol("emitData");
|
|
var EMITEND = Symbol("emitEnd");
|
|
var EMITEND2 = Symbol("emitEnd2");
|
|
var ASYNC = Symbol("async");
|
|
var ABORT = Symbol("abort");
|
|
var ABORTED = Symbol("aborted");
|
|
var SIGNAL = Symbol("signal");
|
|
var DATALISTENERS = Symbol("dataListeners");
|
|
var DISCARDED = Symbol("discarded");
|
|
var defer = (fn) => Promise.resolve().then(fn);
|
|
var nodefer = (fn) => fn();
|
|
var isEndish = (ev) => ev === "end" || ev === "finish" || ev === "prefinish";
|
|
var isArrayBufferLike = (b) => b instanceof ArrayBuffer || !!b && typeof b === "object" && b.constructor && b.constructor.name === "ArrayBuffer" && b.byteLength >= 0;
|
|
var isArrayBufferView = (b) => !Buffer.isBuffer(b) && ArrayBuffer.isView(b);
|
|
var Pipe = class {
|
|
src;
|
|
dest;
|
|
opts;
|
|
ondrain;
|
|
constructor(src, dest, opts) {
|
|
this.src = src;
|
|
this.dest = dest;
|
|
this.opts = opts;
|
|
this.ondrain = () => src[RESUME]();
|
|
this.dest.on("drain", this.ondrain);
|
|
}
|
|
unpipe() {
|
|
this.dest.removeListener("drain", this.ondrain);
|
|
}
|
|
// only here for the prototype
|
|
/* c8 ignore start */
|
|
proxyErrors(_er) {
|
|
}
|
|
/* c8 ignore stop */
|
|
end() {
|
|
this.unpipe();
|
|
if (this.opts.end)
|
|
this.dest.end();
|
|
}
|
|
};
|
|
var PipeProxyErrors = class extends Pipe {
|
|
unpipe() {
|
|
this.src.removeListener("error", this.proxyErrors);
|
|
super.unpipe();
|
|
}
|
|
constructor(src, dest, opts) {
|
|
super(src, dest, opts);
|
|
this.proxyErrors = (er) => this.dest.emit("error", er);
|
|
src.on("error", this.proxyErrors);
|
|
}
|
|
};
|
|
var isObjectModeOptions = (o) => !!o.objectMode;
|
|
var isEncodingOptions = (o) => !o.objectMode && !!o.encoding && o.encoding !== "buffer";
|
|
var Minipass = class extends node_events_1.EventEmitter {
|
|
[FLOWING] = false;
|
|
[PAUSED] = false;
|
|
[PIPES] = [];
|
|
[BUFFER] = [];
|
|
[OBJECTMODE];
|
|
[ENCODING];
|
|
[ASYNC];
|
|
[DECODER];
|
|
[EOF] = false;
|
|
[EMITTED_END] = false;
|
|
[EMITTING_END] = false;
|
|
[CLOSED] = false;
|
|
[EMITTED_ERROR] = null;
|
|
[BUFFERLENGTH] = 0;
|
|
[DESTROYED] = false;
|
|
[SIGNAL];
|
|
[ABORTED] = false;
|
|
[DATALISTENERS] = 0;
|
|
[DISCARDED] = false;
|
|
/**
|
|
* true if the stream can be written
|
|
*/
|
|
writable = true;
|
|
/**
|
|
* true if the stream can be read
|
|
*/
|
|
readable = true;
|
|
/**
|
|
* If `RType` is Buffer, then options do not need to be provided.
|
|
* Otherwise, an options object must be provided to specify either
|
|
* {@link Minipass.SharedOptions.objectMode} or
|
|
* {@link Minipass.SharedOptions.encoding}, as appropriate.
|
|
*/
|
|
constructor(...args) {
|
|
const options = args[0] || {};
|
|
super();
|
|
if (options.objectMode && typeof options.encoding === "string") {
|
|
throw new TypeError("Encoding and objectMode may not be used together");
|
|
}
|
|
if (isObjectModeOptions(options)) {
|
|
this[OBJECTMODE] = true;
|
|
this[ENCODING] = null;
|
|
} else if (isEncodingOptions(options)) {
|
|
this[ENCODING] = options.encoding;
|
|
this[OBJECTMODE] = false;
|
|
} else {
|
|
this[OBJECTMODE] = false;
|
|
this[ENCODING] = null;
|
|
}
|
|
this[ASYNC] = !!options.async;
|
|
this[DECODER] = this[ENCODING] ? new node_string_decoder_1.StringDecoder(this[ENCODING]) : null;
|
|
if (options && options.debugExposeBuffer === true) {
|
|
Object.defineProperty(this, "buffer", { get: () => this[BUFFER] });
|
|
}
|
|
if (options && options.debugExposePipes === true) {
|
|
Object.defineProperty(this, "pipes", { get: () => this[PIPES] });
|
|
}
|
|
const { signal } = options;
|
|
if (signal) {
|
|
this[SIGNAL] = signal;
|
|
if (signal.aborted) {
|
|
this[ABORT]();
|
|
} else {
|
|
signal.addEventListener("abort", () => this[ABORT]());
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* The amount of data stored in the buffer waiting to be read.
|
|
*
|
|
* For Buffer strings, this will be the total byte length.
|
|
* For string encoding streams, this will be the string character length,
|
|
* according to JavaScript's `string.length` logic.
|
|
* For objectMode streams, this is a count of the items waiting to be
|
|
* emitted.
|
|
*/
|
|
get bufferLength() {
|
|
return this[BUFFERLENGTH];
|
|
}
|
|
/**
|
|
* The `BufferEncoding` currently in use, or `null`
|
|
*/
|
|
get encoding() {
|
|
return this[ENCODING];
|
|
}
|
|
/**
|
|
* @deprecated - This is a read only property
|
|
*/
|
|
set encoding(_enc) {
|
|
throw new Error("Encoding must be set at instantiation time");
|
|
}
|
|
/**
|
|
* @deprecated - Encoding may only be set at instantiation time
|
|
*/
|
|
setEncoding(_enc) {
|
|
throw new Error("Encoding must be set at instantiation time");
|
|
}
|
|
/**
|
|
* True if this is an objectMode stream
|
|
*/
|
|
get objectMode() {
|
|
return this[OBJECTMODE];
|
|
}
|
|
/**
|
|
* @deprecated - This is a read-only property
|
|
*/
|
|
set objectMode(_om) {
|
|
throw new Error("objectMode must be set at instantiation time");
|
|
}
|
|
/**
|
|
* true if this is an async stream
|
|
*/
|
|
get ["async"]() {
|
|
return this[ASYNC];
|
|
}
|
|
/**
|
|
* Set to true to make this stream async.
|
|
*
|
|
* Once set, it cannot be unset, as this would potentially cause incorrect
|
|
* behavior. Ie, a sync stream can be made async, but an async stream
|
|
* cannot be safely made sync.
|
|
*/
|
|
set ["async"](a) {
|
|
this[ASYNC] = this[ASYNC] || !!a;
|
|
}
|
|
// drop everything and get out of the flow completely
|
|
[ABORT]() {
|
|
this[ABORTED] = true;
|
|
this.emit("abort", this[SIGNAL]?.reason);
|
|
this.destroy(this[SIGNAL]?.reason);
|
|
}
|
|
/**
|
|
* True if the stream has been aborted.
|
|
*/
|
|
get aborted() {
|
|
return this[ABORTED];
|
|
}
|
|
/**
|
|
* No-op setter. Stream aborted status is set via the AbortSignal provided
|
|
* in the constructor options.
|
|
*/
|
|
set aborted(_) {
|
|
}
|
|
write(chunk, encoding, cb) {
|
|
if (this[ABORTED])
|
|
return false;
|
|
if (this[EOF])
|
|
throw new Error("write after end");
|
|
if (this[DESTROYED]) {
|
|
this.emit("error", Object.assign(new Error("Cannot call write after a stream was destroyed"), { code: "ERR_STREAM_DESTROYED" }));
|
|
return true;
|
|
}
|
|
if (typeof encoding === "function") {
|
|
cb = encoding;
|
|
encoding = "utf8";
|
|
}
|
|
if (!encoding)
|
|
encoding = "utf8";
|
|
const fn = this[ASYNC] ? defer : nodefer;
|
|
if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) {
|
|
if (isArrayBufferView(chunk)) {
|
|
chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
|
|
} else if (isArrayBufferLike(chunk)) {
|
|
chunk = Buffer.from(chunk);
|
|
} else if (typeof chunk !== "string") {
|
|
throw new Error("Non-contiguous data written to non-objectMode stream");
|
|
}
|
|
}
|
|
if (this[OBJECTMODE]) {
|
|
if (this[FLOWING] && this[BUFFERLENGTH] !== 0)
|
|
this[FLUSH](true);
|
|
if (this[FLOWING])
|
|
this.emit("data", chunk);
|
|
else
|
|
this[BUFFERPUSH](chunk);
|
|
if (this[BUFFERLENGTH] !== 0)
|
|
this.emit("readable");
|
|
if (cb)
|
|
fn(cb);
|
|
return this[FLOWING];
|
|
}
|
|
if (!chunk.length) {
|
|
if (this[BUFFERLENGTH] !== 0)
|
|
this.emit("readable");
|
|
if (cb)
|
|
fn(cb);
|
|
return this[FLOWING];
|
|
}
|
|
if (typeof chunk === "string" && // unless it is a string already ready for us to use
|
|
!(encoding === this[ENCODING] && !this[DECODER]?.lastNeed)) {
|
|
chunk = Buffer.from(chunk, encoding);
|
|
}
|
|
if (Buffer.isBuffer(chunk) && this[ENCODING]) {
|
|
chunk = this[DECODER].write(chunk);
|
|
}
|
|
if (this[FLOWING] && this[BUFFERLENGTH] !== 0)
|
|
this[FLUSH](true);
|
|
if (this[FLOWING])
|
|
this.emit("data", chunk);
|
|
else
|
|
this[BUFFERPUSH](chunk);
|
|
if (this[BUFFERLENGTH] !== 0)
|
|
this.emit("readable");
|
|
if (cb)
|
|
fn(cb);
|
|
return this[FLOWING];
|
|
}
|
|
/**
|
|
* Low-level explicit read method.
|
|
*
|
|
* In objectMode, the argument is ignored, and one item is returned if
|
|
* available.
|
|
*
|
|
* `n` is the number of bytes (or in the case of encoding streams,
|
|
* characters) to consume. If `n` is not provided, then the entire buffer
|
|
* is returned, or `null` is returned if no data is available.
|
|
*
|
|
* If `n` is greater that the amount of data in the internal buffer,
|
|
* then `null` is returned.
|
|
*/
|
|
read(n) {
|
|
if (this[DESTROYED])
|
|
return null;
|
|
this[DISCARDED] = false;
|
|
if (this[BUFFERLENGTH] === 0 || n === 0 || n && n > this[BUFFERLENGTH]) {
|
|
this[MAYBE_EMIT_END]();
|
|
return null;
|
|
}
|
|
if (this[OBJECTMODE])
|
|
n = null;
|
|
if (this[BUFFER].length > 1 && !this[OBJECTMODE]) {
|
|
this[BUFFER] = [
|
|
this[ENCODING] ? this[BUFFER].join("") : Buffer.concat(this[BUFFER], this[BUFFERLENGTH])
|
|
];
|
|
}
|
|
const ret = this[READ](n || null, this[BUFFER][0]);
|
|
this[MAYBE_EMIT_END]();
|
|
return ret;
|
|
}
|
|
[READ](n, chunk) {
|
|
if (this[OBJECTMODE])
|
|
this[BUFFERSHIFT]();
|
|
else {
|
|
const c = chunk;
|
|
if (n === c.length || n === null)
|
|
this[BUFFERSHIFT]();
|
|
else if (typeof c === "string") {
|
|
this[BUFFER][0] = c.slice(n);
|
|
chunk = c.slice(0, n);
|
|
this[BUFFERLENGTH] -= n;
|
|
} else {
|
|
this[BUFFER][0] = c.subarray(n);
|
|
chunk = c.subarray(0, n);
|
|
this[BUFFERLENGTH] -= n;
|
|
}
|
|
}
|
|
this.emit("data", chunk);
|
|
if (!this[BUFFER].length && !this[EOF])
|
|
this.emit("drain");
|
|
return chunk;
|
|
}
|
|
end(chunk, encoding, cb) {
|
|
if (typeof chunk === "function") {
|
|
cb = chunk;
|
|
chunk = void 0;
|
|
}
|
|
if (typeof encoding === "function") {
|
|
cb = encoding;
|
|
encoding = "utf8";
|
|
}
|
|
if (chunk !== void 0)
|
|
this.write(chunk, encoding);
|
|
if (cb)
|
|
this.once("end", cb);
|
|
this[EOF] = true;
|
|
this.writable = false;
|
|
if (this[FLOWING] || !this[PAUSED])
|
|
this[MAYBE_EMIT_END]();
|
|
return this;
|
|
}
|
|
// don't let the internal resume be overwritten
|
|
[RESUME]() {
|
|
if (this[DESTROYED])
|
|
return;
|
|
if (!this[DATALISTENERS] && !this[PIPES].length) {
|
|
this[DISCARDED] = true;
|
|
}
|
|
this[PAUSED] = false;
|
|
this[FLOWING] = true;
|
|
this.emit("resume");
|
|
if (this[BUFFER].length)
|
|
this[FLUSH]();
|
|
else if (this[EOF])
|
|
this[MAYBE_EMIT_END]();
|
|
else
|
|
this.emit("drain");
|
|
}
|
|
/**
|
|
* Resume the stream if it is currently in a paused state
|
|
*
|
|
* If called when there are no pipe destinations or `data` event listeners,
|
|
* this will place the stream in a "discarded" state, where all data will
|
|
* be thrown away. The discarded state is removed if a pipe destination or
|
|
* data handler is added, if pause() is called, or if any synchronous or
|
|
* asynchronous iteration is started.
|
|
*/
|
|
resume() {
|
|
return this[RESUME]();
|
|
}
|
|
/**
|
|
* Pause the stream
|
|
*/
|
|
pause() {
|
|
this[FLOWING] = false;
|
|
this[PAUSED] = true;
|
|
this[DISCARDED] = false;
|
|
}
|
|
/**
|
|
* true if the stream has been forcibly destroyed
|
|
*/
|
|
get destroyed() {
|
|
return this[DESTROYED];
|
|
}
|
|
/**
|
|
* true if the stream is currently in a flowing state, meaning that
|
|
* any writes will be immediately emitted.
|
|
*/
|
|
get flowing() {
|
|
return this[FLOWING];
|
|
}
|
|
/**
|
|
* true if the stream is currently in a paused state
|
|
*/
|
|
get paused() {
|
|
return this[PAUSED];
|
|
}
|
|
[BUFFERPUSH](chunk) {
|
|
if (this[OBJECTMODE])
|
|
this[BUFFERLENGTH] += 1;
|
|
else
|
|
this[BUFFERLENGTH] += chunk.length;
|
|
this[BUFFER].push(chunk);
|
|
}
|
|
[BUFFERSHIFT]() {
|
|
if (this[OBJECTMODE])
|
|
this[BUFFERLENGTH] -= 1;
|
|
else
|
|
this[BUFFERLENGTH] -= this[BUFFER][0].length;
|
|
return this[BUFFER].shift();
|
|
}
|
|
[FLUSH](noDrain = false) {
|
|
do {
|
|
} while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) && this[BUFFER].length);
|
|
if (!noDrain && !this[BUFFER].length && !this[EOF])
|
|
this.emit("drain");
|
|
}
|
|
[FLUSHCHUNK](chunk) {
|
|
this.emit("data", chunk);
|
|
return this[FLOWING];
|
|
}
|
|
/**
|
|
* Pipe all data emitted by this stream into the destination provided.
|
|
*
|
|
* Triggers the flow of data.
|
|
*/
|
|
pipe(dest, opts) {
|
|
if (this[DESTROYED])
|
|
return dest;
|
|
this[DISCARDED] = false;
|
|
const ended = this[EMITTED_END];
|
|
opts = opts || {};
|
|
if (dest === proc.stdout || dest === proc.stderr)
|
|
opts.end = false;
|
|
else
|
|
opts.end = opts.end !== false;
|
|
opts.proxyErrors = !!opts.proxyErrors;
|
|
if (ended) {
|
|
if (opts.end)
|
|
dest.end();
|
|
} else {
|
|
this[PIPES].push(!opts.proxyErrors ? new Pipe(this, dest, opts) : new PipeProxyErrors(this, dest, opts));
|
|
if (this[ASYNC])
|
|
defer(() => this[RESUME]());
|
|
else
|
|
this[RESUME]();
|
|
}
|
|
return dest;
|
|
}
|
|
/**
|
|
* Fully unhook a piped destination stream.
|
|
*
|
|
* If the destination stream was the only consumer of this stream (ie,
|
|
* there are no other piped destinations or `'data'` event listeners)
|
|
* then the flow of data will stop until there is another consumer or
|
|
* {@link Minipass#resume} is explicitly called.
|
|
*/
|
|
unpipe(dest) {
|
|
const p = this[PIPES].find((p2) => p2.dest === dest);
|
|
if (p) {
|
|
if (this[PIPES].length === 1) {
|
|
if (this[FLOWING] && this[DATALISTENERS] === 0) {
|
|
this[FLOWING] = false;
|
|
}
|
|
this[PIPES] = [];
|
|
} else
|
|
this[PIPES].splice(this[PIPES].indexOf(p), 1);
|
|
p.unpipe();
|
|
}
|
|
}
|
|
/**
|
|
* Alias for {@link Minipass#on}
|
|
*/
|
|
addListener(ev, handler) {
|
|
return this.on(ev, handler);
|
|
}
|
|
/**
|
|
* Mostly identical to `EventEmitter.on`, with the following
|
|
* behavior differences to prevent data loss and unnecessary hangs:
|
|
*
|
|
* - Adding a 'data' event handler will trigger the flow of data
|
|
*
|
|
* - Adding a 'readable' event handler when there is data waiting to be read
|
|
* will cause 'readable' to be emitted immediately.
|
|
*
|
|
* - Adding an 'endish' event handler ('end', 'finish', etc.) which has
|
|
* already passed will cause the event to be emitted immediately and all
|
|
* handlers removed.
|
|
*
|
|
* - Adding an 'error' event handler after an error has been emitted will
|
|
* cause the event to be re-emitted immediately with the error previously
|
|
* raised.
|
|
*/
|
|
on(ev, handler) {
|
|
const ret = super.on(ev, handler);
|
|
if (ev === "data") {
|
|
this[DISCARDED] = false;
|
|
this[DATALISTENERS]++;
|
|
if (!this[PIPES].length && !this[FLOWING]) {
|
|
this[RESUME]();
|
|
}
|
|
} else if (ev === "readable" && this[BUFFERLENGTH] !== 0) {
|
|
super.emit("readable");
|
|
} else if (isEndish(ev) && this[EMITTED_END]) {
|
|
super.emit(ev);
|
|
this.removeAllListeners(ev);
|
|
} else if (ev === "error" && this[EMITTED_ERROR]) {
|
|
const h = handler;
|
|
if (this[ASYNC])
|
|
defer(() => h.call(this, this[EMITTED_ERROR]));
|
|
else
|
|
h.call(this, this[EMITTED_ERROR]);
|
|
}
|
|
return ret;
|
|
}
|
|
/**
|
|
* Alias for {@link Minipass#off}
|
|
*/
|
|
removeListener(ev, handler) {
|
|
return this.off(ev, handler);
|
|
}
|
|
/**
|
|
* Mostly identical to `EventEmitter.off`
|
|
*
|
|
* If a 'data' event handler is removed, and it was the last consumer
|
|
* (ie, there are no pipe destinations or other 'data' event listeners),
|
|
* then the flow of data will stop until there is another consumer or
|
|
* {@link Minipass#resume} is explicitly called.
|
|
*/
|
|
off(ev, handler) {
|
|
const ret = super.off(ev, handler);
|
|
if (ev === "data") {
|
|
this[DATALISTENERS] = this.listeners("data").length;
|
|
if (this[DATALISTENERS] === 0 && !this[DISCARDED] && !this[PIPES].length) {
|
|
this[FLOWING] = false;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
/**
|
|
* Mostly identical to `EventEmitter.removeAllListeners`
|
|
*
|
|
* If all 'data' event handlers are removed, and they were the last consumer
|
|
* (ie, there are no pipe destinations), then the flow of data will stop
|
|
* until there is another consumer or {@link Minipass#resume} is explicitly
|
|
* called.
|
|
*/
|
|
removeAllListeners(ev) {
|
|
const ret = super.removeAllListeners(ev);
|
|
if (ev === "data" || ev === void 0) {
|
|
this[DATALISTENERS] = 0;
|
|
if (!this[DISCARDED] && !this[PIPES].length) {
|
|
this[FLOWING] = false;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
/**
|
|
* true if the 'end' event has been emitted
|
|
*/
|
|
get emittedEnd() {
|
|
return this[EMITTED_END];
|
|
}
|
|
[MAYBE_EMIT_END]() {
|
|
if (!this[EMITTING_END] && !this[EMITTED_END] && !this[DESTROYED] && this[BUFFER].length === 0 && this[EOF]) {
|
|
this[EMITTING_END] = true;
|
|
this.emit("end");
|
|
this.emit("prefinish");
|
|
this.emit("finish");
|
|
if (this[CLOSED])
|
|
this.emit("close");
|
|
this[EMITTING_END] = false;
|
|
}
|
|
}
|
|
/**
|
|
* Mostly identical to `EventEmitter.emit`, with the following
|
|
* behavior differences to prevent data loss and unnecessary hangs:
|
|
*
|
|
* If the stream has been destroyed, and the event is something other
|
|
* than 'close' or 'error', then `false` is returned and no handlers
|
|
* are called.
|
|
*
|
|
* If the event is 'end', and has already been emitted, then the event
|
|
* is ignored. If the stream is in a paused or non-flowing state, then
|
|
* the event will be deferred until data flow resumes. If the stream is
|
|
* async, then handlers will be called on the next tick rather than
|
|
* immediately.
|
|
*
|
|
* If the event is 'close', and 'end' has not yet been emitted, then
|
|
* the event will be deferred until after 'end' is emitted.
|
|
*
|
|
* If the event is 'error', and an AbortSignal was provided for the stream,
|
|
* and there are no listeners, then the event is ignored, matching the
|
|
* behavior of node core streams in the presense of an AbortSignal.
|
|
*
|
|
* If the event is 'finish' or 'prefinish', then all listeners will be
|
|
* removed after emitting the event, to prevent double-firing.
|
|
*/
|
|
emit(ev, ...args) {
|
|
const data = args[0];
|
|
if (ev !== "error" && ev !== "close" && ev !== DESTROYED && this[DESTROYED]) {
|
|
return false;
|
|
} else if (ev === "data") {
|
|
return !this[OBJECTMODE] && !data ? false : this[ASYNC] ? (defer(() => this[EMITDATA](data)), true) : this[EMITDATA](data);
|
|
} else if (ev === "end") {
|
|
return this[EMITEND]();
|
|
} else if (ev === "close") {
|
|
this[CLOSED] = true;
|
|
if (!this[EMITTED_END] && !this[DESTROYED])
|
|
return false;
|
|
const ret2 = super.emit("close");
|
|
this.removeAllListeners("close");
|
|
return ret2;
|
|
} else if (ev === "error") {
|
|
this[EMITTED_ERROR] = data;
|
|
super.emit(ERROR, data);
|
|
const ret2 = !this[SIGNAL] || this.listeners("error").length ? super.emit("error", data) : false;
|
|
this[MAYBE_EMIT_END]();
|
|
return ret2;
|
|
} else if (ev === "resume") {
|
|
const ret2 = super.emit("resume");
|
|
this[MAYBE_EMIT_END]();
|
|
return ret2;
|
|
} else if (ev === "finish" || ev === "prefinish") {
|
|
const ret2 = super.emit(ev);
|
|
this.removeAllListeners(ev);
|
|
return ret2;
|
|
}
|
|
const ret = super.emit(ev, ...args);
|
|
this[MAYBE_EMIT_END]();
|
|
return ret;
|
|
}
|
|
[EMITDATA](data) {
|
|
for (const p of this[PIPES]) {
|
|
if (p.dest.write(data) === false)
|
|
this.pause();
|
|
}
|
|
const ret = this[DISCARDED] ? false : super.emit("data", data);
|
|
this[MAYBE_EMIT_END]();
|
|
return ret;
|
|
}
|
|
[EMITEND]() {
|
|
if (this[EMITTED_END])
|
|
return false;
|
|
this[EMITTED_END] = true;
|
|
this.readable = false;
|
|
return this[ASYNC] ? (defer(() => this[EMITEND2]()), true) : this[EMITEND2]();
|
|
}
|
|
[EMITEND2]() {
|
|
if (this[DECODER]) {
|
|
const data = this[DECODER].end();
|
|
if (data) {
|
|
for (const p of this[PIPES]) {
|
|
p.dest.write(data);
|
|
}
|
|
if (!this[DISCARDED])
|
|
super.emit("data", data);
|
|
}
|
|
}
|
|
for (const p of this[PIPES]) {
|
|
p.end();
|
|
}
|
|
const ret = super.emit("end");
|
|
this.removeAllListeners("end");
|
|
return ret;
|
|
}
|
|
/**
|
|
* Return a Promise that resolves to an array of all emitted data once
|
|
* the stream ends.
|
|
*/
|
|
async collect() {
|
|
const buf = Object.assign([], {
|
|
dataLength: 0
|
|
});
|
|
if (!this[OBJECTMODE])
|
|
buf.dataLength = 0;
|
|
const p = this.promise();
|
|
this.on("data", (c) => {
|
|
buf.push(c);
|
|
if (!this[OBJECTMODE])
|
|
buf.dataLength += c.length;
|
|
});
|
|
await p;
|
|
return buf;
|
|
}
|
|
/**
|
|
* Return a Promise that resolves to the concatenation of all emitted data
|
|
* once the stream ends.
|
|
*
|
|
* Not allowed on objectMode streams.
|
|
*/
|
|
async concat() {
|
|
if (this[OBJECTMODE]) {
|
|
throw new Error("cannot concat in objectMode");
|
|
}
|
|
const buf = await this.collect();
|
|
return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
|
|
}
|
|
/**
|
|
* Return a void Promise that resolves once the stream ends.
|
|
*/
|
|
async promise() {
|
|
return new Promise((resolve, reject) => {
|
|
this.on(DESTROYED, () => reject(new Error("stream destroyed")));
|
|
this.on("error", (er) => reject(er));
|
|
this.on("end", () => resolve());
|
|
});
|
|
}
|
|
/**
|
|
* Asynchronous `for await of` iteration.
|
|
*
|
|
* This will continue emitting all chunks until the stream terminates.
|
|
*/
|
|
[Symbol.asyncIterator]() {
|
|
this[DISCARDED] = false;
|
|
let stopped = false;
|
|
const stop = async () => {
|
|
this.pause();
|
|
stopped = true;
|
|
return { value: void 0, done: true };
|
|
};
|
|
const next = () => {
|
|
if (stopped)
|
|
return stop();
|
|
const res = this.read();
|
|
if (res !== null)
|
|
return Promise.resolve({ done: false, value: res });
|
|
if (this[EOF])
|
|
return stop();
|
|
let resolve;
|
|
let reject;
|
|
const onerr = (er) => {
|
|
this.off("data", ondata);
|
|
this.off("end", onend);
|
|
this.off(DESTROYED, ondestroy);
|
|
stop();
|
|
reject(er);
|
|
};
|
|
const ondata = (value) => {
|
|
this.off("error", onerr);
|
|
this.off("end", onend);
|
|
this.off(DESTROYED, ondestroy);
|
|
this.pause();
|
|
resolve({ value, done: !!this[EOF] });
|
|
};
|
|
const onend = () => {
|
|
this.off("error", onerr);
|
|
this.off("data", ondata);
|
|
this.off(DESTROYED, ondestroy);
|
|
stop();
|
|
resolve({ done: true, value: void 0 });
|
|
};
|
|
const ondestroy = () => onerr(new Error("stream destroyed"));
|
|
return new Promise((res2, rej) => {
|
|
reject = rej;
|
|
resolve = res2;
|
|
this.once(DESTROYED, ondestroy);
|
|
this.once("error", onerr);
|
|
this.once("end", onend);
|
|
this.once("data", ondata);
|
|
});
|
|
};
|
|
return {
|
|
next,
|
|
throw: stop,
|
|
return: stop,
|
|
[Symbol.asyncIterator]() {
|
|
return this;
|
|
},
|
|
[Symbol.asyncDispose]: async () => {
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Synchronous `for of` iteration.
|
|
*
|
|
* The iteration will terminate when the internal buffer runs out, even
|
|
* if the stream has not yet terminated.
|
|
*/
|
|
[Symbol.iterator]() {
|
|
this[DISCARDED] = false;
|
|
let stopped = false;
|
|
const stop = () => {
|
|
this.pause();
|
|
this.off(ERROR, stop);
|
|
this.off(DESTROYED, stop);
|
|
this.off("end", stop);
|
|
stopped = true;
|
|
return { done: true, value: void 0 };
|
|
};
|
|
const next = () => {
|
|
if (stopped)
|
|
return stop();
|
|
const value = this.read();
|
|
return value === null ? stop() : { done: false, value };
|
|
};
|
|
this.once("end", stop);
|
|
this.once(ERROR, stop);
|
|
this.once(DESTROYED, stop);
|
|
return {
|
|
next,
|
|
throw: stop,
|
|
return: stop,
|
|
[Symbol.iterator]() {
|
|
return this;
|
|
},
|
|
[Symbol.dispose]: () => {
|
|
}
|
|
};
|
|
}
|
|
/**
|
|
* Destroy a stream, preventing it from being used for any further purpose.
|
|
*
|
|
* If the stream has a `close()` method, then it will be called on
|
|
* destruction.
|
|
*
|
|
* After destruction, any attempt to write data, read data, or emit most
|
|
* events will be ignored.
|
|
*
|
|
* If an error argument is provided, then it will be emitted in an
|
|
* 'error' event.
|
|
*/
|
|
destroy(er) {
|
|
if (this[DESTROYED]) {
|
|
if (er)
|
|
this.emit("error", er);
|
|
else
|
|
this.emit(DESTROYED);
|
|
return this;
|
|
}
|
|
this[DESTROYED] = true;
|
|
this[DISCARDED] = true;
|
|
this[BUFFER].length = 0;
|
|
this[BUFFERLENGTH] = 0;
|
|
const wc = this;
|
|
if (typeof wc.close === "function" && !this[CLOSED])
|
|
wc.close();
|
|
if (er)
|
|
this.emit("error", er);
|
|
else
|
|
this.emit(DESTROYED);
|
|
return this;
|
|
}
|
|
/**
|
|
* Alias for {@link isStream}
|
|
*
|
|
* Former export location, maintained for backwards compatibility.
|
|
*
|
|
* @deprecated
|
|
*/
|
|
static get isStream() {
|
|
return exports.isStream;
|
|
}
|
|
};
|
|
exports.Minipass = Minipass;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/path-scurry/dist/commonjs/index.js
|
|
var require_commonjs4 = __commonJS({
|
|
"../../node_modules/path-scurry/dist/commonjs/index.js"(exports) {
|
|
"use strict";
|
|
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === void 0) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() {
|
|
return m[k];
|
|
} };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === void 0) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = exports && exports.__importStar || function(mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) {
|
|
for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
}
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.PathScurry = exports.Path = exports.PathScurryDarwin = exports.PathScurryPosix = exports.PathScurryWin32 = exports.PathScurryBase = exports.PathPosix = exports.PathWin32 = exports.PathBase = exports.ChildrenCache = exports.ResolveCache = void 0;
|
|
var lru_cache_1 = require_commonjs2();
|
|
var node_path_1 = __require("bare-path");
|
|
var node_url_1 = __require("bare-url");
|
|
var fs_1 = __require("fs");
|
|
var actualFS = __importStar(__require("bare-fs"));
|
|
var realpathSync = fs_1.realpathSync.native;
|
|
var promises_1 = __require("bare-fs/promises");
|
|
var minipass_1 = require_commonjs3();
|
|
var defaultFS = {
|
|
lstatSync: fs_1.lstatSync,
|
|
readdir: fs_1.readdir,
|
|
readdirSync: fs_1.readdirSync,
|
|
readlinkSync: fs_1.readlinkSync,
|
|
realpathSync,
|
|
promises: {
|
|
lstat: promises_1.lstat,
|
|
readdir: promises_1.readdir,
|
|
readlink: promises_1.readlink,
|
|
realpath: promises_1.realpath
|
|
}
|
|
};
|
|
var fsFromOption = (fsOption) => !fsOption || fsOption === defaultFS || fsOption === actualFS ? defaultFS : {
|
|
...defaultFS,
|
|
...fsOption,
|
|
promises: {
|
|
...defaultFS.promises,
|
|
...fsOption.promises || {}
|
|
}
|
|
};
|
|
var uncDriveRegexp = /^\\\\\?\\([a-z]:)\\?$/i;
|
|
var uncToDrive = (rootPath) => rootPath.replace(/\//g, "\\").replace(uncDriveRegexp, "$1\\");
|
|
var eitherSep = /[\\\/]/;
|
|
var UNKNOWN = 0;
|
|
var IFIFO = 1;
|
|
var IFCHR = 2;
|
|
var IFDIR = 4;
|
|
var IFBLK = 6;
|
|
var IFREG = 8;
|
|
var IFLNK = 10;
|
|
var IFSOCK = 12;
|
|
var IFMT = 15;
|
|
var IFMT_UNKNOWN = ~IFMT;
|
|
var READDIR_CALLED = 16;
|
|
var LSTAT_CALLED = 32;
|
|
var ENOTDIR = 64;
|
|
var ENOENT = 128;
|
|
var ENOREADLINK = 256;
|
|
var ENOREALPATH = 512;
|
|
var ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH;
|
|
var TYPEMASK = 1023;
|
|
var entToType = (s) => s.isFile() ? IFREG : s.isDirectory() ? IFDIR : s.isSymbolicLink() ? IFLNK : s.isCharacterDevice() ? IFCHR : s.isBlockDevice() ? IFBLK : s.isSocket() ? IFSOCK : s.isFIFO() ? IFIFO : UNKNOWN;
|
|
var normalizeCache = /* @__PURE__ */ new Map();
|
|
var normalize = (s) => {
|
|
const c = normalizeCache.get(s);
|
|
if (c)
|
|
return c;
|
|
const n = s.normalize("NFKD");
|
|
normalizeCache.set(s, n);
|
|
return n;
|
|
};
|
|
var normalizeNocaseCache = /* @__PURE__ */ new Map();
|
|
var normalizeNocase = (s) => {
|
|
const c = normalizeNocaseCache.get(s);
|
|
if (c)
|
|
return c;
|
|
const n = normalize(s.toLowerCase());
|
|
normalizeNocaseCache.set(s, n);
|
|
return n;
|
|
};
|
|
var ResolveCache = class extends lru_cache_1.LRUCache {
|
|
constructor() {
|
|
super({ max: 256 });
|
|
}
|
|
};
|
|
exports.ResolveCache = ResolveCache;
|
|
var ChildrenCache = class extends lru_cache_1.LRUCache {
|
|
constructor(maxSize = 16 * 1024) {
|
|
super({
|
|
maxSize,
|
|
// parent + children
|
|
sizeCalculation: (a) => a.length + 1
|
|
});
|
|
}
|
|
};
|
|
exports.ChildrenCache = ChildrenCache;
|
|
var setAsCwd = Symbol("PathScurry setAsCwd");
|
|
var PathBase = class {
|
|
/**
|
|
* the basename of this path
|
|
*
|
|
* **Important**: *always* test the path name against any test string
|
|
* usingthe {@link isNamed} method, and not by directly comparing this
|
|
* string. Otherwise, unicode path strings that the system sees as identical
|
|
* will not be properly treated as the same path, leading to incorrect
|
|
* behavior and possible security issues.
|
|
*/
|
|
name;
|
|
/**
|
|
* the Path entry corresponding to the path root.
|
|
*
|
|
* @internal
|
|
*/
|
|
root;
|
|
/**
|
|
* All roots found within the current PathScurry family
|
|
*
|
|
* @internal
|
|
*/
|
|
roots;
|
|
/**
|
|
* a reference to the parent path, or undefined in the case of root entries
|
|
*
|
|
* @internal
|
|
*/
|
|
parent;
|
|
/**
|
|
* boolean indicating whether paths are compared case-insensitively
|
|
* @internal
|
|
*/
|
|
nocase;
|
|
/**
|
|
* boolean indicating that this path is the current working directory
|
|
* of the PathScurry collection that contains it.
|
|
*/
|
|
isCWD = false;
|
|
// potential default fs override
|
|
#fs;
|
|
// Stats fields
|
|
#dev;
|
|
get dev() {
|
|
return this.#dev;
|
|
}
|
|
#mode;
|
|
get mode() {
|
|
return this.#mode;
|
|
}
|
|
#nlink;
|
|
get nlink() {
|
|
return this.#nlink;
|
|
}
|
|
#uid;
|
|
get uid() {
|
|
return this.#uid;
|
|
}
|
|
#gid;
|
|
get gid() {
|
|
return this.#gid;
|
|
}
|
|
#rdev;
|
|
get rdev() {
|
|
return this.#rdev;
|
|
}
|
|
#blksize;
|
|
get blksize() {
|
|
return this.#blksize;
|
|
}
|
|
#ino;
|
|
get ino() {
|
|
return this.#ino;
|
|
}
|
|
#size;
|
|
get size() {
|
|
return this.#size;
|
|
}
|
|
#blocks;
|
|
get blocks() {
|
|
return this.#blocks;
|
|
}
|
|
#atimeMs;
|
|
get atimeMs() {
|
|
return this.#atimeMs;
|
|
}
|
|
#mtimeMs;
|
|
get mtimeMs() {
|
|
return this.#mtimeMs;
|
|
}
|
|
#ctimeMs;
|
|
get ctimeMs() {
|
|
return this.#ctimeMs;
|
|
}
|
|
#birthtimeMs;
|
|
get birthtimeMs() {
|
|
return this.#birthtimeMs;
|
|
}
|
|
#atime;
|
|
get atime() {
|
|
return this.#atime;
|
|
}
|
|
#mtime;
|
|
get mtime() {
|
|
return this.#mtime;
|
|
}
|
|
#ctime;
|
|
get ctime() {
|
|
return this.#ctime;
|
|
}
|
|
#birthtime;
|
|
get birthtime() {
|
|
return this.#birthtime;
|
|
}
|
|
#matchName;
|
|
#depth;
|
|
#fullpath;
|
|
#fullpathPosix;
|
|
#relative;
|
|
#relativePosix;
|
|
#type;
|
|
#children;
|
|
#linkTarget;
|
|
#realpath;
|
|
/**
|
|
* This property is for compatibility with the Dirent class as of
|
|
* Node v20, where Dirent['parentPath'] refers to the path of the
|
|
* directory that was passed to readdir. For root entries, it's the path
|
|
* to the entry itself.
|
|
*/
|
|
get parentPath() {
|
|
return (this.parent || this).fullpath();
|
|
}
|
|
/**
|
|
* Deprecated alias for Dirent['parentPath'] Somewhat counterintuitively,
|
|
* this property refers to the *parent* path, not the path object itself.
|
|
*/
|
|
get path() {
|
|
return this.parentPath;
|
|
}
|
|
/**
|
|
* Do not create new Path objects directly. They should always be accessed
|
|
* via the PathScurry class or other methods on the Path class.
|
|
*
|
|
* @internal
|
|
*/
|
|
constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
|
|
this.name = name;
|
|
this.#matchName = nocase ? normalizeNocase(name) : normalize(name);
|
|
this.#type = type & TYPEMASK;
|
|
this.nocase = nocase;
|
|
this.roots = roots;
|
|
this.root = root || this;
|
|
this.#children = children;
|
|
this.#fullpath = opts.fullpath;
|
|
this.#relative = opts.relative;
|
|
this.#relativePosix = opts.relativePosix;
|
|
this.parent = opts.parent;
|
|
if (this.parent) {
|
|
this.#fs = this.parent.#fs;
|
|
} else {
|
|
this.#fs = fsFromOption(opts.fs);
|
|
}
|
|
}
|
|
/**
|
|
* Returns the depth of the Path object from its root.
|
|
*
|
|
* For example, a path at `/foo/bar` would have a depth of 2.
|
|
*/
|
|
depth() {
|
|
if (this.#depth !== void 0)
|
|
return this.#depth;
|
|
if (!this.parent)
|
|
return this.#depth = 0;
|
|
return this.#depth = this.parent.depth() + 1;
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
childrenCache() {
|
|
return this.#children;
|
|
}
|
|
/**
|
|
* Get the Path object referenced by the string path, resolved from this Path
|
|
*/
|
|
resolve(path) {
|
|
if (!path) {
|
|
return this;
|
|
}
|
|
const rootPath = this.getRootString(path);
|
|
const dir = path.substring(rootPath.length);
|
|
const dirParts = dir.split(this.splitSep);
|
|
const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
|
|
return result;
|
|
}
|
|
#resolveParts(dirParts) {
|
|
let p = this;
|
|
for (const part of dirParts) {
|
|
p = p.child(part);
|
|
}
|
|
return p;
|
|
}
|
|
/**
|
|
* Returns the cached children Path objects, if still available. If they
|
|
* have fallen out of the cache, then returns an empty array, and resets the
|
|
* READDIR_CALLED bit, so that future calls to readdir() will require an fs
|
|
* lookup.
|
|
*
|
|
* @internal
|
|
*/
|
|
children() {
|
|
const cached = this.#children.get(this);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
const children = Object.assign([], { provisional: 0 });
|
|
this.#children.set(this, children);
|
|
this.#type &= ~READDIR_CALLED;
|
|
return children;
|
|
}
|
|
/**
|
|
* Resolves a path portion and returns or creates the child Path.
|
|
*
|
|
* Returns `this` if pathPart is `''` or `'.'`, or `parent` if pathPart is
|
|
* `'..'`.
|
|
*
|
|
* This should not be called directly. If `pathPart` contains any path
|
|
* separators, it will lead to unsafe undefined behavior.
|
|
*
|
|
* Use `Path.resolve()` instead.
|
|
*
|
|
* @internal
|
|
*/
|
|
child(pathPart, opts) {
|
|
if (pathPart === "" || pathPart === ".") {
|
|
return this;
|
|
}
|
|
if (pathPart === "..") {
|
|
return this.parent || this;
|
|
}
|
|
const children = this.children();
|
|
const name = this.nocase ? normalizeNocase(pathPart) : normalize(pathPart);
|
|
for (const p of children) {
|
|
if (p.#matchName === name) {
|
|
return p;
|
|
}
|
|
}
|
|
const s = this.parent ? this.sep : "";
|
|
const fullpath = this.#fullpath ? this.#fullpath + s + pathPart : void 0;
|
|
const pchild = this.newChild(pathPart, UNKNOWN, {
|
|
...opts,
|
|
parent: this,
|
|
fullpath
|
|
});
|
|
if (!this.canReaddir()) {
|
|
pchild.#type |= ENOENT;
|
|
}
|
|
children.push(pchild);
|
|
return pchild;
|
|
}
|
|
/**
|
|
* The relative path from the cwd. If it does not share an ancestor with
|
|
* the cwd, then this ends up being equivalent to the fullpath()
|
|
*/
|
|
relative() {
|
|
if (this.isCWD)
|
|
return "";
|
|
if (this.#relative !== void 0) {
|
|
return this.#relative;
|
|
}
|
|
const name = this.name;
|
|
const p = this.parent;
|
|
if (!p) {
|
|
return this.#relative = this.name;
|
|
}
|
|
const pv = p.relative();
|
|
return pv + (!pv || !p.parent ? "" : this.sep) + name;
|
|
}
|
|
/**
|
|
* The relative path from the cwd, using / as the path separator.
|
|
* If it does not share an ancestor with
|
|
* the cwd, then this ends up being equivalent to the fullpathPosix()
|
|
* On posix systems, this is identical to relative().
|
|
*/
|
|
relativePosix() {
|
|
if (this.sep === "/")
|
|
return this.relative();
|
|
if (this.isCWD)
|
|
return "";
|
|
if (this.#relativePosix !== void 0)
|
|
return this.#relativePosix;
|
|
const name = this.name;
|
|
const p = this.parent;
|
|
if (!p) {
|
|
return this.#relativePosix = this.fullpathPosix();
|
|
}
|
|
const pv = p.relativePosix();
|
|
return pv + (!pv || !p.parent ? "" : "/") + name;
|
|
}
|
|
/**
|
|
* The fully resolved path string for this Path entry
|
|
*/
|
|
fullpath() {
|
|
if (this.#fullpath !== void 0) {
|
|
return this.#fullpath;
|
|
}
|
|
const name = this.name;
|
|
const p = this.parent;
|
|
if (!p) {
|
|
return this.#fullpath = this.name;
|
|
}
|
|
const pv = p.fullpath();
|
|
const fp = pv + (!p.parent ? "" : this.sep) + name;
|
|
return this.#fullpath = fp;
|
|
}
|
|
/**
|
|
* On platforms other than windows, this is identical to fullpath.
|
|
*
|
|
* On windows, this is overridden to return the forward-slash form of the
|
|
* full UNC path.
|
|
*/
|
|
fullpathPosix() {
|
|
if (this.#fullpathPosix !== void 0)
|
|
return this.#fullpathPosix;
|
|
if (this.sep === "/")
|
|
return this.#fullpathPosix = this.fullpath();
|
|
if (!this.parent) {
|
|
const p2 = this.fullpath().replace(/\\/g, "/");
|
|
if (/^[a-z]:\//i.test(p2)) {
|
|
return this.#fullpathPosix = `//?/${p2}`;
|
|
} else {
|
|
return this.#fullpathPosix = p2;
|
|
}
|
|
}
|
|
const p = this.parent;
|
|
const pfpp = p.fullpathPosix();
|
|
const fpp = pfpp + (!pfpp || !p.parent ? "" : "/") + this.name;
|
|
return this.#fullpathPosix = fpp;
|
|
}
|
|
/**
|
|
* Is the Path of an unknown type?
|
|
*
|
|
* Note that we might know *something* about it if there has been a previous
|
|
* filesystem operation, for example that it does not exist, or is not a
|
|
* link, or whether it has child entries.
|
|
*/
|
|
isUnknown() {
|
|
return (this.#type & IFMT) === UNKNOWN;
|
|
}
|
|
isType(type) {
|
|
return this[`is${type}`]();
|
|
}
|
|
getType() {
|
|
return this.isUnknown() ? "Unknown" : this.isDirectory() ? "Directory" : this.isFile() ? "File" : this.isSymbolicLink() ? "SymbolicLink" : this.isFIFO() ? "FIFO" : this.isCharacterDevice() ? "CharacterDevice" : this.isBlockDevice() ? "BlockDevice" : (
|
|
/* c8 ignore start */
|
|
this.isSocket() ? "Socket" : "Unknown"
|
|
);
|
|
}
|
|
/**
|
|
* Is the Path a regular file?
|
|
*/
|
|
isFile() {
|
|
return (this.#type & IFMT) === IFREG;
|
|
}
|
|
/**
|
|
* Is the Path a directory?
|
|
*/
|
|
isDirectory() {
|
|
return (this.#type & IFMT) === IFDIR;
|
|
}
|
|
/**
|
|
* Is the path a character device?
|
|
*/
|
|
isCharacterDevice() {
|
|
return (this.#type & IFMT) === IFCHR;
|
|
}
|
|
/**
|
|
* Is the path a block device?
|
|
*/
|
|
isBlockDevice() {
|
|
return (this.#type & IFMT) === IFBLK;
|
|
}
|
|
/**
|
|
* Is the path a FIFO pipe?
|
|
*/
|
|
isFIFO() {
|
|
return (this.#type & IFMT) === IFIFO;
|
|
}
|
|
/**
|
|
* Is the path a socket?
|
|
*/
|
|
isSocket() {
|
|
return (this.#type & IFMT) === IFSOCK;
|
|
}
|
|
/**
|
|
* Is the path a symbolic link?
|
|
*/
|
|
isSymbolicLink() {
|
|
return (this.#type & IFLNK) === IFLNK;
|
|
}
|
|
/**
|
|
* Return the entry if it has been subject of a successful lstat, or
|
|
* undefined otherwise.
|
|
*
|
|
* Does not read the filesystem, so an undefined result *could* simply
|
|
* mean that we haven't called lstat on it.
|
|
*/
|
|
lstatCached() {
|
|
return this.#type & LSTAT_CALLED ? this : void 0;
|
|
}
|
|
/**
|
|
* Return the cached link target if the entry has been the subject of a
|
|
* successful readlink, or undefined otherwise.
|
|
*
|
|
* Does not read the filesystem, so an undefined result *could* just mean we
|
|
* don't have any cached data. Only use it if you are very sure that a
|
|
* readlink() has been called at some point.
|
|
*/
|
|
readlinkCached() {
|
|
return this.#linkTarget;
|
|
}
|
|
/**
|
|
* Returns the cached realpath target if the entry has been the subject
|
|
* of a successful realpath, or undefined otherwise.
|
|
*
|
|
* Does not read the filesystem, so an undefined result *could* just mean we
|
|
* don't have any cached data. Only use it if you are very sure that a
|
|
* realpath() has been called at some point.
|
|
*/
|
|
realpathCached() {
|
|
return this.#realpath;
|
|
}
|
|
/**
|
|
* Returns the cached child Path entries array if the entry has been the
|
|
* subject of a successful readdir(), or [] otherwise.
|
|
*
|
|
* Does not read the filesystem, so an empty array *could* just mean we
|
|
* don't have any cached data. Only use it if you are very sure that a
|
|
* readdir() has been called recently enough to still be valid.
|
|
*/
|
|
readdirCached() {
|
|
const children = this.children();
|
|
return children.slice(0, children.provisional);
|
|
}
|
|
/**
|
|
* Return true if it's worth trying to readlink. Ie, we don't (yet) have
|
|
* any indication that readlink will definitely fail.
|
|
*
|
|
* Returns false if the path is known to not be a symlink, if a previous
|
|
* readlink failed, or if the entry does not exist.
|
|
*/
|
|
canReadlink() {
|
|
if (this.#linkTarget)
|
|
return true;
|
|
if (!this.parent)
|
|
return false;
|
|
const ifmt = this.#type & IFMT;
|
|
return !(ifmt !== UNKNOWN && ifmt !== IFLNK || this.#type & ENOREADLINK || this.#type & ENOENT);
|
|
}
|
|
/**
|
|
* Return true if readdir has previously been successfully called on this
|
|
* path, indicating that cachedReaddir() is likely valid.
|
|
*/
|
|
calledReaddir() {
|
|
return !!(this.#type & READDIR_CALLED);
|
|
}
|
|
/**
|
|
* Returns true if the path is known to not exist. That is, a previous lstat
|
|
* or readdir failed to verify its existence when that would have been
|
|
* expected, or a parent entry was marked either enoent or enotdir.
|
|
*/
|
|
isENOENT() {
|
|
return !!(this.#type & ENOENT);
|
|
}
|
|
/**
|
|
* Return true if the path is a match for the given path name. This handles
|
|
* case sensitivity and unicode normalization.
|
|
*
|
|
* Note: even on case-sensitive systems, it is **not** safe to test the
|
|
* equality of the `.name` property to determine whether a given pathname
|
|
* matches, due to unicode normalization mismatches.
|
|
*
|
|
* Always use this method instead of testing the `path.name` property
|
|
* directly.
|
|
*/
|
|
isNamed(n) {
|
|
return !this.nocase ? this.#matchName === normalize(n) : this.#matchName === normalizeNocase(n);
|
|
}
|
|
/**
|
|
* Return the Path object corresponding to the target of a symbolic link.
|
|
*
|
|
* If the Path is not a symbolic link, or if the readlink call fails for any
|
|
* reason, `undefined` is returned.
|
|
*
|
|
* Result is cached, and thus may be outdated if the filesystem is mutated.
|
|
*/
|
|
async readlink() {
|
|
const target = this.#linkTarget;
|
|
if (target) {
|
|
return target;
|
|
}
|
|
if (!this.canReadlink()) {
|
|
return void 0;
|
|
}
|
|
if (!this.parent) {
|
|
return void 0;
|
|
}
|
|
try {
|
|
const read = await this.#fs.promises.readlink(this.fullpath());
|
|
const linkTarget = (await this.parent.realpath())?.resolve(read);
|
|
if (linkTarget) {
|
|
return this.#linkTarget = linkTarget;
|
|
}
|
|
} catch (er) {
|
|
this.#readlinkFail(er.code);
|
|
return void 0;
|
|
}
|
|
}
|
|
/**
|
|
* Synchronous {@link PathBase.readlink}
|
|
*/
|
|
readlinkSync() {
|
|
const target = this.#linkTarget;
|
|
if (target) {
|
|
return target;
|
|
}
|
|
if (!this.canReadlink()) {
|
|
return void 0;
|
|
}
|
|
if (!this.parent) {
|
|
return void 0;
|
|
}
|
|
try {
|
|
const read = this.#fs.readlinkSync(this.fullpath());
|
|
const linkTarget = this.parent.realpathSync()?.resolve(read);
|
|
if (linkTarget) {
|
|
return this.#linkTarget = linkTarget;
|
|
}
|
|
} catch (er) {
|
|
this.#readlinkFail(er.code);
|
|
return void 0;
|
|
}
|
|
}
|
|
#readdirSuccess(children) {
|
|
this.#type |= READDIR_CALLED;
|
|
for (let p = children.provisional; p < children.length; p++) {
|
|
const c = children[p];
|
|
if (c)
|
|
c.#markENOENT();
|
|
}
|
|
}
|
|
#markENOENT() {
|
|
if (this.#type & ENOENT)
|
|
return;
|
|
this.#type = (this.#type | ENOENT) & IFMT_UNKNOWN;
|
|
this.#markChildrenENOENT();
|
|
}
|
|
#markChildrenENOENT() {
|
|
const children = this.children();
|
|
children.provisional = 0;
|
|
for (const p of children) {
|
|
p.#markENOENT();
|
|
}
|
|
}
|
|
#markENOREALPATH() {
|
|
this.#type |= ENOREALPATH;
|
|
this.#markENOTDIR();
|
|
}
|
|
// save the information when we know the entry is not a dir
|
|
#markENOTDIR() {
|
|
if (this.#type & ENOTDIR)
|
|
return;
|
|
let t = this.#type;
|
|
if ((t & IFMT) === IFDIR)
|
|
t &= IFMT_UNKNOWN;
|
|
this.#type = t | ENOTDIR;
|
|
this.#markChildrenENOENT();
|
|
}
|
|
#readdirFail(code = "") {
|
|
if (code === "ENOTDIR" || code === "EPERM") {
|
|
this.#markENOTDIR();
|
|
} else if (code === "ENOENT") {
|
|
this.#markENOENT();
|
|
} else {
|
|
this.children().provisional = 0;
|
|
}
|
|
}
|
|
#lstatFail(code = "") {
|
|
if (code === "ENOTDIR") {
|
|
const p = this.parent;
|
|
p.#markENOTDIR();
|
|
} else if (code === "ENOENT") {
|
|
this.#markENOENT();
|
|
}
|
|
}
|
|
#readlinkFail(code = "") {
|
|
let ter = this.#type;
|
|
ter |= ENOREADLINK;
|
|
if (code === "ENOENT")
|
|
ter |= ENOENT;
|
|
if (code === "EINVAL" || code === "UNKNOWN") {
|
|
ter &= IFMT_UNKNOWN;
|
|
}
|
|
this.#type = ter;
|
|
if (code === "ENOTDIR" && this.parent) {
|
|
this.parent.#markENOTDIR();
|
|
}
|
|
}
|
|
#readdirAddChild(e, c) {
|
|
return this.#readdirMaybePromoteChild(e, c) || this.#readdirAddNewChild(e, c);
|
|
}
|
|
#readdirAddNewChild(e, c) {
|
|
const type = entToType(e);
|
|
const child = this.newChild(e.name, type, { parent: this });
|
|
const ifmt = child.#type & IFMT;
|
|
if (ifmt !== IFDIR && ifmt !== IFLNK && ifmt !== UNKNOWN) {
|
|
child.#type |= ENOTDIR;
|
|
}
|
|
c.unshift(child);
|
|
c.provisional++;
|
|
return child;
|
|
}
|
|
#readdirMaybePromoteChild(e, c) {
|
|
for (let p = c.provisional; p < c.length; p++) {
|
|
const pchild = c[p];
|
|
const name = this.nocase ? normalizeNocase(e.name) : normalize(e.name);
|
|
if (name !== pchild.#matchName) {
|
|
continue;
|
|
}
|
|
return this.#readdirPromoteChild(e, pchild, p, c);
|
|
}
|
|
}
|
|
#readdirPromoteChild(e, p, index, c) {
|
|
const v = p.name;
|
|
p.#type = p.#type & IFMT_UNKNOWN | entToType(e);
|
|
if (v !== e.name)
|
|
p.name = e.name;
|
|
if (index !== c.provisional) {
|
|
if (index === c.length - 1)
|
|
c.pop();
|
|
else
|
|
c.splice(index, 1);
|
|
c.unshift(p);
|
|
}
|
|
c.provisional++;
|
|
return p;
|
|
}
|
|
/**
|
|
* Call lstat() on this Path, and update all known information that can be
|
|
* determined.
|
|
*
|
|
* Note that unlike `fs.lstat()`, the returned value does not contain some
|
|
* information, such as `mode`, `dev`, `nlink`, and `ino`. If that
|
|
* information is required, you will need to call `fs.lstat` yourself.
|
|
*
|
|
* If the Path refers to a nonexistent file, or if the lstat call fails for
|
|
* any reason, `undefined` is returned. Otherwise the updated Path object is
|
|
* returned.
|
|
*
|
|
* Results are cached, and thus may be out of date if the filesystem is
|
|
* mutated.
|
|
*/
|
|
async lstat() {
|
|
if ((this.#type & ENOENT) === 0) {
|
|
try {
|
|
this.#applyStat(await this.#fs.promises.lstat(this.fullpath()));
|
|
return this;
|
|
} catch (er) {
|
|
this.#lstatFail(er.code);
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* synchronous {@link PathBase.lstat}
|
|
*/
|
|
lstatSync() {
|
|
if ((this.#type & ENOENT) === 0) {
|
|
try {
|
|
this.#applyStat(this.#fs.lstatSync(this.fullpath()));
|
|
return this;
|
|
} catch (er) {
|
|
this.#lstatFail(er.code);
|
|
}
|
|
}
|
|
}
|
|
#applyStat(st) {
|
|
const { atime, atimeMs, birthtime, birthtimeMs, blksize, blocks, ctime, ctimeMs, dev, gid, ino, mode, mtime, mtimeMs, nlink, rdev, size, uid } = st;
|
|
this.#atime = atime;
|
|
this.#atimeMs = atimeMs;
|
|
this.#birthtime = birthtime;
|
|
this.#birthtimeMs = birthtimeMs;
|
|
this.#blksize = blksize;
|
|
this.#blocks = blocks;
|
|
this.#ctime = ctime;
|
|
this.#ctimeMs = ctimeMs;
|
|
this.#dev = dev;
|
|
this.#gid = gid;
|
|
this.#ino = ino;
|
|
this.#mode = mode;
|
|
this.#mtime = mtime;
|
|
this.#mtimeMs = mtimeMs;
|
|
this.#nlink = nlink;
|
|
this.#rdev = rdev;
|
|
this.#size = size;
|
|
this.#uid = uid;
|
|
const ifmt = entToType(st);
|
|
this.#type = this.#type & IFMT_UNKNOWN | ifmt | LSTAT_CALLED;
|
|
if (ifmt !== UNKNOWN && ifmt !== IFDIR && ifmt !== IFLNK) {
|
|
this.#type |= ENOTDIR;
|
|
}
|
|
}
|
|
#onReaddirCB = [];
|
|
#readdirCBInFlight = false;
|
|
#callOnReaddirCB(children) {
|
|
this.#readdirCBInFlight = false;
|
|
const cbs = this.#onReaddirCB.slice();
|
|
this.#onReaddirCB.length = 0;
|
|
cbs.forEach((cb) => cb(null, children));
|
|
}
|
|
/**
|
|
* Standard node-style callback interface to get list of directory entries.
|
|
*
|
|
* If the Path cannot or does not contain any children, then an empty array
|
|
* is returned.
|
|
*
|
|
* Results are cached, and thus may be out of date if the filesystem is
|
|
* mutated.
|
|
*
|
|
* @param cb The callback called with (er, entries). Note that the `er`
|
|
* param is somewhat extraneous, as all readdir() errors are handled and
|
|
* simply result in an empty set of entries being returned.
|
|
* @param allowZalgo Boolean indicating that immediately known results should
|
|
* *not* be deferred with `queueMicrotask`. Defaults to `false`. Release
|
|
* zalgo at your peril, the dark pony lord is devious and unforgiving.
|
|
*/
|
|
readdirCB(cb, allowZalgo = false) {
|
|
if (!this.canReaddir()) {
|
|
if (allowZalgo)
|
|
cb(null, []);
|
|
else
|
|
queueMicrotask(() => cb(null, []));
|
|
return;
|
|
}
|
|
const children = this.children();
|
|
if (this.calledReaddir()) {
|
|
const c = children.slice(0, children.provisional);
|
|
if (allowZalgo)
|
|
cb(null, c);
|
|
else
|
|
queueMicrotask(() => cb(null, c));
|
|
return;
|
|
}
|
|
this.#onReaddirCB.push(cb);
|
|
if (this.#readdirCBInFlight) {
|
|
return;
|
|
}
|
|
this.#readdirCBInFlight = true;
|
|
const fullpath = this.fullpath();
|
|
this.#fs.readdir(fullpath, { withFileTypes: true }, (er, entries) => {
|
|
if (er) {
|
|
this.#readdirFail(er.code);
|
|
children.provisional = 0;
|
|
} else {
|
|
for (const e of entries) {
|
|
this.#readdirAddChild(e, children);
|
|
}
|
|
this.#readdirSuccess(children);
|
|
}
|
|
this.#callOnReaddirCB(children.slice(0, children.provisional));
|
|
return;
|
|
});
|
|
}
|
|
#asyncReaddirInFlight;
|
|
/**
|
|
* Return an array of known child entries.
|
|
*
|
|
* If the Path cannot or does not contain any children, then an empty array
|
|
* is returned.
|
|
*
|
|
* Results are cached, and thus may be out of date if the filesystem is
|
|
* mutated.
|
|
*/
|
|
async readdir() {
|
|
if (!this.canReaddir()) {
|
|
return [];
|
|
}
|
|
const children = this.children();
|
|
if (this.calledReaddir()) {
|
|
return children.slice(0, children.provisional);
|
|
}
|
|
const fullpath = this.fullpath();
|
|
if (this.#asyncReaddirInFlight) {
|
|
await this.#asyncReaddirInFlight;
|
|
} else {
|
|
let resolve = () => {
|
|
};
|
|
this.#asyncReaddirInFlight = new Promise((res) => resolve = res);
|
|
try {
|
|
for (const e of await this.#fs.promises.readdir(fullpath, {
|
|
withFileTypes: true
|
|
})) {
|
|
this.#readdirAddChild(e, children);
|
|
}
|
|
this.#readdirSuccess(children);
|
|
} catch (er) {
|
|
this.#readdirFail(er.code);
|
|
children.provisional = 0;
|
|
}
|
|
this.#asyncReaddirInFlight = void 0;
|
|
resolve();
|
|
}
|
|
return children.slice(0, children.provisional);
|
|
}
|
|
/**
|
|
* synchronous {@link PathBase.readdir}
|
|
*/
|
|
readdirSync() {
|
|
if (!this.canReaddir()) {
|
|
return [];
|
|
}
|
|
const children = this.children();
|
|
if (this.calledReaddir()) {
|
|
return children.slice(0, children.provisional);
|
|
}
|
|
const fullpath = this.fullpath();
|
|
try {
|
|
for (const e of this.#fs.readdirSync(fullpath, {
|
|
withFileTypes: true
|
|
})) {
|
|
this.#readdirAddChild(e, children);
|
|
}
|
|
this.#readdirSuccess(children);
|
|
} catch (er) {
|
|
this.#readdirFail(er.code);
|
|
children.provisional = 0;
|
|
}
|
|
return children.slice(0, children.provisional);
|
|
}
|
|
canReaddir() {
|
|
if (this.#type & ENOCHILD)
|
|
return false;
|
|
const ifmt = IFMT & this.#type;
|
|
if (!(ifmt === UNKNOWN || ifmt === IFDIR || ifmt === IFLNK)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
shouldWalk(dirs, walkFilter) {
|
|
return (this.#type & IFDIR) === IFDIR && !(this.#type & ENOCHILD) && !dirs.has(this) && (!walkFilter || walkFilter(this));
|
|
}
|
|
/**
|
|
* Return the Path object corresponding to path as resolved
|
|
* by realpath(3).
|
|
*
|
|
* If the realpath call fails for any reason, `undefined` is returned.
|
|
*
|
|
* Result is cached, and thus may be outdated if the filesystem is mutated.
|
|
* On success, returns a Path object.
|
|
*/
|
|
async realpath() {
|
|
if (this.#realpath)
|
|
return this.#realpath;
|
|
if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type)
|
|
return void 0;
|
|
try {
|
|
const rp = await this.#fs.promises.realpath(this.fullpath());
|
|
return this.#realpath = this.resolve(rp);
|
|
} catch (_) {
|
|
this.#markENOREALPATH();
|
|
}
|
|
}
|
|
/**
|
|
* Synchronous {@link realpath}
|
|
*/
|
|
realpathSync() {
|
|
if (this.#realpath)
|
|
return this.#realpath;
|
|
if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type)
|
|
return void 0;
|
|
try {
|
|
const rp = this.#fs.realpathSync(this.fullpath());
|
|
return this.#realpath = this.resolve(rp);
|
|
} catch (_) {
|
|
this.#markENOREALPATH();
|
|
}
|
|
}
|
|
/**
|
|
* Internal method to mark this Path object as the scurry cwd,
|
|
* called by {@link PathScurry#chdir}
|
|
*
|
|
* @internal
|
|
*/
|
|
[setAsCwd](oldCwd) {
|
|
if (oldCwd === this)
|
|
return;
|
|
oldCwd.isCWD = false;
|
|
this.isCWD = true;
|
|
const changed = /* @__PURE__ */ new Set([]);
|
|
let rp = [];
|
|
let p = this;
|
|
while (p && p.parent) {
|
|
changed.add(p);
|
|
p.#relative = rp.join(this.sep);
|
|
p.#relativePosix = rp.join("/");
|
|
p = p.parent;
|
|
rp.push("..");
|
|
}
|
|
p = oldCwd;
|
|
while (p && p.parent && !changed.has(p)) {
|
|
p.#relative = void 0;
|
|
p.#relativePosix = void 0;
|
|
p = p.parent;
|
|
}
|
|
}
|
|
};
|
|
exports.PathBase = PathBase;
|
|
var PathWin32 = class _PathWin32 extends PathBase {
|
|
/**
|
|
* Separator for generating path strings.
|
|
*/
|
|
sep = "\\";
|
|
/**
|
|
* Separator for parsing path strings.
|
|
*/
|
|
splitSep = eitherSep;
|
|
/**
|
|
* Do not create new Path objects directly. They should always be accessed
|
|
* via the PathScurry class or other methods on the Path class.
|
|
*
|
|
* @internal
|
|
*/
|
|
constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
|
|
super(name, type, root, roots, nocase, children, opts);
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
newChild(name, type = UNKNOWN, opts = {}) {
|
|
return new _PathWin32(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
getRootString(path) {
|
|
return node_path_1.win32.parse(path).root;
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
getRoot(rootPath) {
|
|
rootPath = uncToDrive(rootPath.toUpperCase());
|
|
if (rootPath === this.root.name) {
|
|
return this.root;
|
|
}
|
|
for (const [compare, root] of Object.entries(this.roots)) {
|
|
if (this.sameRoot(rootPath, compare)) {
|
|
return this.roots[rootPath] = root;
|
|
}
|
|
}
|
|
return this.roots[rootPath] = new PathScurryWin32(rootPath, this).root;
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
sameRoot(rootPath, compare = this.root.name) {
|
|
rootPath = rootPath.toUpperCase().replace(/\//g, "\\").replace(uncDriveRegexp, "$1\\");
|
|
return rootPath === compare;
|
|
}
|
|
};
|
|
exports.PathWin32 = PathWin32;
|
|
var PathPosix = class _PathPosix extends PathBase {
|
|
/**
|
|
* separator for parsing path strings
|
|
*/
|
|
splitSep = "/";
|
|
/**
|
|
* separator for generating path strings
|
|
*/
|
|
sep = "/";
|
|
/**
|
|
* Do not create new Path objects directly. They should always be accessed
|
|
* via the PathScurry class or other methods on the Path class.
|
|
*
|
|
* @internal
|
|
*/
|
|
constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
|
|
super(name, type, root, roots, nocase, children, opts);
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
getRootString(path) {
|
|
return path.startsWith("/") ? "/" : "";
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
getRoot(_rootPath) {
|
|
return this.root;
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
newChild(name, type = UNKNOWN, opts = {}) {
|
|
return new _PathPosix(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
|
|
}
|
|
};
|
|
exports.PathPosix = PathPosix;
|
|
var PathScurryBase = class {
|
|
/**
|
|
* The root Path entry for the current working directory of this Scurry
|
|
*/
|
|
root;
|
|
/**
|
|
* The string path for the root of this Scurry's current working directory
|
|
*/
|
|
rootPath;
|
|
/**
|
|
* A collection of all roots encountered, referenced by rootPath
|
|
*/
|
|
roots;
|
|
/**
|
|
* The Path entry corresponding to this PathScurry's current working directory.
|
|
*/
|
|
cwd;
|
|
#resolveCache;
|
|
#resolvePosixCache;
|
|
#children;
|
|
/**
|
|
* Perform path comparisons case-insensitively.
|
|
*
|
|
* Defaults true on Darwin and Windows systems, false elsewhere.
|
|
*/
|
|
nocase;
|
|
#fs;
|
|
/**
|
|
* This class should not be instantiated directly.
|
|
*
|
|
* Use PathScurryWin32, PathScurryDarwin, PathScurryPosix, or PathScurry
|
|
*
|
|
* @internal
|
|
*/
|
|
constructor(cwd = process.cwd(), pathImpl, sep, { nocase, childrenCacheSize = 16 * 1024, fs = defaultFS } = {}) {
|
|
this.#fs = fsFromOption(fs);
|
|
if (cwd instanceof URL || cwd.startsWith("file://")) {
|
|
cwd = (0, node_url_1.fileURLToPath)(cwd);
|
|
}
|
|
const cwdPath = pathImpl.resolve(cwd);
|
|
this.roots = /* @__PURE__ */ Object.create(null);
|
|
this.rootPath = this.parseRootPath(cwdPath);
|
|
this.#resolveCache = new ResolveCache();
|
|
this.#resolvePosixCache = new ResolveCache();
|
|
this.#children = new ChildrenCache(childrenCacheSize);
|
|
const split = cwdPath.substring(this.rootPath.length).split(sep);
|
|
if (split.length === 1 && !split[0]) {
|
|
split.pop();
|
|
}
|
|
if (nocase === void 0) {
|
|
throw new TypeError("must provide nocase setting to PathScurryBase ctor");
|
|
}
|
|
this.nocase = nocase;
|
|
this.root = this.newRoot(this.#fs);
|
|
this.roots[this.rootPath] = this.root;
|
|
let prev = this.root;
|
|
let len = split.length - 1;
|
|
const joinSep = pathImpl.sep;
|
|
let abs = this.rootPath;
|
|
let sawFirst = false;
|
|
for (const part of split) {
|
|
const l = len--;
|
|
prev = prev.child(part, {
|
|
relative: new Array(l).fill("..").join(joinSep),
|
|
relativePosix: new Array(l).fill("..").join("/"),
|
|
fullpath: abs += (sawFirst ? "" : joinSep) + part
|
|
});
|
|
sawFirst = true;
|
|
}
|
|
this.cwd = prev;
|
|
}
|
|
/**
|
|
* Get the depth of a provided path, string, or the cwd
|
|
*/
|
|
depth(path = this.cwd) {
|
|
if (typeof path === "string") {
|
|
path = this.cwd.resolve(path);
|
|
}
|
|
return path.depth();
|
|
}
|
|
/**
|
|
* Return the cache of child entries. Exposed so subclasses can create
|
|
* child Path objects in a platform-specific way.
|
|
*
|
|
* @internal
|
|
*/
|
|
childrenCache() {
|
|
return this.#children;
|
|
}
|
|
/**
|
|
* Resolve one or more path strings to a resolved string
|
|
*
|
|
* Same interface as require('path').resolve.
|
|
*
|
|
* Much faster than path.resolve() when called multiple times for the same
|
|
* path, because the resolved Path objects are cached. Much slower
|
|
* otherwise.
|
|
*/
|
|
resolve(...paths) {
|
|
let r = "";
|
|
for (let i = paths.length - 1; i >= 0; i--) {
|
|
const p = paths[i];
|
|
if (!p || p === ".")
|
|
continue;
|
|
r = r ? `${p}/${r}` : p;
|
|
if (this.isAbsolute(p)) {
|
|
break;
|
|
}
|
|
}
|
|
const cached = this.#resolveCache.get(r);
|
|
if (cached !== void 0) {
|
|
return cached;
|
|
}
|
|
const result = this.cwd.resolve(r).fullpath();
|
|
this.#resolveCache.set(r, result);
|
|
return result;
|
|
}
|
|
/**
|
|
* Resolve one or more path strings to a resolved string, returning
|
|
* the posix path. Identical to .resolve() on posix systems, but on
|
|
* windows will return a forward-slash separated UNC path.
|
|
*
|
|
* Same interface as require('path').resolve.
|
|
*
|
|
* Much faster than path.resolve() when called multiple times for the same
|
|
* path, because the resolved Path objects are cached. Much slower
|
|
* otherwise.
|
|
*/
|
|
resolvePosix(...paths) {
|
|
let r = "";
|
|
for (let i = paths.length - 1; i >= 0; i--) {
|
|
const p = paths[i];
|
|
if (!p || p === ".")
|
|
continue;
|
|
r = r ? `${p}/${r}` : p;
|
|
if (this.isAbsolute(p)) {
|
|
break;
|
|
}
|
|
}
|
|
const cached = this.#resolvePosixCache.get(r);
|
|
if (cached !== void 0) {
|
|
return cached;
|
|
}
|
|
const result = this.cwd.resolve(r).fullpathPosix();
|
|
this.#resolvePosixCache.set(r, result);
|
|
return result;
|
|
}
|
|
/**
|
|
* find the relative path from the cwd to the supplied path string or entry
|
|
*/
|
|
relative(entry = this.cwd) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
}
|
|
return entry.relative();
|
|
}
|
|
/**
|
|
* find the relative path from the cwd to the supplied path string or
|
|
* entry, using / as the path delimiter, even on Windows.
|
|
*/
|
|
relativePosix(entry = this.cwd) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
}
|
|
return entry.relativePosix();
|
|
}
|
|
/**
|
|
* Return the basename for the provided string or Path object
|
|
*/
|
|
basename(entry = this.cwd) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
}
|
|
return entry.name;
|
|
}
|
|
/**
|
|
* Return the dirname for the provided string or Path object
|
|
*/
|
|
dirname(entry = this.cwd) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
}
|
|
return (entry.parent || entry).fullpath();
|
|
}
|
|
async readdir(entry = this.cwd, opts = {
|
|
withFileTypes: true
|
|
}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
opts = entry;
|
|
entry = this.cwd;
|
|
}
|
|
const { withFileTypes } = opts;
|
|
if (!entry.canReaddir()) {
|
|
return [];
|
|
} else {
|
|
const p = await entry.readdir();
|
|
return withFileTypes ? p : p.map((e) => e.name);
|
|
}
|
|
}
|
|
readdirSync(entry = this.cwd, opts = {
|
|
withFileTypes: true
|
|
}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
opts = entry;
|
|
entry = this.cwd;
|
|
}
|
|
const { withFileTypes = true } = opts;
|
|
if (!entry.canReaddir()) {
|
|
return [];
|
|
} else if (withFileTypes) {
|
|
return entry.readdirSync();
|
|
} else {
|
|
return entry.readdirSync().map((e) => e.name);
|
|
}
|
|
}
|
|
/**
|
|
* Call lstat() on the string or Path object, and update all known
|
|
* information that can be determined.
|
|
*
|
|
* Note that unlike `fs.lstat()`, the returned value does not contain some
|
|
* information, such as `mode`, `dev`, `nlink`, and `ino`. If that
|
|
* information is required, you will need to call `fs.lstat` yourself.
|
|
*
|
|
* If the Path refers to a nonexistent file, or if the lstat call fails for
|
|
* any reason, `undefined` is returned. Otherwise the updated Path object is
|
|
* returned.
|
|
*
|
|
* Results are cached, and thus may be out of date if the filesystem is
|
|
* mutated.
|
|
*/
|
|
async lstat(entry = this.cwd) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
}
|
|
return entry.lstat();
|
|
}
|
|
/**
|
|
* synchronous {@link PathScurryBase.lstat}
|
|
*/
|
|
lstatSync(entry = this.cwd) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
}
|
|
return entry.lstatSync();
|
|
}
|
|
async readlink(entry = this.cwd, { withFileTypes } = {
|
|
withFileTypes: false
|
|
}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
withFileTypes = entry.withFileTypes;
|
|
entry = this.cwd;
|
|
}
|
|
const e = await entry.readlink();
|
|
return withFileTypes ? e : e?.fullpath();
|
|
}
|
|
readlinkSync(entry = this.cwd, { withFileTypes } = {
|
|
withFileTypes: false
|
|
}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
withFileTypes = entry.withFileTypes;
|
|
entry = this.cwd;
|
|
}
|
|
const e = entry.readlinkSync();
|
|
return withFileTypes ? e : e?.fullpath();
|
|
}
|
|
async realpath(entry = this.cwd, { withFileTypes } = {
|
|
withFileTypes: false
|
|
}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
withFileTypes = entry.withFileTypes;
|
|
entry = this.cwd;
|
|
}
|
|
const e = await entry.realpath();
|
|
return withFileTypes ? e : e?.fullpath();
|
|
}
|
|
realpathSync(entry = this.cwd, { withFileTypes } = {
|
|
withFileTypes: false
|
|
}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
withFileTypes = entry.withFileTypes;
|
|
entry = this.cwd;
|
|
}
|
|
const e = entry.realpathSync();
|
|
return withFileTypes ? e : e?.fullpath();
|
|
}
|
|
async walk(entry = this.cwd, opts = {}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
opts = entry;
|
|
entry = this.cwd;
|
|
}
|
|
const { withFileTypes = true, follow = false, filter, walkFilter } = opts;
|
|
const results = [];
|
|
if (!filter || filter(entry)) {
|
|
results.push(withFileTypes ? entry : entry.fullpath());
|
|
}
|
|
const dirs = /* @__PURE__ */ new Set();
|
|
const walk = (dir, cb) => {
|
|
dirs.add(dir);
|
|
dir.readdirCB((er, entries) => {
|
|
if (er) {
|
|
return cb(er);
|
|
}
|
|
let len = entries.length;
|
|
if (!len)
|
|
return cb();
|
|
const next = () => {
|
|
if (--len === 0) {
|
|
cb();
|
|
}
|
|
};
|
|
for (const e of entries) {
|
|
if (!filter || filter(e)) {
|
|
results.push(withFileTypes ? e : e.fullpath());
|
|
}
|
|
if (follow && e.isSymbolicLink()) {
|
|
e.realpath().then((r) => r?.isUnknown() ? r.lstat() : r).then((r) => r?.shouldWalk(dirs, walkFilter) ? walk(r, next) : next());
|
|
} else {
|
|
if (e.shouldWalk(dirs, walkFilter)) {
|
|
walk(e, next);
|
|
} else {
|
|
next();
|
|
}
|
|
}
|
|
}
|
|
}, true);
|
|
};
|
|
const start = entry;
|
|
return new Promise((res, rej) => {
|
|
walk(start, (er) => {
|
|
if (er)
|
|
return rej(er);
|
|
res(results);
|
|
});
|
|
});
|
|
}
|
|
walkSync(entry = this.cwd, opts = {}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
opts = entry;
|
|
entry = this.cwd;
|
|
}
|
|
const { withFileTypes = true, follow = false, filter, walkFilter } = opts;
|
|
const results = [];
|
|
if (!filter || filter(entry)) {
|
|
results.push(withFileTypes ? entry : entry.fullpath());
|
|
}
|
|
const dirs = /* @__PURE__ */ new Set([entry]);
|
|
for (const dir of dirs) {
|
|
const entries = dir.readdirSync();
|
|
for (const e of entries) {
|
|
if (!filter || filter(e)) {
|
|
results.push(withFileTypes ? e : e.fullpath());
|
|
}
|
|
let r = e;
|
|
if (e.isSymbolicLink()) {
|
|
if (!(follow && (r = e.realpathSync())))
|
|
continue;
|
|
if (r.isUnknown())
|
|
r.lstatSync();
|
|
}
|
|
if (r.shouldWalk(dirs, walkFilter)) {
|
|
dirs.add(r);
|
|
}
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
/**
|
|
* Support for `for await`
|
|
*
|
|
* Alias for {@link PathScurryBase.iterate}
|
|
*
|
|
* Note: As of Node 19, this is very slow, compared to other methods of
|
|
* walking. Consider using {@link PathScurryBase.stream} if memory overhead
|
|
* and backpressure are concerns, or {@link PathScurryBase.walk} if not.
|
|
*/
|
|
[Symbol.asyncIterator]() {
|
|
return this.iterate();
|
|
}
|
|
iterate(entry = this.cwd, options = {}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
options = entry;
|
|
entry = this.cwd;
|
|
}
|
|
return this.stream(entry, options)[Symbol.asyncIterator]();
|
|
}
|
|
/**
|
|
* Iterating over a PathScurry performs a synchronous walk.
|
|
*
|
|
* Alias for {@link PathScurryBase.iterateSync}
|
|
*/
|
|
[Symbol.iterator]() {
|
|
return this.iterateSync();
|
|
}
|
|
*iterateSync(entry = this.cwd, opts = {}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
opts = entry;
|
|
entry = this.cwd;
|
|
}
|
|
const { withFileTypes = true, follow = false, filter, walkFilter } = opts;
|
|
if (!filter || filter(entry)) {
|
|
yield withFileTypes ? entry : entry.fullpath();
|
|
}
|
|
const dirs = /* @__PURE__ */ new Set([entry]);
|
|
for (const dir of dirs) {
|
|
const entries = dir.readdirSync();
|
|
for (const e of entries) {
|
|
if (!filter || filter(e)) {
|
|
yield withFileTypes ? e : e.fullpath();
|
|
}
|
|
let r = e;
|
|
if (e.isSymbolicLink()) {
|
|
if (!(follow && (r = e.realpathSync())))
|
|
continue;
|
|
if (r.isUnknown())
|
|
r.lstatSync();
|
|
}
|
|
if (r.shouldWalk(dirs, walkFilter)) {
|
|
dirs.add(r);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
stream(entry = this.cwd, opts = {}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
opts = entry;
|
|
entry = this.cwd;
|
|
}
|
|
const { withFileTypes = true, follow = false, filter, walkFilter } = opts;
|
|
const results = new minipass_1.Minipass({ objectMode: true });
|
|
if (!filter || filter(entry)) {
|
|
results.write(withFileTypes ? entry : entry.fullpath());
|
|
}
|
|
const dirs = /* @__PURE__ */ new Set();
|
|
const queue = [entry];
|
|
let processing = 0;
|
|
const process2 = () => {
|
|
let paused = false;
|
|
while (!paused) {
|
|
const dir = queue.shift();
|
|
if (!dir) {
|
|
if (processing === 0)
|
|
results.end();
|
|
return;
|
|
}
|
|
processing++;
|
|
dirs.add(dir);
|
|
const onReaddir = (er, entries, didRealpaths = false) => {
|
|
if (er)
|
|
return results.emit("error", er);
|
|
if (follow && !didRealpaths) {
|
|
const promises = [];
|
|
for (const e of entries) {
|
|
if (e.isSymbolicLink()) {
|
|
promises.push(e.realpath().then((r) => r?.isUnknown() ? r.lstat() : r));
|
|
}
|
|
}
|
|
if (promises.length) {
|
|
Promise.all(promises).then(() => onReaddir(null, entries, true));
|
|
return;
|
|
}
|
|
}
|
|
for (const e of entries) {
|
|
if (e && (!filter || filter(e))) {
|
|
if (!results.write(withFileTypes ? e : e.fullpath())) {
|
|
paused = true;
|
|
}
|
|
}
|
|
}
|
|
processing--;
|
|
for (const e of entries) {
|
|
const r = e.realpathCached() || e;
|
|
if (r.shouldWalk(dirs, walkFilter)) {
|
|
queue.push(r);
|
|
}
|
|
}
|
|
if (paused && !results.flowing) {
|
|
results.once("drain", process2);
|
|
} else if (!sync) {
|
|
process2();
|
|
}
|
|
};
|
|
let sync = true;
|
|
dir.readdirCB(onReaddir, true);
|
|
sync = false;
|
|
}
|
|
};
|
|
process2();
|
|
return results;
|
|
}
|
|
streamSync(entry = this.cwd, opts = {}) {
|
|
if (typeof entry === "string") {
|
|
entry = this.cwd.resolve(entry);
|
|
} else if (!(entry instanceof PathBase)) {
|
|
opts = entry;
|
|
entry = this.cwd;
|
|
}
|
|
const { withFileTypes = true, follow = false, filter, walkFilter } = opts;
|
|
const results = new minipass_1.Minipass({ objectMode: true });
|
|
const dirs = /* @__PURE__ */ new Set();
|
|
if (!filter || filter(entry)) {
|
|
results.write(withFileTypes ? entry : entry.fullpath());
|
|
}
|
|
const queue = [entry];
|
|
let processing = 0;
|
|
const process2 = () => {
|
|
let paused = false;
|
|
while (!paused) {
|
|
const dir = queue.shift();
|
|
if (!dir) {
|
|
if (processing === 0)
|
|
results.end();
|
|
return;
|
|
}
|
|
processing++;
|
|
dirs.add(dir);
|
|
const entries = dir.readdirSync();
|
|
for (const e of entries) {
|
|
if (!filter || filter(e)) {
|
|
if (!results.write(withFileTypes ? e : e.fullpath())) {
|
|
paused = true;
|
|
}
|
|
}
|
|
}
|
|
processing--;
|
|
for (const e of entries) {
|
|
let r = e;
|
|
if (e.isSymbolicLink()) {
|
|
if (!(follow && (r = e.realpathSync())))
|
|
continue;
|
|
if (r.isUnknown())
|
|
r.lstatSync();
|
|
}
|
|
if (r.shouldWalk(dirs, walkFilter)) {
|
|
queue.push(r);
|
|
}
|
|
}
|
|
}
|
|
if (paused && !results.flowing)
|
|
results.once("drain", process2);
|
|
};
|
|
process2();
|
|
return results;
|
|
}
|
|
chdir(path = this.cwd) {
|
|
const oldCwd = this.cwd;
|
|
this.cwd = typeof path === "string" ? this.cwd.resolve(path) : path;
|
|
this.cwd[setAsCwd](oldCwd);
|
|
}
|
|
};
|
|
exports.PathScurryBase = PathScurryBase;
|
|
var PathScurryWin32 = class extends PathScurryBase {
|
|
/**
|
|
* separator for generating path strings
|
|
*/
|
|
sep = "\\";
|
|
constructor(cwd = process.cwd(), opts = {}) {
|
|
const { nocase = true } = opts;
|
|
super(cwd, node_path_1.win32, "\\", { ...opts, nocase });
|
|
this.nocase = nocase;
|
|
for (let p = this.cwd; p; p = p.parent) {
|
|
p.nocase = this.nocase;
|
|
}
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
parseRootPath(dir) {
|
|
return node_path_1.win32.parse(dir).root.toUpperCase();
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
newRoot(fs) {
|
|
return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs });
|
|
}
|
|
/**
|
|
* Return true if the provided path string is an absolute path
|
|
*/
|
|
isAbsolute(p) {
|
|
return p.startsWith("/") || p.startsWith("\\") || /^[a-z]:(\/|\\)/i.test(p);
|
|
}
|
|
};
|
|
exports.PathScurryWin32 = PathScurryWin32;
|
|
var PathScurryPosix = class extends PathScurryBase {
|
|
/**
|
|
* separator for generating path strings
|
|
*/
|
|
sep = "/";
|
|
constructor(cwd = process.cwd(), opts = {}) {
|
|
const { nocase = false } = opts;
|
|
super(cwd, node_path_1.posix, "/", { ...opts, nocase });
|
|
this.nocase = nocase;
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
parseRootPath(_dir) {
|
|
return "/";
|
|
}
|
|
/**
|
|
* @internal
|
|
*/
|
|
newRoot(fs) {
|
|
return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs });
|
|
}
|
|
/**
|
|
* Return true if the provided path string is an absolute path
|
|
*/
|
|
isAbsolute(p) {
|
|
return p.startsWith("/");
|
|
}
|
|
};
|
|
exports.PathScurryPosix = PathScurryPosix;
|
|
var PathScurryDarwin = class extends PathScurryPosix {
|
|
constructor(cwd = process.cwd(), opts = {}) {
|
|
const { nocase = true } = opts;
|
|
super(cwd, { ...opts, nocase });
|
|
}
|
|
};
|
|
exports.PathScurryDarwin = PathScurryDarwin;
|
|
exports.Path = process.platform === "win32" ? PathWin32 : PathPosix;
|
|
exports.PathScurry = process.platform === "win32" ? PathScurryWin32 : process.platform === "darwin" ? PathScurryDarwin : PathScurryPosix;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/glob/dist/commonjs/pattern.js
|
|
var require_pattern = __commonJS({
|
|
"../../node_modules/glob/dist/commonjs/pattern.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Pattern = void 0;
|
|
var minimatch_1 = require_commonjs();
|
|
var isPatternList = (pl) => pl.length >= 1;
|
|
var isGlobList = (gl) => gl.length >= 1;
|
|
var Pattern = class _Pattern {
|
|
#patternList;
|
|
#globList;
|
|
#index;
|
|
length;
|
|
#platform;
|
|
#rest;
|
|
#globString;
|
|
#isDrive;
|
|
#isUNC;
|
|
#isAbsolute;
|
|
#followGlobstar = true;
|
|
constructor(patternList, globList, index, platform) {
|
|
if (!isPatternList(patternList)) {
|
|
throw new TypeError("empty pattern list");
|
|
}
|
|
if (!isGlobList(globList)) {
|
|
throw new TypeError("empty glob list");
|
|
}
|
|
if (globList.length !== patternList.length) {
|
|
throw new TypeError("mismatched pattern list and glob list lengths");
|
|
}
|
|
this.length = patternList.length;
|
|
if (index < 0 || index >= this.length) {
|
|
throw new TypeError("index out of range");
|
|
}
|
|
this.#patternList = patternList;
|
|
this.#globList = globList;
|
|
this.#index = index;
|
|
this.#platform = platform;
|
|
if (this.#index === 0) {
|
|
if (this.isUNC()) {
|
|
const [p0, p1, p2, p3, ...prest] = this.#patternList;
|
|
const [g0, g1, g2, g3, ...grest] = this.#globList;
|
|
if (prest[0] === "") {
|
|
prest.shift();
|
|
grest.shift();
|
|
}
|
|
const p = [p0, p1, p2, p3, ""].join("/");
|
|
const g = [g0, g1, g2, g3, ""].join("/");
|
|
this.#patternList = [p, ...prest];
|
|
this.#globList = [g, ...grest];
|
|
this.length = this.#patternList.length;
|
|
} else if (this.isDrive() || this.isAbsolute()) {
|
|
const [p1, ...prest] = this.#patternList;
|
|
const [g1, ...grest] = this.#globList;
|
|
if (prest[0] === "") {
|
|
prest.shift();
|
|
grest.shift();
|
|
}
|
|
const p = p1 + "/";
|
|
const g = g1 + "/";
|
|
this.#patternList = [p, ...prest];
|
|
this.#globList = [g, ...grest];
|
|
this.length = this.#patternList.length;
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* The first entry in the parsed list of patterns
|
|
*/
|
|
pattern() {
|
|
return this.#patternList[this.#index];
|
|
}
|
|
/**
|
|
* true of if pattern() returns a string
|
|
*/
|
|
isString() {
|
|
return typeof this.#patternList[this.#index] === "string";
|
|
}
|
|
/**
|
|
* true of if pattern() returns GLOBSTAR
|
|
*/
|
|
isGlobstar() {
|
|
return this.#patternList[this.#index] === minimatch_1.GLOBSTAR;
|
|
}
|
|
/**
|
|
* true if pattern() returns a regexp
|
|
*/
|
|
isRegExp() {
|
|
return this.#patternList[this.#index] instanceof RegExp;
|
|
}
|
|
/**
|
|
* The /-joined set of glob parts that make up this pattern
|
|
*/
|
|
globString() {
|
|
return this.#globString = this.#globString || (this.#index === 0 ? this.isAbsolute() ? this.#globList[0] + this.#globList.slice(1).join("/") : this.#globList.join("/") : this.#globList.slice(this.#index).join("/"));
|
|
}
|
|
/**
|
|
* true if there are more pattern parts after this one
|
|
*/
|
|
hasMore() {
|
|
return this.length > this.#index + 1;
|
|
}
|
|
/**
|
|
* The rest of the pattern after this part, or null if this is the end
|
|
*/
|
|
rest() {
|
|
if (this.#rest !== void 0)
|
|
return this.#rest;
|
|
if (!this.hasMore())
|
|
return this.#rest = null;
|
|
this.#rest = new _Pattern(this.#patternList, this.#globList, this.#index + 1, this.#platform);
|
|
this.#rest.#isAbsolute = this.#isAbsolute;
|
|
this.#rest.#isUNC = this.#isUNC;
|
|
this.#rest.#isDrive = this.#isDrive;
|
|
return this.#rest;
|
|
}
|
|
/**
|
|
* true if the pattern represents a //unc/path/ on windows
|
|
*/
|
|
isUNC() {
|
|
const pl = this.#patternList;
|
|
return this.#isUNC !== void 0 ? this.#isUNC : this.#isUNC = this.#platform === "win32" && this.#index === 0 && pl[0] === "" && pl[1] === "" && typeof pl[2] === "string" && !!pl[2] && typeof pl[3] === "string" && !!pl[3];
|
|
}
|
|
// pattern like C:/...
|
|
// split = ['C:', ...]
|
|
// Enhancement: handle patterns like `c:*` to test the cwd
|
|
// in c: for *, but I don't know of a way to even figure out what that
|
|
// cwd is without actually chdir'ing into it?
|
|
/**
|
|
* True if the pattern starts with a drive letter on Windows
|
|
*/
|
|
isDrive() {
|
|
const pl = this.#patternList;
|
|
return this.#isDrive !== void 0 ? this.#isDrive : this.#isDrive = this.#platform === "win32" && this.#index === 0 && this.length > 1 && typeof pl[0] === "string" && /^[a-z]:$/i.test(pl[0]);
|
|
}
|
|
// pattern = '/' or '/...' or '/x/...'
|
|
// split = ['', ''] or ['', ...] or ['', 'x', ...]
|
|
// Drive and UNC both considered absolute on windows
|
|
/**
|
|
* True if the pattern is rooted on an absolute path
|
|
*/
|
|
isAbsolute() {
|
|
const pl = this.#patternList;
|
|
return this.#isAbsolute !== void 0 ? this.#isAbsolute : this.#isAbsolute = pl[0] === "" && pl.length > 1 || this.isDrive() || this.isUNC();
|
|
}
|
|
/**
|
|
* consume the root of the pattern, and return it
|
|
*/
|
|
root() {
|
|
const p = this.#patternList[0];
|
|
return typeof p === "string" && this.isAbsolute() && this.#index === 0 ? p : "";
|
|
}
|
|
/**
|
|
* Check to see if the current globstar pattern is allowed to follow
|
|
* a symbolic link.
|
|
*/
|
|
checkFollowGlobstar() {
|
|
return !(this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar);
|
|
}
|
|
/**
|
|
* Mark that the current globstar pattern is following a symbolic link
|
|
*/
|
|
markFollowGlobstar() {
|
|
if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar)
|
|
return false;
|
|
this.#followGlobstar = false;
|
|
return true;
|
|
}
|
|
};
|
|
exports.Pattern = Pattern;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/glob/dist/commonjs/ignore.js
|
|
var require_ignore = __commonJS({
|
|
"../../node_modules/glob/dist/commonjs/ignore.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Ignore = void 0;
|
|
var minimatch_1 = require_commonjs();
|
|
var pattern_js_1 = require_pattern();
|
|
var defaultPlatform = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
|
|
var Ignore = class {
|
|
relative;
|
|
relativeChildren;
|
|
absolute;
|
|
absoluteChildren;
|
|
platform;
|
|
mmopts;
|
|
constructor(ignored, { nobrace, nocase, noext, noglobstar, platform = defaultPlatform }) {
|
|
this.relative = [];
|
|
this.absolute = [];
|
|
this.relativeChildren = [];
|
|
this.absoluteChildren = [];
|
|
this.platform = platform;
|
|
this.mmopts = {
|
|
dot: true,
|
|
nobrace,
|
|
nocase,
|
|
noext,
|
|
noglobstar,
|
|
optimizationLevel: 2,
|
|
platform,
|
|
nocomment: true,
|
|
nonegate: true
|
|
};
|
|
for (const ign of ignored)
|
|
this.add(ign);
|
|
}
|
|
add(ign) {
|
|
const mm = new minimatch_1.Minimatch(ign, this.mmopts);
|
|
for (let i = 0; i < mm.set.length; i++) {
|
|
const parsed = mm.set[i];
|
|
const globParts = mm.globParts[i];
|
|
if (!parsed || !globParts) {
|
|
throw new Error("invalid pattern object");
|
|
}
|
|
while (parsed[0] === "." && globParts[0] === ".") {
|
|
parsed.shift();
|
|
globParts.shift();
|
|
}
|
|
const p = new pattern_js_1.Pattern(parsed, globParts, 0, this.platform);
|
|
const m = new minimatch_1.Minimatch(p.globString(), this.mmopts);
|
|
const children = globParts[globParts.length - 1] === "**";
|
|
const absolute = p.isAbsolute();
|
|
if (absolute)
|
|
this.absolute.push(m);
|
|
else
|
|
this.relative.push(m);
|
|
if (children) {
|
|
if (absolute)
|
|
this.absoluteChildren.push(m);
|
|
else
|
|
this.relativeChildren.push(m);
|
|
}
|
|
}
|
|
}
|
|
ignored(p) {
|
|
const fullpath = p.fullpath();
|
|
const fullpaths = `${fullpath}/`;
|
|
const relative = p.relative() || ".";
|
|
const relatives = `${relative}/`;
|
|
for (const m of this.relative) {
|
|
if (m.match(relative) || m.match(relatives))
|
|
return true;
|
|
}
|
|
for (const m of this.absolute) {
|
|
if (m.match(fullpath) || m.match(fullpaths))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
childrenIgnored(p) {
|
|
const fullpath = p.fullpath() + "/";
|
|
const relative = (p.relative() || ".") + "/";
|
|
for (const m of this.relativeChildren) {
|
|
if (m.match(relative))
|
|
return true;
|
|
}
|
|
for (const m of this.absoluteChildren) {
|
|
if (m.match(fullpath))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
exports.Ignore = Ignore;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/glob/dist/commonjs/processor.js
|
|
var require_processor = __commonJS({
|
|
"../../node_modules/glob/dist/commonjs/processor.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Processor = exports.SubWalks = exports.MatchRecord = exports.HasWalkedCache = void 0;
|
|
var minimatch_1 = require_commonjs();
|
|
var HasWalkedCache = class _HasWalkedCache {
|
|
store;
|
|
constructor(store = /* @__PURE__ */ new Map()) {
|
|
this.store = store;
|
|
}
|
|
copy() {
|
|
return new _HasWalkedCache(new Map(this.store));
|
|
}
|
|
hasWalked(target, pattern) {
|
|
return this.store.get(target.fullpath())?.has(pattern.globString());
|
|
}
|
|
storeWalked(target, pattern) {
|
|
const fullpath = target.fullpath();
|
|
const cached = this.store.get(fullpath);
|
|
if (cached)
|
|
cached.add(pattern.globString());
|
|
else
|
|
this.store.set(fullpath, /* @__PURE__ */ new Set([pattern.globString()]));
|
|
}
|
|
};
|
|
exports.HasWalkedCache = HasWalkedCache;
|
|
var MatchRecord = class {
|
|
store = /* @__PURE__ */ new Map();
|
|
add(target, absolute, ifDir) {
|
|
const n = (absolute ? 2 : 0) | (ifDir ? 1 : 0);
|
|
const current = this.store.get(target);
|
|
this.store.set(target, current === void 0 ? n : n & current);
|
|
}
|
|
// match, absolute, ifdir
|
|
entries() {
|
|
return [...this.store.entries()].map(([path, n]) => [
|
|
path,
|
|
!!(n & 2),
|
|
!!(n & 1)
|
|
]);
|
|
}
|
|
};
|
|
exports.MatchRecord = MatchRecord;
|
|
var SubWalks = class {
|
|
store = /* @__PURE__ */ new Map();
|
|
add(target, pattern) {
|
|
if (!target.canReaddir()) {
|
|
return;
|
|
}
|
|
const subs = this.store.get(target);
|
|
if (subs) {
|
|
if (!subs.find((p) => p.globString() === pattern.globString())) {
|
|
subs.push(pattern);
|
|
}
|
|
} else
|
|
this.store.set(target, [pattern]);
|
|
}
|
|
get(target) {
|
|
const subs = this.store.get(target);
|
|
if (!subs) {
|
|
throw new Error("attempting to walk unknown path");
|
|
}
|
|
return subs;
|
|
}
|
|
entries() {
|
|
return this.keys().map((k) => [k, this.store.get(k)]);
|
|
}
|
|
keys() {
|
|
return [...this.store.keys()].filter((t) => t.canReaddir());
|
|
}
|
|
};
|
|
exports.SubWalks = SubWalks;
|
|
var Processor = class _Processor {
|
|
hasWalkedCache;
|
|
matches = new MatchRecord();
|
|
subwalks = new SubWalks();
|
|
patterns;
|
|
follow;
|
|
dot;
|
|
opts;
|
|
constructor(opts, hasWalkedCache) {
|
|
this.opts = opts;
|
|
this.follow = !!opts.follow;
|
|
this.dot = !!opts.dot;
|
|
this.hasWalkedCache = hasWalkedCache ? hasWalkedCache.copy() : new HasWalkedCache();
|
|
}
|
|
processPatterns(target, patterns) {
|
|
this.patterns = patterns;
|
|
const processingSet = patterns.map((p) => [target, p]);
|
|
for (let [t, pattern] of processingSet) {
|
|
this.hasWalkedCache.storeWalked(t, pattern);
|
|
const root = pattern.root();
|
|
const absolute = pattern.isAbsolute() && this.opts.absolute !== false;
|
|
if (root) {
|
|
t = t.resolve(root === "/" && this.opts.root !== void 0 ? this.opts.root : root);
|
|
const rest2 = pattern.rest();
|
|
if (!rest2) {
|
|
this.matches.add(t, true, false);
|
|
continue;
|
|
} else {
|
|
pattern = rest2;
|
|
}
|
|
}
|
|
if (t.isENOENT())
|
|
continue;
|
|
let p;
|
|
let rest;
|
|
let changed = false;
|
|
while (typeof (p = pattern.pattern()) === "string" && (rest = pattern.rest())) {
|
|
const c = t.resolve(p);
|
|
t = c;
|
|
pattern = rest;
|
|
changed = true;
|
|
}
|
|
p = pattern.pattern();
|
|
rest = pattern.rest();
|
|
if (changed) {
|
|
if (this.hasWalkedCache.hasWalked(t, pattern))
|
|
continue;
|
|
this.hasWalkedCache.storeWalked(t, pattern);
|
|
}
|
|
if (typeof p === "string") {
|
|
const ifDir = p === ".." || p === "" || p === ".";
|
|
this.matches.add(t.resolve(p), absolute, ifDir);
|
|
continue;
|
|
} else if (p === minimatch_1.GLOBSTAR) {
|
|
if (!t.isSymbolicLink() || this.follow || pattern.checkFollowGlobstar()) {
|
|
this.subwalks.add(t, pattern);
|
|
}
|
|
const rp = rest?.pattern();
|
|
const rrest = rest?.rest();
|
|
if (!rest || (rp === "" || rp === ".") && !rrest) {
|
|
this.matches.add(t, absolute, rp === "" || rp === ".");
|
|
} else {
|
|
if (rp === "..") {
|
|
const tp = t.parent || t;
|
|
if (!rrest)
|
|
this.matches.add(tp, absolute, true);
|
|
else if (!this.hasWalkedCache.hasWalked(tp, rrest)) {
|
|
this.subwalks.add(tp, rrest);
|
|
}
|
|
}
|
|
}
|
|
} else if (p instanceof RegExp) {
|
|
this.subwalks.add(t, pattern);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
subwalkTargets() {
|
|
return this.subwalks.keys();
|
|
}
|
|
child() {
|
|
return new _Processor(this.opts, this.hasWalkedCache);
|
|
}
|
|
// return a new Processor containing the subwalks for each
|
|
// child entry, and a set of matches, and
|
|
// a hasWalkedCache that's a copy of this one
|
|
// then we're going to call
|
|
filterEntries(parent, entries) {
|
|
const patterns = this.subwalks.get(parent);
|
|
const results = this.child();
|
|
for (const e of entries) {
|
|
for (const pattern of patterns) {
|
|
const absolute = pattern.isAbsolute();
|
|
const p = pattern.pattern();
|
|
const rest = pattern.rest();
|
|
if (p === minimatch_1.GLOBSTAR) {
|
|
results.testGlobstar(e, pattern, rest, absolute);
|
|
} else if (p instanceof RegExp) {
|
|
results.testRegExp(e, p, rest, absolute);
|
|
} else {
|
|
results.testString(e, p, rest, absolute);
|
|
}
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
testGlobstar(e, pattern, rest, absolute) {
|
|
if (this.dot || !e.name.startsWith(".")) {
|
|
if (!pattern.hasMore()) {
|
|
this.matches.add(e, absolute, false);
|
|
}
|
|
if (e.canReaddir()) {
|
|
if (this.follow || !e.isSymbolicLink()) {
|
|
this.subwalks.add(e, pattern);
|
|
} else if (e.isSymbolicLink()) {
|
|
if (rest && pattern.checkFollowGlobstar()) {
|
|
this.subwalks.add(e, rest);
|
|
} else if (pattern.markFollowGlobstar()) {
|
|
this.subwalks.add(e, pattern);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (rest) {
|
|
const rp = rest.pattern();
|
|
if (typeof rp === "string" && // dots and empty were handled already
|
|
rp !== ".." && rp !== "" && rp !== ".") {
|
|
this.testString(e, rp, rest.rest(), absolute);
|
|
} else if (rp === "..") {
|
|
const ep = e.parent || e;
|
|
this.subwalks.add(ep, rest);
|
|
} else if (rp instanceof RegExp) {
|
|
this.testRegExp(e, rp, rest.rest(), absolute);
|
|
}
|
|
}
|
|
}
|
|
testRegExp(e, p, rest, absolute) {
|
|
if (!p.test(e.name))
|
|
return;
|
|
if (!rest) {
|
|
this.matches.add(e, absolute, false);
|
|
} else {
|
|
this.subwalks.add(e, rest);
|
|
}
|
|
}
|
|
testString(e, p, rest, absolute) {
|
|
if (!e.isNamed(p))
|
|
return;
|
|
if (!rest) {
|
|
this.matches.add(e, absolute, false);
|
|
} else {
|
|
this.subwalks.add(e, rest);
|
|
}
|
|
}
|
|
};
|
|
exports.Processor = Processor;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/glob/dist/commonjs/walker.js
|
|
var require_walker = __commonJS({
|
|
"../../node_modules/glob/dist/commonjs/walker.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.GlobStream = exports.GlobWalker = exports.GlobUtil = void 0;
|
|
var minipass_1 = require_commonjs3();
|
|
var ignore_js_1 = require_ignore();
|
|
var processor_js_1 = require_processor();
|
|
var makeIgnore = (ignore, opts) => typeof ignore === "string" ? new ignore_js_1.Ignore([ignore], opts) : Array.isArray(ignore) ? new ignore_js_1.Ignore(ignore, opts) : ignore;
|
|
var GlobUtil = class {
|
|
path;
|
|
patterns;
|
|
opts;
|
|
seen = /* @__PURE__ */ new Set();
|
|
paused = false;
|
|
aborted = false;
|
|
#onResume = [];
|
|
#ignore;
|
|
#sep;
|
|
signal;
|
|
maxDepth;
|
|
includeChildMatches;
|
|
constructor(patterns, path, opts) {
|
|
this.patterns = patterns;
|
|
this.path = path;
|
|
this.opts = opts;
|
|
this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
|
|
this.includeChildMatches = opts.includeChildMatches !== false;
|
|
if (opts.ignore || !this.includeChildMatches) {
|
|
this.#ignore = makeIgnore(opts.ignore ?? [], opts);
|
|
if (!this.includeChildMatches && typeof this.#ignore.add !== "function") {
|
|
const m = "cannot ignore child matches, ignore lacks add() method.";
|
|
throw new Error(m);
|
|
}
|
|
}
|
|
this.maxDepth = opts.maxDepth || Infinity;
|
|
if (opts.signal) {
|
|
this.signal = opts.signal;
|
|
this.signal.addEventListener("abort", () => {
|
|
this.#onResume.length = 0;
|
|
});
|
|
}
|
|
}
|
|
#ignored(path) {
|
|
return this.seen.has(path) || !!this.#ignore?.ignored?.(path);
|
|
}
|
|
#childrenIgnored(path) {
|
|
return !!this.#ignore?.childrenIgnored?.(path);
|
|
}
|
|
// backpressure mechanism
|
|
pause() {
|
|
this.paused = true;
|
|
}
|
|
resume() {
|
|
if (this.signal?.aborted)
|
|
return;
|
|
this.paused = false;
|
|
let fn = void 0;
|
|
while (!this.paused && (fn = this.#onResume.shift())) {
|
|
fn();
|
|
}
|
|
}
|
|
onResume(fn) {
|
|
if (this.signal?.aborted)
|
|
return;
|
|
if (!this.paused) {
|
|
fn();
|
|
} else {
|
|
this.#onResume.push(fn);
|
|
}
|
|
}
|
|
// do the requisite realpath/stat checking, and return the path
|
|
// to add or undefined to filter it out.
|
|
async matchCheck(e, ifDir) {
|
|
if (ifDir && this.opts.nodir)
|
|
return void 0;
|
|
let rpc;
|
|
if (this.opts.realpath) {
|
|
rpc = e.realpathCached() || await e.realpath();
|
|
if (!rpc)
|
|
return void 0;
|
|
e = rpc;
|
|
}
|
|
const needStat = e.isUnknown() || this.opts.stat;
|
|
const s = needStat ? await e.lstat() : e;
|
|
if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
|
|
const target = await s.realpath();
|
|
if (target && (target.isUnknown() || this.opts.stat)) {
|
|
await target.lstat();
|
|
}
|
|
}
|
|
return this.matchCheckTest(s, ifDir);
|
|
}
|
|
matchCheckTest(e, ifDir) {
|
|
return e && (this.maxDepth === Infinity || e.depth() <= this.maxDepth) && (!ifDir || e.canReaddir()) && (!this.opts.nodir || !e.isDirectory()) && (!this.opts.nodir || !this.opts.follow || !e.isSymbolicLink() || !e.realpathCached()?.isDirectory()) && !this.#ignored(e) ? e : void 0;
|
|
}
|
|
matchCheckSync(e, ifDir) {
|
|
if (ifDir && this.opts.nodir)
|
|
return void 0;
|
|
let rpc;
|
|
if (this.opts.realpath) {
|
|
rpc = e.realpathCached() || e.realpathSync();
|
|
if (!rpc)
|
|
return void 0;
|
|
e = rpc;
|
|
}
|
|
const needStat = e.isUnknown() || this.opts.stat;
|
|
const s = needStat ? e.lstatSync() : e;
|
|
if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
|
|
const target = s.realpathSync();
|
|
if (target && (target?.isUnknown() || this.opts.stat)) {
|
|
target.lstatSync();
|
|
}
|
|
}
|
|
return this.matchCheckTest(s, ifDir);
|
|
}
|
|
matchFinish(e, absolute) {
|
|
if (this.#ignored(e))
|
|
return;
|
|
if (!this.includeChildMatches && this.#ignore?.add) {
|
|
const ign = `${e.relativePosix()}/**`;
|
|
this.#ignore.add(ign);
|
|
}
|
|
const abs = this.opts.absolute === void 0 ? absolute : this.opts.absolute;
|
|
this.seen.add(e);
|
|
const mark = this.opts.mark && e.isDirectory() ? this.#sep : "";
|
|
if (this.opts.withFileTypes) {
|
|
this.matchEmit(e);
|
|
} else if (abs) {
|
|
const abs2 = this.opts.posix ? e.fullpathPosix() : e.fullpath();
|
|
this.matchEmit(abs2 + mark);
|
|
} else {
|
|
const rel = this.opts.posix ? e.relativePosix() : e.relative();
|
|
const pre = this.opts.dotRelative && !rel.startsWith(".." + this.#sep) ? "." + this.#sep : "";
|
|
this.matchEmit(!rel ? "." + mark : pre + rel + mark);
|
|
}
|
|
}
|
|
async match(e, absolute, ifDir) {
|
|
const p = await this.matchCheck(e, ifDir);
|
|
if (p)
|
|
this.matchFinish(p, absolute);
|
|
}
|
|
matchSync(e, absolute, ifDir) {
|
|
const p = this.matchCheckSync(e, ifDir);
|
|
if (p)
|
|
this.matchFinish(p, absolute);
|
|
}
|
|
walkCB(target, patterns, cb) {
|
|
if (this.signal?.aborted)
|
|
cb();
|
|
this.walkCB2(target, patterns, new processor_js_1.Processor(this.opts), cb);
|
|
}
|
|
walkCB2(target, patterns, processor, cb) {
|
|
if (this.#childrenIgnored(target))
|
|
return cb();
|
|
if (this.signal?.aborted)
|
|
cb();
|
|
if (this.paused) {
|
|
this.onResume(() => this.walkCB2(target, patterns, processor, cb));
|
|
return;
|
|
}
|
|
processor.processPatterns(target, patterns);
|
|
let tasks = 1;
|
|
const next = () => {
|
|
if (--tasks === 0)
|
|
cb();
|
|
};
|
|
for (const [m, absolute, ifDir] of processor.matches.entries()) {
|
|
if (this.#ignored(m))
|
|
continue;
|
|
tasks++;
|
|
this.match(m, absolute, ifDir).then(() => next());
|
|
}
|
|
for (const t of processor.subwalkTargets()) {
|
|
if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
|
|
continue;
|
|
}
|
|
tasks++;
|
|
const childrenCached = t.readdirCached();
|
|
if (t.calledReaddir())
|
|
this.walkCB3(t, childrenCached, processor, next);
|
|
else {
|
|
t.readdirCB((_, entries) => this.walkCB3(t, entries, processor, next), true);
|
|
}
|
|
}
|
|
next();
|
|
}
|
|
walkCB3(target, entries, processor, cb) {
|
|
processor = processor.filterEntries(target, entries);
|
|
let tasks = 1;
|
|
const next = () => {
|
|
if (--tasks === 0)
|
|
cb();
|
|
};
|
|
for (const [m, absolute, ifDir] of processor.matches.entries()) {
|
|
if (this.#ignored(m))
|
|
continue;
|
|
tasks++;
|
|
this.match(m, absolute, ifDir).then(() => next());
|
|
}
|
|
for (const [target2, patterns] of processor.subwalks.entries()) {
|
|
tasks++;
|
|
this.walkCB2(target2, patterns, processor.child(), next);
|
|
}
|
|
next();
|
|
}
|
|
walkCBSync(target, patterns, cb) {
|
|
if (this.signal?.aborted)
|
|
cb();
|
|
this.walkCB2Sync(target, patterns, new processor_js_1.Processor(this.opts), cb);
|
|
}
|
|
walkCB2Sync(target, patterns, processor, cb) {
|
|
if (this.#childrenIgnored(target))
|
|
return cb();
|
|
if (this.signal?.aborted)
|
|
cb();
|
|
if (this.paused) {
|
|
this.onResume(() => this.walkCB2Sync(target, patterns, processor, cb));
|
|
return;
|
|
}
|
|
processor.processPatterns(target, patterns);
|
|
let tasks = 1;
|
|
const next = () => {
|
|
if (--tasks === 0)
|
|
cb();
|
|
};
|
|
for (const [m, absolute, ifDir] of processor.matches.entries()) {
|
|
if (this.#ignored(m))
|
|
continue;
|
|
this.matchSync(m, absolute, ifDir);
|
|
}
|
|
for (const t of processor.subwalkTargets()) {
|
|
if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
|
|
continue;
|
|
}
|
|
tasks++;
|
|
const children = t.readdirSync();
|
|
this.walkCB3Sync(t, children, processor, next);
|
|
}
|
|
next();
|
|
}
|
|
walkCB3Sync(target, entries, processor, cb) {
|
|
processor = processor.filterEntries(target, entries);
|
|
let tasks = 1;
|
|
const next = () => {
|
|
if (--tasks === 0)
|
|
cb();
|
|
};
|
|
for (const [m, absolute, ifDir] of processor.matches.entries()) {
|
|
if (this.#ignored(m))
|
|
continue;
|
|
this.matchSync(m, absolute, ifDir);
|
|
}
|
|
for (const [target2, patterns] of processor.subwalks.entries()) {
|
|
tasks++;
|
|
this.walkCB2Sync(target2, patterns, processor.child(), next);
|
|
}
|
|
next();
|
|
}
|
|
};
|
|
exports.GlobUtil = GlobUtil;
|
|
var GlobWalker = class extends GlobUtil {
|
|
matches = /* @__PURE__ */ new Set();
|
|
constructor(patterns, path, opts) {
|
|
super(patterns, path, opts);
|
|
}
|
|
matchEmit(e) {
|
|
this.matches.add(e);
|
|
}
|
|
async walk() {
|
|
if (this.signal?.aborted)
|
|
throw this.signal.reason;
|
|
if (this.path.isUnknown()) {
|
|
await this.path.lstat();
|
|
}
|
|
await new Promise((res, rej) => {
|
|
this.walkCB(this.path, this.patterns, () => {
|
|
if (this.signal?.aborted) {
|
|
rej(this.signal.reason);
|
|
} else {
|
|
res(this.matches);
|
|
}
|
|
});
|
|
});
|
|
return this.matches;
|
|
}
|
|
walkSync() {
|
|
if (this.signal?.aborted)
|
|
throw this.signal.reason;
|
|
if (this.path.isUnknown()) {
|
|
this.path.lstatSync();
|
|
}
|
|
this.walkCBSync(this.path, this.patterns, () => {
|
|
if (this.signal?.aborted)
|
|
throw this.signal.reason;
|
|
});
|
|
return this.matches;
|
|
}
|
|
};
|
|
exports.GlobWalker = GlobWalker;
|
|
var GlobStream = class extends GlobUtil {
|
|
results;
|
|
constructor(patterns, path, opts) {
|
|
super(patterns, path, opts);
|
|
this.results = new minipass_1.Minipass({
|
|
signal: this.signal,
|
|
objectMode: true
|
|
});
|
|
this.results.on("drain", () => this.resume());
|
|
this.results.on("resume", () => this.resume());
|
|
}
|
|
matchEmit(e) {
|
|
this.results.write(e);
|
|
if (!this.results.flowing)
|
|
this.pause();
|
|
}
|
|
stream() {
|
|
const target = this.path;
|
|
if (target.isUnknown()) {
|
|
target.lstat().then(() => {
|
|
this.walkCB(target, this.patterns, () => this.results.end());
|
|
});
|
|
} else {
|
|
this.walkCB(target, this.patterns, () => this.results.end());
|
|
}
|
|
return this.results;
|
|
}
|
|
streamSync() {
|
|
if (this.path.isUnknown()) {
|
|
this.path.lstatSync();
|
|
}
|
|
this.walkCBSync(this.path, this.patterns, () => this.results.end());
|
|
return this.results;
|
|
}
|
|
};
|
|
exports.GlobStream = GlobStream;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/glob/dist/commonjs/glob.js
|
|
var require_glob = __commonJS({
|
|
"../../node_modules/glob/dist/commonjs/glob.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Glob = void 0;
|
|
var minimatch_1 = require_commonjs();
|
|
var node_url_1 = __require("bare-url");
|
|
var path_scurry_1 = require_commonjs4();
|
|
var pattern_js_1 = require_pattern();
|
|
var walker_js_1 = require_walker();
|
|
var defaultPlatform = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
|
|
var Glob = class {
|
|
absolute;
|
|
cwd;
|
|
root;
|
|
dot;
|
|
dotRelative;
|
|
follow;
|
|
ignore;
|
|
magicalBraces;
|
|
mark;
|
|
matchBase;
|
|
maxDepth;
|
|
nobrace;
|
|
nocase;
|
|
nodir;
|
|
noext;
|
|
noglobstar;
|
|
pattern;
|
|
platform;
|
|
realpath;
|
|
scurry;
|
|
stat;
|
|
signal;
|
|
windowsPathsNoEscape;
|
|
withFileTypes;
|
|
includeChildMatches;
|
|
/**
|
|
* The options provided to the constructor.
|
|
*/
|
|
opts;
|
|
/**
|
|
* An array of parsed immutable {@link Pattern} objects.
|
|
*/
|
|
patterns;
|
|
/**
|
|
* All options are stored as properties on the `Glob` object.
|
|
*
|
|
* See {@link GlobOptions} for full options descriptions.
|
|
*
|
|
* Note that a previous `Glob` object can be passed as the
|
|
* `GlobOptions` to another `Glob` instantiation to re-use settings
|
|
* and caches with a new pattern.
|
|
*
|
|
* Traversal functions can be called multiple times to run the walk
|
|
* again.
|
|
*/
|
|
constructor(pattern, opts) {
|
|
if (!opts)
|
|
throw new TypeError("glob options required");
|
|
this.withFileTypes = !!opts.withFileTypes;
|
|
this.signal = opts.signal;
|
|
this.follow = !!opts.follow;
|
|
this.dot = !!opts.dot;
|
|
this.dotRelative = !!opts.dotRelative;
|
|
this.nodir = !!opts.nodir;
|
|
this.mark = !!opts.mark;
|
|
if (!opts.cwd) {
|
|
this.cwd = "";
|
|
} else if (opts.cwd instanceof URL || opts.cwd.startsWith("file://")) {
|
|
opts.cwd = (0, node_url_1.fileURLToPath)(opts.cwd);
|
|
}
|
|
this.cwd = opts.cwd || "";
|
|
this.root = opts.root;
|
|
this.magicalBraces = !!opts.magicalBraces;
|
|
this.nobrace = !!opts.nobrace;
|
|
this.noext = !!opts.noext;
|
|
this.realpath = !!opts.realpath;
|
|
this.absolute = opts.absolute;
|
|
this.includeChildMatches = opts.includeChildMatches !== false;
|
|
this.noglobstar = !!opts.noglobstar;
|
|
this.matchBase = !!opts.matchBase;
|
|
this.maxDepth = typeof opts.maxDepth === "number" ? opts.maxDepth : Infinity;
|
|
this.stat = !!opts.stat;
|
|
this.ignore = opts.ignore;
|
|
if (this.withFileTypes && this.absolute !== void 0) {
|
|
throw new Error("cannot set absolute and withFileTypes:true");
|
|
}
|
|
if (typeof pattern === "string") {
|
|
pattern = [pattern];
|
|
}
|
|
this.windowsPathsNoEscape = !!opts.windowsPathsNoEscape || opts.allowWindowsEscape === false;
|
|
if (this.windowsPathsNoEscape) {
|
|
pattern = pattern.map((p) => p.replace(/\\/g, "/"));
|
|
}
|
|
if (this.matchBase) {
|
|
if (opts.noglobstar) {
|
|
throw new TypeError("base matching requires globstar");
|
|
}
|
|
pattern = pattern.map((p) => p.includes("/") ? p : `./**/${p}`);
|
|
}
|
|
this.pattern = pattern;
|
|
this.platform = opts.platform || defaultPlatform;
|
|
this.opts = { ...opts, platform: this.platform };
|
|
if (opts.scurry) {
|
|
this.scurry = opts.scurry;
|
|
if (opts.nocase !== void 0 && opts.nocase !== opts.scurry.nocase) {
|
|
throw new Error("nocase option contradicts provided scurry option");
|
|
}
|
|
} else {
|
|
const Scurry = opts.platform === "win32" ? path_scurry_1.PathScurryWin32 : opts.platform === "darwin" ? path_scurry_1.PathScurryDarwin : opts.platform ? path_scurry_1.PathScurryPosix : path_scurry_1.PathScurry;
|
|
this.scurry = new Scurry(this.cwd, {
|
|
nocase: opts.nocase,
|
|
fs: opts.fs
|
|
});
|
|
}
|
|
this.nocase = this.scurry.nocase;
|
|
const nocaseMagicOnly = this.platform === "darwin" || this.platform === "win32";
|
|
const mmo = {
|
|
// default nocase based on platform
|
|
...opts,
|
|
dot: this.dot,
|
|
matchBase: this.matchBase,
|
|
nobrace: this.nobrace,
|
|
nocase: this.nocase,
|
|
nocaseMagicOnly,
|
|
nocomment: true,
|
|
noext: this.noext,
|
|
nonegate: true,
|
|
optimizationLevel: 2,
|
|
platform: this.platform,
|
|
windowsPathsNoEscape: this.windowsPathsNoEscape,
|
|
debug: !!this.opts.debug
|
|
};
|
|
const mms = this.pattern.map((p) => new minimatch_1.Minimatch(p, mmo));
|
|
const [matchSet, globParts] = mms.reduce((set, m) => {
|
|
set[0].push(...m.set);
|
|
set[1].push(...m.globParts);
|
|
return set;
|
|
}, [[], []]);
|
|
this.patterns = matchSet.map((set, i) => {
|
|
const g = globParts[i];
|
|
if (!g)
|
|
throw new Error("invalid pattern object");
|
|
return new pattern_js_1.Pattern(set, g, 0, this.platform);
|
|
});
|
|
}
|
|
async walk() {
|
|
return [
|
|
...await new walker_js_1.GlobWalker(this.patterns, this.scurry.cwd, {
|
|
...this.opts,
|
|
maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
|
|
platform: this.platform,
|
|
nocase: this.nocase,
|
|
includeChildMatches: this.includeChildMatches
|
|
}).walk()
|
|
];
|
|
}
|
|
walkSync() {
|
|
return [
|
|
...new walker_js_1.GlobWalker(this.patterns, this.scurry.cwd, {
|
|
...this.opts,
|
|
maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
|
|
platform: this.platform,
|
|
nocase: this.nocase,
|
|
includeChildMatches: this.includeChildMatches
|
|
}).walkSync()
|
|
];
|
|
}
|
|
stream() {
|
|
return new walker_js_1.GlobStream(this.patterns, this.scurry.cwd, {
|
|
...this.opts,
|
|
maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
|
|
platform: this.platform,
|
|
nocase: this.nocase,
|
|
includeChildMatches: this.includeChildMatches
|
|
}).stream();
|
|
}
|
|
streamSync() {
|
|
return new walker_js_1.GlobStream(this.patterns, this.scurry.cwd, {
|
|
...this.opts,
|
|
maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
|
|
platform: this.platform,
|
|
nocase: this.nocase,
|
|
includeChildMatches: this.includeChildMatches
|
|
}).streamSync();
|
|
}
|
|
/**
|
|
* Default sync iteration function. Returns a Generator that
|
|
* iterates over the results.
|
|
*/
|
|
iterateSync() {
|
|
return this.streamSync()[Symbol.iterator]();
|
|
}
|
|
[Symbol.iterator]() {
|
|
return this.iterateSync();
|
|
}
|
|
/**
|
|
* Default async iteration function. Returns an AsyncGenerator that
|
|
* iterates over the results.
|
|
*/
|
|
iterate() {
|
|
return this.stream()[Symbol.asyncIterator]();
|
|
}
|
|
[Symbol.asyncIterator]() {
|
|
return this.iterate();
|
|
}
|
|
};
|
|
exports.Glob = Glob;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/glob/dist/commonjs/has-magic.js
|
|
var require_has_magic = __commonJS({
|
|
"../../node_modules/glob/dist/commonjs/has-magic.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.hasMagic = void 0;
|
|
var minimatch_1 = require_commonjs();
|
|
var hasMagic = (pattern, options = {}) => {
|
|
if (!Array.isArray(pattern)) {
|
|
pattern = [pattern];
|
|
}
|
|
for (const p of pattern) {
|
|
if (new minimatch_1.Minimatch(p, options).hasMagic())
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
exports.hasMagic = hasMagic;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/glob/dist/commonjs/index.js
|
|
var require_commonjs5 = __commonJS({
|
|
"../../node_modules/glob/dist/commonjs/index.js"(exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.glob = exports.sync = exports.iterate = exports.iterateSync = exports.stream = exports.streamSync = exports.Ignore = exports.hasMagic = exports.Glob = exports.unescape = exports.escape = void 0;
|
|
exports.globStreamSync = globStreamSync;
|
|
exports.globStream = globStream;
|
|
exports.globSync = globSync;
|
|
exports.globIterateSync = globIterateSync;
|
|
exports.globIterate = globIterate;
|
|
var minimatch_1 = require_commonjs();
|
|
var glob_js_1 = require_glob();
|
|
var has_magic_js_1 = require_has_magic();
|
|
var minimatch_2 = require_commonjs();
|
|
Object.defineProperty(exports, "escape", { enumerable: true, get: function() {
|
|
return minimatch_2.escape;
|
|
} });
|
|
Object.defineProperty(exports, "unescape", { enumerable: true, get: function() {
|
|
return minimatch_2.unescape;
|
|
} });
|
|
var glob_js_2 = require_glob();
|
|
Object.defineProperty(exports, "Glob", { enumerable: true, get: function() {
|
|
return glob_js_2.Glob;
|
|
} });
|
|
var has_magic_js_2 = require_has_magic();
|
|
Object.defineProperty(exports, "hasMagic", { enumerable: true, get: function() {
|
|
return has_magic_js_2.hasMagic;
|
|
} });
|
|
var ignore_js_1 = require_ignore();
|
|
Object.defineProperty(exports, "Ignore", { enumerable: true, get: function() {
|
|
return ignore_js_1.Ignore;
|
|
} });
|
|
function globStreamSync(pattern, options = {}) {
|
|
return new glob_js_1.Glob(pattern, options).streamSync();
|
|
}
|
|
function globStream(pattern, options = {}) {
|
|
return new glob_js_1.Glob(pattern, options).stream();
|
|
}
|
|
function globSync(pattern, options = {}) {
|
|
return new glob_js_1.Glob(pattern, options).walkSync();
|
|
}
|
|
async function glob_(pattern, options = {}) {
|
|
return new glob_js_1.Glob(pattern, options).walk();
|
|
}
|
|
function globIterateSync(pattern, options = {}) {
|
|
return new glob_js_1.Glob(pattern, options).iterateSync();
|
|
}
|
|
function globIterate(pattern, options = {}) {
|
|
return new glob_js_1.Glob(pattern, options).iterate();
|
|
}
|
|
exports.streamSync = globStreamSync;
|
|
exports.stream = Object.assign(globStream, { sync: globStreamSync });
|
|
exports.iterateSync = globIterateSync;
|
|
exports.iterate = Object.assign(globIterate, {
|
|
sync: globIterateSync
|
|
});
|
|
exports.sync = Object.assign(globSync, {
|
|
stream: globStreamSync,
|
|
iterate: globIterateSync
|
|
});
|
|
exports.glob = Object.assign(glob_, {
|
|
glob: glob_,
|
|
globSync,
|
|
sync: exports.sync,
|
|
globStream,
|
|
stream: exports.stream,
|
|
globStreamSync,
|
|
streamSync: exports.streamSync,
|
|
globIterate,
|
|
iterate: exports.iterate,
|
|
globIterateSync,
|
|
iterateSync: exports.iterateSync,
|
|
Glob: glob_js_1.Glob,
|
|
hasMagic: has_magic_js_1.hasMagic,
|
|
escape: minimatch_1.escape,
|
|
unescape: minimatch_1.unescape
|
|
});
|
|
exports.glob.glob = exports.glob;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/run.js
|
|
var require_run = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/run.js"(exports, module) {
|
|
var path = __require("path");
|
|
var { globSync } = require_commonjs5();
|
|
var launch = require_launch();
|
|
var adb = require_adb();
|
|
module.exports = function run(apk, opts = {}) {
|
|
const {
|
|
device = null,
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
if (apk === null) {
|
|
[apk = null] = globSync(path.join(cwd, "**/*.apk"), {
|
|
ignore: [
|
|
"**/vendor/**",
|
|
// Ignore unsigned packages
|
|
"**/*-unsigned.apk"
|
|
]
|
|
});
|
|
if (apk === null) {
|
|
throw new Error("no .apk found");
|
|
}
|
|
}
|
|
const id = launch(device, opts);
|
|
apk = path.resolve(cwd, apk);
|
|
adb.install(id, apk, opts);
|
|
adb.start(id, apk, opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/graceful-fs/polyfills.js
|
|
var require_polyfills = __commonJS({
|
|
"../../node_modules/graceful-fs/polyfills.js"(exports, module) {
|
|
var constants = __require("constants");
|
|
var origCwd = process.cwd;
|
|
var cwd = null;
|
|
var platform = process.env.GRACEFUL_FS_PLATFORM || process.platform;
|
|
process.cwd = function() {
|
|
if (!cwd)
|
|
cwd = origCwd.call(process);
|
|
return cwd;
|
|
};
|
|
try {
|
|
process.cwd();
|
|
} catch (er) {
|
|
}
|
|
if (typeof process.chdir === "function") {
|
|
chdir = process.chdir;
|
|
process.chdir = function(d) {
|
|
cwd = null;
|
|
chdir.call(process, d);
|
|
};
|
|
if (Object.setPrototypeOf) Object.setPrototypeOf(process.chdir, chdir);
|
|
}
|
|
var chdir;
|
|
module.exports = patch;
|
|
function patch(fs) {
|
|
if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
|
patchLchmod(fs);
|
|
}
|
|
if (!fs.lutimes) {
|
|
patchLutimes(fs);
|
|
}
|
|
fs.chown = chownFix(fs.chown);
|
|
fs.fchown = chownFix(fs.fchown);
|
|
fs.lchown = chownFix(fs.lchown);
|
|
fs.chmod = chmodFix(fs.chmod);
|
|
fs.fchmod = chmodFix(fs.fchmod);
|
|
fs.lchmod = chmodFix(fs.lchmod);
|
|
fs.chownSync = chownFixSync(fs.chownSync);
|
|
fs.fchownSync = chownFixSync(fs.fchownSync);
|
|
fs.lchownSync = chownFixSync(fs.lchownSync);
|
|
fs.chmodSync = chmodFixSync(fs.chmodSync);
|
|
fs.fchmodSync = chmodFixSync(fs.fchmodSync);
|
|
fs.lchmodSync = chmodFixSync(fs.lchmodSync);
|
|
fs.stat = statFix(fs.stat);
|
|
fs.fstat = statFix(fs.fstat);
|
|
fs.lstat = statFix(fs.lstat);
|
|
fs.statSync = statFixSync(fs.statSync);
|
|
fs.fstatSync = statFixSync(fs.fstatSync);
|
|
fs.lstatSync = statFixSync(fs.lstatSync);
|
|
if (fs.chmod && !fs.lchmod) {
|
|
fs.lchmod = function(path, mode, cb) {
|
|
if (cb) process.nextTick(cb);
|
|
};
|
|
fs.lchmodSync = function() {
|
|
};
|
|
}
|
|
if (fs.chown && !fs.lchown) {
|
|
fs.lchown = function(path, uid, gid, cb) {
|
|
if (cb) process.nextTick(cb);
|
|
};
|
|
fs.lchownSync = function() {
|
|
};
|
|
}
|
|
if (platform === "win32") {
|
|
fs.rename = typeof fs.rename !== "function" ? fs.rename : (function(fs$rename) {
|
|
function rename(from, to, cb) {
|
|
var start = Date.now();
|
|
var backoff = 0;
|
|
fs$rename(from, to, function CB(er) {
|
|
if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 6e4) {
|
|
setTimeout(function() {
|
|
fs.stat(to, function(stater, st) {
|
|
if (stater && stater.code === "ENOENT")
|
|
fs$rename(from, to, CB);
|
|
else
|
|
cb(er);
|
|
});
|
|
}, backoff);
|
|
if (backoff < 100)
|
|
backoff += 10;
|
|
return;
|
|
}
|
|
if (cb) cb(er);
|
|
});
|
|
}
|
|
if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename);
|
|
return rename;
|
|
})(fs.rename);
|
|
}
|
|
fs.read = typeof fs.read !== "function" ? fs.read : (function(fs$read) {
|
|
function read(fd, buffer, offset, length, position, callback_) {
|
|
var callback;
|
|
if (callback_ && typeof callback_ === "function") {
|
|
var eagCounter = 0;
|
|
callback = function(er, _, __) {
|
|
if (er && er.code === "EAGAIN" && eagCounter < 10) {
|
|
eagCounter++;
|
|
return fs$read.call(fs, fd, buffer, offset, length, position, callback);
|
|
}
|
|
callback_.apply(this, arguments);
|
|
};
|
|
}
|
|
return fs$read.call(fs, fd, buffer, offset, length, position, callback);
|
|
}
|
|
if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read);
|
|
return read;
|
|
})(fs.read);
|
|
fs.readSync = typeof fs.readSync !== "function" ? fs.readSync : /* @__PURE__ */ (function(fs$readSync) {
|
|
return function(fd, buffer, offset, length, position) {
|
|
var eagCounter = 0;
|
|
while (true) {
|
|
try {
|
|
return fs$readSync.call(fs, fd, buffer, offset, length, position);
|
|
} catch (er) {
|
|
if (er.code === "EAGAIN" && eagCounter < 10) {
|
|
eagCounter++;
|
|
continue;
|
|
}
|
|
throw er;
|
|
}
|
|
}
|
|
};
|
|
})(fs.readSync);
|
|
function patchLchmod(fs2) {
|
|
fs2.lchmod = function(path, mode, callback) {
|
|
fs2.open(
|
|
path,
|
|
constants.O_WRONLY | constants.O_SYMLINK,
|
|
mode,
|
|
function(err, fd) {
|
|
if (err) {
|
|
if (callback) callback(err);
|
|
return;
|
|
}
|
|
fs2.fchmod(fd, mode, function(err2) {
|
|
fs2.close(fd, function(err22) {
|
|
if (callback) callback(err2 || err22);
|
|
});
|
|
});
|
|
}
|
|
);
|
|
};
|
|
fs2.lchmodSync = function(path, mode) {
|
|
var fd = fs2.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode);
|
|
var threw = true;
|
|
var ret;
|
|
try {
|
|
ret = fs2.fchmodSync(fd, mode);
|
|
threw = false;
|
|
} finally {
|
|
if (threw) {
|
|
try {
|
|
fs2.closeSync(fd);
|
|
} catch (er) {
|
|
}
|
|
} else {
|
|
fs2.closeSync(fd);
|
|
}
|
|
}
|
|
return ret;
|
|
};
|
|
}
|
|
function patchLutimes(fs2) {
|
|
if (constants.hasOwnProperty("O_SYMLINK") && fs2.futimes) {
|
|
fs2.lutimes = function(path, at, mt, cb) {
|
|
fs2.open(path, constants.O_SYMLINK, function(er, fd) {
|
|
if (er) {
|
|
if (cb) cb(er);
|
|
return;
|
|
}
|
|
fs2.futimes(fd, at, mt, function(er2) {
|
|
fs2.close(fd, function(er22) {
|
|
if (cb) cb(er2 || er22);
|
|
});
|
|
});
|
|
});
|
|
};
|
|
fs2.lutimesSync = function(path, at, mt) {
|
|
var fd = fs2.openSync(path, constants.O_SYMLINK);
|
|
var ret;
|
|
var threw = true;
|
|
try {
|
|
ret = fs2.futimesSync(fd, at, mt);
|
|
threw = false;
|
|
} finally {
|
|
if (threw) {
|
|
try {
|
|
fs2.closeSync(fd);
|
|
} catch (er) {
|
|
}
|
|
} else {
|
|
fs2.closeSync(fd);
|
|
}
|
|
}
|
|
return ret;
|
|
};
|
|
} else if (fs2.futimes) {
|
|
fs2.lutimes = function(_a, _b, _c, cb) {
|
|
if (cb) process.nextTick(cb);
|
|
};
|
|
fs2.lutimesSync = function() {
|
|
};
|
|
}
|
|
}
|
|
function chmodFix(orig) {
|
|
if (!orig) return orig;
|
|
return function(target, mode, cb) {
|
|
return orig.call(fs, target, mode, function(er) {
|
|
if (chownErOk(er)) er = null;
|
|
if (cb) cb.apply(this, arguments);
|
|
});
|
|
};
|
|
}
|
|
function chmodFixSync(orig) {
|
|
if (!orig) return orig;
|
|
return function(target, mode) {
|
|
try {
|
|
return orig.call(fs, target, mode);
|
|
} catch (er) {
|
|
if (!chownErOk(er)) throw er;
|
|
}
|
|
};
|
|
}
|
|
function chownFix(orig) {
|
|
if (!orig) return orig;
|
|
return function(target, uid, gid, cb) {
|
|
return orig.call(fs, target, uid, gid, function(er) {
|
|
if (chownErOk(er)) er = null;
|
|
if (cb) cb.apply(this, arguments);
|
|
});
|
|
};
|
|
}
|
|
function chownFixSync(orig) {
|
|
if (!orig) return orig;
|
|
return function(target, uid, gid) {
|
|
try {
|
|
return orig.call(fs, target, uid, gid);
|
|
} catch (er) {
|
|
if (!chownErOk(er)) throw er;
|
|
}
|
|
};
|
|
}
|
|
function statFix(orig) {
|
|
if (!orig) return orig;
|
|
return function(target, options, cb) {
|
|
if (typeof options === "function") {
|
|
cb = options;
|
|
options = null;
|
|
}
|
|
function callback(er, stats) {
|
|
if (stats) {
|
|
if (stats.uid < 0) stats.uid += 4294967296;
|
|
if (stats.gid < 0) stats.gid += 4294967296;
|
|
}
|
|
if (cb) cb.apply(this, arguments);
|
|
}
|
|
return options ? orig.call(fs, target, options, callback) : orig.call(fs, target, callback);
|
|
};
|
|
}
|
|
function statFixSync(orig) {
|
|
if (!orig) return orig;
|
|
return function(target, options) {
|
|
var stats = options ? orig.call(fs, target, options) : orig.call(fs, target);
|
|
if (stats) {
|
|
if (stats.uid < 0) stats.uid += 4294967296;
|
|
if (stats.gid < 0) stats.gid += 4294967296;
|
|
}
|
|
return stats;
|
|
};
|
|
}
|
|
function chownErOk(er) {
|
|
if (!er)
|
|
return true;
|
|
if (er.code === "ENOSYS")
|
|
return true;
|
|
var nonroot = !process.getuid || process.getuid() !== 0;
|
|
if (nonroot) {
|
|
if (er.code === "EINVAL" || er.code === "EPERM")
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/graceful-fs/legacy-streams.js
|
|
var require_legacy_streams = __commonJS({
|
|
"../../node_modules/graceful-fs/legacy-streams.js"(exports, module) {
|
|
var Stream = __require("stream").Stream;
|
|
module.exports = legacy;
|
|
function legacy(fs) {
|
|
return {
|
|
ReadStream,
|
|
WriteStream
|
|
};
|
|
function ReadStream(path, options) {
|
|
if (!(this instanceof ReadStream)) return new ReadStream(path, options);
|
|
Stream.call(this);
|
|
var self2 = this;
|
|
this.path = path;
|
|
this.fd = null;
|
|
this.readable = true;
|
|
this.paused = false;
|
|
this.flags = "r";
|
|
this.mode = 438;
|
|
this.bufferSize = 64 * 1024;
|
|
options = options || {};
|
|
var keys = Object.keys(options);
|
|
for (var index = 0, length = keys.length; index < length; index++) {
|
|
var key = keys[index];
|
|
this[key] = options[key];
|
|
}
|
|
if (this.encoding) this.setEncoding(this.encoding);
|
|
if (this.start !== void 0) {
|
|
if ("number" !== typeof this.start) {
|
|
throw TypeError("start must be a Number");
|
|
}
|
|
if (this.end === void 0) {
|
|
this.end = Infinity;
|
|
} else if ("number" !== typeof this.end) {
|
|
throw TypeError("end must be a Number");
|
|
}
|
|
if (this.start > this.end) {
|
|
throw new Error("start must be <= end");
|
|
}
|
|
this.pos = this.start;
|
|
}
|
|
if (this.fd !== null) {
|
|
process.nextTick(function() {
|
|
self2._read();
|
|
});
|
|
return;
|
|
}
|
|
fs.open(this.path, this.flags, this.mode, function(err, fd) {
|
|
if (err) {
|
|
self2.emit("error", err);
|
|
self2.readable = false;
|
|
return;
|
|
}
|
|
self2.fd = fd;
|
|
self2.emit("open", fd);
|
|
self2._read();
|
|
});
|
|
}
|
|
function WriteStream(path, options) {
|
|
if (!(this instanceof WriteStream)) return new WriteStream(path, options);
|
|
Stream.call(this);
|
|
this.path = path;
|
|
this.fd = null;
|
|
this.writable = true;
|
|
this.flags = "w";
|
|
this.encoding = "binary";
|
|
this.mode = 438;
|
|
this.bytesWritten = 0;
|
|
options = options || {};
|
|
var keys = Object.keys(options);
|
|
for (var index = 0, length = keys.length; index < length; index++) {
|
|
var key = keys[index];
|
|
this[key] = options[key];
|
|
}
|
|
if (this.start !== void 0) {
|
|
if ("number" !== typeof this.start) {
|
|
throw TypeError("start must be a Number");
|
|
}
|
|
if (this.start < 0) {
|
|
throw new Error("start must be >= zero");
|
|
}
|
|
this.pos = this.start;
|
|
}
|
|
this.busy = false;
|
|
this._queue = [];
|
|
if (this.fd === null) {
|
|
this._open = fs.open;
|
|
this._queue.push([this._open, this.path, this.flags, this.mode, void 0]);
|
|
this.flush();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/graceful-fs/clone.js
|
|
var require_clone = __commonJS({
|
|
"../../node_modules/graceful-fs/clone.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = clone;
|
|
var getPrototypeOf = Object.getPrototypeOf || function(obj) {
|
|
return obj.__proto__;
|
|
};
|
|
function clone(obj) {
|
|
if (obj === null || typeof obj !== "object")
|
|
return obj;
|
|
if (obj instanceof Object)
|
|
var copy = { __proto__: getPrototypeOf(obj) };
|
|
else
|
|
var copy = /* @__PURE__ */ Object.create(null);
|
|
Object.getOwnPropertyNames(obj).forEach(function(key) {
|
|
Object.defineProperty(copy, key, Object.getOwnPropertyDescriptor(obj, key));
|
|
});
|
|
return copy;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/graceful-fs/graceful-fs.js
|
|
var require_graceful_fs = __commonJS({
|
|
"../../node_modules/graceful-fs/graceful-fs.js"(exports, module) {
|
|
var fs = __require("fs");
|
|
var polyfills = require_polyfills();
|
|
var legacy = require_legacy_streams();
|
|
var clone = require_clone();
|
|
var util = __require("util");
|
|
var gracefulQueue;
|
|
var previousSymbol;
|
|
if (typeof Symbol === "function" && typeof Symbol.for === "function") {
|
|
gracefulQueue = Symbol.for("graceful-fs.queue");
|
|
previousSymbol = Symbol.for("graceful-fs.previous");
|
|
} else {
|
|
gracefulQueue = "___graceful-fs.queue";
|
|
previousSymbol = "___graceful-fs.previous";
|
|
}
|
|
function noop() {
|
|
}
|
|
function publishQueue(context, queue2) {
|
|
Object.defineProperty(context, gracefulQueue, {
|
|
get: function() {
|
|
return queue2;
|
|
}
|
|
});
|
|
}
|
|
var debug = noop;
|
|
if (util.debuglog)
|
|
debug = util.debuglog("gfs4");
|
|
else if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || ""))
|
|
debug = function() {
|
|
var m = util.format.apply(util, arguments);
|
|
m = "GFS4: " + m.split(/\n/).join("\nGFS4: ");
|
|
console.error(m);
|
|
};
|
|
if (!fs[gracefulQueue]) {
|
|
queue = global[gracefulQueue] || [];
|
|
publishQueue(fs, queue);
|
|
fs.close = (function(fs$close) {
|
|
function close(fd, cb) {
|
|
return fs$close.call(fs, fd, function(err) {
|
|
if (!err) {
|
|
resetQueue();
|
|
}
|
|
if (typeof cb === "function")
|
|
cb.apply(this, arguments);
|
|
});
|
|
}
|
|
Object.defineProperty(close, previousSymbol, {
|
|
value: fs$close
|
|
});
|
|
return close;
|
|
})(fs.close);
|
|
fs.closeSync = (function(fs$closeSync) {
|
|
function closeSync(fd) {
|
|
fs$closeSync.apply(fs, arguments);
|
|
resetQueue();
|
|
}
|
|
Object.defineProperty(closeSync, previousSymbol, {
|
|
value: fs$closeSync
|
|
});
|
|
return closeSync;
|
|
})(fs.closeSync);
|
|
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
|
|
process.on("exit", function() {
|
|
debug(fs[gracefulQueue]);
|
|
__require("assert").equal(fs[gracefulQueue].length, 0);
|
|
});
|
|
}
|
|
}
|
|
var queue;
|
|
if (!global[gracefulQueue]) {
|
|
publishQueue(global, fs[gracefulQueue]);
|
|
}
|
|
module.exports = patch(clone(fs));
|
|
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs.__patched) {
|
|
module.exports = patch(fs);
|
|
fs.__patched = true;
|
|
}
|
|
function patch(fs2) {
|
|
polyfills(fs2);
|
|
fs2.gracefulify = patch;
|
|
fs2.createReadStream = createReadStream;
|
|
fs2.createWriteStream = createWriteStream;
|
|
var fs$readFile = fs2.readFile;
|
|
fs2.readFile = readFile;
|
|
function readFile(path, options, cb) {
|
|
if (typeof options === "function")
|
|
cb = options, options = null;
|
|
return go$readFile(path, options, cb);
|
|
function go$readFile(path2, options2, cb2, startTime) {
|
|
return fs$readFile(path2, options2, function(err) {
|
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
enqueue([go$readFile, [path2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
else {
|
|
if (typeof cb2 === "function")
|
|
cb2.apply(this, arguments);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
var fs$writeFile = fs2.writeFile;
|
|
fs2.writeFile = writeFile;
|
|
function writeFile(path, data, options, cb) {
|
|
if (typeof options === "function")
|
|
cb = options, options = null;
|
|
return go$writeFile(path, data, options, cb);
|
|
function go$writeFile(path2, data2, options2, cb2, startTime) {
|
|
return fs$writeFile(path2, data2, options2, function(err) {
|
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
enqueue([go$writeFile, [path2, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
else {
|
|
if (typeof cb2 === "function")
|
|
cb2.apply(this, arguments);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
var fs$appendFile = fs2.appendFile;
|
|
if (fs$appendFile)
|
|
fs2.appendFile = appendFile;
|
|
function appendFile(path, data, options, cb) {
|
|
if (typeof options === "function")
|
|
cb = options, options = null;
|
|
return go$appendFile(path, data, options, cb);
|
|
function go$appendFile(path2, data2, options2, cb2, startTime) {
|
|
return fs$appendFile(path2, data2, options2, function(err) {
|
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
enqueue([go$appendFile, [path2, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
else {
|
|
if (typeof cb2 === "function")
|
|
cb2.apply(this, arguments);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
var fs$copyFile = fs2.copyFile;
|
|
if (fs$copyFile)
|
|
fs2.copyFile = copyFile;
|
|
function copyFile(src, dest, flags, cb) {
|
|
if (typeof flags === "function") {
|
|
cb = flags;
|
|
flags = 0;
|
|
}
|
|
return go$copyFile(src, dest, flags, cb);
|
|
function go$copyFile(src2, dest2, flags2, cb2, startTime) {
|
|
return fs$copyFile(src2, dest2, flags2, function(err) {
|
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
enqueue([go$copyFile, [src2, dest2, flags2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
else {
|
|
if (typeof cb2 === "function")
|
|
cb2.apply(this, arguments);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
var fs$readdir = fs2.readdir;
|
|
fs2.readdir = readdir;
|
|
var noReaddirOptionVersions = /^v[0-5]\./;
|
|
function readdir(path, options, cb) {
|
|
if (typeof options === "function")
|
|
cb = options, options = null;
|
|
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path2, options2, cb2, startTime) {
|
|
return fs$readdir(path2, fs$readdirCallback(
|
|
path2,
|
|
options2,
|
|
cb2,
|
|
startTime
|
|
));
|
|
} : function go$readdir2(path2, options2, cb2, startTime) {
|
|
return fs$readdir(path2, options2, fs$readdirCallback(
|
|
path2,
|
|
options2,
|
|
cb2,
|
|
startTime
|
|
));
|
|
};
|
|
return go$readdir(path, options, cb);
|
|
function fs$readdirCallback(path2, options2, cb2, startTime) {
|
|
return function(err, files) {
|
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
enqueue([
|
|
go$readdir,
|
|
[path2, options2, cb2],
|
|
err,
|
|
startTime || Date.now(),
|
|
Date.now()
|
|
]);
|
|
else {
|
|
if (files && files.sort)
|
|
files.sort();
|
|
if (typeof cb2 === "function")
|
|
cb2.call(this, err, files);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
if (process.version.substr(0, 4) === "v0.8") {
|
|
var legStreams = legacy(fs2);
|
|
ReadStream = legStreams.ReadStream;
|
|
WriteStream = legStreams.WriteStream;
|
|
}
|
|
var fs$ReadStream = fs2.ReadStream;
|
|
if (fs$ReadStream) {
|
|
ReadStream.prototype = Object.create(fs$ReadStream.prototype);
|
|
ReadStream.prototype.open = ReadStream$open;
|
|
}
|
|
var fs$WriteStream = fs2.WriteStream;
|
|
if (fs$WriteStream) {
|
|
WriteStream.prototype = Object.create(fs$WriteStream.prototype);
|
|
WriteStream.prototype.open = WriteStream$open;
|
|
}
|
|
Object.defineProperty(fs2, "ReadStream", {
|
|
get: function() {
|
|
return ReadStream;
|
|
},
|
|
set: function(val) {
|
|
ReadStream = val;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(fs2, "WriteStream", {
|
|
get: function() {
|
|
return WriteStream;
|
|
},
|
|
set: function(val) {
|
|
WriteStream = val;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
var FileReadStream = ReadStream;
|
|
Object.defineProperty(fs2, "FileReadStream", {
|
|
get: function() {
|
|
return FileReadStream;
|
|
},
|
|
set: function(val) {
|
|
FileReadStream = val;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
var FileWriteStream = WriteStream;
|
|
Object.defineProperty(fs2, "FileWriteStream", {
|
|
get: function() {
|
|
return FileWriteStream;
|
|
},
|
|
set: function(val) {
|
|
FileWriteStream = val;
|
|
},
|
|
enumerable: true,
|
|
configurable: true
|
|
});
|
|
function ReadStream(path, options) {
|
|
if (this instanceof ReadStream)
|
|
return fs$ReadStream.apply(this, arguments), this;
|
|
else
|
|
return ReadStream.apply(Object.create(ReadStream.prototype), arguments);
|
|
}
|
|
function ReadStream$open() {
|
|
var that = this;
|
|
open(that.path, that.flags, that.mode, function(err, fd) {
|
|
if (err) {
|
|
if (that.autoClose)
|
|
that.destroy();
|
|
that.emit("error", err);
|
|
} else {
|
|
that.fd = fd;
|
|
that.emit("open", fd);
|
|
that.read();
|
|
}
|
|
});
|
|
}
|
|
function WriteStream(path, options) {
|
|
if (this instanceof WriteStream)
|
|
return fs$WriteStream.apply(this, arguments), this;
|
|
else
|
|
return WriteStream.apply(Object.create(WriteStream.prototype), arguments);
|
|
}
|
|
function WriteStream$open() {
|
|
var that = this;
|
|
open(that.path, that.flags, that.mode, function(err, fd) {
|
|
if (err) {
|
|
that.destroy();
|
|
that.emit("error", err);
|
|
} else {
|
|
that.fd = fd;
|
|
that.emit("open", fd);
|
|
}
|
|
});
|
|
}
|
|
function createReadStream(path, options) {
|
|
return new fs2.ReadStream(path, options);
|
|
}
|
|
function createWriteStream(path, options) {
|
|
return new fs2.WriteStream(path, options);
|
|
}
|
|
var fs$open = fs2.open;
|
|
fs2.open = open;
|
|
function open(path, flags, mode, cb) {
|
|
if (typeof mode === "function")
|
|
cb = mode, mode = null;
|
|
return go$open(path, flags, mode, cb);
|
|
function go$open(path2, flags2, mode2, cb2, startTime) {
|
|
return fs$open(path2, flags2, mode2, function(err, fd) {
|
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
enqueue([go$open, [path2, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
else {
|
|
if (typeof cb2 === "function")
|
|
cb2.apply(this, arguments);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
return fs2;
|
|
}
|
|
function enqueue(elem) {
|
|
debug("ENQUEUE", elem[0].name, elem[1]);
|
|
fs[gracefulQueue].push(elem);
|
|
retry();
|
|
}
|
|
var retryTimer;
|
|
function resetQueue() {
|
|
var now = Date.now();
|
|
for (var i = 0; i < fs[gracefulQueue].length; ++i) {
|
|
if (fs[gracefulQueue][i].length > 2) {
|
|
fs[gracefulQueue][i][3] = now;
|
|
fs[gracefulQueue][i][4] = now;
|
|
}
|
|
}
|
|
retry();
|
|
}
|
|
function retry() {
|
|
clearTimeout(retryTimer);
|
|
retryTimer = void 0;
|
|
if (fs[gracefulQueue].length === 0)
|
|
return;
|
|
var elem = fs[gracefulQueue].shift();
|
|
var fn = elem[0];
|
|
var args = elem[1];
|
|
var err = elem[2];
|
|
var startTime = elem[3];
|
|
var lastTime = elem[4];
|
|
if (startTime === void 0) {
|
|
debug("RETRY", fn.name, args);
|
|
fn.apply(null, args);
|
|
} else if (Date.now() - startTime >= 6e4) {
|
|
debug("TIMEOUT", fn.name, args);
|
|
var cb = args.pop();
|
|
if (typeof cb === "function")
|
|
cb.call(null, err);
|
|
} else {
|
|
var sinceAttempt = Date.now() - lastTime;
|
|
var sinceStart = Math.max(lastTime - startTime, 1);
|
|
var desiredDelay = Math.min(sinceStart * 1.2, 100);
|
|
if (sinceAttempt >= desiredDelay) {
|
|
debug("RETRY", fn.name, args);
|
|
fn.apply(null, args.concat([startTime]));
|
|
} else {
|
|
fs[gracefulQueue].push(elem);
|
|
}
|
|
}
|
|
if (retryTimer === void 0) {
|
|
retryTimer = setTimeout(retry, 0);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/file-type/index.js
|
|
var require_file_type = __commonJS({
|
|
"../../node_modules/file-type/index.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = (input) => {
|
|
const buf = new Uint8Array(input);
|
|
if (!(buf && buf.length > 1)) {
|
|
return null;
|
|
}
|
|
const check = (header, opts) => {
|
|
opts = Object.assign({
|
|
offset: 0
|
|
}, opts);
|
|
for (let i = 0; i < header.length; i++) {
|
|
if (header[i] !== buf[i + opts.offset]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
if (check([255, 216, 255])) {
|
|
return {
|
|
ext: "jpg",
|
|
mime: "image/jpeg"
|
|
};
|
|
}
|
|
if (check([137, 80, 78, 71, 13, 10, 26, 10])) {
|
|
return {
|
|
ext: "png",
|
|
mime: "image/png"
|
|
};
|
|
}
|
|
if (check([71, 73, 70])) {
|
|
return {
|
|
ext: "gif",
|
|
mime: "image/gif"
|
|
};
|
|
}
|
|
if (check([87, 69, 66, 80], { offset: 8 })) {
|
|
return {
|
|
ext: "webp",
|
|
mime: "image/webp"
|
|
};
|
|
}
|
|
if (check([70, 76, 73, 70])) {
|
|
return {
|
|
ext: "flif",
|
|
mime: "image/flif"
|
|
};
|
|
}
|
|
if ((check([73, 73, 42, 0]) || check([77, 77, 0, 42])) && check([67, 82], { offset: 8 })) {
|
|
return {
|
|
ext: "cr2",
|
|
mime: "image/x-canon-cr2"
|
|
};
|
|
}
|
|
if (check([73, 73, 42, 0]) || check([77, 77, 0, 42])) {
|
|
return {
|
|
ext: "tif",
|
|
mime: "image/tiff"
|
|
};
|
|
}
|
|
if (check([66, 77])) {
|
|
return {
|
|
ext: "bmp",
|
|
mime: "image/bmp"
|
|
};
|
|
}
|
|
if (check([73, 73, 188])) {
|
|
return {
|
|
ext: "jxr",
|
|
mime: "image/vnd.ms-photo"
|
|
};
|
|
}
|
|
if (check([56, 66, 80, 83])) {
|
|
return {
|
|
ext: "psd",
|
|
mime: "image/vnd.adobe.photoshop"
|
|
};
|
|
}
|
|
if (check([80, 75, 3, 4]) && check([109, 105, 109, 101, 116, 121, 112, 101, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 101, 112, 117, 98, 43, 122, 105, 112], { offset: 30 })) {
|
|
return {
|
|
ext: "epub",
|
|
mime: "application/epub+zip"
|
|
};
|
|
}
|
|
if (check([80, 75, 3, 4]) && check([77, 69, 84, 65, 45, 73, 78, 70, 47, 109, 111, 122, 105, 108, 108, 97, 46, 114, 115, 97], { offset: 30 })) {
|
|
return {
|
|
ext: "xpi",
|
|
mime: "application/x-xpinstall"
|
|
};
|
|
}
|
|
if (check([80, 75]) && (buf[2] === 3 || buf[2] === 5 || buf[2] === 7) && (buf[3] === 4 || buf[3] === 6 || buf[3] === 8)) {
|
|
return {
|
|
ext: "zip",
|
|
mime: "application/zip"
|
|
};
|
|
}
|
|
if (check([117, 115, 116, 97, 114], { offset: 257 })) {
|
|
return {
|
|
ext: "tar",
|
|
mime: "application/x-tar"
|
|
};
|
|
}
|
|
if (check([82, 97, 114, 33, 26, 7]) && (buf[6] === 0 || buf[6] === 1)) {
|
|
return {
|
|
ext: "rar",
|
|
mime: "application/x-rar-compressed"
|
|
};
|
|
}
|
|
if (check([31, 139, 8])) {
|
|
return {
|
|
ext: "gz",
|
|
mime: "application/gzip"
|
|
};
|
|
}
|
|
if (check([66, 90, 104])) {
|
|
return {
|
|
ext: "bz2",
|
|
mime: "application/x-bzip2"
|
|
};
|
|
}
|
|
if (check([55, 122, 188, 175, 39, 28])) {
|
|
return {
|
|
ext: "7z",
|
|
mime: "application/x-7z-compressed"
|
|
};
|
|
}
|
|
if (check([120, 1])) {
|
|
return {
|
|
ext: "dmg",
|
|
mime: "application/x-apple-diskimage"
|
|
};
|
|
}
|
|
if (check([0, 0, 0]) && (buf[3] === 24 || buf[3] === 32) && check([102, 116, 121, 112], { offset: 4 }) || check([51, 103, 112, 53]) || check([0, 0, 0, 28, 102, 116, 121, 112, 109, 112, 52, 50]) && check([109, 112, 52, 49, 109, 112, 52, 50, 105, 115, 111, 109], { offset: 16 }) || check([0, 0, 0, 28, 102, 116, 121, 112, 105, 115, 111, 109]) || check([0, 0, 0, 28, 102, 116, 121, 112, 109, 112, 52, 50, 0, 0, 0, 0])) {
|
|
return {
|
|
ext: "mp4",
|
|
mime: "video/mp4"
|
|
};
|
|
}
|
|
if (check([0, 0, 0, 28, 102, 116, 121, 112, 77, 52, 86])) {
|
|
return {
|
|
ext: "m4v",
|
|
mime: "video/x-m4v"
|
|
};
|
|
}
|
|
if (check([77, 84, 104, 100])) {
|
|
return {
|
|
ext: "mid",
|
|
mime: "audio/midi"
|
|
};
|
|
}
|
|
if (check([26, 69, 223, 163])) {
|
|
const sliced = buf.subarray(4, 4 + 4096);
|
|
const idPos = sliced.findIndex((el, i, arr) => arr[i] === 66 && arr[i + 1] === 130);
|
|
if (idPos >= 0) {
|
|
const docTypePos = idPos + 3;
|
|
const findDocType = (type) => Array.from(type).every((c, i) => sliced[docTypePos + i] === c.charCodeAt(0));
|
|
if (findDocType("matroska")) {
|
|
return {
|
|
ext: "mkv",
|
|
mime: "video/x-matroska"
|
|
};
|
|
}
|
|
if (findDocType("webm")) {
|
|
return {
|
|
ext: "webm",
|
|
mime: "video/webm"
|
|
};
|
|
}
|
|
}
|
|
}
|
|
if (check([0, 0, 0, 20, 102, 116, 121, 112, 113, 116, 32, 32]) || check([102, 114, 101, 101], { offset: 4 }) || check([102, 116, 121, 112, 113, 116, 32, 32], { offset: 4 }) || check([109, 100, 97, 116], { offset: 4 }) || // MJPEG
|
|
check([119, 105, 100, 101], { offset: 4 })) {
|
|
return {
|
|
ext: "mov",
|
|
mime: "video/quicktime"
|
|
};
|
|
}
|
|
if (check([82, 73, 70, 70]) && check([65, 86, 73], { offset: 8 })) {
|
|
return {
|
|
ext: "avi",
|
|
mime: "video/x-msvideo"
|
|
};
|
|
}
|
|
if (check([48, 38, 178, 117, 142, 102, 207, 17, 166, 217])) {
|
|
return {
|
|
ext: "wmv",
|
|
mime: "video/x-ms-wmv"
|
|
};
|
|
}
|
|
if (check([0, 0, 1, 186])) {
|
|
return {
|
|
ext: "mpg",
|
|
mime: "video/mpeg"
|
|
};
|
|
}
|
|
if (check([73, 68, 51]) || check([255, 251])) {
|
|
return {
|
|
ext: "mp3",
|
|
mime: "audio/mpeg"
|
|
};
|
|
}
|
|
if (check([102, 116, 121, 112, 77, 52, 65], { offset: 4 }) || check([77, 52, 65, 32])) {
|
|
return {
|
|
ext: "m4a",
|
|
mime: "audio/m4a"
|
|
};
|
|
}
|
|
if (check([79, 112, 117, 115, 72, 101, 97, 100], { offset: 28 })) {
|
|
return {
|
|
ext: "opus",
|
|
mime: "audio/opus"
|
|
};
|
|
}
|
|
if (check([79, 103, 103, 83])) {
|
|
return {
|
|
ext: "ogg",
|
|
mime: "audio/ogg"
|
|
};
|
|
}
|
|
if (check([102, 76, 97, 67])) {
|
|
return {
|
|
ext: "flac",
|
|
mime: "audio/x-flac"
|
|
};
|
|
}
|
|
if (check([82, 73, 70, 70]) && check([87, 65, 86, 69], { offset: 8 })) {
|
|
return {
|
|
ext: "wav",
|
|
mime: "audio/x-wav"
|
|
};
|
|
}
|
|
if (check([35, 33, 65, 77, 82, 10])) {
|
|
return {
|
|
ext: "amr",
|
|
mime: "audio/amr"
|
|
};
|
|
}
|
|
if (check([37, 80, 68, 70])) {
|
|
return {
|
|
ext: "pdf",
|
|
mime: "application/pdf"
|
|
};
|
|
}
|
|
if (check([77, 90])) {
|
|
return {
|
|
ext: "exe",
|
|
mime: "application/x-msdownload"
|
|
};
|
|
}
|
|
if ((buf[0] === 67 || buf[0] === 70) && check([87, 83], { offset: 1 })) {
|
|
return {
|
|
ext: "swf",
|
|
mime: "application/x-shockwave-flash"
|
|
};
|
|
}
|
|
if (check([123, 92, 114, 116, 102])) {
|
|
return {
|
|
ext: "rtf",
|
|
mime: "application/rtf"
|
|
};
|
|
}
|
|
if (check([0, 97, 115, 109])) {
|
|
return {
|
|
ext: "wasm",
|
|
mime: "application/wasm"
|
|
};
|
|
}
|
|
if (check([119, 79, 70, 70]) && (check([0, 1, 0, 0], { offset: 4 }) || check([79, 84, 84, 79], { offset: 4 }))) {
|
|
return {
|
|
ext: "woff",
|
|
mime: "font/woff"
|
|
};
|
|
}
|
|
if (check([119, 79, 70, 50]) && (check([0, 1, 0, 0], { offset: 4 }) || check([79, 84, 84, 79], { offset: 4 }))) {
|
|
return {
|
|
ext: "woff2",
|
|
mime: "font/woff2"
|
|
};
|
|
}
|
|
if (check([76, 80], { offset: 34 }) && (check([0, 0, 1], { offset: 8 }) || check([1, 0, 2], { offset: 8 }) || check([2, 0, 2], { offset: 8 }))) {
|
|
return {
|
|
ext: "eot",
|
|
mime: "application/octet-stream"
|
|
};
|
|
}
|
|
if (check([0, 1, 0, 0, 0])) {
|
|
return {
|
|
ext: "ttf",
|
|
mime: "font/ttf"
|
|
};
|
|
}
|
|
if (check([79, 84, 84, 79, 0])) {
|
|
return {
|
|
ext: "otf",
|
|
mime: "font/otf"
|
|
};
|
|
}
|
|
if (check([0, 0, 1, 0])) {
|
|
return {
|
|
ext: "ico",
|
|
mime: "image/x-icon"
|
|
};
|
|
}
|
|
if (check([70, 76, 86, 1])) {
|
|
return {
|
|
ext: "flv",
|
|
mime: "video/x-flv"
|
|
};
|
|
}
|
|
if (check([37, 33])) {
|
|
return {
|
|
ext: "ps",
|
|
mime: "application/postscript"
|
|
};
|
|
}
|
|
if (check([253, 55, 122, 88, 90, 0])) {
|
|
return {
|
|
ext: "xz",
|
|
mime: "application/x-xz"
|
|
};
|
|
}
|
|
if (check([83, 81, 76, 105])) {
|
|
return {
|
|
ext: "sqlite",
|
|
mime: "application/x-sqlite3"
|
|
};
|
|
}
|
|
if (check([78, 69, 83, 26])) {
|
|
return {
|
|
ext: "nes",
|
|
mime: "application/x-nintendo-nes-rom"
|
|
};
|
|
}
|
|
if (check([67, 114, 50, 52])) {
|
|
return {
|
|
ext: "crx",
|
|
mime: "application/x-google-chrome-extension"
|
|
};
|
|
}
|
|
if (check([77, 83, 67, 70]) || check([73, 83, 99, 40])) {
|
|
return {
|
|
ext: "cab",
|
|
mime: "application/vnd.ms-cab-compressed"
|
|
};
|
|
}
|
|
if (check([33, 60, 97, 114, 99, 104, 62, 10, 100, 101, 98, 105, 97, 110, 45, 98, 105, 110, 97, 114, 121])) {
|
|
return {
|
|
ext: "deb",
|
|
mime: "application/x-deb"
|
|
};
|
|
}
|
|
if (check([33, 60, 97, 114, 99, 104, 62])) {
|
|
return {
|
|
ext: "ar",
|
|
mime: "application/x-unix-archive"
|
|
};
|
|
}
|
|
if (check([237, 171, 238, 219])) {
|
|
return {
|
|
ext: "rpm",
|
|
mime: "application/x-rpm"
|
|
};
|
|
}
|
|
if (check([31, 160]) || check([31, 157])) {
|
|
return {
|
|
ext: "Z",
|
|
mime: "application/x-compress"
|
|
};
|
|
}
|
|
if (check([76, 90, 73, 80])) {
|
|
return {
|
|
ext: "lz",
|
|
mime: "application/x-lzip"
|
|
};
|
|
}
|
|
if (check([208, 207, 17, 224, 161, 177, 26, 225])) {
|
|
return {
|
|
ext: "msi",
|
|
mime: "application/x-msi"
|
|
};
|
|
}
|
|
if (check([6, 14, 43, 52, 2, 5, 1, 1, 13, 1, 2, 1, 1, 2])) {
|
|
return {
|
|
ext: "mxf",
|
|
mime: "application/mxf"
|
|
};
|
|
}
|
|
if (check([71], { offset: 4 }) && (check([71], { offset: 192 }) || check([71], { offset: 196 }))) {
|
|
return {
|
|
ext: "mts",
|
|
mime: "video/mp2t"
|
|
};
|
|
}
|
|
if (check([66, 76, 69, 78, 68, 69, 82])) {
|
|
return {
|
|
ext: "blend",
|
|
mime: "application/x-blender"
|
|
};
|
|
}
|
|
if (check([66, 80, 71, 251])) {
|
|
return {
|
|
ext: "bpg",
|
|
mime: "image/bpg"
|
|
};
|
|
}
|
|
return null;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/is-stream/index.js
|
|
var require_is_stream = __commonJS({
|
|
"../../node_modules/is-stream/index.js"(exports, module) {
|
|
"use strict";
|
|
var isStream = module.exports = function(stream) {
|
|
return stream !== null && typeof stream === "object" && typeof stream.pipe === "function";
|
|
};
|
|
isStream.writable = function(stream) {
|
|
return isStream(stream) && stream.writable !== false && typeof stream._write === "function" && typeof stream._writableState === "object";
|
|
};
|
|
isStream.readable = function(stream) {
|
|
return isStream(stream) && stream.readable !== false && typeof stream._read === "function" && typeof stream._readableState === "object";
|
|
};
|
|
isStream.duplex = function(stream) {
|
|
return isStream.writable(stream) && isStream.readable(stream);
|
|
};
|
|
isStream.transform = function(stream) {
|
|
return isStream.duplex(stream) && typeof stream._transform === "function" && typeof stream._transformState === "object";
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/process-nextick-args/index.js
|
|
var require_process_nextick_args = __commonJS({
|
|
"../../node_modules/process-nextick-args/index.js"(exports, module) {
|
|
"use strict";
|
|
if (typeof process === "undefined" || !process.version || process.version.indexOf("v0.") === 0 || process.version.indexOf("v1.") === 0 && process.version.indexOf("v1.8.") !== 0) {
|
|
module.exports = { nextTick };
|
|
} else {
|
|
module.exports = process;
|
|
}
|
|
function nextTick(fn, arg1, arg2, arg3) {
|
|
if (typeof fn !== "function") {
|
|
throw new TypeError('"callback" argument must be a function');
|
|
}
|
|
var len = arguments.length;
|
|
var args, i;
|
|
switch (len) {
|
|
case 0:
|
|
case 1:
|
|
return process.nextTick(fn);
|
|
case 2:
|
|
return process.nextTick(function afterTickOne() {
|
|
fn.call(null, arg1);
|
|
});
|
|
case 3:
|
|
return process.nextTick(function afterTickTwo() {
|
|
fn.call(null, arg1, arg2);
|
|
});
|
|
case 4:
|
|
return process.nextTick(function afterTickThree() {
|
|
fn.call(null, arg1, arg2, arg3);
|
|
});
|
|
default:
|
|
args = new Array(len - 1);
|
|
i = 0;
|
|
while (i < args.length) {
|
|
args[i++] = arguments[i];
|
|
}
|
|
return process.nextTick(function afterTick() {
|
|
fn.apply(null, args);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/isarray/index.js
|
|
var require_isarray = __commonJS({
|
|
"../../node_modules/bl/node_modules/isarray/index.js"(exports, module) {
|
|
var toString = {}.toString;
|
|
module.exports = Array.isArray || function(arr) {
|
|
return toString.call(arr) == "[object Array]";
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/lib/internal/streams/stream.js
|
|
var require_stream = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/lib/internal/streams/stream.js"(exports, module) {
|
|
module.exports = __require("stream");
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/safe-buffer/index.js
|
|
var require_safe_buffer = __commonJS({
|
|
"../../node_modules/bl/node_modules/safe-buffer/index.js"(exports, module) {
|
|
var buffer = __require("buffer");
|
|
var Buffer2 = buffer.Buffer;
|
|
function copyProps(src, dst) {
|
|
for (var key in src) {
|
|
dst[key] = src[key];
|
|
}
|
|
}
|
|
if (Buffer2.from && Buffer2.alloc && Buffer2.allocUnsafe && Buffer2.allocUnsafeSlow) {
|
|
module.exports = buffer;
|
|
} else {
|
|
copyProps(buffer, exports);
|
|
exports.Buffer = SafeBuffer;
|
|
}
|
|
function SafeBuffer(arg, encodingOrOffset, length) {
|
|
return Buffer2(arg, encodingOrOffset, length);
|
|
}
|
|
copyProps(Buffer2, SafeBuffer);
|
|
SafeBuffer.from = function(arg, encodingOrOffset, length) {
|
|
if (typeof arg === "number") {
|
|
throw new TypeError("Argument must not be a number");
|
|
}
|
|
return Buffer2(arg, encodingOrOffset, length);
|
|
};
|
|
SafeBuffer.alloc = function(size, fill, encoding) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
var buf = Buffer2(size);
|
|
if (fill !== void 0) {
|
|
if (typeof encoding === "string") {
|
|
buf.fill(fill, encoding);
|
|
} else {
|
|
buf.fill(fill);
|
|
}
|
|
} else {
|
|
buf.fill(0);
|
|
}
|
|
return buf;
|
|
};
|
|
SafeBuffer.allocUnsafe = function(size) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
return Buffer2(size);
|
|
};
|
|
SafeBuffer.allocUnsafeSlow = function(size) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
return buffer.SlowBuffer(size);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/core-util-is/lib/util.js
|
|
var require_util = __commonJS({
|
|
"../../node_modules/core-util-is/lib/util.js"(exports) {
|
|
function isArray(arg) {
|
|
if (Array.isArray) {
|
|
return Array.isArray(arg);
|
|
}
|
|
return objectToString(arg) === "[object Array]";
|
|
}
|
|
exports.isArray = isArray;
|
|
function isBoolean(arg) {
|
|
return typeof arg === "boolean";
|
|
}
|
|
exports.isBoolean = isBoolean;
|
|
function isNull(arg) {
|
|
return arg === null;
|
|
}
|
|
exports.isNull = isNull;
|
|
function isNullOrUndefined(arg) {
|
|
return arg == null;
|
|
}
|
|
exports.isNullOrUndefined = isNullOrUndefined;
|
|
function isNumber(arg) {
|
|
return typeof arg === "number";
|
|
}
|
|
exports.isNumber = isNumber;
|
|
function isString(arg) {
|
|
return typeof arg === "string";
|
|
}
|
|
exports.isString = isString;
|
|
function isSymbol(arg) {
|
|
return typeof arg === "symbol";
|
|
}
|
|
exports.isSymbol = isSymbol;
|
|
function isUndefined(arg) {
|
|
return arg === void 0;
|
|
}
|
|
exports.isUndefined = isUndefined;
|
|
function isRegExp(re) {
|
|
return objectToString(re) === "[object RegExp]";
|
|
}
|
|
exports.isRegExp = isRegExp;
|
|
function isObject(arg) {
|
|
return typeof arg === "object" && arg !== null;
|
|
}
|
|
exports.isObject = isObject;
|
|
function isDate(d) {
|
|
return objectToString(d) === "[object Date]";
|
|
}
|
|
exports.isDate = isDate;
|
|
function isError(e) {
|
|
return objectToString(e) === "[object Error]" || e instanceof Error;
|
|
}
|
|
exports.isError = isError;
|
|
function isFunction(arg) {
|
|
return typeof arg === "function";
|
|
}
|
|
exports.isFunction = isFunction;
|
|
function isPrimitive(arg) {
|
|
return arg === null || typeof arg === "boolean" || typeof arg === "number" || typeof arg === "string" || typeof arg === "symbol" || // ES6 symbol
|
|
typeof arg === "undefined";
|
|
}
|
|
exports.isPrimitive = isPrimitive;
|
|
exports.isBuffer = __require("buffer").Buffer.isBuffer;
|
|
function objectToString(o) {
|
|
return Object.prototype.toString.call(o);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/inherits/inherits_browser.js
|
|
var require_inherits_browser = __commonJS({
|
|
"../../node_modules/inherits/inherits_browser.js"(exports, module) {
|
|
if (typeof Object.create === "function") {
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
if (superCtor) {
|
|
ctor.super_ = superCtor;
|
|
ctor.prototype = Object.create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
}
|
|
};
|
|
} else {
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
if (superCtor) {
|
|
ctor.super_ = superCtor;
|
|
var TempCtor = function() {
|
|
};
|
|
TempCtor.prototype = superCtor.prototype;
|
|
ctor.prototype = new TempCtor();
|
|
ctor.prototype.constructor = ctor;
|
|
}
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/inherits/inherits.js
|
|
var require_inherits = __commonJS({
|
|
"../../node_modules/inherits/inherits.js"(exports, module) {
|
|
try {
|
|
util = __require("util");
|
|
if (typeof util.inherits !== "function") throw "";
|
|
module.exports = util.inherits;
|
|
} catch (e) {
|
|
module.exports = require_inherits_browser();
|
|
}
|
|
var util;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/lib/internal/streams/BufferList.js
|
|
var require_BufferList = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/lib/internal/streams/BufferList.js"(exports, module) {
|
|
"use strict";
|
|
function _classCallCheck(instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
}
|
|
var Buffer2 = require_safe_buffer().Buffer;
|
|
var util = __require("util");
|
|
function copyBuffer(src, target, offset) {
|
|
src.copy(target, offset);
|
|
}
|
|
module.exports = (function() {
|
|
function BufferList() {
|
|
_classCallCheck(this, BufferList);
|
|
this.head = null;
|
|
this.tail = null;
|
|
this.length = 0;
|
|
}
|
|
BufferList.prototype.push = function push(v) {
|
|
var entry = { data: v, next: null };
|
|
if (this.length > 0) this.tail.next = entry;
|
|
else this.head = entry;
|
|
this.tail = entry;
|
|
++this.length;
|
|
};
|
|
BufferList.prototype.unshift = function unshift(v) {
|
|
var entry = { data: v, next: this.head };
|
|
if (this.length === 0) this.tail = entry;
|
|
this.head = entry;
|
|
++this.length;
|
|
};
|
|
BufferList.prototype.shift = function shift() {
|
|
if (this.length === 0) return;
|
|
var ret = this.head.data;
|
|
if (this.length === 1) this.head = this.tail = null;
|
|
else this.head = this.head.next;
|
|
--this.length;
|
|
return ret;
|
|
};
|
|
BufferList.prototype.clear = function clear() {
|
|
this.head = this.tail = null;
|
|
this.length = 0;
|
|
};
|
|
BufferList.prototype.join = function join(s) {
|
|
if (this.length === 0) return "";
|
|
var p = this.head;
|
|
var ret = "" + p.data;
|
|
while (p = p.next) {
|
|
ret += s + p.data;
|
|
}
|
|
return ret;
|
|
};
|
|
BufferList.prototype.concat = function concat(n) {
|
|
if (this.length === 0) return Buffer2.alloc(0);
|
|
var ret = Buffer2.allocUnsafe(n >>> 0);
|
|
var p = this.head;
|
|
var i = 0;
|
|
while (p) {
|
|
copyBuffer(p.data, ret, i);
|
|
i += p.data.length;
|
|
p = p.next;
|
|
}
|
|
return ret;
|
|
};
|
|
return BufferList;
|
|
})();
|
|
if (util && util.inspect && util.inspect.custom) {
|
|
module.exports.prototype[util.inspect.custom] = function() {
|
|
var obj = util.inspect({ length: this.length });
|
|
return this.constructor.name + " " + obj;
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/lib/internal/streams/destroy.js
|
|
var require_destroy = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/lib/internal/streams/destroy.js"(exports, module) {
|
|
"use strict";
|
|
var pna = require_process_nextick_args();
|
|
function destroy(err, cb) {
|
|
var _this = this;
|
|
var readableDestroyed = this._readableState && this._readableState.destroyed;
|
|
var writableDestroyed = this._writableState && this._writableState.destroyed;
|
|
if (readableDestroyed || writableDestroyed) {
|
|
if (cb) {
|
|
cb(err);
|
|
} else if (err) {
|
|
if (!this._writableState) {
|
|
pna.nextTick(emitErrorNT, this, err);
|
|
} else if (!this._writableState.errorEmitted) {
|
|
this._writableState.errorEmitted = true;
|
|
pna.nextTick(emitErrorNT, this, err);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = true;
|
|
}
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = true;
|
|
}
|
|
this._destroy(err || null, function(err2) {
|
|
if (!cb && err2) {
|
|
if (!_this._writableState) {
|
|
pna.nextTick(emitErrorNT, _this, err2);
|
|
} else if (!_this._writableState.errorEmitted) {
|
|
_this._writableState.errorEmitted = true;
|
|
pna.nextTick(emitErrorNT, _this, err2);
|
|
}
|
|
} else if (cb) {
|
|
cb(err2);
|
|
}
|
|
});
|
|
return this;
|
|
}
|
|
function undestroy() {
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = false;
|
|
this._readableState.reading = false;
|
|
this._readableState.ended = false;
|
|
this._readableState.endEmitted = false;
|
|
}
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = false;
|
|
this._writableState.ended = false;
|
|
this._writableState.ending = false;
|
|
this._writableState.finalCalled = false;
|
|
this._writableState.prefinished = false;
|
|
this._writableState.finished = false;
|
|
this._writableState.errorEmitted = false;
|
|
}
|
|
}
|
|
function emitErrorNT(self2, err) {
|
|
self2.emit("error", err);
|
|
}
|
|
module.exports = {
|
|
destroy,
|
|
undestroy
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/util-deprecate/node.js
|
|
var require_node = __commonJS({
|
|
"../../node_modules/util-deprecate/node.js"(exports, module) {
|
|
module.exports = __require("util").deprecate;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/lib/_stream_writable.js
|
|
var require_stream_writable = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/lib/_stream_writable.js"(exports, module) {
|
|
"use strict";
|
|
var pna = require_process_nextick_args();
|
|
module.exports = Writable;
|
|
function CorkedRequest(state) {
|
|
var _this = this;
|
|
this.next = null;
|
|
this.entry = null;
|
|
this.finish = function() {
|
|
onCorkedFinish(_this, state);
|
|
};
|
|
}
|
|
var asyncWrite = !process.browser && ["v0.10", "v0.9."].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
|
|
var Duplex;
|
|
Writable.WritableState = WritableState;
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
var internalUtil = {
|
|
deprecate: require_node()
|
|
};
|
|
var Stream = require_stream();
|
|
var Buffer2 = require_safe_buffer().Buffer;
|
|
var OurUint8Array = (typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {}).Uint8Array || function() {
|
|
};
|
|
function _uint8ArrayToBuffer(chunk) {
|
|
return Buffer2.from(chunk);
|
|
}
|
|
function _isUint8Array(obj) {
|
|
return Buffer2.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
}
|
|
var destroyImpl = require_destroy();
|
|
util.inherits(Writable, Stream);
|
|
function nop() {
|
|
}
|
|
function WritableState(options, stream) {
|
|
Duplex = Duplex || require_stream_duplex();
|
|
options = options || {};
|
|
var isDuplex = stream instanceof Duplex;
|
|
this.objectMode = !!options.objectMode;
|
|
if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
|
|
var hwm = options.highWaterMark;
|
|
var writableHwm = options.writableHighWaterMark;
|
|
var defaultHwm = this.objectMode ? 16 : 16 * 1024;
|
|
if (hwm || hwm === 0) this.highWaterMark = hwm;
|
|
else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;
|
|
else this.highWaterMark = defaultHwm;
|
|
this.highWaterMark = Math.floor(this.highWaterMark);
|
|
this.finalCalled = false;
|
|
this.needDrain = false;
|
|
this.ending = false;
|
|
this.ended = false;
|
|
this.finished = false;
|
|
this.destroyed = false;
|
|
var noDecode = options.decodeStrings === false;
|
|
this.decodeStrings = !noDecode;
|
|
this.defaultEncoding = options.defaultEncoding || "utf8";
|
|
this.length = 0;
|
|
this.writing = false;
|
|
this.corked = 0;
|
|
this.sync = true;
|
|
this.bufferProcessing = false;
|
|
this.onwrite = function(er) {
|
|
onwrite(stream, er);
|
|
};
|
|
this.writecb = null;
|
|
this.writelen = 0;
|
|
this.bufferedRequest = null;
|
|
this.lastBufferedRequest = null;
|
|
this.pendingcb = 0;
|
|
this.prefinished = false;
|
|
this.errorEmitted = false;
|
|
this.bufferedRequestCount = 0;
|
|
this.corkedRequestsFree = new CorkedRequest(this);
|
|
}
|
|
WritableState.prototype.getBuffer = function getBuffer() {
|
|
var current = this.bufferedRequest;
|
|
var out = [];
|
|
while (current) {
|
|
out.push(current);
|
|
current = current.next;
|
|
}
|
|
return out;
|
|
};
|
|
(function() {
|
|
try {
|
|
Object.defineProperty(WritableState.prototype, "buffer", {
|
|
get: internalUtil.deprecate(function() {
|
|
return this.getBuffer();
|
|
}, "_writableState.buffer is deprecated. Use _writableState.getBuffer instead.", "DEP0003")
|
|
});
|
|
} catch (_) {
|
|
}
|
|
})();
|
|
var realHasInstance;
|
|
if (typeof Symbol === "function" && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === "function") {
|
|
realHasInstance = Function.prototype[Symbol.hasInstance];
|
|
Object.defineProperty(Writable, Symbol.hasInstance, {
|
|
value: function(object) {
|
|
if (realHasInstance.call(this, object)) return true;
|
|
if (this !== Writable) return false;
|
|
return object && object._writableState instanceof WritableState;
|
|
}
|
|
});
|
|
} else {
|
|
realHasInstance = function(object) {
|
|
return object instanceof this;
|
|
};
|
|
}
|
|
function Writable(options) {
|
|
Duplex = Duplex || require_stream_duplex();
|
|
if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
|
|
return new Writable(options);
|
|
}
|
|
this._writableState = new WritableState(options, this);
|
|
this.writable = true;
|
|
if (options) {
|
|
if (typeof options.write === "function") this._write = options.write;
|
|
if (typeof options.writev === "function") this._writev = options.writev;
|
|
if (typeof options.destroy === "function") this._destroy = options.destroy;
|
|
if (typeof options.final === "function") this._final = options.final;
|
|
}
|
|
Stream.call(this);
|
|
}
|
|
Writable.prototype.pipe = function() {
|
|
this.emit("error", new Error("Cannot pipe, not readable"));
|
|
};
|
|
function writeAfterEnd(stream, cb) {
|
|
var er = new Error("write after end");
|
|
stream.emit("error", er);
|
|
pna.nextTick(cb, er);
|
|
}
|
|
function validChunk(stream, state, chunk, cb) {
|
|
var valid = true;
|
|
var er = false;
|
|
if (chunk === null) {
|
|
er = new TypeError("May not write null values to stream");
|
|
} else if (typeof chunk !== "string" && chunk !== void 0 && !state.objectMode) {
|
|
er = new TypeError("Invalid non-string/buffer chunk");
|
|
}
|
|
if (er) {
|
|
stream.emit("error", er);
|
|
pna.nextTick(cb, er);
|
|
valid = false;
|
|
}
|
|
return valid;
|
|
}
|
|
Writable.prototype.write = function(chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
var ret = false;
|
|
var isBuf = !state.objectMode && _isUint8Array(chunk);
|
|
if (isBuf && !Buffer2.isBuffer(chunk)) {
|
|
chunk = _uint8ArrayToBuffer(chunk);
|
|
}
|
|
if (typeof encoding === "function") {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
if (isBuf) encoding = "buffer";
|
|
else if (!encoding) encoding = state.defaultEncoding;
|
|
if (typeof cb !== "function") cb = nop;
|
|
if (state.ended) writeAfterEnd(this, cb);
|
|
else if (isBuf || validChunk(this, state, chunk, cb)) {
|
|
state.pendingcb++;
|
|
ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
|
|
}
|
|
return ret;
|
|
};
|
|
Writable.prototype.cork = function() {
|
|
var state = this._writableState;
|
|
state.corked++;
|
|
};
|
|
Writable.prototype.uncork = function() {
|
|
var state = this._writableState;
|
|
if (state.corked) {
|
|
state.corked--;
|
|
if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
|
|
}
|
|
};
|
|
Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
|
|
if (typeof encoding === "string") encoding = encoding.toLowerCase();
|
|
if (!(["hex", "utf8", "utf-8", "ascii", "binary", "base64", "ucs2", "ucs-2", "utf16le", "utf-16le", "raw"].indexOf((encoding + "").toLowerCase()) > -1)) throw new TypeError("Unknown encoding: " + encoding);
|
|
this._writableState.defaultEncoding = encoding;
|
|
return this;
|
|
};
|
|
function decodeChunk(state, chunk, encoding) {
|
|
if (!state.objectMode && state.decodeStrings !== false && typeof chunk === "string") {
|
|
chunk = Buffer2.from(chunk, encoding);
|
|
}
|
|
return chunk;
|
|
}
|
|
Object.defineProperty(Writable.prototype, "writableHighWaterMark", {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function() {
|
|
return this._writableState.highWaterMark;
|
|
}
|
|
});
|
|
function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
|
|
if (!isBuf) {
|
|
var newChunk = decodeChunk(state, chunk, encoding);
|
|
if (chunk !== newChunk) {
|
|
isBuf = true;
|
|
encoding = "buffer";
|
|
chunk = newChunk;
|
|
}
|
|
}
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
state.length += len;
|
|
var ret = state.length < state.highWaterMark;
|
|
if (!ret) state.needDrain = true;
|
|
if (state.writing || state.corked) {
|
|
var last = state.lastBufferedRequest;
|
|
state.lastBufferedRequest = {
|
|
chunk,
|
|
encoding,
|
|
isBuf,
|
|
callback: cb,
|
|
next: null
|
|
};
|
|
if (last) {
|
|
last.next = state.lastBufferedRequest;
|
|
} else {
|
|
state.bufferedRequest = state.lastBufferedRequest;
|
|
}
|
|
state.bufferedRequestCount += 1;
|
|
} else {
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
}
|
|
return ret;
|
|
}
|
|
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
|
|
state.writelen = len;
|
|
state.writecb = cb;
|
|
state.writing = true;
|
|
state.sync = true;
|
|
if (writev) stream._writev(chunk, state.onwrite);
|
|
else stream._write(chunk, encoding, state.onwrite);
|
|
state.sync = false;
|
|
}
|
|
function onwriteError(stream, state, sync, er, cb) {
|
|
--state.pendingcb;
|
|
if (sync) {
|
|
pna.nextTick(cb, er);
|
|
pna.nextTick(finishMaybe, stream, state);
|
|
stream._writableState.errorEmitted = true;
|
|
stream.emit("error", er);
|
|
} else {
|
|
cb(er);
|
|
stream._writableState.errorEmitted = true;
|
|
stream.emit("error", er);
|
|
finishMaybe(stream, state);
|
|
}
|
|
}
|
|
function onwriteStateUpdate(state) {
|
|
state.writing = false;
|
|
state.writecb = null;
|
|
state.length -= state.writelen;
|
|
state.writelen = 0;
|
|
}
|
|
function onwrite(stream, er) {
|
|
var state = stream._writableState;
|
|
var sync = state.sync;
|
|
var cb = state.writecb;
|
|
onwriteStateUpdate(state);
|
|
if (er) onwriteError(stream, state, sync, er, cb);
|
|
else {
|
|
var finished = needFinish(state);
|
|
if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
|
|
clearBuffer(stream, state);
|
|
}
|
|
if (sync) {
|
|
asyncWrite(afterWrite, stream, state, finished, cb);
|
|
} else {
|
|
afterWrite(stream, state, finished, cb);
|
|
}
|
|
}
|
|
}
|
|
function afterWrite(stream, state, finished, cb) {
|
|
if (!finished) onwriteDrain(stream, state);
|
|
state.pendingcb--;
|
|
cb();
|
|
finishMaybe(stream, state);
|
|
}
|
|
function onwriteDrain(stream, state) {
|
|
if (state.length === 0 && state.needDrain) {
|
|
state.needDrain = false;
|
|
stream.emit("drain");
|
|
}
|
|
}
|
|
function clearBuffer(stream, state) {
|
|
state.bufferProcessing = true;
|
|
var entry = state.bufferedRequest;
|
|
if (stream._writev && entry && entry.next) {
|
|
var l = state.bufferedRequestCount;
|
|
var buffer = new Array(l);
|
|
var holder = state.corkedRequestsFree;
|
|
holder.entry = entry;
|
|
var count = 0;
|
|
var allBuffers = true;
|
|
while (entry) {
|
|
buffer[count] = entry;
|
|
if (!entry.isBuf) allBuffers = false;
|
|
entry = entry.next;
|
|
count += 1;
|
|
}
|
|
buffer.allBuffers = allBuffers;
|
|
doWrite(stream, state, true, state.length, buffer, "", holder.finish);
|
|
state.pendingcb++;
|
|
state.lastBufferedRequest = null;
|
|
if (holder.next) {
|
|
state.corkedRequestsFree = holder.next;
|
|
holder.next = null;
|
|
} else {
|
|
state.corkedRequestsFree = new CorkedRequest(state);
|
|
}
|
|
state.bufferedRequestCount = 0;
|
|
} else {
|
|
while (entry) {
|
|
var chunk = entry.chunk;
|
|
var encoding = entry.encoding;
|
|
var cb = entry.callback;
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
entry = entry.next;
|
|
state.bufferedRequestCount--;
|
|
if (state.writing) {
|
|
break;
|
|
}
|
|
}
|
|
if (entry === null) state.lastBufferedRequest = null;
|
|
}
|
|
state.bufferedRequest = entry;
|
|
state.bufferProcessing = false;
|
|
}
|
|
Writable.prototype._write = function(chunk, encoding, cb) {
|
|
cb(new Error("_write() is not implemented"));
|
|
};
|
|
Writable.prototype._writev = null;
|
|
Writable.prototype.end = function(chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
if (typeof chunk === "function") {
|
|
cb = chunk;
|
|
chunk = null;
|
|
encoding = null;
|
|
} else if (typeof encoding === "function") {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
if (chunk !== null && chunk !== void 0) this.write(chunk, encoding);
|
|
if (state.corked) {
|
|
state.corked = 1;
|
|
this.uncork();
|
|
}
|
|
if (!state.ending) endWritable(this, state, cb);
|
|
};
|
|
function needFinish(state) {
|
|
return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
|
|
}
|
|
function callFinal(stream, state) {
|
|
stream._final(function(err) {
|
|
state.pendingcb--;
|
|
if (err) {
|
|
stream.emit("error", err);
|
|
}
|
|
state.prefinished = true;
|
|
stream.emit("prefinish");
|
|
finishMaybe(stream, state);
|
|
});
|
|
}
|
|
function prefinish(stream, state) {
|
|
if (!state.prefinished && !state.finalCalled) {
|
|
if (typeof stream._final === "function") {
|
|
state.pendingcb++;
|
|
state.finalCalled = true;
|
|
pna.nextTick(callFinal, stream, state);
|
|
} else {
|
|
state.prefinished = true;
|
|
stream.emit("prefinish");
|
|
}
|
|
}
|
|
}
|
|
function finishMaybe(stream, state) {
|
|
var need = needFinish(state);
|
|
if (need) {
|
|
prefinish(stream, state);
|
|
if (state.pendingcb === 0) {
|
|
state.finished = true;
|
|
stream.emit("finish");
|
|
}
|
|
}
|
|
return need;
|
|
}
|
|
function endWritable(stream, state, cb) {
|
|
state.ending = true;
|
|
finishMaybe(stream, state);
|
|
if (cb) {
|
|
if (state.finished) pna.nextTick(cb);
|
|
else stream.once("finish", cb);
|
|
}
|
|
state.ended = true;
|
|
stream.writable = false;
|
|
}
|
|
function onCorkedFinish(corkReq, state, err) {
|
|
var entry = corkReq.entry;
|
|
corkReq.entry = null;
|
|
while (entry) {
|
|
var cb = entry.callback;
|
|
state.pendingcb--;
|
|
cb(err);
|
|
entry = entry.next;
|
|
}
|
|
state.corkedRequestsFree.next = corkReq;
|
|
}
|
|
Object.defineProperty(Writable.prototype, "destroyed", {
|
|
get: function() {
|
|
if (this._writableState === void 0) {
|
|
return false;
|
|
}
|
|
return this._writableState.destroyed;
|
|
},
|
|
set: function(value) {
|
|
if (!this._writableState) {
|
|
return;
|
|
}
|
|
this._writableState.destroyed = value;
|
|
}
|
|
});
|
|
Writable.prototype.destroy = destroyImpl.destroy;
|
|
Writable.prototype._undestroy = destroyImpl.undestroy;
|
|
Writable.prototype._destroy = function(err, cb) {
|
|
this.end();
|
|
cb(err);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/lib/_stream_duplex.js
|
|
var require_stream_duplex = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/lib/_stream_duplex.js"(exports, module) {
|
|
"use strict";
|
|
var pna = require_process_nextick_args();
|
|
var objectKeys = Object.keys || function(obj) {
|
|
var keys2 = [];
|
|
for (var key in obj) {
|
|
keys2.push(key);
|
|
}
|
|
return keys2;
|
|
};
|
|
module.exports = Duplex;
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
var Readable = require_stream_readable();
|
|
var Writable = require_stream_writable();
|
|
util.inherits(Duplex, Readable);
|
|
{
|
|
keys = objectKeys(Writable.prototype);
|
|
for (v = 0; v < keys.length; v++) {
|
|
method = keys[v];
|
|
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
|
|
}
|
|
}
|
|
var keys;
|
|
var method;
|
|
var v;
|
|
function Duplex(options) {
|
|
if (!(this instanceof Duplex)) return new Duplex(options);
|
|
Readable.call(this, options);
|
|
Writable.call(this, options);
|
|
if (options && options.readable === false) this.readable = false;
|
|
if (options && options.writable === false) this.writable = false;
|
|
this.allowHalfOpen = true;
|
|
if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
|
|
this.once("end", onend);
|
|
}
|
|
Object.defineProperty(Duplex.prototype, "writableHighWaterMark", {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function() {
|
|
return this._writableState.highWaterMark;
|
|
}
|
|
});
|
|
function onend() {
|
|
if (this.allowHalfOpen || this._writableState.ended) return;
|
|
pna.nextTick(onEndNT, this);
|
|
}
|
|
function onEndNT(self2) {
|
|
self2.end();
|
|
}
|
|
Object.defineProperty(Duplex.prototype, "destroyed", {
|
|
get: function() {
|
|
if (this._readableState === void 0 || this._writableState === void 0) {
|
|
return false;
|
|
}
|
|
return this._readableState.destroyed && this._writableState.destroyed;
|
|
},
|
|
set: function(value) {
|
|
if (this._readableState === void 0 || this._writableState === void 0) {
|
|
return;
|
|
}
|
|
this._readableState.destroyed = value;
|
|
this._writableState.destroyed = value;
|
|
}
|
|
});
|
|
Duplex.prototype._destroy = function(err, cb) {
|
|
this.push(null);
|
|
this.end();
|
|
pna.nextTick(cb, err);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/string_decoder/lib/string_decoder.js
|
|
var require_string_decoder = __commonJS({
|
|
"../../node_modules/bl/node_modules/string_decoder/lib/string_decoder.js"(exports) {
|
|
"use strict";
|
|
var Buffer2 = require_safe_buffer().Buffer;
|
|
var isEncoding = Buffer2.isEncoding || function(encoding) {
|
|
encoding = "" + encoding;
|
|
switch (encoding && encoding.toLowerCase()) {
|
|
case "hex":
|
|
case "utf8":
|
|
case "utf-8":
|
|
case "ascii":
|
|
case "binary":
|
|
case "base64":
|
|
case "ucs2":
|
|
case "ucs-2":
|
|
case "utf16le":
|
|
case "utf-16le":
|
|
case "raw":
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
function _normalizeEncoding(enc) {
|
|
if (!enc) return "utf8";
|
|
var retried;
|
|
while (true) {
|
|
switch (enc) {
|
|
case "utf8":
|
|
case "utf-8":
|
|
return "utf8";
|
|
case "ucs2":
|
|
case "ucs-2":
|
|
case "utf16le":
|
|
case "utf-16le":
|
|
return "utf16le";
|
|
case "latin1":
|
|
case "binary":
|
|
return "latin1";
|
|
case "base64":
|
|
case "ascii":
|
|
case "hex":
|
|
return enc;
|
|
default:
|
|
if (retried) return;
|
|
enc = ("" + enc).toLowerCase();
|
|
retried = true;
|
|
}
|
|
}
|
|
}
|
|
function normalizeEncoding(enc) {
|
|
var nenc = _normalizeEncoding(enc);
|
|
if (typeof nenc !== "string" && (Buffer2.isEncoding === isEncoding || !isEncoding(enc))) throw new Error("Unknown encoding: " + enc);
|
|
return nenc || enc;
|
|
}
|
|
exports.StringDecoder = StringDecoder;
|
|
function StringDecoder(encoding) {
|
|
this.encoding = normalizeEncoding(encoding);
|
|
var nb;
|
|
switch (this.encoding) {
|
|
case "utf16le":
|
|
this.text = utf16Text;
|
|
this.end = utf16End;
|
|
nb = 4;
|
|
break;
|
|
case "utf8":
|
|
this.fillLast = utf8FillLast;
|
|
nb = 4;
|
|
break;
|
|
case "base64":
|
|
this.text = base64Text;
|
|
this.end = base64End;
|
|
nb = 3;
|
|
break;
|
|
default:
|
|
this.write = simpleWrite;
|
|
this.end = simpleEnd;
|
|
return;
|
|
}
|
|
this.lastNeed = 0;
|
|
this.lastTotal = 0;
|
|
this.lastChar = Buffer2.allocUnsafe(nb);
|
|
}
|
|
StringDecoder.prototype.write = function(buf) {
|
|
if (buf.length === 0) return "";
|
|
var r;
|
|
var i;
|
|
if (this.lastNeed) {
|
|
r = this.fillLast(buf);
|
|
if (r === void 0) return "";
|
|
i = this.lastNeed;
|
|
this.lastNeed = 0;
|
|
} else {
|
|
i = 0;
|
|
}
|
|
if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
|
|
return r || "";
|
|
};
|
|
StringDecoder.prototype.end = utf8End;
|
|
StringDecoder.prototype.text = utf8Text;
|
|
StringDecoder.prototype.fillLast = function(buf) {
|
|
if (this.lastNeed <= buf.length) {
|
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
|
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
}
|
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
|
|
this.lastNeed -= buf.length;
|
|
};
|
|
function utf8CheckByte(byte) {
|
|
if (byte <= 127) return 0;
|
|
else if (byte >> 5 === 6) return 2;
|
|
else if (byte >> 4 === 14) return 3;
|
|
else if (byte >> 3 === 30) return 4;
|
|
return byte >> 6 === 2 ? -1 : -2;
|
|
}
|
|
function utf8CheckIncomplete(self2, buf, i) {
|
|
var j = buf.length - 1;
|
|
if (j < i) return 0;
|
|
var nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) self2.lastNeed = nb - 1;
|
|
return nb;
|
|
}
|
|
if (--j < i || nb === -2) return 0;
|
|
nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) self2.lastNeed = nb - 2;
|
|
return nb;
|
|
}
|
|
if (--j < i || nb === -2) return 0;
|
|
nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) {
|
|
if (nb === 2) nb = 0;
|
|
else self2.lastNeed = nb - 3;
|
|
}
|
|
return nb;
|
|
}
|
|
return 0;
|
|
}
|
|
function utf8CheckExtraBytes(self2, buf, p) {
|
|
if ((buf[0] & 192) !== 128) {
|
|
self2.lastNeed = 0;
|
|
return "\uFFFD";
|
|
}
|
|
if (self2.lastNeed > 1 && buf.length > 1) {
|
|
if ((buf[1] & 192) !== 128) {
|
|
self2.lastNeed = 1;
|
|
return "\uFFFD";
|
|
}
|
|
if (self2.lastNeed > 2 && buf.length > 2) {
|
|
if ((buf[2] & 192) !== 128) {
|
|
self2.lastNeed = 2;
|
|
return "\uFFFD";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function utf8FillLast(buf) {
|
|
var p = this.lastTotal - this.lastNeed;
|
|
var r = utf8CheckExtraBytes(this, buf, p);
|
|
if (r !== void 0) return r;
|
|
if (this.lastNeed <= buf.length) {
|
|
buf.copy(this.lastChar, p, 0, this.lastNeed);
|
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
}
|
|
buf.copy(this.lastChar, p, 0, buf.length);
|
|
this.lastNeed -= buf.length;
|
|
}
|
|
function utf8Text(buf, i) {
|
|
var total = utf8CheckIncomplete(this, buf, i);
|
|
if (!this.lastNeed) return buf.toString("utf8", i);
|
|
this.lastTotal = total;
|
|
var end = buf.length - (total - this.lastNeed);
|
|
buf.copy(this.lastChar, 0, end);
|
|
return buf.toString("utf8", i, end);
|
|
}
|
|
function utf8End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : "";
|
|
if (this.lastNeed) return r + "\uFFFD";
|
|
return r;
|
|
}
|
|
function utf16Text(buf, i) {
|
|
if ((buf.length - i) % 2 === 0) {
|
|
var r = buf.toString("utf16le", i);
|
|
if (r) {
|
|
var c = r.charCodeAt(r.length - 1);
|
|
if (c >= 55296 && c <= 56319) {
|
|
this.lastNeed = 2;
|
|
this.lastTotal = 4;
|
|
this.lastChar[0] = buf[buf.length - 2];
|
|
this.lastChar[1] = buf[buf.length - 1];
|
|
return r.slice(0, -1);
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
this.lastNeed = 1;
|
|
this.lastTotal = 2;
|
|
this.lastChar[0] = buf[buf.length - 1];
|
|
return buf.toString("utf16le", i, buf.length - 1);
|
|
}
|
|
function utf16End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : "";
|
|
if (this.lastNeed) {
|
|
var end = this.lastTotal - this.lastNeed;
|
|
return r + this.lastChar.toString("utf16le", 0, end);
|
|
}
|
|
return r;
|
|
}
|
|
function base64Text(buf, i) {
|
|
var n = (buf.length - i) % 3;
|
|
if (n === 0) return buf.toString("base64", i);
|
|
this.lastNeed = 3 - n;
|
|
this.lastTotal = 3;
|
|
if (n === 1) {
|
|
this.lastChar[0] = buf[buf.length - 1];
|
|
} else {
|
|
this.lastChar[0] = buf[buf.length - 2];
|
|
this.lastChar[1] = buf[buf.length - 1];
|
|
}
|
|
return buf.toString("base64", i, buf.length - n);
|
|
}
|
|
function base64End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : "";
|
|
if (this.lastNeed) return r + this.lastChar.toString("base64", 0, 3 - this.lastNeed);
|
|
return r;
|
|
}
|
|
function simpleWrite(buf) {
|
|
return buf.toString(this.encoding);
|
|
}
|
|
function simpleEnd(buf) {
|
|
return buf && buf.length ? this.write(buf) : "";
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/lib/_stream_readable.js
|
|
var require_stream_readable = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/lib/_stream_readable.js"(exports, module) {
|
|
"use strict";
|
|
var pna = require_process_nextick_args();
|
|
module.exports = Readable;
|
|
var isArray = require_isarray();
|
|
var Duplex;
|
|
Readable.ReadableState = ReadableState;
|
|
var EE = __require("events").EventEmitter;
|
|
var EElistenerCount = function(emitter, type) {
|
|
return emitter.listeners(type).length;
|
|
};
|
|
var Stream = require_stream();
|
|
var Buffer2 = require_safe_buffer().Buffer;
|
|
var OurUint8Array = (typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {}).Uint8Array || function() {
|
|
};
|
|
function _uint8ArrayToBuffer(chunk) {
|
|
return Buffer2.from(chunk);
|
|
}
|
|
function _isUint8Array(obj) {
|
|
return Buffer2.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
}
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
var debugUtil = __require("util");
|
|
var debug = void 0;
|
|
if (debugUtil && debugUtil.debuglog) {
|
|
debug = debugUtil.debuglog("stream");
|
|
} else {
|
|
debug = function() {
|
|
};
|
|
}
|
|
var BufferList = require_BufferList();
|
|
var destroyImpl = require_destroy();
|
|
var StringDecoder;
|
|
util.inherits(Readable, Stream);
|
|
var kProxyEvents = ["error", "close", "destroy", "pause", "resume"];
|
|
function prependListener(emitter, event, fn) {
|
|
if (typeof emitter.prependListener === "function") return emitter.prependListener(event, fn);
|
|
if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);
|
|
else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);
|
|
else emitter._events[event] = [fn, emitter._events[event]];
|
|
}
|
|
function ReadableState(options, stream) {
|
|
Duplex = Duplex || require_stream_duplex();
|
|
options = options || {};
|
|
var isDuplex = stream instanceof Duplex;
|
|
this.objectMode = !!options.objectMode;
|
|
if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
|
|
var hwm = options.highWaterMark;
|
|
var readableHwm = options.readableHighWaterMark;
|
|
var defaultHwm = this.objectMode ? 16 : 16 * 1024;
|
|
if (hwm || hwm === 0) this.highWaterMark = hwm;
|
|
else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;
|
|
else this.highWaterMark = defaultHwm;
|
|
this.highWaterMark = Math.floor(this.highWaterMark);
|
|
this.buffer = new BufferList();
|
|
this.length = 0;
|
|
this.pipes = null;
|
|
this.pipesCount = 0;
|
|
this.flowing = null;
|
|
this.ended = false;
|
|
this.endEmitted = false;
|
|
this.reading = false;
|
|
this.sync = true;
|
|
this.needReadable = false;
|
|
this.emittedReadable = false;
|
|
this.readableListening = false;
|
|
this.resumeScheduled = false;
|
|
this.destroyed = false;
|
|
this.defaultEncoding = options.defaultEncoding || "utf8";
|
|
this.awaitDrain = 0;
|
|
this.readingMore = false;
|
|
this.decoder = null;
|
|
this.encoding = null;
|
|
if (options.encoding) {
|
|
if (!StringDecoder) StringDecoder = require_string_decoder().StringDecoder;
|
|
this.decoder = new StringDecoder(options.encoding);
|
|
this.encoding = options.encoding;
|
|
}
|
|
}
|
|
function Readable(options) {
|
|
Duplex = Duplex || require_stream_duplex();
|
|
if (!(this instanceof Readable)) return new Readable(options);
|
|
this._readableState = new ReadableState(options, this);
|
|
this.readable = true;
|
|
if (options) {
|
|
if (typeof options.read === "function") this._read = options.read;
|
|
if (typeof options.destroy === "function") this._destroy = options.destroy;
|
|
}
|
|
Stream.call(this);
|
|
}
|
|
Object.defineProperty(Readable.prototype, "destroyed", {
|
|
get: function() {
|
|
if (this._readableState === void 0) {
|
|
return false;
|
|
}
|
|
return this._readableState.destroyed;
|
|
},
|
|
set: function(value) {
|
|
if (!this._readableState) {
|
|
return;
|
|
}
|
|
this._readableState.destroyed = value;
|
|
}
|
|
});
|
|
Readable.prototype.destroy = destroyImpl.destroy;
|
|
Readable.prototype._undestroy = destroyImpl.undestroy;
|
|
Readable.prototype._destroy = function(err, cb) {
|
|
this.push(null);
|
|
cb(err);
|
|
};
|
|
Readable.prototype.push = function(chunk, encoding) {
|
|
var state = this._readableState;
|
|
var skipChunkCheck;
|
|
if (!state.objectMode) {
|
|
if (typeof chunk === "string") {
|
|
encoding = encoding || state.defaultEncoding;
|
|
if (encoding !== state.encoding) {
|
|
chunk = Buffer2.from(chunk, encoding);
|
|
encoding = "";
|
|
}
|
|
skipChunkCheck = true;
|
|
}
|
|
} else {
|
|
skipChunkCheck = true;
|
|
}
|
|
return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
|
|
};
|
|
Readable.prototype.unshift = function(chunk) {
|
|
return readableAddChunk(this, chunk, null, true, false);
|
|
};
|
|
function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
|
|
var state = stream._readableState;
|
|
if (chunk === null) {
|
|
state.reading = false;
|
|
onEofChunk(stream, state);
|
|
} else {
|
|
var er;
|
|
if (!skipChunkCheck) er = chunkInvalid(state, chunk);
|
|
if (er) {
|
|
stream.emit("error", er);
|
|
} else if (state.objectMode || chunk && chunk.length > 0) {
|
|
if (typeof chunk !== "string" && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer2.prototype) {
|
|
chunk = _uint8ArrayToBuffer(chunk);
|
|
}
|
|
if (addToFront) {
|
|
if (state.endEmitted) stream.emit("error", new Error("stream.unshift() after end event"));
|
|
else addChunk(stream, state, chunk, true);
|
|
} else if (state.ended) {
|
|
stream.emit("error", new Error("stream.push() after EOF"));
|
|
} else {
|
|
state.reading = false;
|
|
if (state.decoder && !encoding) {
|
|
chunk = state.decoder.write(chunk);
|
|
if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);
|
|
else maybeReadMore(stream, state);
|
|
} else {
|
|
addChunk(stream, state, chunk, false);
|
|
}
|
|
}
|
|
} else if (!addToFront) {
|
|
state.reading = false;
|
|
}
|
|
}
|
|
return needMoreData(state);
|
|
}
|
|
function addChunk(stream, state, chunk, addToFront) {
|
|
if (state.flowing && state.length === 0 && !state.sync) {
|
|
stream.emit("data", chunk);
|
|
stream.read(0);
|
|
} else {
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
if (addToFront) state.buffer.unshift(chunk);
|
|
else state.buffer.push(chunk);
|
|
if (state.needReadable) emitReadable(stream);
|
|
}
|
|
maybeReadMore(stream, state);
|
|
}
|
|
function chunkInvalid(state, chunk) {
|
|
var er;
|
|
if (!_isUint8Array(chunk) && typeof chunk !== "string" && chunk !== void 0 && !state.objectMode) {
|
|
er = new TypeError("Invalid non-string/buffer chunk");
|
|
}
|
|
return er;
|
|
}
|
|
function needMoreData(state) {
|
|
return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
|
|
}
|
|
Readable.prototype.isPaused = function() {
|
|
return this._readableState.flowing === false;
|
|
};
|
|
Readable.prototype.setEncoding = function(enc) {
|
|
if (!StringDecoder) StringDecoder = require_string_decoder().StringDecoder;
|
|
this._readableState.decoder = new StringDecoder(enc);
|
|
this._readableState.encoding = enc;
|
|
return this;
|
|
};
|
|
var MAX_HWM = 8388608;
|
|
function computeNewHighWaterMark(n) {
|
|
if (n >= MAX_HWM) {
|
|
n = MAX_HWM;
|
|
} else {
|
|
n--;
|
|
n |= n >>> 1;
|
|
n |= n >>> 2;
|
|
n |= n >>> 4;
|
|
n |= n >>> 8;
|
|
n |= n >>> 16;
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
function howMuchToRead(n, state) {
|
|
if (n <= 0 || state.length === 0 && state.ended) return 0;
|
|
if (state.objectMode) return 1;
|
|
if (n !== n) {
|
|
if (state.flowing && state.length) return state.buffer.head.data.length;
|
|
else return state.length;
|
|
}
|
|
if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
|
|
if (n <= state.length) return n;
|
|
if (!state.ended) {
|
|
state.needReadable = true;
|
|
return 0;
|
|
}
|
|
return state.length;
|
|
}
|
|
Readable.prototype.read = function(n) {
|
|
debug("read", n);
|
|
n = parseInt(n, 10);
|
|
var state = this._readableState;
|
|
var nOrig = n;
|
|
if (n !== 0) state.emittedReadable = false;
|
|
if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
|
|
debug("read: emitReadable", state.length, state.ended);
|
|
if (state.length === 0 && state.ended) endReadable(this);
|
|
else emitReadable(this);
|
|
return null;
|
|
}
|
|
n = howMuchToRead(n, state);
|
|
if (n === 0 && state.ended) {
|
|
if (state.length === 0) endReadable(this);
|
|
return null;
|
|
}
|
|
var doRead = state.needReadable;
|
|
debug("need readable", doRead);
|
|
if (state.length === 0 || state.length - n < state.highWaterMark) {
|
|
doRead = true;
|
|
debug("length less than watermark", doRead);
|
|
}
|
|
if (state.ended || state.reading) {
|
|
doRead = false;
|
|
debug("reading or ended", doRead);
|
|
} else if (doRead) {
|
|
debug("do read");
|
|
state.reading = true;
|
|
state.sync = true;
|
|
if (state.length === 0) state.needReadable = true;
|
|
this._read(state.highWaterMark);
|
|
state.sync = false;
|
|
if (!state.reading) n = howMuchToRead(nOrig, state);
|
|
}
|
|
var ret;
|
|
if (n > 0) ret = fromList(n, state);
|
|
else ret = null;
|
|
if (ret === null) {
|
|
state.needReadable = true;
|
|
n = 0;
|
|
} else {
|
|
state.length -= n;
|
|
}
|
|
if (state.length === 0) {
|
|
if (!state.ended) state.needReadable = true;
|
|
if (nOrig !== n && state.ended) endReadable(this);
|
|
}
|
|
if (ret !== null) this.emit("data", ret);
|
|
return ret;
|
|
};
|
|
function onEofChunk(stream, state) {
|
|
if (state.ended) return;
|
|
if (state.decoder) {
|
|
var chunk = state.decoder.end();
|
|
if (chunk && chunk.length) {
|
|
state.buffer.push(chunk);
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
}
|
|
}
|
|
state.ended = true;
|
|
emitReadable(stream);
|
|
}
|
|
function emitReadable(stream) {
|
|
var state = stream._readableState;
|
|
state.needReadable = false;
|
|
if (!state.emittedReadable) {
|
|
debug("emitReadable", state.flowing);
|
|
state.emittedReadable = true;
|
|
if (state.sync) pna.nextTick(emitReadable_, stream);
|
|
else emitReadable_(stream);
|
|
}
|
|
}
|
|
function emitReadable_(stream) {
|
|
debug("emit readable");
|
|
stream.emit("readable");
|
|
flow(stream);
|
|
}
|
|
function maybeReadMore(stream, state) {
|
|
if (!state.readingMore) {
|
|
state.readingMore = true;
|
|
pna.nextTick(maybeReadMore_, stream, state);
|
|
}
|
|
}
|
|
function maybeReadMore_(stream, state) {
|
|
var len = state.length;
|
|
while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
|
|
debug("maybeReadMore read 0");
|
|
stream.read(0);
|
|
if (len === state.length)
|
|
break;
|
|
else len = state.length;
|
|
}
|
|
state.readingMore = false;
|
|
}
|
|
Readable.prototype._read = function(n) {
|
|
this.emit("error", new Error("_read() is not implemented"));
|
|
};
|
|
Readable.prototype.pipe = function(dest, pipeOpts) {
|
|
var src = this;
|
|
var state = this._readableState;
|
|
switch (state.pipesCount) {
|
|
case 0:
|
|
state.pipes = dest;
|
|
break;
|
|
case 1:
|
|
state.pipes = [state.pipes, dest];
|
|
break;
|
|
default:
|
|
state.pipes.push(dest);
|
|
break;
|
|
}
|
|
state.pipesCount += 1;
|
|
debug("pipe count=%d opts=%j", state.pipesCount, pipeOpts);
|
|
var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
|
|
var endFn = doEnd ? onend : unpipe;
|
|
if (state.endEmitted) pna.nextTick(endFn);
|
|
else src.once("end", endFn);
|
|
dest.on("unpipe", onunpipe);
|
|
function onunpipe(readable, unpipeInfo) {
|
|
debug("onunpipe");
|
|
if (readable === src) {
|
|
if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
|
|
unpipeInfo.hasUnpiped = true;
|
|
cleanup();
|
|
}
|
|
}
|
|
}
|
|
function onend() {
|
|
debug("onend");
|
|
dest.end();
|
|
}
|
|
var ondrain = pipeOnDrain(src);
|
|
dest.on("drain", ondrain);
|
|
var cleanedUp = false;
|
|
function cleanup() {
|
|
debug("cleanup");
|
|
dest.removeListener("close", onclose);
|
|
dest.removeListener("finish", onfinish);
|
|
dest.removeListener("drain", ondrain);
|
|
dest.removeListener("error", onerror);
|
|
dest.removeListener("unpipe", onunpipe);
|
|
src.removeListener("end", onend);
|
|
src.removeListener("end", unpipe);
|
|
src.removeListener("data", ondata);
|
|
cleanedUp = true;
|
|
if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
|
|
}
|
|
var increasedAwaitDrain = false;
|
|
src.on("data", ondata);
|
|
function ondata(chunk) {
|
|
debug("ondata");
|
|
increasedAwaitDrain = false;
|
|
var ret = dest.write(chunk);
|
|
if (false === ret && !increasedAwaitDrain) {
|
|
if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
|
|
debug("false write response, pause", state.awaitDrain);
|
|
state.awaitDrain++;
|
|
increasedAwaitDrain = true;
|
|
}
|
|
src.pause();
|
|
}
|
|
}
|
|
function onerror(er) {
|
|
debug("onerror", er);
|
|
unpipe();
|
|
dest.removeListener("error", onerror);
|
|
if (EElistenerCount(dest, "error") === 0) dest.emit("error", er);
|
|
}
|
|
prependListener(dest, "error", onerror);
|
|
function onclose() {
|
|
dest.removeListener("finish", onfinish);
|
|
unpipe();
|
|
}
|
|
dest.once("close", onclose);
|
|
function onfinish() {
|
|
debug("onfinish");
|
|
dest.removeListener("close", onclose);
|
|
unpipe();
|
|
}
|
|
dest.once("finish", onfinish);
|
|
function unpipe() {
|
|
debug("unpipe");
|
|
src.unpipe(dest);
|
|
}
|
|
dest.emit("pipe", src);
|
|
if (!state.flowing) {
|
|
debug("pipe resume");
|
|
src.resume();
|
|
}
|
|
return dest;
|
|
};
|
|
function pipeOnDrain(src) {
|
|
return function() {
|
|
var state = src._readableState;
|
|
debug("pipeOnDrain", state.awaitDrain);
|
|
if (state.awaitDrain) state.awaitDrain--;
|
|
if (state.awaitDrain === 0 && EElistenerCount(src, "data")) {
|
|
state.flowing = true;
|
|
flow(src);
|
|
}
|
|
};
|
|
}
|
|
Readable.prototype.unpipe = function(dest) {
|
|
var state = this._readableState;
|
|
var unpipeInfo = { hasUnpiped: false };
|
|
if (state.pipesCount === 0) return this;
|
|
if (state.pipesCount === 1) {
|
|
if (dest && dest !== state.pipes) return this;
|
|
if (!dest) dest = state.pipes;
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
if (dest) dest.emit("unpipe", this, unpipeInfo);
|
|
return this;
|
|
}
|
|
if (!dest) {
|
|
var dests = state.pipes;
|
|
var len = state.pipesCount;
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
for (var i = 0; i < len; i++) {
|
|
dests[i].emit("unpipe", this, { hasUnpiped: false });
|
|
}
|
|
return this;
|
|
}
|
|
var index = indexOf(state.pipes, dest);
|
|
if (index === -1) return this;
|
|
state.pipes.splice(index, 1);
|
|
state.pipesCount -= 1;
|
|
if (state.pipesCount === 1) state.pipes = state.pipes[0];
|
|
dest.emit("unpipe", this, unpipeInfo);
|
|
return this;
|
|
};
|
|
Readable.prototype.on = function(ev, fn) {
|
|
var res = Stream.prototype.on.call(this, ev, fn);
|
|
if (ev === "data") {
|
|
if (this._readableState.flowing !== false) this.resume();
|
|
} else if (ev === "readable") {
|
|
var state = this._readableState;
|
|
if (!state.endEmitted && !state.readableListening) {
|
|
state.readableListening = state.needReadable = true;
|
|
state.emittedReadable = false;
|
|
if (!state.reading) {
|
|
pna.nextTick(nReadingNextTick, this);
|
|
} else if (state.length) {
|
|
emitReadable(this);
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Readable.prototype.addListener = Readable.prototype.on;
|
|
function nReadingNextTick(self2) {
|
|
debug("readable nexttick read 0");
|
|
self2.read(0);
|
|
}
|
|
Readable.prototype.resume = function() {
|
|
var state = this._readableState;
|
|
if (!state.flowing) {
|
|
debug("resume");
|
|
state.flowing = true;
|
|
resume(this, state);
|
|
}
|
|
return this;
|
|
};
|
|
function resume(stream, state) {
|
|
if (!state.resumeScheduled) {
|
|
state.resumeScheduled = true;
|
|
pna.nextTick(resume_, stream, state);
|
|
}
|
|
}
|
|
function resume_(stream, state) {
|
|
if (!state.reading) {
|
|
debug("resume read 0");
|
|
stream.read(0);
|
|
}
|
|
state.resumeScheduled = false;
|
|
state.awaitDrain = 0;
|
|
stream.emit("resume");
|
|
flow(stream);
|
|
if (state.flowing && !state.reading) stream.read(0);
|
|
}
|
|
Readable.prototype.pause = function() {
|
|
debug("call pause flowing=%j", this._readableState.flowing);
|
|
if (false !== this._readableState.flowing) {
|
|
debug("pause");
|
|
this._readableState.flowing = false;
|
|
this.emit("pause");
|
|
}
|
|
return this;
|
|
};
|
|
function flow(stream) {
|
|
var state = stream._readableState;
|
|
debug("flow", state.flowing);
|
|
while (state.flowing && stream.read() !== null) {
|
|
}
|
|
}
|
|
Readable.prototype.wrap = function(stream) {
|
|
var _this = this;
|
|
var state = this._readableState;
|
|
var paused = false;
|
|
stream.on("end", function() {
|
|
debug("wrapped end");
|
|
if (state.decoder && !state.ended) {
|
|
var chunk = state.decoder.end();
|
|
if (chunk && chunk.length) _this.push(chunk);
|
|
}
|
|
_this.push(null);
|
|
});
|
|
stream.on("data", function(chunk) {
|
|
debug("wrapped data");
|
|
if (state.decoder) chunk = state.decoder.write(chunk);
|
|
if (state.objectMode && (chunk === null || chunk === void 0)) return;
|
|
else if (!state.objectMode && (!chunk || !chunk.length)) return;
|
|
var ret = _this.push(chunk);
|
|
if (!ret) {
|
|
paused = true;
|
|
stream.pause();
|
|
}
|
|
});
|
|
for (var i in stream) {
|
|
if (this[i] === void 0 && typeof stream[i] === "function") {
|
|
this[i] = /* @__PURE__ */ (function(method) {
|
|
return function() {
|
|
return stream[method].apply(stream, arguments);
|
|
};
|
|
})(i);
|
|
}
|
|
}
|
|
for (var n = 0; n < kProxyEvents.length; n++) {
|
|
stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n]));
|
|
}
|
|
this._read = function(n2) {
|
|
debug("wrapped _read", n2);
|
|
if (paused) {
|
|
paused = false;
|
|
stream.resume();
|
|
}
|
|
};
|
|
return this;
|
|
};
|
|
Object.defineProperty(Readable.prototype, "readableHighWaterMark", {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function() {
|
|
return this._readableState.highWaterMark;
|
|
}
|
|
});
|
|
Readable._fromList = fromList;
|
|
function fromList(n, state) {
|
|
if (state.length === 0) return null;
|
|
var ret;
|
|
if (state.objectMode) ret = state.buffer.shift();
|
|
else if (!n || n >= state.length) {
|
|
if (state.decoder) ret = state.buffer.join("");
|
|
else if (state.buffer.length === 1) ret = state.buffer.head.data;
|
|
else ret = state.buffer.concat(state.length);
|
|
state.buffer.clear();
|
|
} else {
|
|
ret = fromListPartial(n, state.buffer, state.decoder);
|
|
}
|
|
return ret;
|
|
}
|
|
function fromListPartial(n, list, hasStrings) {
|
|
var ret;
|
|
if (n < list.head.data.length) {
|
|
ret = list.head.data.slice(0, n);
|
|
list.head.data = list.head.data.slice(n);
|
|
} else if (n === list.head.data.length) {
|
|
ret = list.shift();
|
|
} else {
|
|
ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
|
|
}
|
|
return ret;
|
|
}
|
|
function copyFromBufferString(n, list) {
|
|
var p = list.head;
|
|
var c = 1;
|
|
var ret = p.data;
|
|
n -= ret.length;
|
|
while (p = p.next) {
|
|
var str = p.data;
|
|
var nb = n > str.length ? str.length : n;
|
|
if (nb === str.length) ret += str;
|
|
else ret += str.slice(0, n);
|
|
n -= nb;
|
|
if (n === 0) {
|
|
if (nb === str.length) {
|
|
++c;
|
|
if (p.next) list.head = p.next;
|
|
else list.head = list.tail = null;
|
|
} else {
|
|
list.head = p;
|
|
p.data = str.slice(nb);
|
|
}
|
|
break;
|
|
}
|
|
++c;
|
|
}
|
|
list.length -= c;
|
|
return ret;
|
|
}
|
|
function copyFromBuffer(n, list) {
|
|
var ret = Buffer2.allocUnsafe(n);
|
|
var p = list.head;
|
|
var c = 1;
|
|
p.data.copy(ret);
|
|
n -= p.data.length;
|
|
while (p = p.next) {
|
|
var buf = p.data;
|
|
var nb = n > buf.length ? buf.length : n;
|
|
buf.copy(ret, ret.length - n, 0, nb);
|
|
n -= nb;
|
|
if (n === 0) {
|
|
if (nb === buf.length) {
|
|
++c;
|
|
if (p.next) list.head = p.next;
|
|
else list.head = list.tail = null;
|
|
} else {
|
|
list.head = p;
|
|
p.data = buf.slice(nb);
|
|
}
|
|
break;
|
|
}
|
|
++c;
|
|
}
|
|
list.length -= c;
|
|
return ret;
|
|
}
|
|
function endReadable(stream) {
|
|
var state = stream._readableState;
|
|
if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream');
|
|
if (!state.endEmitted) {
|
|
state.ended = true;
|
|
pna.nextTick(endReadableNT, state, stream);
|
|
}
|
|
}
|
|
function endReadableNT(state, stream) {
|
|
if (!state.endEmitted && state.length === 0) {
|
|
state.endEmitted = true;
|
|
stream.readable = false;
|
|
stream.emit("end");
|
|
}
|
|
}
|
|
function indexOf(xs, x) {
|
|
for (var i = 0, l = xs.length; i < l; i++) {
|
|
if (xs[i] === x) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/lib/_stream_transform.js
|
|
var require_stream_transform = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/lib/_stream_transform.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Transform;
|
|
var Duplex = require_stream_duplex();
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
util.inherits(Transform, Duplex);
|
|
function afterTransform(er, data) {
|
|
var ts = this._transformState;
|
|
ts.transforming = false;
|
|
var cb = ts.writecb;
|
|
if (!cb) {
|
|
return this.emit("error", new Error("write callback called multiple times"));
|
|
}
|
|
ts.writechunk = null;
|
|
ts.writecb = null;
|
|
if (data != null)
|
|
this.push(data);
|
|
cb(er);
|
|
var rs = this._readableState;
|
|
rs.reading = false;
|
|
if (rs.needReadable || rs.length < rs.highWaterMark) {
|
|
this._read(rs.highWaterMark);
|
|
}
|
|
}
|
|
function Transform(options) {
|
|
if (!(this instanceof Transform)) return new Transform(options);
|
|
Duplex.call(this, options);
|
|
this._transformState = {
|
|
afterTransform: afterTransform.bind(this),
|
|
needTransform: false,
|
|
transforming: false,
|
|
writecb: null,
|
|
writechunk: null,
|
|
writeencoding: null
|
|
};
|
|
this._readableState.needReadable = true;
|
|
this._readableState.sync = false;
|
|
if (options) {
|
|
if (typeof options.transform === "function") this._transform = options.transform;
|
|
if (typeof options.flush === "function") this._flush = options.flush;
|
|
}
|
|
this.on("prefinish", prefinish);
|
|
}
|
|
function prefinish() {
|
|
var _this = this;
|
|
if (typeof this._flush === "function") {
|
|
this._flush(function(er, data) {
|
|
done(_this, er, data);
|
|
});
|
|
} else {
|
|
done(this, null, null);
|
|
}
|
|
}
|
|
Transform.prototype.push = function(chunk, encoding) {
|
|
this._transformState.needTransform = false;
|
|
return Duplex.prototype.push.call(this, chunk, encoding);
|
|
};
|
|
Transform.prototype._transform = function(chunk, encoding, cb) {
|
|
throw new Error("_transform() is not implemented");
|
|
};
|
|
Transform.prototype._write = function(chunk, encoding, cb) {
|
|
var ts = this._transformState;
|
|
ts.writecb = cb;
|
|
ts.writechunk = chunk;
|
|
ts.writeencoding = encoding;
|
|
if (!ts.transforming) {
|
|
var rs = this._readableState;
|
|
if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
|
|
}
|
|
};
|
|
Transform.prototype._read = function(n) {
|
|
var ts = this._transformState;
|
|
if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
|
|
ts.transforming = true;
|
|
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
|
|
} else {
|
|
ts.needTransform = true;
|
|
}
|
|
};
|
|
Transform.prototype._destroy = function(err, cb) {
|
|
var _this2 = this;
|
|
Duplex.prototype._destroy.call(this, err, function(err2) {
|
|
cb(err2);
|
|
_this2.emit("close");
|
|
});
|
|
};
|
|
function done(stream, er, data) {
|
|
if (er) return stream.emit("error", er);
|
|
if (data != null)
|
|
stream.push(data);
|
|
if (stream._writableState.length) throw new Error("Calling transform done when ws.length != 0");
|
|
if (stream._transformState.transforming) throw new Error("Calling transform done when still transforming");
|
|
return stream.push(null);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/lib/_stream_passthrough.js
|
|
var require_stream_passthrough = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/lib/_stream_passthrough.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = PassThrough;
|
|
var Transform = require_stream_transform();
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
util.inherits(PassThrough, Transform);
|
|
function PassThrough(options) {
|
|
if (!(this instanceof PassThrough)) return new PassThrough(options);
|
|
Transform.call(this, options);
|
|
}
|
|
PassThrough.prototype._transform = function(chunk, encoding, cb) {
|
|
cb(null, chunk);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/readable.js
|
|
var require_readable = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/readable.js"(exports, module) {
|
|
var Stream = __require("stream");
|
|
if (process.env.READABLE_STREAM === "disable" && Stream) {
|
|
module.exports = Stream;
|
|
exports = module.exports = Stream.Readable;
|
|
exports.Readable = Stream.Readable;
|
|
exports.Writable = Stream.Writable;
|
|
exports.Duplex = Stream.Duplex;
|
|
exports.Transform = Stream.Transform;
|
|
exports.PassThrough = Stream.PassThrough;
|
|
exports.Stream = Stream;
|
|
} else {
|
|
exports = module.exports = require_stream_readable();
|
|
exports.Stream = Stream || exports;
|
|
exports.Readable = exports;
|
|
exports.Writable = require_stream_writable();
|
|
exports.Duplex = require_stream_duplex();
|
|
exports.Transform = require_stream_transform();
|
|
exports.PassThrough = require_stream_passthrough();
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/node_modules/readable-stream/duplex.js
|
|
var require_duplex = __commonJS({
|
|
"../../node_modules/bl/node_modules/readable-stream/duplex.js"(exports, module) {
|
|
module.exports = require_readable().Duplex;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bl/bl.js
|
|
var require_bl = __commonJS({
|
|
"../../node_modules/bl/bl.js"(exports, module) {
|
|
var DuplexStream = require_duplex();
|
|
var util = __require("util");
|
|
var Buffer2 = require_safe_buffer().Buffer;
|
|
function BufferList(callback) {
|
|
if (!(this instanceof BufferList))
|
|
return new BufferList(callback);
|
|
this._bufs = [];
|
|
this.length = 0;
|
|
if (typeof callback == "function") {
|
|
this._callback = callback;
|
|
var piper = function piper2(err) {
|
|
if (this._callback) {
|
|
this._callback(err);
|
|
this._callback = null;
|
|
}
|
|
}.bind(this);
|
|
this.on("pipe", function onPipe(src) {
|
|
src.on("error", piper);
|
|
});
|
|
this.on("unpipe", function onUnpipe(src) {
|
|
src.removeListener("error", piper);
|
|
});
|
|
} else {
|
|
this.append(callback);
|
|
}
|
|
DuplexStream.call(this);
|
|
}
|
|
util.inherits(BufferList, DuplexStream);
|
|
BufferList.prototype._offset = function _offset(offset) {
|
|
var tot = 0, i = 0, _t;
|
|
if (offset === 0) return [0, 0];
|
|
for (; i < this._bufs.length; i++) {
|
|
_t = tot + this._bufs[i].length;
|
|
if (offset < _t || i == this._bufs.length - 1)
|
|
return [i, offset - tot];
|
|
tot = _t;
|
|
}
|
|
};
|
|
BufferList.prototype.append = function append(buf) {
|
|
var i = 0;
|
|
if (Buffer2.isBuffer(buf)) {
|
|
this._appendBuffer(buf);
|
|
} else if (Array.isArray(buf)) {
|
|
for (; i < buf.length; i++)
|
|
this.append(buf[i]);
|
|
} else if (buf instanceof BufferList) {
|
|
for (; i < buf._bufs.length; i++)
|
|
this.append(buf._bufs[i]);
|
|
} else if (buf != null) {
|
|
if (typeof buf == "number")
|
|
buf = buf.toString();
|
|
this._appendBuffer(Buffer2.from(buf));
|
|
}
|
|
return this;
|
|
};
|
|
BufferList.prototype._appendBuffer = function appendBuffer(buf) {
|
|
this._bufs.push(buf);
|
|
this.length += buf.length;
|
|
};
|
|
BufferList.prototype._write = function _write(buf, encoding, callback) {
|
|
this._appendBuffer(buf);
|
|
if (typeof callback == "function")
|
|
callback();
|
|
};
|
|
BufferList.prototype._read = function _read(size) {
|
|
if (!this.length)
|
|
return this.push(null);
|
|
size = Math.min(size, this.length);
|
|
this.push(this.slice(0, size));
|
|
this.consume(size);
|
|
};
|
|
BufferList.prototype.end = function end(chunk) {
|
|
DuplexStream.prototype.end.call(this, chunk);
|
|
if (this._callback) {
|
|
this._callback(null, this.slice());
|
|
this._callback = null;
|
|
}
|
|
};
|
|
BufferList.prototype.get = function get(index) {
|
|
return this.slice(index, index + 1)[0];
|
|
};
|
|
BufferList.prototype.slice = function slice(start, end) {
|
|
if (typeof start == "number" && start < 0)
|
|
start += this.length;
|
|
if (typeof end == "number" && end < 0)
|
|
end += this.length;
|
|
return this.copy(null, 0, start, end);
|
|
};
|
|
BufferList.prototype.copy = function copy(dst, dstStart, srcStart, srcEnd) {
|
|
if (typeof srcStart != "number" || srcStart < 0)
|
|
srcStart = 0;
|
|
if (typeof srcEnd != "number" || srcEnd > this.length)
|
|
srcEnd = this.length;
|
|
if (srcStart >= this.length)
|
|
return dst || Buffer2.alloc(0);
|
|
if (srcEnd <= 0)
|
|
return dst || Buffer2.alloc(0);
|
|
var copy2 = !!dst, off = this._offset(srcStart), len = srcEnd - srcStart, bytes = len, bufoff = copy2 && dstStart || 0, start = off[1], l, i;
|
|
if (srcStart === 0 && srcEnd == this.length) {
|
|
if (!copy2) {
|
|
return this._bufs.length === 1 ? this._bufs[0] : Buffer2.concat(this._bufs, this.length);
|
|
}
|
|
for (i = 0; i < this._bufs.length; i++) {
|
|
this._bufs[i].copy(dst, bufoff);
|
|
bufoff += this._bufs[i].length;
|
|
}
|
|
return dst;
|
|
}
|
|
if (bytes <= this._bufs[off[0]].length - start) {
|
|
return copy2 ? this._bufs[off[0]].copy(dst, dstStart, start, start + bytes) : this._bufs[off[0]].slice(start, start + bytes);
|
|
}
|
|
if (!copy2)
|
|
dst = Buffer2.allocUnsafe(len);
|
|
for (i = off[0]; i < this._bufs.length; i++) {
|
|
l = this._bufs[i].length - start;
|
|
if (bytes > l) {
|
|
this._bufs[i].copy(dst, bufoff, start);
|
|
bufoff += l;
|
|
} else {
|
|
this._bufs[i].copy(dst, bufoff, start, start + bytes);
|
|
bufoff += l;
|
|
break;
|
|
}
|
|
bytes -= l;
|
|
if (start)
|
|
start = 0;
|
|
}
|
|
if (dst.length > bufoff) return dst.slice(0, bufoff);
|
|
return dst;
|
|
};
|
|
BufferList.prototype.shallowSlice = function shallowSlice(start, end) {
|
|
start = start || 0;
|
|
end = end || this.length;
|
|
if (start < 0)
|
|
start += this.length;
|
|
if (end < 0)
|
|
end += this.length;
|
|
var startOffset = this._offset(start), endOffset = this._offset(end), buffers = this._bufs.slice(startOffset[0], endOffset[0] + 1);
|
|
if (endOffset[1] == 0)
|
|
buffers.pop();
|
|
else
|
|
buffers[buffers.length - 1] = buffers[buffers.length - 1].slice(0, endOffset[1]);
|
|
if (startOffset[1] != 0)
|
|
buffers[0] = buffers[0].slice(startOffset[1]);
|
|
return new BufferList(buffers);
|
|
};
|
|
BufferList.prototype.toString = function toString(encoding, start, end) {
|
|
return this.slice(start, end).toString(encoding);
|
|
};
|
|
BufferList.prototype.consume = function consume(bytes) {
|
|
bytes = Math.trunc(bytes);
|
|
if (Number.isNaN(bytes) || bytes <= 0) return this;
|
|
while (this._bufs.length) {
|
|
if (bytes >= this._bufs[0].length) {
|
|
bytes -= this._bufs[0].length;
|
|
this.length -= this._bufs[0].length;
|
|
this._bufs.shift();
|
|
} else {
|
|
this._bufs[0] = this._bufs[0].slice(bytes);
|
|
this.length -= bytes;
|
|
break;
|
|
}
|
|
}
|
|
return this;
|
|
};
|
|
BufferList.prototype.duplicate = function duplicate() {
|
|
var i = 0, copy = new BufferList();
|
|
for (; i < this._bufs.length; i++)
|
|
copy.append(this._bufs[i]);
|
|
return copy;
|
|
};
|
|
BufferList.prototype.destroy = function destroy() {
|
|
this._bufs.length = 0;
|
|
this.length = 0;
|
|
this.push(null);
|
|
};
|
|
(function() {
|
|
var methods = {
|
|
"readDoubleBE": 8,
|
|
"readDoubleLE": 8,
|
|
"readFloatBE": 4,
|
|
"readFloatLE": 4,
|
|
"readInt32BE": 4,
|
|
"readInt32LE": 4,
|
|
"readUInt32BE": 4,
|
|
"readUInt32LE": 4,
|
|
"readInt16BE": 2,
|
|
"readInt16LE": 2,
|
|
"readUInt16BE": 2,
|
|
"readUInt16LE": 2,
|
|
"readInt8": 1,
|
|
"readUInt8": 1
|
|
};
|
|
for (var m in methods) {
|
|
(function(m2) {
|
|
BufferList.prototype[m2] = function(offset) {
|
|
return this.slice(offset, offset + methods[m2])[m2](0);
|
|
};
|
|
})(m);
|
|
}
|
|
})();
|
|
module.exports = BufferList;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/xtend/immutable.js
|
|
var require_immutable = __commonJS({
|
|
"../../node_modules/xtend/immutable.js"(exports, module) {
|
|
module.exports = extend;
|
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
function extend() {
|
|
var target = {};
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
var source = arguments[i];
|
|
for (var key in source) {
|
|
if (hasOwnProperty.call(source, key)) {
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
return target;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/safe-buffer/index.js
|
|
var require_safe_buffer2 = __commonJS({
|
|
"../../node_modules/safe-buffer/index.js"(exports, module) {
|
|
var buffer = __require("buffer");
|
|
var Buffer2 = buffer.Buffer;
|
|
function copyProps(src, dst) {
|
|
for (var key in src) {
|
|
dst[key] = src[key];
|
|
}
|
|
}
|
|
if (Buffer2.from && Buffer2.alloc && Buffer2.allocUnsafe && Buffer2.allocUnsafeSlow) {
|
|
module.exports = buffer;
|
|
} else {
|
|
copyProps(buffer, exports);
|
|
exports.Buffer = SafeBuffer;
|
|
}
|
|
function SafeBuffer(arg, encodingOrOffset, length) {
|
|
return Buffer2(arg, encodingOrOffset, length);
|
|
}
|
|
SafeBuffer.prototype = Object.create(Buffer2.prototype);
|
|
copyProps(Buffer2, SafeBuffer);
|
|
SafeBuffer.from = function(arg, encodingOrOffset, length) {
|
|
if (typeof arg === "number") {
|
|
throw new TypeError("Argument must not be a number");
|
|
}
|
|
return Buffer2(arg, encodingOrOffset, length);
|
|
};
|
|
SafeBuffer.alloc = function(size, fill, encoding) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
var buf = Buffer2(size);
|
|
if (fill !== void 0) {
|
|
if (typeof encoding === "string") {
|
|
buf.fill(fill, encoding);
|
|
} else {
|
|
buf.fill(fill);
|
|
}
|
|
} else {
|
|
buf.fill(0);
|
|
}
|
|
return buf;
|
|
};
|
|
SafeBuffer.allocUnsafe = function(size) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
return Buffer2(size);
|
|
};
|
|
SafeBuffer.allocUnsafeSlow = function(size) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
return buffer.SlowBuffer(size);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/isarray/index.js
|
|
var require_isarray2 = __commonJS({
|
|
"../../node_modules/isarray/index.js"(exports, module) {
|
|
var toString = {}.toString;
|
|
module.exports = Array.isArray || function(arr) {
|
|
return toString.call(arr) == "[object Array]";
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-errors/type.js
|
|
var require_type = __commonJS({
|
|
"../../node_modules/es-errors/type.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = TypeError;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-object-atoms/index.js
|
|
var require_es_object_atoms = __commonJS({
|
|
"../../node_modules/es-object-atoms/index.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Object;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-errors/index.js
|
|
var require_es_errors = __commonJS({
|
|
"../../node_modules/es-errors/index.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Error;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-errors/eval.js
|
|
var require_eval = __commonJS({
|
|
"../../node_modules/es-errors/eval.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = EvalError;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-errors/range.js
|
|
var require_range = __commonJS({
|
|
"../../node_modules/es-errors/range.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = RangeError;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-errors/ref.js
|
|
var require_ref = __commonJS({
|
|
"../../node_modules/es-errors/ref.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = ReferenceError;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-errors/syntax.js
|
|
var require_syntax = __commonJS({
|
|
"../../node_modules/es-errors/syntax.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = SyntaxError;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-errors/uri.js
|
|
var require_uri = __commonJS({
|
|
"../../node_modules/es-errors/uri.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = URIError;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/math-intrinsics/abs.js
|
|
var require_abs = __commonJS({
|
|
"../../node_modules/math-intrinsics/abs.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Math.abs;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/math-intrinsics/floor.js
|
|
var require_floor = __commonJS({
|
|
"../../node_modules/math-intrinsics/floor.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Math.floor;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/math-intrinsics/max.js
|
|
var require_max = __commonJS({
|
|
"../../node_modules/math-intrinsics/max.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Math.max;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/math-intrinsics/min.js
|
|
var require_min = __commonJS({
|
|
"../../node_modules/math-intrinsics/min.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Math.min;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/math-intrinsics/pow.js
|
|
var require_pow = __commonJS({
|
|
"../../node_modules/math-intrinsics/pow.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Math.pow;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/math-intrinsics/round.js
|
|
var require_round = __commonJS({
|
|
"../../node_modules/math-intrinsics/round.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Math.round;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/math-intrinsics/isNaN.js
|
|
var require_isNaN = __commonJS({
|
|
"../../node_modules/math-intrinsics/isNaN.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Number.isNaN || function isNaN2(a) {
|
|
return a !== a;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/math-intrinsics/sign.js
|
|
var require_sign = __commonJS({
|
|
"../../node_modules/math-intrinsics/sign.js"(exports, module) {
|
|
"use strict";
|
|
var $isNaN = require_isNaN();
|
|
module.exports = function sign(number) {
|
|
if ($isNaN(number) || number === 0) {
|
|
return number;
|
|
}
|
|
return number < 0 ? -1 : 1;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/gopd/gOPD.js
|
|
var require_gOPD = __commonJS({
|
|
"../../node_modules/gopd/gOPD.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Object.getOwnPropertyDescriptor;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/gopd/index.js
|
|
var require_gopd = __commonJS({
|
|
"../../node_modules/gopd/index.js"(exports, module) {
|
|
"use strict";
|
|
var $gOPD = require_gOPD();
|
|
if ($gOPD) {
|
|
try {
|
|
$gOPD([], "length");
|
|
} catch (e) {
|
|
$gOPD = null;
|
|
}
|
|
}
|
|
module.exports = $gOPD;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-define-property/index.js
|
|
var require_es_define_property = __commonJS({
|
|
"../../node_modules/es-define-property/index.js"(exports, module) {
|
|
"use strict";
|
|
var $defineProperty = Object.defineProperty || false;
|
|
if ($defineProperty) {
|
|
try {
|
|
$defineProperty({}, "a", { value: 1 });
|
|
} catch (e) {
|
|
$defineProperty = false;
|
|
}
|
|
}
|
|
module.exports = $defineProperty;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/has-symbols/shams.js
|
|
var require_shams = __commonJS({
|
|
"../../node_modules/has-symbols/shams.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = function hasSymbols() {
|
|
if (typeof Symbol !== "function" || typeof Object.getOwnPropertySymbols !== "function") {
|
|
return false;
|
|
}
|
|
if (typeof Symbol.iterator === "symbol") {
|
|
return true;
|
|
}
|
|
var obj = {};
|
|
var sym = Symbol("test");
|
|
var symObj = Object(sym);
|
|
if (typeof sym === "string") {
|
|
return false;
|
|
}
|
|
if (Object.prototype.toString.call(sym) !== "[object Symbol]") {
|
|
return false;
|
|
}
|
|
if (Object.prototype.toString.call(symObj) !== "[object Symbol]") {
|
|
return false;
|
|
}
|
|
var symVal = 42;
|
|
obj[sym] = symVal;
|
|
for (var _ in obj) {
|
|
return false;
|
|
}
|
|
if (typeof Object.keys === "function" && Object.keys(obj).length !== 0) {
|
|
return false;
|
|
}
|
|
if (typeof Object.getOwnPropertyNames === "function" && Object.getOwnPropertyNames(obj).length !== 0) {
|
|
return false;
|
|
}
|
|
var syms = Object.getOwnPropertySymbols(obj);
|
|
if (syms.length !== 1 || syms[0] !== sym) {
|
|
return false;
|
|
}
|
|
if (!Object.prototype.propertyIsEnumerable.call(obj, sym)) {
|
|
return false;
|
|
}
|
|
if (typeof Object.getOwnPropertyDescriptor === "function") {
|
|
var descriptor = (
|
|
/** @type {PropertyDescriptor} */
|
|
Object.getOwnPropertyDescriptor(obj, sym)
|
|
);
|
|
if (descriptor.value !== symVal || descriptor.enumerable !== true) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/has-symbols/index.js
|
|
var require_has_symbols = __commonJS({
|
|
"../../node_modules/has-symbols/index.js"(exports, module) {
|
|
"use strict";
|
|
var origSymbol = typeof Symbol !== "undefined" && Symbol;
|
|
var hasSymbolSham = require_shams();
|
|
module.exports = function hasNativeSymbols() {
|
|
if (typeof origSymbol !== "function") {
|
|
return false;
|
|
}
|
|
if (typeof Symbol !== "function") {
|
|
return false;
|
|
}
|
|
if (typeof origSymbol("foo") !== "symbol") {
|
|
return false;
|
|
}
|
|
if (typeof Symbol("bar") !== "symbol") {
|
|
return false;
|
|
}
|
|
return hasSymbolSham();
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/get-proto/Reflect.getPrototypeOf.js
|
|
var require_Reflect_getPrototypeOf = __commonJS({
|
|
"../../node_modules/get-proto/Reflect.getPrototypeOf.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = typeof Reflect !== "undefined" && Reflect.getPrototypeOf || null;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/get-proto/Object.getPrototypeOf.js
|
|
var require_Object_getPrototypeOf = __commonJS({
|
|
"../../node_modules/get-proto/Object.getPrototypeOf.js"(exports, module) {
|
|
"use strict";
|
|
var $Object = require_es_object_atoms();
|
|
module.exports = $Object.getPrototypeOf || null;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/function-bind/implementation.js
|
|
var require_implementation = __commonJS({
|
|
"../../node_modules/function-bind/implementation.js"(exports, module) {
|
|
"use strict";
|
|
var ERROR_MESSAGE = "Function.prototype.bind called on incompatible ";
|
|
var toStr = Object.prototype.toString;
|
|
var max = Math.max;
|
|
var funcType = "[object Function]";
|
|
var concatty = function concatty2(a, b) {
|
|
var arr = [];
|
|
for (var i = 0; i < a.length; i += 1) {
|
|
arr[i] = a[i];
|
|
}
|
|
for (var j = 0; j < b.length; j += 1) {
|
|
arr[j + a.length] = b[j];
|
|
}
|
|
return arr;
|
|
};
|
|
var slicy = function slicy2(arrLike, offset) {
|
|
var arr = [];
|
|
for (var i = offset || 0, j = 0; i < arrLike.length; i += 1, j += 1) {
|
|
arr[j] = arrLike[i];
|
|
}
|
|
return arr;
|
|
};
|
|
var joiny = function(arr, joiner) {
|
|
var str = "";
|
|
for (var i = 0; i < arr.length; i += 1) {
|
|
str += arr[i];
|
|
if (i + 1 < arr.length) {
|
|
str += joiner;
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
module.exports = function bind(that) {
|
|
var target = this;
|
|
if (typeof target !== "function" || toStr.apply(target) !== funcType) {
|
|
throw new TypeError(ERROR_MESSAGE + target);
|
|
}
|
|
var args = slicy(arguments, 1);
|
|
var bound;
|
|
var binder = function() {
|
|
if (this instanceof bound) {
|
|
var result = target.apply(
|
|
this,
|
|
concatty(args, arguments)
|
|
);
|
|
if (Object(result) === result) {
|
|
return result;
|
|
}
|
|
return this;
|
|
}
|
|
return target.apply(
|
|
that,
|
|
concatty(args, arguments)
|
|
);
|
|
};
|
|
var boundLength = max(0, target.length - args.length);
|
|
var boundArgs = [];
|
|
for (var i = 0; i < boundLength; i++) {
|
|
boundArgs[i] = "$" + i;
|
|
}
|
|
bound = Function("binder", "return function (" + joiny(boundArgs, ",") + "){ return binder.apply(this,arguments); }")(binder);
|
|
if (target.prototype) {
|
|
var Empty = function Empty2() {
|
|
};
|
|
Empty.prototype = target.prototype;
|
|
bound.prototype = new Empty();
|
|
Empty.prototype = null;
|
|
}
|
|
return bound;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/function-bind/index.js
|
|
var require_function_bind = __commonJS({
|
|
"../../node_modules/function-bind/index.js"(exports, module) {
|
|
"use strict";
|
|
var implementation = require_implementation();
|
|
module.exports = Function.prototype.bind || implementation;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/call-bind-apply-helpers/functionCall.js
|
|
var require_functionCall = __commonJS({
|
|
"../../node_modules/call-bind-apply-helpers/functionCall.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Function.prototype.call;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/call-bind-apply-helpers/functionApply.js
|
|
var require_functionApply = __commonJS({
|
|
"../../node_modules/call-bind-apply-helpers/functionApply.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Function.prototype.apply;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/call-bind-apply-helpers/reflectApply.js
|
|
var require_reflectApply = __commonJS({
|
|
"../../node_modules/call-bind-apply-helpers/reflectApply.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = typeof Reflect !== "undefined" && Reflect && Reflect.apply;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/call-bind-apply-helpers/actualApply.js
|
|
var require_actualApply = __commonJS({
|
|
"../../node_modules/call-bind-apply-helpers/actualApply.js"(exports, module) {
|
|
"use strict";
|
|
var bind = require_function_bind();
|
|
var $apply = require_functionApply();
|
|
var $call = require_functionCall();
|
|
var $reflectApply = require_reflectApply();
|
|
module.exports = $reflectApply || bind.call($call, $apply);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/call-bind-apply-helpers/index.js
|
|
var require_call_bind_apply_helpers = __commonJS({
|
|
"../../node_modules/call-bind-apply-helpers/index.js"(exports, module) {
|
|
"use strict";
|
|
var bind = require_function_bind();
|
|
var $TypeError = require_type();
|
|
var $call = require_functionCall();
|
|
var $actualApply = require_actualApply();
|
|
module.exports = function callBindBasic(args) {
|
|
if (args.length < 1 || typeof args[0] !== "function") {
|
|
throw new $TypeError("a function is required");
|
|
}
|
|
return $actualApply(bind, $call, args);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dunder-proto/get.js
|
|
var require_get = __commonJS({
|
|
"../../node_modules/dunder-proto/get.js"(exports, module) {
|
|
"use strict";
|
|
var callBind = require_call_bind_apply_helpers();
|
|
var gOPD = require_gopd();
|
|
var hasProtoAccessor;
|
|
try {
|
|
hasProtoAccessor = /** @type {{ __proto__?: typeof Array.prototype }} */
|
|
[].__proto__ === Array.prototype;
|
|
} catch (e) {
|
|
if (!e || typeof e !== "object" || !("code" in e) || e.code !== "ERR_PROTO_ACCESS") {
|
|
throw e;
|
|
}
|
|
}
|
|
var desc = !!hasProtoAccessor && gOPD && gOPD(
|
|
Object.prototype,
|
|
/** @type {keyof typeof Object.prototype} */
|
|
"__proto__"
|
|
);
|
|
var $Object = Object;
|
|
var $getPrototypeOf = $Object.getPrototypeOf;
|
|
module.exports = desc && typeof desc.get === "function" ? callBind([desc.get]) : typeof $getPrototypeOf === "function" ? (
|
|
/** @type {import('./get')} */
|
|
function getDunder(value) {
|
|
return $getPrototypeOf(value == null ? value : $Object(value));
|
|
}
|
|
) : false;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/get-proto/index.js
|
|
var require_get_proto = __commonJS({
|
|
"../../node_modules/get-proto/index.js"(exports, module) {
|
|
"use strict";
|
|
var reflectGetProto = require_Reflect_getPrototypeOf();
|
|
var originalGetProto = require_Object_getPrototypeOf();
|
|
var getDunderProto = require_get();
|
|
module.exports = reflectGetProto ? function getProto(O) {
|
|
return reflectGetProto(O);
|
|
} : originalGetProto ? function getProto(O) {
|
|
if (!O || typeof O !== "object" && typeof O !== "function") {
|
|
throw new TypeError("getProto: not an object");
|
|
}
|
|
return originalGetProto(O);
|
|
} : getDunderProto ? function getProto(O) {
|
|
return getDunderProto(O);
|
|
} : null;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hasown/index.js
|
|
var require_hasown = __commonJS({
|
|
"../../node_modules/hasown/index.js"(exports, module) {
|
|
"use strict";
|
|
var call = Function.prototype.call;
|
|
var $hasOwn = Object.prototype.hasOwnProperty;
|
|
var bind = require_function_bind();
|
|
module.exports = bind.call(call, $hasOwn);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/get-intrinsic/index.js
|
|
var require_get_intrinsic = __commonJS({
|
|
"../../node_modules/get-intrinsic/index.js"(exports, module) {
|
|
"use strict";
|
|
var undefined2;
|
|
var $Object = require_es_object_atoms();
|
|
var $Error = require_es_errors();
|
|
var $EvalError = require_eval();
|
|
var $RangeError = require_range();
|
|
var $ReferenceError = require_ref();
|
|
var $SyntaxError = require_syntax();
|
|
var $TypeError = require_type();
|
|
var $URIError = require_uri();
|
|
var abs = require_abs();
|
|
var floor = require_floor();
|
|
var max = require_max();
|
|
var min = require_min();
|
|
var pow = require_pow();
|
|
var round = require_round();
|
|
var sign = require_sign();
|
|
var $Function = Function;
|
|
var getEvalledConstructor = function(expressionSyntax) {
|
|
try {
|
|
return $Function('"use strict"; return (' + expressionSyntax + ").constructor;")();
|
|
} catch (e) {
|
|
}
|
|
};
|
|
var $gOPD = require_gopd();
|
|
var $defineProperty = require_es_define_property();
|
|
var throwTypeError = function() {
|
|
throw new $TypeError();
|
|
};
|
|
var ThrowTypeError = $gOPD ? (function() {
|
|
try {
|
|
arguments.callee;
|
|
return throwTypeError;
|
|
} catch (calleeThrows) {
|
|
try {
|
|
return $gOPD(arguments, "callee").get;
|
|
} catch (gOPDthrows) {
|
|
return throwTypeError;
|
|
}
|
|
}
|
|
})() : throwTypeError;
|
|
var hasSymbols = require_has_symbols()();
|
|
var getProto = require_get_proto();
|
|
var $ObjectGPO = require_Object_getPrototypeOf();
|
|
var $ReflectGPO = require_Reflect_getPrototypeOf();
|
|
var $apply = require_functionApply();
|
|
var $call = require_functionCall();
|
|
var needsEval = {};
|
|
var TypedArray = typeof Uint8Array === "undefined" || !getProto ? undefined2 : getProto(Uint8Array);
|
|
var INTRINSICS = {
|
|
__proto__: null,
|
|
"%AggregateError%": typeof AggregateError === "undefined" ? undefined2 : AggregateError,
|
|
"%Array%": Array,
|
|
"%ArrayBuffer%": typeof ArrayBuffer === "undefined" ? undefined2 : ArrayBuffer,
|
|
"%ArrayIteratorPrototype%": hasSymbols && getProto ? getProto([][Symbol.iterator]()) : undefined2,
|
|
"%AsyncFromSyncIteratorPrototype%": undefined2,
|
|
"%AsyncFunction%": needsEval,
|
|
"%AsyncGenerator%": needsEval,
|
|
"%AsyncGeneratorFunction%": needsEval,
|
|
"%AsyncIteratorPrototype%": needsEval,
|
|
"%Atomics%": typeof Atomics === "undefined" ? undefined2 : Atomics,
|
|
"%BigInt%": typeof BigInt === "undefined" ? undefined2 : BigInt,
|
|
"%BigInt64Array%": typeof BigInt64Array === "undefined" ? undefined2 : BigInt64Array,
|
|
"%BigUint64Array%": typeof BigUint64Array === "undefined" ? undefined2 : BigUint64Array,
|
|
"%Boolean%": Boolean,
|
|
"%DataView%": typeof DataView === "undefined" ? undefined2 : DataView,
|
|
"%Date%": Date,
|
|
"%decodeURI%": decodeURI,
|
|
"%decodeURIComponent%": decodeURIComponent,
|
|
"%encodeURI%": encodeURI,
|
|
"%encodeURIComponent%": encodeURIComponent,
|
|
"%Error%": $Error,
|
|
"%eval%": eval,
|
|
// eslint-disable-line no-eval
|
|
"%EvalError%": $EvalError,
|
|
"%Float16Array%": typeof Float16Array === "undefined" ? undefined2 : Float16Array,
|
|
"%Float32Array%": typeof Float32Array === "undefined" ? undefined2 : Float32Array,
|
|
"%Float64Array%": typeof Float64Array === "undefined" ? undefined2 : Float64Array,
|
|
"%FinalizationRegistry%": typeof FinalizationRegistry === "undefined" ? undefined2 : FinalizationRegistry,
|
|
"%Function%": $Function,
|
|
"%GeneratorFunction%": needsEval,
|
|
"%Int8Array%": typeof Int8Array === "undefined" ? undefined2 : Int8Array,
|
|
"%Int16Array%": typeof Int16Array === "undefined" ? undefined2 : Int16Array,
|
|
"%Int32Array%": typeof Int32Array === "undefined" ? undefined2 : Int32Array,
|
|
"%isFinite%": isFinite,
|
|
"%isNaN%": isNaN,
|
|
"%IteratorPrototype%": hasSymbols && getProto ? getProto(getProto([][Symbol.iterator]())) : undefined2,
|
|
"%JSON%": typeof JSON === "object" ? JSON : undefined2,
|
|
"%Map%": typeof Map === "undefined" ? undefined2 : Map,
|
|
"%MapIteratorPrototype%": typeof Map === "undefined" || !hasSymbols || !getProto ? undefined2 : getProto((/* @__PURE__ */ new Map())[Symbol.iterator]()),
|
|
"%Math%": Math,
|
|
"%Number%": Number,
|
|
"%Object%": $Object,
|
|
"%Object.getOwnPropertyDescriptor%": $gOPD,
|
|
"%parseFloat%": parseFloat,
|
|
"%parseInt%": parseInt,
|
|
"%Promise%": typeof Promise === "undefined" ? undefined2 : Promise,
|
|
"%Proxy%": typeof Proxy === "undefined" ? undefined2 : Proxy,
|
|
"%RangeError%": $RangeError,
|
|
"%ReferenceError%": $ReferenceError,
|
|
"%Reflect%": typeof Reflect === "undefined" ? undefined2 : Reflect,
|
|
"%RegExp%": RegExp,
|
|
"%Set%": typeof Set === "undefined" ? undefined2 : Set,
|
|
"%SetIteratorPrototype%": typeof Set === "undefined" || !hasSymbols || !getProto ? undefined2 : getProto((/* @__PURE__ */ new Set())[Symbol.iterator]()),
|
|
"%SharedArrayBuffer%": typeof SharedArrayBuffer === "undefined" ? undefined2 : SharedArrayBuffer,
|
|
"%String%": String,
|
|
"%StringIteratorPrototype%": hasSymbols && getProto ? getProto(""[Symbol.iterator]()) : undefined2,
|
|
"%Symbol%": hasSymbols ? Symbol : undefined2,
|
|
"%SyntaxError%": $SyntaxError,
|
|
"%ThrowTypeError%": ThrowTypeError,
|
|
"%TypedArray%": TypedArray,
|
|
"%TypeError%": $TypeError,
|
|
"%Uint8Array%": typeof Uint8Array === "undefined" ? undefined2 : Uint8Array,
|
|
"%Uint8ClampedArray%": typeof Uint8ClampedArray === "undefined" ? undefined2 : Uint8ClampedArray,
|
|
"%Uint16Array%": typeof Uint16Array === "undefined" ? undefined2 : Uint16Array,
|
|
"%Uint32Array%": typeof Uint32Array === "undefined" ? undefined2 : Uint32Array,
|
|
"%URIError%": $URIError,
|
|
"%WeakMap%": typeof WeakMap === "undefined" ? undefined2 : WeakMap,
|
|
"%WeakRef%": typeof WeakRef === "undefined" ? undefined2 : WeakRef,
|
|
"%WeakSet%": typeof WeakSet === "undefined" ? undefined2 : WeakSet,
|
|
"%Function.prototype.call%": $call,
|
|
"%Function.prototype.apply%": $apply,
|
|
"%Object.defineProperty%": $defineProperty,
|
|
"%Object.getPrototypeOf%": $ObjectGPO,
|
|
"%Math.abs%": abs,
|
|
"%Math.floor%": floor,
|
|
"%Math.max%": max,
|
|
"%Math.min%": min,
|
|
"%Math.pow%": pow,
|
|
"%Math.round%": round,
|
|
"%Math.sign%": sign,
|
|
"%Reflect.getPrototypeOf%": $ReflectGPO
|
|
};
|
|
if (getProto) {
|
|
try {
|
|
null.error;
|
|
} catch (e) {
|
|
errorProto = getProto(getProto(e));
|
|
INTRINSICS["%Error.prototype%"] = errorProto;
|
|
}
|
|
}
|
|
var errorProto;
|
|
var doEval = function doEval2(name) {
|
|
var value;
|
|
if (name === "%AsyncFunction%") {
|
|
value = getEvalledConstructor("async function () {}");
|
|
} else if (name === "%GeneratorFunction%") {
|
|
value = getEvalledConstructor("function* () {}");
|
|
} else if (name === "%AsyncGeneratorFunction%") {
|
|
value = getEvalledConstructor("async function* () {}");
|
|
} else if (name === "%AsyncGenerator%") {
|
|
var fn = doEval2("%AsyncGeneratorFunction%");
|
|
if (fn) {
|
|
value = fn.prototype;
|
|
}
|
|
} else if (name === "%AsyncIteratorPrototype%") {
|
|
var gen = doEval2("%AsyncGenerator%");
|
|
if (gen && getProto) {
|
|
value = getProto(gen.prototype);
|
|
}
|
|
}
|
|
INTRINSICS[name] = value;
|
|
return value;
|
|
};
|
|
var LEGACY_ALIASES = {
|
|
__proto__: null,
|
|
"%ArrayBufferPrototype%": ["ArrayBuffer", "prototype"],
|
|
"%ArrayPrototype%": ["Array", "prototype"],
|
|
"%ArrayProto_entries%": ["Array", "prototype", "entries"],
|
|
"%ArrayProto_forEach%": ["Array", "prototype", "forEach"],
|
|
"%ArrayProto_keys%": ["Array", "prototype", "keys"],
|
|
"%ArrayProto_values%": ["Array", "prototype", "values"],
|
|
"%AsyncFunctionPrototype%": ["AsyncFunction", "prototype"],
|
|
"%AsyncGenerator%": ["AsyncGeneratorFunction", "prototype"],
|
|
"%AsyncGeneratorPrototype%": ["AsyncGeneratorFunction", "prototype", "prototype"],
|
|
"%BooleanPrototype%": ["Boolean", "prototype"],
|
|
"%DataViewPrototype%": ["DataView", "prototype"],
|
|
"%DatePrototype%": ["Date", "prototype"],
|
|
"%ErrorPrototype%": ["Error", "prototype"],
|
|
"%EvalErrorPrototype%": ["EvalError", "prototype"],
|
|
"%Float32ArrayPrototype%": ["Float32Array", "prototype"],
|
|
"%Float64ArrayPrototype%": ["Float64Array", "prototype"],
|
|
"%FunctionPrototype%": ["Function", "prototype"],
|
|
"%Generator%": ["GeneratorFunction", "prototype"],
|
|
"%GeneratorPrototype%": ["GeneratorFunction", "prototype", "prototype"],
|
|
"%Int8ArrayPrototype%": ["Int8Array", "prototype"],
|
|
"%Int16ArrayPrototype%": ["Int16Array", "prototype"],
|
|
"%Int32ArrayPrototype%": ["Int32Array", "prototype"],
|
|
"%JSONParse%": ["JSON", "parse"],
|
|
"%JSONStringify%": ["JSON", "stringify"],
|
|
"%MapPrototype%": ["Map", "prototype"],
|
|
"%NumberPrototype%": ["Number", "prototype"],
|
|
"%ObjectPrototype%": ["Object", "prototype"],
|
|
"%ObjProto_toString%": ["Object", "prototype", "toString"],
|
|
"%ObjProto_valueOf%": ["Object", "prototype", "valueOf"],
|
|
"%PromisePrototype%": ["Promise", "prototype"],
|
|
"%PromiseProto_then%": ["Promise", "prototype", "then"],
|
|
"%Promise_all%": ["Promise", "all"],
|
|
"%Promise_reject%": ["Promise", "reject"],
|
|
"%Promise_resolve%": ["Promise", "resolve"],
|
|
"%RangeErrorPrototype%": ["RangeError", "prototype"],
|
|
"%ReferenceErrorPrototype%": ["ReferenceError", "prototype"],
|
|
"%RegExpPrototype%": ["RegExp", "prototype"],
|
|
"%SetPrototype%": ["Set", "prototype"],
|
|
"%SharedArrayBufferPrototype%": ["SharedArrayBuffer", "prototype"],
|
|
"%StringPrototype%": ["String", "prototype"],
|
|
"%SymbolPrototype%": ["Symbol", "prototype"],
|
|
"%SyntaxErrorPrototype%": ["SyntaxError", "prototype"],
|
|
"%TypedArrayPrototype%": ["TypedArray", "prototype"],
|
|
"%TypeErrorPrototype%": ["TypeError", "prototype"],
|
|
"%Uint8ArrayPrototype%": ["Uint8Array", "prototype"],
|
|
"%Uint8ClampedArrayPrototype%": ["Uint8ClampedArray", "prototype"],
|
|
"%Uint16ArrayPrototype%": ["Uint16Array", "prototype"],
|
|
"%Uint32ArrayPrototype%": ["Uint32Array", "prototype"],
|
|
"%URIErrorPrototype%": ["URIError", "prototype"],
|
|
"%WeakMapPrototype%": ["WeakMap", "prototype"],
|
|
"%WeakSetPrototype%": ["WeakSet", "prototype"]
|
|
};
|
|
var bind = require_function_bind();
|
|
var hasOwn = require_hasown();
|
|
var $concat = bind.call($call, Array.prototype.concat);
|
|
var $spliceApply = bind.call($apply, Array.prototype.splice);
|
|
var $replace = bind.call($call, String.prototype.replace);
|
|
var $strSlice = bind.call($call, String.prototype.slice);
|
|
var $exec = bind.call($call, RegExp.prototype.exec);
|
|
var rePropName = /[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g;
|
|
var reEscapeChar = /\\(\\)?/g;
|
|
var stringToPath = function stringToPath2(string) {
|
|
var first = $strSlice(string, 0, 1);
|
|
var last = $strSlice(string, -1);
|
|
if (first === "%" && last !== "%") {
|
|
throw new $SyntaxError("invalid intrinsic syntax, expected closing `%`");
|
|
} else if (last === "%" && first !== "%") {
|
|
throw new $SyntaxError("invalid intrinsic syntax, expected opening `%`");
|
|
}
|
|
var result = [];
|
|
$replace(string, rePropName, function(match, number, quote, subString) {
|
|
result[result.length] = quote ? $replace(subString, reEscapeChar, "$1") : number || match;
|
|
});
|
|
return result;
|
|
};
|
|
var getBaseIntrinsic = function getBaseIntrinsic2(name, allowMissing) {
|
|
var intrinsicName = name;
|
|
var alias;
|
|
if (hasOwn(LEGACY_ALIASES, intrinsicName)) {
|
|
alias = LEGACY_ALIASES[intrinsicName];
|
|
intrinsicName = "%" + alias[0] + "%";
|
|
}
|
|
if (hasOwn(INTRINSICS, intrinsicName)) {
|
|
var value = INTRINSICS[intrinsicName];
|
|
if (value === needsEval) {
|
|
value = doEval(intrinsicName);
|
|
}
|
|
if (typeof value === "undefined" && !allowMissing) {
|
|
throw new $TypeError("intrinsic " + name + " exists, but is not available. Please file an issue!");
|
|
}
|
|
return {
|
|
alias,
|
|
name: intrinsicName,
|
|
value
|
|
};
|
|
}
|
|
throw new $SyntaxError("intrinsic " + name + " does not exist!");
|
|
};
|
|
module.exports = function GetIntrinsic(name, allowMissing) {
|
|
if (typeof name !== "string" || name.length === 0) {
|
|
throw new $TypeError("intrinsic name must be a non-empty string");
|
|
}
|
|
if (arguments.length > 1 && typeof allowMissing !== "boolean") {
|
|
throw new $TypeError('"allowMissing" argument must be a boolean');
|
|
}
|
|
if ($exec(/^%?[^%]*%?$/, name) === null) {
|
|
throw new $SyntaxError("`%` may not be present anywhere but at the beginning and end of the intrinsic name");
|
|
}
|
|
var parts = stringToPath(name);
|
|
var intrinsicBaseName = parts.length > 0 ? parts[0] : "";
|
|
var intrinsic = getBaseIntrinsic("%" + intrinsicBaseName + "%", allowMissing);
|
|
var intrinsicRealName = intrinsic.name;
|
|
var value = intrinsic.value;
|
|
var skipFurtherCaching = false;
|
|
var alias = intrinsic.alias;
|
|
if (alias) {
|
|
intrinsicBaseName = alias[0];
|
|
$spliceApply(parts, $concat([0, 1], alias));
|
|
}
|
|
for (var i = 1, isOwn = true; i < parts.length; i += 1) {
|
|
var part = parts[i];
|
|
var first = $strSlice(part, 0, 1);
|
|
var last = $strSlice(part, -1);
|
|
if ((first === '"' || first === "'" || first === "`" || (last === '"' || last === "'" || last === "`")) && first !== last) {
|
|
throw new $SyntaxError("property names with quotes must have matching quotes");
|
|
}
|
|
if (part === "constructor" || !isOwn) {
|
|
skipFurtherCaching = true;
|
|
}
|
|
intrinsicBaseName += "." + part;
|
|
intrinsicRealName = "%" + intrinsicBaseName + "%";
|
|
if (hasOwn(INTRINSICS, intrinsicRealName)) {
|
|
value = INTRINSICS[intrinsicRealName];
|
|
} else if (value != null) {
|
|
if (!(part in value)) {
|
|
if (!allowMissing) {
|
|
throw new $TypeError("base intrinsic for " + name + " exists, but the property is not available.");
|
|
}
|
|
return void undefined2;
|
|
}
|
|
if ($gOPD && i + 1 >= parts.length) {
|
|
var desc = $gOPD(value, part);
|
|
isOwn = !!desc;
|
|
if (isOwn && "get" in desc && !("originalValue" in desc.get)) {
|
|
value = desc.get;
|
|
} else {
|
|
value = value[part];
|
|
}
|
|
} else {
|
|
isOwn = hasOwn(value, part);
|
|
value = value[part];
|
|
}
|
|
if (isOwn && !skipFurtherCaching) {
|
|
INTRINSICS[intrinsicRealName] = value;
|
|
}
|
|
}
|
|
}
|
|
return value;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/call-bound/index.js
|
|
var require_call_bound = __commonJS({
|
|
"../../node_modules/call-bound/index.js"(exports, module) {
|
|
"use strict";
|
|
var GetIntrinsic = require_get_intrinsic();
|
|
var callBindBasic = require_call_bind_apply_helpers();
|
|
var $indexOf = callBindBasic([GetIntrinsic("%String.prototype.indexOf%")]);
|
|
module.exports = function callBoundIntrinsic(name, allowMissing) {
|
|
var intrinsic = (
|
|
/** @type {(this: unknown, ...args: unknown[]) => unknown} */
|
|
GetIntrinsic(name, !!allowMissing)
|
|
);
|
|
if (typeof intrinsic === "function" && $indexOf(name, ".prototype.") > -1) {
|
|
return callBindBasic(
|
|
/** @type {const} */
|
|
[intrinsic]
|
|
);
|
|
}
|
|
return intrinsic;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/is-callable/index.js
|
|
var require_is_callable = __commonJS({
|
|
"../../node_modules/is-callable/index.js"(exports, module) {
|
|
"use strict";
|
|
var fnToStr = Function.prototype.toString;
|
|
var reflectApply = typeof Reflect === "object" && Reflect !== null && Reflect.apply;
|
|
var badArrayLike;
|
|
var isCallableMarker;
|
|
if (typeof reflectApply === "function" && typeof Object.defineProperty === "function") {
|
|
try {
|
|
badArrayLike = Object.defineProperty({}, "length", {
|
|
get: function() {
|
|
throw isCallableMarker;
|
|
}
|
|
});
|
|
isCallableMarker = {};
|
|
reflectApply(function() {
|
|
throw 42;
|
|
}, null, badArrayLike);
|
|
} catch (_) {
|
|
if (_ !== isCallableMarker) {
|
|
reflectApply = null;
|
|
}
|
|
}
|
|
} else {
|
|
reflectApply = null;
|
|
}
|
|
var constructorRegex = /^\s*class\b/;
|
|
var isES6ClassFn = function isES6ClassFunction(value) {
|
|
try {
|
|
var fnStr = fnToStr.call(value);
|
|
return constructorRegex.test(fnStr);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
var tryFunctionObject = function tryFunctionToStr(value) {
|
|
try {
|
|
if (isES6ClassFn(value)) {
|
|
return false;
|
|
}
|
|
fnToStr.call(value);
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
var toStr = Object.prototype.toString;
|
|
var objectClass = "[object Object]";
|
|
var fnClass = "[object Function]";
|
|
var genClass = "[object GeneratorFunction]";
|
|
var ddaClass = "[object HTMLAllCollection]";
|
|
var ddaClass2 = "[object HTML document.all class]";
|
|
var ddaClass3 = "[object HTMLCollection]";
|
|
var hasToStringTag = typeof Symbol === "function" && !!Symbol.toStringTag;
|
|
var isIE68 = !(0 in [,]);
|
|
var isDDA = function isDocumentDotAll() {
|
|
return false;
|
|
};
|
|
if (typeof document === "object") {
|
|
all = document.all;
|
|
if (toStr.call(all) === toStr.call(document.all)) {
|
|
isDDA = function isDocumentDotAll(value) {
|
|
if ((isIE68 || !value) && (typeof value === "undefined" || typeof value === "object")) {
|
|
try {
|
|
var str = toStr.call(value);
|
|
return (str === ddaClass || str === ddaClass2 || str === ddaClass3 || str === objectClass) && value("") == null;
|
|
} catch (e) {
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
}
|
|
}
|
|
var all;
|
|
module.exports = reflectApply ? function isCallable(value) {
|
|
if (isDDA(value)) {
|
|
return true;
|
|
}
|
|
if (!value) {
|
|
return false;
|
|
}
|
|
if (typeof value !== "function" && typeof value !== "object") {
|
|
return false;
|
|
}
|
|
try {
|
|
reflectApply(value, null, badArrayLike);
|
|
} catch (e) {
|
|
if (e !== isCallableMarker) {
|
|
return false;
|
|
}
|
|
}
|
|
return !isES6ClassFn(value) && tryFunctionObject(value);
|
|
} : function isCallable(value) {
|
|
if (isDDA(value)) {
|
|
return true;
|
|
}
|
|
if (!value) {
|
|
return false;
|
|
}
|
|
if (typeof value !== "function" && typeof value !== "object") {
|
|
return false;
|
|
}
|
|
if (hasToStringTag) {
|
|
return tryFunctionObject(value);
|
|
}
|
|
if (isES6ClassFn(value)) {
|
|
return false;
|
|
}
|
|
var strClass = toStr.call(value);
|
|
if (strClass !== fnClass && strClass !== genClass && !/^\[object HTML/.test(strClass)) {
|
|
return false;
|
|
}
|
|
return tryFunctionObject(value);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/for-each/index.js
|
|
var require_for_each = __commonJS({
|
|
"../../node_modules/for-each/index.js"(exports, module) {
|
|
"use strict";
|
|
var isCallable = require_is_callable();
|
|
var toStr = Object.prototype.toString;
|
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
var forEachArray = function forEachArray2(array, iterator, receiver) {
|
|
for (var i = 0, len = array.length; i < len; i++) {
|
|
if (hasOwnProperty.call(array, i)) {
|
|
if (receiver == null) {
|
|
iterator(array[i], i, array);
|
|
} else {
|
|
iterator.call(receiver, array[i], i, array);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var forEachString = function forEachString2(string, iterator, receiver) {
|
|
for (var i = 0, len = string.length; i < len; i++) {
|
|
if (receiver == null) {
|
|
iterator(string.charAt(i), i, string);
|
|
} else {
|
|
iterator.call(receiver, string.charAt(i), i, string);
|
|
}
|
|
}
|
|
};
|
|
var forEachObject = function forEachObject2(object, iterator, receiver) {
|
|
for (var k in object) {
|
|
if (hasOwnProperty.call(object, k)) {
|
|
if (receiver == null) {
|
|
iterator(object[k], k, object);
|
|
} else {
|
|
iterator.call(receiver, object[k], k, object);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
function isArray(x) {
|
|
return toStr.call(x) === "[object Array]";
|
|
}
|
|
module.exports = function forEach(list, iterator, thisArg) {
|
|
if (!isCallable(iterator)) {
|
|
throw new TypeError("iterator must be a function");
|
|
}
|
|
var receiver;
|
|
if (arguments.length >= 3) {
|
|
receiver = thisArg;
|
|
}
|
|
if (isArray(list)) {
|
|
forEachArray(list, iterator, receiver);
|
|
} else if (typeof list === "string") {
|
|
forEachString(list, iterator, receiver);
|
|
} else {
|
|
forEachObject(list, iterator, receiver);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/possible-typed-array-names/index.js
|
|
var require_possible_typed_array_names = __commonJS({
|
|
"../../node_modules/possible-typed-array-names/index.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = [
|
|
"Float16Array",
|
|
"Float32Array",
|
|
"Float64Array",
|
|
"Int8Array",
|
|
"Int16Array",
|
|
"Int32Array",
|
|
"Uint8Array",
|
|
"Uint8ClampedArray",
|
|
"Uint16Array",
|
|
"Uint32Array",
|
|
"BigInt64Array",
|
|
"BigUint64Array"
|
|
];
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/available-typed-arrays/index.js
|
|
var require_available_typed_arrays = __commonJS({
|
|
"../../node_modules/available-typed-arrays/index.js"(exports, module) {
|
|
"use strict";
|
|
var possibleNames = require_possible_typed_array_names();
|
|
var g = typeof globalThis === "undefined" ? global : globalThis;
|
|
module.exports = function availableTypedArrays() {
|
|
var out = [];
|
|
for (var i = 0; i < possibleNames.length; i++) {
|
|
if (typeof g[possibleNames[i]] === "function") {
|
|
out[out.length] = possibleNames[i];
|
|
}
|
|
}
|
|
return out;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/define-data-property/index.js
|
|
var require_define_data_property = __commonJS({
|
|
"../../node_modules/define-data-property/index.js"(exports, module) {
|
|
"use strict";
|
|
var $defineProperty = require_es_define_property();
|
|
var $SyntaxError = require_syntax();
|
|
var $TypeError = require_type();
|
|
var gopd = require_gopd();
|
|
module.exports = function defineDataProperty(obj, property, value) {
|
|
if (!obj || typeof obj !== "object" && typeof obj !== "function") {
|
|
throw new $TypeError("`obj` must be an object or a function`");
|
|
}
|
|
if (typeof property !== "string" && typeof property !== "symbol") {
|
|
throw new $TypeError("`property` must be a string or a symbol`");
|
|
}
|
|
if (arguments.length > 3 && typeof arguments[3] !== "boolean" && arguments[3] !== null) {
|
|
throw new $TypeError("`nonEnumerable`, if provided, must be a boolean or null");
|
|
}
|
|
if (arguments.length > 4 && typeof arguments[4] !== "boolean" && arguments[4] !== null) {
|
|
throw new $TypeError("`nonWritable`, if provided, must be a boolean or null");
|
|
}
|
|
if (arguments.length > 5 && typeof arguments[5] !== "boolean" && arguments[5] !== null) {
|
|
throw new $TypeError("`nonConfigurable`, if provided, must be a boolean or null");
|
|
}
|
|
if (arguments.length > 6 && typeof arguments[6] !== "boolean") {
|
|
throw new $TypeError("`loose`, if provided, must be a boolean");
|
|
}
|
|
var nonEnumerable = arguments.length > 3 ? arguments[3] : null;
|
|
var nonWritable = arguments.length > 4 ? arguments[4] : null;
|
|
var nonConfigurable = arguments.length > 5 ? arguments[5] : null;
|
|
var loose = arguments.length > 6 ? arguments[6] : false;
|
|
var desc = !!gopd && gopd(obj, property);
|
|
if ($defineProperty) {
|
|
$defineProperty(obj, property, {
|
|
configurable: nonConfigurable === null && desc ? desc.configurable : !nonConfigurable,
|
|
enumerable: nonEnumerable === null && desc ? desc.enumerable : !nonEnumerable,
|
|
value,
|
|
writable: nonWritable === null && desc ? desc.writable : !nonWritable
|
|
});
|
|
} else if (loose || !nonEnumerable && !nonWritable && !nonConfigurable) {
|
|
obj[property] = value;
|
|
} else {
|
|
throw new $SyntaxError("This environment does not support defining a property as non-configurable, non-writable, or non-enumerable.");
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/has-property-descriptors/index.js
|
|
var require_has_property_descriptors = __commonJS({
|
|
"../../node_modules/has-property-descriptors/index.js"(exports, module) {
|
|
"use strict";
|
|
var $defineProperty = require_es_define_property();
|
|
var hasPropertyDescriptors = function hasPropertyDescriptors2() {
|
|
return !!$defineProperty;
|
|
};
|
|
hasPropertyDescriptors.hasArrayLengthDefineBug = function hasArrayLengthDefineBug() {
|
|
if (!$defineProperty) {
|
|
return null;
|
|
}
|
|
try {
|
|
return $defineProperty([], "length", { value: 1 }).length !== 1;
|
|
} catch (e) {
|
|
return true;
|
|
}
|
|
};
|
|
module.exports = hasPropertyDescriptors;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/set-function-length/index.js
|
|
var require_set_function_length = __commonJS({
|
|
"../../node_modules/set-function-length/index.js"(exports, module) {
|
|
"use strict";
|
|
var GetIntrinsic = require_get_intrinsic();
|
|
var define = require_define_data_property();
|
|
var hasDescriptors = require_has_property_descriptors()();
|
|
var gOPD = require_gopd();
|
|
var $TypeError = require_type();
|
|
var $floor = GetIntrinsic("%Math.floor%");
|
|
module.exports = function setFunctionLength(fn, length) {
|
|
if (typeof fn !== "function") {
|
|
throw new $TypeError("`fn` is not a function");
|
|
}
|
|
if (typeof length !== "number" || length < 0 || length > 4294967295 || $floor(length) !== length) {
|
|
throw new $TypeError("`length` must be a positive 32-bit integer");
|
|
}
|
|
var loose = arguments.length > 2 && !!arguments[2];
|
|
var functionLengthIsConfigurable = true;
|
|
var functionLengthIsWritable = true;
|
|
if ("length" in fn && gOPD) {
|
|
var desc = gOPD(fn, "length");
|
|
if (desc && !desc.configurable) {
|
|
functionLengthIsConfigurable = false;
|
|
}
|
|
if (desc && !desc.writable) {
|
|
functionLengthIsWritable = false;
|
|
}
|
|
}
|
|
if (functionLengthIsConfigurable || functionLengthIsWritable || !loose) {
|
|
if (hasDescriptors) {
|
|
define(
|
|
/** @type {Parameters<define>[0]} */
|
|
fn,
|
|
"length",
|
|
length,
|
|
true,
|
|
true
|
|
);
|
|
} else {
|
|
define(
|
|
/** @type {Parameters<define>[0]} */
|
|
fn,
|
|
"length",
|
|
length
|
|
);
|
|
}
|
|
}
|
|
return fn;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/call-bind-apply-helpers/applyBind.js
|
|
var require_applyBind = __commonJS({
|
|
"../../node_modules/call-bind-apply-helpers/applyBind.js"(exports, module) {
|
|
"use strict";
|
|
var bind = require_function_bind();
|
|
var $apply = require_functionApply();
|
|
var actualApply = require_actualApply();
|
|
module.exports = function applyBind() {
|
|
return actualApply(bind, $apply, arguments);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/call-bind/index.js
|
|
var require_call_bind = __commonJS({
|
|
"../../node_modules/call-bind/index.js"(exports, module) {
|
|
"use strict";
|
|
var setFunctionLength = require_set_function_length();
|
|
var $defineProperty = require_es_define_property();
|
|
var callBindBasic = require_call_bind_apply_helpers();
|
|
var applyBind = require_applyBind();
|
|
module.exports = function callBind(originalFunction) {
|
|
var func = callBindBasic(arguments);
|
|
var adjustedLength = originalFunction.length - (arguments.length - 1);
|
|
return setFunctionLength(
|
|
func,
|
|
1 + (adjustedLength > 0 ? adjustedLength : 0),
|
|
true
|
|
);
|
|
};
|
|
if ($defineProperty) {
|
|
$defineProperty(module.exports, "apply", { value: applyBind });
|
|
} else {
|
|
module.exports.apply = applyBind;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/has-tostringtag/shams.js
|
|
var require_shams2 = __commonJS({
|
|
"../../node_modules/has-tostringtag/shams.js"(exports, module) {
|
|
"use strict";
|
|
var hasSymbols = require_shams();
|
|
module.exports = function hasToStringTagShams() {
|
|
return hasSymbols() && !!Symbol.toStringTag;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/which-typed-array/index.js
|
|
var require_which_typed_array = __commonJS({
|
|
"../../node_modules/which-typed-array/index.js"(exports, module) {
|
|
"use strict";
|
|
var forEach = require_for_each();
|
|
var availableTypedArrays = require_available_typed_arrays();
|
|
var callBind = require_call_bind();
|
|
var callBound = require_call_bound();
|
|
var gOPD = require_gopd();
|
|
var getProto = require_get_proto();
|
|
var $toString = callBound("Object.prototype.toString");
|
|
var hasToStringTag = require_shams2()();
|
|
var g = typeof globalThis === "undefined" ? global : globalThis;
|
|
var typedArrays = availableTypedArrays();
|
|
var $slice = callBound("String.prototype.slice");
|
|
var $indexOf = callBound("Array.prototype.indexOf", true) || function indexOf(array, value) {
|
|
for (var i = 0; i < array.length; i += 1) {
|
|
if (array[i] === value) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
var cache = { __proto__: null };
|
|
if (hasToStringTag && gOPD && getProto) {
|
|
forEach(typedArrays, function(typedArray) {
|
|
var arr = new g[typedArray]();
|
|
if (Symbol.toStringTag in arr && getProto) {
|
|
var proto = getProto(arr);
|
|
var descriptor = gOPD(proto, Symbol.toStringTag);
|
|
if (!descriptor && proto) {
|
|
var superProto = getProto(proto);
|
|
descriptor = gOPD(superProto, Symbol.toStringTag);
|
|
}
|
|
if (descriptor && descriptor.get) {
|
|
var bound = callBind(descriptor.get);
|
|
cache[
|
|
/** @type {`$${import('.').TypedArrayName}`} */
|
|
"$" + typedArray
|
|
] = bound;
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
forEach(typedArrays, function(typedArray) {
|
|
var arr = new g[typedArray]();
|
|
var fn = arr.slice || arr.set;
|
|
if (fn) {
|
|
var bound = (
|
|
/** @type {import('./types').BoundSlice | import('./types').BoundSet} */
|
|
// @ts-expect-error upstream-type-bridge
|
|
callBind(fn)
|
|
);
|
|
cache[
|
|
/** @type {`$${import('.').TypedArrayName}`} */
|
|
"$" + typedArray
|
|
] = bound;
|
|
}
|
|
});
|
|
}
|
|
var tryTypedArrays = function tryAllTypedArrays(value) {
|
|
var found = false;
|
|
forEach(
|
|
/** @type {Record<`\$${import('.').TypedArrayName}`, Getter>} */
|
|
cache,
|
|
/** @type {(getter: Getter, name: `\$${import('.').TypedArrayName}`) => void} */
|
|
function(getter, typedArray) {
|
|
if (!found) {
|
|
try {
|
|
if ("$" + getter(value) === typedArray) {
|
|
found = /** @type {import('.').TypedArrayName} */
|
|
$slice(typedArray, 1);
|
|
}
|
|
} catch (e) {
|
|
}
|
|
}
|
|
}
|
|
);
|
|
return found;
|
|
};
|
|
var trySlices = function tryAllSlices(value) {
|
|
var found = false;
|
|
forEach(
|
|
/** @type {Record<`\$${import('.').TypedArrayName}`, Getter>} */
|
|
cache,
|
|
/** @type {(getter: Getter, name: `\$${import('.').TypedArrayName}`) => void} */
|
|
function(getter, name) {
|
|
if (!found) {
|
|
try {
|
|
getter(value);
|
|
found = /** @type {import('.').TypedArrayName} */
|
|
$slice(name, 1);
|
|
} catch (e) {
|
|
}
|
|
}
|
|
}
|
|
);
|
|
return found;
|
|
};
|
|
module.exports = function whichTypedArray(value) {
|
|
if (!value || typeof value !== "object") {
|
|
return false;
|
|
}
|
|
if (!hasToStringTag) {
|
|
var tag = $slice($toString(value), 8, -1);
|
|
if ($indexOf(typedArrays, tag) > -1) {
|
|
return tag;
|
|
}
|
|
if (tag !== "Object") {
|
|
return false;
|
|
}
|
|
return trySlices(value);
|
|
}
|
|
if (!gOPD) {
|
|
return null;
|
|
}
|
|
return tryTypedArrays(value);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/is-typed-array/index.js
|
|
var require_is_typed_array = __commonJS({
|
|
"../../node_modules/is-typed-array/index.js"(exports, module) {
|
|
"use strict";
|
|
var whichTypedArray = require_which_typed_array();
|
|
module.exports = function isTypedArray(value) {
|
|
return !!whichTypedArray(value);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/typed-array-buffer/index.js
|
|
var require_typed_array_buffer = __commonJS({
|
|
"../../node_modules/typed-array-buffer/index.js"(exports, module) {
|
|
"use strict";
|
|
var $TypeError = require_type();
|
|
var callBound = require_call_bound();
|
|
var $typedArrayBuffer = callBound("TypedArray.prototype.buffer", true);
|
|
var isTypedArray = require_is_typed_array();
|
|
module.exports = $typedArrayBuffer || function typedArrayBuffer(x) {
|
|
if (!isTypedArray(x)) {
|
|
throw new $TypeError("Not a Typed Array");
|
|
}
|
|
return x.buffer;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/to-buffer/index.js
|
|
var require_to_buffer = __commonJS({
|
|
"../../node_modules/to-buffer/index.js"(exports, module) {
|
|
"use strict";
|
|
var Buffer2 = require_safe_buffer2().Buffer;
|
|
var isArray = require_isarray2();
|
|
var typedArrayBuffer = require_typed_array_buffer();
|
|
var isView = ArrayBuffer.isView || function isView2(obj) {
|
|
try {
|
|
typedArrayBuffer(obj);
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
};
|
|
var useUint8Array = typeof Uint8Array !== "undefined";
|
|
var useArrayBuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined";
|
|
var useFromArrayBuffer = useArrayBuffer && (Buffer2.prototype instanceof Uint8Array || Buffer2.TYPED_ARRAY_SUPPORT);
|
|
module.exports = function toBuffer(data, encoding) {
|
|
if (Buffer2.isBuffer(data)) {
|
|
if (data.constructor && !("isBuffer" in data)) {
|
|
return Buffer2.from(data);
|
|
}
|
|
return data;
|
|
}
|
|
if (typeof data === "string") {
|
|
return Buffer2.from(data, encoding);
|
|
}
|
|
if (useArrayBuffer && isView(data)) {
|
|
if (data.byteLength === 0) {
|
|
return Buffer2.alloc(0);
|
|
}
|
|
if (useFromArrayBuffer) {
|
|
var res = Buffer2.from(data.buffer, data.byteOffset, data.byteLength);
|
|
if (res.byteLength === data.byteLength) {
|
|
return res;
|
|
}
|
|
}
|
|
var uint8 = data instanceof Uint8Array ? data : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
var result = Buffer2.from(uint8);
|
|
if (result.length === data.byteLength) {
|
|
return result;
|
|
}
|
|
}
|
|
if (useUint8Array && data instanceof Uint8Array) {
|
|
return Buffer2.from(data);
|
|
}
|
|
var isArr = isArray(data);
|
|
if (isArr) {
|
|
for (var i = 0; i < data.length; i += 1) {
|
|
var x = data[i];
|
|
if (typeof x !== "number" || x < 0 || x > 255 || ~~x !== x) {
|
|
throw new RangeError("Array items must be numbers in the range 0-255.");
|
|
}
|
|
}
|
|
}
|
|
if (isArr || Buffer2.isBuffer(data) && data.constructor && typeof data.constructor.isBuffer === "function" && data.constructor.isBuffer(data)) {
|
|
return Buffer2.from(data);
|
|
}
|
|
throw new TypeError('The "data" argument must be a string, an Array, a Buffer, a Uint8Array, or a DataView.');
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/buffer-fill/index.js
|
|
var require_buffer_fill = __commonJS({
|
|
"../../node_modules/buffer-fill/index.js"(exports, module) {
|
|
var hasFullSupport = (function() {
|
|
try {
|
|
if (!Buffer.isEncoding("latin1")) {
|
|
return false;
|
|
}
|
|
var buf = Buffer.alloc ? Buffer.alloc(4) : new Buffer(4);
|
|
buf.fill("ab", "ucs2");
|
|
return buf.toString("hex") === "61006200";
|
|
} catch (_) {
|
|
return false;
|
|
}
|
|
})();
|
|
function isSingleByte(val) {
|
|
return val.length === 1 && val.charCodeAt(0) < 256;
|
|
}
|
|
function fillWithNumber(buffer, val, start, end) {
|
|
if (start < 0 || end > buffer.length) {
|
|
throw new RangeError("Out of range index");
|
|
}
|
|
start = start >>> 0;
|
|
end = end === void 0 ? buffer.length : end >>> 0;
|
|
if (end > start) {
|
|
buffer.fill(val, start, end);
|
|
}
|
|
return buffer;
|
|
}
|
|
function fillWithBuffer(buffer, val, start, end) {
|
|
if (start < 0 || end > buffer.length) {
|
|
throw new RangeError("Out of range index");
|
|
}
|
|
if (end <= start) {
|
|
return buffer;
|
|
}
|
|
start = start >>> 0;
|
|
end = end === void 0 ? buffer.length : end >>> 0;
|
|
var pos = start;
|
|
var len = val.length;
|
|
while (pos <= end - len) {
|
|
val.copy(buffer, pos);
|
|
pos += len;
|
|
}
|
|
if (pos !== end) {
|
|
val.copy(buffer, pos, 0, end - pos);
|
|
}
|
|
return buffer;
|
|
}
|
|
function fill(buffer, val, start, end, encoding) {
|
|
if (hasFullSupport) {
|
|
return buffer.fill(val, start, end, encoding);
|
|
}
|
|
if (typeof val === "number") {
|
|
return fillWithNumber(buffer, val, start, end);
|
|
}
|
|
if (typeof val === "string") {
|
|
if (typeof start === "string") {
|
|
encoding = start;
|
|
start = 0;
|
|
end = buffer.length;
|
|
} else if (typeof end === "string") {
|
|
encoding = end;
|
|
end = buffer.length;
|
|
}
|
|
if (encoding !== void 0 && typeof encoding !== "string") {
|
|
throw new TypeError("encoding must be a string");
|
|
}
|
|
if (encoding === "latin1") {
|
|
encoding = "binary";
|
|
}
|
|
if (typeof encoding === "string" && !Buffer.isEncoding(encoding)) {
|
|
throw new TypeError("Unknown encoding: " + encoding);
|
|
}
|
|
if (val === "") {
|
|
return fillWithNumber(buffer, 0, start, end);
|
|
}
|
|
if (isSingleByte(val)) {
|
|
return fillWithNumber(buffer, val.charCodeAt(0), start, end);
|
|
}
|
|
val = new Buffer(val, encoding);
|
|
}
|
|
if (Buffer.isBuffer(val)) {
|
|
return fillWithBuffer(buffer, val, start, end);
|
|
}
|
|
return fillWithNumber(buffer, 0, start, end);
|
|
}
|
|
module.exports = fill;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/buffer-alloc-unsafe/index.js
|
|
var require_buffer_alloc_unsafe = __commonJS({
|
|
"../../node_modules/buffer-alloc-unsafe/index.js"(exports, module) {
|
|
function allocUnsafe(size) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError('"size" argument must be a number');
|
|
}
|
|
if (size < 0) {
|
|
throw new RangeError('"size" argument must not be negative');
|
|
}
|
|
if (Buffer.allocUnsafe) {
|
|
return Buffer.allocUnsafe(size);
|
|
} else {
|
|
return new Buffer(size);
|
|
}
|
|
}
|
|
module.exports = allocUnsafe;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/buffer-alloc/index.js
|
|
var require_buffer_alloc = __commonJS({
|
|
"../../node_modules/buffer-alloc/index.js"(exports, module) {
|
|
var bufferFill = require_buffer_fill();
|
|
var allocUnsafe = require_buffer_alloc_unsafe();
|
|
module.exports = function alloc(size, fill, encoding) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError('"size" argument must be a number');
|
|
}
|
|
if (size < 0) {
|
|
throw new RangeError('"size" argument must not be negative');
|
|
}
|
|
if (Buffer.alloc) {
|
|
return Buffer.alloc(size, fill, encoding);
|
|
}
|
|
var buffer = allocUnsafe(size);
|
|
if (size === 0) {
|
|
return buffer;
|
|
}
|
|
if (fill === void 0) {
|
|
return bufferFill(buffer, 0);
|
|
}
|
|
if (typeof encoding !== "string") {
|
|
encoding = void 0;
|
|
}
|
|
return bufferFill(buffer, fill, encoding);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/headers.js
|
|
var require_headers = __commonJS({
|
|
"../../node_modules/tar-stream/headers.js"(exports) {
|
|
var toBuffer = require_to_buffer();
|
|
var alloc = require_buffer_alloc();
|
|
var ZEROS = "0000000000000000000";
|
|
var SEVENS = "7777777777777777777";
|
|
var ZERO_OFFSET = "0".charCodeAt(0);
|
|
var USTAR = "ustar\x0000";
|
|
var MASK = parseInt("7777", 8);
|
|
var clamp = function(index, len, defaultValue) {
|
|
if (typeof index !== "number") return defaultValue;
|
|
index = ~~index;
|
|
if (index >= len) return len;
|
|
if (index >= 0) return index;
|
|
index += len;
|
|
if (index >= 0) return index;
|
|
return 0;
|
|
};
|
|
var toType = function(flag) {
|
|
switch (flag) {
|
|
case 0:
|
|
return "file";
|
|
case 1:
|
|
return "link";
|
|
case 2:
|
|
return "symlink";
|
|
case 3:
|
|
return "character-device";
|
|
case 4:
|
|
return "block-device";
|
|
case 5:
|
|
return "directory";
|
|
case 6:
|
|
return "fifo";
|
|
case 7:
|
|
return "contiguous-file";
|
|
case 72:
|
|
return "pax-header";
|
|
case 55:
|
|
return "pax-global-header";
|
|
case 27:
|
|
return "gnu-long-link-path";
|
|
case 28:
|
|
case 30:
|
|
return "gnu-long-path";
|
|
}
|
|
return null;
|
|
};
|
|
var toTypeflag = function(flag) {
|
|
switch (flag) {
|
|
case "file":
|
|
return 0;
|
|
case "link":
|
|
return 1;
|
|
case "symlink":
|
|
return 2;
|
|
case "character-device":
|
|
return 3;
|
|
case "block-device":
|
|
return 4;
|
|
case "directory":
|
|
return 5;
|
|
case "fifo":
|
|
return 6;
|
|
case "contiguous-file":
|
|
return 7;
|
|
case "pax-header":
|
|
return 72;
|
|
}
|
|
return 0;
|
|
};
|
|
var indexOf = function(block, num, offset, end) {
|
|
for (; offset < end; offset++) {
|
|
if (block[offset] === num) return offset;
|
|
}
|
|
return end;
|
|
};
|
|
var cksum = function(block) {
|
|
var sum = 8 * 32;
|
|
for (var i = 0; i < 148; i++) sum += block[i];
|
|
for (var j = 156; j < 512; j++) sum += block[j];
|
|
return sum;
|
|
};
|
|
var encodeOct = function(val, n) {
|
|
val = val.toString(8);
|
|
if (val.length > n) return SEVENS.slice(0, n) + " ";
|
|
else return ZEROS.slice(0, n - val.length) + val + " ";
|
|
};
|
|
function parse256(buf) {
|
|
var positive;
|
|
if (buf[0] === 128) positive = true;
|
|
else if (buf[0] === 255) positive = false;
|
|
else return null;
|
|
var zero = false;
|
|
var tuple = [];
|
|
for (var i = buf.length - 1; i > 0; i--) {
|
|
var byte = buf[i];
|
|
if (positive) tuple.push(byte);
|
|
else if (zero && byte === 0) tuple.push(0);
|
|
else if (zero) {
|
|
zero = false;
|
|
tuple.push(256 - byte);
|
|
} else tuple.push(255 - byte);
|
|
}
|
|
var sum = 0;
|
|
var l = tuple.length;
|
|
for (i = 0; i < l; i++) {
|
|
sum += tuple[i] * Math.pow(256, i);
|
|
}
|
|
return positive ? sum : -1 * sum;
|
|
}
|
|
var decodeOct = function(val, offset, length) {
|
|
val = val.slice(offset, offset + length);
|
|
offset = 0;
|
|
if (val[offset] & 128) {
|
|
return parse256(val);
|
|
} else {
|
|
while (offset < val.length && val[offset] === 32) offset++;
|
|
var end = clamp(indexOf(val, 32, offset, val.length), val.length, val.length);
|
|
while (offset < end && val[offset] === 0) offset++;
|
|
if (end === offset) return 0;
|
|
return parseInt(val.slice(offset, end).toString(), 8);
|
|
}
|
|
};
|
|
var decodeStr = function(val, offset, length, encoding) {
|
|
return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString(encoding);
|
|
};
|
|
var addLength = function(str) {
|
|
var len = Buffer.byteLength(str);
|
|
var digits = Math.floor(Math.log(len) / Math.log(10)) + 1;
|
|
if (len + digits >= Math.pow(10, digits)) digits++;
|
|
return len + digits + str;
|
|
};
|
|
exports.decodeLongPath = function(buf, encoding) {
|
|
return decodeStr(buf, 0, buf.length, encoding);
|
|
};
|
|
exports.encodePax = function(opts) {
|
|
var result = "";
|
|
if (opts.name) result += addLength(" path=" + opts.name + "\n");
|
|
if (opts.linkname) result += addLength(" linkpath=" + opts.linkname + "\n");
|
|
var pax = opts.pax;
|
|
if (pax) {
|
|
for (var key in pax) {
|
|
result += addLength(" " + key + "=" + pax[key] + "\n");
|
|
}
|
|
}
|
|
return toBuffer(result);
|
|
};
|
|
exports.decodePax = function(buf) {
|
|
var result = {};
|
|
while (buf.length) {
|
|
var i = 0;
|
|
while (i < buf.length && buf[i] !== 32) i++;
|
|
var len = parseInt(buf.slice(0, i).toString(), 10);
|
|
if (!len) return result;
|
|
var b = buf.slice(i + 1, len - 1).toString();
|
|
var keyIndex = b.indexOf("=");
|
|
if (keyIndex === -1) return result;
|
|
result[b.slice(0, keyIndex)] = b.slice(keyIndex + 1);
|
|
buf = buf.slice(len);
|
|
}
|
|
return result;
|
|
};
|
|
exports.encode = function(opts) {
|
|
var buf = alloc(512);
|
|
var name = opts.name;
|
|
var prefix = "";
|
|
if (opts.typeflag === 5 && name[name.length - 1] !== "/") name += "/";
|
|
if (Buffer.byteLength(name) !== name.length) return null;
|
|
while (Buffer.byteLength(name) > 100) {
|
|
var i = name.indexOf("/");
|
|
if (i === -1) return null;
|
|
prefix += prefix ? "/" + name.slice(0, i) : name.slice(0, i);
|
|
name = name.slice(i + 1);
|
|
}
|
|
if (Buffer.byteLength(name) > 100 || Buffer.byteLength(prefix) > 155) return null;
|
|
if (opts.linkname && Buffer.byteLength(opts.linkname) > 100) return null;
|
|
buf.write(name);
|
|
buf.write(encodeOct(opts.mode & MASK, 6), 100);
|
|
buf.write(encodeOct(opts.uid, 6), 108);
|
|
buf.write(encodeOct(opts.gid, 6), 116);
|
|
buf.write(encodeOct(opts.size, 11), 124);
|
|
buf.write(encodeOct(opts.mtime.getTime() / 1e3 | 0, 11), 136);
|
|
buf[156] = ZERO_OFFSET + toTypeflag(opts.type);
|
|
if (opts.linkname) buf.write(opts.linkname, 157);
|
|
buf.write(USTAR, 257);
|
|
if (opts.uname) buf.write(opts.uname, 265);
|
|
if (opts.gname) buf.write(opts.gname, 297);
|
|
buf.write(encodeOct(opts.devmajor || 0, 6), 329);
|
|
buf.write(encodeOct(opts.devminor || 0, 6), 337);
|
|
if (prefix) buf.write(prefix, 345);
|
|
buf.write(encodeOct(cksum(buf), 6), 148);
|
|
return buf;
|
|
};
|
|
exports.decode = function(buf, filenameEncoding) {
|
|
var typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET;
|
|
var name = decodeStr(buf, 0, 100, filenameEncoding);
|
|
var mode = decodeOct(buf, 100, 8);
|
|
var uid = decodeOct(buf, 108, 8);
|
|
var gid = decodeOct(buf, 116, 8);
|
|
var size = decodeOct(buf, 124, 12);
|
|
var mtime = decodeOct(buf, 136, 12);
|
|
var type = toType(typeflag);
|
|
var linkname = buf[157] === 0 ? null : decodeStr(buf, 157, 100, filenameEncoding);
|
|
var uname = decodeStr(buf, 265, 32);
|
|
var gname = decodeStr(buf, 297, 32);
|
|
var devmajor = decodeOct(buf, 329, 8);
|
|
var devminor = decodeOct(buf, 337, 8);
|
|
if (buf[345]) name = decodeStr(buf, 345, 155, filenameEncoding) + "/" + name;
|
|
if (typeflag === 0 && name && name[name.length - 1] === "/") typeflag = 5;
|
|
var c = cksum(buf);
|
|
if (c === 8 * 32) return null;
|
|
if (c !== decodeOct(buf, 148, 8)) throw new Error("Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?");
|
|
return {
|
|
name,
|
|
mode,
|
|
uid,
|
|
gid,
|
|
size,
|
|
mtime: new Date(1e3 * mtime),
|
|
type,
|
|
linkname,
|
|
uname,
|
|
gname,
|
|
devmajor,
|
|
devminor
|
|
};
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/isarray/index.js
|
|
var require_isarray3 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/isarray/index.js"(exports, module) {
|
|
var toString = {}.toString;
|
|
module.exports = Array.isArray || function(arr) {
|
|
return toString.call(arr) == "[object Array]";
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/lib/internal/streams/stream.js
|
|
var require_stream2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/lib/internal/streams/stream.js"(exports, module) {
|
|
module.exports = __require("stream");
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/safe-buffer/index.js
|
|
var require_safe_buffer3 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/safe-buffer/index.js"(exports, module) {
|
|
var buffer = __require("buffer");
|
|
var Buffer2 = buffer.Buffer;
|
|
function copyProps(src, dst) {
|
|
for (var key in src) {
|
|
dst[key] = src[key];
|
|
}
|
|
}
|
|
if (Buffer2.from && Buffer2.alloc && Buffer2.allocUnsafe && Buffer2.allocUnsafeSlow) {
|
|
module.exports = buffer;
|
|
} else {
|
|
copyProps(buffer, exports);
|
|
exports.Buffer = SafeBuffer;
|
|
}
|
|
function SafeBuffer(arg, encodingOrOffset, length) {
|
|
return Buffer2(arg, encodingOrOffset, length);
|
|
}
|
|
copyProps(Buffer2, SafeBuffer);
|
|
SafeBuffer.from = function(arg, encodingOrOffset, length) {
|
|
if (typeof arg === "number") {
|
|
throw new TypeError("Argument must not be a number");
|
|
}
|
|
return Buffer2(arg, encodingOrOffset, length);
|
|
};
|
|
SafeBuffer.alloc = function(size, fill, encoding) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
var buf = Buffer2(size);
|
|
if (fill !== void 0) {
|
|
if (typeof encoding === "string") {
|
|
buf.fill(fill, encoding);
|
|
} else {
|
|
buf.fill(fill);
|
|
}
|
|
} else {
|
|
buf.fill(0);
|
|
}
|
|
return buf;
|
|
};
|
|
SafeBuffer.allocUnsafe = function(size) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
return Buffer2(size);
|
|
};
|
|
SafeBuffer.allocUnsafeSlow = function(size) {
|
|
if (typeof size !== "number") {
|
|
throw new TypeError("Argument must be a number");
|
|
}
|
|
return buffer.SlowBuffer(size);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/lib/internal/streams/BufferList.js
|
|
var require_BufferList2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/lib/internal/streams/BufferList.js"(exports, module) {
|
|
"use strict";
|
|
function _classCallCheck(instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError("Cannot call a class as a function");
|
|
}
|
|
}
|
|
var Buffer2 = require_safe_buffer3().Buffer;
|
|
var util = __require("util");
|
|
function copyBuffer(src, target, offset) {
|
|
src.copy(target, offset);
|
|
}
|
|
module.exports = (function() {
|
|
function BufferList() {
|
|
_classCallCheck(this, BufferList);
|
|
this.head = null;
|
|
this.tail = null;
|
|
this.length = 0;
|
|
}
|
|
BufferList.prototype.push = function push(v) {
|
|
var entry = { data: v, next: null };
|
|
if (this.length > 0) this.tail.next = entry;
|
|
else this.head = entry;
|
|
this.tail = entry;
|
|
++this.length;
|
|
};
|
|
BufferList.prototype.unshift = function unshift(v) {
|
|
var entry = { data: v, next: this.head };
|
|
if (this.length === 0) this.tail = entry;
|
|
this.head = entry;
|
|
++this.length;
|
|
};
|
|
BufferList.prototype.shift = function shift() {
|
|
if (this.length === 0) return;
|
|
var ret = this.head.data;
|
|
if (this.length === 1) this.head = this.tail = null;
|
|
else this.head = this.head.next;
|
|
--this.length;
|
|
return ret;
|
|
};
|
|
BufferList.prototype.clear = function clear() {
|
|
this.head = this.tail = null;
|
|
this.length = 0;
|
|
};
|
|
BufferList.prototype.join = function join(s) {
|
|
if (this.length === 0) return "";
|
|
var p = this.head;
|
|
var ret = "" + p.data;
|
|
while (p = p.next) {
|
|
ret += s + p.data;
|
|
}
|
|
return ret;
|
|
};
|
|
BufferList.prototype.concat = function concat(n) {
|
|
if (this.length === 0) return Buffer2.alloc(0);
|
|
var ret = Buffer2.allocUnsafe(n >>> 0);
|
|
var p = this.head;
|
|
var i = 0;
|
|
while (p) {
|
|
copyBuffer(p.data, ret, i);
|
|
i += p.data.length;
|
|
p = p.next;
|
|
}
|
|
return ret;
|
|
};
|
|
return BufferList;
|
|
})();
|
|
if (util && util.inspect && util.inspect.custom) {
|
|
module.exports.prototype[util.inspect.custom] = function() {
|
|
var obj = util.inspect({ length: this.length });
|
|
return this.constructor.name + " " + obj;
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/lib/internal/streams/destroy.js
|
|
var require_destroy2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/lib/internal/streams/destroy.js"(exports, module) {
|
|
"use strict";
|
|
var pna = require_process_nextick_args();
|
|
function destroy(err, cb) {
|
|
var _this = this;
|
|
var readableDestroyed = this._readableState && this._readableState.destroyed;
|
|
var writableDestroyed = this._writableState && this._writableState.destroyed;
|
|
if (readableDestroyed || writableDestroyed) {
|
|
if (cb) {
|
|
cb(err);
|
|
} else if (err) {
|
|
if (!this._writableState) {
|
|
pna.nextTick(emitErrorNT, this, err);
|
|
} else if (!this._writableState.errorEmitted) {
|
|
this._writableState.errorEmitted = true;
|
|
pna.nextTick(emitErrorNT, this, err);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = true;
|
|
}
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = true;
|
|
}
|
|
this._destroy(err || null, function(err2) {
|
|
if (!cb && err2) {
|
|
if (!_this._writableState) {
|
|
pna.nextTick(emitErrorNT, _this, err2);
|
|
} else if (!_this._writableState.errorEmitted) {
|
|
_this._writableState.errorEmitted = true;
|
|
pna.nextTick(emitErrorNT, _this, err2);
|
|
}
|
|
} else if (cb) {
|
|
cb(err2);
|
|
}
|
|
});
|
|
return this;
|
|
}
|
|
function undestroy() {
|
|
if (this._readableState) {
|
|
this._readableState.destroyed = false;
|
|
this._readableState.reading = false;
|
|
this._readableState.ended = false;
|
|
this._readableState.endEmitted = false;
|
|
}
|
|
if (this._writableState) {
|
|
this._writableState.destroyed = false;
|
|
this._writableState.ended = false;
|
|
this._writableState.ending = false;
|
|
this._writableState.finalCalled = false;
|
|
this._writableState.prefinished = false;
|
|
this._writableState.finished = false;
|
|
this._writableState.errorEmitted = false;
|
|
}
|
|
}
|
|
function emitErrorNT(self2, err) {
|
|
self2.emit("error", err);
|
|
}
|
|
module.exports = {
|
|
destroy,
|
|
undestroy
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_writable.js
|
|
var require_stream_writable2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_writable.js"(exports, module) {
|
|
"use strict";
|
|
var pna = require_process_nextick_args();
|
|
module.exports = Writable;
|
|
function CorkedRequest(state) {
|
|
var _this = this;
|
|
this.next = null;
|
|
this.entry = null;
|
|
this.finish = function() {
|
|
onCorkedFinish(_this, state);
|
|
};
|
|
}
|
|
var asyncWrite = !process.browser && ["v0.10", "v0.9."].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick;
|
|
var Duplex;
|
|
Writable.WritableState = WritableState;
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
var internalUtil = {
|
|
deprecate: require_node()
|
|
};
|
|
var Stream = require_stream2();
|
|
var Buffer2 = require_safe_buffer3().Buffer;
|
|
var OurUint8Array = (typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {}).Uint8Array || function() {
|
|
};
|
|
function _uint8ArrayToBuffer(chunk) {
|
|
return Buffer2.from(chunk);
|
|
}
|
|
function _isUint8Array(obj) {
|
|
return Buffer2.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
}
|
|
var destroyImpl = require_destroy2();
|
|
util.inherits(Writable, Stream);
|
|
function nop() {
|
|
}
|
|
function WritableState(options, stream) {
|
|
Duplex = Duplex || require_stream_duplex2();
|
|
options = options || {};
|
|
var isDuplex = stream instanceof Duplex;
|
|
this.objectMode = !!options.objectMode;
|
|
if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode;
|
|
var hwm = options.highWaterMark;
|
|
var writableHwm = options.writableHighWaterMark;
|
|
var defaultHwm = this.objectMode ? 16 : 16 * 1024;
|
|
if (hwm || hwm === 0) this.highWaterMark = hwm;
|
|
else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;
|
|
else this.highWaterMark = defaultHwm;
|
|
this.highWaterMark = Math.floor(this.highWaterMark);
|
|
this.finalCalled = false;
|
|
this.needDrain = false;
|
|
this.ending = false;
|
|
this.ended = false;
|
|
this.finished = false;
|
|
this.destroyed = false;
|
|
var noDecode = options.decodeStrings === false;
|
|
this.decodeStrings = !noDecode;
|
|
this.defaultEncoding = options.defaultEncoding || "utf8";
|
|
this.length = 0;
|
|
this.writing = false;
|
|
this.corked = 0;
|
|
this.sync = true;
|
|
this.bufferProcessing = false;
|
|
this.onwrite = function(er) {
|
|
onwrite(stream, er);
|
|
};
|
|
this.writecb = null;
|
|
this.writelen = 0;
|
|
this.bufferedRequest = null;
|
|
this.lastBufferedRequest = null;
|
|
this.pendingcb = 0;
|
|
this.prefinished = false;
|
|
this.errorEmitted = false;
|
|
this.bufferedRequestCount = 0;
|
|
this.corkedRequestsFree = new CorkedRequest(this);
|
|
}
|
|
WritableState.prototype.getBuffer = function getBuffer() {
|
|
var current = this.bufferedRequest;
|
|
var out = [];
|
|
while (current) {
|
|
out.push(current);
|
|
current = current.next;
|
|
}
|
|
return out;
|
|
};
|
|
(function() {
|
|
try {
|
|
Object.defineProperty(WritableState.prototype, "buffer", {
|
|
get: internalUtil.deprecate(function() {
|
|
return this.getBuffer();
|
|
}, "_writableState.buffer is deprecated. Use _writableState.getBuffer instead.", "DEP0003")
|
|
});
|
|
} catch (_) {
|
|
}
|
|
})();
|
|
var realHasInstance;
|
|
if (typeof Symbol === "function" && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === "function") {
|
|
realHasInstance = Function.prototype[Symbol.hasInstance];
|
|
Object.defineProperty(Writable, Symbol.hasInstance, {
|
|
value: function(object) {
|
|
if (realHasInstance.call(this, object)) return true;
|
|
if (this !== Writable) return false;
|
|
return object && object._writableState instanceof WritableState;
|
|
}
|
|
});
|
|
} else {
|
|
realHasInstance = function(object) {
|
|
return object instanceof this;
|
|
};
|
|
}
|
|
function Writable(options) {
|
|
Duplex = Duplex || require_stream_duplex2();
|
|
if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) {
|
|
return new Writable(options);
|
|
}
|
|
this._writableState = new WritableState(options, this);
|
|
this.writable = true;
|
|
if (options) {
|
|
if (typeof options.write === "function") this._write = options.write;
|
|
if (typeof options.writev === "function") this._writev = options.writev;
|
|
if (typeof options.destroy === "function") this._destroy = options.destroy;
|
|
if (typeof options.final === "function") this._final = options.final;
|
|
}
|
|
Stream.call(this);
|
|
}
|
|
Writable.prototype.pipe = function() {
|
|
this.emit("error", new Error("Cannot pipe, not readable"));
|
|
};
|
|
function writeAfterEnd(stream, cb) {
|
|
var er = new Error("write after end");
|
|
stream.emit("error", er);
|
|
pna.nextTick(cb, er);
|
|
}
|
|
function validChunk(stream, state, chunk, cb) {
|
|
var valid = true;
|
|
var er = false;
|
|
if (chunk === null) {
|
|
er = new TypeError("May not write null values to stream");
|
|
} else if (typeof chunk !== "string" && chunk !== void 0 && !state.objectMode) {
|
|
er = new TypeError("Invalid non-string/buffer chunk");
|
|
}
|
|
if (er) {
|
|
stream.emit("error", er);
|
|
pna.nextTick(cb, er);
|
|
valid = false;
|
|
}
|
|
return valid;
|
|
}
|
|
Writable.prototype.write = function(chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
var ret = false;
|
|
var isBuf = !state.objectMode && _isUint8Array(chunk);
|
|
if (isBuf && !Buffer2.isBuffer(chunk)) {
|
|
chunk = _uint8ArrayToBuffer(chunk);
|
|
}
|
|
if (typeof encoding === "function") {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
if (isBuf) encoding = "buffer";
|
|
else if (!encoding) encoding = state.defaultEncoding;
|
|
if (typeof cb !== "function") cb = nop;
|
|
if (state.ended) writeAfterEnd(this, cb);
|
|
else if (isBuf || validChunk(this, state, chunk, cb)) {
|
|
state.pendingcb++;
|
|
ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
|
|
}
|
|
return ret;
|
|
};
|
|
Writable.prototype.cork = function() {
|
|
var state = this._writableState;
|
|
state.corked++;
|
|
};
|
|
Writable.prototype.uncork = function() {
|
|
var state = this._writableState;
|
|
if (state.corked) {
|
|
state.corked--;
|
|
if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
|
|
}
|
|
};
|
|
Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
|
|
if (typeof encoding === "string") encoding = encoding.toLowerCase();
|
|
if (!(["hex", "utf8", "utf-8", "ascii", "binary", "base64", "ucs2", "ucs-2", "utf16le", "utf-16le", "raw"].indexOf((encoding + "").toLowerCase()) > -1)) throw new TypeError("Unknown encoding: " + encoding);
|
|
this._writableState.defaultEncoding = encoding;
|
|
return this;
|
|
};
|
|
function decodeChunk(state, chunk, encoding) {
|
|
if (!state.objectMode && state.decodeStrings !== false && typeof chunk === "string") {
|
|
chunk = Buffer2.from(chunk, encoding);
|
|
}
|
|
return chunk;
|
|
}
|
|
Object.defineProperty(Writable.prototype, "writableHighWaterMark", {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function() {
|
|
return this._writableState.highWaterMark;
|
|
}
|
|
});
|
|
function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
|
|
if (!isBuf) {
|
|
var newChunk = decodeChunk(state, chunk, encoding);
|
|
if (chunk !== newChunk) {
|
|
isBuf = true;
|
|
encoding = "buffer";
|
|
chunk = newChunk;
|
|
}
|
|
}
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
state.length += len;
|
|
var ret = state.length < state.highWaterMark;
|
|
if (!ret) state.needDrain = true;
|
|
if (state.writing || state.corked) {
|
|
var last = state.lastBufferedRequest;
|
|
state.lastBufferedRequest = {
|
|
chunk,
|
|
encoding,
|
|
isBuf,
|
|
callback: cb,
|
|
next: null
|
|
};
|
|
if (last) {
|
|
last.next = state.lastBufferedRequest;
|
|
} else {
|
|
state.bufferedRequest = state.lastBufferedRequest;
|
|
}
|
|
state.bufferedRequestCount += 1;
|
|
} else {
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
}
|
|
return ret;
|
|
}
|
|
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
|
|
state.writelen = len;
|
|
state.writecb = cb;
|
|
state.writing = true;
|
|
state.sync = true;
|
|
if (writev) stream._writev(chunk, state.onwrite);
|
|
else stream._write(chunk, encoding, state.onwrite);
|
|
state.sync = false;
|
|
}
|
|
function onwriteError(stream, state, sync, er, cb) {
|
|
--state.pendingcb;
|
|
if (sync) {
|
|
pna.nextTick(cb, er);
|
|
pna.nextTick(finishMaybe, stream, state);
|
|
stream._writableState.errorEmitted = true;
|
|
stream.emit("error", er);
|
|
} else {
|
|
cb(er);
|
|
stream._writableState.errorEmitted = true;
|
|
stream.emit("error", er);
|
|
finishMaybe(stream, state);
|
|
}
|
|
}
|
|
function onwriteStateUpdate(state) {
|
|
state.writing = false;
|
|
state.writecb = null;
|
|
state.length -= state.writelen;
|
|
state.writelen = 0;
|
|
}
|
|
function onwrite(stream, er) {
|
|
var state = stream._writableState;
|
|
var sync = state.sync;
|
|
var cb = state.writecb;
|
|
onwriteStateUpdate(state);
|
|
if (er) onwriteError(stream, state, sync, er, cb);
|
|
else {
|
|
var finished = needFinish(state);
|
|
if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
|
|
clearBuffer(stream, state);
|
|
}
|
|
if (sync) {
|
|
asyncWrite(afterWrite, stream, state, finished, cb);
|
|
} else {
|
|
afterWrite(stream, state, finished, cb);
|
|
}
|
|
}
|
|
}
|
|
function afterWrite(stream, state, finished, cb) {
|
|
if (!finished) onwriteDrain(stream, state);
|
|
state.pendingcb--;
|
|
cb();
|
|
finishMaybe(stream, state);
|
|
}
|
|
function onwriteDrain(stream, state) {
|
|
if (state.length === 0 && state.needDrain) {
|
|
state.needDrain = false;
|
|
stream.emit("drain");
|
|
}
|
|
}
|
|
function clearBuffer(stream, state) {
|
|
state.bufferProcessing = true;
|
|
var entry = state.bufferedRequest;
|
|
if (stream._writev && entry && entry.next) {
|
|
var l = state.bufferedRequestCount;
|
|
var buffer = new Array(l);
|
|
var holder = state.corkedRequestsFree;
|
|
holder.entry = entry;
|
|
var count = 0;
|
|
var allBuffers = true;
|
|
while (entry) {
|
|
buffer[count] = entry;
|
|
if (!entry.isBuf) allBuffers = false;
|
|
entry = entry.next;
|
|
count += 1;
|
|
}
|
|
buffer.allBuffers = allBuffers;
|
|
doWrite(stream, state, true, state.length, buffer, "", holder.finish);
|
|
state.pendingcb++;
|
|
state.lastBufferedRequest = null;
|
|
if (holder.next) {
|
|
state.corkedRequestsFree = holder.next;
|
|
holder.next = null;
|
|
} else {
|
|
state.corkedRequestsFree = new CorkedRequest(state);
|
|
}
|
|
state.bufferedRequestCount = 0;
|
|
} else {
|
|
while (entry) {
|
|
var chunk = entry.chunk;
|
|
var encoding = entry.encoding;
|
|
var cb = entry.callback;
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
entry = entry.next;
|
|
state.bufferedRequestCount--;
|
|
if (state.writing) {
|
|
break;
|
|
}
|
|
}
|
|
if (entry === null) state.lastBufferedRequest = null;
|
|
}
|
|
state.bufferedRequest = entry;
|
|
state.bufferProcessing = false;
|
|
}
|
|
Writable.prototype._write = function(chunk, encoding, cb) {
|
|
cb(new Error("_write() is not implemented"));
|
|
};
|
|
Writable.prototype._writev = null;
|
|
Writable.prototype.end = function(chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
if (typeof chunk === "function") {
|
|
cb = chunk;
|
|
chunk = null;
|
|
encoding = null;
|
|
} else if (typeof encoding === "function") {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
if (chunk !== null && chunk !== void 0) this.write(chunk, encoding);
|
|
if (state.corked) {
|
|
state.corked = 1;
|
|
this.uncork();
|
|
}
|
|
if (!state.ending) endWritable(this, state, cb);
|
|
};
|
|
function needFinish(state) {
|
|
return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
|
|
}
|
|
function callFinal(stream, state) {
|
|
stream._final(function(err) {
|
|
state.pendingcb--;
|
|
if (err) {
|
|
stream.emit("error", err);
|
|
}
|
|
state.prefinished = true;
|
|
stream.emit("prefinish");
|
|
finishMaybe(stream, state);
|
|
});
|
|
}
|
|
function prefinish(stream, state) {
|
|
if (!state.prefinished && !state.finalCalled) {
|
|
if (typeof stream._final === "function") {
|
|
state.pendingcb++;
|
|
state.finalCalled = true;
|
|
pna.nextTick(callFinal, stream, state);
|
|
} else {
|
|
state.prefinished = true;
|
|
stream.emit("prefinish");
|
|
}
|
|
}
|
|
}
|
|
function finishMaybe(stream, state) {
|
|
var need = needFinish(state);
|
|
if (need) {
|
|
prefinish(stream, state);
|
|
if (state.pendingcb === 0) {
|
|
state.finished = true;
|
|
stream.emit("finish");
|
|
}
|
|
}
|
|
return need;
|
|
}
|
|
function endWritable(stream, state, cb) {
|
|
state.ending = true;
|
|
finishMaybe(stream, state);
|
|
if (cb) {
|
|
if (state.finished) pna.nextTick(cb);
|
|
else stream.once("finish", cb);
|
|
}
|
|
state.ended = true;
|
|
stream.writable = false;
|
|
}
|
|
function onCorkedFinish(corkReq, state, err) {
|
|
var entry = corkReq.entry;
|
|
corkReq.entry = null;
|
|
while (entry) {
|
|
var cb = entry.callback;
|
|
state.pendingcb--;
|
|
cb(err);
|
|
entry = entry.next;
|
|
}
|
|
state.corkedRequestsFree.next = corkReq;
|
|
}
|
|
Object.defineProperty(Writable.prototype, "destroyed", {
|
|
get: function() {
|
|
if (this._writableState === void 0) {
|
|
return false;
|
|
}
|
|
return this._writableState.destroyed;
|
|
},
|
|
set: function(value) {
|
|
if (!this._writableState) {
|
|
return;
|
|
}
|
|
this._writableState.destroyed = value;
|
|
}
|
|
});
|
|
Writable.prototype.destroy = destroyImpl.destroy;
|
|
Writable.prototype._undestroy = destroyImpl.undestroy;
|
|
Writable.prototype._destroy = function(err, cb) {
|
|
this.end();
|
|
cb(err);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_duplex.js
|
|
var require_stream_duplex2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_duplex.js"(exports, module) {
|
|
"use strict";
|
|
var pna = require_process_nextick_args();
|
|
var objectKeys = Object.keys || function(obj) {
|
|
var keys2 = [];
|
|
for (var key in obj) {
|
|
keys2.push(key);
|
|
}
|
|
return keys2;
|
|
};
|
|
module.exports = Duplex;
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
var Readable = require_stream_readable2();
|
|
var Writable = require_stream_writable2();
|
|
util.inherits(Duplex, Readable);
|
|
{
|
|
keys = objectKeys(Writable.prototype);
|
|
for (v = 0; v < keys.length; v++) {
|
|
method = keys[v];
|
|
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
|
|
}
|
|
}
|
|
var keys;
|
|
var method;
|
|
var v;
|
|
function Duplex(options) {
|
|
if (!(this instanceof Duplex)) return new Duplex(options);
|
|
Readable.call(this, options);
|
|
Writable.call(this, options);
|
|
if (options && options.readable === false) this.readable = false;
|
|
if (options && options.writable === false) this.writable = false;
|
|
this.allowHalfOpen = true;
|
|
if (options && options.allowHalfOpen === false) this.allowHalfOpen = false;
|
|
this.once("end", onend);
|
|
}
|
|
Object.defineProperty(Duplex.prototype, "writableHighWaterMark", {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function() {
|
|
return this._writableState.highWaterMark;
|
|
}
|
|
});
|
|
function onend() {
|
|
if (this.allowHalfOpen || this._writableState.ended) return;
|
|
pna.nextTick(onEndNT, this);
|
|
}
|
|
function onEndNT(self2) {
|
|
self2.end();
|
|
}
|
|
Object.defineProperty(Duplex.prototype, "destroyed", {
|
|
get: function() {
|
|
if (this._readableState === void 0 || this._writableState === void 0) {
|
|
return false;
|
|
}
|
|
return this._readableState.destroyed && this._writableState.destroyed;
|
|
},
|
|
set: function(value) {
|
|
if (this._readableState === void 0 || this._writableState === void 0) {
|
|
return;
|
|
}
|
|
this._readableState.destroyed = value;
|
|
this._writableState.destroyed = value;
|
|
}
|
|
});
|
|
Duplex.prototype._destroy = function(err, cb) {
|
|
this.push(null);
|
|
this.end();
|
|
pna.nextTick(cb, err);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/string_decoder/lib/string_decoder.js
|
|
var require_string_decoder2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/string_decoder/lib/string_decoder.js"(exports) {
|
|
"use strict";
|
|
var Buffer2 = require_safe_buffer3().Buffer;
|
|
var isEncoding = Buffer2.isEncoding || function(encoding) {
|
|
encoding = "" + encoding;
|
|
switch (encoding && encoding.toLowerCase()) {
|
|
case "hex":
|
|
case "utf8":
|
|
case "utf-8":
|
|
case "ascii":
|
|
case "binary":
|
|
case "base64":
|
|
case "ucs2":
|
|
case "ucs-2":
|
|
case "utf16le":
|
|
case "utf-16le":
|
|
case "raw":
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
function _normalizeEncoding(enc) {
|
|
if (!enc) return "utf8";
|
|
var retried;
|
|
while (true) {
|
|
switch (enc) {
|
|
case "utf8":
|
|
case "utf-8":
|
|
return "utf8";
|
|
case "ucs2":
|
|
case "ucs-2":
|
|
case "utf16le":
|
|
case "utf-16le":
|
|
return "utf16le";
|
|
case "latin1":
|
|
case "binary":
|
|
return "latin1";
|
|
case "base64":
|
|
case "ascii":
|
|
case "hex":
|
|
return enc;
|
|
default:
|
|
if (retried) return;
|
|
enc = ("" + enc).toLowerCase();
|
|
retried = true;
|
|
}
|
|
}
|
|
}
|
|
function normalizeEncoding(enc) {
|
|
var nenc = _normalizeEncoding(enc);
|
|
if (typeof nenc !== "string" && (Buffer2.isEncoding === isEncoding || !isEncoding(enc))) throw new Error("Unknown encoding: " + enc);
|
|
return nenc || enc;
|
|
}
|
|
exports.StringDecoder = StringDecoder;
|
|
function StringDecoder(encoding) {
|
|
this.encoding = normalizeEncoding(encoding);
|
|
var nb;
|
|
switch (this.encoding) {
|
|
case "utf16le":
|
|
this.text = utf16Text;
|
|
this.end = utf16End;
|
|
nb = 4;
|
|
break;
|
|
case "utf8":
|
|
this.fillLast = utf8FillLast;
|
|
nb = 4;
|
|
break;
|
|
case "base64":
|
|
this.text = base64Text;
|
|
this.end = base64End;
|
|
nb = 3;
|
|
break;
|
|
default:
|
|
this.write = simpleWrite;
|
|
this.end = simpleEnd;
|
|
return;
|
|
}
|
|
this.lastNeed = 0;
|
|
this.lastTotal = 0;
|
|
this.lastChar = Buffer2.allocUnsafe(nb);
|
|
}
|
|
StringDecoder.prototype.write = function(buf) {
|
|
if (buf.length === 0) return "";
|
|
var r;
|
|
var i;
|
|
if (this.lastNeed) {
|
|
r = this.fillLast(buf);
|
|
if (r === void 0) return "";
|
|
i = this.lastNeed;
|
|
this.lastNeed = 0;
|
|
} else {
|
|
i = 0;
|
|
}
|
|
if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i);
|
|
return r || "";
|
|
};
|
|
StringDecoder.prototype.end = utf8End;
|
|
StringDecoder.prototype.text = utf8Text;
|
|
StringDecoder.prototype.fillLast = function(buf) {
|
|
if (this.lastNeed <= buf.length) {
|
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed);
|
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
}
|
|
buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length);
|
|
this.lastNeed -= buf.length;
|
|
};
|
|
function utf8CheckByte(byte) {
|
|
if (byte <= 127) return 0;
|
|
else if (byte >> 5 === 6) return 2;
|
|
else if (byte >> 4 === 14) return 3;
|
|
else if (byte >> 3 === 30) return 4;
|
|
return byte >> 6 === 2 ? -1 : -2;
|
|
}
|
|
function utf8CheckIncomplete(self2, buf, i) {
|
|
var j = buf.length - 1;
|
|
if (j < i) return 0;
|
|
var nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) self2.lastNeed = nb - 1;
|
|
return nb;
|
|
}
|
|
if (--j < i || nb === -2) return 0;
|
|
nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) self2.lastNeed = nb - 2;
|
|
return nb;
|
|
}
|
|
if (--j < i || nb === -2) return 0;
|
|
nb = utf8CheckByte(buf[j]);
|
|
if (nb >= 0) {
|
|
if (nb > 0) {
|
|
if (nb === 2) nb = 0;
|
|
else self2.lastNeed = nb - 3;
|
|
}
|
|
return nb;
|
|
}
|
|
return 0;
|
|
}
|
|
function utf8CheckExtraBytes(self2, buf, p) {
|
|
if ((buf[0] & 192) !== 128) {
|
|
self2.lastNeed = 0;
|
|
return "\uFFFD";
|
|
}
|
|
if (self2.lastNeed > 1 && buf.length > 1) {
|
|
if ((buf[1] & 192) !== 128) {
|
|
self2.lastNeed = 1;
|
|
return "\uFFFD";
|
|
}
|
|
if (self2.lastNeed > 2 && buf.length > 2) {
|
|
if ((buf[2] & 192) !== 128) {
|
|
self2.lastNeed = 2;
|
|
return "\uFFFD";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function utf8FillLast(buf) {
|
|
var p = this.lastTotal - this.lastNeed;
|
|
var r = utf8CheckExtraBytes(this, buf, p);
|
|
if (r !== void 0) return r;
|
|
if (this.lastNeed <= buf.length) {
|
|
buf.copy(this.lastChar, p, 0, this.lastNeed);
|
|
return this.lastChar.toString(this.encoding, 0, this.lastTotal);
|
|
}
|
|
buf.copy(this.lastChar, p, 0, buf.length);
|
|
this.lastNeed -= buf.length;
|
|
}
|
|
function utf8Text(buf, i) {
|
|
var total = utf8CheckIncomplete(this, buf, i);
|
|
if (!this.lastNeed) return buf.toString("utf8", i);
|
|
this.lastTotal = total;
|
|
var end = buf.length - (total - this.lastNeed);
|
|
buf.copy(this.lastChar, 0, end);
|
|
return buf.toString("utf8", i, end);
|
|
}
|
|
function utf8End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : "";
|
|
if (this.lastNeed) return r + "\uFFFD";
|
|
return r;
|
|
}
|
|
function utf16Text(buf, i) {
|
|
if ((buf.length - i) % 2 === 0) {
|
|
var r = buf.toString("utf16le", i);
|
|
if (r) {
|
|
var c = r.charCodeAt(r.length - 1);
|
|
if (c >= 55296 && c <= 56319) {
|
|
this.lastNeed = 2;
|
|
this.lastTotal = 4;
|
|
this.lastChar[0] = buf[buf.length - 2];
|
|
this.lastChar[1] = buf[buf.length - 1];
|
|
return r.slice(0, -1);
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
this.lastNeed = 1;
|
|
this.lastTotal = 2;
|
|
this.lastChar[0] = buf[buf.length - 1];
|
|
return buf.toString("utf16le", i, buf.length - 1);
|
|
}
|
|
function utf16End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : "";
|
|
if (this.lastNeed) {
|
|
var end = this.lastTotal - this.lastNeed;
|
|
return r + this.lastChar.toString("utf16le", 0, end);
|
|
}
|
|
return r;
|
|
}
|
|
function base64Text(buf, i) {
|
|
var n = (buf.length - i) % 3;
|
|
if (n === 0) return buf.toString("base64", i);
|
|
this.lastNeed = 3 - n;
|
|
this.lastTotal = 3;
|
|
if (n === 1) {
|
|
this.lastChar[0] = buf[buf.length - 1];
|
|
} else {
|
|
this.lastChar[0] = buf[buf.length - 2];
|
|
this.lastChar[1] = buf[buf.length - 1];
|
|
}
|
|
return buf.toString("base64", i, buf.length - n);
|
|
}
|
|
function base64End(buf) {
|
|
var r = buf && buf.length ? this.write(buf) : "";
|
|
if (this.lastNeed) return r + this.lastChar.toString("base64", 0, 3 - this.lastNeed);
|
|
return r;
|
|
}
|
|
function simpleWrite(buf) {
|
|
return buf.toString(this.encoding);
|
|
}
|
|
function simpleEnd(buf) {
|
|
return buf && buf.length ? this.write(buf) : "";
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js
|
|
var require_stream_readable2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_readable.js"(exports, module) {
|
|
"use strict";
|
|
var pna = require_process_nextick_args();
|
|
module.exports = Readable;
|
|
var isArray = require_isarray3();
|
|
var Duplex;
|
|
Readable.ReadableState = ReadableState;
|
|
var EE = __require("events").EventEmitter;
|
|
var EElistenerCount = function(emitter, type) {
|
|
return emitter.listeners(type).length;
|
|
};
|
|
var Stream = require_stream2();
|
|
var Buffer2 = require_safe_buffer3().Buffer;
|
|
var OurUint8Array = (typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {}).Uint8Array || function() {
|
|
};
|
|
function _uint8ArrayToBuffer(chunk) {
|
|
return Buffer2.from(chunk);
|
|
}
|
|
function _isUint8Array(obj) {
|
|
return Buffer2.isBuffer(obj) || obj instanceof OurUint8Array;
|
|
}
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
var debugUtil = __require("util");
|
|
var debug = void 0;
|
|
if (debugUtil && debugUtil.debuglog) {
|
|
debug = debugUtil.debuglog("stream");
|
|
} else {
|
|
debug = function() {
|
|
};
|
|
}
|
|
var BufferList = require_BufferList2();
|
|
var destroyImpl = require_destroy2();
|
|
var StringDecoder;
|
|
util.inherits(Readable, Stream);
|
|
var kProxyEvents = ["error", "close", "destroy", "pause", "resume"];
|
|
function prependListener(emitter, event, fn) {
|
|
if (typeof emitter.prependListener === "function") return emitter.prependListener(event, fn);
|
|
if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);
|
|
else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);
|
|
else emitter._events[event] = [fn, emitter._events[event]];
|
|
}
|
|
function ReadableState(options, stream) {
|
|
Duplex = Duplex || require_stream_duplex2();
|
|
options = options || {};
|
|
var isDuplex = stream instanceof Duplex;
|
|
this.objectMode = !!options.objectMode;
|
|
if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode;
|
|
var hwm = options.highWaterMark;
|
|
var readableHwm = options.readableHighWaterMark;
|
|
var defaultHwm = this.objectMode ? 16 : 16 * 1024;
|
|
if (hwm || hwm === 0) this.highWaterMark = hwm;
|
|
else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;
|
|
else this.highWaterMark = defaultHwm;
|
|
this.highWaterMark = Math.floor(this.highWaterMark);
|
|
this.buffer = new BufferList();
|
|
this.length = 0;
|
|
this.pipes = null;
|
|
this.pipesCount = 0;
|
|
this.flowing = null;
|
|
this.ended = false;
|
|
this.endEmitted = false;
|
|
this.reading = false;
|
|
this.sync = true;
|
|
this.needReadable = false;
|
|
this.emittedReadable = false;
|
|
this.readableListening = false;
|
|
this.resumeScheduled = false;
|
|
this.destroyed = false;
|
|
this.defaultEncoding = options.defaultEncoding || "utf8";
|
|
this.awaitDrain = 0;
|
|
this.readingMore = false;
|
|
this.decoder = null;
|
|
this.encoding = null;
|
|
if (options.encoding) {
|
|
if (!StringDecoder) StringDecoder = require_string_decoder2().StringDecoder;
|
|
this.decoder = new StringDecoder(options.encoding);
|
|
this.encoding = options.encoding;
|
|
}
|
|
}
|
|
function Readable(options) {
|
|
Duplex = Duplex || require_stream_duplex2();
|
|
if (!(this instanceof Readable)) return new Readable(options);
|
|
this._readableState = new ReadableState(options, this);
|
|
this.readable = true;
|
|
if (options) {
|
|
if (typeof options.read === "function") this._read = options.read;
|
|
if (typeof options.destroy === "function") this._destroy = options.destroy;
|
|
}
|
|
Stream.call(this);
|
|
}
|
|
Object.defineProperty(Readable.prototype, "destroyed", {
|
|
get: function() {
|
|
if (this._readableState === void 0) {
|
|
return false;
|
|
}
|
|
return this._readableState.destroyed;
|
|
},
|
|
set: function(value) {
|
|
if (!this._readableState) {
|
|
return;
|
|
}
|
|
this._readableState.destroyed = value;
|
|
}
|
|
});
|
|
Readable.prototype.destroy = destroyImpl.destroy;
|
|
Readable.prototype._undestroy = destroyImpl.undestroy;
|
|
Readable.prototype._destroy = function(err, cb) {
|
|
this.push(null);
|
|
cb(err);
|
|
};
|
|
Readable.prototype.push = function(chunk, encoding) {
|
|
var state = this._readableState;
|
|
var skipChunkCheck;
|
|
if (!state.objectMode) {
|
|
if (typeof chunk === "string") {
|
|
encoding = encoding || state.defaultEncoding;
|
|
if (encoding !== state.encoding) {
|
|
chunk = Buffer2.from(chunk, encoding);
|
|
encoding = "";
|
|
}
|
|
skipChunkCheck = true;
|
|
}
|
|
} else {
|
|
skipChunkCheck = true;
|
|
}
|
|
return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
|
|
};
|
|
Readable.prototype.unshift = function(chunk) {
|
|
return readableAddChunk(this, chunk, null, true, false);
|
|
};
|
|
function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
|
|
var state = stream._readableState;
|
|
if (chunk === null) {
|
|
state.reading = false;
|
|
onEofChunk(stream, state);
|
|
} else {
|
|
var er;
|
|
if (!skipChunkCheck) er = chunkInvalid(state, chunk);
|
|
if (er) {
|
|
stream.emit("error", er);
|
|
} else if (state.objectMode || chunk && chunk.length > 0) {
|
|
if (typeof chunk !== "string" && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer2.prototype) {
|
|
chunk = _uint8ArrayToBuffer(chunk);
|
|
}
|
|
if (addToFront) {
|
|
if (state.endEmitted) stream.emit("error", new Error("stream.unshift() after end event"));
|
|
else addChunk(stream, state, chunk, true);
|
|
} else if (state.ended) {
|
|
stream.emit("error", new Error("stream.push() after EOF"));
|
|
} else {
|
|
state.reading = false;
|
|
if (state.decoder && !encoding) {
|
|
chunk = state.decoder.write(chunk);
|
|
if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);
|
|
else maybeReadMore(stream, state);
|
|
} else {
|
|
addChunk(stream, state, chunk, false);
|
|
}
|
|
}
|
|
} else if (!addToFront) {
|
|
state.reading = false;
|
|
}
|
|
}
|
|
return needMoreData(state);
|
|
}
|
|
function addChunk(stream, state, chunk, addToFront) {
|
|
if (state.flowing && state.length === 0 && !state.sync) {
|
|
stream.emit("data", chunk);
|
|
stream.read(0);
|
|
} else {
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
if (addToFront) state.buffer.unshift(chunk);
|
|
else state.buffer.push(chunk);
|
|
if (state.needReadable) emitReadable(stream);
|
|
}
|
|
maybeReadMore(stream, state);
|
|
}
|
|
function chunkInvalid(state, chunk) {
|
|
var er;
|
|
if (!_isUint8Array(chunk) && typeof chunk !== "string" && chunk !== void 0 && !state.objectMode) {
|
|
er = new TypeError("Invalid non-string/buffer chunk");
|
|
}
|
|
return er;
|
|
}
|
|
function needMoreData(state) {
|
|
return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
|
|
}
|
|
Readable.prototype.isPaused = function() {
|
|
return this._readableState.flowing === false;
|
|
};
|
|
Readable.prototype.setEncoding = function(enc) {
|
|
if (!StringDecoder) StringDecoder = require_string_decoder2().StringDecoder;
|
|
this._readableState.decoder = new StringDecoder(enc);
|
|
this._readableState.encoding = enc;
|
|
return this;
|
|
};
|
|
var MAX_HWM = 8388608;
|
|
function computeNewHighWaterMark(n) {
|
|
if (n >= MAX_HWM) {
|
|
n = MAX_HWM;
|
|
} else {
|
|
n--;
|
|
n |= n >>> 1;
|
|
n |= n >>> 2;
|
|
n |= n >>> 4;
|
|
n |= n >>> 8;
|
|
n |= n >>> 16;
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
function howMuchToRead(n, state) {
|
|
if (n <= 0 || state.length === 0 && state.ended) return 0;
|
|
if (state.objectMode) return 1;
|
|
if (n !== n) {
|
|
if (state.flowing && state.length) return state.buffer.head.data.length;
|
|
else return state.length;
|
|
}
|
|
if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n);
|
|
if (n <= state.length) return n;
|
|
if (!state.ended) {
|
|
state.needReadable = true;
|
|
return 0;
|
|
}
|
|
return state.length;
|
|
}
|
|
Readable.prototype.read = function(n) {
|
|
debug("read", n);
|
|
n = parseInt(n, 10);
|
|
var state = this._readableState;
|
|
var nOrig = n;
|
|
if (n !== 0) state.emittedReadable = false;
|
|
if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) {
|
|
debug("read: emitReadable", state.length, state.ended);
|
|
if (state.length === 0 && state.ended) endReadable(this);
|
|
else emitReadable(this);
|
|
return null;
|
|
}
|
|
n = howMuchToRead(n, state);
|
|
if (n === 0 && state.ended) {
|
|
if (state.length === 0) endReadable(this);
|
|
return null;
|
|
}
|
|
var doRead = state.needReadable;
|
|
debug("need readable", doRead);
|
|
if (state.length === 0 || state.length - n < state.highWaterMark) {
|
|
doRead = true;
|
|
debug("length less than watermark", doRead);
|
|
}
|
|
if (state.ended || state.reading) {
|
|
doRead = false;
|
|
debug("reading or ended", doRead);
|
|
} else if (doRead) {
|
|
debug("do read");
|
|
state.reading = true;
|
|
state.sync = true;
|
|
if (state.length === 0) state.needReadable = true;
|
|
this._read(state.highWaterMark);
|
|
state.sync = false;
|
|
if (!state.reading) n = howMuchToRead(nOrig, state);
|
|
}
|
|
var ret;
|
|
if (n > 0) ret = fromList(n, state);
|
|
else ret = null;
|
|
if (ret === null) {
|
|
state.needReadable = true;
|
|
n = 0;
|
|
} else {
|
|
state.length -= n;
|
|
}
|
|
if (state.length === 0) {
|
|
if (!state.ended) state.needReadable = true;
|
|
if (nOrig !== n && state.ended) endReadable(this);
|
|
}
|
|
if (ret !== null) this.emit("data", ret);
|
|
return ret;
|
|
};
|
|
function onEofChunk(stream, state) {
|
|
if (state.ended) return;
|
|
if (state.decoder) {
|
|
var chunk = state.decoder.end();
|
|
if (chunk && chunk.length) {
|
|
state.buffer.push(chunk);
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
}
|
|
}
|
|
state.ended = true;
|
|
emitReadable(stream);
|
|
}
|
|
function emitReadable(stream) {
|
|
var state = stream._readableState;
|
|
state.needReadable = false;
|
|
if (!state.emittedReadable) {
|
|
debug("emitReadable", state.flowing);
|
|
state.emittedReadable = true;
|
|
if (state.sync) pna.nextTick(emitReadable_, stream);
|
|
else emitReadable_(stream);
|
|
}
|
|
}
|
|
function emitReadable_(stream) {
|
|
debug("emit readable");
|
|
stream.emit("readable");
|
|
flow(stream);
|
|
}
|
|
function maybeReadMore(stream, state) {
|
|
if (!state.readingMore) {
|
|
state.readingMore = true;
|
|
pna.nextTick(maybeReadMore_, stream, state);
|
|
}
|
|
}
|
|
function maybeReadMore_(stream, state) {
|
|
var len = state.length;
|
|
while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) {
|
|
debug("maybeReadMore read 0");
|
|
stream.read(0);
|
|
if (len === state.length)
|
|
break;
|
|
else len = state.length;
|
|
}
|
|
state.readingMore = false;
|
|
}
|
|
Readable.prototype._read = function(n) {
|
|
this.emit("error", new Error("_read() is not implemented"));
|
|
};
|
|
Readable.prototype.pipe = function(dest, pipeOpts) {
|
|
var src = this;
|
|
var state = this._readableState;
|
|
switch (state.pipesCount) {
|
|
case 0:
|
|
state.pipes = dest;
|
|
break;
|
|
case 1:
|
|
state.pipes = [state.pipes, dest];
|
|
break;
|
|
default:
|
|
state.pipes.push(dest);
|
|
break;
|
|
}
|
|
state.pipesCount += 1;
|
|
debug("pipe count=%d opts=%j", state.pipesCount, pipeOpts);
|
|
var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
|
|
var endFn = doEnd ? onend : unpipe;
|
|
if (state.endEmitted) pna.nextTick(endFn);
|
|
else src.once("end", endFn);
|
|
dest.on("unpipe", onunpipe);
|
|
function onunpipe(readable, unpipeInfo) {
|
|
debug("onunpipe");
|
|
if (readable === src) {
|
|
if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
|
|
unpipeInfo.hasUnpiped = true;
|
|
cleanup();
|
|
}
|
|
}
|
|
}
|
|
function onend() {
|
|
debug("onend");
|
|
dest.end();
|
|
}
|
|
var ondrain = pipeOnDrain(src);
|
|
dest.on("drain", ondrain);
|
|
var cleanedUp = false;
|
|
function cleanup() {
|
|
debug("cleanup");
|
|
dest.removeListener("close", onclose);
|
|
dest.removeListener("finish", onfinish);
|
|
dest.removeListener("drain", ondrain);
|
|
dest.removeListener("error", onerror);
|
|
dest.removeListener("unpipe", onunpipe);
|
|
src.removeListener("end", onend);
|
|
src.removeListener("end", unpipe);
|
|
src.removeListener("data", ondata);
|
|
cleanedUp = true;
|
|
if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain();
|
|
}
|
|
var increasedAwaitDrain = false;
|
|
src.on("data", ondata);
|
|
function ondata(chunk) {
|
|
debug("ondata");
|
|
increasedAwaitDrain = false;
|
|
var ret = dest.write(chunk);
|
|
if (false === ret && !increasedAwaitDrain) {
|
|
if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) {
|
|
debug("false write response, pause", state.awaitDrain);
|
|
state.awaitDrain++;
|
|
increasedAwaitDrain = true;
|
|
}
|
|
src.pause();
|
|
}
|
|
}
|
|
function onerror(er) {
|
|
debug("onerror", er);
|
|
unpipe();
|
|
dest.removeListener("error", onerror);
|
|
if (EElistenerCount(dest, "error") === 0) dest.emit("error", er);
|
|
}
|
|
prependListener(dest, "error", onerror);
|
|
function onclose() {
|
|
dest.removeListener("finish", onfinish);
|
|
unpipe();
|
|
}
|
|
dest.once("close", onclose);
|
|
function onfinish() {
|
|
debug("onfinish");
|
|
dest.removeListener("close", onclose);
|
|
unpipe();
|
|
}
|
|
dest.once("finish", onfinish);
|
|
function unpipe() {
|
|
debug("unpipe");
|
|
src.unpipe(dest);
|
|
}
|
|
dest.emit("pipe", src);
|
|
if (!state.flowing) {
|
|
debug("pipe resume");
|
|
src.resume();
|
|
}
|
|
return dest;
|
|
};
|
|
function pipeOnDrain(src) {
|
|
return function() {
|
|
var state = src._readableState;
|
|
debug("pipeOnDrain", state.awaitDrain);
|
|
if (state.awaitDrain) state.awaitDrain--;
|
|
if (state.awaitDrain === 0 && EElistenerCount(src, "data")) {
|
|
state.flowing = true;
|
|
flow(src);
|
|
}
|
|
};
|
|
}
|
|
Readable.prototype.unpipe = function(dest) {
|
|
var state = this._readableState;
|
|
var unpipeInfo = { hasUnpiped: false };
|
|
if (state.pipesCount === 0) return this;
|
|
if (state.pipesCount === 1) {
|
|
if (dest && dest !== state.pipes) return this;
|
|
if (!dest) dest = state.pipes;
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
if (dest) dest.emit("unpipe", this, unpipeInfo);
|
|
return this;
|
|
}
|
|
if (!dest) {
|
|
var dests = state.pipes;
|
|
var len = state.pipesCount;
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
for (var i = 0; i < len; i++) {
|
|
dests[i].emit("unpipe", this, { hasUnpiped: false });
|
|
}
|
|
return this;
|
|
}
|
|
var index = indexOf(state.pipes, dest);
|
|
if (index === -1) return this;
|
|
state.pipes.splice(index, 1);
|
|
state.pipesCount -= 1;
|
|
if (state.pipesCount === 1) state.pipes = state.pipes[0];
|
|
dest.emit("unpipe", this, unpipeInfo);
|
|
return this;
|
|
};
|
|
Readable.prototype.on = function(ev, fn) {
|
|
var res = Stream.prototype.on.call(this, ev, fn);
|
|
if (ev === "data") {
|
|
if (this._readableState.flowing !== false) this.resume();
|
|
} else if (ev === "readable") {
|
|
var state = this._readableState;
|
|
if (!state.endEmitted && !state.readableListening) {
|
|
state.readableListening = state.needReadable = true;
|
|
state.emittedReadable = false;
|
|
if (!state.reading) {
|
|
pna.nextTick(nReadingNextTick, this);
|
|
} else if (state.length) {
|
|
emitReadable(this);
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
};
|
|
Readable.prototype.addListener = Readable.prototype.on;
|
|
function nReadingNextTick(self2) {
|
|
debug("readable nexttick read 0");
|
|
self2.read(0);
|
|
}
|
|
Readable.prototype.resume = function() {
|
|
var state = this._readableState;
|
|
if (!state.flowing) {
|
|
debug("resume");
|
|
state.flowing = true;
|
|
resume(this, state);
|
|
}
|
|
return this;
|
|
};
|
|
function resume(stream, state) {
|
|
if (!state.resumeScheduled) {
|
|
state.resumeScheduled = true;
|
|
pna.nextTick(resume_, stream, state);
|
|
}
|
|
}
|
|
function resume_(stream, state) {
|
|
if (!state.reading) {
|
|
debug("resume read 0");
|
|
stream.read(0);
|
|
}
|
|
state.resumeScheduled = false;
|
|
state.awaitDrain = 0;
|
|
stream.emit("resume");
|
|
flow(stream);
|
|
if (state.flowing && !state.reading) stream.read(0);
|
|
}
|
|
Readable.prototype.pause = function() {
|
|
debug("call pause flowing=%j", this._readableState.flowing);
|
|
if (false !== this._readableState.flowing) {
|
|
debug("pause");
|
|
this._readableState.flowing = false;
|
|
this.emit("pause");
|
|
}
|
|
return this;
|
|
};
|
|
function flow(stream) {
|
|
var state = stream._readableState;
|
|
debug("flow", state.flowing);
|
|
while (state.flowing && stream.read() !== null) {
|
|
}
|
|
}
|
|
Readable.prototype.wrap = function(stream) {
|
|
var _this = this;
|
|
var state = this._readableState;
|
|
var paused = false;
|
|
stream.on("end", function() {
|
|
debug("wrapped end");
|
|
if (state.decoder && !state.ended) {
|
|
var chunk = state.decoder.end();
|
|
if (chunk && chunk.length) _this.push(chunk);
|
|
}
|
|
_this.push(null);
|
|
});
|
|
stream.on("data", function(chunk) {
|
|
debug("wrapped data");
|
|
if (state.decoder) chunk = state.decoder.write(chunk);
|
|
if (state.objectMode && (chunk === null || chunk === void 0)) return;
|
|
else if (!state.objectMode && (!chunk || !chunk.length)) return;
|
|
var ret = _this.push(chunk);
|
|
if (!ret) {
|
|
paused = true;
|
|
stream.pause();
|
|
}
|
|
});
|
|
for (var i in stream) {
|
|
if (this[i] === void 0 && typeof stream[i] === "function") {
|
|
this[i] = /* @__PURE__ */ (function(method) {
|
|
return function() {
|
|
return stream[method].apply(stream, arguments);
|
|
};
|
|
})(i);
|
|
}
|
|
}
|
|
for (var n = 0; n < kProxyEvents.length; n++) {
|
|
stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n]));
|
|
}
|
|
this._read = function(n2) {
|
|
debug("wrapped _read", n2);
|
|
if (paused) {
|
|
paused = false;
|
|
stream.resume();
|
|
}
|
|
};
|
|
return this;
|
|
};
|
|
Object.defineProperty(Readable.prototype, "readableHighWaterMark", {
|
|
// making it explicit this property is not enumerable
|
|
// because otherwise some prototype manipulation in
|
|
// userland will fail
|
|
enumerable: false,
|
|
get: function() {
|
|
return this._readableState.highWaterMark;
|
|
}
|
|
});
|
|
Readable._fromList = fromList;
|
|
function fromList(n, state) {
|
|
if (state.length === 0) return null;
|
|
var ret;
|
|
if (state.objectMode) ret = state.buffer.shift();
|
|
else if (!n || n >= state.length) {
|
|
if (state.decoder) ret = state.buffer.join("");
|
|
else if (state.buffer.length === 1) ret = state.buffer.head.data;
|
|
else ret = state.buffer.concat(state.length);
|
|
state.buffer.clear();
|
|
} else {
|
|
ret = fromListPartial(n, state.buffer, state.decoder);
|
|
}
|
|
return ret;
|
|
}
|
|
function fromListPartial(n, list, hasStrings) {
|
|
var ret;
|
|
if (n < list.head.data.length) {
|
|
ret = list.head.data.slice(0, n);
|
|
list.head.data = list.head.data.slice(n);
|
|
} else if (n === list.head.data.length) {
|
|
ret = list.shift();
|
|
} else {
|
|
ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list);
|
|
}
|
|
return ret;
|
|
}
|
|
function copyFromBufferString(n, list) {
|
|
var p = list.head;
|
|
var c = 1;
|
|
var ret = p.data;
|
|
n -= ret.length;
|
|
while (p = p.next) {
|
|
var str = p.data;
|
|
var nb = n > str.length ? str.length : n;
|
|
if (nb === str.length) ret += str;
|
|
else ret += str.slice(0, n);
|
|
n -= nb;
|
|
if (n === 0) {
|
|
if (nb === str.length) {
|
|
++c;
|
|
if (p.next) list.head = p.next;
|
|
else list.head = list.tail = null;
|
|
} else {
|
|
list.head = p;
|
|
p.data = str.slice(nb);
|
|
}
|
|
break;
|
|
}
|
|
++c;
|
|
}
|
|
list.length -= c;
|
|
return ret;
|
|
}
|
|
function copyFromBuffer(n, list) {
|
|
var ret = Buffer2.allocUnsafe(n);
|
|
var p = list.head;
|
|
var c = 1;
|
|
p.data.copy(ret);
|
|
n -= p.data.length;
|
|
while (p = p.next) {
|
|
var buf = p.data;
|
|
var nb = n > buf.length ? buf.length : n;
|
|
buf.copy(ret, ret.length - n, 0, nb);
|
|
n -= nb;
|
|
if (n === 0) {
|
|
if (nb === buf.length) {
|
|
++c;
|
|
if (p.next) list.head = p.next;
|
|
else list.head = list.tail = null;
|
|
} else {
|
|
list.head = p;
|
|
p.data = buf.slice(nb);
|
|
}
|
|
break;
|
|
}
|
|
++c;
|
|
}
|
|
list.length -= c;
|
|
return ret;
|
|
}
|
|
function endReadable(stream) {
|
|
var state = stream._readableState;
|
|
if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream');
|
|
if (!state.endEmitted) {
|
|
state.ended = true;
|
|
pna.nextTick(endReadableNT, state, stream);
|
|
}
|
|
}
|
|
function endReadableNT(state, stream) {
|
|
if (!state.endEmitted && state.length === 0) {
|
|
state.endEmitted = true;
|
|
stream.readable = false;
|
|
stream.emit("end");
|
|
}
|
|
}
|
|
function indexOf(xs, x) {
|
|
for (var i = 0, l = xs.length; i < l; i++) {
|
|
if (xs[i] === x) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_transform.js
|
|
var require_stream_transform2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_transform.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = Transform;
|
|
var Duplex = require_stream_duplex2();
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
util.inherits(Transform, Duplex);
|
|
function afterTransform(er, data) {
|
|
var ts = this._transformState;
|
|
ts.transforming = false;
|
|
var cb = ts.writecb;
|
|
if (!cb) {
|
|
return this.emit("error", new Error("write callback called multiple times"));
|
|
}
|
|
ts.writechunk = null;
|
|
ts.writecb = null;
|
|
if (data != null)
|
|
this.push(data);
|
|
cb(er);
|
|
var rs = this._readableState;
|
|
rs.reading = false;
|
|
if (rs.needReadable || rs.length < rs.highWaterMark) {
|
|
this._read(rs.highWaterMark);
|
|
}
|
|
}
|
|
function Transform(options) {
|
|
if (!(this instanceof Transform)) return new Transform(options);
|
|
Duplex.call(this, options);
|
|
this._transformState = {
|
|
afterTransform: afterTransform.bind(this),
|
|
needTransform: false,
|
|
transforming: false,
|
|
writecb: null,
|
|
writechunk: null,
|
|
writeencoding: null
|
|
};
|
|
this._readableState.needReadable = true;
|
|
this._readableState.sync = false;
|
|
if (options) {
|
|
if (typeof options.transform === "function") this._transform = options.transform;
|
|
if (typeof options.flush === "function") this._flush = options.flush;
|
|
}
|
|
this.on("prefinish", prefinish);
|
|
}
|
|
function prefinish() {
|
|
var _this = this;
|
|
if (typeof this._flush === "function") {
|
|
this._flush(function(er, data) {
|
|
done(_this, er, data);
|
|
});
|
|
} else {
|
|
done(this, null, null);
|
|
}
|
|
}
|
|
Transform.prototype.push = function(chunk, encoding) {
|
|
this._transformState.needTransform = false;
|
|
return Duplex.prototype.push.call(this, chunk, encoding);
|
|
};
|
|
Transform.prototype._transform = function(chunk, encoding, cb) {
|
|
throw new Error("_transform() is not implemented");
|
|
};
|
|
Transform.prototype._write = function(chunk, encoding, cb) {
|
|
var ts = this._transformState;
|
|
ts.writecb = cb;
|
|
ts.writechunk = chunk;
|
|
ts.writeencoding = encoding;
|
|
if (!ts.transforming) {
|
|
var rs = this._readableState;
|
|
if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
|
|
}
|
|
};
|
|
Transform.prototype._read = function(n) {
|
|
var ts = this._transformState;
|
|
if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
|
|
ts.transforming = true;
|
|
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
|
|
} else {
|
|
ts.needTransform = true;
|
|
}
|
|
};
|
|
Transform.prototype._destroy = function(err, cb) {
|
|
var _this2 = this;
|
|
Duplex.prototype._destroy.call(this, err, function(err2) {
|
|
cb(err2);
|
|
_this2.emit("close");
|
|
});
|
|
};
|
|
function done(stream, er, data) {
|
|
if (er) return stream.emit("error", er);
|
|
if (data != null)
|
|
stream.push(data);
|
|
if (stream._writableState.length) throw new Error("Calling transform done when ws.length != 0");
|
|
if (stream._transformState.transforming) throw new Error("Calling transform done when still transforming");
|
|
return stream.push(null);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_passthrough.js
|
|
var require_stream_passthrough2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/lib/_stream_passthrough.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = PassThrough;
|
|
var Transform = require_stream_transform2();
|
|
var util = Object.create(require_util());
|
|
util.inherits = require_inherits();
|
|
util.inherits(PassThrough, Transform);
|
|
function PassThrough(options) {
|
|
if (!(this instanceof PassThrough)) return new PassThrough(options);
|
|
Transform.call(this, options);
|
|
}
|
|
PassThrough.prototype._transform = function(chunk, encoding, cb) {
|
|
cb(null, chunk);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/node_modules/readable-stream/readable.js
|
|
var require_readable2 = __commonJS({
|
|
"../../node_modules/tar-stream/node_modules/readable-stream/readable.js"(exports, module) {
|
|
var Stream = __require("stream");
|
|
if (process.env.READABLE_STREAM === "disable" && Stream) {
|
|
module.exports = Stream;
|
|
exports = module.exports = Stream.Readable;
|
|
exports.Readable = Stream.Readable;
|
|
exports.Writable = Stream.Writable;
|
|
exports.Duplex = Stream.Duplex;
|
|
exports.Transform = Stream.Transform;
|
|
exports.PassThrough = Stream.PassThrough;
|
|
exports.Stream = Stream;
|
|
} else {
|
|
exports = module.exports = require_stream_readable2();
|
|
exports.Stream = Stream || exports;
|
|
exports.Readable = exports;
|
|
exports.Writable = require_stream_writable2();
|
|
exports.Duplex = require_stream_duplex2();
|
|
exports.Transform = require_stream_transform2();
|
|
exports.PassThrough = require_stream_passthrough2();
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/extract.js
|
|
var require_extract = __commonJS({
|
|
"../../node_modules/tar-stream/extract.js"(exports, module) {
|
|
var util = __require("util");
|
|
var bl = require_bl();
|
|
var xtend = require_immutable();
|
|
var headers = require_headers();
|
|
var Writable = require_readable2().Writable;
|
|
var PassThrough = require_readable2().PassThrough;
|
|
var noop = function() {
|
|
};
|
|
var overflow = function(size) {
|
|
size &= 511;
|
|
return size && 512 - size;
|
|
};
|
|
var emptyStream = function(self2, offset) {
|
|
var s = new Source(self2, offset);
|
|
s.end();
|
|
return s;
|
|
};
|
|
var mixinPax = function(header, pax) {
|
|
if (pax.path) header.name = pax.path;
|
|
if (pax.linkpath) header.linkname = pax.linkpath;
|
|
if (pax.size) header.size = parseInt(pax.size, 10);
|
|
header.pax = pax;
|
|
return header;
|
|
};
|
|
var Source = function(self2, offset) {
|
|
this._parent = self2;
|
|
this.offset = offset;
|
|
PassThrough.call(this);
|
|
};
|
|
util.inherits(Source, PassThrough);
|
|
Source.prototype.destroy = function(err) {
|
|
this._parent.destroy(err);
|
|
};
|
|
var Extract = function(opts) {
|
|
if (!(this instanceof Extract)) return new Extract(opts);
|
|
Writable.call(this, opts);
|
|
opts = opts || {};
|
|
this._offset = 0;
|
|
this._buffer = bl();
|
|
this._missing = 0;
|
|
this._partial = false;
|
|
this._onparse = noop;
|
|
this._header = null;
|
|
this._stream = null;
|
|
this._overflow = null;
|
|
this._cb = null;
|
|
this._locked = false;
|
|
this._destroyed = false;
|
|
this._pax = null;
|
|
this._paxGlobal = null;
|
|
this._gnuLongPath = null;
|
|
this._gnuLongLinkPath = null;
|
|
var self2 = this;
|
|
var b = self2._buffer;
|
|
var oncontinue = function() {
|
|
self2._continue();
|
|
};
|
|
var onunlock = function(err) {
|
|
self2._locked = false;
|
|
if (err) return self2.destroy(err);
|
|
if (!self2._stream) oncontinue();
|
|
};
|
|
var onstreamend = function() {
|
|
self2._stream = null;
|
|
var drain = overflow(self2._header.size);
|
|
if (drain) self2._parse(drain, ondrain);
|
|
else self2._parse(512, onheader);
|
|
if (!self2._locked) oncontinue();
|
|
};
|
|
var ondrain = function() {
|
|
self2._buffer.consume(overflow(self2._header.size));
|
|
self2._parse(512, onheader);
|
|
oncontinue();
|
|
};
|
|
var onpaxglobalheader = function() {
|
|
var size = self2._header.size;
|
|
self2._paxGlobal = headers.decodePax(b.slice(0, size));
|
|
b.consume(size);
|
|
onstreamend();
|
|
};
|
|
var onpaxheader = function() {
|
|
var size = self2._header.size;
|
|
self2._pax = headers.decodePax(b.slice(0, size));
|
|
if (self2._paxGlobal) self2._pax = xtend(self2._paxGlobal, self2._pax);
|
|
b.consume(size);
|
|
onstreamend();
|
|
};
|
|
var ongnulongpath = function() {
|
|
var size = self2._header.size;
|
|
this._gnuLongPath = headers.decodeLongPath(b.slice(0, size), opts.filenameEncoding);
|
|
b.consume(size);
|
|
onstreamend();
|
|
};
|
|
var ongnulonglinkpath = function() {
|
|
var size = self2._header.size;
|
|
this._gnuLongLinkPath = headers.decodeLongPath(b.slice(0, size), opts.filenameEncoding);
|
|
b.consume(size);
|
|
onstreamend();
|
|
};
|
|
var onheader = function() {
|
|
var offset = self2._offset;
|
|
var header;
|
|
try {
|
|
header = self2._header = headers.decode(b.slice(0, 512), opts.filenameEncoding);
|
|
} catch (err) {
|
|
self2.emit("error", err);
|
|
}
|
|
b.consume(512);
|
|
if (!header) {
|
|
self2._parse(512, onheader);
|
|
oncontinue();
|
|
return;
|
|
}
|
|
if (header.type === "gnu-long-path") {
|
|
self2._parse(header.size, ongnulongpath);
|
|
oncontinue();
|
|
return;
|
|
}
|
|
if (header.type === "gnu-long-link-path") {
|
|
self2._parse(header.size, ongnulonglinkpath);
|
|
oncontinue();
|
|
return;
|
|
}
|
|
if (header.type === "pax-global-header") {
|
|
self2._parse(header.size, onpaxglobalheader);
|
|
oncontinue();
|
|
return;
|
|
}
|
|
if (header.type === "pax-header") {
|
|
self2._parse(header.size, onpaxheader);
|
|
oncontinue();
|
|
return;
|
|
}
|
|
if (self2._gnuLongPath) {
|
|
header.name = self2._gnuLongPath;
|
|
self2._gnuLongPath = null;
|
|
}
|
|
if (self2._gnuLongLinkPath) {
|
|
header.linkname = self2._gnuLongLinkPath;
|
|
self2._gnuLongLinkPath = null;
|
|
}
|
|
if (self2._pax) {
|
|
self2._header = header = mixinPax(header, self2._pax);
|
|
self2._pax = null;
|
|
}
|
|
self2._locked = true;
|
|
if (!header.size || header.type === "directory") {
|
|
self2._parse(512, onheader);
|
|
self2.emit("entry", header, emptyStream(self2, offset), onunlock);
|
|
return;
|
|
}
|
|
self2._stream = new Source(self2, offset);
|
|
self2.emit("entry", header, self2._stream, onunlock);
|
|
self2._parse(header.size, onstreamend);
|
|
oncontinue();
|
|
};
|
|
this._onheader = onheader;
|
|
this._parse(512, onheader);
|
|
};
|
|
util.inherits(Extract, Writable);
|
|
Extract.prototype.destroy = function(err) {
|
|
if (this._destroyed) return;
|
|
this._destroyed = true;
|
|
if (err) this.emit("error", err);
|
|
this.emit("close");
|
|
if (this._stream) this._stream.emit("close");
|
|
};
|
|
Extract.prototype._parse = function(size, onparse) {
|
|
if (this._destroyed) return;
|
|
this._offset += size;
|
|
this._missing = size;
|
|
if (onparse === this._onheader) this._partial = false;
|
|
this._onparse = onparse;
|
|
};
|
|
Extract.prototype._continue = function() {
|
|
if (this._destroyed) return;
|
|
var cb = this._cb;
|
|
this._cb = noop;
|
|
if (this._overflow) this._write(this._overflow, void 0, cb);
|
|
else cb();
|
|
};
|
|
Extract.prototype._write = function(data, enc, cb) {
|
|
if (this._destroyed) return;
|
|
var s = this._stream;
|
|
var b = this._buffer;
|
|
var missing = this._missing;
|
|
if (data.length) this._partial = true;
|
|
if (data.length < missing) {
|
|
this._missing -= data.length;
|
|
this._overflow = null;
|
|
if (s) return s.write(data, cb);
|
|
b.append(data);
|
|
return cb();
|
|
}
|
|
this._cb = cb;
|
|
this._missing = 0;
|
|
var overflow2 = null;
|
|
if (data.length > missing) {
|
|
overflow2 = data.slice(missing);
|
|
data = data.slice(0, missing);
|
|
}
|
|
if (s) s.end(data);
|
|
else b.append(data);
|
|
this._overflow = overflow2;
|
|
this._onparse();
|
|
};
|
|
Extract.prototype._final = function(cb) {
|
|
if (this._partial) return this.destroy(new Error("Unexpected end of data"));
|
|
cb();
|
|
};
|
|
module.exports = Extract;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/fs-constants/index.js
|
|
var require_fs_constants = __commonJS({
|
|
"../../node_modules/fs-constants/index.js"(exports, module) {
|
|
module.exports = __require("fs").constants || __require("constants");
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/wrappy/wrappy.js
|
|
var require_wrappy = __commonJS({
|
|
"../../node_modules/wrappy/wrappy.js"(exports, module) {
|
|
module.exports = wrappy;
|
|
function wrappy(fn, cb) {
|
|
if (fn && cb) return wrappy(fn)(cb);
|
|
if (typeof fn !== "function")
|
|
throw new TypeError("need wrapper function");
|
|
Object.keys(fn).forEach(function(k) {
|
|
wrapper[k] = fn[k];
|
|
});
|
|
return wrapper;
|
|
function wrapper() {
|
|
var args = new Array(arguments.length);
|
|
for (var i = 0; i < args.length; i++) {
|
|
args[i] = arguments[i];
|
|
}
|
|
var ret = fn.apply(this, args);
|
|
var cb2 = args[args.length - 1];
|
|
if (typeof ret === "function" && ret !== cb2) {
|
|
Object.keys(cb2).forEach(function(k) {
|
|
ret[k] = cb2[k];
|
|
});
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/once/once.js
|
|
var require_once = __commonJS({
|
|
"../../node_modules/once/once.js"(exports, module) {
|
|
var wrappy = require_wrappy();
|
|
module.exports = wrappy(once);
|
|
module.exports.strict = wrappy(onceStrict);
|
|
once.proto = once(function() {
|
|
Object.defineProperty(Function.prototype, "once", {
|
|
value: function() {
|
|
return once(this);
|
|
},
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(Function.prototype, "onceStrict", {
|
|
value: function() {
|
|
return onceStrict(this);
|
|
},
|
|
configurable: true
|
|
});
|
|
});
|
|
function once(fn) {
|
|
var f = function() {
|
|
if (f.called) return f.value;
|
|
f.called = true;
|
|
return f.value = fn.apply(this, arguments);
|
|
};
|
|
f.called = false;
|
|
return f;
|
|
}
|
|
function onceStrict(fn) {
|
|
var f = function() {
|
|
if (f.called)
|
|
throw new Error(f.onceError);
|
|
f.called = true;
|
|
return f.value = fn.apply(this, arguments);
|
|
};
|
|
var name = fn.name || "Function wrapped with `once`";
|
|
f.onceError = name + " shouldn't be called more than once";
|
|
f.called = false;
|
|
return f;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/end-of-stream/index.js
|
|
var require_end_of_stream = __commonJS({
|
|
"../../node_modules/end-of-stream/index.js"(exports, module) {
|
|
var once = require_once();
|
|
var noop = function() {
|
|
};
|
|
var qnt = global.Bare ? queueMicrotask : process.nextTick.bind(process);
|
|
var isRequest = function(stream) {
|
|
return stream.setHeader && typeof stream.abort === "function";
|
|
};
|
|
var isChildProcess = function(stream) {
|
|
return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3;
|
|
};
|
|
var eos = function(stream, opts, callback) {
|
|
if (typeof opts === "function") return eos(stream, null, opts);
|
|
if (!opts) opts = {};
|
|
callback = once(callback || noop);
|
|
var ws = stream._writableState;
|
|
var rs = stream._readableState;
|
|
var readable = opts.readable || opts.readable !== false && stream.readable;
|
|
var writable = opts.writable || opts.writable !== false && stream.writable;
|
|
var cancelled = false;
|
|
var onlegacyfinish = function() {
|
|
if (!stream.writable) onfinish();
|
|
};
|
|
var onfinish = function() {
|
|
writable = false;
|
|
if (!readable) callback.call(stream);
|
|
};
|
|
var onend = function() {
|
|
readable = false;
|
|
if (!writable) callback.call(stream);
|
|
};
|
|
var onexit = function(exitCode) {
|
|
callback.call(stream, exitCode ? new Error("exited with error code: " + exitCode) : null);
|
|
};
|
|
var onerror = function(err) {
|
|
callback.call(stream, err);
|
|
};
|
|
var onclose = function() {
|
|
qnt(onclosenexttick);
|
|
};
|
|
var onclosenexttick = function() {
|
|
if (cancelled) return;
|
|
if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error("premature close"));
|
|
if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error("premature close"));
|
|
};
|
|
var onrequest = function() {
|
|
stream.req.on("finish", onfinish);
|
|
};
|
|
if (isRequest(stream)) {
|
|
stream.on("complete", onfinish);
|
|
stream.on("abort", onclose);
|
|
if (stream.req) onrequest();
|
|
else stream.on("request", onrequest);
|
|
} else if (writable && !ws) {
|
|
stream.on("end", onlegacyfinish);
|
|
stream.on("close", onlegacyfinish);
|
|
}
|
|
if (isChildProcess(stream)) stream.on("exit", onexit);
|
|
stream.on("end", onend);
|
|
stream.on("finish", onfinish);
|
|
if (opts.error !== false) stream.on("error", onerror);
|
|
stream.on("close", onclose);
|
|
return function() {
|
|
cancelled = true;
|
|
stream.removeListener("complete", onfinish);
|
|
stream.removeListener("abort", onclose);
|
|
stream.removeListener("request", onrequest);
|
|
if (stream.req) stream.req.removeListener("finish", onfinish);
|
|
stream.removeListener("end", onlegacyfinish);
|
|
stream.removeListener("close", onlegacyfinish);
|
|
stream.removeListener("finish", onfinish);
|
|
stream.removeListener("exit", onexit);
|
|
stream.removeListener("end", onend);
|
|
stream.removeListener("error", onerror);
|
|
stream.removeListener("close", onclose);
|
|
};
|
|
};
|
|
module.exports = eos;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/pack.js
|
|
var require_pack = __commonJS({
|
|
"../../node_modules/tar-stream/pack.js"(exports, module) {
|
|
var constants = require_fs_constants();
|
|
var eos = require_end_of_stream();
|
|
var util = __require("util");
|
|
var alloc = require_buffer_alloc();
|
|
var toBuffer = require_to_buffer();
|
|
var Readable = require_readable2().Readable;
|
|
var Writable = require_readable2().Writable;
|
|
var StringDecoder = __require("string_decoder").StringDecoder;
|
|
var headers = require_headers();
|
|
var DMODE = parseInt("755", 8);
|
|
var FMODE = parseInt("644", 8);
|
|
var END_OF_TAR = alloc(1024);
|
|
var noop = function() {
|
|
};
|
|
var overflow = function(self2, size) {
|
|
size &= 511;
|
|
if (size) self2.push(END_OF_TAR.slice(0, 512 - size));
|
|
};
|
|
function modeToType(mode) {
|
|
switch (mode & constants.S_IFMT) {
|
|
case constants.S_IFBLK:
|
|
return "block-device";
|
|
case constants.S_IFCHR:
|
|
return "character-device";
|
|
case constants.S_IFDIR:
|
|
return "directory";
|
|
case constants.S_IFIFO:
|
|
return "fifo";
|
|
case constants.S_IFLNK:
|
|
return "symlink";
|
|
}
|
|
return "file";
|
|
}
|
|
var Sink = function(to) {
|
|
Writable.call(this);
|
|
this.written = 0;
|
|
this._to = to;
|
|
this._destroyed = false;
|
|
};
|
|
util.inherits(Sink, Writable);
|
|
Sink.prototype._write = function(data, enc, cb) {
|
|
this.written += data.length;
|
|
if (this._to.push(data)) return cb();
|
|
this._to._drain = cb;
|
|
};
|
|
Sink.prototype.destroy = function() {
|
|
if (this._destroyed) return;
|
|
this._destroyed = true;
|
|
this.emit("close");
|
|
};
|
|
var LinkSink = function() {
|
|
Writable.call(this);
|
|
this.linkname = "";
|
|
this._decoder = new StringDecoder("utf-8");
|
|
this._destroyed = false;
|
|
};
|
|
util.inherits(LinkSink, Writable);
|
|
LinkSink.prototype._write = function(data, enc, cb) {
|
|
this.linkname += this._decoder.write(data);
|
|
cb();
|
|
};
|
|
LinkSink.prototype.destroy = function() {
|
|
if (this._destroyed) return;
|
|
this._destroyed = true;
|
|
this.emit("close");
|
|
};
|
|
var Void = function() {
|
|
Writable.call(this);
|
|
this._destroyed = false;
|
|
};
|
|
util.inherits(Void, Writable);
|
|
Void.prototype._write = function(data, enc, cb) {
|
|
cb(new Error("No body allowed for this entry"));
|
|
};
|
|
Void.prototype.destroy = function() {
|
|
if (this._destroyed) return;
|
|
this._destroyed = true;
|
|
this.emit("close");
|
|
};
|
|
var Pack = function(opts) {
|
|
if (!(this instanceof Pack)) return new Pack(opts);
|
|
Readable.call(this, opts);
|
|
this._drain = noop;
|
|
this._finalized = false;
|
|
this._finalizing = false;
|
|
this._destroyed = false;
|
|
this._stream = null;
|
|
};
|
|
util.inherits(Pack, Readable);
|
|
Pack.prototype.entry = function(header, buffer, callback) {
|
|
if (this._stream) throw new Error("already piping an entry");
|
|
if (this._finalized || this._destroyed) return;
|
|
if (typeof buffer === "function") {
|
|
callback = buffer;
|
|
buffer = null;
|
|
}
|
|
if (!callback) callback = noop;
|
|
var self2 = this;
|
|
if (!header.size || header.type === "symlink") header.size = 0;
|
|
if (!header.type) header.type = modeToType(header.mode);
|
|
if (!header.mode) header.mode = header.type === "directory" ? DMODE : FMODE;
|
|
if (!header.uid) header.uid = 0;
|
|
if (!header.gid) header.gid = 0;
|
|
if (!header.mtime) header.mtime = /* @__PURE__ */ new Date();
|
|
if (typeof buffer === "string") buffer = toBuffer(buffer);
|
|
if (Buffer.isBuffer(buffer)) {
|
|
header.size = buffer.length;
|
|
this._encode(header);
|
|
this.push(buffer);
|
|
overflow(self2, header.size);
|
|
process.nextTick(callback);
|
|
return new Void();
|
|
}
|
|
if (header.type === "symlink" && !header.linkname) {
|
|
var linkSink = new LinkSink();
|
|
eos(linkSink, function(err) {
|
|
if (err) {
|
|
self2.destroy();
|
|
return callback(err);
|
|
}
|
|
header.linkname = linkSink.linkname;
|
|
self2._encode(header);
|
|
callback();
|
|
});
|
|
return linkSink;
|
|
}
|
|
this._encode(header);
|
|
if (header.type !== "file" && header.type !== "contiguous-file") {
|
|
process.nextTick(callback);
|
|
return new Void();
|
|
}
|
|
var sink = new Sink(this);
|
|
this._stream = sink;
|
|
eos(sink, function(err) {
|
|
self2._stream = null;
|
|
if (err) {
|
|
self2.destroy();
|
|
return callback(err);
|
|
}
|
|
if (sink.written !== header.size) {
|
|
self2.destroy();
|
|
return callback(new Error("size mismatch"));
|
|
}
|
|
overflow(self2, header.size);
|
|
if (self2._finalizing) self2.finalize();
|
|
callback();
|
|
});
|
|
return sink;
|
|
};
|
|
Pack.prototype.finalize = function() {
|
|
if (this._stream) {
|
|
this._finalizing = true;
|
|
return;
|
|
}
|
|
if (this._finalized) return;
|
|
this._finalized = true;
|
|
this.push(END_OF_TAR);
|
|
this.push(null);
|
|
};
|
|
Pack.prototype.destroy = function(err) {
|
|
if (this._destroyed) return;
|
|
this._destroyed = true;
|
|
if (err) this.emit("error", err);
|
|
this.emit("close");
|
|
if (this._stream && this._stream.destroy) this._stream.destroy();
|
|
};
|
|
Pack.prototype._encode = function(header) {
|
|
if (!header.pax) {
|
|
var buf = headers.encode(header);
|
|
if (buf) {
|
|
this.push(buf);
|
|
return;
|
|
}
|
|
}
|
|
this._encodePax(header);
|
|
};
|
|
Pack.prototype._encodePax = function(header) {
|
|
var paxHeader = headers.encodePax({
|
|
name: header.name,
|
|
linkname: header.linkname,
|
|
pax: header.pax
|
|
});
|
|
var newHeader = {
|
|
name: "PaxHeader",
|
|
mode: header.mode,
|
|
uid: header.uid,
|
|
gid: header.gid,
|
|
size: paxHeader.length,
|
|
mtime: header.mtime,
|
|
type: "pax-header",
|
|
linkname: header.linkname && "PaxHeader",
|
|
uname: header.uname,
|
|
gname: header.gname,
|
|
devmajor: header.devmajor,
|
|
devminor: header.devminor
|
|
};
|
|
this.push(headers.encode(newHeader));
|
|
this.push(paxHeader);
|
|
overflow(this, paxHeader.length);
|
|
newHeader.size = header.size;
|
|
newHeader.type = header.type;
|
|
this.push(headers.encode(newHeader));
|
|
};
|
|
Pack.prototype._read = function(n) {
|
|
var drain = this._drain;
|
|
this._drain = noop;
|
|
drain();
|
|
};
|
|
module.exports = Pack;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/tar-stream/index.js
|
|
var require_tar_stream = __commonJS({
|
|
"../../node_modules/tar-stream/index.js"(exports) {
|
|
exports.extract = require_extract();
|
|
exports.pack = require_pack();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress-tar/index.js
|
|
var require_decompress_tar = __commonJS({
|
|
"../../node_modules/decompress-tar/index.js"(exports, module) {
|
|
"use strict";
|
|
var fileType = require_file_type();
|
|
var isStream = require_is_stream();
|
|
var tarStream = require_tar_stream();
|
|
module.exports = () => (input) => {
|
|
if (!Buffer.isBuffer(input) && !isStream(input)) {
|
|
return Promise.reject(new TypeError(`Expected a Buffer or Stream, got ${typeof input}`));
|
|
}
|
|
if (Buffer.isBuffer(input) && (!fileType(input) || fileType(input).ext !== "tar")) {
|
|
return Promise.resolve([]);
|
|
}
|
|
const extract = tarStream.extract();
|
|
const files = [];
|
|
extract.on("entry", (header, stream, cb) => {
|
|
const chunk = [];
|
|
stream.on("data", (data) => chunk.push(data));
|
|
stream.on("end", () => {
|
|
const file = {
|
|
data: Buffer.concat(chunk),
|
|
mode: header.mode,
|
|
mtime: header.mtime,
|
|
path: header.name,
|
|
type: header.type
|
|
};
|
|
if (header.type === "symlink" || header.type === "link") {
|
|
file.linkname = header.linkname;
|
|
}
|
|
files.push(file);
|
|
cb();
|
|
});
|
|
});
|
|
const promise = new Promise((resolve, reject) => {
|
|
if (!Buffer.isBuffer(input)) {
|
|
input.on("error", reject);
|
|
}
|
|
extract.on("finish", () => resolve(files));
|
|
extract.on("error", reject);
|
|
});
|
|
extract.then = promise.then.bind(promise);
|
|
extract.catch = promise.catch.bind(promise);
|
|
if (Buffer.isBuffer(input)) {
|
|
extract.end(input);
|
|
} else {
|
|
input.pipe(extract);
|
|
}
|
|
return extract;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress-tarbz2/node_modules/file-type/index.js
|
|
var require_file_type2 = __commonJS({
|
|
"../../node_modules/decompress-tarbz2/node_modules/file-type/index.js"(exports, module) {
|
|
"use strict";
|
|
var toBytes = (s) => Array.from(s).map((c) => c.charCodeAt(0));
|
|
var xpiZipFilename = toBytes("META-INF/mozilla.rsa");
|
|
var oxmlContentTypes = toBytes("[Content_Types].xml");
|
|
var oxmlRels = toBytes("_rels/.rels");
|
|
module.exports = (input) => {
|
|
const buf = new Uint8Array(input);
|
|
if (!(buf && buf.length > 1)) {
|
|
return null;
|
|
}
|
|
const check = (header, opts) => {
|
|
opts = Object.assign({
|
|
offset: 0
|
|
}, opts);
|
|
for (let i = 0; i < header.length; i++) {
|
|
if (opts.mask) {
|
|
if (header[i] !== (opts.mask[i] & buf[i + opts.offset])) {
|
|
return false;
|
|
}
|
|
} else if (header[i] !== buf[i + opts.offset]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
if (check([255, 216, 255])) {
|
|
return {
|
|
ext: "jpg",
|
|
mime: "image/jpeg"
|
|
};
|
|
}
|
|
if (check([137, 80, 78, 71, 13, 10, 26, 10])) {
|
|
return {
|
|
ext: "png",
|
|
mime: "image/png"
|
|
};
|
|
}
|
|
if (check([71, 73, 70])) {
|
|
return {
|
|
ext: "gif",
|
|
mime: "image/gif"
|
|
};
|
|
}
|
|
if (check([87, 69, 66, 80], { offset: 8 })) {
|
|
return {
|
|
ext: "webp",
|
|
mime: "image/webp"
|
|
};
|
|
}
|
|
if (check([70, 76, 73, 70])) {
|
|
return {
|
|
ext: "flif",
|
|
mime: "image/flif"
|
|
};
|
|
}
|
|
if ((check([73, 73, 42, 0]) || check([77, 77, 0, 42])) && check([67, 82], { offset: 8 })) {
|
|
return {
|
|
ext: "cr2",
|
|
mime: "image/x-canon-cr2"
|
|
};
|
|
}
|
|
if (check([73, 73, 42, 0]) || check([77, 77, 0, 42])) {
|
|
return {
|
|
ext: "tif",
|
|
mime: "image/tiff"
|
|
};
|
|
}
|
|
if (check([66, 77])) {
|
|
return {
|
|
ext: "bmp",
|
|
mime: "image/bmp"
|
|
};
|
|
}
|
|
if (check([73, 73, 188])) {
|
|
return {
|
|
ext: "jxr",
|
|
mime: "image/vnd.ms-photo"
|
|
};
|
|
}
|
|
if (check([56, 66, 80, 83])) {
|
|
return {
|
|
ext: "psd",
|
|
mime: "image/vnd.adobe.photoshop"
|
|
};
|
|
}
|
|
if (check([80, 75, 3, 4])) {
|
|
if (check([109, 105, 109, 101, 116, 121, 112, 101, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 101, 112, 117, 98, 43, 122, 105, 112], { offset: 30 })) {
|
|
return {
|
|
ext: "epub",
|
|
mime: "application/epub+zip"
|
|
};
|
|
}
|
|
if (check(xpiZipFilename, { offset: 30 })) {
|
|
return {
|
|
ext: "xpi",
|
|
mime: "application/x-xpinstall"
|
|
};
|
|
}
|
|
if (check(oxmlContentTypes, { offset: 30 }) || check(oxmlRels, { offset: 30 })) {
|
|
const sliced = buf.subarray(4, 4 + 2e3);
|
|
const nextZipHeaderIndex = (arr) => arr.findIndex((el, i, arr2) => arr2[i] === 80 && arr2[i + 1] === 75 && arr2[i + 2] === 3 && arr2[i + 3] === 4);
|
|
const header2Pos = nextZipHeaderIndex(sliced);
|
|
if (header2Pos !== -1) {
|
|
const slicedAgain = buf.subarray(header2Pos + 8, header2Pos + 8 + 1e3);
|
|
const header3Pos = nextZipHeaderIndex(slicedAgain);
|
|
if (header3Pos !== -1) {
|
|
const offset = 8 + header2Pos + header3Pos + 30;
|
|
if (check(toBytes("word/"), { offset })) {
|
|
return {
|
|
ext: "docx",
|
|
mime: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
};
|
|
}
|
|
if (check(toBytes("ppt/"), { offset })) {
|
|
return {
|
|
ext: "pptx",
|
|
mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
};
|
|
}
|
|
if (check(toBytes("xl/"), { offset })) {
|
|
return {
|
|
ext: "xlsx",
|
|
mime: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (check([80, 75]) && (buf[2] === 3 || buf[2] === 5 || buf[2] === 7) && (buf[3] === 4 || buf[3] === 6 || buf[3] === 8)) {
|
|
return {
|
|
ext: "zip",
|
|
mime: "application/zip"
|
|
};
|
|
}
|
|
if (check([117, 115, 116, 97, 114], { offset: 257 })) {
|
|
return {
|
|
ext: "tar",
|
|
mime: "application/x-tar"
|
|
};
|
|
}
|
|
if (check([82, 97, 114, 33, 26, 7]) && (buf[6] === 0 || buf[6] === 1)) {
|
|
return {
|
|
ext: "rar",
|
|
mime: "application/x-rar-compressed"
|
|
};
|
|
}
|
|
if (check([31, 139, 8])) {
|
|
return {
|
|
ext: "gz",
|
|
mime: "application/gzip"
|
|
};
|
|
}
|
|
if (check([66, 90, 104])) {
|
|
return {
|
|
ext: "bz2",
|
|
mime: "application/x-bzip2"
|
|
};
|
|
}
|
|
if (check([55, 122, 188, 175, 39, 28])) {
|
|
return {
|
|
ext: "7z",
|
|
mime: "application/x-7z-compressed"
|
|
};
|
|
}
|
|
if (check([120, 1])) {
|
|
return {
|
|
ext: "dmg",
|
|
mime: "application/x-apple-diskimage"
|
|
};
|
|
}
|
|
if (check([51, 103, 112, 53]) || // 3gp5
|
|
check([0, 0, 0]) && check([102, 116, 121, 112], { offset: 4 }) && (check([109, 112, 52, 49], { offset: 8 }) || // MP41
|
|
check([109, 112, 52, 50], { offset: 8 }) || // MP42
|
|
check([105, 115, 111, 109], { offset: 8 }) || // ISOM
|
|
check([105, 115, 111, 50], { offset: 8 }) || // ISO2
|
|
check([109, 109, 112, 52], { offset: 8 }) || // MMP4
|
|
check([77, 52, 86], { offset: 8 }) || // M4V
|
|
check([100, 97, 115, 104], { offset: 8 }))) {
|
|
return {
|
|
ext: "mp4",
|
|
mime: "video/mp4"
|
|
};
|
|
}
|
|
if (check([77, 84, 104, 100])) {
|
|
return {
|
|
ext: "mid",
|
|
mime: "audio/midi"
|
|
};
|
|
}
|
|
if (check([26, 69, 223, 163])) {
|
|
const sliced = buf.subarray(4, 4 + 4096);
|
|
const idPos = sliced.findIndex((el, i, arr) => arr[i] === 66 && arr[i + 1] === 130);
|
|
if (idPos !== -1) {
|
|
const docTypePos = idPos + 3;
|
|
const findDocType = (type) => Array.from(type).every((c, i) => sliced[docTypePos + i] === c.charCodeAt(0));
|
|
if (findDocType("matroska")) {
|
|
return {
|
|
ext: "mkv",
|
|
mime: "video/x-matroska"
|
|
};
|
|
}
|
|
if (findDocType("webm")) {
|
|
return {
|
|
ext: "webm",
|
|
mime: "video/webm"
|
|
};
|
|
}
|
|
}
|
|
}
|
|
if (check([0, 0, 0, 20, 102, 116, 121, 112, 113, 116, 32, 32]) || check([102, 114, 101, 101], { offset: 4 }) || check([102, 116, 121, 112, 113, 116, 32, 32], { offset: 4 }) || check([109, 100, 97, 116], { offset: 4 }) || // MJPEG
|
|
check([119, 105, 100, 101], { offset: 4 })) {
|
|
return {
|
|
ext: "mov",
|
|
mime: "video/quicktime"
|
|
};
|
|
}
|
|
if (check([82, 73, 70, 70]) && check([65, 86, 73], { offset: 8 })) {
|
|
return {
|
|
ext: "avi",
|
|
mime: "video/x-msvideo"
|
|
};
|
|
}
|
|
if (check([48, 38, 178, 117, 142, 102, 207, 17, 166, 217])) {
|
|
return {
|
|
ext: "wmv",
|
|
mime: "video/x-ms-wmv"
|
|
};
|
|
}
|
|
if (check([0, 0, 1, 186])) {
|
|
return {
|
|
ext: "mpg",
|
|
mime: "video/mpeg"
|
|
};
|
|
}
|
|
for (let start = 0; start < 2 && start < buf.length - 16; start++) {
|
|
if (check([73, 68, 51], { offset: start }) || // ID3 header
|
|
check([255, 226], { offset: start, mask: [255, 226] })) {
|
|
return {
|
|
ext: "mp3",
|
|
mime: "audio/mpeg"
|
|
};
|
|
}
|
|
}
|
|
if (check([102, 116, 121, 112, 77, 52, 65], { offset: 4 }) || check([77, 52, 65, 32])) {
|
|
return {
|
|
ext: "m4a",
|
|
mime: "audio/m4a"
|
|
};
|
|
}
|
|
if (check([79, 112, 117, 115, 72, 101, 97, 100], { offset: 28 })) {
|
|
return {
|
|
ext: "opus",
|
|
mime: "audio/opus"
|
|
};
|
|
}
|
|
if (check([79, 103, 103, 83])) {
|
|
return {
|
|
ext: "ogg",
|
|
mime: "audio/ogg"
|
|
};
|
|
}
|
|
if (check([102, 76, 97, 67])) {
|
|
return {
|
|
ext: "flac",
|
|
mime: "audio/x-flac"
|
|
};
|
|
}
|
|
if (check([82, 73, 70, 70]) && check([87, 65, 86, 69], { offset: 8 })) {
|
|
return {
|
|
ext: "wav",
|
|
mime: "audio/x-wav"
|
|
};
|
|
}
|
|
if (check([35, 33, 65, 77, 82, 10])) {
|
|
return {
|
|
ext: "amr",
|
|
mime: "audio/amr"
|
|
};
|
|
}
|
|
if (check([37, 80, 68, 70])) {
|
|
return {
|
|
ext: "pdf",
|
|
mime: "application/pdf"
|
|
};
|
|
}
|
|
if (check([77, 90])) {
|
|
return {
|
|
ext: "exe",
|
|
mime: "application/x-msdownload"
|
|
};
|
|
}
|
|
if ((buf[0] === 67 || buf[0] === 70) && check([87, 83], { offset: 1 })) {
|
|
return {
|
|
ext: "swf",
|
|
mime: "application/x-shockwave-flash"
|
|
};
|
|
}
|
|
if (check([123, 92, 114, 116, 102])) {
|
|
return {
|
|
ext: "rtf",
|
|
mime: "application/rtf"
|
|
};
|
|
}
|
|
if (check([0, 97, 115, 109])) {
|
|
return {
|
|
ext: "wasm",
|
|
mime: "application/wasm"
|
|
};
|
|
}
|
|
if (check([119, 79, 70, 70]) && (check([0, 1, 0, 0], { offset: 4 }) || check([79, 84, 84, 79], { offset: 4 }))) {
|
|
return {
|
|
ext: "woff",
|
|
mime: "font/woff"
|
|
};
|
|
}
|
|
if (check([119, 79, 70, 50]) && (check([0, 1, 0, 0], { offset: 4 }) || check([79, 84, 84, 79], { offset: 4 }))) {
|
|
return {
|
|
ext: "woff2",
|
|
mime: "font/woff2"
|
|
};
|
|
}
|
|
if (check([76, 80], { offset: 34 }) && (check([0, 0, 1], { offset: 8 }) || check([1, 0, 2], { offset: 8 }) || check([2, 0, 2], { offset: 8 }))) {
|
|
return {
|
|
ext: "eot",
|
|
mime: "application/octet-stream"
|
|
};
|
|
}
|
|
if (check([0, 1, 0, 0, 0])) {
|
|
return {
|
|
ext: "ttf",
|
|
mime: "font/ttf"
|
|
};
|
|
}
|
|
if (check([79, 84, 84, 79, 0])) {
|
|
return {
|
|
ext: "otf",
|
|
mime: "font/otf"
|
|
};
|
|
}
|
|
if (check([0, 0, 1, 0])) {
|
|
return {
|
|
ext: "ico",
|
|
mime: "image/x-icon"
|
|
};
|
|
}
|
|
if (check([70, 76, 86, 1])) {
|
|
return {
|
|
ext: "flv",
|
|
mime: "video/x-flv"
|
|
};
|
|
}
|
|
if (check([37, 33])) {
|
|
return {
|
|
ext: "ps",
|
|
mime: "application/postscript"
|
|
};
|
|
}
|
|
if (check([253, 55, 122, 88, 90, 0])) {
|
|
return {
|
|
ext: "xz",
|
|
mime: "application/x-xz"
|
|
};
|
|
}
|
|
if (check([83, 81, 76, 105])) {
|
|
return {
|
|
ext: "sqlite",
|
|
mime: "application/x-sqlite3"
|
|
};
|
|
}
|
|
if (check([78, 69, 83, 26])) {
|
|
return {
|
|
ext: "nes",
|
|
mime: "application/x-nintendo-nes-rom"
|
|
};
|
|
}
|
|
if (check([67, 114, 50, 52])) {
|
|
return {
|
|
ext: "crx",
|
|
mime: "application/x-google-chrome-extension"
|
|
};
|
|
}
|
|
if (check([77, 83, 67, 70]) || check([73, 83, 99, 40])) {
|
|
return {
|
|
ext: "cab",
|
|
mime: "application/vnd.ms-cab-compressed"
|
|
};
|
|
}
|
|
if (check([33, 60, 97, 114, 99, 104, 62, 10, 100, 101, 98, 105, 97, 110, 45, 98, 105, 110, 97, 114, 121])) {
|
|
return {
|
|
ext: "deb",
|
|
mime: "application/x-deb"
|
|
};
|
|
}
|
|
if (check([33, 60, 97, 114, 99, 104, 62])) {
|
|
return {
|
|
ext: "ar",
|
|
mime: "application/x-unix-archive"
|
|
};
|
|
}
|
|
if (check([237, 171, 238, 219])) {
|
|
return {
|
|
ext: "rpm",
|
|
mime: "application/x-rpm"
|
|
};
|
|
}
|
|
if (check([31, 160]) || check([31, 157])) {
|
|
return {
|
|
ext: "Z",
|
|
mime: "application/x-compress"
|
|
};
|
|
}
|
|
if (check([76, 90, 73, 80])) {
|
|
return {
|
|
ext: "lz",
|
|
mime: "application/x-lzip"
|
|
};
|
|
}
|
|
if (check([208, 207, 17, 224, 161, 177, 26, 225])) {
|
|
return {
|
|
ext: "msi",
|
|
mime: "application/x-msi"
|
|
};
|
|
}
|
|
if (check([6, 14, 43, 52, 2, 5, 1, 1, 13, 1, 2, 1, 1, 2])) {
|
|
return {
|
|
ext: "mxf",
|
|
mime: "application/mxf"
|
|
};
|
|
}
|
|
if (check([71], { offset: 4 }) && (check([71], { offset: 192 }) || check([71], { offset: 196 }))) {
|
|
return {
|
|
ext: "mts",
|
|
mime: "video/mp2t"
|
|
};
|
|
}
|
|
if (check([66, 76, 69, 78, 68, 69, 82])) {
|
|
return {
|
|
ext: "blend",
|
|
mime: "application/x-blender"
|
|
};
|
|
}
|
|
if (check([66, 80, 71, 251])) {
|
|
return {
|
|
ext: "bpg",
|
|
mime: "image/bpg"
|
|
};
|
|
}
|
|
return null;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/seek-bzip/lib/bitreader.js
|
|
var require_bitreader = __commonJS({
|
|
"../../node_modules/seek-bzip/lib/bitreader.js"(exports, module) {
|
|
var BITMASK = [0, 1, 3, 7, 15, 31, 63, 127, 255];
|
|
var BitReader = function(stream) {
|
|
this.stream = stream;
|
|
this.bitOffset = 0;
|
|
this.curByte = 0;
|
|
this.hasByte = false;
|
|
};
|
|
BitReader.prototype._ensureByte = function() {
|
|
if (!this.hasByte) {
|
|
this.curByte = this.stream.readByte();
|
|
this.hasByte = true;
|
|
}
|
|
};
|
|
BitReader.prototype.read = function(bits) {
|
|
var result = 0;
|
|
while (bits > 0) {
|
|
this._ensureByte();
|
|
var remaining = 8 - this.bitOffset;
|
|
if (bits >= remaining) {
|
|
result <<= remaining;
|
|
result |= BITMASK[remaining] & this.curByte;
|
|
this.hasByte = false;
|
|
this.bitOffset = 0;
|
|
bits -= remaining;
|
|
} else {
|
|
result <<= bits;
|
|
var shift = remaining - bits;
|
|
result |= (this.curByte & BITMASK[bits] << shift) >> shift;
|
|
this.bitOffset += bits;
|
|
bits = 0;
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
BitReader.prototype.seek = function(pos) {
|
|
var n_bit = pos % 8;
|
|
var n_byte = (pos - n_bit) / 8;
|
|
this.bitOffset = n_bit;
|
|
this.stream.seek(n_byte);
|
|
this.hasByte = false;
|
|
};
|
|
BitReader.prototype.pi = function() {
|
|
var buf = new Buffer(6), i;
|
|
for (i = 0; i < buf.length; i++) {
|
|
buf[i] = this.read(8);
|
|
}
|
|
return buf.toString("hex");
|
|
};
|
|
module.exports = BitReader;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/seek-bzip/lib/stream.js
|
|
var require_stream3 = __commonJS({
|
|
"../../node_modules/seek-bzip/lib/stream.js"(exports, module) {
|
|
var Stream = function() {
|
|
};
|
|
Stream.prototype.readByte = function() {
|
|
throw new Error("abstract method readByte() not implemented");
|
|
};
|
|
Stream.prototype.read = function(buffer, bufOffset, length) {
|
|
var bytesRead = 0;
|
|
while (bytesRead < length) {
|
|
var c = this.readByte();
|
|
if (c < 0) {
|
|
return bytesRead === 0 ? -1 : bytesRead;
|
|
}
|
|
buffer[bufOffset++] = c;
|
|
bytesRead++;
|
|
}
|
|
return bytesRead;
|
|
};
|
|
Stream.prototype.seek = function(new_pos) {
|
|
throw new Error("abstract method seek() not implemented");
|
|
};
|
|
Stream.prototype.writeByte = function(_byte) {
|
|
throw new Error("abstract method readByte() not implemented");
|
|
};
|
|
Stream.prototype.write = function(buffer, bufOffset, length) {
|
|
var i;
|
|
for (i = 0; i < length; i++) {
|
|
this.writeByte(buffer[bufOffset++]);
|
|
}
|
|
return length;
|
|
};
|
|
Stream.prototype.flush = function() {
|
|
};
|
|
module.exports = Stream;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/seek-bzip/lib/crc32.js
|
|
var require_crc32 = __commonJS({
|
|
"../../node_modules/seek-bzip/lib/crc32.js"(exports, module) {
|
|
module.exports = (function() {
|
|
var crc32Lookup = new Uint32Array([
|
|
0,
|
|
79764919,
|
|
159529838,
|
|
222504665,
|
|
319059676,
|
|
398814059,
|
|
445009330,
|
|
507990021,
|
|
638119352,
|
|
583659535,
|
|
797628118,
|
|
726387553,
|
|
890018660,
|
|
835552979,
|
|
1015980042,
|
|
944750013,
|
|
1276238704,
|
|
1221641927,
|
|
1167319070,
|
|
1095957929,
|
|
1595256236,
|
|
1540665371,
|
|
1452775106,
|
|
1381403509,
|
|
1780037320,
|
|
1859660671,
|
|
1671105958,
|
|
1733955601,
|
|
2031960084,
|
|
2111593891,
|
|
1889500026,
|
|
1952343757,
|
|
2552477408,
|
|
2632100695,
|
|
2443283854,
|
|
2506133561,
|
|
2334638140,
|
|
2414271883,
|
|
2191915858,
|
|
2254759653,
|
|
3190512472,
|
|
3135915759,
|
|
3081330742,
|
|
3009969537,
|
|
2905550212,
|
|
2850959411,
|
|
2762807018,
|
|
2691435357,
|
|
3560074640,
|
|
3505614887,
|
|
3719321342,
|
|
3648080713,
|
|
3342211916,
|
|
3287746299,
|
|
3467911202,
|
|
3396681109,
|
|
4063920168,
|
|
4143685023,
|
|
4223187782,
|
|
4286162673,
|
|
3779000052,
|
|
3858754371,
|
|
3904687514,
|
|
3967668269,
|
|
881225847,
|
|
809987520,
|
|
1023691545,
|
|
969234094,
|
|
662832811,
|
|
591600412,
|
|
771767749,
|
|
717299826,
|
|
311336399,
|
|
374308984,
|
|
453813921,
|
|
533576470,
|
|
25881363,
|
|
88864420,
|
|
134795389,
|
|
214552010,
|
|
2023205639,
|
|
2086057648,
|
|
1897238633,
|
|
1976864222,
|
|
1804852699,
|
|
1867694188,
|
|
1645340341,
|
|
1724971778,
|
|
1587496639,
|
|
1516133128,
|
|
1461550545,
|
|
1406951526,
|
|
1302016099,
|
|
1230646740,
|
|
1142491917,
|
|
1087903418,
|
|
2896545431,
|
|
2825181984,
|
|
2770861561,
|
|
2716262478,
|
|
3215044683,
|
|
3143675388,
|
|
3055782693,
|
|
3001194130,
|
|
2326604591,
|
|
2389456536,
|
|
2200899649,
|
|
2280525302,
|
|
2578013683,
|
|
2640855108,
|
|
2418763421,
|
|
2498394922,
|
|
3769900519,
|
|
3832873040,
|
|
3912640137,
|
|
3992402750,
|
|
4088425275,
|
|
4151408268,
|
|
4197601365,
|
|
4277358050,
|
|
3334271071,
|
|
3263032808,
|
|
3476998961,
|
|
3422541446,
|
|
3585640067,
|
|
3514407732,
|
|
3694837229,
|
|
3640369242,
|
|
1762451694,
|
|
1842216281,
|
|
1619975040,
|
|
1682949687,
|
|
2047383090,
|
|
2127137669,
|
|
1938468188,
|
|
2001449195,
|
|
1325665622,
|
|
1271206113,
|
|
1183200824,
|
|
1111960463,
|
|
1543535498,
|
|
1489069629,
|
|
1434599652,
|
|
1363369299,
|
|
622672798,
|
|
568075817,
|
|
748617968,
|
|
677256519,
|
|
907627842,
|
|
853037301,
|
|
1067152940,
|
|
995781531,
|
|
51762726,
|
|
131386257,
|
|
177728840,
|
|
240578815,
|
|
269590778,
|
|
349224269,
|
|
429104020,
|
|
491947555,
|
|
4046411278,
|
|
4126034873,
|
|
4172115296,
|
|
4234965207,
|
|
3794477266,
|
|
3874110821,
|
|
3953728444,
|
|
4016571915,
|
|
3609705398,
|
|
3555108353,
|
|
3735388376,
|
|
3664026991,
|
|
3290680682,
|
|
3236090077,
|
|
3449943556,
|
|
3378572211,
|
|
3174993278,
|
|
3120533705,
|
|
3032266256,
|
|
2961025959,
|
|
2923101090,
|
|
2868635157,
|
|
2813903052,
|
|
2742672763,
|
|
2604032198,
|
|
2683796849,
|
|
2461293480,
|
|
2524268063,
|
|
2284983834,
|
|
2364738477,
|
|
2175806836,
|
|
2238787779,
|
|
1569362073,
|
|
1498123566,
|
|
1409854455,
|
|
1355396672,
|
|
1317987909,
|
|
1246755826,
|
|
1192025387,
|
|
1137557660,
|
|
2072149281,
|
|
2135122070,
|
|
1912620623,
|
|
1992383480,
|
|
1753615357,
|
|
1816598090,
|
|
1627664531,
|
|
1707420964,
|
|
295390185,
|
|
358241886,
|
|
404320391,
|
|
483945776,
|
|
43990325,
|
|
106832002,
|
|
186451547,
|
|
266083308,
|
|
932423249,
|
|
861060070,
|
|
1041341759,
|
|
986742920,
|
|
613929101,
|
|
542559546,
|
|
756411363,
|
|
701822548,
|
|
3316196985,
|
|
3244833742,
|
|
3425377559,
|
|
3370778784,
|
|
3601682597,
|
|
3530312978,
|
|
3744426955,
|
|
3689838204,
|
|
3819031489,
|
|
3881883254,
|
|
3928223919,
|
|
4007849240,
|
|
4037393693,
|
|
4100235434,
|
|
4180117107,
|
|
4259748804,
|
|
2310601993,
|
|
2373574846,
|
|
2151335527,
|
|
2231098320,
|
|
2596047829,
|
|
2659030626,
|
|
2470359227,
|
|
2550115596,
|
|
2947551409,
|
|
2876312838,
|
|
2788305887,
|
|
2733848168,
|
|
3165939309,
|
|
3094707162,
|
|
3040238851,
|
|
2985771188
|
|
]);
|
|
var CRC32 = function() {
|
|
var crc = 4294967295;
|
|
this.getCRC = function() {
|
|
return ~crc >>> 0;
|
|
};
|
|
this.updateCRC = function(value) {
|
|
crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 255];
|
|
};
|
|
this.updateCRCRun = function(value, count) {
|
|
while (count-- > 0) {
|
|
crc = crc << 8 ^ crc32Lookup[(crc >>> 24 ^ value) & 255];
|
|
}
|
|
};
|
|
};
|
|
return CRC32;
|
|
})();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/seek-bzip/package.json
|
|
var require_package = __commonJS({
|
|
"../../node_modules/seek-bzip/package.json"(exports, module) {
|
|
module.exports = {
|
|
name: "seek-bzip",
|
|
version: "1.0.6",
|
|
contributors: [
|
|
"C. Scott Ananian (http://cscott.net)",
|
|
"Eli Skeggs",
|
|
"Kevin Kwok",
|
|
"Rob Landley (http://landley.net)"
|
|
],
|
|
description: "a pure-JavaScript Node.JS module for random-access decoding bzip2 data",
|
|
main: "./lib/index.js",
|
|
repository: {
|
|
type: "git",
|
|
url: "https://github.com/cscott/seek-bzip.git"
|
|
},
|
|
license: "MIT",
|
|
bin: {
|
|
"seek-bunzip": "./bin/seek-bunzip",
|
|
"seek-table": "./bin/seek-bzip-table"
|
|
},
|
|
directories: {
|
|
test: "test"
|
|
},
|
|
dependencies: {
|
|
commander: "^2.8.1"
|
|
},
|
|
devDependencies: {
|
|
fibers: "~1.0.6",
|
|
mocha: "~2.2.5"
|
|
},
|
|
scripts: {
|
|
test: "mocha"
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/seek-bzip/lib/index.js
|
|
var require_lib = __commonJS({
|
|
"../../node_modules/seek-bzip/lib/index.js"(exports, module) {
|
|
var BitReader = require_bitreader();
|
|
var Stream = require_stream3();
|
|
var CRC32 = require_crc32();
|
|
var pjson = require_package();
|
|
var MAX_HUFCODE_BITS = 20;
|
|
var MAX_SYMBOLS = 258;
|
|
var SYMBOL_RUNA = 0;
|
|
var SYMBOL_RUNB = 1;
|
|
var MIN_GROUPS = 2;
|
|
var MAX_GROUPS = 6;
|
|
var GROUP_SIZE = 50;
|
|
var WHOLEPI = "314159265359";
|
|
var SQRTPI = "177245385090";
|
|
var mtf = function(array, index) {
|
|
var src = array[index], i;
|
|
for (i = index; i > 0; i--) {
|
|
array[i] = array[i - 1];
|
|
}
|
|
array[0] = src;
|
|
return src;
|
|
};
|
|
var Err = {
|
|
OK: 0,
|
|
LAST_BLOCK: -1,
|
|
NOT_BZIP_DATA: -2,
|
|
UNEXPECTED_INPUT_EOF: -3,
|
|
UNEXPECTED_OUTPUT_EOF: -4,
|
|
DATA_ERROR: -5,
|
|
OUT_OF_MEMORY: -6,
|
|
OBSOLETE_INPUT: -7,
|
|
END_OF_BLOCK: -8
|
|
};
|
|
var ErrorMessages = {};
|
|
ErrorMessages[Err.LAST_BLOCK] = "Bad file checksum";
|
|
ErrorMessages[Err.NOT_BZIP_DATA] = "Not bzip data";
|
|
ErrorMessages[Err.UNEXPECTED_INPUT_EOF] = "Unexpected input EOF";
|
|
ErrorMessages[Err.UNEXPECTED_OUTPUT_EOF] = "Unexpected output EOF";
|
|
ErrorMessages[Err.DATA_ERROR] = "Data error";
|
|
ErrorMessages[Err.OUT_OF_MEMORY] = "Out of memory";
|
|
ErrorMessages[Err.OBSOLETE_INPUT] = "Obsolete (pre 0.9.5) bzip format not supported.";
|
|
var _throw = function(status, optDetail) {
|
|
var msg = ErrorMessages[status] || "unknown error";
|
|
if (optDetail) {
|
|
msg += ": " + optDetail;
|
|
}
|
|
var e = new TypeError(msg);
|
|
e.errorCode = status;
|
|
throw e;
|
|
};
|
|
var Bunzip = function(inputStream, outputStream) {
|
|
this.writePos = this.writeCurrent = this.writeCount = 0;
|
|
this._start_bunzip(inputStream, outputStream);
|
|
};
|
|
Bunzip.prototype._init_block = function() {
|
|
var moreBlocks = this._get_next_block();
|
|
if (!moreBlocks) {
|
|
this.writeCount = -1;
|
|
return false;
|
|
}
|
|
this.blockCRC = new CRC32();
|
|
return true;
|
|
};
|
|
Bunzip.prototype._start_bunzip = function(inputStream, outputStream) {
|
|
var buf = new Buffer(4);
|
|
if (inputStream.read(buf, 0, 4) !== 4 || String.fromCharCode(buf[0], buf[1], buf[2]) !== "BZh")
|
|
_throw(Err.NOT_BZIP_DATA, "bad magic");
|
|
var level = buf[3] - 48;
|
|
if (level < 1 || level > 9)
|
|
_throw(Err.NOT_BZIP_DATA, "level out of range");
|
|
this.reader = new BitReader(inputStream);
|
|
this.dbufSize = 1e5 * level;
|
|
this.nextoutput = 0;
|
|
this.outputStream = outputStream;
|
|
this.streamCRC = 0;
|
|
};
|
|
Bunzip.prototype._get_next_block = function() {
|
|
var i, j, k;
|
|
var reader = this.reader;
|
|
var h = reader.pi();
|
|
if (h === SQRTPI) {
|
|
return false;
|
|
}
|
|
if (h !== WHOLEPI)
|
|
_throw(Err.NOT_BZIP_DATA);
|
|
this.targetBlockCRC = reader.read(32) >>> 0;
|
|
this.streamCRC = (this.targetBlockCRC ^ (this.streamCRC << 1 | this.streamCRC >>> 31)) >>> 0;
|
|
if (reader.read(1))
|
|
_throw(Err.OBSOLETE_INPUT);
|
|
var origPointer = reader.read(24);
|
|
if (origPointer > this.dbufSize)
|
|
_throw(Err.DATA_ERROR, "initial position out of bounds");
|
|
var t = reader.read(16);
|
|
var symToByte = new Buffer(256), symTotal = 0;
|
|
for (i = 0; i < 16; i++) {
|
|
if (t & 1 << 15 - i) {
|
|
var o = i * 16;
|
|
k = reader.read(16);
|
|
for (j = 0; j < 16; j++)
|
|
if (k & 1 << 15 - j)
|
|
symToByte[symTotal++] = o + j;
|
|
}
|
|
}
|
|
var groupCount = reader.read(3);
|
|
if (groupCount < MIN_GROUPS || groupCount > MAX_GROUPS)
|
|
_throw(Err.DATA_ERROR);
|
|
var nSelectors = reader.read(15);
|
|
if (nSelectors === 0)
|
|
_throw(Err.DATA_ERROR);
|
|
var mtfSymbol = new Buffer(256);
|
|
for (i = 0; i < groupCount; i++)
|
|
mtfSymbol[i] = i;
|
|
var selectors = new Buffer(nSelectors);
|
|
for (i = 0; i < nSelectors; i++) {
|
|
for (j = 0; reader.read(1); j++)
|
|
if (j >= groupCount) _throw(Err.DATA_ERROR);
|
|
selectors[i] = mtf(mtfSymbol, j);
|
|
}
|
|
var symCount = symTotal + 2;
|
|
var groups = [], hufGroup;
|
|
for (j = 0; j < groupCount; j++) {
|
|
var length = new Buffer(symCount), temp = new Uint16Array(MAX_HUFCODE_BITS + 1);
|
|
t = reader.read(5);
|
|
for (i = 0; i < symCount; i++) {
|
|
for (; ; ) {
|
|
if (t < 1 || t > MAX_HUFCODE_BITS) _throw(Err.DATA_ERROR);
|
|
if (!reader.read(1))
|
|
break;
|
|
if (!reader.read(1))
|
|
t++;
|
|
else
|
|
t--;
|
|
}
|
|
length[i] = t;
|
|
}
|
|
var minLen, maxLen;
|
|
minLen = maxLen = length[0];
|
|
for (i = 1; i < symCount; i++) {
|
|
if (length[i] > maxLen)
|
|
maxLen = length[i];
|
|
else if (length[i] < minLen)
|
|
minLen = length[i];
|
|
}
|
|
hufGroup = {};
|
|
groups.push(hufGroup);
|
|
hufGroup.permute = new Uint16Array(MAX_SYMBOLS);
|
|
hufGroup.limit = new Uint32Array(MAX_HUFCODE_BITS + 2);
|
|
hufGroup.base = new Uint32Array(MAX_HUFCODE_BITS + 1);
|
|
hufGroup.minLen = minLen;
|
|
hufGroup.maxLen = maxLen;
|
|
var pp = 0;
|
|
for (i = minLen; i <= maxLen; i++) {
|
|
temp[i] = hufGroup.limit[i] = 0;
|
|
for (t = 0; t < symCount; t++)
|
|
if (length[t] === i)
|
|
hufGroup.permute[pp++] = t;
|
|
}
|
|
for (i = 0; i < symCount; i++)
|
|
temp[length[i]]++;
|
|
pp = t = 0;
|
|
for (i = minLen; i < maxLen; i++) {
|
|
pp += temp[i];
|
|
hufGroup.limit[i] = pp - 1;
|
|
pp <<= 1;
|
|
t += temp[i];
|
|
hufGroup.base[i + 1] = pp - t;
|
|
}
|
|
hufGroup.limit[maxLen + 1] = Number.MAX_VALUE;
|
|
hufGroup.limit[maxLen] = pp + temp[maxLen] - 1;
|
|
hufGroup.base[minLen] = 0;
|
|
}
|
|
var byteCount = new Uint32Array(256);
|
|
for (i = 0; i < 256; i++)
|
|
mtfSymbol[i] = i;
|
|
var runPos = 0, dbufCount = 0, selector = 0, uc;
|
|
var dbuf = this.dbuf = new Uint32Array(this.dbufSize);
|
|
symCount = 0;
|
|
for (; ; ) {
|
|
if (!symCount--) {
|
|
symCount = GROUP_SIZE - 1;
|
|
if (selector >= nSelectors) {
|
|
_throw(Err.DATA_ERROR);
|
|
}
|
|
hufGroup = groups[selectors[selector++]];
|
|
}
|
|
i = hufGroup.minLen;
|
|
j = reader.read(i);
|
|
for (; ; i++) {
|
|
if (i > hufGroup.maxLen) {
|
|
_throw(Err.DATA_ERROR);
|
|
}
|
|
if (j <= hufGroup.limit[i])
|
|
break;
|
|
j = j << 1 | reader.read(1);
|
|
}
|
|
j -= hufGroup.base[i];
|
|
if (j < 0 || j >= MAX_SYMBOLS) {
|
|
_throw(Err.DATA_ERROR);
|
|
}
|
|
var nextSym = hufGroup.permute[j];
|
|
if (nextSym === SYMBOL_RUNA || nextSym === SYMBOL_RUNB) {
|
|
if (!runPos) {
|
|
runPos = 1;
|
|
t = 0;
|
|
}
|
|
if (nextSym === SYMBOL_RUNA)
|
|
t += runPos;
|
|
else
|
|
t += 2 * runPos;
|
|
runPos <<= 1;
|
|
continue;
|
|
}
|
|
if (runPos) {
|
|
runPos = 0;
|
|
if (dbufCount + t > this.dbufSize) {
|
|
_throw(Err.DATA_ERROR);
|
|
}
|
|
uc = symToByte[mtfSymbol[0]];
|
|
byteCount[uc] += t;
|
|
while (t--)
|
|
dbuf[dbufCount++] = uc;
|
|
}
|
|
if (nextSym > symTotal)
|
|
break;
|
|
if (dbufCount >= this.dbufSize) {
|
|
_throw(Err.DATA_ERROR);
|
|
}
|
|
i = nextSym - 1;
|
|
uc = mtf(mtfSymbol, i);
|
|
uc = symToByte[uc];
|
|
byteCount[uc]++;
|
|
dbuf[dbufCount++] = uc;
|
|
}
|
|
if (origPointer < 0 || origPointer >= dbufCount) {
|
|
_throw(Err.DATA_ERROR);
|
|
}
|
|
j = 0;
|
|
for (i = 0; i < 256; i++) {
|
|
k = j + byteCount[i];
|
|
byteCount[i] = j;
|
|
j = k;
|
|
}
|
|
for (i = 0; i < dbufCount; i++) {
|
|
uc = dbuf[i] & 255;
|
|
dbuf[byteCount[uc]] |= i << 8;
|
|
byteCount[uc]++;
|
|
}
|
|
var pos = 0, current = 0, run = 0;
|
|
if (dbufCount) {
|
|
pos = dbuf[origPointer];
|
|
current = pos & 255;
|
|
pos >>= 8;
|
|
run = -1;
|
|
}
|
|
this.writePos = pos;
|
|
this.writeCurrent = current;
|
|
this.writeCount = dbufCount;
|
|
this.writeRun = run;
|
|
return true;
|
|
};
|
|
Bunzip.prototype._read_bunzip = function(outputBuffer, len) {
|
|
var copies, previous, outbyte;
|
|
if (this.writeCount < 0) {
|
|
return 0;
|
|
}
|
|
var gotcount = 0;
|
|
var dbuf = this.dbuf, pos = this.writePos, current = this.writeCurrent;
|
|
var dbufCount = this.writeCount, outputsize = this.outputsize;
|
|
var run = this.writeRun;
|
|
while (dbufCount) {
|
|
dbufCount--;
|
|
previous = current;
|
|
pos = dbuf[pos];
|
|
current = pos & 255;
|
|
pos >>= 8;
|
|
if (run++ === 3) {
|
|
copies = current;
|
|
outbyte = previous;
|
|
current = -1;
|
|
} else {
|
|
copies = 1;
|
|
outbyte = current;
|
|
}
|
|
this.blockCRC.updateCRCRun(outbyte, copies);
|
|
while (copies--) {
|
|
this.outputStream.writeByte(outbyte);
|
|
this.nextoutput++;
|
|
}
|
|
if (current != previous)
|
|
run = 0;
|
|
}
|
|
this.writeCount = dbufCount;
|
|
if (this.blockCRC.getCRC() !== this.targetBlockCRC) {
|
|
_throw(Err.DATA_ERROR, "Bad block CRC (got " + this.blockCRC.getCRC().toString(16) + " expected " + this.targetBlockCRC.toString(16) + ")");
|
|
}
|
|
return this.nextoutput;
|
|
};
|
|
var coerceInputStream = function(input) {
|
|
if ("readByte" in input) {
|
|
return input;
|
|
}
|
|
var inputStream = new Stream();
|
|
inputStream.pos = 0;
|
|
inputStream.readByte = function() {
|
|
return input[this.pos++];
|
|
};
|
|
inputStream.seek = function(pos) {
|
|
this.pos = pos;
|
|
};
|
|
inputStream.eof = function() {
|
|
return this.pos >= input.length;
|
|
};
|
|
return inputStream;
|
|
};
|
|
var coerceOutputStream = function(output) {
|
|
var outputStream = new Stream();
|
|
var resizeOk = true;
|
|
if (output) {
|
|
if (typeof output === "number") {
|
|
outputStream.buffer = new Buffer(output);
|
|
resizeOk = false;
|
|
} else if ("writeByte" in output) {
|
|
return output;
|
|
} else {
|
|
outputStream.buffer = output;
|
|
resizeOk = false;
|
|
}
|
|
} else {
|
|
outputStream.buffer = new Buffer(16384);
|
|
}
|
|
outputStream.pos = 0;
|
|
outputStream.writeByte = function(_byte) {
|
|
if (resizeOk && this.pos >= this.buffer.length) {
|
|
var newBuffer = new Buffer(this.buffer.length * 2);
|
|
this.buffer.copy(newBuffer);
|
|
this.buffer = newBuffer;
|
|
}
|
|
this.buffer[this.pos++] = _byte;
|
|
};
|
|
outputStream.getBuffer = function() {
|
|
if (this.pos !== this.buffer.length) {
|
|
if (!resizeOk)
|
|
throw new TypeError("outputsize does not match decoded input");
|
|
var newBuffer = new Buffer(this.pos);
|
|
this.buffer.copy(newBuffer, 0, 0, this.pos);
|
|
this.buffer = newBuffer;
|
|
}
|
|
return this.buffer;
|
|
};
|
|
outputStream._coerced = true;
|
|
return outputStream;
|
|
};
|
|
Bunzip.Err = Err;
|
|
Bunzip.decode = function(input, output, multistream) {
|
|
var inputStream = coerceInputStream(input);
|
|
var outputStream = coerceOutputStream(output);
|
|
var bz = new Bunzip(inputStream, outputStream);
|
|
while (true) {
|
|
if ("eof" in inputStream && inputStream.eof()) break;
|
|
if (bz._init_block()) {
|
|
bz._read_bunzip();
|
|
} else {
|
|
var targetStreamCRC = bz.reader.read(32) >>> 0;
|
|
if (targetStreamCRC !== bz.streamCRC) {
|
|
_throw(Err.DATA_ERROR, "Bad stream CRC (got " + bz.streamCRC.toString(16) + " expected " + targetStreamCRC.toString(16) + ")");
|
|
}
|
|
if (multistream && "eof" in inputStream && !inputStream.eof()) {
|
|
bz._start_bunzip(inputStream, outputStream);
|
|
} else break;
|
|
}
|
|
}
|
|
if ("getBuffer" in outputStream)
|
|
return outputStream.getBuffer();
|
|
};
|
|
Bunzip.decodeBlock = function(input, pos, output) {
|
|
var inputStream = coerceInputStream(input);
|
|
var outputStream = coerceOutputStream(output);
|
|
var bz = new Bunzip(inputStream, outputStream);
|
|
bz.reader.seek(pos);
|
|
var moreBlocks = bz._get_next_block();
|
|
if (moreBlocks) {
|
|
bz.blockCRC = new CRC32();
|
|
bz.writeCopies = 0;
|
|
bz._read_bunzip();
|
|
}
|
|
if ("getBuffer" in outputStream)
|
|
return outputStream.getBuffer();
|
|
};
|
|
Bunzip.table = function(input, callback, multistream) {
|
|
var inputStream = new Stream();
|
|
inputStream.delegate = coerceInputStream(input);
|
|
inputStream.pos = 0;
|
|
inputStream.readByte = function() {
|
|
this.pos++;
|
|
return this.delegate.readByte();
|
|
};
|
|
if (inputStream.delegate.eof) {
|
|
inputStream.eof = inputStream.delegate.eof.bind(inputStream.delegate);
|
|
}
|
|
var outputStream = new Stream();
|
|
outputStream.pos = 0;
|
|
outputStream.writeByte = function() {
|
|
this.pos++;
|
|
};
|
|
var bz = new Bunzip(inputStream, outputStream);
|
|
var blockSize = bz.dbufSize;
|
|
while (true) {
|
|
if ("eof" in inputStream && inputStream.eof()) break;
|
|
var position = inputStream.pos * 8 + bz.reader.bitOffset;
|
|
if (bz.reader.hasByte) {
|
|
position -= 8;
|
|
}
|
|
if (bz._init_block()) {
|
|
var start = outputStream.pos;
|
|
bz._read_bunzip();
|
|
callback(position, outputStream.pos - start);
|
|
} else {
|
|
var crc = bz.reader.read(32);
|
|
if (multistream && "eof" in inputStream && !inputStream.eof()) {
|
|
bz._start_bunzip(inputStream, outputStream);
|
|
console.assert(
|
|
bz.dbufSize === blockSize,
|
|
"shouldn't change block size within multistream file"
|
|
);
|
|
} else break;
|
|
}
|
|
}
|
|
};
|
|
Bunzip.Stream = Stream;
|
|
Bunzip.version = pjson.version;
|
|
Bunzip.license = pjson.license;
|
|
module.exports = Bunzip;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/through/index.js
|
|
var require_through = __commonJS({
|
|
"../../node_modules/through/index.js"(exports, module) {
|
|
var Stream = __require("stream");
|
|
exports = module.exports = through;
|
|
through.through = through;
|
|
function through(write, end, opts) {
|
|
write = write || function(data) {
|
|
this.queue(data);
|
|
};
|
|
end = end || function() {
|
|
this.queue(null);
|
|
};
|
|
var ended = false, destroyed = false, buffer = [], _ended = false;
|
|
var stream = new Stream();
|
|
stream.readable = stream.writable = true;
|
|
stream.paused = false;
|
|
stream.autoDestroy = !(opts && opts.autoDestroy === false);
|
|
stream.write = function(data) {
|
|
write.call(this, data);
|
|
return !stream.paused;
|
|
};
|
|
function drain() {
|
|
while (buffer.length && !stream.paused) {
|
|
var data = buffer.shift();
|
|
if (null === data)
|
|
return stream.emit("end");
|
|
else
|
|
stream.emit("data", data);
|
|
}
|
|
}
|
|
stream.queue = stream.push = function(data) {
|
|
if (_ended) return stream;
|
|
if (data === null) _ended = true;
|
|
buffer.push(data);
|
|
drain();
|
|
return stream;
|
|
};
|
|
stream.on("end", function() {
|
|
stream.readable = false;
|
|
if (!stream.writable && stream.autoDestroy)
|
|
process.nextTick(function() {
|
|
stream.destroy();
|
|
});
|
|
});
|
|
function _end() {
|
|
stream.writable = false;
|
|
end.call(stream);
|
|
if (!stream.readable && stream.autoDestroy)
|
|
stream.destroy();
|
|
}
|
|
stream.end = function(data) {
|
|
if (ended) return;
|
|
ended = true;
|
|
if (arguments.length) stream.write(data);
|
|
_end();
|
|
return stream;
|
|
};
|
|
stream.destroy = function() {
|
|
if (destroyed) return;
|
|
destroyed = true;
|
|
ended = true;
|
|
buffer.length = 0;
|
|
stream.writable = stream.readable = false;
|
|
stream.emit("close");
|
|
return stream;
|
|
};
|
|
stream.pause = function() {
|
|
if (stream.paused) return;
|
|
stream.paused = true;
|
|
return stream;
|
|
};
|
|
stream.resume = function() {
|
|
if (stream.paused) {
|
|
stream.paused = false;
|
|
stream.emit("resume");
|
|
}
|
|
drain();
|
|
if (!stream.paused)
|
|
stream.emit("drain");
|
|
return stream;
|
|
};
|
|
return stream;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/unbzip2-stream/lib/bzip2.js
|
|
var require_bzip2 = __commonJS({
|
|
"../../node_modules/unbzip2-stream/lib/bzip2.js"(exports, module) {
|
|
function Bzip2Error(message2) {
|
|
this.name = "Bzip2Error";
|
|
this.message = message2;
|
|
this.stack = new Error().stack;
|
|
}
|
|
Bzip2Error.prototype = new Error();
|
|
var message = {
|
|
Error: function(message2) {
|
|
throw new Bzip2Error(message2);
|
|
}
|
|
};
|
|
var bzip2 = {};
|
|
bzip2.Bzip2Error = Bzip2Error;
|
|
bzip2.crcTable = [
|
|
0,
|
|
79764919,
|
|
159529838,
|
|
222504665,
|
|
319059676,
|
|
398814059,
|
|
445009330,
|
|
507990021,
|
|
638119352,
|
|
583659535,
|
|
797628118,
|
|
726387553,
|
|
890018660,
|
|
835552979,
|
|
1015980042,
|
|
944750013,
|
|
1276238704,
|
|
1221641927,
|
|
1167319070,
|
|
1095957929,
|
|
1595256236,
|
|
1540665371,
|
|
1452775106,
|
|
1381403509,
|
|
1780037320,
|
|
1859660671,
|
|
1671105958,
|
|
1733955601,
|
|
2031960084,
|
|
2111593891,
|
|
1889500026,
|
|
1952343757,
|
|
2552477408,
|
|
2632100695,
|
|
2443283854,
|
|
2506133561,
|
|
2334638140,
|
|
2414271883,
|
|
2191915858,
|
|
2254759653,
|
|
3190512472,
|
|
3135915759,
|
|
3081330742,
|
|
3009969537,
|
|
2905550212,
|
|
2850959411,
|
|
2762807018,
|
|
2691435357,
|
|
3560074640,
|
|
3505614887,
|
|
3719321342,
|
|
3648080713,
|
|
3342211916,
|
|
3287746299,
|
|
3467911202,
|
|
3396681109,
|
|
4063920168,
|
|
4143685023,
|
|
4223187782,
|
|
4286162673,
|
|
3779000052,
|
|
3858754371,
|
|
3904687514,
|
|
3967668269,
|
|
881225847,
|
|
809987520,
|
|
1023691545,
|
|
969234094,
|
|
662832811,
|
|
591600412,
|
|
771767749,
|
|
717299826,
|
|
311336399,
|
|
374308984,
|
|
453813921,
|
|
533576470,
|
|
25881363,
|
|
88864420,
|
|
134795389,
|
|
214552010,
|
|
2023205639,
|
|
2086057648,
|
|
1897238633,
|
|
1976864222,
|
|
1804852699,
|
|
1867694188,
|
|
1645340341,
|
|
1724971778,
|
|
1587496639,
|
|
1516133128,
|
|
1461550545,
|
|
1406951526,
|
|
1302016099,
|
|
1230646740,
|
|
1142491917,
|
|
1087903418,
|
|
2896545431,
|
|
2825181984,
|
|
2770861561,
|
|
2716262478,
|
|
3215044683,
|
|
3143675388,
|
|
3055782693,
|
|
3001194130,
|
|
2326604591,
|
|
2389456536,
|
|
2200899649,
|
|
2280525302,
|
|
2578013683,
|
|
2640855108,
|
|
2418763421,
|
|
2498394922,
|
|
3769900519,
|
|
3832873040,
|
|
3912640137,
|
|
3992402750,
|
|
4088425275,
|
|
4151408268,
|
|
4197601365,
|
|
4277358050,
|
|
3334271071,
|
|
3263032808,
|
|
3476998961,
|
|
3422541446,
|
|
3585640067,
|
|
3514407732,
|
|
3694837229,
|
|
3640369242,
|
|
1762451694,
|
|
1842216281,
|
|
1619975040,
|
|
1682949687,
|
|
2047383090,
|
|
2127137669,
|
|
1938468188,
|
|
2001449195,
|
|
1325665622,
|
|
1271206113,
|
|
1183200824,
|
|
1111960463,
|
|
1543535498,
|
|
1489069629,
|
|
1434599652,
|
|
1363369299,
|
|
622672798,
|
|
568075817,
|
|
748617968,
|
|
677256519,
|
|
907627842,
|
|
853037301,
|
|
1067152940,
|
|
995781531,
|
|
51762726,
|
|
131386257,
|
|
177728840,
|
|
240578815,
|
|
269590778,
|
|
349224269,
|
|
429104020,
|
|
491947555,
|
|
4046411278,
|
|
4126034873,
|
|
4172115296,
|
|
4234965207,
|
|
3794477266,
|
|
3874110821,
|
|
3953728444,
|
|
4016571915,
|
|
3609705398,
|
|
3555108353,
|
|
3735388376,
|
|
3664026991,
|
|
3290680682,
|
|
3236090077,
|
|
3449943556,
|
|
3378572211,
|
|
3174993278,
|
|
3120533705,
|
|
3032266256,
|
|
2961025959,
|
|
2923101090,
|
|
2868635157,
|
|
2813903052,
|
|
2742672763,
|
|
2604032198,
|
|
2683796849,
|
|
2461293480,
|
|
2524268063,
|
|
2284983834,
|
|
2364738477,
|
|
2175806836,
|
|
2238787779,
|
|
1569362073,
|
|
1498123566,
|
|
1409854455,
|
|
1355396672,
|
|
1317987909,
|
|
1246755826,
|
|
1192025387,
|
|
1137557660,
|
|
2072149281,
|
|
2135122070,
|
|
1912620623,
|
|
1992383480,
|
|
1753615357,
|
|
1816598090,
|
|
1627664531,
|
|
1707420964,
|
|
295390185,
|
|
358241886,
|
|
404320391,
|
|
483945776,
|
|
43990325,
|
|
106832002,
|
|
186451547,
|
|
266083308,
|
|
932423249,
|
|
861060070,
|
|
1041341759,
|
|
986742920,
|
|
613929101,
|
|
542559546,
|
|
756411363,
|
|
701822548,
|
|
3316196985,
|
|
3244833742,
|
|
3425377559,
|
|
3370778784,
|
|
3601682597,
|
|
3530312978,
|
|
3744426955,
|
|
3689838204,
|
|
3819031489,
|
|
3881883254,
|
|
3928223919,
|
|
4007849240,
|
|
4037393693,
|
|
4100235434,
|
|
4180117107,
|
|
4259748804,
|
|
2310601993,
|
|
2373574846,
|
|
2151335527,
|
|
2231098320,
|
|
2596047829,
|
|
2659030626,
|
|
2470359227,
|
|
2550115596,
|
|
2947551409,
|
|
2876312838,
|
|
2788305887,
|
|
2733848168,
|
|
3165939309,
|
|
3094707162,
|
|
3040238851,
|
|
2985771188
|
|
];
|
|
bzip2.array = function(bytes) {
|
|
var bit = 0, byte = 0;
|
|
var BITMASK = [0, 1, 3, 7, 15, 31, 63, 127, 255];
|
|
return function(n) {
|
|
var result = 0;
|
|
while (n > 0) {
|
|
var left = 8 - bit;
|
|
if (n >= left) {
|
|
result <<= left;
|
|
result |= BITMASK[left] & bytes[byte++];
|
|
bit = 0;
|
|
n -= left;
|
|
} else {
|
|
result <<= n;
|
|
result |= (bytes[byte] & BITMASK[n] << 8 - n - bit) >> 8 - n - bit;
|
|
bit += n;
|
|
n = 0;
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
};
|
|
bzip2.simple = function(srcbuffer, stream) {
|
|
var bits = bzip2.array(srcbuffer);
|
|
var size = bzip2.header(bits);
|
|
var ret = false;
|
|
var bufsize = 1e5 * size;
|
|
var buf = new Int32Array(bufsize);
|
|
do {
|
|
ret = bzip2.decompress(bits, stream, buf, bufsize);
|
|
} while (!ret);
|
|
};
|
|
bzip2.header = function(bits) {
|
|
this.byteCount = new Int32Array(256);
|
|
this.symToByte = new Uint8Array(256);
|
|
this.mtfSymbol = new Int32Array(256);
|
|
this.selectors = new Uint8Array(32768);
|
|
if (bits(8 * 3) != 4348520) message.Error("No magic number found");
|
|
var i = bits(8) - 48;
|
|
if (i < 1 || i > 9) message.Error("Not a BZIP archive");
|
|
return i;
|
|
};
|
|
bzip2.decompress = function(bits, stream, buf, bufsize, streamCRC) {
|
|
var MAX_HUFCODE_BITS = 20;
|
|
var MAX_SYMBOLS = 258;
|
|
var SYMBOL_RUNA = 0;
|
|
var SYMBOL_RUNB = 1;
|
|
var GROUP_SIZE = 50;
|
|
var crc = 0 ^ -1;
|
|
for (var h = "", i = 0; i < 6; i++) h += bits(8).toString(16);
|
|
if (h == "177245385090") {
|
|
var finalCRC = bits(32) | 0;
|
|
if (finalCRC !== streamCRC) message.Error("Error in bzip2: crc32 do not match");
|
|
bits(null);
|
|
return null;
|
|
}
|
|
if (h != "314159265359") message.Error("eek not valid bzip data");
|
|
var crcblock = bits(32) | 0;
|
|
if (bits(1)) message.Error("unsupported obsolete version");
|
|
var origPtr = bits(24);
|
|
if (origPtr > bufsize) message.Error("Initial position larger than buffer size");
|
|
var t = bits(16);
|
|
var symTotal = 0;
|
|
for (i = 0; i < 16; i++) {
|
|
if (t & 1 << 15 - i) {
|
|
var k = bits(16);
|
|
for (j = 0; j < 16; j++) {
|
|
if (k & 1 << 15 - j) {
|
|
this.symToByte[symTotal++] = 16 * i + j;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var groupCount = bits(3);
|
|
if (groupCount < 2 || groupCount > 6) message.Error("another error");
|
|
var nSelectors = bits(15);
|
|
if (nSelectors == 0) message.Error("meh");
|
|
for (var i = 0; i < groupCount; i++) this.mtfSymbol[i] = i;
|
|
for (var i = 0; i < nSelectors; i++) {
|
|
for (var j = 0; bits(1); j++) if (j >= groupCount) message.Error("whoops another error");
|
|
var uc = this.mtfSymbol[j];
|
|
for (var k = j - 1; k >= 0; k--) {
|
|
this.mtfSymbol[k + 1] = this.mtfSymbol[k];
|
|
}
|
|
this.mtfSymbol[0] = uc;
|
|
this.selectors[i] = uc;
|
|
}
|
|
var symCount = symTotal + 2;
|
|
var groups = [];
|
|
var length = new Uint8Array(MAX_SYMBOLS), temp = new Uint16Array(MAX_HUFCODE_BITS + 1);
|
|
var hufGroup;
|
|
for (var j = 0; j < groupCount; j++) {
|
|
t = bits(5);
|
|
for (var i = 0; i < symCount; i++) {
|
|
while (true) {
|
|
if (t < 1 || t > MAX_HUFCODE_BITS) message.Error("I gave up a while ago on writing error messages");
|
|
if (!bits(1)) break;
|
|
if (!bits(1)) t++;
|
|
else t--;
|
|
}
|
|
length[i] = t;
|
|
}
|
|
var minLen, maxLen;
|
|
minLen = maxLen = length[0];
|
|
for (var i = 1; i < symCount; i++) {
|
|
if (length[i] > maxLen) maxLen = length[i];
|
|
else if (length[i] < minLen) minLen = length[i];
|
|
}
|
|
hufGroup = groups[j] = {};
|
|
hufGroup.permute = new Int32Array(MAX_SYMBOLS);
|
|
hufGroup.limit = new Int32Array(MAX_HUFCODE_BITS + 1);
|
|
hufGroup.base = new Int32Array(MAX_HUFCODE_BITS + 1);
|
|
hufGroup.minLen = minLen;
|
|
hufGroup.maxLen = maxLen;
|
|
var base = hufGroup.base;
|
|
var limit = hufGroup.limit;
|
|
var pp = 0;
|
|
for (var i = minLen; i <= maxLen; i++)
|
|
for (var t = 0; t < symCount; t++)
|
|
if (length[t] == i) hufGroup.permute[pp++] = t;
|
|
for (i = minLen; i <= maxLen; i++) temp[i] = limit[i] = 0;
|
|
for (i = 0; i < symCount; i++) temp[length[i]]++;
|
|
pp = t = 0;
|
|
for (i = minLen; i < maxLen; i++) {
|
|
pp += temp[i];
|
|
limit[i] = pp - 1;
|
|
pp <<= 1;
|
|
base[i + 1] = pp - (t += temp[i]);
|
|
}
|
|
limit[maxLen] = pp + temp[maxLen] - 1;
|
|
base[minLen] = 0;
|
|
}
|
|
for (var i = 0; i < 256; i++) {
|
|
this.mtfSymbol[i] = i;
|
|
this.byteCount[i] = 0;
|
|
}
|
|
var runPos, count, symCount, selector;
|
|
runPos = count = symCount = selector = 0;
|
|
while (true) {
|
|
if (!symCount--) {
|
|
symCount = GROUP_SIZE - 1;
|
|
if (selector >= nSelectors) message.Error("meow i'm a kitty, that's an error");
|
|
hufGroup = groups[this.selectors[selector++]];
|
|
base = hufGroup.base;
|
|
limit = hufGroup.limit;
|
|
}
|
|
i = hufGroup.minLen;
|
|
j = bits(i);
|
|
while (true) {
|
|
if (i > hufGroup.maxLen) message.Error("rawr i'm a dinosaur");
|
|
if (j <= limit[i]) break;
|
|
i++;
|
|
j = j << 1 | bits(1);
|
|
}
|
|
j -= base[i];
|
|
if (j < 0 || j >= MAX_SYMBOLS) message.Error("moo i'm a cow");
|
|
var nextSym = hufGroup.permute[j];
|
|
if (nextSym == SYMBOL_RUNA || nextSym == SYMBOL_RUNB) {
|
|
if (!runPos) {
|
|
runPos = 1;
|
|
t = 0;
|
|
}
|
|
if (nextSym == SYMBOL_RUNA) t += runPos;
|
|
else t += 2 * runPos;
|
|
runPos <<= 1;
|
|
continue;
|
|
}
|
|
if (runPos) {
|
|
runPos = 0;
|
|
if (count + t > bufsize) message.Error("Boom.");
|
|
uc = this.symToByte[this.mtfSymbol[0]];
|
|
this.byteCount[uc] += t;
|
|
while (t--) buf[count++] = uc;
|
|
}
|
|
if (nextSym > symTotal) break;
|
|
if (count >= bufsize) message.Error("I can't think of anything. Error");
|
|
i = nextSym - 1;
|
|
uc = this.mtfSymbol[i];
|
|
for (var k = i - 1; k >= 0; k--) {
|
|
this.mtfSymbol[k + 1] = this.mtfSymbol[k];
|
|
}
|
|
this.mtfSymbol[0] = uc;
|
|
uc = this.symToByte[uc];
|
|
this.byteCount[uc]++;
|
|
buf[count++] = uc;
|
|
}
|
|
if (origPtr < 0 || origPtr >= count) message.Error("I'm a monkey and I'm throwing something at someone, namely you");
|
|
var j = 0;
|
|
for (var i = 0; i < 256; i++) {
|
|
k = j + this.byteCount[i];
|
|
this.byteCount[i] = j;
|
|
j = k;
|
|
}
|
|
for (var i = 0; i < count; i++) {
|
|
uc = buf[i] & 255;
|
|
buf[this.byteCount[uc]] |= i << 8;
|
|
this.byteCount[uc]++;
|
|
}
|
|
var pos = 0, current = 0, run = 0;
|
|
if (count) {
|
|
pos = buf[origPtr];
|
|
current = pos & 255;
|
|
pos >>= 8;
|
|
run = -1;
|
|
}
|
|
count = count;
|
|
var copies, previous, outbyte;
|
|
while (count) {
|
|
count--;
|
|
previous = current;
|
|
pos = buf[pos];
|
|
current = pos & 255;
|
|
pos >>= 8;
|
|
if (run++ == 3) {
|
|
copies = current;
|
|
outbyte = previous;
|
|
current = -1;
|
|
} else {
|
|
copies = 1;
|
|
outbyte = current;
|
|
}
|
|
while (copies--) {
|
|
crc = (crc << 8 ^ this.crcTable[(crc >> 24 ^ outbyte) & 255]) & 4294967295;
|
|
stream(outbyte);
|
|
}
|
|
if (current != previous) run = 0;
|
|
}
|
|
crc = (crc ^ -1) >>> 0;
|
|
if ((crc | 0) != (crcblock | 0)) message.Error("Error in bzip2: crc32 do not match");
|
|
streamCRC = (crc ^ (streamCRC << 1 | streamCRC >>> 31)) & 4294967295;
|
|
return streamCRC;
|
|
};
|
|
module.exports = bzip2;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/unbzip2-stream/lib/bit_iterator.js
|
|
var require_bit_iterator = __commonJS({
|
|
"../../node_modules/unbzip2-stream/lib/bit_iterator.js"(exports, module) {
|
|
var BITMASK = [0, 1, 3, 7, 15, 31, 63, 127, 255];
|
|
module.exports = function bitIterator(nextBuffer) {
|
|
var bit = 0, byte = 0;
|
|
var bytes = nextBuffer();
|
|
var f = function(n) {
|
|
if (n === null && bit != 0) {
|
|
bit = 0;
|
|
byte++;
|
|
return;
|
|
}
|
|
var result = 0;
|
|
while (n > 0) {
|
|
if (byte >= bytes.length) {
|
|
byte = 0;
|
|
bytes = nextBuffer();
|
|
}
|
|
var left = 8 - bit;
|
|
if (bit === 0 && n > 0)
|
|
f.bytesRead++;
|
|
if (n >= left) {
|
|
result <<= left;
|
|
result |= BITMASK[left] & bytes[byte++];
|
|
bit = 0;
|
|
n -= left;
|
|
} else {
|
|
result <<= n;
|
|
result |= (bytes[byte] & BITMASK[n] << 8 - n - bit) >> 8 - n - bit;
|
|
bit += n;
|
|
n = 0;
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
f.bytesRead = 0;
|
|
return f;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/unbzip2-stream/index.js
|
|
var require_unbzip2_stream = __commonJS({
|
|
"../../node_modules/unbzip2-stream/index.js"(exports, module) {
|
|
var through = require_through();
|
|
var bz2 = require_bzip2();
|
|
var bitIterator = require_bit_iterator();
|
|
module.exports = unbzip2Stream;
|
|
function unbzip2Stream() {
|
|
var bufferQueue = [];
|
|
var hasBytes = 0;
|
|
var blockSize = 0;
|
|
var broken = false;
|
|
var done = false;
|
|
var bitReader = null;
|
|
var streamCRC = null;
|
|
function decompressBlock(push) {
|
|
if (!blockSize) {
|
|
blockSize = bz2.header(bitReader);
|
|
streamCRC = 0;
|
|
return true;
|
|
} else {
|
|
var bufsize = 1e5 * blockSize;
|
|
var buf = new Int32Array(bufsize);
|
|
var chunk = [];
|
|
var f = function(b) {
|
|
chunk.push(b);
|
|
};
|
|
streamCRC = bz2.decompress(bitReader, f, buf, bufsize, streamCRC);
|
|
if (streamCRC === null) {
|
|
blockSize = 0;
|
|
return false;
|
|
} else {
|
|
push(Buffer.from(chunk));
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
var outlength = 0;
|
|
function decompressAndQueue(stream) {
|
|
if (broken) return;
|
|
try {
|
|
return decompressBlock(function(d) {
|
|
stream.queue(d);
|
|
if (d !== null) {
|
|
outlength += d.length;
|
|
} else {
|
|
}
|
|
});
|
|
} catch (e) {
|
|
stream.emit("error", e);
|
|
broken = true;
|
|
return false;
|
|
}
|
|
}
|
|
return through(
|
|
function write(data) {
|
|
bufferQueue.push(data);
|
|
hasBytes += data.length;
|
|
if (bitReader === null) {
|
|
bitReader = bitIterator(function() {
|
|
return bufferQueue.shift();
|
|
});
|
|
}
|
|
while (!broken && hasBytes - bitReader.bytesRead + 1 >= (25e3 + 1e5 * blockSize || 4)) {
|
|
decompressAndQueue(this);
|
|
}
|
|
},
|
|
function end(x) {
|
|
while (!broken && bitReader && hasBytes > bitReader.bytesRead) {
|
|
decompressAndQueue(this);
|
|
}
|
|
if (!broken) {
|
|
if (streamCRC !== null)
|
|
this.emit("error", new Error("input stream ended prematurely"));
|
|
this.queue(null);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress-tarbz2/index.js
|
|
var require_decompress_tarbz2 = __commonJS({
|
|
"../../node_modules/decompress-tarbz2/index.js"(exports, module) {
|
|
"use strict";
|
|
var decompressTar = require_decompress_tar();
|
|
var fileType = require_file_type2();
|
|
var isStream = require_is_stream();
|
|
var seekBzip = require_lib();
|
|
var unbzip2Stream = require_unbzip2_stream();
|
|
module.exports = () => (input) => {
|
|
if (!Buffer.isBuffer(input) && !isStream(input)) {
|
|
return Promise.reject(new TypeError(`Expected a Buffer or Stream, got ${typeof input}`));
|
|
}
|
|
if (Buffer.isBuffer(input) && (!fileType(input) || fileType(input).ext !== "bz2")) {
|
|
return Promise.resolve([]);
|
|
}
|
|
if (Buffer.isBuffer(input)) {
|
|
return decompressTar()(seekBzip.decode(input));
|
|
}
|
|
return decompressTar()(input.pipe(unbzip2Stream()));
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress-targz/index.js
|
|
var require_decompress_targz = __commonJS({
|
|
"../../node_modules/decompress-targz/index.js"(exports, module) {
|
|
"use strict";
|
|
var zlib = __require("zlib");
|
|
var decompressTar = require_decompress_tar();
|
|
var fileType = require_file_type();
|
|
var isStream = require_is_stream();
|
|
module.exports = () => (input) => {
|
|
if (!Buffer.isBuffer(input) && !isStream(input)) {
|
|
return Promise.reject(new TypeError(`Expected a Buffer or Stream, got ${typeof input}`));
|
|
}
|
|
if (Buffer.isBuffer(input) && (!fileType(input) || fileType(input).ext !== "gz")) {
|
|
return Promise.resolve([]);
|
|
}
|
|
const unzip = zlib.createGunzip();
|
|
const result = decompressTar()(unzip);
|
|
if (Buffer.isBuffer(input)) {
|
|
unzip.end(input);
|
|
} else {
|
|
input.pipe(unzip);
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress-unzip/node_modules/file-type/index.js
|
|
var require_file_type3 = __commonJS({
|
|
"../../node_modules/decompress-unzip/node_modules/file-type/index.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = function(buf) {
|
|
if (!(buf && buf.length > 1)) {
|
|
return null;
|
|
}
|
|
if (buf[0] === 255 && buf[1] === 216 && buf[2] === 255) {
|
|
return {
|
|
ext: "jpg",
|
|
mime: "image/jpeg"
|
|
};
|
|
}
|
|
if (buf[0] === 137 && buf[1] === 80 && buf[2] === 78 && buf[3] === 71) {
|
|
return {
|
|
ext: "png",
|
|
mime: "image/png"
|
|
};
|
|
}
|
|
if (buf[0] === 71 && buf[1] === 73 && buf[2] === 70) {
|
|
return {
|
|
ext: "gif",
|
|
mime: "image/gif"
|
|
};
|
|
}
|
|
if (buf[8] === 87 && buf[9] === 69 && buf[10] === 66 && buf[11] === 80) {
|
|
return {
|
|
ext: "webp",
|
|
mime: "image/webp"
|
|
};
|
|
}
|
|
if (buf[0] === 70 && buf[1] === 76 && buf[2] === 73 && buf[3] === 70) {
|
|
return {
|
|
ext: "flif",
|
|
mime: "image/flif"
|
|
};
|
|
}
|
|
if ((buf[0] === 73 && buf[1] === 73 && buf[2] === 42 && buf[3] === 0 || buf[0] === 77 && buf[1] === 77 && buf[2] === 0 && buf[3] === 42) && buf[8] === 67 && buf[9] === 82) {
|
|
return {
|
|
ext: "cr2",
|
|
mime: "image/x-canon-cr2"
|
|
};
|
|
}
|
|
if (buf[0] === 73 && buf[1] === 73 && buf[2] === 42 && buf[3] === 0 || buf[0] === 77 && buf[1] === 77 && buf[2] === 0 && buf[3] === 42) {
|
|
return {
|
|
ext: "tif",
|
|
mime: "image/tiff"
|
|
};
|
|
}
|
|
if (buf[0] === 66 && buf[1] === 77) {
|
|
return {
|
|
ext: "bmp",
|
|
mime: "image/bmp"
|
|
};
|
|
}
|
|
if (buf[0] === 73 && buf[1] === 73 && buf[2] === 188) {
|
|
return {
|
|
ext: "jxr",
|
|
mime: "image/vnd.ms-photo"
|
|
};
|
|
}
|
|
if (buf[0] === 56 && buf[1] === 66 && buf[2] === 80 && buf[3] === 83) {
|
|
return {
|
|
ext: "psd",
|
|
mime: "image/vnd.adobe.photoshop"
|
|
};
|
|
}
|
|
if (buf[0] === 80 && buf[1] === 75 && buf[2] === 3 && buf[3] === 4 && buf[30] === 109 && buf[31] === 105 && buf[32] === 109 && buf[33] === 101 && buf[34] === 116 && buf[35] === 121 && buf[36] === 112 && buf[37] === 101 && buf[38] === 97 && buf[39] === 112 && buf[40] === 112 && buf[41] === 108 && buf[42] === 105 && buf[43] === 99 && buf[44] === 97 && buf[45] === 116 && buf[46] === 105 && buf[47] === 111 && buf[48] === 110 && buf[49] === 47 && buf[50] === 101 && buf[51] === 112 && buf[52] === 117 && buf[53] === 98 && buf[54] === 43 && buf[55] === 122 && buf[56] === 105 && buf[57] === 112) {
|
|
return {
|
|
ext: "epub",
|
|
mime: "application/epub+zip"
|
|
};
|
|
}
|
|
if (buf[0] === 80 && buf[1] === 75 && buf[2] === 3 && buf[3] === 4 && buf[30] === 77 && buf[31] === 69 && buf[32] === 84 && buf[33] === 65 && buf[34] === 45 && buf[35] === 73 && buf[36] === 78 && buf[37] === 70 && buf[38] === 47 && buf[39] === 109 && buf[40] === 111 && buf[41] === 122 && buf[42] === 105 && buf[43] === 108 && buf[44] === 108 && buf[45] === 97 && buf[46] === 46 && buf[47] === 114 && buf[48] === 115 && buf[49] === 97) {
|
|
return {
|
|
ext: "xpi",
|
|
mime: "application/x-xpinstall"
|
|
};
|
|
}
|
|
if (buf[0] === 80 && buf[1] === 75 && (buf[2] === 3 || buf[2] === 5 || buf[2] === 7) && (buf[3] === 4 || buf[3] === 6 || buf[3] === 8)) {
|
|
return {
|
|
ext: "zip",
|
|
mime: "application/zip"
|
|
};
|
|
}
|
|
if (buf[257] === 117 && buf[258] === 115 && buf[259] === 116 && buf[260] === 97 && buf[261] === 114) {
|
|
return {
|
|
ext: "tar",
|
|
mime: "application/x-tar"
|
|
};
|
|
}
|
|
if (buf[0] === 82 && buf[1] === 97 && buf[2] === 114 && buf[3] === 33 && buf[4] === 26 && buf[5] === 7 && (buf[6] === 0 || buf[6] === 1)) {
|
|
return {
|
|
ext: "rar",
|
|
mime: "application/x-rar-compressed"
|
|
};
|
|
}
|
|
if (buf[0] === 31 && buf[1] === 139 && buf[2] === 8) {
|
|
return {
|
|
ext: "gz",
|
|
mime: "application/gzip"
|
|
};
|
|
}
|
|
if (buf[0] === 66 && buf[1] === 90 && buf[2] === 104) {
|
|
return {
|
|
ext: "bz2",
|
|
mime: "application/x-bzip2"
|
|
};
|
|
}
|
|
if (buf[0] === 55 && buf[1] === 122 && buf[2] === 188 && buf[3] === 175 && buf[4] === 39 && buf[5] === 28) {
|
|
return {
|
|
ext: "7z",
|
|
mime: "application/x-7z-compressed"
|
|
};
|
|
}
|
|
if (buf[0] === 120 && buf[1] === 1) {
|
|
return {
|
|
ext: "dmg",
|
|
mime: "application/x-apple-diskimage"
|
|
};
|
|
}
|
|
if (buf[0] === 0 && buf[1] === 0 && buf[2] === 0 && (buf[3] === 24 || buf[3] === 32) && buf[4] === 102 && buf[5] === 116 && buf[6] === 121 && buf[7] === 112 || buf[0] === 51 && buf[1] === 103 && buf[2] === 112 && buf[3] === 53 || buf[0] === 0 && buf[1] === 0 && buf[2] === 0 && buf[3] === 28 && buf[4] === 102 && buf[5] === 116 && buf[6] === 121 && buf[7] === 112 && buf[8] === 109 && buf[9] === 112 && buf[10] === 52 && buf[11] === 50 && buf[16] === 109 && buf[17] === 112 && buf[18] === 52 && buf[19] === 49 && buf[20] === 109 && buf[21] === 112 && buf[22] === 52 && buf[23] === 50 && buf[24] === 105 && buf[25] === 115 && buf[26] === 111 && buf[27] === 109 || buf[0] === 0 && buf[1] === 0 && buf[2] === 0 && buf[3] === 28 && buf[4] === 102 && buf[5] === 116 && buf[6] === 121 && buf[7] === 112 && buf[8] === 105 && buf[9] === 115 && buf[10] === 111 && buf[11] === 109 || buf[0] === 0 && buf[1] === 0 && buf[2] === 0 && buf[3] === 28 && buf[4] === 102 && buf[5] === 116 && buf[6] === 121 && buf[7] === 112 && buf[8] === 109 && buf[9] === 112 && buf[10] === 52 && buf[11] === 50 && buf[12] === 0 && buf[13] === 0 && buf[14] === 0 && buf[15] === 0) {
|
|
return {
|
|
ext: "mp4",
|
|
mime: "video/mp4"
|
|
};
|
|
}
|
|
if (buf[0] === 0 && buf[1] === 0 && buf[2] === 0 && buf[3] === 28 && buf[4] === 102 && buf[5] === 116 && buf[6] === 121 && buf[7] === 112 && buf[8] === 77 && buf[9] === 52 && buf[10] === 86) {
|
|
return {
|
|
ext: "m4v",
|
|
mime: "video/x-m4v"
|
|
};
|
|
}
|
|
if (buf[0] === 77 && buf[1] === 84 && buf[2] === 104 && buf[3] === 100) {
|
|
return {
|
|
ext: "mid",
|
|
mime: "audio/midi"
|
|
};
|
|
}
|
|
if (buf[31] === 109 && buf[32] === 97 && buf[33] === 116 && buf[34] === 114 && buf[35] === 111 && buf[36] === 115 && buf[37] === 107 && buf[38] === 97) {
|
|
return {
|
|
ext: "mkv",
|
|
mime: "video/x-matroska"
|
|
};
|
|
}
|
|
if (buf[0] === 26 && buf[1] === 69 && buf[2] === 223 && buf[3] === 163) {
|
|
return {
|
|
ext: "webm",
|
|
mime: "video/webm"
|
|
};
|
|
}
|
|
if (buf[0] === 0 && buf[1] === 0 && buf[2] === 0 && buf[3] === 20 && buf[4] === 102 && buf[5] === 116 && buf[6] === 121 && buf[7] === 112) {
|
|
return {
|
|
ext: "mov",
|
|
mime: "video/quicktime"
|
|
};
|
|
}
|
|
if (buf[0] === 82 && buf[1] === 73 && buf[2] === 70 && buf[3] === 70 && buf[8] === 65 && buf[9] === 86 && buf[10] === 73) {
|
|
return {
|
|
ext: "avi",
|
|
mime: "video/x-msvideo"
|
|
};
|
|
}
|
|
if (buf[0] === 48 && buf[1] === 38 && buf[2] === 178 && buf[3] === 117 && buf[4] === 142 && buf[5] === 102 && buf[6] === 207 && buf[7] === 17 && buf[8] === 166 && buf[9] === 217) {
|
|
return {
|
|
ext: "wmv",
|
|
mime: "video/x-ms-wmv"
|
|
};
|
|
}
|
|
if (buf[0] === 0 && buf[1] === 0 && buf[2] === 1 && buf[3].toString(16)[0] === "b") {
|
|
return {
|
|
ext: "mpg",
|
|
mime: "video/mpeg"
|
|
};
|
|
}
|
|
if (buf[0] === 73 && buf[1] === 68 && buf[2] === 51 || buf[0] === 255 && buf[1] === 251) {
|
|
return {
|
|
ext: "mp3",
|
|
mime: "audio/mpeg"
|
|
};
|
|
}
|
|
if (buf[4] === 102 && buf[5] === 116 && buf[6] === 121 && buf[7] === 112 && buf[8] === 77 && buf[9] === 52 && buf[10] === 65 || buf[0] === 77 && buf[1] === 52 && buf[2] === 65 && buf[3] === 32) {
|
|
return {
|
|
ext: "m4a",
|
|
mime: "audio/m4a"
|
|
};
|
|
}
|
|
if (buf[28] === 79 && buf[29] === 112 && buf[30] === 117 && buf[31] === 115 && buf[32] === 72 && buf[33] === 101 && buf[34] === 97 && buf[35] === 100) {
|
|
return {
|
|
ext: "opus",
|
|
mime: "audio/opus"
|
|
};
|
|
}
|
|
if (buf[0] === 79 && buf[1] === 103 && buf[2] === 103 && buf[3] === 83) {
|
|
return {
|
|
ext: "ogg",
|
|
mime: "audio/ogg"
|
|
};
|
|
}
|
|
if (buf[0] === 102 && buf[1] === 76 && buf[2] === 97 && buf[3] === 67) {
|
|
return {
|
|
ext: "flac",
|
|
mime: "audio/x-flac"
|
|
};
|
|
}
|
|
if (buf[0] === 82 && buf[1] === 73 && buf[2] === 70 && buf[3] === 70 && buf[8] === 87 && buf[9] === 65 && buf[10] === 86 && buf[11] === 69) {
|
|
return {
|
|
ext: "wav",
|
|
mime: "audio/x-wav"
|
|
};
|
|
}
|
|
if (buf[0] === 35 && buf[1] === 33 && buf[2] === 65 && buf[3] === 77 && buf[4] === 82 && buf[5] === 10) {
|
|
return {
|
|
ext: "amr",
|
|
mime: "audio/amr"
|
|
};
|
|
}
|
|
if (buf[0] === 37 && buf[1] === 80 && buf[2] === 68 && buf[3] === 70) {
|
|
return {
|
|
ext: "pdf",
|
|
mime: "application/pdf"
|
|
};
|
|
}
|
|
if (buf[0] === 77 && buf[1] === 90) {
|
|
return {
|
|
ext: "exe",
|
|
mime: "application/x-msdownload"
|
|
};
|
|
}
|
|
if ((buf[0] === 67 || buf[0] === 70) && buf[1] === 87 && buf[2] === 83) {
|
|
return {
|
|
ext: "swf",
|
|
mime: "application/x-shockwave-flash"
|
|
};
|
|
}
|
|
if (buf[0] === 123 && buf[1] === 92 && buf[2] === 114 && buf[3] === 116 && buf[4] === 102) {
|
|
return {
|
|
ext: "rtf",
|
|
mime: "application/rtf"
|
|
};
|
|
}
|
|
if (buf[0] === 119 && buf[1] === 79 && buf[2] === 70 && buf[3] === 70 && (buf[4] === 0 && buf[5] === 1 && buf[6] === 0 && buf[7] === 0 || buf[4] === 79 && buf[5] === 84 && buf[6] === 84 && buf[7] === 79)) {
|
|
return {
|
|
ext: "woff",
|
|
mime: "application/font-woff"
|
|
};
|
|
}
|
|
if (buf[0] === 119 && buf[1] === 79 && buf[2] === 70 && buf[3] === 50 && (buf[4] === 0 && buf[5] === 1 && buf[6] === 0 && buf[7] === 0 || buf[4] === 79 && buf[5] === 84 && buf[6] === 84 && buf[7] === 79)) {
|
|
return {
|
|
ext: "woff2",
|
|
mime: "application/font-woff"
|
|
};
|
|
}
|
|
if (buf[34] === 76 && buf[35] === 80 && (buf[8] === 0 && buf[9] === 0 && buf[10] === 1 || buf[8] === 1 && buf[9] === 0 && buf[10] === 2 || buf[8] === 2 && buf[9] === 0 && buf[10] === 2)) {
|
|
return {
|
|
ext: "eot",
|
|
mime: "application/octet-stream"
|
|
};
|
|
}
|
|
if (buf[0] === 0 && buf[1] === 1 && buf[2] === 0 && buf[3] === 0 && buf[4] === 0) {
|
|
return {
|
|
ext: "ttf",
|
|
mime: "application/font-sfnt"
|
|
};
|
|
}
|
|
if (buf[0] === 79 && buf[1] === 84 && buf[2] === 84 && buf[3] === 79 && buf[4] === 0) {
|
|
return {
|
|
ext: "otf",
|
|
mime: "application/font-sfnt"
|
|
};
|
|
}
|
|
if (buf[0] === 0 && buf[1] === 0 && buf[2] === 1 && buf[3] === 0) {
|
|
return {
|
|
ext: "ico",
|
|
mime: "image/x-icon"
|
|
};
|
|
}
|
|
if (buf[0] === 70 && buf[1] === 76 && buf[2] === 86 && buf[3] === 1) {
|
|
return {
|
|
ext: "flv",
|
|
mime: "video/x-flv"
|
|
};
|
|
}
|
|
if (buf[0] === 37 && buf[1] === 33) {
|
|
return {
|
|
ext: "ps",
|
|
mime: "application/postscript"
|
|
};
|
|
}
|
|
if (buf[0] === 253 && buf[1] === 55 && buf[2] === 122 && buf[3] === 88 && buf[4] === 90 && buf[5] === 0) {
|
|
return {
|
|
ext: "xz",
|
|
mime: "application/x-xz"
|
|
};
|
|
}
|
|
if (buf[0] === 83 && buf[1] === 81 && buf[2] === 76 && buf[3] === 105) {
|
|
return {
|
|
ext: "sqlite",
|
|
mime: "application/x-sqlite3"
|
|
};
|
|
}
|
|
if (buf[0] === 78 && buf[1] === 69 && buf[2] === 83 && buf[3] === 26) {
|
|
return {
|
|
ext: "nes",
|
|
mime: "application/x-nintendo-nes-rom"
|
|
};
|
|
}
|
|
if (buf[0] === 67 && buf[1] === 114 && buf[2] === 50 && buf[3] === 52) {
|
|
return {
|
|
ext: "crx",
|
|
mime: "application/x-google-chrome-extension"
|
|
};
|
|
}
|
|
if (buf[0] === 77 && buf[1] === 83 && buf[2] === 67 && buf[3] === 70 || buf[0] === 73 && buf[1] === 83 && buf[2] === 99 && buf[3] === 40) {
|
|
return {
|
|
ext: "cab",
|
|
mime: "application/vnd.ms-cab-compressed"
|
|
};
|
|
}
|
|
if (buf[0] === 33 && buf[1] === 60 && buf[2] === 97 && buf[3] === 114 && buf[4] === 99 && buf[5] === 104 && buf[6] === 62 && buf[7] === 10 && buf[8] === 100 && buf[9] === 101 && buf[10] === 98 && buf[11] === 105 && buf[12] === 97 && buf[13] === 110 && buf[14] === 45 && buf[15] === 98 && buf[16] === 105 && buf[17] === 110 && buf[18] === 97 && buf[19] === 114 && buf[20] === 121) {
|
|
return {
|
|
ext: "deb",
|
|
mime: "application/x-deb"
|
|
};
|
|
}
|
|
if (buf[0] === 33 && buf[1] === 60 && buf[2] === 97 && buf[3] === 114 && buf[4] === 99 && buf[5] === 104 && buf[6] === 62) {
|
|
return {
|
|
ext: "ar",
|
|
mime: "application/x-unix-archive"
|
|
};
|
|
}
|
|
if (buf[0] === 237 && buf[1] === 171 && buf[2] === 238 && buf[3] === 219) {
|
|
return {
|
|
ext: "rpm",
|
|
mime: "application/x-rpm"
|
|
};
|
|
}
|
|
if (buf[0] === 31 && buf[1] === 160 || buf[0] === 31 && buf[1] === 157) {
|
|
return {
|
|
ext: "Z",
|
|
mime: "application/x-compress"
|
|
};
|
|
}
|
|
if (buf[0] === 76 && buf[1] === 90 && buf[2] === 73 && buf[3] === 80) {
|
|
return {
|
|
ext: "lz",
|
|
mime: "application/x-lzip"
|
|
};
|
|
}
|
|
if (buf[0] === 208 && buf[1] === 207 && buf[2] === 17 && buf[3] === 224 && buf[4] === 161 && buf[5] === 177 && buf[6] === 26 && buf[7] === 225) {
|
|
return {
|
|
ext: "msi",
|
|
mime: "application/x-msi"
|
|
};
|
|
}
|
|
return null;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/pinkie/index.js
|
|
var require_pinkie = __commonJS({
|
|
"../../node_modules/pinkie/index.js"(exports, module) {
|
|
"use strict";
|
|
var PENDING = "pending";
|
|
var SETTLED = "settled";
|
|
var FULFILLED = "fulfilled";
|
|
var REJECTED = "rejected";
|
|
var NOOP = function() {
|
|
};
|
|
var isNode = typeof global !== "undefined" && typeof global.process !== "undefined" && typeof global.process.emit === "function";
|
|
var asyncSetTimer = typeof setImmediate === "undefined" ? setTimeout : setImmediate;
|
|
var asyncQueue = [];
|
|
var asyncTimer;
|
|
function asyncFlush() {
|
|
for (var i = 0; i < asyncQueue.length; i++) {
|
|
asyncQueue[i][0](asyncQueue[i][1]);
|
|
}
|
|
asyncQueue = [];
|
|
asyncTimer = false;
|
|
}
|
|
function asyncCall(callback, arg) {
|
|
asyncQueue.push([callback, arg]);
|
|
if (!asyncTimer) {
|
|
asyncTimer = true;
|
|
asyncSetTimer(asyncFlush, 0);
|
|
}
|
|
}
|
|
function invokeResolver(resolver, promise) {
|
|
function resolvePromise(value) {
|
|
resolve(promise, value);
|
|
}
|
|
function rejectPromise(reason) {
|
|
reject(promise, reason);
|
|
}
|
|
try {
|
|
resolver(resolvePromise, rejectPromise);
|
|
} catch (e) {
|
|
rejectPromise(e);
|
|
}
|
|
}
|
|
function invokeCallback(subscriber) {
|
|
var owner = subscriber.owner;
|
|
var settled = owner._state;
|
|
var value = owner._data;
|
|
var callback = subscriber[settled];
|
|
var promise = subscriber.then;
|
|
if (typeof callback === "function") {
|
|
settled = FULFILLED;
|
|
try {
|
|
value = callback(value);
|
|
} catch (e) {
|
|
reject(promise, e);
|
|
}
|
|
}
|
|
if (!handleThenable(promise, value)) {
|
|
if (settled === FULFILLED) {
|
|
resolve(promise, value);
|
|
}
|
|
if (settled === REJECTED) {
|
|
reject(promise, value);
|
|
}
|
|
}
|
|
}
|
|
function handleThenable(promise, value) {
|
|
var resolved;
|
|
try {
|
|
if (promise === value) {
|
|
throw new TypeError("A promises callback cannot return that same promise.");
|
|
}
|
|
if (value && (typeof value === "function" || typeof value === "object")) {
|
|
var then = value.then;
|
|
if (typeof then === "function") {
|
|
then.call(value, function(val) {
|
|
if (!resolved) {
|
|
resolved = true;
|
|
if (value === val) {
|
|
fulfill(promise, val);
|
|
} else {
|
|
resolve(promise, val);
|
|
}
|
|
}
|
|
}, function(reason) {
|
|
if (!resolved) {
|
|
resolved = true;
|
|
reject(promise, reason);
|
|
}
|
|
});
|
|
return true;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
if (!resolved) {
|
|
reject(promise, e);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
function resolve(promise, value) {
|
|
if (promise === value || !handleThenable(promise, value)) {
|
|
fulfill(promise, value);
|
|
}
|
|
}
|
|
function fulfill(promise, value) {
|
|
if (promise._state === PENDING) {
|
|
promise._state = SETTLED;
|
|
promise._data = value;
|
|
asyncCall(publishFulfillment, promise);
|
|
}
|
|
}
|
|
function reject(promise, reason) {
|
|
if (promise._state === PENDING) {
|
|
promise._state = SETTLED;
|
|
promise._data = reason;
|
|
asyncCall(publishRejection, promise);
|
|
}
|
|
}
|
|
function publish(promise) {
|
|
promise._then = promise._then.forEach(invokeCallback);
|
|
}
|
|
function publishFulfillment(promise) {
|
|
promise._state = FULFILLED;
|
|
publish(promise);
|
|
}
|
|
function publishRejection(promise) {
|
|
promise._state = REJECTED;
|
|
publish(promise);
|
|
if (!promise._handled && isNode) {
|
|
global.process.emit("unhandledRejection", promise._data, promise);
|
|
}
|
|
}
|
|
function notifyRejectionHandled(promise) {
|
|
global.process.emit("rejectionHandled", promise);
|
|
}
|
|
function Promise2(resolver) {
|
|
if (typeof resolver !== "function") {
|
|
throw new TypeError("Promise resolver " + resolver + " is not a function");
|
|
}
|
|
if (this instanceof Promise2 === false) {
|
|
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
|
|
}
|
|
this._then = [];
|
|
invokeResolver(resolver, this);
|
|
}
|
|
Promise2.prototype = {
|
|
constructor: Promise2,
|
|
_state: PENDING,
|
|
_then: null,
|
|
_data: void 0,
|
|
_handled: false,
|
|
then: function(onFulfillment, onRejection) {
|
|
var subscriber = {
|
|
owner: this,
|
|
then: new this.constructor(NOOP),
|
|
fulfilled: onFulfillment,
|
|
rejected: onRejection
|
|
};
|
|
if ((onRejection || onFulfillment) && !this._handled) {
|
|
this._handled = true;
|
|
if (this._state === REJECTED && isNode) {
|
|
asyncCall(notifyRejectionHandled, this);
|
|
}
|
|
}
|
|
if (this._state === FULFILLED || this._state === REJECTED) {
|
|
asyncCall(invokeCallback, subscriber);
|
|
} else {
|
|
this._then.push(subscriber);
|
|
}
|
|
return subscriber.then;
|
|
},
|
|
catch: function(onRejection) {
|
|
return this.then(null, onRejection);
|
|
}
|
|
};
|
|
Promise2.all = function(promises) {
|
|
if (!Array.isArray(promises)) {
|
|
throw new TypeError("You must pass an array to Promise.all().");
|
|
}
|
|
return new Promise2(function(resolve2, reject2) {
|
|
var results = [];
|
|
var remaining = 0;
|
|
function resolver(index) {
|
|
remaining++;
|
|
return function(value) {
|
|
results[index] = value;
|
|
if (!--remaining) {
|
|
resolve2(results);
|
|
}
|
|
};
|
|
}
|
|
for (var i = 0, promise; i < promises.length; i++) {
|
|
promise = promises[i];
|
|
if (promise && typeof promise.then === "function") {
|
|
promise.then(resolver(i), reject2);
|
|
} else {
|
|
results[i] = promise;
|
|
}
|
|
}
|
|
if (!remaining) {
|
|
resolve2(results);
|
|
}
|
|
});
|
|
};
|
|
Promise2.race = function(promises) {
|
|
if (!Array.isArray(promises)) {
|
|
throw new TypeError("You must pass an array to Promise.race().");
|
|
}
|
|
return new Promise2(function(resolve2, reject2) {
|
|
for (var i = 0, promise; i < promises.length; i++) {
|
|
promise = promises[i];
|
|
if (promise && typeof promise.then === "function") {
|
|
promise.then(resolve2, reject2);
|
|
} else {
|
|
resolve2(promise);
|
|
}
|
|
}
|
|
});
|
|
};
|
|
Promise2.resolve = function(value) {
|
|
if (value && typeof value === "object" && value.constructor === Promise2) {
|
|
return value;
|
|
}
|
|
return new Promise2(function(resolve2) {
|
|
resolve2(value);
|
|
});
|
|
};
|
|
Promise2.reject = function(reason) {
|
|
return new Promise2(function(resolve2, reject2) {
|
|
reject2(reason);
|
|
});
|
|
};
|
|
module.exports = Promise2;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/pinkie-promise/index.js
|
|
var require_pinkie_promise = __commonJS({
|
|
"../../node_modules/pinkie-promise/index.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = typeof Promise === "function" ? Promise : require_pinkie();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/object-assign/index.js
|
|
var require_object_assign = __commonJS({
|
|
"../../node_modules/object-assign/index.js"(exports, module) {
|
|
"use strict";
|
|
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
function toObject(val) {
|
|
if (val === null || val === void 0) {
|
|
throw new TypeError("Object.assign cannot be called with null or undefined");
|
|
}
|
|
return Object(val);
|
|
}
|
|
function shouldUseNative() {
|
|
try {
|
|
if (!Object.assign) {
|
|
return false;
|
|
}
|
|
var test1 = new String("abc");
|
|
test1[5] = "de";
|
|
if (Object.getOwnPropertyNames(test1)[0] === "5") {
|
|
return false;
|
|
}
|
|
var test2 = {};
|
|
for (var i = 0; i < 10; i++) {
|
|
test2["_" + String.fromCharCode(i)] = i;
|
|
}
|
|
var order2 = Object.getOwnPropertyNames(test2).map(function(n) {
|
|
return test2[n];
|
|
});
|
|
if (order2.join("") !== "0123456789") {
|
|
return false;
|
|
}
|
|
var test3 = {};
|
|
"abcdefghijklmnopqrst".split("").forEach(function(letter) {
|
|
test3[letter] = letter;
|
|
});
|
|
if (Object.keys(Object.assign({}, test3)).join("") !== "abcdefghijklmnopqrst") {
|
|
return false;
|
|
}
|
|
return true;
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
module.exports = shouldUseNative() ? Object.assign : function(target, source) {
|
|
var from;
|
|
var to = toObject(target);
|
|
var symbols;
|
|
for (var s = 1; s < arguments.length; s++) {
|
|
from = Object(arguments[s]);
|
|
for (var key in from) {
|
|
if (hasOwnProperty.call(from, key)) {
|
|
to[key] = from[key];
|
|
}
|
|
}
|
|
if (getOwnPropertySymbols) {
|
|
symbols = getOwnPropertySymbols(from);
|
|
for (var i = 0; i < symbols.length; i++) {
|
|
if (propIsEnumerable.call(from, symbols[i])) {
|
|
to[symbols[i]] = from[symbols[i]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return to;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/get-stream/buffer-stream.js
|
|
var require_buffer_stream = __commonJS({
|
|
"../../node_modules/get-stream/buffer-stream.js"(exports, module) {
|
|
var PassThrough = __require("stream").PassThrough;
|
|
var objectAssign = require_object_assign();
|
|
module.exports = function(opts) {
|
|
opts = objectAssign({}, opts);
|
|
var array = opts.array;
|
|
var encoding = opts.encoding;
|
|
var buffer = encoding === "buffer";
|
|
var objectMode = false;
|
|
if (array) {
|
|
objectMode = !(encoding || buffer);
|
|
} else {
|
|
encoding = encoding || "utf8";
|
|
}
|
|
if (buffer) {
|
|
encoding = null;
|
|
}
|
|
var len = 0;
|
|
var ret = [];
|
|
var stream = new PassThrough({ objectMode });
|
|
if (encoding) {
|
|
stream.setEncoding(encoding);
|
|
}
|
|
stream.on("data", function(chunk) {
|
|
ret.push(chunk);
|
|
if (objectMode) {
|
|
len = ret.length;
|
|
} else {
|
|
len += chunk.length;
|
|
}
|
|
});
|
|
stream.getBufferedValue = function() {
|
|
if (array) {
|
|
return ret;
|
|
}
|
|
return buffer ? Buffer.concat(ret, len) : ret.join("");
|
|
};
|
|
stream.getBufferedLength = function() {
|
|
return len;
|
|
};
|
|
return stream;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/get-stream/index.js
|
|
var require_get_stream = __commonJS({
|
|
"../../node_modules/get-stream/index.js"(exports, module) {
|
|
"use strict";
|
|
var Promise2 = require_pinkie_promise();
|
|
var objectAssign = require_object_assign();
|
|
var bufferStream = require_buffer_stream();
|
|
function getStream(inputStream, opts) {
|
|
if (!inputStream) {
|
|
return Promise2.reject(new Error("Expected a stream"));
|
|
}
|
|
opts = objectAssign({ maxBuffer: Infinity }, opts);
|
|
var maxBuffer = opts.maxBuffer;
|
|
var stream;
|
|
var clean;
|
|
var p = new Promise2(function(resolve, reject) {
|
|
stream = bufferStream(opts);
|
|
inputStream.once("error", error);
|
|
inputStream.pipe(stream);
|
|
stream.on("data", function() {
|
|
if (stream.getBufferedLength() > maxBuffer) {
|
|
reject(new Error("maxBuffer exceeded"));
|
|
}
|
|
});
|
|
stream.once("error", error);
|
|
stream.on("end", resolve);
|
|
clean = function() {
|
|
if (inputStream.unpipe) {
|
|
inputStream.unpipe(stream);
|
|
}
|
|
};
|
|
function error(err) {
|
|
if (err) {
|
|
err.bufferedData = stream.getBufferedValue();
|
|
}
|
|
reject(err);
|
|
}
|
|
});
|
|
p.then(clean, clean);
|
|
return p.then(function() {
|
|
return stream.getBufferedValue();
|
|
});
|
|
}
|
|
module.exports = getStream;
|
|
module.exports.buffer = function(stream, opts) {
|
|
return getStream(stream, objectAssign({}, opts, { encoding: "buffer" }));
|
|
};
|
|
module.exports.array = function(stream, opts) {
|
|
return getStream(stream, objectAssign({}, opts, { array: true }));
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress-unzip/node_modules/pify/index.js
|
|
var require_pify = __commonJS({
|
|
"../../node_modules/decompress-unzip/node_modules/pify/index.js"(exports, module) {
|
|
"use strict";
|
|
var processFn = function(fn, P, opts) {
|
|
return function() {
|
|
var that = this;
|
|
var args = new Array(arguments.length);
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
args[i] = arguments[i];
|
|
}
|
|
return new P(function(resolve, reject) {
|
|
args.push(function(err, result) {
|
|
if (err) {
|
|
reject(err);
|
|
} else if (opts.multiArgs) {
|
|
var results = new Array(arguments.length - 1);
|
|
for (var i2 = 1; i2 < arguments.length; i2++) {
|
|
results[i2 - 1] = arguments[i2];
|
|
}
|
|
resolve(results);
|
|
} else {
|
|
resolve(result);
|
|
}
|
|
});
|
|
fn.apply(that, args);
|
|
});
|
|
};
|
|
};
|
|
var pify = module.exports = function(obj, P, opts) {
|
|
if (typeof P !== "function") {
|
|
opts = P;
|
|
P = Promise;
|
|
}
|
|
opts = opts || {};
|
|
opts.exclude = opts.exclude || [/.+Sync$/];
|
|
var filter = function(key) {
|
|
var match = function(pattern) {
|
|
return typeof pattern === "string" ? key === pattern : pattern.test(key);
|
|
};
|
|
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
|
|
};
|
|
var ret = typeof obj === "function" ? function() {
|
|
if (opts.excludeMain) {
|
|
return obj.apply(this, arguments);
|
|
}
|
|
return processFn(obj, P, opts).apply(this, arguments);
|
|
} : {};
|
|
return Object.keys(obj).reduce(function(ret2, key) {
|
|
var x = obj[key];
|
|
ret2[key] = typeof x === "function" && filter(key) ? processFn(x, P, opts) : x;
|
|
return ret2;
|
|
}, ret);
|
|
};
|
|
pify.all = pify;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/pend/index.js
|
|
var require_pend = __commonJS({
|
|
"../../node_modules/pend/index.js"(exports, module) {
|
|
module.exports = Pend;
|
|
function Pend() {
|
|
this.pending = 0;
|
|
this.max = Infinity;
|
|
this.listeners = [];
|
|
this.waiting = [];
|
|
this.error = null;
|
|
}
|
|
Pend.prototype.go = function(fn) {
|
|
if (this.pending < this.max) {
|
|
pendGo(this, fn);
|
|
} else {
|
|
this.waiting.push(fn);
|
|
}
|
|
};
|
|
Pend.prototype.wait = function(cb) {
|
|
if (this.pending === 0) {
|
|
cb(this.error);
|
|
} else {
|
|
this.listeners.push(cb);
|
|
}
|
|
};
|
|
Pend.prototype.hold = function() {
|
|
return pendHold(this);
|
|
};
|
|
function pendHold(self2) {
|
|
self2.pending += 1;
|
|
var called = false;
|
|
return onCb;
|
|
function onCb(err) {
|
|
if (called) throw new Error("callback called twice");
|
|
called = true;
|
|
self2.error = self2.error || err;
|
|
self2.pending -= 1;
|
|
if (self2.waiting.length > 0 && self2.pending < self2.max) {
|
|
pendGo(self2, self2.waiting.shift());
|
|
} else if (self2.pending === 0) {
|
|
var listeners = self2.listeners;
|
|
self2.listeners = [];
|
|
listeners.forEach(cbListener);
|
|
}
|
|
}
|
|
function cbListener(listener) {
|
|
listener(self2.error);
|
|
}
|
|
}
|
|
function pendGo(self2, fn) {
|
|
fn(pendHold(self2));
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/fd-slicer/index.js
|
|
var require_fd_slicer = __commonJS({
|
|
"../../node_modules/fd-slicer/index.js"(exports) {
|
|
var fs = __require("fs");
|
|
var util = __require("util");
|
|
var stream = __require("stream");
|
|
var Readable = stream.Readable;
|
|
var Writable = stream.Writable;
|
|
var PassThrough = stream.PassThrough;
|
|
var Pend = require_pend();
|
|
var EventEmitter = __require("events").EventEmitter;
|
|
exports.createFromBuffer = createFromBuffer;
|
|
exports.createFromFd = createFromFd;
|
|
exports.BufferSlicer = BufferSlicer;
|
|
exports.FdSlicer = FdSlicer;
|
|
util.inherits(FdSlicer, EventEmitter);
|
|
function FdSlicer(fd, options) {
|
|
options = options || {};
|
|
EventEmitter.call(this);
|
|
this.fd = fd;
|
|
this.pend = new Pend();
|
|
this.pend.max = 1;
|
|
this.refCount = 0;
|
|
this.autoClose = !!options.autoClose;
|
|
}
|
|
FdSlicer.prototype.read = function(buffer, offset, length, position, callback) {
|
|
var self2 = this;
|
|
self2.pend.go(function(cb) {
|
|
fs.read(self2.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) {
|
|
cb();
|
|
callback(err, bytesRead, buffer2);
|
|
});
|
|
});
|
|
};
|
|
FdSlicer.prototype.write = function(buffer, offset, length, position, callback) {
|
|
var self2 = this;
|
|
self2.pend.go(function(cb) {
|
|
fs.write(self2.fd, buffer, offset, length, position, function(err, written, buffer2) {
|
|
cb();
|
|
callback(err, written, buffer2);
|
|
});
|
|
});
|
|
};
|
|
FdSlicer.prototype.createReadStream = function(options) {
|
|
return new ReadStream(this, options);
|
|
};
|
|
FdSlicer.prototype.createWriteStream = function(options) {
|
|
return new WriteStream(this, options);
|
|
};
|
|
FdSlicer.prototype.ref = function() {
|
|
this.refCount += 1;
|
|
};
|
|
FdSlicer.prototype.unref = function() {
|
|
var self2 = this;
|
|
self2.refCount -= 1;
|
|
if (self2.refCount > 0) return;
|
|
if (self2.refCount < 0) throw new Error("invalid unref");
|
|
if (self2.autoClose) {
|
|
fs.close(self2.fd, onCloseDone);
|
|
}
|
|
function onCloseDone(err) {
|
|
if (err) {
|
|
self2.emit("error", err);
|
|
} else {
|
|
self2.emit("close");
|
|
}
|
|
}
|
|
};
|
|
util.inherits(ReadStream, Readable);
|
|
function ReadStream(context, options) {
|
|
options = options || {};
|
|
Readable.call(this, options);
|
|
this.context = context;
|
|
this.context.ref();
|
|
this.start = options.start || 0;
|
|
this.endOffset = options.end;
|
|
this.pos = this.start;
|
|
this.destroyed = false;
|
|
}
|
|
ReadStream.prototype._read = function(n) {
|
|
var self2 = this;
|
|
if (self2.destroyed) return;
|
|
var toRead = Math.min(self2._readableState.highWaterMark, n);
|
|
if (self2.endOffset != null) {
|
|
toRead = Math.min(toRead, self2.endOffset - self2.pos);
|
|
}
|
|
if (toRead <= 0) {
|
|
self2.destroyed = true;
|
|
self2.push(null);
|
|
self2.context.unref();
|
|
return;
|
|
}
|
|
self2.context.pend.go(function(cb) {
|
|
if (self2.destroyed) return cb();
|
|
var buffer = new Buffer(toRead);
|
|
fs.read(self2.context.fd, buffer, 0, toRead, self2.pos, function(err, bytesRead) {
|
|
if (err) {
|
|
self2.destroy(err);
|
|
} else if (bytesRead === 0) {
|
|
self2.destroyed = true;
|
|
self2.push(null);
|
|
self2.context.unref();
|
|
} else {
|
|
self2.pos += bytesRead;
|
|
self2.push(buffer.slice(0, bytesRead));
|
|
}
|
|
cb();
|
|
});
|
|
});
|
|
};
|
|
ReadStream.prototype.destroy = function(err) {
|
|
if (this.destroyed) return;
|
|
err = err || new Error("stream destroyed");
|
|
this.destroyed = true;
|
|
this.emit("error", err);
|
|
this.context.unref();
|
|
};
|
|
util.inherits(WriteStream, Writable);
|
|
function WriteStream(context, options) {
|
|
options = options || {};
|
|
Writable.call(this, options);
|
|
this.context = context;
|
|
this.context.ref();
|
|
this.start = options.start || 0;
|
|
this.endOffset = options.end == null ? Infinity : +options.end;
|
|
this.bytesWritten = 0;
|
|
this.pos = this.start;
|
|
this.destroyed = false;
|
|
this.on("finish", this.destroy.bind(this));
|
|
}
|
|
WriteStream.prototype._write = function(buffer, encoding, callback) {
|
|
var self2 = this;
|
|
if (self2.destroyed) return;
|
|
if (self2.pos + buffer.length > self2.endOffset) {
|
|
var err = new Error("maximum file length exceeded");
|
|
err.code = "ETOOBIG";
|
|
self2.destroy();
|
|
callback(err);
|
|
return;
|
|
}
|
|
self2.context.pend.go(function(cb) {
|
|
if (self2.destroyed) return cb();
|
|
fs.write(self2.context.fd, buffer, 0, buffer.length, self2.pos, function(err2, bytes) {
|
|
if (err2) {
|
|
self2.destroy();
|
|
cb();
|
|
callback(err2);
|
|
} else {
|
|
self2.bytesWritten += bytes;
|
|
self2.pos += bytes;
|
|
self2.emit("progress");
|
|
cb();
|
|
callback();
|
|
}
|
|
});
|
|
});
|
|
};
|
|
WriteStream.prototype.destroy = function() {
|
|
if (this.destroyed) return;
|
|
this.destroyed = true;
|
|
this.context.unref();
|
|
};
|
|
util.inherits(BufferSlicer, EventEmitter);
|
|
function BufferSlicer(buffer, options) {
|
|
EventEmitter.call(this);
|
|
options = options || {};
|
|
this.refCount = 0;
|
|
this.buffer = buffer;
|
|
this.maxChunkSize = options.maxChunkSize || Number.MAX_SAFE_INTEGER;
|
|
}
|
|
BufferSlicer.prototype.read = function(buffer, offset, length, position, callback) {
|
|
var end = position + length;
|
|
var delta = end - this.buffer.length;
|
|
var written = delta > 0 ? delta : length;
|
|
this.buffer.copy(buffer, offset, position, end);
|
|
setImmediate(function() {
|
|
callback(null, written);
|
|
});
|
|
};
|
|
BufferSlicer.prototype.write = function(buffer, offset, length, position, callback) {
|
|
buffer.copy(this.buffer, position, offset, offset + length);
|
|
setImmediate(function() {
|
|
callback(null, length, buffer);
|
|
});
|
|
};
|
|
BufferSlicer.prototype.createReadStream = function(options) {
|
|
options = options || {};
|
|
var readStream = new PassThrough(options);
|
|
readStream.destroyed = false;
|
|
readStream.start = options.start || 0;
|
|
readStream.endOffset = options.end;
|
|
readStream.pos = readStream.endOffset || this.buffer.length;
|
|
var entireSlice = this.buffer.slice(readStream.start, readStream.pos);
|
|
var offset = 0;
|
|
while (true) {
|
|
var nextOffset = offset + this.maxChunkSize;
|
|
if (nextOffset >= entireSlice.length) {
|
|
if (offset < entireSlice.length) {
|
|
readStream.write(entireSlice.slice(offset, entireSlice.length));
|
|
}
|
|
break;
|
|
}
|
|
readStream.write(entireSlice.slice(offset, nextOffset));
|
|
offset = nextOffset;
|
|
}
|
|
readStream.end();
|
|
readStream.destroy = function() {
|
|
readStream.destroyed = true;
|
|
};
|
|
return readStream;
|
|
};
|
|
BufferSlicer.prototype.createWriteStream = function(options) {
|
|
var bufferSlicer = this;
|
|
options = options || {};
|
|
var writeStream = new Writable(options);
|
|
writeStream.start = options.start || 0;
|
|
writeStream.endOffset = options.end == null ? this.buffer.length : +options.end;
|
|
writeStream.bytesWritten = 0;
|
|
writeStream.pos = writeStream.start;
|
|
writeStream.destroyed = false;
|
|
writeStream._write = function(buffer, encoding, callback) {
|
|
if (writeStream.destroyed) return;
|
|
var end = writeStream.pos + buffer.length;
|
|
if (end > writeStream.endOffset) {
|
|
var err = new Error("maximum file length exceeded");
|
|
err.code = "ETOOBIG";
|
|
writeStream.destroyed = true;
|
|
callback(err);
|
|
return;
|
|
}
|
|
buffer.copy(bufferSlicer.buffer, writeStream.pos, 0, buffer.length);
|
|
writeStream.bytesWritten += buffer.length;
|
|
writeStream.pos = end;
|
|
writeStream.emit("progress");
|
|
callback();
|
|
};
|
|
writeStream.destroy = function() {
|
|
writeStream.destroyed = true;
|
|
};
|
|
return writeStream;
|
|
};
|
|
BufferSlicer.prototype.ref = function() {
|
|
this.refCount += 1;
|
|
};
|
|
BufferSlicer.prototype.unref = function() {
|
|
this.refCount -= 1;
|
|
if (this.refCount < 0) {
|
|
throw new Error("invalid unref");
|
|
}
|
|
};
|
|
function createFromBuffer(buffer, options) {
|
|
return new BufferSlicer(buffer, options);
|
|
}
|
|
function createFromFd(fd, options) {
|
|
return new FdSlicer(fd, options);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/buffer-crc32/index.js
|
|
var require_buffer_crc32 = __commonJS({
|
|
"../../node_modules/buffer-crc32/index.js"(exports, module) {
|
|
var Buffer2 = __require("buffer").Buffer;
|
|
var CRC_TABLE = [
|
|
0,
|
|
1996959894,
|
|
3993919788,
|
|
2567524794,
|
|
124634137,
|
|
1886057615,
|
|
3915621685,
|
|
2657392035,
|
|
249268274,
|
|
2044508324,
|
|
3772115230,
|
|
2547177864,
|
|
162941995,
|
|
2125561021,
|
|
3887607047,
|
|
2428444049,
|
|
498536548,
|
|
1789927666,
|
|
4089016648,
|
|
2227061214,
|
|
450548861,
|
|
1843258603,
|
|
4107580753,
|
|
2211677639,
|
|
325883990,
|
|
1684777152,
|
|
4251122042,
|
|
2321926636,
|
|
335633487,
|
|
1661365465,
|
|
4195302755,
|
|
2366115317,
|
|
997073096,
|
|
1281953886,
|
|
3579855332,
|
|
2724688242,
|
|
1006888145,
|
|
1258607687,
|
|
3524101629,
|
|
2768942443,
|
|
901097722,
|
|
1119000684,
|
|
3686517206,
|
|
2898065728,
|
|
853044451,
|
|
1172266101,
|
|
3705015759,
|
|
2882616665,
|
|
651767980,
|
|
1373503546,
|
|
3369554304,
|
|
3218104598,
|
|
565507253,
|
|
1454621731,
|
|
3485111705,
|
|
3099436303,
|
|
671266974,
|
|
1594198024,
|
|
3322730930,
|
|
2970347812,
|
|
795835527,
|
|
1483230225,
|
|
3244367275,
|
|
3060149565,
|
|
1994146192,
|
|
31158534,
|
|
2563907772,
|
|
4023717930,
|
|
1907459465,
|
|
112637215,
|
|
2680153253,
|
|
3904427059,
|
|
2013776290,
|
|
251722036,
|
|
2517215374,
|
|
3775830040,
|
|
2137656763,
|
|
141376813,
|
|
2439277719,
|
|
3865271297,
|
|
1802195444,
|
|
476864866,
|
|
2238001368,
|
|
4066508878,
|
|
1812370925,
|
|
453092731,
|
|
2181625025,
|
|
4111451223,
|
|
1706088902,
|
|
314042704,
|
|
2344532202,
|
|
4240017532,
|
|
1658658271,
|
|
366619977,
|
|
2362670323,
|
|
4224994405,
|
|
1303535960,
|
|
984961486,
|
|
2747007092,
|
|
3569037538,
|
|
1256170817,
|
|
1037604311,
|
|
2765210733,
|
|
3554079995,
|
|
1131014506,
|
|
879679996,
|
|
2909243462,
|
|
3663771856,
|
|
1141124467,
|
|
855842277,
|
|
2852801631,
|
|
3708648649,
|
|
1342533948,
|
|
654459306,
|
|
3188396048,
|
|
3373015174,
|
|
1466479909,
|
|
544179635,
|
|
3110523913,
|
|
3462522015,
|
|
1591671054,
|
|
702138776,
|
|
2966460450,
|
|
3352799412,
|
|
1504918807,
|
|
783551873,
|
|
3082640443,
|
|
3233442989,
|
|
3988292384,
|
|
2596254646,
|
|
62317068,
|
|
1957810842,
|
|
3939845945,
|
|
2647816111,
|
|
81470997,
|
|
1943803523,
|
|
3814918930,
|
|
2489596804,
|
|
225274430,
|
|
2053790376,
|
|
3826175755,
|
|
2466906013,
|
|
167816743,
|
|
2097651377,
|
|
4027552580,
|
|
2265490386,
|
|
503444072,
|
|
1762050814,
|
|
4150417245,
|
|
2154129355,
|
|
426522225,
|
|
1852507879,
|
|
4275313526,
|
|
2312317920,
|
|
282753626,
|
|
1742555852,
|
|
4189708143,
|
|
2394877945,
|
|
397917763,
|
|
1622183637,
|
|
3604390888,
|
|
2714866558,
|
|
953729732,
|
|
1340076626,
|
|
3518719985,
|
|
2797360999,
|
|
1068828381,
|
|
1219638859,
|
|
3624741850,
|
|
2936675148,
|
|
906185462,
|
|
1090812512,
|
|
3747672003,
|
|
2825379669,
|
|
829329135,
|
|
1181335161,
|
|
3412177804,
|
|
3160834842,
|
|
628085408,
|
|
1382605366,
|
|
3423369109,
|
|
3138078467,
|
|
570562233,
|
|
1426400815,
|
|
3317316542,
|
|
2998733608,
|
|
733239954,
|
|
1555261956,
|
|
3268935591,
|
|
3050360625,
|
|
752459403,
|
|
1541320221,
|
|
2607071920,
|
|
3965973030,
|
|
1969922972,
|
|
40735498,
|
|
2617837225,
|
|
3943577151,
|
|
1913087877,
|
|
83908371,
|
|
2512341634,
|
|
3803740692,
|
|
2075208622,
|
|
213261112,
|
|
2463272603,
|
|
3855990285,
|
|
2094854071,
|
|
198958881,
|
|
2262029012,
|
|
4057260610,
|
|
1759359992,
|
|
534414190,
|
|
2176718541,
|
|
4139329115,
|
|
1873836001,
|
|
414664567,
|
|
2282248934,
|
|
4279200368,
|
|
1711684554,
|
|
285281116,
|
|
2405801727,
|
|
4167216745,
|
|
1634467795,
|
|
376229701,
|
|
2685067896,
|
|
3608007406,
|
|
1308918612,
|
|
956543938,
|
|
2808555105,
|
|
3495958263,
|
|
1231636301,
|
|
1047427035,
|
|
2932959818,
|
|
3654703836,
|
|
1088359270,
|
|
936918e3,
|
|
2847714899,
|
|
3736837829,
|
|
1202900863,
|
|
817233897,
|
|
3183342108,
|
|
3401237130,
|
|
1404277552,
|
|
615818150,
|
|
3134207493,
|
|
3453421203,
|
|
1423857449,
|
|
601450431,
|
|
3009837614,
|
|
3294710456,
|
|
1567103746,
|
|
711928724,
|
|
3020668471,
|
|
3272380065,
|
|
1510334235,
|
|
755167117
|
|
];
|
|
if (typeof Int32Array !== "undefined") {
|
|
CRC_TABLE = new Int32Array(CRC_TABLE);
|
|
}
|
|
function ensureBuffer(input) {
|
|
if (Buffer2.isBuffer(input)) {
|
|
return input;
|
|
}
|
|
var hasNewBufferAPI = typeof Buffer2.alloc === "function" && typeof Buffer2.from === "function";
|
|
if (typeof input === "number") {
|
|
return hasNewBufferAPI ? Buffer2.alloc(input) : new Buffer2(input);
|
|
} else if (typeof input === "string") {
|
|
return hasNewBufferAPI ? Buffer2.from(input) : new Buffer2(input);
|
|
} else {
|
|
throw new Error("input must be buffer, number, or string, received " + typeof input);
|
|
}
|
|
}
|
|
function bufferizeInt(num) {
|
|
var tmp = ensureBuffer(4);
|
|
tmp.writeInt32BE(num, 0);
|
|
return tmp;
|
|
}
|
|
function _crc32(buf, previous) {
|
|
buf = ensureBuffer(buf);
|
|
if (Buffer2.isBuffer(previous)) {
|
|
previous = previous.readUInt32BE(0);
|
|
}
|
|
var crc = ~~previous ^ -1;
|
|
for (var n = 0; n < buf.length; n++) {
|
|
crc = CRC_TABLE[(crc ^ buf[n]) & 255] ^ crc >>> 8;
|
|
}
|
|
return crc ^ -1;
|
|
}
|
|
function crc32() {
|
|
return bufferizeInt(_crc32.apply(null, arguments));
|
|
}
|
|
crc32.signed = function() {
|
|
return _crc32.apply(null, arguments);
|
|
};
|
|
crc32.unsigned = function() {
|
|
return _crc32.apply(null, arguments) >>> 0;
|
|
};
|
|
module.exports = crc32;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/yauzl/index.js
|
|
var require_yauzl = __commonJS({
|
|
"../../node_modules/yauzl/index.js"(exports) {
|
|
var fs = __require("fs");
|
|
var zlib = __require("zlib");
|
|
var fd_slicer = require_fd_slicer();
|
|
var crc32 = require_buffer_crc32();
|
|
var util = __require("util");
|
|
var EventEmitter = __require("events").EventEmitter;
|
|
var Transform = __require("stream").Transform;
|
|
var PassThrough = __require("stream").PassThrough;
|
|
var Writable = __require("stream").Writable;
|
|
exports.open = open;
|
|
exports.fromFd = fromFd;
|
|
exports.fromBuffer = fromBuffer;
|
|
exports.fromRandomAccessReader = fromRandomAccessReader;
|
|
exports.dosDateTimeToDate = dosDateTimeToDate;
|
|
exports.validateFileName = validateFileName;
|
|
exports.ZipFile = ZipFile;
|
|
exports.Entry = Entry;
|
|
exports.RandomAccessReader = RandomAccessReader;
|
|
function open(path, options, callback) {
|
|
if (typeof options === "function") {
|
|
callback = options;
|
|
options = null;
|
|
}
|
|
if (options == null) options = {};
|
|
if (options.autoClose == null) options.autoClose = true;
|
|
if (options.lazyEntries == null) options.lazyEntries = false;
|
|
if (options.decodeStrings == null) options.decodeStrings = true;
|
|
if (options.validateEntrySizes == null) options.validateEntrySizes = true;
|
|
if (options.strictFileNames == null) options.strictFileNames = false;
|
|
if (callback == null) callback = defaultCallback;
|
|
fs.open(path, "r", function(err, fd) {
|
|
if (err) return callback(err);
|
|
fromFd(fd, options, function(err2, zipfile) {
|
|
if (err2) fs.close(fd, defaultCallback);
|
|
callback(err2, zipfile);
|
|
});
|
|
});
|
|
}
|
|
function fromFd(fd, options, callback) {
|
|
if (typeof options === "function") {
|
|
callback = options;
|
|
options = null;
|
|
}
|
|
if (options == null) options = {};
|
|
if (options.autoClose == null) options.autoClose = false;
|
|
if (options.lazyEntries == null) options.lazyEntries = false;
|
|
if (options.decodeStrings == null) options.decodeStrings = true;
|
|
if (options.validateEntrySizes == null) options.validateEntrySizes = true;
|
|
if (options.strictFileNames == null) options.strictFileNames = false;
|
|
if (callback == null) callback = defaultCallback;
|
|
fs.fstat(fd, function(err, stats) {
|
|
if (err) return callback(err);
|
|
var reader = fd_slicer.createFromFd(fd, { autoClose: true });
|
|
fromRandomAccessReader(reader, stats.size, options, callback);
|
|
});
|
|
}
|
|
function fromBuffer(buffer, options, callback) {
|
|
if (typeof options === "function") {
|
|
callback = options;
|
|
options = null;
|
|
}
|
|
if (options == null) options = {};
|
|
options.autoClose = false;
|
|
if (options.lazyEntries == null) options.lazyEntries = false;
|
|
if (options.decodeStrings == null) options.decodeStrings = true;
|
|
if (options.validateEntrySizes == null) options.validateEntrySizes = true;
|
|
if (options.strictFileNames == null) options.strictFileNames = false;
|
|
var reader = fd_slicer.createFromBuffer(buffer, { maxChunkSize: 65536 });
|
|
fromRandomAccessReader(reader, buffer.length, options, callback);
|
|
}
|
|
function fromRandomAccessReader(reader, totalSize, options, callback) {
|
|
if (typeof options === "function") {
|
|
callback = options;
|
|
options = null;
|
|
}
|
|
if (options == null) options = {};
|
|
if (options.autoClose == null) options.autoClose = true;
|
|
if (options.lazyEntries == null) options.lazyEntries = false;
|
|
if (options.decodeStrings == null) options.decodeStrings = true;
|
|
var decodeStrings = !!options.decodeStrings;
|
|
if (options.validateEntrySizes == null) options.validateEntrySizes = true;
|
|
if (options.strictFileNames == null) options.strictFileNames = false;
|
|
if (callback == null) callback = defaultCallback;
|
|
if (typeof totalSize !== "number") throw new Error("expected totalSize parameter to be a number");
|
|
if (totalSize > Number.MAX_SAFE_INTEGER) {
|
|
throw new Error("zip file too large. only file sizes up to 2^52 are supported due to JavaScript's Number type being an IEEE 754 double.");
|
|
}
|
|
reader.ref();
|
|
var eocdrWithoutCommentSize = 22;
|
|
var maxCommentSize = 65535;
|
|
var bufferSize = Math.min(eocdrWithoutCommentSize + maxCommentSize, totalSize);
|
|
var buffer = newBuffer(bufferSize);
|
|
var bufferReadStart = totalSize - buffer.length;
|
|
readAndAssertNoEof(reader, buffer, 0, bufferSize, bufferReadStart, function(err) {
|
|
if (err) return callback(err);
|
|
for (var i = bufferSize - eocdrWithoutCommentSize; i >= 0; i -= 1) {
|
|
if (buffer.readUInt32LE(i) !== 101010256) continue;
|
|
var eocdrBuffer = buffer.slice(i);
|
|
var diskNumber = eocdrBuffer.readUInt16LE(4);
|
|
if (diskNumber !== 0) {
|
|
return callback(new Error("multi-disk zip files are not supported: found disk number: " + diskNumber));
|
|
}
|
|
var entryCount = eocdrBuffer.readUInt16LE(10);
|
|
var centralDirectoryOffset = eocdrBuffer.readUInt32LE(16);
|
|
var commentLength = eocdrBuffer.readUInt16LE(20);
|
|
var expectedCommentLength = eocdrBuffer.length - eocdrWithoutCommentSize;
|
|
if (commentLength !== expectedCommentLength) {
|
|
return callback(new Error("invalid comment length. expected: " + expectedCommentLength + ". found: " + commentLength));
|
|
}
|
|
var comment = decodeStrings ? decodeBuffer(eocdrBuffer, 22, eocdrBuffer.length, false) : eocdrBuffer.slice(22);
|
|
if (!(entryCount === 65535 || centralDirectoryOffset === 4294967295)) {
|
|
return callback(null, new ZipFile(reader, centralDirectoryOffset, totalSize, entryCount, comment, options.autoClose, options.lazyEntries, decodeStrings, options.validateEntrySizes, options.strictFileNames));
|
|
}
|
|
var zip64EocdlBuffer = newBuffer(20);
|
|
var zip64EocdlOffset = bufferReadStart + i - zip64EocdlBuffer.length;
|
|
readAndAssertNoEof(reader, zip64EocdlBuffer, 0, zip64EocdlBuffer.length, zip64EocdlOffset, function(err2) {
|
|
if (err2) return callback(err2);
|
|
if (zip64EocdlBuffer.readUInt32LE(0) !== 117853008) {
|
|
return callback(new Error("invalid zip64 end of central directory locator signature"));
|
|
}
|
|
var zip64EocdrOffset = readUInt64LE(zip64EocdlBuffer, 8);
|
|
var zip64EocdrBuffer = newBuffer(56);
|
|
readAndAssertNoEof(reader, zip64EocdrBuffer, 0, zip64EocdrBuffer.length, zip64EocdrOffset, function(err3) {
|
|
if (err3) return callback(err3);
|
|
if (zip64EocdrBuffer.readUInt32LE(0) !== 101075792) {
|
|
return callback(new Error("invalid zip64 end of central directory record signature"));
|
|
}
|
|
entryCount = readUInt64LE(zip64EocdrBuffer, 32);
|
|
centralDirectoryOffset = readUInt64LE(zip64EocdrBuffer, 48);
|
|
return callback(null, new ZipFile(reader, centralDirectoryOffset, totalSize, entryCount, comment, options.autoClose, options.lazyEntries, decodeStrings, options.validateEntrySizes, options.strictFileNames));
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
callback(new Error("end of central directory record signature not found"));
|
|
});
|
|
}
|
|
util.inherits(ZipFile, EventEmitter);
|
|
function ZipFile(reader, centralDirectoryOffset, fileSize, entryCount, comment, autoClose, lazyEntries, decodeStrings, validateEntrySizes, strictFileNames) {
|
|
var self2 = this;
|
|
EventEmitter.call(self2);
|
|
self2.reader = reader;
|
|
self2.reader.on("error", function(err) {
|
|
emitError(self2, err);
|
|
});
|
|
self2.reader.once("close", function() {
|
|
self2.emit("close");
|
|
});
|
|
self2.readEntryCursor = centralDirectoryOffset;
|
|
self2.fileSize = fileSize;
|
|
self2.entryCount = entryCount;
|
|
self2.comment = comment;
|
|
self2.entriesRead = 0;
|
|
self2.autoClose = !!autoClose;
|
|
self2.lazyEntries = !!lazyEntries;
|
|
self2.decodeStrings = !!decodeStrings;
|
|
self2.validateEntrySizes = !!validateEntrySizes;
|
|
self2.strictFileNames = !!strictFileNames;
|
|
self2.isOpen = true;
|
|
self2.emittedError = false;
|
|
if (!self2.lazyEntries) self2._readEntry();
|
|
}
|
|
ZipFile.prototype.close = function() {
|
|
if (!this.isOpen) return;
|
|
this.isOpen = false;
|
|
this.reader.unref();
|
|
};
|
|
function emitErrorAndAutoClose(self2, err) {
|
|
if (self2.autoClose) self2.close();
|
|
emitError(self2, err);
|
|
}
|
|
function emitError(self2, err) {
|
|
if (self2.emittedError) return;
|
|
self2.emittedError = true;
|
|
self2.emit("error", err);
|
|
}
|
|
ZipFile.prototype.readEntry = function() {
|
|
if (!this.lazyEntries) throw new Error("readEntry() called without lazyEntries:true");
|
|
this._readEntry();
|
|
};
|
|
ZipFile.prototype._readEntry = function() {
|
|
var self2 = this;
|
|
if (self2.entryCount === self2.entriesRead) {
|
|
setImmediate(function() {
|
|
if (self2.autoClose) self2.close();
|
|
if (self2.emittedError) return;
|
|
self2.emit("end");
|
|
});
|
|
return;
|
|
}
|
|
if (self2.emittedError) return;
|
|
var buffer = newBuffer(46);
|
|
readAndAssertNoEof(self2.reader, buffer, 0, buffer.length, self2.readEntryCursor, function(err) {
|
|
if (err) return emitErrorAndAutoClose(self2, err);
|
|
if (self2.emittedError) return;
|
|
var entry = new Entry();
|
|
var signature = buffer.readUInt32LE(0);
|
|
if (signature !== 33639248) return emitErrorAndAutoClose(self2, new Error("invalid central directory file header signature: 0x" + signature.toString(16)));
|
|
entry.versionMadeBy = buffer.readUInt16LE(4);
|
|
entry.versionNeededToExtract = buffer.readUInt16LE(6);
|
|
entry.generalPurposeBitFlag = buffer.readUInt16LE(8);
|
|
entry.compressionMethod = buffer.readUInt16LE(10);
|
|
entry.lastModFileTime = buffer.readUInt16LE(12);
|
|
entry.lastModFileDate = buffer.readUInt16LE(14);
|
|
entry.crc32 = buffer.readUInt32LE(16);
|
|
entry.compressedSize = buffer.readUInt32LE(20);
|
|
entry.uncompressedSize = buffer.readUInt32LE(24);
|
|
entry.fileNameLength = buffer.readUInt16LE(28);
|
|
entry.extraFieldLength = buffer.readUInt16LE(30);
|
|
entry.fileCommentLength = buffer.readUInt16LE(32);
|
|
entry.internalFileAttributes = buffer.readUInt16LE(36);
|
|
entry.externalFileAttributes = buffer.readUInt32LE(38);
|
|
entry.relativeOffsetOfLocalHeader = buffer.readUInt32LE(42);
|
|
if (entry.generalPurposeBitFlag & 64) return emitErrorAndAutoClose(self2, new Error("strong encryption is not supported"));
|
|
self2.readEntryCursor += 46;
|
|
buffer = newBuffer(entry.fileNameLength + entry.extraFieldLength + entry.fileCommentLength);
|
|
readAndAssertNoEof(self2.reader, buffer, 0, buffer.length, self2.readEntryCursor, function(err2) {
|
|
if (err2) return emitErrorAndAutoClose(self2, err2);
|
|
if (self2.emittedError) return;
|
|
var isUtf8 = (entry.generalPurposeBitFlag & 2048) !== 0;
|
|
entry.fileName = self2.decodeStrings ? decodeBuffer(buffer, 0, entry.fileNameLength, isUtf8) : buffer.slice(0, entry.fileNameLength);
|
|
var fileCommentStart = entry.fileNameLength + entry.extraFieldLength;
|
|
var extraFieldBuffer = buffer.slice(entry.fileNameLength, fileCommentStart);
|
|
entry.extraFields = [];
|
|
var i = 0;
|
|
while (i < extraFieldBuffer.length - 3) {
|
|
var headerId = extraFieldBuffer.readUInt16LE(i + 0);
|
|
var dataSize = extraFieldBuffer.readUInt16LE(i + 2);
|
|
var dataStart = i + 4;
|
|
var dataEnd = dataStart + dataSize;
|
|
if (dataEnd > extraFieldBuffer.length) return emitErrorAndAutoClose(self2, new Error("extra field length exceeds extra field buffer size"));
|
|
var dataBuffer = newBuffer(dataSize);
|
|
extraFieldBuffer.copy(dataBuffer, 0, dataStart, dataEnd);
|
|
entry.extraFields.push({
|
|
id: headerId,
|
|
data: dataBuffer
|
|
});
|
|
i = dataEnd;
|
|
}
|
|
entry.fileComment = self2.decodeStrings ? decodeBuffer(buffer, fileCommentStart, fileCommentStart + entry.fileCommentLength, isUtf8) : buffer.slice(fileCommentStart, fileCommentStart + entry.fileCommentLength);
|
|
entry.comment = entry.fileComment;
|
|
self2.readEntryCursor += buffer.length;
|
|
self2.entriesRead += 1;
|
|
if (entry.uncompressedSize === 4294967295 || entry.compressedSize === 4294967295 || entry.relativeOffsetOfLocalHeader === 4294967295) {
|
|
var zip64EiefBuffer = null;
|
|
for (var i = 0; i < entry.extraFields.length; i++) {
|
|
var extraField = entry.extraFields[i];
|
|
if (extraField.id === 1) {
|
|
zip64EiefBuffer = extraField.data;
|
|
break;
|
|
}
|
|
}
|
|
if (zip64EiefBuffer == null) {
|
|
return emitErrorAndAutoClose(self2, new Error("expected zip64 extended information extra field"));
|
|
}
|
|
var index = 0;
|
|
if (entry.uncompressedSize === 4294967295) {
|
|
if (index + 8 > zip64EiefBuffer.length) {
|
|
return emitErrorAndAutoClose(self2, new Error("zip64 extended information extra field does not include uncompressed size"));
|
|
}
|
|
entry.uncompressedSize = readUInt64LE(zip64EiefBuffer, index);
|
|
index += 8;
|
|
}
|
|
if (entry.compressedSize === 4294967295) {
|
|
if (index + 8 > zip64EiefBuffer.length) {
|
|
return emitErrorAndAutoClose(self2, new Error("zip64 extended information extra field does not include compressed size"));
|
|
}
|
|
entry.compressedSize = readUInt64LE(zip64EiefBuffer, index);
|
|
index += 8;
|
|
}
|
|
if (entry.relativeOffsetOfLocalHeader === 4294967295) {
|
|
if (index + 8 > zip64EiefBuffer.length) {
|
|
return emitErrorAndAutoClose(self2, new Error("zip64 extended information extra field does not include relative header offset"));
|
|
}
|
|
entry.relativeOffsetOfLocalHeader = readUInt64LE(zip64EiefBuffer, index);
|
|
index += 8;
|
|
}
|
|
}
|
|
if (self2.decodeStrings) {
|
|
for (var i = 0; i < entry.extraFields.length; i++) {
|
|
var extraField = entry.extraFields[i];
|
|
if (extraField.id === 28789) {
|
|
if (extraField.data.length < 6) {
|
|
continue;
|
|
}
|
|
if (extraField.data.readUInt8(0) !== 1) {
|
|
continue;
|
|
}
|
|
var oldNameCrc32 = extraField.data.readUInt32LE(1);
|
|
if (crc32.unsigned(buffer.slice(0, entry.fileNameLength)) !== oldNameCrc32) {
|
|
continue;
|
|
}
|
|
entry.fileName = decodeBuffer(extraField.data, 5, extraField.data.length, true);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (self2.validateEntrySizes && entry.compressionMethod === 0) {
|
|
var expectedCompressedSize = entry.uncompressedSize;
|
|
if (entry.isEncrypted()) {
|
|
expectedCompressedSize += 12;
|
|
}
|
|
if (entry.compressedSize !== expectedCompressedSize) {
|
|
var msg = "compressed/uncompressed size mismatch for stored file: " + entry.compressedSize + " != " + entry.uncompressedSize;
|
|
return emitErrorAndAutoClose(self2, new Error(msg));
|
|
}
|
|
}
|
|
if (self2.decodeStrings) {
|
|
if (!self2.strictFileNames) {
|
|
entry.fileName = entry.fileName.replace(/\\/g, "/");
|
|
}
|
|
var errorMessage = validateFileName(entry.fileName, self2.validateFileNameOptions);
|
|
if (errorMessage != null) return emitErrorAndAutoClose(self2, new Error(errorMessage));
|
|
}
|
|
self2.emit("entry", entry);
|
|
if (!self2.lazyEntries) self2._readEntry();
|
|
});
|
|
});
|
|
};
|
|
ZipFile.prototype.openReadStream = function(entry, options, callback) {
|
|
var self2 = this;
|
|
var relativeStart = 0;
|
|
var relativeEnd = entry.compressedSize;
|
|
if (callback == null) {
|
|
callback = options;
|
|
options = {};
|
|
} else {
|
|
if (options.decrypt != null) {
|
|
if (!entry.isEncrypted()) {
|
|
throw new Error("options.decrypt can only be specified for encrypted entries");
|
|
}
|
|
if (options.decrypt !== false) throw new Error("invalid options.decrypt value: " + options.decrypt);
|
|
if (entry.isCompressed()) {
|
|
if (options.decompress !== false) throw new Error("entry is encrypted and compressed, and options.decompress !== false");
|
|
}
|
|
}
|
|
if (options.decompress != null) {
|
|
if (!entry.isCompressed()) {
|
|
throw new Error("options.decompress can only be specified for compressed entries");
|
|
}
|
|
if (!(options.decompress === false || options.decompress === true)) {
|
|
throw new Error("invalid options.decompress value: " + options.decompress);
|
|
}
|
|
}
|
|
if (options.start != null || options.end != null) {
|
|
if (entry.isCompressed() && options.decompress !== false) {
|
|
throw new Error("start/end range not allowed for compressed entry without options.decompress === false");
|
|
}
|
|
if (entry.isEncrypted() && options.decrypt !== false) {
|
|
throw new Error("start/end range not allowed for encrypted entry without options.decrypt === false");
|
|
}
|
|
}
|
|
if (options.start != null) {
|
|
relativeStart = options.start;
|
|
if (relativeStart < 0) throw new Error("options.start < 0");
|
|
if (relativeStart > entry.compressedSize) throw new Error("options.start > entry.compressedSize");
|
|
}
|
|
if (options.end != null) {
|
|
relativeEnd = options.end;
|
|
if (relativeEnd < 0) throw new Error("options.end < 0");
|
|
if (relativeEnd > entry.compressedSize) throw new Error("options.end > entry.compressedSize");
|
|
if (relativeEnd < relativeStart) throw new Error("options.end < options.start");
|
|
}
|
|
}
|
|
if (!self2.isOpen) return callback(new Error("closed"));
|
|
if (entry.isEncrypted()) {
|
|
if (options.decrypt !== false) return callback(new Error("entry is encrypted, and options.decrypt !== false"));
|
|
}
|
|
self2.reader.ref();
|
|
var buffer = newBuffer(30);
|
|
readAndAssertNoEof(self2.reader, buffer, 0, buffer.length, entry.relativeOffsetOfLocalHeader, function(err) {
|
|
try {
|
|
if (err) return callback(err);
|
|
var signature = buffer.readUInt32LE(0);
|
|
if (signature !== 67324752) {
|
|
return callback(new Error("invalid local file header signature: 0x" + signature.toString(16)));
|
|
}
|
|
var fileNameLength = buffer.readUInt16LE(26);
|
|
var extraFieldLength = buffer.readUInt16LE(28);
|
|
var localFileHeaderEnd = entry.relativeOffsetOfLocalHeader + buffer.length + fileNameLength + extraFieldLength;
|
|
var decompress;
|
|
if (entry.compressionMethod === 0) {
|
|
decompress = false;
|
|
} else if (entry.compressionMethod === 8) {
|
|
decompress = options.decompress != null ? options.decompress : true;
|
|
} else {
|
|
return callback(new Error("unsupported compression method: " + entry.compressionMethod));
|
|
}
|
|
var fileDataStart = localFileHeaderEnd;
|
|
var fileDataEnd = fileDataStart + entry.compressedSize;
|
|
if (entry.compressedSize !== 0) {
|
|
if (fileDataEnd > self2.fileSize) {
|
|
return callback(new Error("file data overflows file bounds: " + fileDataStart + " + " + entry.compressedSize + " > " + self2.fileSize));
|
|
}
|
|
}
|
|
var readStream = self2.reader.createReadStream({
|
|
start: fileDataStart + relativeStart,
|
|
end: fileDataStart + relativeEnd
|
|
});
|
|
var endpointStream = readStream;
|
|
if (decompress) {
|
|
var destroyed = false;
|
|
var inflateFilter = zlib.createInflateRaw();
|
|
readStream.on("error", function(err2) {
|
|
setImmediate(function() {
|
|
if (!destroyed) inflateFilter.emit("error", err2);
|
|
});
|
|
});
|
|
readStream.pipe(inflateFilter);
|
|
if (self2.validateEntrySizes) {
|
|
endpointStream = new AssertByteCountStream(entry.uncompressedSize);
|
|
inflateFilter.on("error", function(err2) {
|
|
setImmediate(function() {
|
|
if (!destroyed) endpointStream.emit("error", err2);
|
|
});
|
|
});
|
|
inflateFilter.pipe(endpointStream);
|
|
} else {
|
|
endpointStream = inflateFilter;
|
|
}
|
|
endpointStream.destroy = function() {
|
|
destroyed = true;
|
|
if (inflateFilter !== endpointStream) inflateFilter.unpipe(endpointStream);
|
|
readStream.unpipe(inflateFilter);
|
|
readStream.destroy();
|
|
};
|
|
}
|
|
callback(null, endpointStream);
|
|
} finally {
|
|
self2.reader.unref();
|
|
}
|
|
});
|
|
};
|
|
function Entry() {
|
|
}
|
|
Entry.prototype.getLastModDate = function() {
|
|
return dosDateTimeToDate(this.lastModFileDate, this.lastModFileTime);
|
|
};
|
|
Entry.prototype.isEncrypted = function() {
|
|
return (this.generalPurposeBitFlag & 1) !== 0;
|
|
};
|
|
Entry.prototype.isCompressed = function() {
|
|
return this.compressionMethod === 8;
|
|
};
|
|
function dosDateTimeToDate(date, time) {
|
|
var day = date & 31;
|
|
var month = (date >> 5 & 15) - 1;
|
|
var year = (date >> 9 & 127) + 1980;
|
|
var millisecond = 0;
|
|
var second = (time & 31) * 2;
|
|
var minute = time >> 5 & 63;
|
|
var hour = time >> 11 & 31;
|
|
return new Date(year, month, day, hour, minute, second, millisecond);
|
|
}
|
|
function validateFileName(fileName) {
|
|
if (fileName.indexOf("\\") !== -1) {
|
|
return "invalid characters in fileName: " + fileName;
|
|
}
|
|
if (/^[a-zA-Z]:/.test(fileName) || /^\//.test(fileName)) {
|
|
return "absolute path: " + fileName;
|
|
}
|
|
if (fileName.split("/").indexOf("..") !== -1) {
|
|
return "invalid relative path: " + fileName;
|
|
}
|
|
return null;
|
|
}
|
|
function readAndAssertNoEof(reader, buffer, offset, length, position, callback) {
|
|
if (length === 0) {
|
|
return setImmediate(function() {
|
|
callback(null, newBuffer(0));
|
|
});
|
|
}
|
|
reader.read(buffer, offset, length, position, function(err, bytesRead) {
|
|
if (err) return callback(err);
|
|
if (bytesRead < length) {
|
|
return callback(new Error("unexpected EOF"));
|
|
}
|
|
callback();
|
|
});
|
|
}
|
|
util.inherits(AssertByteCountStream, Transform);
|
|
function AssertByteCountStream(byteCount) {
|
|
Transform.call(this);
|
|
this.actualByteCount = 0;
|
|
this.expectedByteCount = byteCount;
|
|
}
|
|
AssertByteCountStream.prototype._transform = function(chunk, encoding, cb) {
|
|
this.actualByteCount += chunk.length;
|
|
if (this.actualByteCount > this.expectedByteCount) {
|
|
var msg = "too many bytes in the stream. expected " + this.expectedByteCount + ". got at least " + this.actualByteCount;
|
|
return cb(new Error(msg));
|
|
}
|
|
cb(null, chunk);
|
|
};
|
|
AssertByteCountStream.prototype._flush = function(cb) {
|
|
if (this.actualByteCount < this.expectedByteCount) {
|
|
var msg = "not enough bytes in the stream. expected " + this.expectedByteCount + ". got only " + this.actualByteCount;
|
|
return cb(new Error(msg));
|
|
}
|
|
cb();
|
|
};
|
|
util.inherits(RandomAccessReader, EventEmitter);
|
|
function RandomAccessReader() {
|
|
EventEmitter.call(this);
|
|
this.refCount = 0;
|
|
}
|
|
RandomAccessReader.prototype.ref = function() {
|
|
this.refCount += 1;
|
|
};
|
|
RandomAccessReader.prototype.unref = function() {
|
|
var self2 = this;
|
|
self2.refCount -= 1;
|
|
if (self2.refCount > 0) return;
|
|
if (self2.refCount < 0) throw new Error("invalid unref");
|
|
self2.close(onCloseDone);
|
|
function onCloseDone(err) {
|
|
if (err) return self2.emit("error", err);
|
|
self2.emit("close");
|
|
}
|
|
};
|
|
RandomAccessReader.prototype.createReadStream = function(options) {
|
|
var start = options.start;
|
|
var end = options.end;
|
|
if (start === end) {
|
|
var emptyStream = new PassThrough();
|
|
setImmediate(function() {
|
|
emptyStream.end();
|
|
});
|
|
return emptyStream;
|
|
}
|
|
var stream = this._readStreamForRange(start, end);
|
|
var destroyed = false;
|
|
var refUnrefFilter = new RefUnrefFilter(this);
|
|
stream.on("error", function(err) {
|
|
setImmediate(function() {
|
|
if (!destroyed) refUnrefFilter.emit("error", err);
|
|
});
|
|
});
|
|
refUnrefFilter.destroy = function() {
|
|
stream.unpipe(refUnrefFilter);
|
|
refUnrefFilter.unref();
|
|
stream.destroy();
|
|
};
|
|
var byteCounter = new AssertByteCountStream(end - start);
|
|
refUnrefFilter.on("error", function(err) {
|
|
setImmediate(function() {
|
|
if (!destroyed) byteCounter.emit("error", err);
|
|
});
|
|
});
|
|
byteCounter.destroy = function() {
|
|
destroyed = true;
|
|
refUnrefFilter.unpipe(byteCounter);
|
|
refUnrefFilter.destroy();
|
|
};
|
|
return stream.pipe(refUnrefFilter).pipe(byteCounter);
|
|
};
|
|
RandomAccessReader.prototype._readStreamForRange = function(start, end) {
|
|
throw new Error("bare-os: RandomAccessReader range stream unavailable");
|
|
};
|
|
RandomAccessReader.prototype.read = function(buffer, offset, length, position, callback) {
|
|
var readStream = this.createReadStream({ start: position, end: position + length });
|
|
var writeStream = new Writable();
|
|
var written = 0;
|
|
writeStream._write = function(chunk, encoding, cb) {
|
|
chunk.copy(buffer, offset + written, 0, chunk.length);
|
|
written += chunk.length;
|
|
cb();
|
|
};
|
|
writeStream.on("finish", callback);
|
|
readStream.on("error", function(error) {
|
|
callback(error);
|
|
});
|
|
readStream.pipe(writeStream);
|
|
};
|
|
RandomAccessReader.prototype.close = function(callback) {
|
|
setImmediate(callback);
|
|
};
|
|
util.inherits(RefUnrefFilter, PassThrough);
|
|
function RefUnrefFilter(context) {
|
|
PassThrough.call(this);
|
|
this.context = context;
|
|
this.context.ref();
|
|
this.unreffedYet = false;
|
|
}
|
|
RefUnrefFilter.prototype._flush = function(cb) {
|
|
this.unref();
|
|
cb();
|
|
};
|
|
RefUnrefFilter.prototype.unref = function(cb) {
|
|
if (this.unreffedYet) return;
|
|
this.unreffedYet = true;
|
|
this.context.unref();
|
|
};
|
|
var cp437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\xB6\xA7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\xC7\xFC\xE9\xE2\xE4\xE0\xE5\xE7\xEA\xEB\xE8\xEF\xEE\xEC\xC4\xC5\xC9\xE6\xC6\xF4\xF6\xF2\xFB\xF9\xFF\xD6\xDC\xA2\xA3\xA5\u20A7\u0192\xE1\xED\xF3\xFA\xF1\xD1\xAA\xBA\xBF\u2310\xAC\xBD\xBC\xA1\xAB\xBB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\xDF\u0393\u03C0\u03A3\u03C3\xB5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\xB1\u2265\u2264\u2320\u2321\xF7\u2248\xB0\u2219\xB7\u221A\u207F\xB2\u25A0\xA0";
|
|
function decodeBuffer(buffer, start, end, isUtf8) {
|
|
if (isUtf8) {
|
|
return buffer.toString("utf8", start, end);
|
|
} else {
|
|
var result = "";
|
|
for (var i = start; i < end; i++) {
|
|
result += cp437[buffer[i]];
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
function readUInt64LE(buffer, offset) {
|
|
var lower32 = buffer.readUInt32LE(offset);
|
|
var upper32 = buffer.readUInt32LE(offset + 4);
|
|
return upper32 * 4294967296 + lower32;
|
|
}
|
|
var newBuffer;
|
|
if (typeof Buffer.allocUnsafe === "function") {
|
|
newBuffer = function(len) {
|
|
return Buffer.allocUnsafe(len);
|
|
};
|
|
} else {
|
|
newBuffer = function(len) {
|
|
return new Buffer(len);
|
|
};
|
|
}
|
|
function defaultCallback(err) {
|
|
if (err) throw err;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress-unzip/index.js
|
|
var require_decompress_unzip = __commonJS({
|
|
"../../node_modules/decompress-unzip/index.js"(exports, module) {
|
|
"use strict";
|
|
var fileType = require_file_type3();
|
|
var getStream = require_get_stream();
|
|
var pify = require_pify();
|
|
var yauzl = require_yauzl();
|
|
var getType = (entry, mode) => {
|
|
const IFMT = 61440;
|
|
const IFDIR = 16384;
|
|
const IFLNK = 40960;
|
|
const madeBy = entry.versionMadeBy >> 8;
|
|
if ((mode & IFMT) === IFLNK) {
|
|
return "symlink";
|
|
}
|
|
if ((mode & IFMT) === IFDIR || madeBy === 0 && entry.externalFileAttributes === 16) {
|
|
return "directory";
|
|
}
|
|
return "file";
|
|
};
|
|
var extractEntry = (entry, zip) => {
|
|
const file = {
|
|
mode: entry.externalFileAttributes >> 16 & 65535,
|
|
mtime: entry.getLastModDate(),
|
|
path: entry.fileName
|
|
};
|
|
file.type = getType(entry, file.mode);
|
|
if (file.mode === 0 && file.type === "directory") {
|
|
file.mode = 493;
|
|
}
|
|
if (file.mode === 0) {
|
|
file.mode = 420;
|
|
}
|
|
return pify(zip.openReadStream.bind(zip))(entry).then(getStream.buffer).then((buf) => {
|
|
file.data = buf;
|
|
if (file.type === "symlink") {
|
|
file.linkname = buf.toString();
|
|
}
|
|
return file;
|
|
}).catch((err) => {
|
|
zip.close();
|
|
throw err;
|
|
});
|
|
};
|
|
var extractFile = (zip) => new Promise((resolve, reject) => {
|
|
const files = [];
|
|
zip.readEntry();
|
|
zip.on("entry", (entry) => {
|
|
extractEntry(entry, zip).catch(reject).then((file) => {
|
|
files.push(file);
|
|
zip.readEntry();
|
|
});
|
|
});
|
|
zip.on("error", reject);
|
|
zip.on("end", () => resolve(files));
|
|
});
|
|
module.exports = () => (buf) => {
|
|
if (!Buffer.isBuffer(buf)) {
|
|
return Promise.reject(new TypeError(`Expected a Buffer, got ${typeof buf}`));
|
|
}
|
|
if (!fileType(buf) || fileType(buf).ext !== "zip") {
|
|
return Promise.resolve([]);
|
|
}
|
|
return pify(yauzl.fromBuffer)(buf, { lazyEntries: true }).then(extractFile);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/make-dir/node_modules/pify/index.js
|
|
var require_pify2 = __commonJS({
|
|
"../../node_modules/make-dir/node_modules/pify/index.js"(exports, module) {
|
|
"use strict";
|
|
var processFn = (fn, opts) => function() {
|
|
const P = opts.promiseModule;
|
|
const args = new Array(arguments.length);
|
|
for (let i = 0; i < arguments.length; i++) {
|
|
args[i] = arguments[i];
|
|
}
|
|
return new P((resolve, reject) => {
|
|
if (opts.errorFirst) {
|
|
args.push(function(err, result) {
|
|
if (opts.multiArgs) {
|
|
const results = new Array(arguments.length - 1);
|
|
for (let i = 1; i < arguments.length; i++) {
|
|
results[i - 1] = arguments[i];
|
|
}
|
|
if (err) {
|
|
results.unshift(err);
|
|
reject(results);
|
|
} else {
|
|
resolve(results);
|
|
}
|
|
} else if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve(result);
|
|
}
|
|
});
|
|
} else {
|
|
args.push(function(result) {
|
|
if (opts.multiArgs) {
|
|
const results = new Array(arguments.length - 1);
|
|
for (let i = 0; i < arguments.length; i++) {
|
|
results[i] = arguments[i];
|
|
}
|
|
resolve(results);
|
|
} else {
|
|
resolve(result);
|
|
}
|
|
});
|
|
}
|
|
fn.apply(this, args);
|
|
});
|
|
};
|
|
module.exports = (obj, opts) => {
|
|
opts = Object.assign({
|
|
exclude: [/.+(Sync|Stream)$/],
|
|
errorFirst: true,
|
|
promiseModule: Promise
|
|
}, opts);
|
|
const filter = (key) => {
|
|
const match = (pattern) => typeof pattern === "string" ? key === pattern : pattern.test(key);
|
|
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
|
|
};
|
|
let ret;
|
|
if (typeof obj === "function") {
|
|
ret = function() {
|
|
if (opts.excludeMain) {
|
|
return obj.apply(this, arguments);
|
|
}
|
|
return processFn(obj, opts).apply(this, arguments);
|
|
};
|
|
} else {
|
|
ret = Object.create(Object.getPrototypeOf(obj));
|
|
}
|
|
for (const key in obj) {
|
|
const x = obj[key];
|
|
ret[key] = typeof x === "function" && filter(key) ? processFn(x, opts) : x;
|
|
}
|
|
return ret;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/make-dir/index.js
|
|
var require_make_dir = __commonJS({
|
|
"../../node_modules/make-dir/index.js"(exports, module) {
|
|
"use strict";
|
|
var fs = __require("fs");
|
|
var path = __require("path");
|
|
var pify = require_pify2();
|
|
var defaults = {
|
|
mode: 511 & ~process.umask(),
|
|
fs
|
|
};
|
|
var checkPath = (pth) => {
|
|
if (process.platform === "win32") {
|
|
const pathHasInvalidWinCharacters = /[<>:"|?*]/.test(pth.replace(path.parse(pth).root, ""));
|
|
if (pathHasInvalidWinCharacters) {
|
|
const err = new Error(`Path contains invalid characters: ${pth}`);
|
|
err.code = "EINVAL";
|
|
throw err;
|
|
}
|
|
}
|
|
};
|
|
module.exports = (input, opts) => Promise.resolve().then(() => {
|
|
checkPath(input);
|
|
opts = Object.assign({}, defaults, opts);
|
|
const mkdir = pify(opts.fs.mkdir);
|
|
const stat = pify(opts.fs.stat);
|
|
const make = (pth) => {
|
|
return mkdir(pth, opts.mode).then(() => pth).catch((err) => {
|
|
if (err.code === "ENOENT") {
|
|
if (err.message.includes("null bytes") || path.dirname(pth) === pth) {
|
|
throw err;
|
|
}
|
|
return make(path.dirname(pth)).then(() => make(pth));
|
|
}
|
|
return stat(pth).then((stats) => stats.isDirectory() ? pth : Promise.reject()).catch(() => {
|
|
throw err;
|
|
});
|
|
});
|
|
};
|
|
return make(path.resolve(input));
|
|
});
|
|
module.exports.sync = (input, opts) => {
|
|
checkPath(input);
|
|
opts = Object.assign({}, defaults, opts);
|
|
const make = (pth) => {
|
|
try {
|
|
opts.fs.mkdirSync(pth, opts.mode);
|
|
} catch (err) {
|
|
if (err.code === "ENOENT") {
|
|
if (err.message.includes("null bytes") || path.dirname(pth) === pth) {
|
|
throw err;
|
|
}
|
|
make(path.dirname(pth));
|
|
return make(pth);
|
|
}
|
|
try {
|
|
if (!opts.fs.statSync(pth).isDirectory()) {
|
|
throw new Error("The path is not a directory");
|
|
}
|
|
} catch (_) {
|
|
throw err;
|
|
}
|
|
}
|
|
return pth;
|
|
};
|
|
return make(path.resolve(input));
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress/node_modules/pify/index.js
|
|
var require_pify3 = __commonJS({
|
|
"../../node_modules/decompress/node_modules/pify/index.js"(exports, module) {
|
|
"use strict";
|
|
var processFn = function(fn, P, opts) {
|
|
return function() {
|
|
var that = this;
|
|
var args = new Array(arguments.length);
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
args[i] = arguments[i];
|
|
}
|
|
return new P(function(resolve, reject) {
|
|
args.push(function(err, result) {
|
|
if (err) {
|
|
reject(err);
|
|
} else if (opts.multiArgs) {
|
|
var results = new Array(arguments.length - 1);
|
|
for (var i2 = 1; i2 < arguments.length; i2++) {
|
|
results[i2 - 1] = arguments[i2];
|
|
}
|
|
resolve(results);
|
|
} else {
|
|
resolve(result);
|
|
}
|
|
});
|
|
fn.apply(that, args);
|
|
});
|
|
};
|
|
};
|
|
var pify = module.exports = function(obj, P, opts) {
|
|
if (typeof P !== "function") {
|
|
opts = P;
|
|
P = Promise;
|
|
}
|
|
opts = opts || {};
|
|
opts.exclude = opts.exclude || [/.+Sync$/];
|
|
var filter = function(key) {
|
|
var match = function(pattern) {
|
|
return typeof pattern === "string" ? key === pattern : pattern.test(key);
|
|
};
|
|
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
|
|
};
|
|
var ret = typeof obj === "function" ? function() {
|
|
if (opts.excludeMain) {
|
|
return obj.apply(this, arguments);
|
|
}
|
|
return processFn(obj, P, opts).apply(this, arguments);
|
|
} : {};
|
|
return Object.keys(obj).reduce(function(ret2, key) {
|
|
var x = obj[key];
|
|
ret2[key] = typeof x === "function" && filter(key) ? processFn(x, P, opts) : x;
|
|
return ret2;
|
|
}, ret);
|
|
};
|
|
pify.all = pify;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/is-natural-number/index.js
|
|
var require_is_natural_number = __commonJS({
|
|
"../../node_modules/is-natural-number/index.js"(exports, module) {
|
|
"use strict";
|
|
module.exports = function isNaturalNumber(val, option) {
|
|
if (option) {
|
|
if (typeof option !== "object") {
|
|
throw new TypeError(
|
|
String(option) + " is not an object. Expected an object that has boolean `includeZero` property."
|
|
);
|
|
}
|
|
if ("includeZero" in option) {
|
|
if (typeof option.includeZero !== "boolean") {
|
|
throw new TypeError(
|
|
String(option.includeZero) + " is neither true nor false. `includeZero` option must be a Boolean value."
|
|
);
|
|
}
|
|
if (option.includeZero && val === 0) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return Number.isSafeInteger(val) && val >= 1;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/strip-dirs/index.js
|
|
var require_strip_dirs = __commonJS({
|
|
"../../node_modules/strip-dirs/index.js"(exports, module) {
|
|
"use strict";
|
|
var path = __require("path");
|
|
var util = __require("util");
|
|
var isNaturalNumber = require_is_natural_number();
|
|
module.exports = function stripDirs(pathStr, count, option) {
|
|
if (typeof pathStr !== "string") {
|
|
throw new TypeError(
|
|
util.inspect(pathStr) + " is not a string. First argument to strip-dirs must be a path string."
|
|
);
|
|
}
|
|
if (path.posix.isAbsolute(pathStr) || path.win32.isAbsolute(pathStr)) {
|
|
throw new Error(`${pathStr} is an absolute path. strip-dirs requires a relative path.`);
|
|
}
|
|
if (!isNaturalNumber(count, { includeZero: true })) {
|
|
throw new Error(
|
|
"The Second argument of strip-dirs must be a natural number or 0, but received " + util.inspect(count) + "."
|
|
);
|
|
}
|
|
if (option) {
|
|
if (typeof option !== "object") {
|
|
throw new TypeError(
|
|
util.inspect(option) + " is not an object. Expected an object with a boolean `disallowOverflow` property."
|
|
);
|
|
}
|
|
if (Array.isArray(option)) {
|
|
throw new TypeError(
|
|
util.inspect(option) + " is an array. Expected an object with a boolean `disallowOverflow` property."
|
|
);
|
|
}
|
|
if ("disallowOverflow" in option && typeof option.disallowOverflow !== "boolean") {
|
|
throw new TypeError(
|
|
util.inspect(option.disallowOverflow) + " is neither true nor false. `disallowOverflow` option must be a Boolean value."
|
|
);
|
|
}
|
|
} else {
|
|
option = { disallowOverflow: false };
|
|
}
|
|
const pathComponents = path.normalize(pathStr).split(path.sep);
|
|
if (pathComponents.length > 1 && pathComponents[0] === ".") {
|
|
pathComponents.shift();
|
|
}
|
|
if (count > pathComponents.length - 1) {
|
|
if (option.disallowOverflow) {
|
|
throw new RangeError("Cannot strip more directories than there are.");
|
|
}
|
|
count = pathComponents.length - 1;
|
|
}
|
|
return path.join.apply(null, pathComponents.slice(count));
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/decompress/index.js
|
|
var require_decompress = __commonJS({
|
|
"../../node_modules/decompress/index.js"(exports, module) {
|
|
"use strict";
|
|
var path = __require("path");
|
|
var fs = require_graceful_fs();
|
|
var decompressTar = require_decompress_tar();
|
|
var decompressTarbz2 = require_decompress_tarbz2();
|
|
var decompressTargz = require_decompress_targz();
|
|
var decompressUnzip = require_decompress_unzip();
|
|
var makeDir = require_make_dir();
|
|
var pify = require_pify3();
|
|
var stripDirs = require_strip_dirs();
|
|
var fsP = pify(fs);
|
|
var runPlugins = (input, opts) => {
|
|
if (opts.plugins.length === 0) {
|
|
return Promise.resolve([]);
|
|
}
|
|
return Promise.all(opts.plugins.map((x) => x(input, opts))).then((files) => files.reduce((a, b) => a.concat(b)));
|
|
};
|
|
var safeMakeDir = (dir, realOutputPath) => {
|
|
return fsP.realpath(dir).catch((_) => {
|
|
const parent = path.dirname(dir);
|
|
return safeMakeDir(parent, realOutputPath);
|
|
}).then((realParentPath) => {
|
|
if (realParentPath.indexOf(realOutputPath) !== 0) {
|
|
throw new Error("Refusing to create a directory outside the output path.");
|
|
}
|
|
return makeDir(dir).then(fsP.realpath);
|
|
});
|
|
};
|
|
var preventWritingThroughSymlink = (destination, realOutputPath) => {
|
|
return fsP.readlink(destination).catch((_) => {
|
|
return null;
|
|
}).then((symlinkPointsTo) => {
|
|
if (symlinkPointsTo) {
|
|
throw new Error("Refusing to write into a symlink");
|
|
}
|
|
return realOutputPath;
|
|
});
|
|
};
|
|
var extractFile = (input, output, opts) => runPlugins(input, opts).then((files) => {
|
|
if (opts.strip > 0) {
|
|
files = files.map((x) => {
|
|
x.path = stripDirs(x.path, opts.strip);
|
|
return x;
|
|
}).filter((x) => x.path !== ".");
|
|
}
|
|
if (typeof opts.filter === "function") {
|
|
files = files.filter(opts.filter);
|
|
}
|
|
if (typeof opts.map === "function") {
|
|
files = files.map(opts.map);
|
|
}
|
|
if (!output) {
|
|
return files;
|
|
}
|
|
return Promise.all(files.map((x) => {
|
|
const dest = path.join(output, x.path);
|
|
const mode = x.mode & ~process.umask();
|
|
const now = /* @__PURE__ */ new Date();
|
|
if (x.type === "directory") {
|
|
return makeDir(output).then((outputPath) => fsP.realpath(outputPath)).then((realOutputPath) => safeMakeDir(dest, realOutputPath)).then(() => fsP.utimes(dest, now, x.mtime)).then(() => x);
|
|
}
|
|
return makeDir(output).then((outputPath) => fsP.realpath(outputPath)).then((realOutputPath) => {
|
|
return safeMakeDir(path.dirname(dest), realOutputPath).then(() => realOutputPath);
|
|
}).then((realOutputPath) => {
|
|
if (x.type === "file") {
|
|
return preventWritingThroughSymlink(dest, realOutputPath);
|
|
}
|
|
return realOutputPath;
|
|
}).then((realOutputPath) => {
|
|
return fsP.realpath(path.dirname(dest)).then((realDestinationDir) => {
|
|
if (realDestinationDir.indexOf(realOutputPath) !== 0) {
|
|
throw new Error("Refusing to write outside output directory: " + realDestinationDir);
|
|
}
|
|
});
|
|
}).then(() => {
|
|
if (x.type === "link") {
|
|
return fsP.link(x.linkname, dest);
|
|
}
|
|
if (x.type === "symlink" && process.platform === "win32") {
|
|
return fsP.link(x.linkname, dest);
|
|
}
|
|
if (x.type === "symlink") {
|
|
return fsP.symlink(x.linkname, dest);
|
|
}
|
|
return fsP.writeFile(dest, x.data, { mode });
|
|
}).then(() => x.type === "file" && fsP.utimes(dest, now, x.mtime)).then(() => x);
|
|
}));
|
|
});
|
|
module.exports = (input, output, opts) => {
|
|
if (typeof input !== "string" && !Buffer.isBuffer(input)) {
|
|
return Promise.reject(new TypeError("Input file required"));
|
|
}
|
|
if (typeof output === "object") {
|
|
opts = output;
|
|
output = null;
|
|
}
|
|
opts = Object.assign({ plugins: [
|
|
decompressTar(),
|
|
decompressTarbz2(),
|
|
decompressTargz(),
|
|
decompressUnzip()
|
|
] }, opts);
|
|
const read = typeof input === "string" ? fsP.readFile(input) : Promise.resolve(input);
|
|
return read.then((buf) => extractFile(buf, output, opts));
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/sdk/setup.js
|
|
var require_setup = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/sdk/setup.js"(exports, module) {
|
|
var fs = __require("fs");
|
|
var os = __require("os");
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var crypto = __require("crypto");
|
|
var decompress = require_decompress();
|
|
module.exports = async function setup(opts = {}) {
|
|
const {
|
|
sdk = require_sdk().path,
|
|
tools = defaults().tools,
|
|
integrity = defaults().integrity,
|
|
force = false,
|
|
quiet = true
|
|
} = opts;
|
|
const destination = path.join(sdk, "cmdline-tools/latest");
|
|
if (!fs.existsSync(destination) || force) {
|
|
const response = await fetch(tools);
|
|
const input = Buffer.from(await response.arrayBuffer());
|
|
const digest = crypto.createHash("sha256").update(input).digest("hex");
|
|
if (integrity && digest !== integrity) throw new Error("integrity mismatch");
|
|
await decompress(input, destination, {
|
|
map(file) {
|
|
file.path = path.relative("cmdline-tools", file.path);
|
|
return file;
|
|
}
|
|
});
|
|
}
|
|
if (!quiet) process2.stdout.write(`export ANDROID_HOME=${sdk}
|
|
`);
|
|
};
|
|
function defaults() {
|
|
const release = "11076708";
|
|
switch (os.platform()) {
|
|
case "darwin":
|
|
return {
|
|
tools: `https://dl.google.com/android/repository/commandlinetools-mac-${release}_latest.zip`,
|
|
integrity: "7bc5c72ba0275c80a8f19684fb92793b83a6b5c94d4d179fc5988930282d7e64"
|
|
};
|
|
case "linux":
|
|
return {
|
|
tools: `https://dl.google.com/android/repository/commandlinetools-linux-${release}_latest.zip`,
|
|
integrity: "2d2d50857e4eb553af5a6dc3ad507a17adf43d115264b1afc116f95c92e5e258"
|
|
};
|
|
case "win32":
|
|
return {
|
|
tools: `https://dl.google.com/android/repository/commandlinetools-win-${release}_latest.zip`,
|
|
integrity: "4d6931209eebb1bfb7c7e8b240a6a3cb3ab24479ea294f3539429574b1eec862"
|
|
};
|
|
default:
|
|
throw new Error(`unsupported platform ${os.platform()}`);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/sdk/licenses.js
|
|
var require_licenses = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/sdk/licenses.js"(exports) {
|
|
var exec = require_exec();
|
|
var sdk = require_sdk();
|
|
var yes = Buffer.from("y\r\n".repeat(
|
|
7
|
|
/* Review + 6 licenses */
|
|
));
|
|
exports.accept = function accept(opts = {}) {
|
|
exec(sdk.manager(), ["--licenses"], { ...opts, input: yes });
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/sdk.js
|
|
var require_sdk2 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/sdk.js"(exports) {
|
|
exports.setup = require_setup();
|
|
exports.licenses = require_licenses();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android.js
|
|
var require_android = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android.js"(exports) {
|
|
exports.device = require_device();
|
|
exports.run = require_run();
|
|
exports.sdk = require_sdk2();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/cmake-runtime/index.js
|
|
var require_cmake_runtime = __commonJS({
|
|
"../../node_modules/cmake-runtime/index.js"(exports, module) {
|
|
var os = __require("os");
|
|
var path = __require("path");
|
|
module.exports = function runtime(referrer, opts) {
|
|
if (typeof referrer === "object" && referrer !== null) {
|
|
opts = referrer;
|
|
referrer = "cmake";
|
|
} else if (typeof referrer !== "string") {
|
|
referrer = "cmake";
|
|
}
|
|
if (!opts) opts = {};
|
|
const {
|
|
platform = os.platform(),
|
|
arch = platform === "darwin" ? "universal" : os.arch()
|
|
} = opts;
|
|
const filename = path.basename(referrer);
|
|
let mod;
|
|
try {
|
|
mod = __require(`cmake-runtime-${platform}-${arch}`);
|
|
} catch (err) {
|
|
if (err.code === "MODULE_NOT_FOUND") {
|
|
throw new Error(`No binaries found for target '${platform}-${arch}'`);
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
if (filename in mod === false) {
|
|
throw new Error(`No binary found for target '${platform}-${arch}' for referrer '${referrer}'`);
|
|
}
|
|
return mod[filename];
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/shared/cmake.js
|
|
var require_cmake = __commonJS({
|
|
"../../node_modules/bare-dev/lib/shared/cmake.js"(exports, module) {
|
|
var path = __require("path");
|
|
var runtime = require_cmake_runtime();
|
|
module.exports = exports = function cmake() {
|
|
return runtime("cmake");
|
|
};
|
|
exports.ctest = function ctest() {
|
|
return runtime("ctest");
|
|
};
|
|
exports.toPath = function toPath(input, opts = {}) {
|
|
const {
|
|
normalize = true
|
|
} = opts;
|
|
if (normalize) input = path.normalize(input);
|
|
return input.replace(/\\/g, "/");
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/shared/gradle.js
|
|
var require_gradle = __commonJS({
|
|
"../../node_modules/bare-dev/lib/shared/gradle.js"(exports, module) {
|
|
var path = __require("path");
|
|
var which = require_bare_which();
|
|
module.exports = function gradle(opts = {}) {
|
|
const {
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
try {
|
|
return which.sync("gradlew", { path: cwd });
|
|
} catch {
|
|
return which.sync("gradle");
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/paths.js
|
|
var require_paths = __commonJS({
|
|
"../../node_modules/bare-dev/lib/paths.js"(exports, module) {
|
|
var path = __require("path");
|
|
var root = path.join(__dirname, "..");
|
|
var compat = path.join(root, "compat");
|
|
module.exports = {
|
|
cmake: path.join(root, "cmake"),
|
|
// Compatibility paths
|
|
"compat/napi": path.join(compat, "napi")
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/build.js
|
|
var require_build = __commonJS({
|
|
"../../node_modules/bare-dev/lib/build.js"(exports, module) {
|
|
var path = __require("path");
|
|
var fs = __require("fs");
|
|
var spawn = require_spawn();
|
|
var cmake = require_cmake();
|
|
var gradle = require_gradle();
|
|
var paths = require_paths();
|
|
module.exports = exports = function build(opts = {}) {
|
|
const {
|
|
cwd = path.resolve("."),
|
|
cmake: cmake2 = fs.existsSync(path.join(cwd, "CMakeLists.txt")),
|
|
gradle: gradle2 = fs.existsSync(path.join(cwd, "build.gradle"))
|
|
} = opts;
|
|
if (cmake2) return exports.cmake(opts);
|
|
if (gradle2) return exports.gradle(opts);
|
|
throw new Error("no build system recognized");
|
|
};
|
|
exports.cmake = function(opts = {}) {
|
|
const {
|
|
build = "build",
|
|
target = null,
|
|
debug = false,
|
|
cwd = path.resolve("."),
|
|
verbose = false,
|
|
parallel = 0
|
|
} = opts;
|
|
const args = ["--build", path.resolve(cwd, build), "--config", debug ? "Debug" : "Release"];
|
|
if (target) args.push("--target", target);
|
|
if (parallel > 0) args.push("--parallel", parallel);
|
|
if (verbose) args.push("--verbose");
|
|
return spawn(cmake(), args, opts);
|
|
};
|
|
exports.gradle = function(opts = {}) {
|
|
const {
|
|
target = "build",
|
|
env = process.env
|
|
} = opts;
|
|
return spawn(gradle(opts), [target], {
|
|
...opts,
|
|
env: {
|
|
...env,
|
|
CMAKE_MODULE_PATH: cmake.toPath(paths.cmake)
|
|
}
|
|
});
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/unix-path-resolve/index.js
|
|
var require_unix_path_resolve = __commonJS({
|
|
"../../node_modules/unix-path-resolve/index.js"(exports, module) {
|
|
module.exports = resolve;
|
|
function parse2(addr) {
|
|
const names = addr.split(/[/\\]/);
|
|
const r = {
|
|
isAbsolute: false,
|
|
names
|
|
};
|
|
if (names.length === 0) return r;
|
|
if (names.length > 1 && names[0].endsWith(":")) {
|
|
r.isAbsolute = true;
|
|
if (names[0].length === 2) {
|
|
r.names = names.slice(1);
|
|
return r;
|
|
}
|
|
if (names[0] === "file:") {
|
|
r.names = names.slice(1);
|
|
return r;
|
|
}
|
|
r.names = names.slice(3);
|
|
return r;
|
|
}
|
|
r.isAbsolute = addr.startsWith("/") || addr.startsWith("\\");
|
|
return r;
|
|
}
|
|
function resolve(a, b = "") {
|
|
const ap = parse2(a);
|
|
const bp = parse2(b);
|
|
if (bp.isAbsolute) {
|
|
return resolveNames([], bp.names);
|
|
}
|
|
if (!ap.isAbsolute) {
|
|
throw new Error("One of the two paths must be absolute");
|
|
}
|
|
return resolveNames(ap.names, bp.names);
|
|
}
|
|
function toString(p, names) {
|
|
for (let i = 0; i < names.length; i++) {
|
|
if (names[i] === "") continue;
|
|
if (names[i] === ".") continue;
|
|
if (names[i] === "..") {
|
|
if (p.length === 1) throw new Error("Path cannot be resolved, too many '..'");
|
|
p = p.slice(0, p.lastIndexOf("/")) || "/";
|
|
continue;
|
|
}
|
|
p += p.length === 1 ? names[i] : "/" + names[i];
|
|
}
|
|
return p;
|
|
}
|
|
function resolveNames(a, b) {
|
|
return toString(toString("/", a), b);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/include-static/index.js
|
|
var require_include_static = __commonJS({
|
|
"../../node_modules/include-static/index.js"(exports, module) {
|
|
module.exports = function includeStatic(name, buf) {
|
|
let s = "unsigned char " + name + "[] = {\n ";
|
|
for (let i = 0; i < buf.byteLength; i++) {
|
|
s += "0x" + buf[i].toString(16).padStart(2, "0");
|
|
if (i < buf.byteLength - 1) s += ",";
|
|
if (i % 16 === 15) s += "\n ";
|
|
else s += " ";
|
|
}
|
|
s = s.trim() + "\n};\n\n";
|
|
s += "size_t " + name + "_len = " + buf.byteLength + ";\n";
|
|
return s;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-bundle/lib/errors.js
|
|
var require_errors = __commonJS({
|
|
"../../node_modules/bare-bundle/lib/errors.js"(exports, module) {
|
|
module.exports = class BundleError extends Error {
|
|
constructor(msg, fn = BundleError, opts = {}) {
|
|
const { cause, code = fn.name } = opts;
|
|
super(`${code}: ${msg}`, { cause });
|
|
this.code = code;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, fn);
|
|
}
|
|
}
|
|
get name() {
|
|
return "BundleError";
|
|
}
|
|
static INVALID_BUNDLE_HEADER(msg, cause) {
|
|
return new BundleError(msg, BundleError.INVALID_BUNDLE_HEADER, { cause });
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-bundle/index.js
|
|
var require_bare_bundle = __commonJS({
|
|
"../../node_modules/bare-bundle/index.js"(exports, module) {
|
|
var errors = require_errors();
|
|
var kind = Symbol.for("bare.bundle.kind");
|
|
var MemoryFile = class _MemoryFile {
|
|
constructor(data, opts = {}) {
|
|
const { executable = false, mode = executable ? 493 : 420 } = opts;
|
|
this._data = typeof data === "string" ? Buffer.from(data) : data;
|
|
this._mode = mode;
|
|
}
|
|
size() {
|
|
return this._data.byteLength;
|
|
}
|
|
mode() {
|
|
return this._mode;
|
|
}
|
|
read() {
|
|
return this._data;
|
|
}
|
|
inspect() {
|
|
return {
|
|
__proto__: { constructor: _MemoryFile },
|
|
data: this._data,
|
|
mode: this._mode.toString(8)
|
|
};
|
|
}
|
|
[Symbol.for("bare.inspect")]() {
|
|
return this.inspect();
|
|
}
|
|
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
return this.inspect();
|
|
}
|
|
};
|
|
module.exports = exports = class Bundle2 {
|
|
static get [kind]() {
|
|
return 0;
|
|
}
|
|
static get version() {
|
|
return 0;
|
|
}
|
|
constructor(opts = {}) {
|
|
const { File = MemoryFile } = opts;
|
|
this._File = File;
|
|
this._id = null;
|
|
this._main = null;
|
|
this._imports = {};
|
|
this._resolutions = {};
|
|
this._addons = [];
|
|
this._assets = [];
|
|
this._files = /* @__PURE__ */ new Map();
|
|
}
|
|
get [kind]() {
|
|
return Bundle2[kind];
|
|
}
|
|
get version() {
|
|
return Bundle2.version;
|
|
}
|
|
get id() {
|
|
return this._id;
|
|
}
|
|
set id(value) {
|
|
if (typeof value !== "string" && value !== null) {
|
|
throw new TypeError(`ID must be a string or null. Received type ${typeof value} (${value})`);
|
|
}
|
|
this._id = value;
|
|
}
|
|
get main() {
|
|
return this._main;
|
|
}
|
|
set main(value) {
|
|
if (typeof value !== "string" && value !== null) {
|
|
throw new TypeError(`Main must be a string or null. Received type ${typeof value} (${value})`);
|
|
}
|
|
this._main = value;
|
|
}
|
|
get imports() {
|
|
return this._imports;
|
|
}
|
|
set imports(value) {
|
|
this._imports = cloneImportsMap(value);
|
|
}
|
|
get resolutions() {
|
|
return this._resolutions;
|
|
}
|
|
set resolutions(value) {
|
|
this._resolutions = cloneResolutionsMap(value);
|
|
}
|
|
get addons() {
|
|
return this._addons;
|
|
}
|
|
set addons(value) {
|
|
this._addons = cloneFilesList(value, "Addons");
|
|
}
|
|
get assets() {
|
|
return this._assets;
|
|
}
|
|
set assets(value) {
|
|
this._assets = cloneFilesList(value, "Assets");
|
|
}
|
|
get files() {
|
|
return Object.fromEntries(this._files.entries());
|
|
}
|
|
*[Symbol.iterator]() {
|
|
for (const [key, file] of this._files) {
|
|
yield [key, file.read(), file.mode()];
|
|
}
|
|
}
|
|
empty() {
|
|
return this._files.size === 0;
|
|
}
|
|
keys() {
|
|
return this._files.keys();
|
|
}
|
|
exists(key) {
|
|
return this._files.has(key);
|
|
}
|
|
size(key) {
|
|
const file = this._files.get(key) || null;
|
|
if (file === null) return 0;
|
|
return file.size();
|
|
}
|
|
mode(key) {
|
|
const file = this._files.get(key) || null;
|
|
if (file === null) return 0;
|
|
return file.mode();
|
|
}
|
|
read(key) {
|
|
const file = this._files.get(key) || null;
|
|
if (file === null) return null;
|
|
return file.read();
|
|
}
|
|
write(key, data, opts = {}) {
|
|
if (typeof key !== "string") {
|
|
throw new TypeError(`File path must be a string. Received type ${typeof key} (${key})`);
|
|
}
|
|
const { main = false, alias = null, imports = null, addon = false, asset = false } = opts;
|
|
this._files.set(key, new MemoryFile(data, opts));
|
|
if (main) this._main = key;
|
|
if (alias) this._imports[alias] = key;
|
|
if (imports) this._resolutions[key] = cloneImportsMap(imports);
|
|
if (addon) this._addons.push(key);
|
|
if (asset) this._assets.push(key);
|
|
return this;
|
|
}
|
|
mount(root, opts = {}) {
|
|
const bundle = new Bundle2();
|
|
bundle._File = this._File;
|
|
bundle._id = this._id;
|
|
if (this._main) bundle._main = mountSpecifier(this._main, root);
|
|
bundle._imports = transformImportsMap(this._imports, root, null, opts, mountSpecifier);
|
|
bundle._resolutions = transformResolutionsMap(this._resolutions, root, opts, mountSpecifier);
|
|
for (const [key, file] of this._files) {
|
|
bundle._files.set(mountSpecifier(key, root), file);
|
|
}
|
|
bundle._addons = transformFilesList(this._addons, root, mountSpecifier);
|
|
bundle._assets = transformFilesList(this._assets, root, mountSpecifier);
|
|
return bundle;
|
|
}
|
|
unmount(root, opts = {}) {
|
|
const bundle = new Bundle2();
|
|
bundle._File = this._File;
|
|
bundle._id = this._id;
|
|
if (this._main) bundle._main = unmountSpecifier(this._main, root);
|
|
bundle._imports = transformImportsMap(this._imports, root, null, opts, unmountSpecifier);
|
|
bundle._resolutions = transformResolutionsMap(this._resolutions, root, opts, unmountSpecifier);
|
|
for (const [key, file] of this._files) {
|
|
bundle._files.set(unmountSpecifier(key, root), file);
|
|
}
|
|
bundle._addons = transformFilesList(this._addons, root, unmountSpecifier);
|
|
bundle._assets = transformFilesList(this._assets, root, unmountSpecifier);
|
|
return bundle;
|
|
}
|
|
toBuffer(opts = {}) {
|
|
const { indent = 0, shared = false } = opts;
|
|
const header = {
|
|
version: Bundle2.version,
|
|
id: this._id,
|
|
main: this._main,
|
|
imports: cloneImportsMap(this._imports),
|
|
resolutions: cloneResolutionsMap(this._resolutions),
|
|
addons: cloneFilesList(this._addons, "Addons"),
|
|
assets: cloneFilesList(this._assets, "Assets"),
|
|
files: {}
|
|
};
|
|
const keys = [...this._files.keys()].sort();
|
|
let offset = 0;
|
|
for (const key of keys) {
|
|
const length2 = this.size(key);
|
|
header.files[key] = { offset, length: length2, mode: this.mode(key) };
|
|
offset += length2;
|
|
}
|
|
const json = Buffer.from(`
|
|
${JSON.stringify(header, null, indent)}
|
|
`);
|
|
const length = Buffer.from(json.byteLength.toString(10));
|
|
const total = length.byteLength + json.byteLength + offset;
|
|
const storage = shared ? new SharedArrayBuffer(total) : new ArrayBuffer(total);
|
|
const buffer = Buffer.from(storage);
|
|
offset = 0;
|
|
buffer.set(length, offset);
|
|
offset += length.byteLength;
|
|
buffer.set(json, offset);
|
|
offset += json.byteLength;
|
|
for (const key of keys) {
|
|
buffer.set(this.read(key), offset);
|
|
offset += this.size(key);
|
|
}
|
|
return buffer;
|
|
}
|
|
inspect() {
|
|
return {
|
|
__proto__: { constructor: Bundle2 },
|
|
version: this.version,
|
|
id: this.id,
|
|
main: this.main,
|
|
imports: this.imports,
|
|
resolutions: this.resolutions,
|
|
addons: this.addons,
|
|
assets: this.assets,
|
|
files: this.files
|
|
};
|
|
}
|
|
[Symbol.for("bare.inspect")]() {
|
|
return this.inspect();
|
|
}
|
|
[Symbol.for("nodejs.util.inspect.custom")]() {
|
|
return this.inspect();
|
|
}
|
|
};
|
|
var Bundle = exports;
|
|
exports.errors = errors;
|
|
exports.isBundle = function isBundle(value) {
|
|
if (value instanceof Bundle) return true;
|
|
return typeof value === "object" && value !== null && value[kind] === Bundle[kind];
|
|
};
|
|
exports.from = function from(value) {
|
|
if (typeof value === "string") return fromString(value);
|
|
if (Buffer.isBuffer(value)) return fromBuffer(value);
|
|
return value;
|
|
};
|
|
function fromString(string) {
|
|
return fromBuffer(Buffer.from(string));
|
|
}
|
|
function fromBuffer(buffer) {
|
|
if (buffer[0] === 35 && buffer[1] === 33) {
|
|
let end2 = 2;
|
|
while (buffer[end2] !== 10) end2++;
|
|
buffer = buffer.subarray(end2 + 1);
|
|
}
|
|
let end = 0;
|
|
while (isDecimal(buffer[end])) end++;
|
|
const len = parseInt(buffer.toString("utf8", 0, end), 10);
|
|
let header;
|
|
try {
|
|
header = JSON.parse(buffer.toString("utf8", end, end + len));
|
|
} catch (err) {
|
|
throw errors.INVALID_BUNDLE_HEADER("Invalid bundle header", err);
|
|
}
|
|
const bundle = new Bundle();
|
|
if (header.id) bundle.id = header.id;
|
|
if (header.main) bundle.main = header.main;
|
|
if (header.imports) bundle.imports = header.imports;
|
|
if (header.resolutions) bundle.resolutions = header.resolutions;
|
|
if (header.addons) bundle.addons = header.addons;
|
|
if (header.assets) bundle.assets = header.assets;
|
|
let offset = end + len;
|
|
for (const [file, info] of Object.entries(header.files)) {
|
|
bundle.write(file, buffer.subarray(offset, offset + info.length), {
|
|
mode: info.mode || 420
|
|
});
|
|
offset += info.length;
|
|
}
|
|
return bundle;
|
|
}
|
|
function isDecimal(c) {
|
|
return c >= 48 && c <= 57;
|
|
}
|
|
function compareKeys([a], [b]) {
|
|
return a > b ? 1 : a < b ? -1 : 0;
|
|
}
|
|
function cloneImportsMap(value) {
|
|
if (typeof value === "object" && value !== null) {
|
|
const imports = {};
|
|
for (const entry of Object.entries(value).sort(compareKeys)) {
|
|
imports[entry[0]] = cloneImportsMapEntry(entry[1]);
|
|
}
|
|
return imports;
|
|
}
|
|
throw new TypeError(`Imports map must be an object. Received type ${typeof value} (${value})`);
|
|
}
|
|
function cloneImportsMapEntry(value) {
|
|
if (typeof value === "string") return value;
|
|
if (typeof value === "object" && value !== null) {
|
|
const imports = {};
|
|
for (const entry of Object.entries(value)) {
|
|
imports[entry[0]] = cloneImportsMapEntry(entry[1]);
|
|
}
|
|
return imports;
|
|
}
|
|
throw new TypeError(
|
|
`Imports map entry must be a string or object. Received type ${typeof value} (${value})`
|
|
);
|
|
}
|
|
function cloneResolutionsMap(value) {
|
|
if (typeof value === "object" && value !== null) {
|
|
const resolutions = {};
|
|
for (const entry of Object.entries(value).sort(compareKeys)) {
|
|
resolutions[entry[0]] = cloneImportsMap(entry[1]);
|
|
}
|
|
return resolutions;
|
|
}
|
|
throw new TypeError(`Resolutions map must be an object. Received type ${typeof value} (${value})`);
|
|
}
|
|
function cloneFilesList(value, name) {
|
|
if (Array.isArray(value)) {
|
|
const files = [];
|
|
for (const entry of value) {
|
|
if (typeof entry !== "string") {
|
|
throw new TypeError(
|
|
`${name} entry must be a string. Received type ${typeof entry} (${entry})`
|
|
);
|
|
}
|
|
files.push(entry);
|
|
}
|
|
return files.sort();
|
|
}
|
|
throw new TypeError(`${name} list must be an array. Received type ${typeof value} (${value})`);
|
|
}
|
|
function transformImportsMap(value, root, conditionalRoot, opts, fn) {
|
|
const { conditions = {} } = opts;
|
|
const imports = {};
|
|
for (const entry of Object.entries(value)) {
|
|
const condition = entry[0];
|
|
imports[condition] = transformImportsMapEntry(
|
|
entry[1],
|
|
root,
|
|
conditionalRoot || conditions[condition],
|
|
opts,
|
|
fn
|
|
);
|
|
}
|
|
return imports;
|
|
}
|
|
function transformImportsMapEntry(value, root, conditionalRoot, opts, fn) {
|
|
const { conditions = {} } = opts;
|
|
if (typeof value === "string") {
|
|
return fn(value, conditionalRoot || conditions.default || root);
|
|
}
|
|
return transformImportsMap(value, root, conditionalRoot, opts, fn);
|
|
}
|
|
function transformResolutionsMap(value, root, opts, fn) {
|
|
const resolutions = {};
|
|
for (const entry of Object.entries(value)) {
|
|
resolutions[fn(entry[0], root)] = transformImportsMap(entry[1], root, null, opts, fn);
|
|
}
|
|
return resolutions;
|
|
}
|
|
function transformFilesList(value, root, fn) {
|
|
const files = [];
|
|
for (const entry of value) {
|
|
files.push(fn(entry, root));
|
|
}
|
|
return files;
|
|
}
|
|
function mountSpecifier(specifier, root) {
|
|
if (startsWithWindowsDriveLetter(specifier)) {
|
|
specifier = "/" + specifier;
|
|
}
|
|
if (specifier[0] === "/" || specifier[0] === "\\") {
|
|
specifier = "." + specifier;
|
|
}
|
|
if (specifier.startsWith("./") || specifier.startsWith(".\\")) {
|
|
return new URL(specifier, root).href;
|
|
}
|
|
return specifier;
|
|
}
|
|
function unmountSpecifier(specifier, root) {
|
|
specifier = new URL(specifier);
|
|
if (typeof root === "string") root = new URL(root);
|
|
if (specifier.protocol !== root.protocol || specifier.host !== root.host || specifier.port !== root.port) {
|
|
return specifier.href;
|
|
}
|
|
const specifierPath = splitPath(specifier.pathname);
|
|
const rootPath = splitPath(root.pathname);
|
|
while (specifierPath.length > 0 && rootPath[0] === specifierPath[0]) {
|
|
specifierPath.shift();
|
|
rootPath.shift();
|
|
}
|
|
rootPath.fill("..");
|
|
return "/" + rootPath.concat(specifierPath).join("/");
|
|
}
|
|
function splitPath(path) {
|
|
const parts = path.split("/");
|
|
if (!parts[0]) parts.shift();
|
|
if (!parts[parts.length - 1]) parts.pop();
|
|
return parts;
|
|
}
|
|
function isASCIIUpperAlpha(c) {
|
|
return c >= 65 && c <= 90;
|
|
}
|
|
function isASCIILowerAlpha(c) {
|
|
return c >= 97 && c <= 122;
|
|
}
|
|
function isASCIIAlpha(c) {
|
|
return isASCIIUpperAlpha(c) || isASCIILowerAlpha(c);
|
|
}
|
|
function isWindowsDriveLetter(input) {
|
|
return input.length >= 2 && isASCIIAlpha(input.charCodeAt(0)) && (input.charCodeAt(1) === 58 || input.charCodeAt(1) === 124);
|
|
}
|
|
function startsWithWindowsDriveLetter(input) {
|
|
return input.length >= 2 && isWindowsDriveLetter(input) && (input.length === 2 || input.charCodeAt(2) === 47 || input.charCodeAt(2) === 92 || input.charCodeAt(2) === 63 || input.charCodeAt(2) === 35);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/b4a/index.js
|
|
var require_b4a = __commonJS({
|
|
"../../node_modules/b4a/index.js"(exports, module) {
|
|
function isBuffer(value) {
|
|
return Buffer.isBuffer(value) || value instanceof Uint8Array;
|
|
}
|
|
function isEncoding(encoding) {
|
|
return Buffer.isEncoding(encoding);
|
|
}
|
|
function alloc(size, fill2, encoding) {
|
|
return Buffer.alloc(size, fill2, encoding);
|
|
}
|
|
function allocUnsafe(size) {
|
|
return Buffer.allocUnsafe(size);
|
|
}
|
|
function allocUnsafeSlow(size) {
|
|
return Buffer.allocUnsafeSlow(size);
|
|
}
|
|
function byteLength(string, encoding) {
|
|
return Buffer.byteLength(string, encoding);
|
|
}
|
|
function compare(a, b) {
|
|
return Buffer.compare(a, b);
|
|
}
|
|
function concat(buffers, totalLength) {
|
|
return Buffer.concat(buffers, totalLength);
|
|
}
|
|
function copy(source, target, targetStart, start, end) {
|
|
return toBuffer(source).copy(target, targetStart, start, end);
|
|
}
|
|
function equals(a, b) {
|
|
return toBuffer(a).equals(b);
|
|
}
|
|
function fill(buffer, value, offset, end, encoding) {
|
|
return toBuffer(buffer).fill(value, offset, end, encoding);
|
|
}
|
|
function from(value, encodingOrOffset, length) {
|
|
return Buffer.from(value, encodingOrOffset, length);
|
|
}
|
|
function includes(buffer, value, byteOffset, encoding) {
|
|
return toBuffer(buffer).includes(value, byteOffset, encoding);
|
|
}
|
|
function indexOf(buffer, value, byfeOffset, encoding) {
|
|
return toBuffer(buffer).indexOf(value, byfeOffset, encoding);
|
|
}
|
|
function lastIndexOf(buffer, value, byteOffset, encoding) {
|
|
return toBuffer(buffer).lastIndexOf(value, byteOffset, encoding);
|
|
}
|
|
function swap16(buffer) {
|
|
return toBuffer(buffer).swap16();
|
|
}
|
|
function swap32(buffer) {
|
|
return toBuffer(buffer).swap32();
|
|
}
|
|
function swap64(buffer) {
|
|
return toBuffer(buffer).swap64();
|
|
}
|
|
function toBuffer(buffer) {
|
|
if (Buffer.isBuffer(buffer)) return buffer;
|
|
return Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
}
|
|
function toString(buffer, encoding, start, end) {
|
|
return toBuffer(buffer).toString(encoding, start, end);
|
|
}
|
|
function write(buffer, string, offset, length, encoding) {
|
|
return toBuffer(buffer).write(string, offset, length, encoding);
|
|
}
|
|
function readDoubleBE(buffer, offset) {
|
|
return toBuffer(buffer).readDoubleBE(offset);
|
|
}
|
|
function readDoubleLE(buffer, offset) {
|
|
return toBuffer(buffer).readDoubleLE(offset);
|
|
}
|
|
function readFloatBE(buffer, offset) {
|
|
return toBuffer(buffer).readFloatBE(offset);
|
|
}
|
|
function readFloatLE(buffer, offset) {
|
|
return toBuffer(buffer).readFloatLE(offset);
|
|
}
|
|
function readInt32BE(buffer, offset) {
|
|
return toBuffer(buffer).readInt32BE(offset);
|
|
}
|
|
function readInt32LE(buffer, offset) {
|
|
return toBuffer(buffer).readInt32LE(offset);
|
|
}
|
|
function readUInt32BE(buffer, offset) {
|
|
return toBuffer(buffer).readUInt32BE(offset);
|
|
}
|
|
function readUInt32LE(buffer, offset) {
|
|
return toBuffer(buffer).readUInt32LE(offset);
|
|
}
|
|
function writeDoubleBE(buffer, value, offset) {
|
|
return toBuffer(buffer).writeDoubleBE(value, offset);
|
|
}
|
|
function writeDoubleLE(buffer, value, offset) {
|
|
return toBuffer(buffer).writeDoubleLE(value, offset);
|
|
}
|
|
function writeFloatBE(buffer, value, offset) {
|
|
return toBuffer(buffer).writeFloatBE(value, offset);
|
|
}
|
|
function writeFloatLE(buffer, value, offset) {
|
|
return toBuffer(buffer).writeFloatLE(value, offset);
|
|
}
|
|
function writeInt32BE(buffer, value, offset) {
|
|
return toBuffer(buffer).writeInt32BE(value, offset);
|
|
}
|
|
function writeInt32LE(buffer, value, offset) {
|
|
return toBuffer(buffer).writeInt32LE(value, offset);
|
|
}
|
|
function writeUInt32BE(buffer, value, offset) {
|
|
return toBuffer(buffer).writeUInt32BE(value, offset);
|
|
}
|
|
function writeUInt32LE(buffer, value, offset) {
|
|
return toBuffer(buffer).writeUInt32LE(value, offset);
|
|
}
|
|
module.exports = {
|
|
isBuffer,
|
|
isEncoding,
|
|
alloc,
|
|
allocUnsafe,
|
|
allocUnsafeSlow,
|
|
byteLength,
|
|
compare,
|
|
concat,
|
|
copy,
|
|
equals,
|
|
fill,
|
|
from,
|
|
includes,
|
|
indexOf,
|
|
lastIndexOf,
|
|
swap16,
|
|
swap32,
|
|
swap64,
|
|
toBuffer,
|
|
toString,
|
|
write,
|
|
readDoubleBE,
|
|
readDoubleLE,
|
|
readFloatBE,
|
|
readFloatLE,
|
|
readInt32BE,
|
|
readInt32LE,
|
|
readUInt32BE,
|
|
readUInt32LE,
|
|
writeDoubleBE,
|
|
writeDoubleLE,
|
|
writeFloatBE,
|
|
writeFloatLE,
|
|
writeInt32BE,
|
|
writeInt32LE,
|
|
writeUInt32BE,
|
|
writeUInt32LE
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/events-universal/default.js
|
|
var require_default = __commonJS({
|
|
"../../node_modules/events-universal/default.js"(exports, module) {
|
|
module.exports = __require("events");
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/fast-fifo/fixed-size.js
|
|
var require_fixed_size = __commonJS({
|
|
"../../node_modules/fast-fifo/fixed-size.js"(exports, module) {
|
|
module.exports = class FixedFIFO {
|
|
constructor(hwm) {
|
|
if (!(hwm > 0) || (hwm - 1 & hwm) !== 0) throw new Error("Max size for a FixedFIFO should be a power of two");
|
|
this.buffer = new Array(hwm);
|
|
this.mask = hwm - 1;
|
|
this.top = 0;
|
|
this.btm = 0;
|
|
this.next = null;
|
|
}
|
|
clear() {
|
|
this.top = this.btm = 0;
|
|
this.next = null;
|
|
this.buffer.fill(void 0);
|
|
}
|
|
push(data) {
|
|
if (this.buffer[this.top] !== void 0) return false;
|
|
this.buffer[this.top] = data;
|
|
this.top = this.top + 1 & this.mask;
|
|
return true;
|
|
}
|
|
shift() {
|
|
const last = this.buffer[this.btm];
|
|
if (last === void 0) return void 0;
|
|
this.buffer[this.btm] = void 0;
|
|
this.btm = this.btm + 1 & this.mask;
|
|
return last;
|
|
}
|
|
peek() {
|
|
return this.buffer[this.btm];
|
|
}
|
|
isEmpty() {
|
|
return this.buffer[this.btm] === void 0;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/fast-fifo/index.js
|
|
var require_fast_fifo = __commonJS({
|
|
"../../node_modules/fast-fifo/index.js"(exports, module) {
|
|
var FixedFIFO = require_fixed_size();
|
|
module.exports = class FastFIFO {
|
|
constructor(hwm) {
|
|
this.hwm = hwm || 16;
|
|
this.head = new FixedFIFO(this.hwm);
|
|
this.tail = this.head;
|
|
this.length = 0;
|
|
}
|
|
clear() {
|
|
this.head = this.tail;
|
|
this.head.clear();
|
|
this.length = 0;
|
|
}
|
|
push(val) {
|
|
this.length++;
|
|
if (!this.head.push(val)) {
|
|
const prev = this.head;
|
|
this.head = prev.next = new FixedFIFO(2 * this.head.buffer.length);
|
|
this.head.push(val);
|
|
}
|
|
}
|
|
shift() {
|
|
if (this.length !== 0) this.length--;
|
|
const val = this.tail.shift();
|
|
if (val === void 0 && this.tail.next) {
|
|
const next = this.tail.next;
|
|
this.tail.next = null;
|
|
this.tail = next;
|
|
return this.tail.shift();
|
|
}
|
|
return val;
|
|
}
|
|
peek() {
|
|
const val = this.tail.peek();
|
|
if (val === void 0 && this.tail.next) return this.tail.next.peek();
|
|
return val;
|
|
}
|
|
isEmpty() {
|
|
return this.length === 0;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/text-decoder/lib/pass-through-decoder.js
|
|
var require_pass_through_decoder = __commonJS({
|
|
"../../node_modules/text-decoder/lib/pass-through-decoder.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
module.exports = class PassThroughDecoder {
|
|
constructor(encoding) {
|
|
this.encoding = encoding;
|
|
}
|
|
get remaining() {
|
|
return 0;
|
|
}
|
|
decode(data) {
|
|
return b4a.toString(data, this.encoding);
|
|
}
|
|
flush() {
|
|
return "";
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/text-decoder/lib/utf8-decoder.js
|
|
var require_utf8_decoder = __commonJS({
|
|
"../../node_modules/text-decoder/lib/utf8-decoder.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
module.exports = class UTF8Decoder {
|
|
constructor() {
|
|
this._reset();
|
|
}
|
|
get remaining() {
|
|
return this.bytesSeen;
|
|
}
|
|
decode(data) {
|
|
if (data.byteLength === 0) return "";
|
|
if (this.bytesNeeded === 0 && trailingIncomplete(data, 0) === 0) {
|
|
this.bytesSeen = trailingBytesSeen(data);
|
|
return b4a.toString(data, "utf8");
|
|
}
|
|
let result = "";
|
|
let start = 0;
|
|
if (this.bytesNeeded > 0) {
|
|
while (start < data.byteLength) {
|
|
const byte = data[start];
|
|
if (byte < this.lowerBoundary || byte > this.upperBoundary) {
|
|
result += "\uFFFD";
|
|
this._reset();
|
|
break;
|
|
}
|
|
this.lowerBoundary = 128;
|
|
this.upperBoundary = 191;
|
|
this.codePoint = this.codePoint << 6 | byte & 63;
|
|
this.bytesSeen++;
|
|
start++;
|
|
if (this.bytesSeen === this.bytesNeeded) {
|
|
result += String.fromCodePoint(this.codePoint);
|
|
this._reset();
|
|
break;
|
|
}
|
|
}
|
|
if (this.bytesNeeded > 0) return result;
|
|
}
|
|
const trailing = trailingIncomplete(data, start);
|
|
const end = data.byteLength - trailing;
|
|
if (end > start) result += b4a.toString(data, "utf8", start, end);
|
|
for (let i = end; i < data.byteLength; i++) {
|
|
const byte = data[i];
|
|
if (this.bytesNeeded === 0) {
|
|
if (byte <= 127) {
|
|
this.bytesSeen = 0;
|
|
result += String.fromCharCode(byte);
|
|
} else if (byte >= 194 && byte <= 223) {
|
|
this.bytesNeeded = 2;
|
|
this.bytesSeen = 1;
|
|
this.codePoint = byte & 31;
|
|
} else if (byte >= 224 && byte <= 239) {
|
|
if (byte === 224) this.lowerBoundary = 160;
|
|
else if (byte === 237) this.upperBoundary = 159;
|
|
this.bytesNeeded = 3;
|
|
this.bytesSeen = 1;
|
|
this.codePoint = byte & 15;
|
|
} else if (byte >= 240 && byte <= 244) {
|
|
if (byte === 240) this.lowerBoundary = 144;
|
|
else if (byte === 244) this.upperBoundary = 143;
|
|
this.bytesNeeded = 4;
|
|
this.bytesSeen = 1;
|
|
this.codePoint = byte & 7;
|
|
} else {
|
|
this.bytesSeen = 1;
|
|
result += "\uFFFD";
|
|
}
|
|
continue;
|
|
}
|
|
if (byte < this.lowerBoundary || byte > this.upperBoundary) {
|
|
result += "\uFFFD";
|
|
i--;
|
|
this._reset();
|
|
continue;
|
|
}
|
|
this.lowerBoundary = 128;
|
|
this.upperBoundary = 191;
|
|
this.codePoint = this.codePoint << 6 | byte & 63;
|
|
this.bytesSeen++;
|
|
if (this.bytesSeen === this.bytesNeeded) {
|
|
result += String.fromCodePoint(this.codePoint);
|
|
this._reset();
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
flush() {
|
|
const result = this.bytesNeeded > 0 ? "\uFFFD" : "";
|
|
this._reset();
|
|
return result;
|
|
}
|
|
_reset() {
|
|
this.codePoint = 0;
|
|
this.bytesNeeded = 0;
|
|
this.bytesSeen = 0;
|
|
this.lowerBoundary = 128;
|
|
this.upperBoundary = 191;
|
|
}
|
|
};
|
|
function trailingIncomplete(data, start) {
|
|
const len = data.byteLength;
|
|
if (len <= start) return 0;
|
|
const limit = Math.max(start, len - 4);
|
|
let i = len - 1;
|
|
while (i > limit && (data[i] & 192) === 128) i--;
|
|
if (i < start) return 0;
|
|
const byte = data[i];
|
|
let needed;
|
|
if (byte <= 127) return 0;
|
|
if (byte >= 194 && byte <= 223) needed = 2;
|
|
else if (byte >= 224 && byte <= 239) needed = 3;
|
|
else if (byte >= 240 && byte <= 244) needed = 4;
|
|
else return 0;
|
|
const available = len - i;
|
|
return available < needed ? available : 0;
|
|
}
|
|
function trailingBytesSeen(data) {
|
|
const len = data.byteLength;
|
|
if (len === 0) return 0;
|
|
const last = data[len - 1];
|
|
if (last <= 127) return 0;
|
|
if ((last & 192) !== 128) return 1;
|
|
const limit = Math.max(0, len - 4);
|
|
let i = len - 2;
|
|
while (i >= limit && (data[i] & 192) === 128) i--;
|
|
if (i < 0) return 1;
|
|
const first = data[i];
|
|
let needed;
|
|
if (first >= 194 && first <= 223) needed = 2;
|
|
else if (first >= 224 && first <= 239) needed = 3;
|
|
else if (first >= 240 && first <= 244) needed = 4;
|
|
else return 1;
|
|
if (len - i !== needed) return 1;
|
|
if (needed >= 3) {
|
|
const second = data[i + 1];
|
|
if (first === 224 && second < 160) return 1;
|
|
if (first === 237 && second > 159) return 1;
|
|
if (first === 240 && second < 144) return 1;
|
|
if (first === 244 && second > 143) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/text-decoder/index.js
|
|
var require_text_decoder = __commonJS({
|
|
"../../node_modules/text-decoder/index.js"(exports, module) {
|
|
var PassThroughDecoder = require_pass_through_decoder();
|
|
var UTF8Decoder = require_utf8_decoder();
|
|
module.exports = class TextDecoder {
|
|
constructor(encoding = "utf8") {
|
|
this.encoding = normalizeEncoding(encoding);
|
|
switch (this.encoding) {
|
|
case "utf8":
|
|
this.decoder = new UTF8Decoder();
|
|
break;
|
|
case "utf16le":
|
|
case "base64":
|
|
throw new Error("Unsupported encoding: " + this.encoding);
|
|
default:
|
|
this.decoder = new PassThroughDecoder(this.encoding);
|
|
}
|
|
}
|
|
get remaining() {
|
|
return this.decoder.remaining;
|
|
}
|
|
push(data) {
|
|
if (typeof data === "string") return data;
|
|
return this.decoder.decode(data);
|
|
}
|
|
// For Node.js compatibility
|
|
write(data) {
|
|
return this.push(data);
|
|
}
|
|
end(data) {
|
|
let result = "";
|
|
if (data) result = this.push(data);
|
|
result += this.decoder.flush();
|
|
return result;
|
|
}
|
|
};
|
|
function normalizeEncoding(encoding) {
|
|
encoding = encoding.toLowerCase();
|
|
switch (encoding) {
|
|
case "utf8":
|
|
case "utf-8":
|
|
return "utf8";
|
|
case "ucs2":
|
|
case "ucs-2":
|
|
case "utf16le":
|
|
case "utf-16le":
|
|
return "utf16le";
|
|
case "latin1":
|
|
case "binary":
|
|
return "latin1";
|
|
case "base64":
|
|
case "ascii":
|
|
case "hex":
|
|
return encoding;
|
|
default:
|
|
throw new Error("Unknown encoding: " + encoding);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/streamx/index.js
|
|
var require_streamx = __commonJS({
|
|
"../../node_modules/streamx/index.js"(exports, module) {
|
|
var { EventEmitter } = require_default();
|
|
var STREAM_DESTROYED = new Error("Stream was destroyed");
|
|
var PREMATURE_CLOSE = new Error("Premature close");
|
|
var FIFO = require_fast_fifo();
|
|
var TextDecoder = require_text_decoder();
|
|
var qmt = typeof queueMicrotask === "undefined" ? (fn) => global.process.nextTick(fn) : queueMicrotask;
|
|
var MAX = (1 << 29) - 1;
|
|
var OPENING = 1;
|
|
var PREDESTROYING = 2;
|
|
var DESTROYING = 4;
|
|
var DESTROYED = 8;
|
|
var NOT_OPENING = MAX ^ OPENING;
|
|
var NOT_PREDESTROYING = MAX ^ PREDESTROYING;
|
|
var READ_ACTIVE = 1 << 4;
|
|
var READ_UPDATING = 2 << 4;
|
|
var READ_PRIMARY = 4 << 4;
|
|
var READ_QUEUED = 8 << 4;
|
|
var READ_RESUMED = 16 << 4;
|
|
var READ_PIPE_DRAINED = 32 << 4;
|
|
var READ_ENDING = 64 << 4;
|
|
var READ_EMIT_DATA = 128 << 4;
|
|
var READ_EMIT_READABLE = 256 << 4;
|
|
var READ_EMITTED_READABLE = 512 << 4;
|
|
var READ_DONE = 1024 << 4;
|
|
var READ_NEXT_TICK = 2048 << 4;
|
|
var READ_NEEDS_PUSH = 4096 << 4;
|
|
var READ_READ_AHEAD = 8192 << 4;
|
|
var READ_FLOWING = READ_RESUMED | READ_PIPE_DRAINED;
|
|
var READ_ACTIVE_AND_NEEDS_PUSH = READ_ACTIVE | READ_NEEDS_PUSH;
|
|
var READ_PRIMARY_AND_ACTIVE = READ_PRIMARY | READ_ACTIVE;
|
|
var READ_EMIT_READABLE_AND_QUEUED = READ_EMIT_READABLE | READ_QUEUED;
|
|
var READ_RESUMED_READ_AHEAD = READ_RESUMED | READ_READ_AHEAD;
|
|
var READ_NOT_ACTIVE = MAX ^ READ_ACTIVE;
|
|
var READ_NON_PRIMARY = MAX ^ READ_PRIMARY;
|
|
var READ_NON_PRIMARY_AND_PUSHED = MAX ^ (READ_PRIMARY | READ_NEEDS_PUSH);
|
|
var READ_PUSHED = MAX ^ READ_NEEDS_PUSH;
|
|
var READ_PAUSED = MAX ^ READ_RESUMED;
|
|
var READ_NOT_QUEUED = MAX ^ (READ_QUEUED | READ_EMITTED_READABLE);
|
|
var READ_NOT_ENDING = MAX ^ READ_ENDING;
|
|
var READ_PIPE_NOT_DRAINED = MAX ^ READ_FLOWING;
|
|
var READ_NOT_NEXT_TICK = MAX ^ READ_NEXT_TICK;
|
|
var READ_NOT_UPDATING = MAX ^ READ_UPDATING;
|
|
var READ_NO_READ_AHEAD = MAX ^ READ_READ_AHEAD;
|
|
var READ_PAUSED_NO_READ_AHEAD = MAX ^ READ_RESUMED_READ_AHEAD;
|
|
var WRITE_ACTIVE = 1 << 18;
|
|
var WRITE_UPDATING = 2 << 18;
|
|
var WRITE_PRIMARY = 4 << 18;
|
|
var WRITE_QUEUED = 8 << 18;
|
|
var WRITE_UNDRAINED = 16 << 18;
|
|
var WRITE_DONE = 32 << 18;
|
|
var WRITE_EMIT_DRAIN = 64 << 18;
|
|
var WRITE_NEXT_TICK = 128 << 18;
|
|
var WRITE_WRITING = 256 << 18;
|
|
var WRITE_FINISHING = 512 << 18;
|
|
var WRITE_CORKED = 1024 << 18;
|
|
var WRITE_NOT_ACTIVE = MAX ^ (WRITE_ACTIVE | WRITE_WRITING);
|
|
var WRITE_NON_PRIMARY = MAX ^ WRITE_PRIMARY;
|
|
var WRITE_NOT_FINISHING = MAX ^ (WRITE_ACTIVE | WRITE_FINISHING);
|
|
var WRITE_DRAINED = MAX ^ WRITE_UNDRAINED;
|
|
var WRITE_NOT_QUEUED = MAX ^ WRITE_QUEUED;
|
|
var WRITE_NOT_NEXT_TICK = MAX ^ WRITE_NEXT_TICK;
|
|
var WRITE_NOT_UPDATING = MAX ^ WRITE_UPDATING;
|
|
var WRITE_NOT_CORKED = MAX ^ WRITE_CORKED;
|
|
var ACTIVE = READ_ACTIVE | WRITE_ACTIVE;
|
|
var NOT_ACTIVE = MAX ^ ACTIVE;
|
|
var DONE = READ_DONE | WRITE_DONE;
|
|
var DESTROY_STATUS = DESTROYING | DESTROYED | PREDESTROYING;
|
|
var OPEN_STATUS = DESTROY_STATUS | OPENING;
|
|
var AUTO_DESTROY = DESTROY_STATUS | DONE;
|
|
var NON_PRIMARY = WRITE_NON_PRIMARY & READ_NON_PRIMARY;
|
|
var ACTIVE_OR_TICKING = WRITE_NEXT_TICK | READ_NEXT_TICK;
|
|
var TICKING = ACTIVE_OR_TICKING & NOT_ACTIVE;
|
|
var IS_OPENING = OPEN_STATUS | TICKING;
|
|
var READ_PRIMARY_STATUS = OPEN_STATUS | READ_ENDING | READ_DONE;
|
|
var READ_STATUS = OPEN_STATUS | READ_DONE | READ_QUEUED;
|
|
var READ_ENDING_STATUS = OPEN_STATUS | READ_ENDING | READ_QUEUED;
|
|
var READ_READABLE_STATUS = OPEN_STATUS | READ_EMIT_READABLE | READ_QUEUED | READ_EMITTED_READABLE;
|
|
var SHOULD_NOT_READ = OPEN_STATUS | READ_ACTIVE | READ_ENDING | READ_DONE | READ_NEEDS_PUSH | READ_READ_AHEAD;
|
|
var READ_BACKPRESSURE_STATUS = DESTROY_STATUS | READ_ENDING | READ_DONE;
|
|
var READ_UPDATE_SYNC_STATUS = READ_UPDATING | OPEN_STATUS | READ_NEXT_TICK | READ_PRIMARY;
|
|
var READ_NEXT_TICK_OR_OPENING = READ_NEXT_TICK | OPENING;
|
|
var WRITE_PRIMARY_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_DONE;
|
|
var WRITE_QUEUED_AND_UNDRAINED = WRITE_QUEUED | WRITE_UNDRAINED;
|
|
var WRITE_QUEUED_AND_ACTIVE = WRITE_QUEUED | WRITE_ACTIVE;
|
|
var WRITE_DRAIN_STATUS = WRITE_QUEUED | WRITE_UNDRAINED | OPEN_STATUS | WRITE_ACTIVE;
|
|
var WRITE_STATUS = OPEN_STATUS | WRITE_ACTIVE | WRITE_QUEUED | WRITE_CORKED;
|
|
var WRITE_PRIMARY_AND_ACTIVE = WRITE_PRIMARY | WRITE_ACTIVE;
|
|
var WRITE_ACTIVE_AND_WRITING = WRITE_ACTIVE | WRITE_WRITING;
|
|
var WRITE_FINISHING_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_QUEUED_AND_ACTIVE | WRITE_DONE;
|
|
var WRITE_BACKPRESSURE_STATUS = WRITE_UNDRAINED | DESTROY_STATUS | WRITE_FINISHING | WRITE_DONE;
|
|
var WRITE_UPDATE_SYNC_STATUS = WRITE_UPDATING | OPEN_STATUS | WRITE_NEXT_TICK | WRITE_PRIMARY;
|
|
var WRITE_DROP_DATA = WRITE_FINISHING | WRITE_DONE | DESTROY_STATUS;
|
|
var asyncIterator = Symbol.asyncIterator || Symbol("asyncIterator");
|
|
var WritableState = class {
|
|
constructor(stream, { highWaterMark = 16384, map = null, mapWritable, byteLength, byteLengthWritable } = {}) {
|
|
this.stream = stream;
|
|
this.queue = new FIFO();
|
|
this.highWaterMark = highWaterMark;
|
|
this.buffered = 0;
|
|
this.error = null;
|
|
this.pipeline = null;
|
|
this.drains = null;
|
|
this.byteLength = byteLengthWritable || byteLength || defaultByteLength;
|
|
this.map = mapWritable || map;
|
|
this.afterWrite = afterWrite.bind(this);
|
|
this.afterUpdateNextTick = updateWriteNT.bind(this);
|
|
}
|
|
get ending() {
|
|
return (this.stream._duplexState & WRITE_FINISHING) !== 0;
|
|
}
|
|
get ended() {
|
|
return (this.stream._duplexState & WRITE_DONE) !== 0;
|
|
}
|
|
push(data) {
|
|
if ((this.stream._duplexState & WRITE_DROP_DATA) !== 0) return false;
|
|
if (this.map !== null) data = this.map(data);
|
|
this.buffered += this.byteLength(data);
|
|
this.queue.push(data);
|
|
if (this.buffered < this.highWaterMark) {
|
|
this.stream._duplexState |= WRITE_QUEUED;
|
|
return true;
|
|
}
|
|
this.stream._duplexState |= WRITE_QUEUED_AND_UNDRAINED;
|
|
return false;
|
|
}
|
|
shift() {
|
|
const data = this.queue.shift();
|
|
this.buffered -= this.byteLength(data);
|
|
if (this.buffered === 0) this.stream._duplexState &= WRITE_NOT_QUEUED;
|
|
return data;
|
|
}
|
|
end(data) {
|
|
if (typeof data === "function") this.stream.once("finish", data);
|
|
else if (data !== void 0 && data !== null) this.push(data);
|
|
this.stream._duplexState = (this.stream._duplexState | WRITE_FINISHING) & WRITE_NON_PRIMARY;
|
|
}
|
|
autoBatch(data, cb) {
|
|
const buffer = [];
|
|
const stream = this.stream;
|
|
buffer.push(data);
|
|
while ((stream._duplexState & WRITE_STATUS) === WRITE_QUEUED_AND_ACTIVE) {
|
|
buffer.push(stream._writableState.shift());
|
|
}
|
|
if ((stream._duplexState & OPEN_STATUS) !== 0) return cb(null);
|
|
stream._writev(buffer, cb);
|
|
}
|
|
update() {
|
|
const stream = this.stream;
|
|
stream._duplexState |= WRITE_UPDATING;
|
|
do {
|
|
while ((stream._duplexState & WRITE_STATUS) === WRITE_QUEUED) {
|
|
const data = this.shift();
|
|
stream._duplexState |= WRITE_ACTIVE_AND_WRITING;
|
|
stream._write(data, this.afterWrite);
|
|
}
|
|
if ((stream._duplexState & WRITE_PRIMARY_AND_ACTIVE) === 0) this.updateNonPrimary();
|
|
} while (this.continueUpdate() === true);
|
|
stream._duplexState &= WRITE_NOT_UPDATING;
|
|
}
|
|
updateNonPrimary() {
|
|
const stream = this.stream;
|
|
if ((stream._duplexState & WRITE_FINISHING_STATUS) === WRITE_FINISHING) {
|
|
stream._duplexState = stream._duplexState | WRITE_ACTIVE;
|
|
stream._final(afterFinal.bind(this));
|
|
return;
|
|
}
|
|
if ((stream._duplexState & DESTROY_STATUS) === DESTROYING) {
|
|
if ((stream._duplexState & ACTIVE_OR_TICKING) === 0) {
|
|
stream._duplexState |= ACTIVE;
|
|
stream._destroy(afterDestroy.bind(this));
|
|
}
|
|
return;
|
|
}
|
|
if ((stream._duplexState & IS_OPENING) === OPENING) {
|
|
stream._duplexState = (stream._duplexState | ACTIVE) & NOT_OPENING;
|
|
stream._open(afterOpen.bind(this));
|
|
}
|
|
}
|
|
continueUpdate() {
|
|
if ((this.stream._duplexState & WRITE_NEXT_TICK) === 0) return false;
|
|
this.stream._duplexState &= WRITE_NOT_NEXT_TICK;
|
|
return true;
|
|
}
|
|
updateCallback() {
|
|
if ((this.stream._duplexState & WRITE_UPDATE_SYNC_STATUS) === WRITE_PRIMARY) this.update();
|
|
else this.updateNextTick();
|
|
}
|
|
updateNextTick() {
|
|
if ((this.stream._duplexState & WRITE_NEXT_TICK) !== 0) return;
|
|
this.stream._duplexState |= WRITE_NEXT_TICK;
|
|
if ((this.stream._duplexState & WRITE_UPDATING) === 0) qmt(this.afterUpdateNextTick);
|
|
}
|
|
};
|
|
var ReadableState = class {
|
|
constructor(stream, { highWaterMark = 16384, map = null, mapReadable, byteLength, byteLengthReadable } = {}) {
|
|
this.stream = stream;
|
|
this.queue = new FIFO();
|
|
this.highWaterMark = highWaterMark === 0 ? 1 : highWaterMark;
|
|
this.buffered = 0;
|
|
this.readAhead = highWaterMark > 0;
|
|
this.error = null;
|
|
this.pipeline = null;
|
|
this.byteLength = byteLengthReadable || byteLength || defaultByteLength;
|
|
this.map = mapReadable || map;
|
|
this.pipeTo = null;
|
|
this.afterRead = afterRead.bind(this);
|
|
this.afterUpdateNextTick = updateReadNT.bind(this);
|
|
}
|
|
get ending() {
|
|
return (this.stream._duplexState & READ_ENDING) !== 0;
|
|
}
|
|
get ended() {
|
|
return (this.stream._duplexState & READ_DONE) !== 0;
|
|
}
|
|
pipe(pipeTo, cb) {
|
|
if (this.pipeTo !== null) throw new Error("Can only pipe to one destination");
|
|
if (typeof cb !== "function") cb = null;
|
|
this.stream._duplexState |= READ_PIPE_DRAINED;
|
|
this.pipeTo = pipeTo;
|
|
this.pipeline = new Pipeline(this.stream, pipeTo, cb);
|
|
if (cb) this.stream.on("error", noop);
|
|
if (isStreamx(pipeTo)) {
|
|
pipeTo._writableState.pipeline = this.pipeline;
|
|
if (cb) pipeTo.on("error", noop);
|
|
pipeTo.on("finish", this.pipeline.finished.bind(this.pipeline));
|
|
} else {
|
|
const onerror = this.pipeline.done.bind(this.pipeline, pipeTo);
|
|
const onclose = this.pipeline.done.bind(this.pipeline, pipeTo, null);
|
|
pipeTo.on("error", onerror);
|
|
pipeTo.on("close", onclose);
|
|
pipeTo.on("finish", this.pipeline.finished.bind(this.pipeline));
|
|
}
|
|
pipeTo.on("drain", afterDrain.bind(this));
|
|
this.stream.emit("piping", pipeTo);
|
|
pipeTo.emit("pipe", this.stream);
|
|
}
|
|
push(data) {
|
|
const stream = this.stream;
|
|
if (data === null) {
|
|
this.highWaterMark = 0;
|
|
stream._duplexState = (stream._duplexState | READ_ENDING) & READ_NON_PRIMARY_AND_PUSHED;
|
|
return false;
|
|
}
|
|
if (this.map !== null) {
|
|
data = this.map(data);
|
|
if (data === null) {
|
|
stream._duplexState &= READ_PUSHED;
|
|
return this.buffered < this.highWaterMark;
|
|
}
|
|
}
|
|
this.buffered += this.byteLength(data);
|
|
this.queue.push(data);
|
|
stream._duplexState = (stream._duplexState | READ_QUEUED) & READ_PUSHED;
|
|
return this.buffered < this.highWaterMark;
|
|
}
|
|
shift() {
|
|
const data = this.queue.shift();
|
|
this.buffered -= this.byteLength(data);
|
|
if (this.buffered === 0) this.stream._duplexState &= READ_NOT_QUEUED;
|
|
return data;
|
|
}
|
|
unshift(data) {
|
|
const pending = [this.map !== null ? this.map(data) : data];
|
|
while (this.buffered > 0) pending.push(this.shift());
|
|
for (let i = 0; i < pending.length - 1; i++) {
|
|
const data2 = pending[i];
|
|
this.buffered += this.byteLength(data2);
|
|
this.queue.push(data2);
|
|
}
|
|
this.push(pending[pending.length - 1]);
|
|
}
|
|
read() {
|
|
const stream = this.stream;
|
|
if ((stream._duplexState & READ_STATUS) === READ_QUEUED) {
|
|
const data = this.shift();
|
|
if (this.pipeTo !== null && this.pipeTo.write(data) === false)
|
|
stream._duplexState &= READ_PIPE_NOT_DRAINED;
|
|
if ((stream._duplexState & READ_EMIT_DATA) !== 0) stream.emit("data", data);
|
|
return data;
|
|
}
|
|
if (this.readAhead === false) {
|
|
stream._duplexState |= READ_READ_AHEAD;
|
|
this.updateNextTick();
|
|
}
|
|
return null;
|
|
}
|
|
drain() {
|
|
const stream = this.stream;
|
|
while ((stream._duplexState & READ_STATUS) === READ_QUEUED && (stream._duplexState & READ_FLOWING) !== 0) {
|
|
const data = this.shift();
|
|
if (this.pipeTo !== null && this.pipeTo.write(data) === false)
|
|
stream._duplexState &= READ_PIPE_NOT_DRAINED;
|
|
if ((stream._duplexState & READ_EMIT_DATA) !== 0) stream.emit("data", data);
|
|
}
|
|
}
|
|
update() {
|
|
const stream = this.stream;
|
|
stream._duplexState |= READ_UPDATING;
|
|
do {
|
|
this.drain();
|
|
while (this.buffered < this.highWaterMark && (stream._duplexState & SHOULD_NOT_READ) === READ_READ_AHEAD) {
|
|
stream._duplexState |= READ_ACTIVE_AND_NEEDS_PUSH;
|
|
stream._read(this.afterRead);
|
|
this.drain();
|
|
}
|
|
if ((stream._duplexState & READ_READABLE_STATUS) === READ_EMIT_READABLE_AND_QUEUED) {
|
|
stream._duplexState |= READ_EMITTED_READABLE;
|
|
stream.emit("readable");
|
|
}
|
|
if ((stream._duplexState & READ_PRIMARY_AND_ACTIVE) === 0) this.updateNonPrimary();
|
|
} while (this.continueUpdate() === true);
|
|
stream._duplexState &= READ_NOT_UPDATING;
|
|
}
|
|
updateNonPrimary() {
|
|
const stream = this.stream;
|
|
if ((stream._duplexState & READ_ENDING_STATUS) === READ_ENDING) {
|
|
stream._duplexState = (stream._duplexState | READ_DONE) & READ_NOT_ENDING;
|
|
stream.emit("end");
|
|
if ((stream._duplexState & AUTO_DESTROY) === DONE) stream._duplexState |= DESTROYING;
|
|
if (this.pipeTo !== null) this.pipeTo.end();
|
|
}
|
|
if ((stream._duplexState & DESTROY_STATUS) === DESTROYING) {
|
|
if ((stream._duplexState & ACTIVE_OR_TICKING) === 0) {
|
|
stream._duplexState |= ACTIVE;
|
|
stream._destroy(afterDestroy.bind(this));
|
|
}
|
|
return;
|
|
}
|
|
if ((stream._duplexState & IS_OPENING) === OPENING) {
|
|
stream._duplexState = (stream._duplexState | ACTIVE) & NOT_OPENING;
|
|
stream._open(afterOpen.bind(this));
|
|
}
|
|
}
|
|
continueUpdate() {
|
|
if ((this.stream._duplexState & READ_NEXT_TICK) === 0) return false;
|
|
this.stream._duplexState &= READ_NOT_NEXT_TICK;
|
|
return true;
|
|
}
|
|
updateCallback() {
|
|
if ((this.stream._duplexState & READ_UPDATE_SYNC_STATUS) === READ_PRIMARY) this.update();
|
|
else this.updateNextTick();
|
|
}
|
|
updateNextTickIfOpen() {
|
|
if ((this.stream._duplexState & READ_NEXT_TICK_OR_OPENING) !== 0) return;
|
|
this.stream._duplexState |= READ_NEXT_TICK;
|
|
if ((this.stream._duplexState & READ_UPDATING) === 0) qmt(this.afterUpdateNextTick);
|
|
}
|
|
updateNextTick() {
|
|
if ((this.stream._duplexState & READ_NEXT_TICK) !== 0) return;
|
|
this.stream._duplexState |= READ_NEXT_TICK;
|
|
if ((this.stream._duplexState & READ_UPDATING) === 0) qmt(this.afterUpdateNextTick);
|
|
}
|
|
};
|
|
var TransformState = class {
|
|
constructor(stream) {
|
|
this.data = null;
|
|
this.afterTransform = afterTransform.bind(stream);
|
|
this.afterFinal = null;
|
|
}
|
|
};
|
|
var Pipeline = class {
|
|
constructor(src, dst, cb) {
|
|
this.from = src;
|
|
this.to = dst;
|
|
this.afterPipe = cb;
|
|
this.error = null;
|
|
this.pipeToFinished = false;
|
|
}
|
|
finished() {
|
|
this.pipeToFinished = true;
|
|
}
|
|
done(stream, err) {
|
|
if (err) this.error = err;
|
|
if (stream === this.to) {
|
|
this.to = null;
|
|
if (this.from !== null) {
|
|
if ((this.from._duplexState & READ_DONE) === 0 || !this.pipeToFinished) {
|
|
this.from.destroy(this.error || new Error("Writable stream closed prematurely"));
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if (stream === this.from) {
|
|
this.from = null;
|
|
if (this.to !== null) {
|
|
if ((stream._duplexState & READ_DONE) === 0) {
|
|
this.to.destroy(this.error || new Error("Readable stream closed before ending"));
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if (this.afterPipe !== null) this.afterPipe(this.error);
|
|
this.to = this.from = this.afterPipe = null;
|
|
}
|
|
};
|
|
function afterDrain() {
|
|
this.stream._duplexState |= READ_PIPE_DRAINED;
|
|
this.updateCallback();
|
|
}
|
|
function afterFinal(err) {
|
|
const stream = this.stream;
|
|
if (err) stream.destroy(err);
|
|
if ((stream._duplexState & DESTROY_STATUS) === 0) {
|
|
stream._duplexState |= WRITE_DONE;
|
|
stream.emit("finish");
|
|
}
|
|
if ((stream._duplexState & AUTO_DESTROY) === DONE) {
|
|
stream._duplexState |= DESTROYING;
|
|
}
|
|
stream._duplexState &= WRITE_NOT_FINISHING;
|
|
if ((stream._duplexState & WRITE_UPDATING) === 0) this.update();
|
|
else this.updateNextTick();
|
|
}
|
|
function afterDestroy(err) {
|
|
const stream = this.stream;
|
|
if (!err && this.error !== STREAM_DESTROYED) err = this.error;
|
|
if (err) stream.emit("error", err);
|
|
stream._duplexState |= DESTROYED;
|
|
stream.emit("close");
|
|
const rs = stream._readableState;
|
|
const ws = stream._writableState;
|
|
if (rs !== null && rs.pipeline !== null) rs.pipeline.done(stream, err);
|
|
if (ws !== null) {
|
|
while (ws.drains !== null && ws.drains.length > 0) ws.drains.shift().resolve(false);
|
|
if (ws.pipeline !== null) ws.pipeline.done(stream, err);
|
|
}
|
|
}
|
|
function afterWrite(err) {
|
|
const stream = this.stream;
|
|
if (err) stream.destroy(err);
|
|
stream._duplexState &= WRITE_NOT_ACTIVE;
|
|
if (this.drains !== null) tickDrains(this.drains);
|
|
if ((stream._duplexState & WRITE_DRAIN_STATUS) === WRITE_UNDRAINED) {
|
|
stream._duplexState &= WRITE_DRAINED;
|
|
if ((stream._duplexState & WRITE_EMIT_DRAIN) === WRITE_EMIT_DRAIN) {
|
|
stream.emit("drain");
|
|
}
|
|
}
|
|
this.updateCallback();
|
|
}
|
|
function afterRead(err) {
|
|
if (err) this.stream.destroy(err);
|
|
this.stream._duplexState &= READ_NOT_ACTIVE;
|
|
if (this.readAhead === false && (this.stream._duplexState & READ_RESUMED) === 0)
|
|
this.stream._duplexState &= READ_NO_READ_AHEAD;
|
|
this.updateCallback();
|
|
}
|
|
function updateReadNT() {
|
|
if ((this.stream._duplexState & READ_UPDATING) === 0) {
|
|
this.stream._duplexState &= READ_NOT_NEXT_TICK;
|
|
this.update();
|
|
}
|
|
}
|
|
function updateWriteNT() {
|
|
if ((this.stream._duplexState & WRITE_UPDATING) === 0) {
|
|
this.stream._duplexState &= WRITE_NOT_NEXT_TICK;
|
|
this.update();
|
|
}
|
|
}
|
|
function tickDrains(drains) {
|
|
for (let i = 0; i < drains.length; i++) {
|
|
if (--drains[i].writes === 0) {
|
|
drains.shift().resolve(true);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
function afterOpen(err) {
|
|
const stream = this.stream;
|
|
if (err) stream.destroy(err);
|
|
if ((stream._duplexState & DESTROYING) === 0) {
|
|
if ((stream._duplexState & READ_PRIMARY_STATUS) === 0) stream._duplexState |= READ_PRIMARY;
|
|
if ((stream._duplexState & WRITE_PRIMARY_STATUS) === 0) stream._duplexState |= WRITE_PRIMARY;
|
|
stream.emit("open");
|
|
}
|
|
stream._duplexState &= NOT_ACTIVE;
|
|
if (stream._writableState !== null) {
|
|
stream._writableState.updateCallback();
|
|
}
|
|
if (stream._readableState !== null) {
|
|
stream._readableState.updateCallback();
|
|
}
|
|
}
|
|
function afterTransform(err, data) {
|
|
if (data !== void 0 && data !== null) this.push(data);
|
|
this._writableState.afterWrite(err);
|
|
}
|
|
function newListener(name) {
|
|
if (this._readableState !== null) {
|
|
if (name === "data") {
|
|
this._duplexState |= READ_EMIT_DATA | READ_RESUMED_READ_AHEAD;
|
|
this._readableState.updateNextTick();
|
|
}
|
|
if (name === "readable") {
|
|
this._duplexState |= READ_EMIT_READABLE;
|
|
this._readableState.updateNextTick();
|
|
}
|
|
}
|
|
if (this._writableState !== null) {
|
|
if (name === "drain") {
|
|
this._duplexState |= WRITE_EMIT_DRAIN;
|
|
this._writableState.updateNextTick();
|
|
}
|
|
}
|
|
}
|
|
var Stream = class extends EventEmitter {
|
|
constructor(opts) {
|
|
super();
|
|
this._duplexState = 0;
|
|
this._readableState = null;
|
|
this._writableState = null;
|
|
if (opts) {
|
|
if (opts.open) this._open = opts.open;
|
|
if (opts.destroy) this._destroy = opts.destroy;
|
|
if (opts.predestroy) this._predestroy = opts.predestroy;
|
|
if (opts.signal) {
|
|
opts.signal.addEventListener("abort", abort.bind(this));
|
|
}
|
|
}
|
|
this.on("newListener", newListener);
|
|
}
|
|
_open(cb) {
|
|
cb(null);
|
|
}
|
|
_destroy(cb) {
|
|
cb(null);
|
|
}
|
|
_predestroy() {
|
|
}
|
|
get readable() {
|
|
return this._readableState !== null ? true : void 0;
|
|
}
|
|
get writable() {
|
|
return this._writableState !== null ? true : void 0;
|
|
}
|
|
get destroyed() {
|
|
return (this._duplexState & DESTROYED) !== 0;
|
|
}
|
|
get destroying() {
|
|
return (this._duplexState & DESTROY_STATUS) !== 0;
|
|
}
|
|
destroy(err) {
|
|
if ((this._duplexState & DESTROY_STATUS) === 0) {
|
|
if (!err) err = STREAM_DESTROYED;
|
|
this._duplexState = (this._duplexState | DESTROYING) & NON_PRIMARY;
|
|
if (this._readableState !== null) {
|
|
this._readableState.highWaterMark = 0;
|
|
this._readableState.error = err;
|
|
}
|
|
if (this._writableState !== null) {
|
|
this._writableState.highWaterMark = 0;
|
|
this._writableState.error = err;
|
|
}
|
|
this._duplexState |= PREDESTROYING;
|
|
this._predestroy();
|
|
this._duplexState &= NOT_PREDESTROYING;
|
|
if (this._readableState !== null) this._readableState.updateNextTick();
|
|
if (this._writableState !== null) this._writableState.updateNextTick();
|
|
}
|
|
}
|
|
};
|
|
var Readable = class _Readable extends Stream {
|
|
constructor(opts) {
|
|
super(opts);
|
|
this._duplexState |= OPENING | WRITE_DONE | READ_READ_AHEAD;
|
|
this._readableState = new ReadableState(this, opts);
|
|
if (opts) {
|
|
if (this._readableState.readAhead === false) this._duplexState &= READ_NO_READ_AHEAD;
|
|
if (opts.read) this._read = opts.read;
|
|
if (opts.eagerOpen) this._readableState.updateNextTick();
|
|
if (opts.encoding) this.setEncoding(opts.encoding);
|
|
}
|
|
}
|
|
setEncoding(encoding) {
|
|
const dec = new TextDecoder(encoding);
|
|
const map = this._readableState.map || echo;
|
|
this._readableState.map = mapOrSkip;
|
|
return this;
|
|
function mapOrSkip(data) {
|
|
const next = dec.push(data);
|
|
return next === "" && (data.byteLength !== 0 || dec.remaining > 0) ? null : map(next);
|
|
}
|
|
}
|
|
_read(cb) {
|
|
cb(null);
|
|
}
|
|
pipe(dest, cb) {
|
|
this._readableState.updateNextTick();
|
|
this._readableState.pipe(dest, cb);
|
|
return dest;
|
|
}
|
|
read() {
|
|
this._readableState.updateNextTick();
|
|
return this._readableState.read();
|
|
}
|
|
push(data) {
|
|
this._readableState.updateNextTickIfOpen();
|
|
return this._readableState.push(data);
|
|
}
|
|
unshift(data) {
|
|
this._readableState.updateNextTickIfOpen();
|
|
return this._readableState.unshift(data);
|
|
}
|
|
resume() {
|
|
this._duplexState |= READ_RESUMED_READ_AHEAD;
|
|
this._readableState.updateNextTick();
|
|
return this;
|
|
}
|
|
pause() {
|
|
this._duplexState &= this._readableState.readAhead === false ? READ_PAUSED_NO_READ_AHEAD : READ_PAUSED;
|
|
return this;
|
|
}
|
|
static _fromAsyncIterator(ite, opts) {
|
|
let destroy;
|
|
const rs = new _Readable({
|
|
...opts,
|
|
read(cb) {
|
|
ite.next().then(push).then(cb.bind(null, null)).catch(cb);
|
|
},
|
|
predestroy() {
|
|
destroy = ite.return();
|
|
},
|
|
destroy(cb) {
|
|
if (!destroy) return cb(null);
|
|
destroy.then(cb.bind(null, null)).catch(cb);
|
|
}
|
|
});
|
|
return rs;
|
|
function push(data) {
|
|
if (data.done) rs.push(null);
|
|
else rs.push(data.value);
|
|
}
|
|
}
|
|
static from(data, opts) {
|
|
if (isReadStreamx(data)) return data;
|
|
if (data[asyncIterator]) return this._fromAsyncIterator(data[asyncIterator](), opts);
|
|
if (!Array.isArray(data)) data = data === void 0 ? [] : [data];
|
|
let i = 0;
|
|
return new _Readable({
|
|
...opts,
|
|
read(cb) {
|
|
this.push(i === data.length ? null : data[i++]);
|
|
cb(null);
|
|
}
|
|
});
|
|
}
|
|
static isBackpressured(rs) {
|
|
return (rs._duplexState & READ_BACKPRESSURE_STATUS) !== 0 || rs._readableState.buffered >= rs._readableState.highWaterMark;
|
|
}
|
|
static isPaused(rs) {
|
|
return (rs._duplexState & READ_RESUMED) === 0;
|
|
}
|
|
[asyncIterator]() {
|
|
const stream = this;
|
|
let error = null;
|
|
let promiseResolve = null;
|
|
let promiseReject = null;
|
|
this.on("error", (err) => {
|
|
error = err;
|
|
});
|
|
this.on("readable", onreadable);
|
|
this.on("close", onclose);
|
|
return {
|
|
[asyncIterator]() {
|
|
return this;
|
|
},
|
|
next() {
|
|
return new Promise(function(resolve, reject) {
|
|
promiseResolve = resolve;
|
|
promiseReject = reject;
|
|
const data = stream.read();
|
|
if (data !== null) ondata(data);
|
|
else if ((stream._duplexState & DESTROYED) !== 0) ondata(null);
|
|
});
|
|
},
|
|
return() {
|
|
return destroy(null);
|
|
},
|
|
throw(err) {
|
|
return destroy(err);
|
|
}
|
|
};
|
|
function onreadable() {
|
|
if (promiseResolve !== null) ondata(stream.read());
|
|
}
|
|
function onclose() {
|
|
if (promiseResolve !== null) ondata(null);
|
|
}
|
|
function ondata(data) {
|
|
if (promiseReject === null) return;
|
|
if (error) promiseReject(error);
|
|
else if (data === null && (stream._duplexState & READ_DONE) === 0)
|
|
promiseReject(STREAM_DESTROYED);
|
|
else promiseResolve({ value: data, done: data === null });
|
|
promiseReject = promiseResolve = null;
|
|
}
|
|
function destroy(err) {
|
|
stream.destroy(err);
|
|
return new Promise((resolve, reject) => {
|
|
if (stream._duplexState & DESTROYED) return resolve({ value: void 0, done: true });
|
|
stream.once("close", function() {
|
|
if (err) reject(err);
|
|
else resolve({ value: void 0, done: true });
|
|
});
|
|
});
|
|
}
|
|
}
|
|
};
|
|
var Writable = class extends Stream {
|
|
constructor(opts) {
|
|
super(opts);
|
|
this._duplexState |= OPENING | READ_DONE;
|
|
this._writableState = new WritableState(this, opts);
|
|
if (opts) {
|
|
if (opts.writev) this._writev = opts.writev;
|
|
if (opts.write) this._write = opts.write;
|
|
if (opts.final) this._final = opts.final;
|
|
if (opts.eagerOpen) this._writableState.updateNextTick();
|
|
}
|
|
}
|
|
cork() {
|
|
this._duplexState |= WRITE_CORKED;
|
|
}
|
|
uncork() {
|
|
this._duplexState &= WRITE_NOT_CORKED;
|
|
this._writableState.updateNextTick();
|
|
}
|
|
_writev(batch, cb) {
|
|
cb(null);
|
|
}
|
|
_write(data, cb) {
|
|
this._writableState.autoBatch(data, cb);
|
|
}
|
|
_final(cb) {
|
|
cb(null);
|
|
}
|
|
static isBackpressured(ws) {
|
|
return (ws._duplexState & WRITE_BACKPRESSURE_STATUS) !== 0;
|
|
}
|
|
static drained(ws) {
|
|
if (ws.destroyed) return Promise.resolve(false);
|
|
const state = ws._writableState;
|
|
const pending = isWritev(ws) ? Math.min(1, state.queue.length) : state.queue.length;
|
|
const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
|
|
if (writes === 0) return Promise.resolve(true);
|
|
if (state.drains === null) state.drains = [];
|
|
return new Promise((resolve) => {
|
|
state.drains.push({ writes, resolve });
|
|
});
|
|
}
|
|
write(data) {
|
|
this._writableState.updateNextTick();
|
|
return this._writableState.push(data);
|
|
}
|
|
end(data) {
|
|
this._writableState.updateNextTick();
|
|
this._writableState.end(data);
|
|
return this;
|
|
}
|
|
};
|
|
var Duplex = class extends Readable {
|
|
// and Writable
|
|
constructor(opts) {
|
|
super(opts);
|
|
this._duplexState = OPENING | this._duplexState & READ_READ_AHEAD;
|
|
this._writableState = new WritableState(this, opts);
|
|
if (opts) {
|
|
if (opts.writev) this._writev = opts.writev;
|
|
if (opts.write) this._write = opts.write;
|
|
if (opts.final) this._final = opts.final;
|
|
}
|
|
}
|
|
cork() {
|
|
this._duplexState |= WRITE_CORKED;
|
|
}
|
|
uncork() {
|
|
this._duplexState &= WRITE_NOT_CORKED;
|
|
this._writableState.updateNextTick();
|
|
}
|
|
_writev(batch, cb) {
|
|
cb(null);
|
|
}
|
|
_write(data, cb) {
|
|
this._writableState.autoBatch(data, cb);
|
|
}
|
|
_final(cb) {
|
|
cb(null);
|
|
}
|
|
write(data) {
|
|
this._writableState.updateNextTick();
|
|
return this._writableState.push(data);
|
|
}
|
|
end(data) {
|
|
this._writableState.updateNextTick();
|
|
this._writableState.end(data);
|
|
return this;
|
|
}
|
|
};
|
|
var Transform = class extends Duplex {
|
|
constructor(opts) {
|
|
super(opts);
|
|
this._transformState = new TransformState(this);
|
|
if (opts) {
|
|
if (opts.transform) this._transform = opts.transform;
|
|
if (opts.flush) this._flush = opts.flush;
|
|
}
|
|
}
|
|
_write(data, cb) {
|
|
if (this._readableState.buffered >= this._readableState.highWaterMark) {
|
|
this._transformState.data = data;
|
|
} else {
|
|
this._transform(data, this._transformState.afterTransform);
|
|
}
|
|
}
|
|
_read(cb) {
|
|
if (this._transformState.data !== null) {
|
|
const data = this._transformState.data;
|
|
this._transformState.data = null;
|
|
cb(null);
|
|
this._transform(data, this._transformState.afterTransform);
|
|
} else {
|
|
cb(null);
|
|
}
|
|
}
|
|
destroy(err) {
|
|
super.destroy(err);
|
|
if (this._transformState.data !== null) {
|
|
this._transformState.data = null;
|
|
this._transformState.afterTransform();
|
|
}
|
|
}
|
|
_transform(data, cb) {
|
|
cb(null, data);
|
|
}
|
|
_flush(cb) {
|
|
cb(null);
|
|
}
|
|
_final(cb) {
|
|
this._transformState.afterFinal = cb;
|
|
this._flush(transformAfterFlush.bind(this));
|
|
}
|
|
};
|
|
var PassThrough = class extends Transform {
|
|
};
|
|
function transformAfterFlush(err, data) {
|
|
const cb = this._transformState.afterFinal;
|
|
if (err) return cb(err);
|
|
if (data !== null && data !== void 0) this.push(data);
|
|
this.push(null);
|
|
cb(null);
|
|
}
|
|
function pipelinePromise(...streams) {
|
|
return new Promise((resolve, reject) => {
|
|
return pipeline(...streams, (err) => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
function pipeline(stream, ...streams) {
|
|
const all = Array.isArray(stream) ? [...stream, ...streams] : [stream, ...streams];
|
|
const done = all.length && typeof all[all.length - 1] === "function" ? all.pop() : null;
|
|
if (all.length < 2) throw new Error("Pipeline requires at least 2 streams");
|
|
let src = all[0];
|
|
let dest = null;
|
|
let error = null;
|
|
for (let i = 1; i < all.length; i++) {
|
|
dest = all[i];
|
|
if (isStreamx(src)) {
|
|
src.pipe(dest, onerror);
|
|
} else {
|
|
errorHandle(src, true, i > 1, onerror);
|
|
src.pipe(dest);
|
|
}
|
|
src = dest;
|
|
}
|
|
if (done) {
|
|
let fin = false;
|
|
const autoDestroy = isStreamx(dest) || !!(dest._writableState && dest._writableState.autoDestroy);
|
|
dest.on("error", (err) => {
|
|
if (error === null) error = err;
|
|
});
|
|
dest.on("finish", () => {
|
|
fin = true;
|
|
if (!autoDestroy) done(error);
|
|
});
|
|
if (autoDestroy) {
|
|
dest.on("close", () => done(error || (fin ? null : PREMATURE_CLOSE)));
|
|
}
|
|
}
|
|
return dest;
|
|
function errorHandle(s, rd, wr, onerror2) {
|
|
s.on("error", onerror2);
|
|
s.on("close", onclose);
|
|
function onclose() {
|
|
if (rd && s._readableState && !s._readableState.ended) return onerror2(PREMATURE_CLOSE);
|
|
if (wr && s._writableState && !s._writableState.ended) return onerror2(PREMATURE_CLOSE);
|
|
}
|
|
}
|
|
function onerror(err) {
|
|
if (!err || error) return;
|
|
error = err;
|
|
for (const s of all) {
|
|
s.destroy(err);
|
|
}
|
|
}
|
|
}
|
|
function echo(s) {
|
|
return s;
|
|
}
|
|
function isStream(stream) {
|
|
return !!stream._readableState || !!stream._writableState;
|
|
}
|
|
function isStreamx(stream) {
|
|
return typeof stream._duplexState === "number" && isStream(stream);
|
|
}
|
|
function isEnding(stream) {
|
|
return !!stream._readableState && stream._readableState.ending;
|
|
}
|
|
function isEnded(stream) {
|
|
return !!stream._readableState && stream._readableState.ended;
|
|
}
|
|
function isFinishing(stream) {
|
|
return !!stream._writableState && stream._writableState.ending;
|
|
}
|
|
function isFinished(stream) {
|
|
return !!stream._writableState && stream._writableState.ended;
|
|
}
|
|
function getStreamError(stream, opts = {}) {
|
|
const err = stream._readableState && stream._readableState.error || stream._writableState && stream._writableState.error;
|
|
return !opts.all && err === STREAM_DESTROYED ? null : err;
|
|
}
|
|
function isReadStreamx(stream) {
|
|
return isStreamx(stream) && stream.readable;
|
|
}
|
|
function isDisturbed(stream) {
|
|
return (stream._duplexState & OPENING) !== OPENING || (stream._duplexState & DESTROYING) === DESTROYING || (stream._duplexState & ACTIVE_OR_TICKING) !== 0;
|
|
}
|
|
function isTypedArray(data) {
|
|
return typeof data === "object" && data !== null && typeof data.byteLength === "number";
|
|
}
|
|
function defaultByteLength(data) {
|
|
return isTypedArray(data) ? data.byteLength : 1024;
|
|
}
|
|
function noop() {
|
|
}
|
|
function abort() {
|
|
this.destroy(new Error("Stream aborted."));
|
|
}
|
|
function isWritev(s) {
|
|
return s._writev !== Writable.prototype._writev && s._writev !== Duplex.prototype._writev;
|
|
}
|
|
module.exports = {
|
|
pipeline,
|
|
pipelinePromise,
|
|
isStream,
|
|
isStreamx,
|
|
isEnding,
|
|
isEnded,
|
|
isFinishing,
|
|
isFinished,
|
|
isDisturbed,
|
|
getStreamError,
|
|
Stream,
|
|
Writable,
|
|
Readable,
|
|
Duplex,
|
|
Transform,
|
|
// Export PassThrough for compatibility with Node.js core's stream module
|
|
PassThrough
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/localdrive/streams.js
|
|
var require_streams = __commonJS({
|
|
"../../node_modules/localdrive/streams.js"(exports, module) {
|
|
var { Readable, Writable } = require_streamx();
|
|
var fs = __require("fs");
|
|
var fsp = __require("fs/promises");
|
|
var path = __require("path");
|
|
var b4a = require_b4a();
|
|
var FileWriteStream = class extends Writable {
|
|
constructor(filename, key, drive, opts = {}) {
|
|
super({ map });
|
|
this.filename = filename;
|
|
this.atomicFilename = this.filename;
|
|
this.key = key;
|
|
this.drive = drive;
|
|
this.executable = !!opts.executable;
|
|
this.metadata = opts.metadata || null;
|
|
this.fd = 0;
|
|
}
|
|
_open(cb) {
|
|
this._openp().then(cb, cb);
|
|
}
|
|
_final(cb) {
|
|
this._finalp().then(cb, cb);
|
|
}
|
|
_destroy(cb) {
|
|
this._destroyp().then(cb, cb);
|
|
}
|
|
async _openp() {
|
|
this.atomicFilename = this.drive._alloc(this.filename);
|
|
const release = await this.drive._lock();
|
|
const mode = this.executable ? 484 : 420;
|
|
try {
|
|
await fsp.mkdir(path.dirname(this.filename), { recursive: true });
|
|
this.fd = await openFilePromise(this.atomicFilename, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_TRUNC | fs.constants.O_APPEND, mode);
|
|
} finally {
|
|
release();
|
|
}
|
|
const st = await fstatPromise(this.fd);
|
|
if (this.executable !== !!(st.mode & fs.constants.S_IXUSR)) {
|
|
await fchmodPromise(this.fd, mode);
|
|
}
|
|
}
|
|
_writev(datas, cb) {
|
|
fs.writev(this.fd, datas, cb);
|
|
}
|
|
async _destroyp(cb) {
|
|
if (this.fd) await closeFilePromise(this.fd);
|
|
if (this.atomicFilename !== this.filename) {
|
|
await unlinkSafe(this.atomicFilename);
|
|
this._free();
|
|
}
|
|
}
|
|
async _finalp() {
|
|
if (this.metadata === null) {
|
|
if (this.drive.metadata.del) {
|
|
await this.drive.metadata.del(this.key);
|
|
}
|
|
} else if (this.drive.metadata.put) {
|
|
await this.drive.metadata.put(this.key, this.metadata);
|
|
}
|
|
const fd = this.fd;
|
|
this.fd = 0;
|
|
await closeFilePromise(fd);
|
|
if (this.atomicFilename !== this.filename) {
|
|
await renameFilePromise(this.atomicFilename, this.filename);
|
|
this._free();
|
|
}
|
|
}
|
|
_free() {
|
|
if (this.atomicFilename === this.filename) return;
|
|
this.drive._free(this.atomicFilename);
|
|
this.atomicFilename = this.filename;
|
|
}
|
|
};
|
|
var FileReadStream = class extends Readable {
|
|
constructor(filename, opts = {}) {
|
|
super();
|
|
this.filename = filename;
|
|
this.fd = 0;
|
|
this._offset = opts.start || 0;
|
|
this._missing = 0;
|
|
if (opts.length) this._missing = opts.length;
|
|
else if (typeof opts.end === "number") this._missing = opts.end - this._offset + 1;
|
|
else this._missing = -1;
|
|
}
|
|
_open(cb) {
|
|
fs.open(this.filename, fs.constants.O_RDONLY, (err, fd) => {
|
|
if (err) return cb(err);
|
|
const onerror = (err2) => fs.close(fd, () => cb(err2));
|
|
fs.fstat(fd, (err2, st) => {
|
|
if (err2) return onerror(err2);
|
|
if (!st.isFile()) return onerror(new Error(this.filename + " is not a file"));
|
|
this.fd = fd;
|
|
if (this._missing === -1) this._missing = st.size;
|
|
if (st.size < this._offset) {
|
|
this._offset = st.size;
|
|
this._missing = 0;
|
|
return cb(null);
|
|
}
|
|
if (st.size < this._offset + this._missing) {
|
|
this._missing = st.size - this._offset;
|
|
return cb(null);
|
|
}
|
|
cb(null);
|
|
});
|
|
});
|
|
}
|
|
_read(cb) {
|
|
if (!this._missing) {
|
|
this.push(null);
|
|
return cb(null);
|
|
}
|
|
const data = b4a.allocUnsafe(Math.min(this._missing, 65536));
|
|
fs.read(this.fd, data, 0, data.byteLength, this._offset, (err, read) => {
|
|
if (err) return cb(err);
|
|
if (!read) {
|
|
this.push(null);
|
|
return cb(null);
|
|
}
|
|
if (this._missing < read) read = this._missing;
|
|
this.push(data.subarray(0, read));
|
|
this._missing -= read;
|
|
this._offset += read;
|
|
if (!this._missing) this.push(null);
|
|
cb(null);
|
|
});
|
|
}
|
|
_destroy(cb) {
|
|
if (!this.fd) return cb(null);
|
|
fs.close(this.fd, () => cb(null));
|
|
}
|
|
};
|
|
module.exports = { FileWriteStream, FileReadStream };
|
|
function map(s) {
|
|
return typeof s === "string" ? b4a.from(s) : s;
|
|
}
|
|
function openFilePromise(filename, flags, mode) {
|
|
return new Promise((resolve, reject) => {
|
|
fs.open(filename, flags, mode, function(error, fd) {
|
|
if (error) reject(error);
|
|
else resolve(fd);
|
|
});
|
|
});
|
|
}
|
|
function fstatPromise(fd) {
|
|
return new Promise((resolve, reject) => {
|
|
fs.fstat(fd, function(error, stats) {
|
|
if (error) reject(error);
|
|
else resolve(stats);
|
|
});
|
|
});
|
|
}
|
|
function fchmodPromise(fd, mode) {
|
|
return new Promise((resolve, reject) => {
|
|
fs.fchmod(fd, mode, function(error) {
|
|
if (error) reject(error);
|
|
else resolve();
|
|
});
|
|
});
|
|
}
|
|
function closeFilePromise(fd) {
|
|
return new Promise((resolve, reject) => {
|
|
fs.close(fd, function(error) {
|
|
if (error) reject(error);
|
|
else resolve();
|
|
});
|
|
});
|
|
}
|
|
function renameFilePromise(oldPath, newPath) {
|
|
return new Promise((resolve, reject) => {
|
|
fs.rename(oldPath, newPath, function(err) {
|
|
if (err) reject(err);
|
|
else resolve();
|
|
});
|
|
});
|
|
}
|
|
async function unlinkSafe(filename) {
|
|
try {
|
|
await fsp.unlink(filename);
|
|
} catch (err) {
|
|
if (err.code !== "ENOENT") throw err;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/queue-tick/queue-microtask.js
|
|
var require_queue_microtask = __commonJS({
|
|
"../../node_modules/queue-tick/queue-microtask.js"(exports, module) {
|
|
module.exports = typeof queueMicrotask === "function" ? queueMicrotask : (fn) => Promise.resolve().then(fn);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/queue-tick/process-next-tick.js
|
|
var require_process_next_tick = __commonJS({
|
|
"../../node_modules/queue-tick/process-next-tick.js"(exports, module) {
|
|
module.exports = typeof process !== "undefined" && typeof process.nextTick === "function" ? process.nextTick.bind(process) : require_queue_microtask();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/mutexify/index.js
|
|
var require_mutexify = __commonJS({
|
|
"../../node_modules/mutexify/index.js"(exports, module) {
|
|
var queueTick = require_process_next_tick();
|
|
var mutexify = function() {
|
|
var queue = [];
|
|
var used = null;
|
|
var call = function() {
|
|
used(release);
|
|
};
|
|
var acquire = function(fn) {
|
|
if (used) return queue.push(fn);
|
|
used = fn;
|
|
acquire.locked = true;
|
|
queueTick(call);
|
|
return 0;
|
|
};
|
|
acquire.locked = false;
|
|
var release = function(fn, err, value) {
|
|
used = null;
|
|
acquire.locked = false;
|
|
if (queue.length) acquire(queue.shift());
|
|
if (fn) fn(err, value);
|
|
};
|
|
return acquire;
|
|
};
|
|
module.exports = mutexify;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/mutexify/promise.js
|
|
var require_promise = __commonJS({
|
|
"../../node_modules/mutexify/promise.js"(exports, module) {
|
|
var mutexify = require_mutexify();
|
|
var mutexifyPromise = function() {
|
|
var lock = mutexify();
|
|
var acquire = function() {
|
|
return new Promise(lock);
|
|
};
|
|
Object.defineProperty(acquire, "locked", {
|
|
get: function() {
|
|
return lock.locked;
|
|
},
|
|
enumerable: true
|
|
});
|
|
return acquire;
|
|
};
|
|
module.exports = mutexifyPromise;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/same-data/index.js
|
|
var require_same_data = __commonJS({
|
|
"../../node_modules/same-data/index.js"(exports, module) {
|
|
module.exports = sameData;
|
|
function type(o) {
|
|
const t = typeof o;
|
|
return t === "object" ? Array.isArray(o) ? "array" : isTypedArray(o) ? typeof o.equals === "function" ? "buffer" : "array" : o === null ? "null" : "object" : t;
|
|
}
|
|
function isTypedArray(a) {
|
|
return !!a && typeof a.length === "number" && ArrayBuffer.isView(a.array);
|
|
}
|
|
function sameData(a, b) {
|
|
if (a === b) return true;
|
|
const ta = type(a);
|
|
const tb = type(b);
|
|
if (ta !== tb) return false;
|
|
if (ta === "buffer") return a.equals(b);
|
|
if (ta === "array") {
|
|
if (a.length !== b.length) return false;
|
|
for (let i = 0; i < a.length; i++) {
|
|
if (!sameData(a[i], b[i])) return false;
|
|
}
|
|
return true;
|
|
}
|
|
if (ta !== "object") return false;
|
|
const ea = Object.entries(a);
|
|
const eb = Object.entries(b);
|
|
if (ea.length !== eb.length) return false;
|
|
ea.sort(cmp);
|
|
eb.sort(cmp);
|
|
for (let i = 0; i < ea.length; i++) {
|
|
if (ea[i][0] !== eb[i][0] || !sameData(ea[i][1], eb[i][1])) return false;
|
|
}
|
|
return true;
|
|
}
|
|
function cmp(a, b) {
|
|
return a[0] === b[0] ? 0 : a[0] < b[0] ? -1 : 1;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/binary-stream-equals/index.js
|
|
var require_binary_stream_equals = __commonJS({
|
|
"../../node_modules/binary-stream-equals/index.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
module.exports = function(a, b) {
|
|
return new Promise((resolve, reject) => binaryEquals(a, b, resolve, reject));
|
|
};
|
|
function binaryEquals(a, b, resolve, reject) {
|
|
let aBuf = null;
|
|
let aEnded = false;
|
|
let bBuf = null;
|
|
let bEnded = false;
|
|
let closed = 0;
|
|
let done = false;
|
|
let error = null;
|
|
let equals = false;
|
|
a.on("readable", tick);
|
|
a.on("end", onend);
|
|
a.on("error", onerror);
|
|
a.on("close", onclose);
|
|
b.on("readable", tick);
|
|
b.on("end", onend);
|
|
b.on("error", onerror);
|
|
b.on("close", onclose);
|
|
function onerror(err) {
|
|
error = err;
|
|
a.destroy();
|
|
b.destroy();
|
|
}
|
|
function onclose() {
|
|
if (++closed !== 2) return;
|
|
if (error !== null && done === false) reject(error);
|
|
else resolve(equals);
|
|
}
|
|
function ondone(eq) {
|
|
if (done) return;
|
|
done = true;
|
|
equals = eq;
|
|
a.destroy();
|
|
b.destroy();
|
|
}
|
|
function onend() {
|
|
if (this === a) aEnded = true;
|
|
else bEnded = true;
|
|
tick();
|
|
}
|
|
function tick() {
|
|
while (done === false) {
|
|
if (aBuf === null) aBuf = a.read();
|
|
if (bBuf === null) bBuf = b.read();
|
|
if (aBuf === null && bBuf === null && aEnded && bEnded) {
|
|
ondone(true);
|
|
return;
|
|
}
|
|
if (aBuf !== null && (bBuf === null && bEnded)) {
|
|
ondone(false);
|
|
return;
|
|
}
|
|
if (bBuf !== null && (aBuf === null && aEnded)) {
|
|
ondone(false);
|
|
return;
|
|
}
|
|
if (aBuf === null || bBuf === null) return;
|
|
if (aBuf.byteLength === bBuf.byteLength) {
|
|
if (b4a.equals(aBuf, bBuf)) {
|
|
aBuf = bBuf = null;
|
|
continue;
|
|
}
|
|
ondone(false);
|
|
return;
|
|
}
|
|
const min = Math.min(aBuf.byteLength, bBuf.byteLength);
|
|
if (b4a.equals(aBuf.subarray(0, min), bBuf.subarray(0, min))) {
|
|
aBuf = aBuf.byteLength === min ? null : aBuf.subarray(min);
|
|
bBuf = bBuf.byteLength === min ? null : bBuf.subarray(min);
|
|
continue;
|
|
}
|
|
ondone(false);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/speedometer/index.js
|
|
var require_speedometer = __commonJS({
|
|
"../../node_modules/speedometer/index.js"(exports, module) {
|
|
var tick = 1;
|
|
var maxTick = 65535;
|
|
var resolution = 4;
|
|
var timer;
|
|
var inc = function() {
|
|
tick = tick + 1 & maxTick;
|
|
};
|
|
module.exports = function(seconds) {
|
|
if (!timer) {
|
|
timer = setInterval(inc, 1e3 / resolution | 0);
|
|
if (timer.unref) timer.unref();
|
|
}
|
|
var size = resolution * (seconds || 5);
|
|
var buffer = [0];
|
|
var pointer = 1;
|
|
var last = tick - 1 & maxTick;
|
|
return function(delta) {
|
|
var dist = tick - last & maxTick;
|
|
if (dist > size) dist = size;
|
|
last = tick;
|
|
while (dist--) {
|
|
if (pointer === size) pointer = 0;
|
|
buffer[pointer] = buffer[pointer === 0 ? size - 1 : pointer - 1];
|
|
pointer++;
|
|
}
|
|
if (delta) buffer[pointer - 1] += delta;
|
|
var top = buffer[pointer - 1];
|
|
var btm = buffer.length < size ? 0 : buffer[pointer === size ? 0 : pointer];
|
|
return buffer.length < resolution ? top : (top - btm) * resolution / buffer.length;
|
|
};
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-semver/lib/constants.js
|
|
var require_constants = __commonJS({
|
|
"../../node_modules/bare-semver/lib/constants.js"(exports, module) {
|
|
module.exports = {
|
|
EQ: 1,
|
|
LT: 2,
|
|
LTE: 3,
|
|
GT: 4,
|
|
GTE: 5
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-semver/lib/errors.js
|
|
var require_errors2 = __commonJS({
|
|
"../../node_modules/bare-semver/lib/errors.js"(exports, module) {
|
|
module.exports = class SemVerError extends Error {
|
|
constructor(msg, code, fn = SemVerError) {
|
|
super(`${code}: ${msg}`);
|
|
this.code = code;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, fn);
|
|
}
|
|
}
|
|
get name() {
|
|
return "SemVerError";
|
|
}
|
|
static INVALID_VERSION(msg, fn = SemVerError.INVALID_VERSION) {
|
|
return new SemVerError(msg, "INVALID_VERSION", fn);
|
|
}
|
|
static INVALID_RANGE(msg, fn = SemVerError.INVALID_RANGE) {
|
|
return new SemVerError(msg, "INVALID_RANGE", fn);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-semver/lib/version.js
|
|
var require_version = __commonJS({
|
|
"../../node_modules/bare-semver/lib/version.js"(exports, module) {
|
|
var errors = require_errors2();
|
|
var Version = class {
|
|
constructor(major, minor, patch, opts = {}) {
|
|
const { prerelease = [], build = [] } = opts;
|
|
this.major = major;
|
|
this.minor = minor;
|
|
this.patch = patch;
|
|
this.prerelease = prerelease;
|
|
this.build = build;
|
|
}
|
|
compare(version) {
|
|
return exports.compare(this, version);
|
|
}
|
|
toString() {
|
|
let result = `${this.major}.${this.minor}.${this.patch}`;
|
|
if (this.prerelease.length) {
|
|
result += "-" + this.prerelease.join(".");
|
|
}
|
|
if (this.build.length) {
|
|
result += "+" + this.build.join(".");
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
module.exports = exports = Version;
|
|
exports.parse = function parse2(input, state = { position: 0, partial: false, range: false }) {
|
|
let i = state.position;
|
|
let c;
|
|
const unexpected = (expected) => {
|
|
let msg;
|
|
if (i >= input.length) {
|
|
msg = `Unexpected end of input in '${input}'`;
|
|
} else {
|
|
msg = `Unexpected token '${input[i]}' in '${input}' at position ${i}`;
|
|
}
|
|
if (expected) msg += `, ${expected}`;
|
|
throw errors.INVALID_VERSION(msg, unexpected);
|
|
};
|
|
const components = [0, 0, 0];
|
|
let k = 0;
|
|
while (k < 3) {
|
|
c = input[i];
|
|
if (k > 0) {
|
|
if (c === ".") c = input[++i];
|
|
else if (state.range) break;
|
|
else unexpected("expected '.'");
|
|
}
|
|
if (c === "0") {
|
|
i++;
|
|
k++;
|
|
} else if (c >= "1" && c <= "9") {
|
|
let j = 0;
|
|
do
|
|
c = input[i + ++j];
|
|
while (c >= "0" && c <= "9");
|
|
components[k++] = parseInt(input.substring(i, i + j));
|
|
i += j;
|
|
} else unexpected("expected /[0-9]/");
|
|
}
|
|
const prerelease = [];
|
|
if (k === 3 && input[i] === "-") {
|
|
i++;
|
|
while (true) {
|
|
c = input[i];
|
|
let tag = "";
|
|
let j = 0;
|
|
while (c >= "0" && c <= "9") c = input[i + ++j];
|
|
let isNumeric = false;
|
|
if (j) {
|
|
tag += input.substring(i, i + j);
|
|
c = input[i += j];
|
|
isNumeric = tag[0] !== "0" || tag.length === 1;
|
|
}
|
|
j = 0;
|
|
while (c >= "0" && c <= "9" || c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "-")
|
|
c = input[i + ++j];
|
|
if (j) {
|
|
tag += input.substring(i, i + j);
|
|
c = input[i += j];
|
|
} else if (!isNumeric) unexpected("expected /[a-zA-Z-]/");
|
|
prerelease.push(tag);
|
|
if (c === ".") c = input[++i];
|
|
else break;
|
|
}
|
|
}
|
|
const build = [];
|
|
if (k === 3 && input[i] === "+") {
|
|
i++;
|
|
while (true) {
|
|
c = input[i];
|
|
let tag = "";
|
|
let j = 0;
|
|
while (c >= "0" && c <= "9" || c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "-")
|
|
c = input[i + ++j];
|
|
if (j) {
|
|
tag += input.substring(i, i + j);
|
|
c = input[i += j];
|
|
} else unexpected("expected /[0-9a-zA-Z-]/");
|
|
build.push(tag);
|
|
if (c === ".") c = input[++i];
|
|
else break;
|
|
}
|
|
}
|
|
if (i < input.length && state.partial === false) {
|
|
unexpected("expected end of input");
|
|
}
|
|
state.position = i;
|
|
return new Version(...components, { prerelease, build });
|
|
};
|
|
var integer = /^[0-9]+$/;
|
|
exports.compare = function compare(a, b) {
|
|
if (a.major > b.major) return 1;
|
|
if (a.major < b.major) return -1;
|
|
if (a.minor > b.minor) return 1;
|
|
if (a.minor < b.minor) return -1;
|
|
if (a.patch > b.patch) return 1;
|
|
if (a.patch < b.patch) return -1;
|
|
if (a.prerelease.length === 0) return b.prerelease.length === 0 ? 0 : 1;
|
|
if (b.prerelease.length === 0) return -1;
|
|
let i = 0;
|
|
do {
|
|
let x = a.prerelease[i];
|
|
let y = b.prerelease[i];
|
|
if (x === void 0) return y === void 0 ? 0 : -1;
|
|
if (y === void 0) return 1;
|
|
if (x === y) continue;
|
|
const xInt = integer.test(x);
|
|
const yInt = integer.test(y);
|
|
if (xInt && yInt) {
|
|
x = +x;
|
|
y = +y;
|
|
} else {
|
|
if (xInt) return -1;
|
|
if (yInt) return 1;
|
|
}
|
|
return x > y ? 1 : -1;
|
|
} while (++i);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-semver/lib/comparator.js
|
|
var require_comparator = __commonJS({
|
|
"../../node_modules/bare-semver/lib/comparator.js"(exports, module) {
|
|
var constants = require_constants();
|
|
var symbols = {
|
|
[constants.EQ]: "=",
|
|
[constants.LT]: "<",
|
|
[constants.LTE]: "<=",
|
|
[constants.GT]: ">",
|
|
[constants.GTE]: ">="
|
|
};
|
|
module.exports = class Comparator {
|
|
constructor(operator, version) {
|
|
this.operator = operator;
|
|
this.version = version;
|
|
}
|
|
test(version) {
|
|
const result = version.compare(this.version);
|
|
switch (this.operator) {
|
|
case constants.LT:
|
|
return result < 0;
|
|
case constants.LTE:
|
|
return result <= 0;
|
|
case constants.GT:
|
|
return result > 0;
|
|
case constants.GTE:
|
|
return result >= 0;
|
|
default:
|
|
return result === 0;
|
|
}
|
|
}
|
|
toString() {
|
|
return symbols[this.operator] + this.version;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-semver/lib/range.js
|
|
var require_range2 = __commonJS({
|
|
"../../node_modules/bare-semver/lib/range.js"(exports, module) {
|
|
var constants = require_constants();
|
|
var errors = require_errors2();
|
|
var Version = require_version();
|
|
var Comparator = require_comparator();
|
|
var Range = class {
|
|
constructor(comparators = []) {
|
|
this.comparators = comparators;
|
|
}
|
|
test(version) {
|
|
for (const set of this.comparators) {
|
|
let matches = true;
|
|
for (const comparator of set) {
|
|
if (comparator.test(version)) continue;
|
|
matches = false;
|
|
break;
|
|
}
|
|
if (matches) return true;
|
|
}
|
|
return false;
|
|
}
|
|
toString() {
|
|
let result = "";
|
|
let first = true;
|
|
for (const set of this.comparators) {
|
|
if (first) first = false;
|
|
else result += " || ";
|
|
result += set.join(" ");
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
module.exports = exports = Range;
|
|
exports.parse = function parse2(input, state = { position: 0, partial: false }) {
|
|
let i = state.position;
|
|
let c;
|
|
const unexpected = (expected) => {
|
|
let msg;
|
|
if (i >= input.length) {
|
|
msg = `Unexpected end of input in '${input}'`;
|
|
} else {
|
|
msg = `Unexpected token '${input[i]}' in '${input}' at position ${i}`;
|
|
}
|
|
if (expected) msg += `, ${expected}`;
|
|
throw errors.INVALID_VERSION(msg, unexpected);
|
|
};
|
|
const comparators = [];
|
|
while (i < input.length) {
|
|
const set = [];
|
|
while (i < input.length) {
|
|
c = input[i];
|
|
let operator = constants.EQ;
|
|
if (c === "<") {
|
|
operator = constants.LT;
|
|
c = input[++i];
|
|
if (c === "=") {
|
|
operator = constants.LTE;
|
|
c = input[++i];
|
|
}
|
|
} else if (c === ">") {
|
|
operator = constants.GT;
|
|
c = input[++i];
|
|
if (c === "=") {
|
|
operator = constants.GTE;
|
|
c = input[++i];
|
|
}
|
|
} else if (c === "=") {
|
|
c = input[++i];
|
|
}
|
|
const state2 = { position: i, partial: true, range: true };
|
|
set.push(new Comparator(operator, Version.parse(input, state2)));
|
|
c = input[i = state2.position];
|
|
while (c === " ") c = input[++i];
|
|
if (c === "|" && input[i + 1] === "|") {
|
|
c = input[i += 2];
|
|
while (c === " ") c = input[++i];
|
|
break;
|
|
}
|
|
if (c && c !== "<" && c !== ">") unexpected("expected '||', '<', or '>'");
|
|
}
|
|
if (set.length) comparators.push(set);
|
|
}
|
|
if (i < input.length && state.partial === false) {
|
|
unexpected("expected end of input");
|
|
}
|
|
state.position = i;
|
|
return new Range(comparators);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-semver/index.js
|
|
var require_bare_semver = __commonJS({
|
|
"../../node_modules/bare-semver/index.js"(exports) {
|
|
exports.constants = require_constants();
|
|
exports.errors = require_errors2();
|
|
var Version = exports.Version = require_version();
|
|
var Range = exports.Range = require_range2();
|
|
exports.Comparator = require_comparator();
|
|
exports.satisfies = function satisfies(version, range) {
|
|
if (typeof version === "string") version = Version.parse(version);
|
|
if (typeof range === "string") range = Range.parse(range);
|
|
return range.test(version);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-module-resolve/lib/errors.js
|
|
var require_errors3 = __commonJS({
|
|
"../../node_modules/bare-module-resolve/lib/errors.js"(exports, module) {
|
|
module.exports = class ModuleResolveError extends Error {
|
|
constructor(msg, code, fn = ModuleResolveError) {
|
|
super(`${code}: ${msg}`);
|
|
this.code = code;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, fn);
|
|
}
|
|
}
|
|
get name() {
|
|
return "ModuleResolveError";
|
|
}
|
|
static INVALID_MODULE_SPECIFIER(msg) {
|
|
return new ModuleResolveError(
|
|
msg,
|
|
"INVALID_MODULE_SPECIFIER",
|
|
ModuleResolveError.INVALID_MODULE_SPECIFIER
|
|
);
|
|
}
|
|
static INVALID_PACKAGE_TARGET(msg) {
|
|
return new ModuleResolveError(
|
|
msg,
|
|
"INVALID_PACKAGE_TARGET",
|
|
ModuleResolveError.INVALID_PACKAGE_TARGET
|
|
);
|
|
}
|
|
static PACKAGE_PATH_NOT_EXPORTED(msg) {
|
|
return new ModuleResolveError(
|
|
msg,
|
|
"PACKAGE_PATH_NOT_EXPORTED",
|
|
ModuleResolveError.PACKAGE_PATH_NOT_EXPORTED
|
|
);
|
|
}
|
|
static PACKAGE_IMPORT_NOT_DEFINED(msg) {
|
|
return new ModuleResolveError(
|
|
msg,
|
|
"PACKAGE_IMPORT_NOT_DEFINED",
|
|
ModuleResolveError.PACKAGE_IMPORT_NOT_DEFINED
|
|
);
|
|
}
|
|
static UNSUPPORTED_ENGINE(msg) {
|
|
return new ModuleResolveError(msg, "UNSUPPORTED_ENGINE", ModuleResolveError.UNSUPPORTED_ENGINE);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-module-resolve/index.js
|
|
var require_bare_module_resolve = __commonJS({
|
|
"../../node_modules/bare-module-resolve/index.js"(exports, module) {
|
|
var { satisfies } = require_bare_semver();
|
|
var errors = require_errors3();
|
|
module.exports = exports = function resolve(specifier, parentURL, opts, readPackage) {
|
|
if (typeof opts === "function") {
|
|
readPackage = opts;
|
|
opts = {};
|
|
} else if (typeof readPackage !== "function") {
|
|
readPackage = defaultReadPackage;
|
|
}
|
|
return {
|
|
*[Symbol.iterator]() {
|
|
const generator = exports.module(specifier, parentURL, opts);
|
|
let next = generator.next();
|
|
while (next.done !== true) {
|
|
const value = next.value;
|
|
if (value.package) {
|
|
next = generator.next(readPackage(value.package));
|
|
} else {
|
|
next = generator.next(yield value.resolution);
|
|
}
|
|
}
|
|
return next.value;
|
|
},
|
|
async *[Symbol.asyncIterator]() {
|
|
const generator = exports.module(specifier, parentURL, opts);
|
|
let next = generator.next();
|
|
while (next.done !== true) {
|
|
const value = next.value;
|
|
if (value.package) {
|
|
next = generator.next(await readPackage(value.package));
|
|
} else {
|
|
next = generator.next(yield value.resolution);
|
|
}
|
|
}
|
|
return next.value;
|
|
}
|
|
};
|
|
};
|
|
function defaultReadPackage() {
|
|
return null;
|
|
}
|
|
var UNRESOLVED = 0;
|
|
var YIELDED = 1;
|
|
var RESOLVED = YIELDED | 2;
|
|
exports.constants = {
|
|
UNRESOLVED,
|
|
YIELDED,
|
|
RESOLVED
|
|
};
|
|
exports.module = function* (specifier, parentURL, opts = {}) {
|
|
const { resolutions = null, imports = null } = opts;
|
|
if (exports.startsWithWindowsDriveLetter(specifier)) {
|
|
specifier = "/" + specifier;
|
|
}
|
|
let status;
|
|
if (resolutions) {
|
|
status = yield* exports.preresolved(specifier, resolutions, parentURL, opts);
|
|
if (status) return status;
|
|
}
|
|
status = yield* exports.url(specifier, parentURL, opts);
|
|
if (status) return status;
|
|
status = yield* exports.packageImports(specifier, parentURL, opts);
|
|
if (status) return status;
|
|
if (specifier === "." || specifier === ".." || specifier[0] === "/" || specifier[0] === "\\" || specifier.startsWith("./") || specifier.startsWith(".\\") || specifier.startsWith("../") || specifier.startsWith("..\\")) {
|
|
if (imports) {
|
|
status = yield* exports.packageImportsExports(specifier, imports, parentURL, true, opts);
|
|
if (status) return status;
|
|
}
|
|
status = yield* exports.deferred(specifier, opts);
|
|
if (status) return status;
|
|
status = yield* exports.file(specifier, parentURL, false, opts);
|
|
if (status === RESOLVED) return status;
|
|
return yield* exports.directory(specifier, parentURL, opts);
|
|
}
|
|
return yield* exports.package(specifier, parentURL, opts);
|
|
};
|
|
exports.url = function* (url, parentURL, opts = {}) {
|
|
const { imports = null, deferredProtocol = "deferred:", resolutions = null } = opts;
|
|
let resolution;
|
|
try {
|
|
resolution = new URL(url);
|
|
} catch {
|
|
return UNRESOLVED;
|
|
}
|
|
if (imports) {
|
|
const status = yield* exports.packageImportsExports(
|
|
resolution.href,
|
|
imports,
|
|
parentURL,
|
|
true,
|
|
opts
|
|
);
|
|
if (status) return status;
|
|
}
|
|
if (resolution.protocol === deferredProtocol) {
|
|
const specifier = resolution.pathname;
|
|
if (resolutions) {
|
|
const imports2 = resolutions[parentURL.href];
|
|
if (typeof imports2 === "object" && imports2 !== null) {
|
|
opts = {
|
|
...opts,
|
|
resolutions: { ...resolutions, [parentURL.href]: { ...imports2, [specifier]: null } }
|
|
};
|
|
}
|
|
}
|
|
return yield* exports.module(specifier, parentURL, opts);
|
|
}
|
|
if (resolution.protocol === "node:") {
|
|
const specifier = resolution.pathname;
|
|
if (specifier === "." || specifier === ".." || specifier[0] === "/" || specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
throw errors.INVALID_MODULE_SPECIFIER(`Module specifier '${url}' is not a valid package name`);
|
|
}
|
|
return yield* exports.package(specifier, parentURL, opts);
|
|
}
|
|
const resolved = yield { resolution };
|
|
return resolved ? RESOLVED : YIELDED;
|
|
};
|
|
exports.preresolved = function* (specifier, resolutions, parentURL, opts = {}) {
|
|
const imports = resolutions[parentURL.href];
|
|
if (typeof imports === "object" && imports !== null) {
|
|
return yield* exports.packageImportsExports(specifier, imports, parentURL, true, opts);
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.deferred = function* (specifier, opts = {}) {
|
|
const { deferredProtocol = "deferred:", defer = [] } = opts;
|
|
if (defer.includes(specifier)) {
|
|
const resolved = yield { resolution: new URL(deferredProtocol + specifier) };
|
|
return resolved ? RESOLVED : YIELDED;
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.package = function* (packageSpecifier, parentURL, opts = {}) {
|
|
const { builtins = [] } = opts;
|
|
if (packageSpecifier === "") {
|
|
throw errors.INVALID_MODULE_SPECIFIER(
|
|
`Module specifier '${packageSpecifier}' is not a valid package name`
|
|
);
|
|
}
|
|
let packageName;
|
|
if (packageSpecifier[0] !== "@") {
|
|
packageName = packageSpecifier.split("/", 1).join();
|
|
} else {
|
|
if (!packageSpecifier.includes("/")) {
|
|
throw errors.INVALID_MODULE_SPECIFIER(
|
|
`Module specifier '${packageSpecifier}' is not a valid package name`
|
|
);
|
|
}
|
|
packageName = packageSpecifier.split("/", 2).join("/");
|
|
}
|
|
if (packageName[0] === "." || packageName.includes("\\") || packageName.includes("%")) {
|
|
throw errors.INVALID_MODULE_SPECIFIER(
|
|
`Module specifier '${packageSpecifier}' is not a valid package name`
|
|
);
|
|
}
|
|
let status;
|
|
status = yield* exports.builtinTarget(packageSpecifier, null, builtins, opts);
|
|
if (status) return status;
|
|
status = yield* exports.deferred(packageSpecifier, opts);
|
|
if (status) return status;
|
|
let packageSubpath = "." + packageSpecifier.substring(packageName.length);
|
|
status = yield* exports.packageSelf(packageName, packageSubpath, parentURL, opts);
|
|
if (status) return status;
|
|
parentURL = new URL(parentURL.href);
|
|
for (const packageURL of exports.lookupPackageRoot(packageName, parentURL)) {
|
|
const info = yield { package: packageURL };
|
|
if (info) {
|
|
if (info.engines) exports.validateEngines(packageURL, info.engines, opts);
|
|
if (info.exports) {
|
|
return yield* exports.packageExports(packageURL, packageSubpath, info.exports, opts);
|
|
}
|
|
if (packageSubpath === ".") {
|
|
if (typeof info.main === "string" && info.main !== "") {
|
|
packageSubpath = info.main;
|
|
} else {
|
|
return yield* exports.file("index", packageURL, true, opts);
|
|
}
|
|
}
|
|
status = yield* exports.file(packageSubpath, packageURL, false, opts);
|
|
if (status === RESOLVED) return status;
|
|
return yield* exports.directory(packageSubpath, packageURL, opts);
|
|
}
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.packageSelf = function* (packageName, packageSubpath, parentURL, opts = {}) {
|
|
for (const packageURL of exports.lookupPackageScope(parentURL, opts)) {
|
|
const info = yield { package: packageURL };
|
|
if (info) {
|
|
if (info.name !== packageName) return false;
|
|
if (info.exports) {
|
|
return yield* exports.packageExports(packageURL, packageSubpath, info.exports, opts);
|
|
}
|
|
if (packageSubpath === ".") {
|
|
if (typeof info.main === "string" && info.main !== "") {
|
|
packageSubpath = info.main;
|
|
} else {
|
|
return yield* exports.file("index", packageURL, true, opts);
|
|
}
|
|
}
|
|
const status = yield* exports.file(packageSubpath, packageURL, false, opts);
|
|
if (status === RESOLVED) return status;
|
|
return yield* exports.directory(packageSubpath, packageURL, opts);
|
|
}
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.packageExports = function* (packageURL, subpath, packageExports, opts = {}) {
|
|
if (subpath === ".") {
|
|
let mainExport;
|
|
if (typeof packageExports === "string" || Array.isArray(packageExports)) {
|
|
mainExport = packageExports;
|
|
} else if (typeof packageExports === "object" && packageExports !== null) {
|
|
const keys = Object.keys(packageExports);
|
|
if (keys.some((key) => key.startsWith("."))) {
|
|
if ("." in packageExports) mainExport = packageExports["."];
|
|
} else {
|
|
mainExport = packageExports;
|
|
}
|
|
}
|
|
if (mainExport) {
|
|
const status = yield* exports.packageTarget(packageURL, mainExport, null, false, opts);
|
|
if (status) return status;
|
|
}
|
|
} else if (typeof packageExports === "object" && packageExports !== null) {
|
|
const keys = Object.keys(packageExports);
|
|
if (keys.every((key) => key.startsWith("."))) {
|
|
const status = yield* exports.packageImportsExports(
|
|
subpath,
|
|
packageExports,
|
|
packageURL,
|
|
false,
|
|
opts
|
|
);
|
|
if (status) return status;
|
|
}
|
|
}
|
|
throw errors.PACKAGE_PATH_NOT_EXPORTED(
|
|
`Package subpath '${subpath}' is not defined by "exports" in '${packageURL}'`
|
|
);
|
|
};
|
|
exports.packageImports = function* (specifier, parentURL, opts = {}) {
|
|
const { imports = null } = opts;
|
|
if (specifier === "#" || specifier.startsWith("#/")) {
|
|
throw errors.INVALID_MODULE_SPECIFIER(
|
|
`Module specifier '${specifier}' is not a valid internal imports specifier`
|
|
);
|
|
}
|
|
for (const packageURL of exports.lookupPackageScope(parentURL, opts)) {
|
|
const info = yield { package: packageURL };
|
|
if (info) {
|
|
if (info.imports) {
|
|
const status = yield* exports.packageImportsExports(
|
|
specifier,
|
|
info.imports,
|
|
packageURL,
|
|
true,
|
|
opts
|
|
);
|
|
if (status) return status;
|
|
}
|
|
if (specifier.startsWith("#")) {
|
|
throw errors.PACKAGE_IMPORT_NOT_DEFINED(
|
|
`Package import specifier '${specifier}' is not defined by "imports" in '${packageURL}'`
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (imports) {
|
|
const status = yield* exports.packageImportsExports(specifier, imports, parentURL, true, opts);
|
|
if (status) return status;
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.packageImportsExports = function* (matchKey, matchObject, packageURL, isImports, opts = {}) {
|
|
if (matchKey in matchObject && !matchKey.includes("*")) {
|
|
const target = matchObject[matchKey];
|
|
return yield* exports.packageTarget(packageURL, target, null, isImports, opts);
|
|
}
|
|
const expansionKeys = Object.keys(matchObject).filter((key) => key.includes("*")).sort(exports.patternKeyCompare);
|
|
for (const expansionKey of expansionKeys) {
|
|
const patternIndex = expansionKey.indexOf("*");
|
|
const patternBase = expansionKey.substring(0, patternIndex);
|
|
if (matchKey.startsWith(patternBase) && matchKey !== patternBase) {
|
|
const patternTrailer = expansionKey.substring(patternIndex + 1);
|
|
if (patternTrailer === "" || matchKey.endsWith(patternTrailer) && matchKey.length >= expansionKey.length) {
|
|
const target = matchObject[expansionKey];
|
|
const patternMatch = matchKey.substring(
|
|
patternBase.length,
|
|
matchKey.length - patternTrailer.length
|
|
);
|
|
return yield* exports.packageTarget(packageURL, target, patternMatch, isImports, opts);
|
|
}
|
|
}
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.validateEngines = function validateEngines(packageURL, packageEngines, opts = {}) {
|
|
const { engines = {} } = opts;
|
|
for (const [engine, range] of Object.entries(packageEngines)) {
|
|
if (engine in engines) {
|
|
const version = engines[engine];
|
|
if (!satisfies(version, range)) {
|
|
throw errors.UNSUPPORTED_ENGINE(
|
|
`Package not compatible with engine '${engine}' ${version}, requires range '${range}' defined by "engines" in '${packageURL}'`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
exports.patternKeyCompare = function patternKeyCompare(keyA, keyB) {
|
|
const patternIndexA = keyA.indexOf("*");
|
|
const patternIndexB = keyB.indexOf("*");
|
|
const baseLengthA = patternIndexA === -1 ? keyA.length : patternIndexA + 1;
|
|
const baseLengthB = patternIndexB === -1 ? keyB.length : patternIndexB + 1;
|
|
if (baseLengthA > baseLengthB) return -1;
|
|
if (baseLengthB > baseLengthA) return 1;
|
|
if (patternIndexA === -1) return 1;
|
|
if (patternIndexB === -1) return -1;
|
|
if (keyA.length > keyB.length) return -1;
|
|
if (keyB.length > keyA.length) return 1;
|
|
return 0;
|
|
};
|
|
exports.packageTarget = function* (packageURL, target, patternMatch, isImports, opts = {}) {
|
|
const { conditions = [], matchedConditions = [] } = opts;
|
|
if (typeof target === "string") {
|
|
if (!target.startsWith("./") && !isImports) {
|
|
throw errors.INVALID_PACKAGE_TARGET(
|
|
`Invalid target '${target}' defined by "exports" in '${packageURL}'`
|
|
);
|
|
}
|
|
if (patternMatch !== null) {
|
|
target = target.replaceAll("*", patternMatch);
|
|
}
|
|
const status = yield* exports.url(target, packageURL, opts);
|
|
if (status) return status;
|
|
if (target === "." || target === ".." || target[0] === "/" || target.startsWith("./") || target.startsWith("../")) {
|
|
const resolved = yield { resolution: new URL(target, packageURL) };
|
|
return resolved ? RESOLVED : YIELDED;
|
|
}
|
|
return yield* exports.package(target, packageURL, opts);
|
|
}
|
|
if (Array.isArray(target)) {
|
|
for (const targetValue of target) {
|
|
const status = yield* exports.packageTarget(
|
|
packageURL,
|
|
targetValue,
|
|
patternMatch,
|
|
isImports,
|
|
opts
|
|
);
|
|
if (status) return status;
|
|
}
|
|
} else if (typeof target === "object" && target !== null) {
|
|
let status = UNRESOLVED;
|
|
for (const [condition, targetValue, subset] of exports.conditionMatches(
|
|
target,
|
|
conditions,
|
|
opts
|
|
)) {
|
|
matchedConditions.push(condition);
|
|
status |= yield* exports.packageTarget(packageURL, targetValue, patternMatch, isImports, {
|
|
...opts,
|
|
conditions: subset
|
|
});
|
|
matchedConditions.pop();
|
|
}
|
|
if (status) return status;
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.builtinTarget = function* (packageSpecifier, packageVersion, target, opts = {}) {
|
|
const { builtinProtocol = "builtin:", conditions = [], matchedConditions = [] } = opts;
|
|
if (typeof target === "string") {
|
|
const targetParts = target.split("@");
|
|
let targetName;
|
|
let targetVersion;
|
|
if (target[0] !== "@") {
|
|
targetName = targetParts[0];
|
|
targetVersion = targetParts[1] || null;
|
|
} else {
|
|
targetName = targetParts.slice(0, 2).join("@");
|
|
targetVersion = targetParts[2] || null;
|
|
}
|
|
if (packageSpecifier === targetName) {
|
|
if (packageVersion === null && targetVersion === null) {
|
|
const resolved = yield {
|
|
resolution: new URL(builtinProtocol + packageSpecifier)
|
|
};
|
|
return resolved ? RESOLVED : YIELDED;
|
|
}
|
|
let version = null;
|
|
if (packageVersion === null) {
|
|
version = targetVersion;
|
|
} else if (targetVersion === null || packageVersion === targetVersion) {
|
|
version = packageVersion;
|
|
}
|
|
if (version !== null) {
|
|
const resolved = yield {
|
|
resolution: new URL(builtinProtocol + packageSpecifier + "@" + version)
|
|
};
|
|
return resolved ? RESOLVED : YIELDED;
|
|
}
|
|
}
|
|
} else if (Array.isArray(target)) {
|
|
for (const targetValue of target) {
|
|
const status = yield* exports.builtinTarget(
|
|
packageSpecifier,
|
|
packageVersion,
|
|
targetValue,
|
|
opts
|
|
);
|
|
if (status) return status;
|
|
}
|
|
} else if (typeof target === "object" && target !== null) {
|
|
let status = UNRESOLVED;
|
|
for (const [condition, targetValue, subset] of exports.conditionMatches(
|
|
target,
|
|
conditions,
|
|
opts
|
|
)) {
|
|
matchedConditions.push(condition);
|
|
status |= yield* exports.builtinTarget(packageSpecifier, packageVersion, targetValue, {
|
|
...opts,
|
|
conditions: subset
|
|
});
|
|
matchedConditions.pop();
|
|
}
|
|
if (status) return status;
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.conditionMatches = function* conditionMatches(target, conditions, opts = {}) {
|
|
if (conditions.every((condition) => typeof condition === "string")) {
|
|
const keys = Object.keys(target);
|
|
for (const condition of keys) {
|
|
if (condition === "default" || conditions.includes(condition)) {
|
|
yield [condition, target[condition], conditions];
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
let yielded = false;
|
|
for (const subset of conditions) {
|
|
if (yield* conditionMatches(target, subset, opts)) {
|
|
yielded = true;
|
|
}
|
|
}
|
|
return yielded;
|
|
};
|
|
exports.lookupPackageRoot = function* (packageName, parentURL) {
|
|
parentURL = new URL(parentURL.href);
|
|
do {
|
|
const packageURL = new URL("node_modules/" + packageName + "/", parentURL);
|
|
const info = yield new URL("package.json", packageURL);
|
|
if (info) return info;
|
|
parentURL.pathname = parentURL.pathname.substring(0, parentURL.pathname.lastIndexOf("/"));
|
|
if (parentURL.pathname.length === 3 && exports.isWindowsDriveLetter(parentURL.pathname.substring(1))) {
|
|
break;
|
|
}
|
|
} while (parentURL.pathname !== "" && parentURL.pathname !== "/");
|
|
return null;
|
|
};
|
|
exports.lookupPackageScope = function* lookupPackageScope(scopeURL, opts = {}) {
|
|
const { resolutions = null } = opts;
|
|
if (resolutions) {
|
|
for (const { resolution } of exports.preresolved("#package", resolutions, scopeURL, opts)) {
|
|
if (resolution) return yield resolution;
|
|
}
|
|
}
|
|
scopeURL = new URL(scopeURL.href);
|
|
do {
|
|
if (scopeURL.pathname.endsWith("/node_modules")) break;
|
|
const info = yield new URL("package.json", scopeURL);
|
|
if (info) return info;
|
|
scopeURL.pathname = scopeURL.pathname.substring(0, scopeURL.pathname.lastIndexOf("/"));
|
|
if (scopeURL.pathname.length === 3 && exports.isWindowsDriveLetter(scopeURL.pathname.substring(1))) {
|
|
break;
|
|
}
|
|
} while (scopeURL.pathname !== "" && scopeURL.pathname !== "/");
|
|
return null;
|
|
};
|
|
exports.file = function* (filename, parentURL, isIndex, opts = {}) {
|
|
if (filename === "." || filename === ".." || filename[filename.length - 1] === "/" || filename[filename.length - 1] === "\\") {
|
|
return UNRESOLVED;
|
|
}
|
|
if (parentURL.protocol === "file:" && /%2f|%5c/i.test(filename)) {
|
|
throw errors.INVALID_MODULE_SPECIFIER(`Module specifier '${filename}' is invalid`);
|
|
}
|
|
const { extensions = [] } = opts;
|
|
let status = UNRESOLVED;
|
|
if (!isIndex) {
|
|
if (yield { resolution: new URL(filename, parentURL) }) {
|
|
return RESOLVED;
|
|
}
|
|
status = YIELDED;
|
|
}
|
|
for (const ext of extensions) {
|
|
if (filename.endsWith(ext)) continue;
|
|
if (yield { resolution: new URL(filename + ext, parentURL) }) {
|
|
return RESOLVED;
|
|
}
|
|
status = YIELDED;
|
|
}
|
|
return status;
|
|
};
|
|
exports.directory = function* (dirname, parentURL, opts = {}) {
|
|
let directoryURL;
|
|
if (dirname[dirname.length - 1] === "/" || dirname[dirname.length - 1] === "\\") {
|
|
directoryURL = new URL(dirname, parentURL);
|
|
} else {
|
|
directoryURL = new URL(dirname + "/", parentURL);
|
|
}
|
|
const info = yield { package: new URL("package.json", directoryURL) };
|
|
if (info) {
|
|
if (info.exports) {
|
|
return yield* exports.packageExports(directoryURL, ".", info.exports, opts);
|
|
}
|
|
if (typeof info.main === "string" && info.main !== "") {
|
|
const status = yield* exports.file(info.main, directoryURL, false, opts);
|
|
if (status === RESOLVED) return status;
|
|
return yield* exports.directory(info.main, directoryURL, opts);
|
|
}
|
|
}
|
|
return yield* exports.file("index", directoryURL, true, opts);
|
|
};
|
|
function isASCIIUpperAlpha(c) {
|
|
return c >= 65 && c <= 90;
|
|
}
|
|
function isASCIILowerAlpha(c) {
|
|
return c >= 97 && c <= 122;
|
|
}
|
|
function isASCIIAlpha(c) {
|
|
return isASCIIUpperAlpha(c) || isASCIILowerAlpha(c);
|
|
}
|
|
exports.isWindowsDriveLetter = function isWindowsDriveLetter(input) {
|
|
return input.length >= 2 && isASCIIAlpha(input.charCodeAt(0)) && (input.charCodeAt(1) === 58 || input.charCodeAt(1) === 124);
|
|
};
|
|
exports.startsWithWindowsDriveLetter = function startsWithWindowsDriveLetter(input) {
|
|
return input.length >= 2 && exports.isWindowsDriveLetter(input) && (input.length === 2 || input.charCodeAt(2) === 47 || input.charCodeAt(2) === 92 || input.charCodeAt(2) === 63 || input.charCodeAt(2) === 35);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-addon-resolve/lib/errors.js
|
|
var require_errors4 = __commonJS({
|
|
"../../node_modules/bare-addon-resolve/lib/errors.js"(exports, module) {
|
|
module.exports = class AddonResolveError extends Error {
|
|
constructor(msg, code, fn = AddonResolveError) {
|
|
super(`${code}: ${msg}`);
|
|
this.code = code;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, fn);
|
|
}
|
|
}
|
|
get name() {
|
|
return "AddonResolveError";
|
|
}
|
|
static INVALID_ADDON_SPECIFIER(msg) {
|
|
return new AddonResolveError(
|
|
msg,
|
|
"INVALID_ADDON_SPECIFIER",
|
|
AddonResolveError.INVALID_ADDON_SPECIFIER
|
|
);
|
|
}
|
|
static INVALID_PACKAGE_NAME(msg) {
|
|
return new AddonResolveError(
|
|
msg,
|
|
"INVALID_PACKAGE_NAME",
|
|
AddonResolveError.INVALID_PACKAGE_NAME
|
|
);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-addon-resolve/index.js
|
|
var require_bare_addon_resolve = __commonJS({
|
|
"../../node_modules/bare-addon-resolve/index.js"(exports, module) {
|
|
var resolve = require_bare_module_resolve();
|
|
var { Version } = require_bare_semver();
|
|
var errors = require_errors4();
|
|
module.exports = exports = function resolve2(specifier, parentURL, opts, readPackage) {
|
|
if (typeof opts === "function") {
|
|
readPackage = opts;
|
|
opts = {};
|
|
} else if (typeof readPackage !== "function") {
|
|
readPackage = defaultReadPackage;
|
|
}
|
|
return {
|
|
*[Symbol.iterator]() {
|
|
const generator = exports.addon(specifier, parentURL, opts);
|
|
let next = generator.next();
|
|
while (next.done !== true) {
|
|
const value = next.value;
|
|
if (value.package) {
|
|
next = generator.next(readPackage(value.package));
|
|
} else {
|
|
next = generator.next(yield value.resolution);
|
|
}
|
|
}
|
|
return next.value;
|
|
},
|
|
async *[Symbol.asyncIterator]() {
|
|
const generator = exports.addon(specifier, parentURL, opts);
|
|
let next = generator.next();
|
|
while (next.done !== true) {
|
|
const value = next.value;
|
|
if (value.package) {
|
|
next = generator.next(await readPackage(value.package));
|
|
} else {
|
|
next = generator.next(yield value.resolution);
|
|
}
|
|
}
|
|
return next.value;
|
|
}
|
|
};
|
|
};
|
|
function defaultReadPackage() {
|
|
return null;
|
|
}
|
|
var { UNRESOLVED, YIELDED, RESOLVED } = resolve.constants;
|
|
exports.constants = {
|
|
UNRESOLVED,
|
|
YIELDED,
|
|
RESOLVED
|
|
};
|
|
exports.addon = function* (specifier, parentURL, opts = {}) {
|
|
const { resolutions = null } = opts;
|
|
if (exports.startsWithWindowsDriveLetter(specifier)) {
|
|
specifier = "/" + specifier;
|
|
}
|
|
let status;
|
|
if (resolutions) {
|
|
status = yield* resolve.preresolved(specifier, resolutions, parentURL, opts);
|
|
if (status) return status;
|
|
}
|
|
status = yield* exports.url(specifier, parentURL, opts);
|
|
if (status) return status;
|
|
let version = null;
|
|
const i = specifier.lastIndexOf("@");
|
|
if (i > 0) {
|
|
version = specifier.substring(i + 1);
|
|
try {
|
|
Version.parse(version);
|
|
specifier = specifier.substring(0, i);
|
|
} catch {
|
|
version = null;
|
|
}
|
|
}
|
|
if (specifier === "." || specifier === ".." || specifier[0] === "/" || specifier[0] === "\\" || specifier.startsWith("./") || specifier.startsWith(".\\") || specifier.startsWith("../") || specifier.startsWith("..\\")) {
|
|
status = yield* exports.file(specifier, parentURL, opts);
|
|
if (status === RESOLVED) return status;
|
|
return yield* exports.directory(specifier, version, parentURL, opts);
|
|
}
|
|
return yield* exports.package(specifier, version, parentURL, opts);
|
|
};
|
|
exports.url = function* (url, parentURL, opts = {}) {
|
|
let resolution;
|
|
try {
|
|
resolution = new URL(url);
|
|
} catch {
|
|
return UNRESOLVED;
|
|
}
|
|
const resolved = yield { resolution };
|
|
return resolved ? RESOLVED : YIELDED;
|
|
};
|
|
exports.package = function* (packageSpecifier, packageVersion, parentURL, opts = {}) {
|
|
if (packageSpecifier === "") {
|
|
throw errors.INVALID_ADDON_SPECIFIER(
|
|
`Addon specifier '${packageSpecifier}' is not a valid package name`
|
|
);
|
|
}
|
|
let packageName;
|
|
if (packageSpecifier[0] !== "@") {
|
|
packageName = packageSpecifier.split("/", 1).join();
|
|
} else {
|
|
if (!packageSpecifier.includes("/")) {
|
|
throw errors.INVALID_ADDON_SPECIFIER(
|
|
`Addon specifier '${packageSpecifier}' is not a valid package name`
|
|
);
|
|
}
|
|
packageName = packageSpecifier.split("/", 2).join("/");
|
|
}
|
|
if (packageName[0] === "." || packageName.includes("\\") || packageName.includes("%")) {
|
|
throw errors.INVALID_ADDON_SPECIFIER(
|
|
`Addon specifier '${packageSpecifier}' is not a valid package name`
|
|
);
|
|
}
|
|
const packageSubpath = "." + packageSpecifier.substring(packageName.length);
|
|
const status = yield* exports.packageSelf(
|
|
packageName,
|
|
packageSubpath,
|
|
packageVersion,
|
|
parentURL,
|
|
opts
|
|
);
|
|
if (status) return status;
|
|
parentURL = new URL(parentURL.href);
|
|
do {
|
|
const packageURL = new URL("node_modules/" + packageName + "/", parentURL);
|
|
parentURL.pathname = parentURL.pathname.substring(0, parentURL.pathname.lastIndexOf("/"));
|
|
const info = yield { package: new URL("package.json", packageURL) };
|
|
if (info) {
|
|
return yield* exports.directory(packageSubpath, packageVersion, packageURL, opts);
|
|
}
|
|
} while (parentURL.pathname !== "" && parentURL.pathname !== "/");
|
|
return UNRESOLVED;
|
|
};
|
|
exports.packageSelf = function* (packageName, packageSubpath, packageVersion, parentURL, opts = {}) {
|
|
for (const packageURL of resolve.lookupPackageScope(parentURL, opts)) {
|
|
const info = yield { package: packageURL };
|
|
if (info) {
|
|
if (info.name === packageName) {
|
|
return yield* exports.directory(packageSubpath, packageVersion, packageURL, opts);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return UNRESOLVED;
|
|
};
|
|
exports.lookupPrebuildsScope = function* lookupPrebuildsScope(url, opts = {}) {
|
|
const scopeURL = new URL(url.href);
|
|
do {
|
|
yield new URL("prebuilds/", scopeURL);
|
|
scopeURL.pathname = scopeURL.pathname.substring(0, scopeURL.pathname.lastIndexOf("/"));
|
|
if (scopeURL.pathname.length === 3 && exports.isWindowsDriveLetter(scopeURL.pathname.substring(1))) {
|
|
break;
|
|
}
|
|
} while (scopeURL.pathname !== "" && scopeURL.pathname !== "/");
|
|
};
|
|
exports.file = function* (filename, parentURL, opts = {}) {
|
|
if (filename === "." || filename === ".." || filename[filename.length - 1] === "/" || filename[filename.length - 1] === "\\") {
|
|
return UNRESOLVED;
|
|
}
|
|
if (parentURL.protocol === "file:" && /%2f|%5c/i.test(filename)) {
|
|
throw errors.INVALID_ADDON_SPECIFIER(`Addon specifier '${filename}' is invalid`);
|
|
}
|
|
const { extensions = [] } = opts;
|
|
let status = UNRESOLVED;
|
|
for (let ext of extensions) {
|
|
if (filename.endsWith(ext)) ext = "";
|
|
if (yield { resolution: new URL(filename + ext, parentURL) }) {
|
|
return RESOLVED;
|
|
}
|
|
status = YIELDED;
|
|
}
|
|
return status;
|
|
};
|
|
exports.directory = function* (dirname, version, parentURL, opts = {}) {
|
|
const {
|
|
host = null,
|
|
// Shorthand for single host resolution
|
|
hosts = host !== null ? [host] : [],
|
|
builtins = [],
|
|
matchedConditions = []
|
|
} = opts;
|
|
let directoryURL;
|
|
if (dirname[dirname.length - 1] === "/" || dirname[dirname.length - 1] === "\\") {
|
|
directoryURL = new URL(dirname, parentURL);
|
|
} else {
|
|
directoryURL = new URL(dirname + "/", parentURL);
|
|
}
|
|
const unversioned = version === null;
|
|
let name = null;
|
|
const info = yield { package: new URL("package.json", directoryURL) };
|
|
if (info) {
|
|
if (typeof info.name === "string" && info.name !== "") {
|
|
if (info.name.includes("__")) {
|
|
throw errors.INVALID_PACKAGE_NAME(`Package name '${info.name}' is invalid`);
|
|
}
|
|
name = info.name.replace(/\//g, "__").replace(/^@/, "");
|
|
} else {
|
|
return UNRESOLVED;
|
|
}
|
|
if (typeof info.version === "string" && info.version !== "") {
|
|
if (version !== null && info.version !== version) return UNRESOLVED;
|
|
version = info.version;
|
|
}
|
|
} else {
|
|
return UNRESOLVED;
|
|
}
|
|
let status;
|
|
status = yield* resolve.builtinTarget(name, version, builtins, opts);
|
|
if (status) return status;
|
|
for (const prebuildsURL of exports.lookupPrebuildsScope(directoryURL, opts)) {
|
|
status = UNRESOLVED;
|
|
for (const host2 of hosts) {
|
|
const conditions = host2.split("-");
|
|
const universal = supportsUniversalPrebuilds(host2) ? conditions.with(1, "universal").join("-") : null;
|
|
matchedConditions.push(...conditions);
|
|
if (version !== null) {
|
|
status |= yield* exports.file(host2 + "/" + name + "@" + version, prebuildsURL, opts);
|
|
if (universal) {
|
|
status |= yield* exports.file(universal + "/" + name + "@" + version, prebuildsURL, opts);
|
|
}
|
|
}
|
|
if (unversioned) {
|
|
status |= yield* exports.file(host2 + "/" + name, prebuildsURL, opts);
|
|
if (universal) {
|
|
status |= yield* exports.file(universal + "/" + name, prebuildsURL, opts);
|
|
}
|
|
}
|
|
for (const _ of conditions) matchedConditions.pop();
|
|
}
|
|
if (status === RESOLVED) return status;
|
|
}
|
|
return yield* exports.linked(name, version, opts);
|
|
};
|
|
exports.linked = function* (name, version = null, opts = {}) {
|
|
const {
|
|
linked = true,
|
|
host = null,
|
|
// Shorthand for single host resolution
|
|
hosts = host !== null ? [host] : [],
|
|
matchedConditions = []
|
|
} = opts;
|
|
if (linked === false || hosts.length === 0) return UNRESOLVED;
|
|
let status = UNRESOLVED;
|
|
for (const host2 of hosts) {
|
|
const [platform = null] = host2.split("-", 1);
|
|
if (platform === null) continue;
|
|
matchedConditions.push(platform);
|
|
status |= yield* platformArtefact(name, version, platform, opts);
|
|
matchedConditions.pop();
|
|
}
|
|
return status;
|
|
};
|
|
function* platformArtefact(name, version = null, platform, opts = {}) {
|
|
const { linkedProtocol = "linked:" } = opts;
|
|
if (platform === "darwin" || platform === "ios") {
|
|
if (version !== null) {
|
|
if (yield {
|
|
resolution: new URL(`${linkedProtocol}${name}.${version}.framework/${name}.${version}`)
|
|
}) {
|
|
return RESOLVED;
|
|
}
|
|
if (platform === "darwin") {
|
|
if (yield {
|
|
resolution: new URL(`${linkedProtocol}lib${name}.${version}.dylib`)
|
|
}) {
|
|
return RESOLVED;
|
|
}
|
|
}
|
|
}
|
|
if (yield {
|
|
resolution: new URL(`${linkedProtocol}${name}.framework/${name}`)
|
|
}) {
|
|
return RESOLVED;
|
|
}
|
|
if (platform === "darwin") {
|
|
if (yield {
|
|
resolution: new URL(`${linkedProtocol}lib${name}.dylib`)
|
|
}) {
|
|
return RESOLVED;
|
|
}
|
|
}
|
|
return YIELDED;
|
|
}
|
|
if (platform === "linux" || platform === "android") {
|
|
if (version !== null) {
|
|
if (yield {
|
|
resolution: new URL(`${linkedProtocol}lib${name}.${version}.so`)
|
|
}) {
|
|
return RESOLVED;
|
|
}
|
|
}
|
|
if (yield {
|
|
resolution: new URL(`${linkedProtocol}lib${name}.so`)
|
|
}) {
|
|
return RESOLVED;
|
|
}
|
|
return YIELDED;
|
|
}
|
|
if (platform === "win32") {
|
|
if (version !== null) {
|
|
if (yield {
|
|
resolution: new URL(`${linkedProtocol}${name}-${version}.dll`)
|
|
}) {
|
|
return RESOLVED;
|
|
}
|
|
}
|
|
if (yield {
|
|
resolution: new URL(`${linkedProtocol}${name}.dll`)
|
|
}) {
|
|
return RESOLVED;
|
|
}
|
|
}
|
|
return UNRESOLVED;
|
|
}
|
|
exports.isWindowsDriveLetter = resolve.isWindowsDriveLetter;
|
|
exports.startsWithWindowsDriveLetter = resolve.startsWithWindowsDriveLetter;
|
|
function supportsUniversalPrebuilds(host) {
|
|
return host === "darwin-arm64" || host === "darwin-x64" || host === "ios-arm64-simulator" || host === "ios-x64-simulator";
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/require-addon/lib/node.js
|
|
var require_node2 = __commonJS({
|
|
"../../node_modules/require-addon/lib/node.js"(exports, module) {
|
|
if (typeof __require.addon === "function") {
|
|
module.exports = __require.addon.bind(__require);
|
|
} else {
|
|
let readPackage2 = function(packageURL) {
|
|
try {
|
|
return __require(url.fileURLToPath(packageURL));
|
|
} catch (err) {
|
|
return null;
|
|
}
|
|
}, isAlpine2 = function() {
|
|
return process.platform === "linux" && fs.existsSync("/etc/alpine-release");
|
|
};
|
|
readPackage = readPackage2, isAlpine = isAlpine2;
|
|
const url = __require("url");
|
|
const fs = __require("fs");
|
|
const resolve = require_bare_addon_resolve();
|
|
let host = process.platform + "-" + process.arch;
|
|
const conditions = ["addon", "node", process.platform, process.arch];
|
|
const extensions = [".node"];
|
|
if (isAlpine2()) {
|
|
host += "-musl";
|
|
conditions.push("musl");
|
|
}
|
|
module.exports = function addon(specifier, parentURL) {
|
|
if (typeof parentURL === "string") parentURL = url.pathToFileURL(parentURL);
|
|
const candidates = [];
|
|
let cause;
|
|
for (const resolution of resolve(
|
|
specifier,
|
|
parentURL,
|
|
{ host, conditions, extensions },
|
|
readPackage2
|
|
)) {
|
|
candidates.push(resolution);
|
|
switch (resolution.protocol) {
|
|
case "file:":
|
|
try {
|
|
return __require(url.fileURLToPath(resolution));
|
|
} catch (err2) {
|
|
cause = err2;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
let message = `Cannot find addon '${specifier}' imported from '${parentURL.href}'`;
|
|
if (candidates.length > 0) {
|
|
message += "\nCandidates:";
|
|
message += "\n" + candidates.map((url2) => "- " + url2.href).join("\n");
|
|
}
|
|
const err = new Error(message, cause ? { cause } : {});
|
|
err.code = "ADDON_NOT_FOUND";
|
|
err.specifier = specifier;
|
|
err.referrer = parentURL;
|
|
err.candidates = candidates;
|
|
throw err;
|
|
};
|
|
}
|
|
var readPackage;
|
|
var isAlpine;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/rabin-native/binding.js
|
|
var require_binding = __commonJS({
|
|
"../../node_modules/rabin-native/binding.js"(exports, module) {
|
|
__require.addon = require_node2();
|
|
module.exports = __require.addon(".", __filename);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/rabin-native/index.js
|
|
var require_rabin_native = __commonJS({
|
|
"../../node_modules/rabin-native/index.js"(exports) {
|
|
var binding = require_binding();
|
|
var RabinChunker = class {
|
|
constructor(opts = {}) {
|
|
const {
|
|
minSize = 512 * 1024,
|
|
// 512 KiB
|
|
maxSize = 8 * 1024 * 1024
|
|
// 8 MiB
|
|
} = opts;
|
|
this._handle = binding.init(minSize, maxSize);
|
|
}
|
|
*push(data) {
|
|
while (true) {
|
|
const length = binding.push(this._handle, data.buffer, data.byteOffset, data.byteLength);
|
|
if (length === 0) return;
|
|
data = data.subarray(length);
|
|
yield binding.lastChunk(this._handle);
|
|
}
|
|
}
|
|
end() {
|
|
const length = binding.end(this._handle);
|
|
if (length === 0) return null;
|
|
return binding.lastChunk(this._handle);
|
|
}
|
|
};
|
|
exports.Chunker = RabinChunker;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/rabin-stream/index.js
|
|
var require_rabin_stream = __commonJS({
|
|
"../../node_modules/rabin-stream/index.js"(exports, module) {
|
|
var { Transform } = require_streamx();
|
|
var rabin = require_rabin_native();
|
|
module.exports = class RabinStream extends Transform {
|
|
constructor(opts = {}) {
|
|
super();
|
|
this._rabin = new rabin.Chunker(opts);
|
|
this._buffer = [];
|
|
}
|
|
_transform(data, cb) {
|
|
if (typeof data === "string") data = Buffer.from(data);
|
|
this._buffer.push(data);
|
|
const chunks = this._rabin.push(data);
|
|
for (const chunk of chunks) {
|
|
let data2 = this._buffer[0];
|
|
if (data2.byteLength < chunk.length) {
|
|
data2 = Buffer.concat(this._buffer);
|
|
this._buffer = [];
|
|
} else {
|
|
this._buffer.pop();
|
|
}
|
|
this.push(data2.subarray(0, chunk.length));
|
|
data2 = data2.subarray(chunk.length);
|
|
if (data2.byteLength) this._buffer.unshift(data2);
|
|
}
|
|
cb(null);
|
|
}
|
|
_flush(cb) {
|
|
if (this._buffer.length) {
|
|
this.push(Buffer.concat(this._buffer));
|
|
}
|
|
this._buffer = [];
|
|
cb(null);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/mirror-drive/index.js
|
|
var require_mirror_drive = __commonJS({
|
|
"../../node_modules/mirror-drive/index.js"(exports, module) {
|
|
var EventEmitter = __require("events");
|
|
var sameData = require_same_data();
|
|
var unixPathResolve = require_unix_path_resolve();
|
|
var streamEquals = require_binary_stream_equals();
|
|
var speedometer = require_speedometer();
|
|
var { pipelinePromise, isStream } = require_streamx();
|
|
var RabinStream = require_rabin_stream();
|
|
var SAME = 0;
|
|
var DIFF = 1;
|
|
var DIFF_META = 2;
|
|
var Monitor = class extends EventEmitter {
|
|
constructor(mirror, { interval = 250 } = {}) {
|
|
super();
|
|
this.mirror = mirror;
|
|
this.interval = setInterval(this.update.bind(this), interval);
|
|
this.stats = null;
|
|
this.index = mirror.monitors.push(this) - 1;
|
|
this.update();
|
|
}
|
|
get preloaded() {
|
|
return this.mirror.preloaded;
|
|
}
|
|
get destroyed() {
|
|
return this.index === -1;
|
|
}
|
|
update() {
|
|
if (this.index === -1) return;
|
|
this.stats = {
|
|
peers: this.mirror.peers.length,
|
|
download: {
|
|
bytes: this.mirror.downloadedBytes,
|
|
blocks: this.mirror.downloadedBlocks,
|
|
speed: this.mirror.downloadSpeed(),
|
|
progress: this.mirror.downloadProgress
|
|
},
|
|
upload: {
|
|
bytes: this.mirror.uploadedBytes,
|
|
blocks: this.mirror.uploadedBlocks,
|
|
speed: this.mirror.uploadSpeed()
|
|
}
|
|
};
|
|
this.emit("update", this.stats);
|
|
}
|
|
destroy() {
|
|
if (this.index === -1) return;
|
|
clearInterval(this.interval);
|
|
const head = this.mirror.monitors.pop();
|
|
if (head !== this) {
|
|
this.mirror.monitors[this.index] = head;
|
|
head.index = this.index;
|
|
}
|
|
this.index = -1;
|
|
this.emit("destroy");
|
|
}
|
|
};
|
|
module.exports = class MirrorDrive {
|
|
constructor(src, dst, opts = {}) {
|
|
this.src = src;
|
|
this.dst = dst;
|
|
this.prefix = toArray(opts.prefix || "/");
|
|
this.dedup = !!opts.dedup;
|
|
this.dryRun = !!opts.dryRun;
|
|
this.prune = opts.prune !== false;
|
|
this.preload = opts.preload !== false && !!src.getBlobs;
|
|
this.preloaded = false;
|
|
this.includeProgress = !!opts.progress && !!src.getBlobs;
|
|
this.includeEquals = !!opts.includeEquals;
|
|
this.filter = opts.filter || null;
|
|
this.metadataEquals = opts.metadataEquals || null;
|
|
this.batch = !!opts.batch;
|
|
this.entries = opts.entries || null;
|
|
this.transformers = opts.transformers || [];
|
|
this.count = { files: 0, add: 0, remove: 0, change: 0 };
|
|
this.bytesRemoved = 0;
|
|
this.bytesAdded = 0;
|
|
this.ignore = opts.ignore ? toIgnoreFunction(opts.ignore) : null;
|
|
this.finished = false;
|
|
this.downloadedBlocks = 0;
|
|
this.downloadedBlocksEstimate = 0;
|
|
this.downloadedBytes = 0;
|
|
this.downloadSpeed = this.includeProgress ? speedometer() : null;
|
|
this.uploadedBlocks = 0;
|
|
this.uploadedBytes = 0;
|
|
this.uploadSpeed = this.includeProgress ? speedometer() : null;
|
|
this.monitors = [];
|
|
this.iterator = this._init();
|
|
}
|
|
[Symbol.asyncIterator]() {
|
|
return this.iterator;
|
|
}
|
|
get peers() {
|
|
return this.src.core?.peers || [];
|
|
}
|
|
get downloadProgress() {
|
|
if (this.finished) return 1;
|
|
if (!this.downloadedBlocksEstimate) return 0;
|
|
return Math.min(0.99, this.downloadedBlocks / this.downloadedBlocksEstimate);
|
|
}
|
|
monitor(opts) {
|
|
this.includeProgress = true;
|
|
if (this.downloadSpeed === null) this.downloadSpeed = speedometer();
|
|
if (this.uploadSpeed === null) this.uploadSpeed = speedometer();
|
|
return new Monitor(this, opts);
|
|
}
|
|
async done() {
|
|
while (true) {
|
|
const { done } = await this.iterator.next();
|
|
if (done) break;
|
|
}
|
|
}
|
|
_onupload(index, byteLength) {
|
|
this.uploadedBlocks++;
|
|
this.uploadedBytes += byteLength;
|
|
this.uploadSpeed(byteLength);
|
|
}
|
|
_ondownload(index, byteLength) {
|
|
this.downloadedBlocks++;
|
|
this.downloadedBytes += byteLength;
|
|
this.downloadSpeed(byteLength);
|
|
}
|
|
async _getBlobRange(blobs, entry) {
|
|
const blob = entry.value.blob;
|
|
if (!blob || !blob.byteLength) return null;
|
|
if (!blob.byteLength) {
|
|
const dl2 = blobs.core.download({ start: blob.blockOffset, length: blob.blockLength });
|
|
await dl2.ready();
|
|
return dl2;
|
|
}
|
|
const map = await blobs.getBlockMap(blob);
|
|
if (!map) return null;
|
|
const blocks = [];
|
|
for (const b of map.blocks) blocks.push(b.index);
|
|
const dl = blobs.core.download({ blocks });
|
|
await dl.ready();
|
|
return dl;
|
|
}
|
|
async _flushPreload(entries) {
|
|
const blobs = await this.src.getBlobs();
|
|
const promises = [];
|
|
for (const entry of entries) {
|
|
promises.push(this._getBlobRange(blobs, entry));
|
|
}
|
|
const ranges = await Promise.all(promises);
|
|
this.downloadedBlocksEstimate = this.downloadedBlocks;
|
|
for (const dl of ranges) {
|
|
if (!dl || !dl.request.context) continue;
|
|
this.downloadedBlocksEstimate += dl.request.context.end - dl.request.context.start;
|
|
}
|
|
this.preloaded = true;
|
|
for (const m of this.monitors) {
|
|
m.emit("preloaded");
|
|
}
|
|
for (const dl of ranges) {
|
|
if (!dl) continue;
|
|
await dl.done();
|
|
}
|
|
}
|
|
async *_init() {
|
|
try {
|
|
for await (const out of this._mirror()) yield out;
|
|
} finally {
|
|
while (this.monitors.length) {
|
|
this.monitors[this.monitors.length - 1].destroy();
|
|
}
|
|
}
|
|
}
|
|
async *_mirror() {
|
|
await this.src.ready();
|
|
await this.dst.ready();
|
|
if (this.dst.core && !this.dst.core.writable) throw new Error("Destination must be writable");
|
|
const blobs = this.includeProgress ? await this.src.getBlobs() : null;
|
|
const onupload = this._onupload.bind(this);
|
|
const ondownload = this._ondownload.bind(this);
|
|
if (blobs) {
|
|
blobs.core.on("upload", onupload);
|
|
blobs.core.on("download", ondownload);
|
|
}
|
|
const dst = this.batch ? this.dst.batch() : this.dst;
|
|
const dstBlobs = dst.getBlobs ? await dst.getBlobs() : null;
|
|
const srcBlobs = this.src.getBlobs ? await this.src.getBlobs() : null;
|
|
if (this.preload) {
|
|
const entries = [];
|
|
const maps = [];
|
|
const inflight = srcBlobs.core.replicator.inflightRange;
|
|
for await (const [, srcEntry] of this._list(this.src, null, this.filter)) {
|
|
entries.push(srcEntry);
|
|
const blob = srcEntry.value.blob;
|
|
if (blob && blob.blockMap && blob.blockLength) {
|
|
if (maps.length === 0) {
|
|
srcBlobs.core.replicator.setInflightRange(256, 512);
|
|
}
|
|
maps.push(srcBlobs.core.download({ start: blob.blockOffset, length: blob.blockLength }));
|
|
}
|
|
}
|
|
for (const m of maps) await m.done();
|
|
srcBlobs.core.replicator.setInflightRange(inflight);
|
|
this._flushPreload(entries).catch(noop);
|
|
}
|
|
if (this.prune) {
|
|
for await (const [key, dstEntry, srcEntry] of this._list(this.dst, this.src, null)) {
|
|
if (srcEntry) continue;
|
|
const removed = await blobLength(dstEntry, dstBlobs);
|
|
this.count.remove++;
|
|
this.bytesRemoved += removed;
|
|
yield { op: "remove", key, bytesRemoved: removed, bytesAdded: 0 };
|
|
if (!this.dryRun) await dst.del(key);
|
|
}
|
|
}
|
|
for await (const [key, srcEntry, dstEntry] of this._list(this.src, dst, this.filter)) {
|
|
if (!srcEntry) continue;
|
|
this.count.files++;
|
|
const hasTransformers = this.transformers && this.transformers.length > 0;
|
|
const s = hasTransformers === false ? await same(this, srcEntry, dstEntry) : DIFF;
|
|
if (s === SAME) {
|
|
if (this.includeEquals) {
|
|
yield { op: "equal", key, bytesRemoved: 0, bytesAdded: 0 };
|
|
}
|
|
continue;
|
|
}
|
|
const onlyMetadata = s === DIFF_META && !!dst.putEntry;
|
|
const dedup = !!dst.putEntry && this.dedup;
|
|
if (dstEntry) {
|
|
const removed = onlyMetadata ? 0 : await blobLength(dstEntry, dstBlobs);
|
|
const added = onlyMetadata ? 0 : await blobLength(srcEntry, srcBlobs);
|
|
this.count.change++;
|
|
this.bytesRemoved += removed;
|
|
this.bytesAdded += added;
|
|
yield {
|
|
op: "change",
|
|
key,
|
|
bytesRemoved: removed,
|
|
bytesAdded: added
|
|
};
|
|
} else {
|
|
const added = await blobLength(srcEntry, srcBlobs);
|
|
this.count.add++;
|
|
this.bytesAdded += added;
|
|
yield { op: "add", key, bytesRemoved: 0, bytesAdded: added };
|
|
}
|
|
if (this.dryRun) {
|
|
continue;
|
|
}
|
|
const transformers = [];
|
|
for (const transformer of this.transformers) {
|
|
if (typeof transformer !== "function") throw new Error("transformer must be a function");
|
|
const stream = transformer(key);
|
|
if (stream === null) continue;
|
|
if (!isStream(stream)) throw new Error("transformer must return a stream");
|
|
transformers.push(stream);
|
|
}
|
|
if (srcEntry.value.linkname) {
|
|
await dst.symlink(key, srcEntry.value.linkname);
|
|
} else if (!onlyMetadata) {
|
|
if (dedup) transformers.push(new RabinStream());
|
|
await pipelinePromise(
|
|
this.src.createReadStream(srcEntry),
|
|
...transformers,
|
|
dst.createWriteStream(key, {
|
|
dedup,
|
|
executable: srcEntry.value.executable,
|
|
metadata: srcEntry.value.metadata
|
|
})
|
|
);
|
|
} else {
|
|
await dst.putEntry(key, {
|
|
executable: srcEntry.value.executable,
|
|
linkname: srcEntry.value.linkname,
|
|
blob: dstEntry.value.blob,
|
|
metadata: srcEntry.value.metadata
|
|
});
|
|
}
|
|
}
|
|
if (this.batch) await dst.flush();
|
|
if (blobs) {
|
|
blobs.core.off("upload", onupload);
|
|
blobs.core.off("download", ondownload);
|
|
}
|
|
this.finished = true;
|
|
}
|
|
async *_list(a, b, filter) {
|
|
const lists = [];
|
|
for (const prefix of this.prefix) {
|
|
if (this.entries) {
|
|
lists.push(this.entries);
|
|
} else {
|
|
const stream = a.list(prefix, { ignore: this.ignore });
|
|
if (stream.on) {
|
|
stream.on("error", noop);
|
|
stream.resume();
|
|
stream.pause();
|
|
}
|
|
lists.push(stream);
|
|
}
|
|
}
|
|
for (let i = 0; i < this.prefix.length; i++) {
|
|
const prefix = this.prefix[i];
|
|
const list = lists[i];
|
|
for await (const entry of list) {
|
|
const key = typeof entry === "object" ? entry.key : entry;
|
|
if (filter && !filter(key)) continue;
|
|
const entryA = await a.entry(entry);
|
|
const entryB = b ? await b.entry(key) : null;
|
|
yield [key, entryA, entryB];
|
|
}
|
|
if (prefix !== "/" && (!filter || filter(prefix))) {
|
|
const entryA = await a.entry(prefix);
|
|
const entryB = b ? await b.entry(prefix) : null;
|
|
if (!entryA && !entryB) continue;
|
|
yield [prefix, entryA, entryB];
|
|
}
|
|
}
|
|
}
|
|
};
|
|
function blobLength(entry, blobs) {
|
|
const blob = entry.value.blob;
|
|
if (!blob) return 0;
|
|
if (!blob.blockMap) return blob.byteLength;
|
|
return blobs.getByteLength(blob);
|
|
}
|
|
async function same(m, srcEntry, dstEntry) {
|
|
if (!dstEntry) return DIFF;
|
|
if (srcEntry.value.linkname || dstEntry.value.linkname) {
|
|
return srcEntry.value.linkname === dstEntry.value.linkname ? SAME : DIFF;
|
|
}
|
|
if (!maybeEquals(srcEntry, dstEntry)) return DIFF;
|
|
const eq = await streamEquals(m.src.createReadStream(srcEntry), m.dst.createReadStream(dstEntry));
|
|
const diff = eq ? DIFF_META : DIFF;
|
|
if (srcEntry.value.executable !== dstEntry.value.executable) return diff;
|
|
if (!metadataEquals(m, srcEntry, dstEntry)) return diff;
|
|
return eq ? SAME : DIFF;
|
|
}
|
|
function maybeEquals(srcEntry, dstEntry) {
|
|
const srcBlob = srcEntry.value.blob;
|
|
const dstBlob = dstEntry.value.blob;
|
|
if (!srcBlob && !dstBlob) return true;
|
|
if (!srcBlob || !dstBlob) return false;
|
|
if (srcBlob.blockMap || dstBlob.blockMap) return true;
|
|
return srcBlob.byteLength === dstBlob.byteLength;
|
|
}
|
|
function metadataEquals(m, srcEntry, dstEntry) {
|
|
if (!m.src.supportsMetadata || !m.dst.supportsMetadata) return true;
|
|
const srcMetadata = srcEntry.value.metadata;
|
|
const dstMetadata = dstEntry.value.metadata;
|
|
if (m.metadataEquals) {
|
|
return m.metadataEquals(srcMetadata, dstMetadata);
|
|
}
|
|
const noMetadata = !srcMetadata && !dstMetadata;
|
|
const identicalMetadata = !!(srcMetadata && dstMetadata && sameData(srcMetadata, dstMetadata));
|
|
return noMetadata || identicalMetadata;
|
|
}
|
|
function toIgnoreFunction(ignore) {
|
|
if (typeof ignore === "function") return ignore;
|
|
const all = [].concat(ignore).map((e) => unixPathResolve("/", e));
|
|
return (key) => all.some((path) => path === key || key.startsWith(path + "/"));
|
|
}
|
|
function toArray(prefix) {
|
|
return Array.isArray(prefix) ? prefix : [prefix];
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/localdrive/index.js
|
|
var require_localdrive = __commonJS({
|
|
"../../node_modules/localdrive/index.js"(exports, module) {
|
|
var fs = __require("fs");
|
|
var fsp = __require("fs/promises");
|
|
var path = __require("path");
|
|
var b4a = require_b4a();
|
|
var unixPathResolve = require_unix_path_resolve();
|
|
var { FileReadStream, FileWriteStream } = require_streams();
|
|
var mutexify = require_promise();
|
|
var MirrorDrive = require_mirror_drive();
|
|
module.exports = class Localdrive {
|
|
constructor(root, opts = {}) {
|
|
this.root = path.resolve(root);
|
|
this.metadata = handleMetadataHooks(opts.metadata) || {};
|
|
this.supportsMetadata = !!opts.metadata;
|
|
this._roots = [];
|
|
this._stat = opts.followLinks ? stat : lstat;
|
|
this._lock = mutexify();
|
|
this._atomics = opts.atomic ? /* @__PURE__ */ new Set() : null;
|
|
if (opts.roots) {
|
|
for (const prefix of Object.keys(opts.roots)) {
|
|
this._roots.push({
|
|
from: unixPathResolve("/", prefix),
|
|
to: path.resolve(opts.roots[prefix])
|
|
});
|
|
}
|
|
}
|
|
}
|
|
_root(keyname) {
|
|
for (const { from, to } of this._roots) {
|
|
if (keyname.startsWith(from)) return { prefix: from, root: to };
|
|
}
|
|
return { prefix: null, root: this.root };
|
|
}
|
|
_resolve(key) {
|
|
const keyname = unixPathResolve("/", key);
|
|
const { prefix, root } = this._root(keyname);
|
|
const filename = path.join(root, prefix ? keyname.replace(prefix, "") : keyname);
|
|
return { root, keyname, filename };
|
|
}
|
|
async ready() {
|
|
}
|
|
async close() {
|
|
}
|
|
async flush() {
|
|
}
|
|
batch() {
|
|
return this;
|
|
}
|
|
checkout() {
|
|
return this;
|
|
}
|
|
toPath(key) {
|
|
return this._resolve(key).filename;
|
|
}
|
|
async entry(name, opts) {
|
|
if (!opts || !opts.follow) return this._entry(name);
|
|
for (let i = 0; i < 16; i++) {
|
|
const node = await this._entry(name);
|
|
if (!node || !node.value.linkname) return node;
|
|
name = unixPathResolve(node.key, node.value.linkname);
|
|
}
|
|
throw new Error("Recursive symlink");
|
|
}
|
|
async _entry(key) {
|
|
if (typeof key === "object") key = key.key;
|
|
const { root, keyname, filename } = this._resolve(key);
|
|
const st = await this._stat(filename);
|
|
if (!st || st.isDirectory()) {
|
|
return null;
|
|
}
|
|
const entry = {
|
|
key: keyname,
|
|
value: {
|
|
executable: false,
|
|
linkname: null,
|
|
blob: null,
|
|
metadata: null
|
|
},
|
|
mtime: st.mtimeMs
|
|
};
|
|
if (st.isSymbolicLink()) {
|
|
let link = await fsp.readlink(filename);
|
|
if (link.startsWith(root)) link = link.slice(root.length);
|
|
entry.value.linkname = link.replace(/\\/g, "/");
|
|
return entry;
|
|
}
|
|
entry.value.executable = isExecutable(st.mode);
|
|
if (this.metadata.get) entry.value.metadata = await this.metadata.get(keyname);
|
|
if (st.isFile()) {
|
|
const blockLength = st.blocks || Math.ceil(st.size / st.blksize) * 8;
|
|
entry.value.blob = { byteOffset: 0, blockOffset: 0, blockLength, byteLength: st.size };
|
|
return entry;
|
|
}
|
|
return null;
|
|
}
|
|
async get(key, opts) {
|
|
const entry = await this.entry(key, opts);
|
|
if (!entry || !entry.value.blob) return null;
|
|
const rs = this.createReadStream(key);
|
|
const chunks = [];
|
|
for await (const chunk of rs) {
|
|
chunks.push(chunk);
|
|
}
|
|
return b4a.concat(chunks);
|
|
}
|
|
put(key, buffer, opts) {
|
|
return new Promise((resolve, reject) => {
|
|
const ws = this.createWriteStream(key, opts);
|
|
let error = null;
|
|
ws.on("error", (err) => {
|
|
error = err;
|
|
});
|
|
ws.on("close", () => {
|
|
if (error) reject(error);
|
|
else resolve();
|
|
});
|
|
ws.end(buffer);
|
|
});
|
|
}
|
|
async del(key) {
|
|
const { root, keyname, filename } = this._resolve(key);
|
|
try {
|
|
await fsp.unlink(filename);
|
|
} catch (error) {
|
|
if (error.code === "ENOENT") return;
|
|
throw error;
|
|
}
|
|
const release = await this._lock();
|
|
try {
|
|
await gcEmptyFolders(root, path.dirname(filename));
|
|
} finally {
|
|
release();
|
|
}
|
|
if (this.metadata.del) await this.metadata.del(keyname);
|
|
}
|
|
async symlink(key, linkname) {
|
|
const entry = await this.entry(key);
|
|
if (entry) await this.del(key);
|
|
const { filename: pointer } = this._resolve(key);
|
|
const release = await this._lock();
|
|
try {
|
|
await fsp.mkdir(path.dirname(pointer), { recursive: true });
|
|
const target = linkname.startsWith("/") ? this._resolve(linkname).filename : linkname.replace(/\//g, path.sep);
|
|
const st = await this._stat(target);
|
|
const type = st && st.isDirectory() ? "junction" : null;
|
|
await fsp.symlink(target, pointer, type);
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
compare(a, b) {
|
|
const diff = a.mtime - b.mtime;
|
|
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
|
|
}
|
|
async *list(folder, opts = {}) {
|
|
if (typeof folder === "object") {
|
|
opts = folder;
|
|
folder = void 0;
|
|
}
|
|
const ignore = opts.ignore ? [].concat(opts.ignore).map((e) => unixPathResolve("/", e)) : [];
|
|
const { keyname, filename: fulldir } = this._resolve(folder || "/");
|
|
const iterator = await opendir(fulldir);
|
|
if (!iterator) return;
|
|
for await (const dirent of iterator) {
|
|
const key = unixPathResolve(keyname, dirent.name);
|
|
if (ignore.includes(key)) continue;
|
|
if (dirent.isDirectory()) {
|
|
yield* this.list(key, opts);
|
|
continue;
|
|
}
|
|
const entry = await this.entry(key);
|
|
if (entry) yield entry;
|
|
}
|
|
}
|
|
async *readdir(folder) {
|
|
const { keyname, filename: fulldir } = this._resolve(folder || "/");
|
|
const iterator = await readdir(fulldir);
|
|
if (!iterator) return;
|
|
for await (const dirent of iterator) {
|
|
const key = unixPathResolve(keyname, dirent.name);
|
|
let suffix = key.slice(keyname.length);
|
|
const i = suffix.indexOf("/");
|
|
if (i > -1) suffix = suffix.slice(i + 1);
|
|
if (dirent.isDirectory()) {
|
|
if (!await isEmptyDirectory(this, key)) {
|
|
yield suffix;
|
|
}
|
|
continue;
|
|
}
|
|
const entry = await this.entry(key);
|
|
if (entry) yield suffix;
|
|
}
|
|
}
|
|
mirror(out, opts) {
|
|
return new MirrorDrive(this, out, opts);
|
|
}
|
|
createReadStream(key, opts) {
|
|
if (typeof key === "object") key = key.key;
|
|
const { filename } = this._resolve(key);
|
|
return new FileReadStream(filename, opts);
|
|
}
|
|
createWriteStream(key, opts) {
|
|
const { keyname, filename } = this._resolve(key);
|
|
return new FileWriteStream(filename, keyname, this, opts);
|
|
}
|
|
_alloc(filename) {
|
|
if (!this._atomics) return filename;
|
|
let c = 0;
|
|
while (this._atomics.has(filename + "." + c + ".localdrive.tmp")) c++;
|
|
filename += "." + c + ".localdrive.tmp";
|
|
this._atomics.add(filename);
|
|
return filename;
|
|
}
|
|
_free(atomicFilename) {
|
|
this._atomics.delete(atomicFilename);
|
|
}
|
|
};
|
|
function handleMetadataHooks(metadata) {
|
|
if (metadata instanceof Map) {
|
|
return {
|
|
get: (key) => metadata.has(key) ? metadata.get(key) : null,
|
|
put: (key, value) => metadata.set(key, value),
|
|
del: (key) => metadata.delete(key)
|
|
};
|
|
}
|
|
return metadata;
|
|
}
|
|
function isExecutable(mode) {
|
|
return !!(mode & fs.constants.S_IXUSR);
|
|
}
|
|
async function lstat(filename) {
|
|
try {
|
|
return await fsp.lstat(filename);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
async function stat(filename) {
|
|
try {
|
|
return await fsp.stat(filename);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
async function opendir(dir) {
|
|
try {
|
|
return await fsp.opendir(dir);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
async function readdir(dir) {
|
|
try {
|
|
return await fsp.readdir(dir, { withFileTypes: true });
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
async function gcEmptyFolders(root, dir) {
|
|
try {
|
|
while (dir !== root) {
|
|
await fsp.rmdir(dir);
|
|
dir = path.dirname(dir);
|
|
}
|
|
} catch {
|
|
}
|
|
}
|
|
async function isEmptyDirectory(drive, key) {
|
|
for await (const entry of drive.list(key)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/es-module-lexer/dist/lexer.js
|
|
var lexer_exports = {};
|
|
__export(lexer_exports, {
|
|
ImportType: () => ImportType,
|
|
init: () => init,
|
|
initSync: () => initSync,
|
|
parse: () => parse
|
|
});
|
|
function parse(E2, g = "@") {
|
|
if (!C) return init.then((() => parse(E2)));
|
|
const I = E2.length + 1, w = (C.__heap_base.value || C.__heap_base) + 4 * I - C.memory.buffer.byteLength;
|
|
w > 0 && C.memory.grow(Math.ceil(w / 65536));
|
|
const K = C.sa(I - 1);
|
|
if ((A ? B : Q)(E2, new Uint16Array(C.memory.buffer, K, I)), !C.parse()) throw Object.assign(new Error(`Parse error ${g}:${E2.slice(0, C.e()).split("\n").length}:${C.e() - E2.lastIndexOf("\n", C.e() - 1)}`), { idx: C.e() });
|
|
const o = [], D = [];
|
|
for (; C.ri(); ) {
|
|
const A2 = C.is(), Q2 = C.ie(), B2 = C.it(), g2 = C.ai(), I2 = C.id(), w2 = C.ss(), K2 = C.se();
|
|
let D2;
|
|
C.ip() && (D2 = k(E2.slice(-1 === I2 ? A2 - 1 : A2, -1 === I2 ? Q2 + 1 : Q2))), o.push({ n: D2, t: B2, s: A2, e: Q2, ss: w2, se: K2, d: I2, a: g2 });
|
|
}
|
|
for (; C.re(); ) {
|
|
const A2 = C.es(), Q2 = C.ee(), B2 = C.els(), g2 = C.ele(), I2 = E2.slice(A2, Q2), w2 = I2[0], K2 = B2 < 0 ? void 0 : E2.slice(B2, g2), o2 = K2 ? K2[0] : "";
|
|
D.push({ s: A2, e: Q2, ls: B2, le: g2, n: '"' === w2 || "'" === w2 ? k(I2) : I2, ln: '"' === o2 || "'" === o2 ? k(K2) : K2 });
|
|
}
|
|
function k(A2) {
|
|
try {
|
|
return (0, eval)(A2);
|
|
} catch (A3) {
|
|
}
|
|
}
|
|
return [o, D, !!C.f(), !!C.ms()];
|
|
}
|
|
function Q(A2, Q2) {
|
|
const B2 = A2.length;
|
|
let C2 = 0;
|
|
for (; C2 < B2; ) {
|
|
const B3 = A2.charCodeAt(C2);
|
|
Q2[C2++] = (255 & B3) << 8 | B3 >>> 8;
|
|
}
|
|
}
|
|
function B(A2, Q2) {
|
|
const B2 = A2.length;
|
|
let C2 = 0;
|
|
for (; C2 < B2; ) Q2[C2] = A2.charCodeAt(C2++);
|
|
}
|
|
var ImportType, A, C, E, init, initSync;
|
|
var init_lexer = __esm({
|
|
"../../node_modules/es-module-lexer/dist/lexer.js"() {
|
|
!(function(A2) {
|
|
A2[A2.Static = 1] = "Static", A2[A2.Dynamic = 2] = "Dynamic", A2[A2.ImportMeta = 3] = "ImportMeta", A2[A2.StaticSourcePhase = 4] = "StaticSourcePhase", A2[A2.DynamicSourcePhase = 5] = "DynamicSourcePhase", A2[A2.StaticDeferPhase = 6] = "StaticDeferPhase", A2[A2.DynamicDeferPhase = 7] = "DynamicDeferPhase";
|
|
})(ImportType || (ImportType = {}));
|
|
A = 1 === new Uint8Array(new Uint16Array([1]).buffer)[0];
|
|
E = () => {
|
|
return A2 = "AGFzbQEAAAABKwhgAX8Bf2AEf39/fwBgAAF/YAAAYAF/AGADf39/AX9gAn9/AX9gA39/fwADMTAAAQECAgICAgICAgICAgICAgICAgIAAwMDBAQAAAUAAAAAAAMDAwAGAAAABwAGAgUEBQFwAQEBBQMBAAEGDwJ/AUHA8gALfwBBwPIACwd6FQZtZW1vcnkCAAJzYQAAAWUAAwJpcwAEAmllAAUCc3MABgJzZQAHAml0AAgCYWkACQJpZAAKAmlwAAsCZXMADAJlZQANA2VscwAOA2VsZQAPAnJpABACcmUAEQFmABICbXMAEwVwYXJzZQAUC19faGVhcF9iYXNlAwEKzkQwaAEBf0EAIAA2AoAKQQAoAtwJIgEgAEEBdGoiAEEAOwEAQQAgAEECaiIANgKECkEAIAA2AogKQQBBADYC4AlBAEEANgLwCUEAQQA2AugJQQBBADYC5AlBAEEANgL4CUEAQQA2AuwJIAEL0wEBA39BACgC8AkhBEEAQQAoAogKIgU2AvAJQQAgBDYC9AlBACAFQSRqNgKICiAEQSBqQeAJIAQbIAU2AgBBACgC1AkhBEEAKALQCSEGIAUgATYCACAFIAA2AgggBSACIAJBAmpBACAGIANGIgAbIAQgA0YiBBs2AgwgBSADNgIUIAVBADYCECAFIAI2AgQgBUEANgIgIAVBA0EBQQIgABsgBBs2AhwgBUEAKALQCSADRiICOgAYAkACQCACDQBBACgC1AkgA0cNAQtBAEEBOgCMCgsLXgEBf0EAKAL4CSIEQRBqQeQJIAQbQQAoAogKIgQ2AgBBACAENgL4CUEAIARBFGo2AogKQQBBAToAjAogBEEANgIQIAQgAzYCDCAEIAI2AgggBCABNgIEIAQgADYCAAsIAEEAKAKQCgsVAEEAKALoCSgCAEEAKALcCWtBAXULHgEBf0EAKALoCSgCBCIAQQAoAtwJa0EBdUF/IAAbCxUAQQAoAugJKAIIQQAoAtwJa0EBdQseAQF/QQAoAugJKAIMIgBBACgC3AlrQQF1QX8gABsLCwBBACgC6AkoAhwLHgEBf0EAKALoCSgCECIAQQAoAtwJa0EBdUF/IAAbCzsBAX8CQEEAKALoCSgCFCIAQQAoAtAJRw0AQX8PCwJAIABBACgC1AlHDQBBfg8LIABBACgC3AlrQQF1CwsAQQAoAugJLQAYCxUAQQAoAuwJKAIAQQAoAtwJa0EBdQsVAEEAKALsCSgCBEEAKALcCWtBAXULHgEBf0EAKALsCSgCCCIAQQAoAtwJa0EBdUF/IAAbCx4BAX9BACgC7AkoAgwiAEEAKALcCWtBAXVBfyAAGwslAQF/QQBBACgC6AkiAEEgakHgCSAAGygCACIANgLoCSAAQQBHCyUBAX9BAEEAKALsCSIAQRBqQeQJIAAbKAIAIgA2AuwJIABBAEcLCABBAC0AlAoLCABBAC0AjAoL3Q0BBX8jAEGA0ABrIgAkAEEAQQE6AJQKQQBBACgC2Ak2ApwKQQBBACgC3AlBfmoiATYCsApBACABQQAoAoAKQQF0aiICNgK0CkEAQQA6AIwKQQBBADsBlgpBAEEAOwGYCkEAQQA6AKAKQQBBADYCkApBAEEAOgD8CUEAIABBgBBqNgKkCkEAIAA2AqgKQQBBADoArAoCQAJAAkACQANAQQAgAUECaiIDNgKwCiABIAJPDQECQCADLwEAIgJBd2pBBUkNAAJAAkACQAJAAkAgAkGbf2oOBQEICAgCAAsgAkEgRg0EIAJBL0YNAyACQTtGDQIMBwtBAC8BmAoNASADEBVFDQEgAUEEakGCCEEKEC8NARAWQQAtAJQKDQFBAEEAKAKwCiIBNgKcCgwHCyADEBVFDQAgAUEEakGMCEEKEC8NABAXC0EAQQAoArAKNgKcCgwBCwJAIAEvAQQiA0EqRg0AIANBL0cNBBAYDAELQQEQGQtBACgCtAohAkEAKAKwCiEBDAALC0EAIQIgAyEBQQAtAPwJDQIMAQtBACABNgKwCkEAQQA6AJQKCwNAQQAgAUECaiIDNgKwCgJAAkACQAJAAkACQAJAIAFBACgCtApPDQAgAy8BACICQXdqQQVJDQYCQAJAAkACQAJAAkACQAJAAkACQCACQWBqDgoQDwYPDw8PBQECAAsCQAJAAkACQCACQaB/ag4KCxISAxIBEhISAgALIAJBhX9qDgMFEQYJC0EALwGYCg0QIAMQFUUNECABQQRqQYIIQQoQLw0QEBYMEAsgAxAVRQ0PIAFBBGpBjAhBChAvDQ8QFwwPCyADEBVFDQ4gASkABELsgISDsI7AOVINDiABLwEMIgNBd2oiAUEXSw0MQQEgAXRBn4CABHFFDQwMDQtBAEEALwGYCiIBQQFqOwGYCkEAKAKkCiABQQN0aiIBQQE2AgAgAUEAKAKcCjYCBAwNC0EALwGYCiIDRQ0JQQAgA0F/aiIDOwGYCkEALwGWCiICRQ0MQQAoAqQKIANB//8DcUEDdGooAgBBBUcNDAJAIAJBAnRBACgCqApqQXxqKAIAIgMoAgQNACADQQAoApwKQQJqNgIEC0EAIAJBf2o7AZYKIAMgAUEEajYCDAwMCwJAQQAoApwKIgEvAQBBKUcNAEEAKALwCSIDRQ0AIAMoAgQgAUcNAEEAQQAoAvQJIgM2AvAJAkAgA0UNACADQQA2AiAMAQtBAEEANgLgCQtBAEEALwGYCiIDQQFqOwGYCkEAKAKkCiADQQN0aiIDQQZBAkEALQCsChs2AgAgAyABNgIEQQBBADoArAoMCwtBAC8BmAoiAUUNB0EAIAFBf2oiATsBmApBACgCpAogAUH//wNxQQN0aigCAEEERg0EDAoLQScQGgwJC0EiEBoMCAsgAkEvRw0HAkACQCABLwEEIgFBKkYNACABQS9HDQEQGAwKC0EBEBkMCQsCQAJAAkACQEEAKAKcCiIBLwEAIgMQG0UNAAJAAkAgA0FVag4EAAkBAwkLIAFBfmovAQBBK0YNAwwICyABQX5qLwEAQS1GDQIMBwsgA0EpRw0BQQAoAqQKQQAvAZgKIgJBA3RqKAIEEBxFDQIMBgsgAUF+ai8BAEFQakH//wNxQQpPDQULQQAvAZgKIQILAkACQCACQf//A3EiAkUNACADQeYARw0AQQAoAqQKIAJBf2pBA3RqIgQoAgBBAUcNACABQX5qLwEAQe8ARw0BIAQoAgRBlghBAxAdRQ0BDAULIANB/QBHDQBBACgCpAogAkEDdGoiAigCBBAeDQQgAigCAEEGRg0ECyABEB8NAyADRQ0DIANBL0ZBAC0AoApBAEdxDQMCQEEAKAL4CSICRQ0AIAEgAigCAEkNACABIAIoAgRNDQQLIAFBfmohAUEAKALcCSECAkADQCABQQJqIgQgAk0NAUEAIAE2ApwKIAEvAQAhAyABQX5qIgQhASADECBFDQALIARBAmohBAsCQCADQf//A3EQIUUNACAEQX5qIQECQANAIAFBAmoiAyACTQ0BQQAgATYCnAogAS8BACEDIAFBfmoiBCEBIAMQIQ0ACyAEQQJqIQMLIAMQIg0EC0EAQQE6AKAKDAcLQQAoAqQKQQAvAZgKIgFBA3QiA2pBACgCnAo2AgRBACABQQFqOwGYCkEAKAKkCiADakEDNgIACxAjDAULQQAtAPwJQQAvAZYKQQAvAZgKcnJFIQIMBwsQJEEAQQA6AKAKDAMLECVBACECDAULIANBoAFHDQELQQBBAToArAoLQQBBACgCsAo2ApwKC0EAKAKwCiEBDAALCyAAQYDQAGokACACCxoAAkBBACgC3AkgAEcNAEEBDwsgAEF+ahAmC/4KAQZ/QQBBACgCsAoiAEEMaiIBNgKwCkEAKAL4CSECQQEQKSEDAkACQAJAAkACQAJAAkACQAJAQQAoArAKIgQgAUcNACADEChFDQELAkACQAJAAkACQAJAAkAgA0EqRg0AIANB+wBHDQFBACAEQQJqNgKwCkEBECkhA0EAKAKwCiEEA0ACQAJAIANB//8DcSIDQSJGDQAgA0EnRg0AIAMQLBpBACgCsAohAwwBCyADEBpBAEEAKAKwCkECaiIDNgKwCgtBARApGgJAIAQgAxAtIgNBLEcNAEEAQQAoArAKQQJqNgKwCkEBECkhAwsgA0H9AEYNA0EAKAKwCiIFIARGDQ8gBSEEIAVBACgCtApNDQAMDwsLQQAgBEECajYCsApBARApGkEAKAKwCiIDIAMQLRoMAgtBAEEAOgCUCgJAAkACQAJAAkACQCADQZ9/ag4MAgsEAQsDCwsLCwsFAAsgA0H2AEYNBAwKC0EAIARBDmoiAzYCsAoCQAJAAkBBARApQZ9/ag4GABICEhIBEgtBACgCsAoiBSkAAkLzgOSD4I3AMVINESAFLwEKECFFDRFBACAFQQpqNgKwCkEAECkaC0EAKAKwCiIFQQJqQbIIQQ4QLw0QIAUvARAiAkF3aiIBQRdLDQ1BASABdEGfgIAEcUUNDQwOC0EAKAKwCiIFKQACQuyAhIOwjsA5Ug0PIAUvAQoiAkF3aiIBQRdNDQYMCgtBACAEQQpqNgKwCkEAECkaQQAoArAKIQQLQQAgBEEQajYCsAoCQEEBECkiBEEqRw0AQQBBACgCsApBAmo2ArAKQQEQKSEEC0EAKAKwCiEDIAQQLBogA0EAKAKwCiIEIAMgBBACQQBBACgCsApBfmo2ArAKDwsCQCAEKQACQuyAhIOwjsA5Ug0AIAQvAQoQIEUNAEEAIARBCmo2ArAKQQEQKSEEQQAoArAKIQMgBBAsGiADQQAoArAKIgQgAyAEEAJBAEEAKAKwCkF+ajYCsAoPC0EAIARBBGoiBDYCsAoLQQAgBEEGajYCsApBAEEAOgCUCkEBECkhBEEAKAKwCiEDIAQQLCEEQQAoArAKIQIgBEHf/wNxIgFB2wBHDQNBACACQQJqNgKwCkEBECkhBUEAKAKwCiEDQQAhBAwEC0EAQQE6AIwKQQBBACgCsApBAmo2ArAKC0EBECkhBEEAKAKwCiEDAkAgBEHmAEcNACADQQJqQawIQQYQLw0AQQAgA0EIajYCsAogAEEBEClBABArIAJBEGpB5AkgAhshAwNAIAMoAgAiA0UNBSADQgA3AgggA0EQaiEDDAALC0EAIANBfmo2ArAKDAMLQQEgAXRBn4CABHFFDQMMBAtBASEECwNAAkACQCAEDgIAAQELIAVB//8DcRAsGkEBIQQMAQsCQAJAQQAoArAKIgQgA0YNACADIAQgAyAEEAJBARApIQQCQCABQdsARw0AIARBIHJB/QBGDQQLQQAoArAKIQMCQCAEQSxHDQBBACADQQJqNgKwCkEBECkhBUEAKAKwCiEDIAVBIHJB+wBHDQILQQAgA0F+ajYCsAoLIAFB2wBHDQJBACACQX5qNgKwCg8LQQAhBAwACwsPCyACQaABRg0AIAJB+wBHDQQLQQAgBUEKajYCsApBARApIgVB+wBGDQMMAgsCQCACQVhqDgMBAwEACyACQaABRw0CC0EAIAVBEGo2ArAKAkBBARApIgVBKkcNAEEAQQAoArAKQQJqNgKwCkEBECkhBQsgBUEoRg0BC0EAKAKwCiEBIAUQLBpBACgCsAoiBSABTQ0AIAQgAyABIAUQAkEAQQAoArAKQX5qNgKwCg8LIAQgA0EAQQAQAkEAIARBDGo2ArAKDwsQJQuFDAEKf0EAQQAoArAKIgBBDGoiATYCsApBARApIQJBACgCsAohAwJAAkACQAJAAkACQAJAAkAgAkEuRw0AQQAgA0ECajYCsAoCQEEBECkiAkHkAEYNAAJAIAJB8wBGDQAgAkHtAEcNB0EAKAKwCiICQQJqQZwIQQYQLw0HAkBBACgCnAoiAxAqDQAgAy8BAEEuRg0ICyAAIAAgAkEIakEAKALUCRABDwtBACgCsAoiAkECakGiCEEKEC8NBgJAQQAoApwKIgMQKg0AIAMvAQBBLkYNBwtBACEEQQAgAkEMajYCsApBASEFQQUhBkEBECkhAkEAIQdBASEIDAILQQAoArAKIgIpAAJC5YCYg9CMgDlSDQUCQEEAKAKcCiIDECoNACADLwEAQS5GDQYLQQAhBEEAIAJBCmo2ArAKQQIhCEEHIQZBASEHQQEQKSECQQEhBQwBCwJAAkACQAJAIAJB8wBHDQAgAyABTQ0AIANBAmpBoghBChAvDQACQCADLwEMIgRBd2oiB0EXSw0AQQEgB3RBn4CABHENAgsgBEGgAUYNAQtBACEHQQchBkEBIQQgAkHkAEYNAQwCC0EAIQRBACADQQxqIgI2ArAKQQEhBUEBECkhCQJAQQAoArAKIgYgAkYNAEHmACECAkAgCUHmAEYNAEEFIQZBACEHQQEhCCAJIQIMBAtBACEHQQEhCCAGQQJqQawIQQYQLw0EIAYvAQgQIEUNBAtBACEHQQAgAzYCsApBByEGQQEhBEEAIQVBACEIIAkhAgwCCyADIABBCmpNDQBBACEIQeQAIQICQCADKQACQuWAmIPQjIA5Ug0AAkACQCADLwEKIgRBd2oiB0EXSw0AQQEgB3RBn4CABHENAQtBACEIIARBoAFHDQELQQAhBUEAIANBCmo2ArAKQSohAkEBIQdBAiEIQQEQKSIJQSpGDQRBACADNgKwCkEBIQRBACEHQQAhCCAJIQIMAgsgAyEGQQAhBwwCC0EAIQVBACEICwJAIAJBKEcNAEEAKAKkCkEALwGYCiICQQN0aiIDQQAoArAKNgIEQQAgAkEBajsBmAogA0EFNgIAQQAoApwKLwEAQS5GDQRBAEEAKAKwCiIDQQJqNgKwCkEBECkhAiAAQQAoArAKQQAgAxABAkACQCAFDQBBACgC8AkhAQwBC0EAKALwCSIBIAY2AhwLQQBBAC8BlgoiA0EBajsBlgpBACgCqAogA0ECdGogATYCAAJAIAJBIkYNACACQSdGDQBBAEEAKAKwCkF+ajYCsAoPCyACEBpBAEEAKAKwCkECaiICNgKwCgJAAkACQEEBEClBV2oOBAECAgACC0EAQQAoArAKQQJqNgKwCkEBECkaQQAoAvAJIgMgAjYCBCADQQE6ABggA0EAKAKwCiICNgIQQQAgAkF+ajYCsAoPC0EAKALwCSIDIAI2AgQgA0EBOgAYQQBBAC8BmApBf2o7AZgKIANBACgCsApBAmo2AgxBAEEALwGWCkF/ajsBlgoPC0EAQQAoArAKQX5qNgKwCg8LAkAgBEEBcyACQfsAR3INAEEAKAKwCiECQQAvAZgKDQUDQAJAAkACQCACQQAoArQKTw0AQQEQKSICQSJGDQEgAkEnRg0BIAJB/QBHDQJBAEEAKAKwCkECajYCsAoLQQEQKSEDQQAoArAKIQICQCADQeYARw0AIAJBAmpBrAhBBhAvDQcLQQAgAkEIajYCsAoCQEEBECkiAkEiRg0AIAJBJ0cNBwsgACACQQAQKw8LIAIQGgtBAEEAKAKwCkECaiICNgKwCgwACwsCQAJAIAJBWWoOBAMBAQMACyACQSJGDQILQQAoArAKIQYLIAYgAUcNAEEAIABBCmo2ArAKDwsgAkEqRyAHcQ0DQQAvAZgKQf//A3ENA0EAKAKwCiECQQAoArQKIQEDQCACIAFPDQECQAJAIAIvAQAiA0EnRg0AIANBIkcNAQsgACADIAgQKw8LQQAgAkECaiICNgKwCgwACwsQJQsPC0EAIAJBfmo2ArAKDwtBAEEAKAKwCkF+ajYCsAoLRwEDf0EAKAKwCkECaiEAQQAoArQKIQECQANAIAAiAkF+aiABTw0BIAJBAmohACACLwEAQXZqDgQBAAABAAsLQQAgAjYCsAoLmAEBA39BAEEAKAKwCiIBQQJqNgKwCiABQQZqIQFBACgCtAohAgNAAkACQAJAIAFBfGogAk8NACABQX5qLwEAIQMCQAJAIAANACADQSpGDQEgA0F2ag4EAgQEAgQLIANBKkcNAwsgAS8BAEEvRw0CQQAgAUF+ajYCsAoMAQsgAUF+aiEBC0EAIAE2ArAKDwsgAUECaiEBDAALC4gBAQR/QQAoArAKIQFBACgCtAohAgJAAkADQCABIgNBAmohASADIAJPDQEgAS8BACIEIABGDQICQCAEQdwARg0AIARBdmoOBAIBAQIBCyADQQRqIQEgAy8BBEENRw0AIANBBmogASADLwEGQQpGGyEBDAALC0EAIAE2ArAKECUPC0EAIAE2ArAKC2wBAX8CQAJAIABBX2oiAUEFSw0AQQEgAXRBMXENAQsgAEFGakH//wNxQQZJDQAgAEEpRyAAQVhqQf//A3FBB0lxDQACQCAAQaV/ag4EAQAAAQALIABB/QBHIABBhX9qQf//A3FBBElxDwtBAQsuAQF/QQEhAQJAIABBpglBBRAdDQAgAEGWCEEDEB0NACAAQbAJQQIQHSEBCyABC0YBA39BACEDAkAgACACQQF0IgJrIgRBAmoiAEEAKALcCSIFSQ0AIAAgASACEC8NAAJAIAAgBUcNAEEBDwsgBBAmIQMLIAMLgwEBAn9BASEBAkACQAJAAkACQAJAIAAvAQAiAkFFag4EBQQEAQALAkAgAkGbf2oOBAMEBAIACyACQSlGDQQgAkH5AEcNAyAAQX5qQbwJQQYQHQ8LIABBfmovAQBBPUYPCyAAQX5qQbQJQQQQHQ8LIABBfmpByAlBAxAdDwtBACEBCyABC7QDAQJ/QQAhAQJAAkACQAJAAkACQAJAAkACQAJAIAAvAQBBnH9qDhQAAQIJCQkJAwkJBAUJCQYJBwkJCAkLAkACQCAAQX5qLwEAQZd/ag4EAAoKAQoLIABBfGpByghBAhAdDwsgAEF8akHOCEEDEB0PCwJAAkACQCAAQX5qLwEAQY1/ag4DAAECCgsCQCAAQXxqLwEAIgJB4QBGDQAgAkHsAEcNCiAAQXpqQeUAECcPCyAAQXpqQeMAECcPCyAAQXxqQdQIQQQQHQ8LIABBfGpB3AhBBhAdDwsgAEF+ai8BAEHvAEcNBiAAQXxqLwEAQeUARw0GAkAgAEF6ai8BACICQfAARg0AIAJB4wBHDQcgAEF4akHoCEEGEB0PCyAAQXhqQfQIQQIQHQ8LIABBfmpB+AhBBBAdDwtBASEBIABBfmoiAEHpABAnDQQgAEGACUEFEB0PCyAAQX5qQeQAECcPCyAAQX5qQYoJQQcQHQ8LIABBfmpBmAlBBBAdDwsCQCAAQX5qLwEAIgJB7wBGDQAgAkHlAEcNASAAQXxqQe4AECcPCyAAQXxqQaAJQQMQHSEBCyABCzQBAX9BASEBAkAgAEF3akH//wNxQQVJDQAgAEGAAXJBoAFGDQAgAEEuRyAAEChxIQELIAELMAEBfwJAAkAgAEF3aiIBQRdLDQBBASABdEGNgIAEcQ0BCyAAQaABRg0AQQAPC0EBC04BAn9BACEBAkACQCAALwEAIgJB5QBGDQAgAkHrAEcNASAAQX5qQfgIQQQQHQ8LIABBfmovAQBB9QBHDQAgAEF8akHcCEEGEB0hAQsgAQveAQEEf0EAKAKwCiEAQQAoArQKIQECQAJAAkADQCAAIgJBAmohACACIAFPDQECQAJAAkAgAC8BACIDQaR/ag4FAgMDAwEACyADQSRHDQIgAi8BBEH7AEcNAkEAIAJBBGoiADYCsApBAEEALwGYCiICQQFqOwGYCkEAKAKkCiACQQN0aiICQQQ2AgAgAiAANgIEDwtBACAANgKwCkEAQQAvAZgKQX9qIgA7AZgKQQAoAqQKIABB//8DcUEDdGooAgBBA0cNAwwECyACQQRqIQAMAAsLQQAgADYCsAoLECULC3ABAn8CQAJAA0BBAEEAKAKwCiIAQQJqIgE2ArAKIABBACgCtApPDQECQAJAAkAgAS8BACIBQaV/ag4CAQIACwJAIAFBdmoOBAQDAwQACyABQS9HDQIMBAsQLhoMAQtBACAAQQRqNgKwCgwACwsQJQsLNQEBf0EAQQE6APwJQQAoArAKIQBBAEEAKAK0CkECajYCsApBACAAQQAoAtwJa0EBdTYCkAoLQwECf0EBIQECQCAALwEAIgJBd2pB//8DcUEFSQ0AIAJBgAFyQaABRg0AQQAhASACEChFDQAgAkEuRyAAECpyDwsgAQs9AQJ/QQAhAgJAQQAoAtwJIgMgAEsNACAALwEAIAFHDQACQCADIABHDQBBAQ8LIABBfmovAQAQICECCyACC2gBAn9BASEBAkACQCAAQV9qIgJBBUsNAEEBIAJ0QTFxDQELIABB+P8DcUEoRg0AIABBRmpB//8DcUEGSQ0AAkAgAEGlf2oiAkEDSw0AIAJBAUcNAQsgAEGFf2pB//8DcUEESSEBCyABC5wBAQN/QQAoArAKIQECQANAAkACQCABLwEAIgJBL0cNAAJAIAEvAQIiAUEqRg0AIAFBL0cNBBAYDAILIAAQGQwBCwJAAkAgAEUNACACQXdqIgFBF0sNAUEBIAF0QZ+AgARxRQ0BDAILIAIQIUUNAwwBCyACQaABRw0CC0EAQQAoArAKIgNBAmoiATYCsAogA0EAKAK0CkkNAAsLIAILMQEBf0EAIQECQCAALwEAQS5HDQAgAEF+ai8BAEEuRw0AIABBfGovAQBBLkYhAQsgAQumBAEBfwJAIAFBIkYNACABQSdGDQAQJQ8LQQAoArAKIQMgARAaIAAgA0ECakEAKAKwCkEAKALQCRABAkAgAkEBSA0AQQAoAvAJQQRBBiACQQFGGzYCHAtBAEEAKAKwCkECajYCsAoCQAJAAkACQEEAECkiAUHhAEYNACABQfcARg0BQQAoArAKIQEMAgtBACgCsAoiAUECakHACEEKEC8NAUEGIQIMAgtBACgCsAoiAS8BAkHpAEcNACABLwEEQfQARw0AQQQhAiABLwEGQegARg0BC0EAIAFBfmo2ArAKDwtBACABIAJBAXRqNgKwCgJAQQEQKUH7AEYNAEEAIAE2ArAKDwtBACgCsAoiACECA0BBACACQQJqNgKwCgJAAkACQEEBECkiAkEiRg0AIAJBJ0cNAUEnEBpBAEEAKAKwCkECajYCsApBARApIQIMAgtBIhAaQQBBACgCsApBAmo2ArAKQQEQKSECDAELIAIQLCECCwJAIAJBOkYNAEEAIAE2ArAKDwtBAEEAKAKwCkECajYCsAoCQEEBECkiAkEiRg0AIAJBJ0YNAEEAIAE2ArAKDwsgAhAaQQBBACgCsApBAmo2ArAKAkACQEEBECkiAkEsRg0AIAJB/QBGDQFBACABNgKwCg8LQQBBACgCsApBAmo2ArAKQQEQKUH9AEYNAEEAKAKwCiECDAELC0EAKALwCSIBIAA2AhAgAUEAKAKwCkECajYCDAttAQJ/AkACQANAAkAgAEH//wNxIgFBd2oiAkEXSw0AQQEgAnRBn4CABHENAgsgAUGgAUYNASAAIQIgARAoDQJBACECQQBBACgCsAoiAEECajYCsAogAC8BAiIADQAMAgsLIAAhAgsgAkH//wNxC6sBAQR/AkACQEEAKAKwCiICLwEAIgNB4QBGDQAgASEEIAAhBQwBC0EAIAJBBGo2ArAKQQEQKSECQQAoArAKIQUCQAJAIAJBIkYNACACQSdGDQAgAhAsGkEAKAKwCiEEDAELIAIQGkEAQQAoArAKQQJqIgQ2ArAKC0EBECkhA0EAKAKwCiECCwJAIAIgBUYNACAFIARBACAAIAAgAUYiAhtBACABIAIbEAILIAMLcgEEf0EAKAKwCiEAQQAoArQKIQECQAJAA0AgAEECaiECIAAgAU8NAQJAAkAgAi8BACIDQaR/ag4CAQQACyACIQAgA0F2ag4EAgEBAgELIABBBGohAAwACwtBACACNgKwChAlQQAPC0EAIAI2ArAKQd0AC0kBA39BACEDAkAgAkUNAAJAA0AgAC0AACIEIAEtAAAiBUcNASABQQFqIQEgAEEBaiEAIAJBf2oiAg0ADAILCyAEIAVrIQMLIAMLC+wBAgBBgAgLzgEAAHgAcABvAHIAdABtAHAAbwByAHQAZgBvAHIAZQB0AGEAbwB1AHIAYwBlAHIAbwBtAHUAbgBjAHQAaQBvAG4AcwBzAGUAcgB0AHYAbwB5AGkAZQBkAGUAbABlAGMAbwBuAHQAaQBuAGkAbgBzAHQAYQBuAHQAeQBiAHIAZQBhAHIAZQB0AHUAcgBkAGUAYgB1AGcAZwBlAGEAdwBhAGkAdABoAHIAdwBoAGkAbABlAGkAZgBjAGEAdABjAGYAaQBuAGEAbABsAGUAbABzAABB0AkLEAEAAAACAAAAAAQAAEA5AAA=", "undefined" != typeof Buffer ? Buffer.from(A2, "base64") : Uint8Array.from(atob(A2), ((A3) => A3.charCodeAt(0)));
|
|
var A2;
|
|
};
|
|
init = WebAssembly.compile(E()).then(WebAssembly.instantiate).then((({ exports: A2 }) => {
|
|
C = A2;
|
|
}));
|
|
initSync = () => {
|
|
if (C) return;
|
|
const A2 = new WebAssembly.Module(E());
|
|
C = new WebAssembly.Instance(A2).exports;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/cjs-module-lexer/lexer.js
|
|
var require_lexer = __commonJS({
|
|
"../../node_modules/cjs-module-lexer/lexer.js"(exports, module) {
|
|
var source;
|
|
var pos;
|
|
var end;
|
|
var openTokenDepth;
|
|
var templateDepth;
|
|
var lastTokenPos;
|
|
var lastSlashWasDivision;
|
|
var templateStack;
|
|
var templateStackDepth;
|
|
var openTokenPosStack;
|
|
var openClassPosStack;
|
|
var nextBraceIsClass;
|
|
var starExportMap;
|
|
var lastStarExportSpecifier;
|
|
var _exports;
|
|
var unsafeGetters;
|
|
var reexports;
|
|
function resetState() {
|
|
openTokenDepth = 0;
|
|
templateDepth = -1;
|
|
lastTokenPos = -1;
|
|
lastSlashWasDivision = false;
|
|
templateStack = new Array(1024);
|
|
templateStackDepth = 0;
|
|
openTokenPosStack = new Array(1024);
|
|
openClassPosStack = new Array(1024);
|
|
nextBraceIsClass = false;
|
|
starExportMap = /* @__PURE__ */ Object.create(null);
|
|
lastStarExportSpecifier = null;
|
|
_exports = /* @__PURE__ */ new Set();
|
|
unsafeGetters = /* @__PURE__ */ new Set();
|
|
reexports = /* @__PURE__ */ new Set();
|
|
}
|
|
var Import = 0;
|
|
var ExportAssign = 1;
|
|
var ExportStar = 2;
|
|
function parseCJS(source2, name = "@") {
|
|
resetState();
|
|
try {
|
|
parseSource(source2);
|
|
} catch (e) {
|
|
e.message += `
|
|
at ${name}:${source2.slice(0, pos).split("\n").length}:${pos - source2.lastIndexOf("\n", pos - 1)}`;
|
|
e.loc = pos;
|
|
throw e;
|
|
}
|
|
const result = { exports: [..._exports].filter((expt) => expt !== void 0 && !unsafeGetters.has(expt)), reexports: [...reexports].filter((reexpt) => reexpt !== void 0) };
|
|
resetState();
|
|
return result;
|
|
}
|
|
function decode(str) {
|
|
if (str[0] === '"' || str[0] === "'") {
|
|
try {
|
|
const decoded = (0, eval)(str);
|
|
for (let i = 0; i < decoded.length; i++) {
|
|
const surrogatePrefix = decoded.charCodeAt(i) & 64512;
|
|
if (surrogatePrefix < 55296) {
|
|
continue;
|
|
} else if (surrogatePrefix === 55296) {
|
|
if ((decoded.charCodeAt(++i) & 64512) !== 56320)
|
|
return;
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
return decoded;
|
|
} catch {
|
|
}
|
|
} else {
|
|
return str;
|
|
}
|
|
}
|
|
function parseSource(cjsSource) {
|
|
source = cjsSource;
|
|
pos = -1;
|
|
end = source.length - 1;
|
|
let ch2 = 0;
|
|
if (source.charCodeAt(0) === 35 && source.charCodeAt(1) === 33) {
|
|
if (source.length === 2)
|
|
return true;
|
|
pos += 2;
|
|
while (pos++ < end) {
|
|
ch2 = source.charCodeAt(pos);
|
|
if (ch2 === 10 || ch2 === 13)
|
|
break;
|
|
}
|
|
}
|
|
while (pos++ < end) {
|
|
ch2 = source.charCodeAt(pos);
|
|
if (ch2 === 32 || ch2 < 14 && ch2 > 8)
|
|
continue;
|
|
if (openTokenDepth === 0) {
|
|
switch (ch2) {
|
|
case 105:
|
|
if (source.startsWith("mport", pos + 1) && keywordStart(pos))
|
|
throwIfImportStatement();
|
|
lastTokenPos = pos;
|
|
continue;
|
|
case 114:
|
|
const startPos = pos;
|
|
if (tryParseRequire(Import) && keywordStart(startPos))
|
|
tryBacktrackAddStarExportBinding(startPos - 1);
|
|
lastTokenPos = pos;
|
|
continue;
|
|
case 95:
|
|
if (source.startsWith("interopRequireWildcard", pos + 1) && (keywordStart(pos) || source.charCodeAt(pos - 1) === 46)) {
|
|
const startPos2 = pos;
|
|
pos += 23;
|
|
if (source.charCodeAt(pos) === 40) {
|
|
pos++;
|
|
openTokenPosStack[openTokenDepth++] = lastTokenPos;
|
|
if (tryParseRequire(Import) && keywordStart(startPos2)) {
|
|
tryBacktrackAddStarExportBinding(startPos2 - 1);
|
|
}
|
|
}
|
|
} else if (source.startsWith("_export", pos + 1) && (keywordStart(pos) || source.charCodeAt(pos - 1) === 46)) {
|
|
pos += 8;
|
|
if (source.startsWith("Star", pos))
|
|
pos += 4;
|
|
if (source.charCodeAt(pos) === 40) {
|
|
openTokenPosStack[openTokenDepth++] = lastTokenPos;
|
|
if (source.charCodeAt(++pos) === 114)
|
|
tryParseRequire(ExportStar);
|
|
}
|
|
}
|
|
lastTokenPos = pos;
|
|
continue;
|
|
}
|
|
}
|
|
switch (ch2) {
|
|
case 101:
|
|
if (source.startsWith("xport", pos + 1) && keywordStart(pos)) {
|
|
if (source.charCodeAt(pos + 6) === 115)
|
|
tryParseExportsDotAssign(false);
|
|
else if (openTokenDepth === 0)
|
|
throwIfExportStatement();
|
|
}
|
|
break;
|
|
case 99:
|
|
if (keywordStart(pos) && source.startsWith("lass", pos + 1) && isBrOrWs(source.charCodeAt(pos + 5)))
|
|
nextBraceIsClass = true;
|
|
break;
|
|
case 109:
|
|
if (source.startsWith("odule", pos + 1) && keywordStart(pos))
|
|
tryParseModuleExportsDotAssign();
|
|
break;
|
|
case 79:
|
|
if (source.startsWith("bject", pos + 1) && keywordStart(pos))
|
|
tryParseObjectDefineOrKeys(openTokenDepth === 0);
|
|
break;
|
|
case 40:
|
|
openTokenPosStack[openTokenDepth++] = lastTokenPos;
|
|
break;
|
|
case 41:
|
|
if (openTokenDepth === 0)
|
|
throw new Error("Unexpected closing bracket.");
|
|
openTokenDepth--;
|
|
break;
|
|
case 123:
|
|
openClassPosStack[openTokenDepth] = nextBraceIsClass;
|
|
nextBraceIsClass = false;
|
|
openTokenPosStack[openTokenDepth++] = lastTokenPos;
|
|
break;
|
|
case 125:
|
|
if (openTokenDepth === 0)
|
|
throw new Error("Unexpected closing brace.");
|
|
if (openTokenDepth-- === templateDepth) {
|
|
templateDepth = templateStack[--templateStackDepth];
|
|
templateString();
|
|
} else {
|
|
if (templateDepth !== -1 && openTokenDepth < templateDepth)
|
|
throw new Error("Unexpected closing brace.");
|
|
}
|
|
break;
|
|
case 60:
|
|
break;
|
|
case 39:
|
|
case 34:
|
|
stringLiteral(ch2);
|
|
break;
|
|
case 47: {
|
|
const next_ch = source.charCodeAt(pos + 1);
|
|
if (next_ch === 47) {
|
|
lineComment();
|
|
continue;
|
|
} else if (next_ch === 42) {
|
|
blockComment();
|
|
continue;
|
|
} else {
|
|
const lastToken = source.charCodeAt(lastTokenPos);
|
|
if (isExpressionPunctuator(lastToken) && !(lastToken === 46 && (source.charCodeAt(lastTokenPos - 1) >= 48 && source.charCodeAt(lastTokenPos - 1) <= 57)) && !(lastToken === 43 && source.charCodeAt(lastTokenPos - 1) === 43) && !(lastToken === 45 && source.charCodeAt(lastTokenPos - 1) === 45) || lastToken === 41 && isParenKeyword(openTokenPosStack[openTokenDepth]) || lastToken === 125 && (isExpressionTerminator(openTokenPosStack[openTokenDepth]) || openClassPosStack[openTokenDepth]) || lastToken === 47 && lastSlashWasDivision || isExpressionKeyword(lastTokenPos) || !lastToken) {
|
|
regularExpression();
|
|
lastSlashWasDivision = false;
|
|
} else {
|
|
lastSlashWasDivision = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 96:
|
|
templateString();
|
|
break;
|
|
}
|
|
lastTokenPos = pos;
|
|
}
|
|
if (templateDepth !== -1)
|
|
throw new Error("Unterminated template.");
|
|
if (openTokenDepth)
|
|
throw new Error("Unterminated braces.");
|
|
}
|
|
function tryBacktrackAddStarExportBinding(bPos) {
|
|
while (source.charCodeAt(bPos) === 32 && bPos >= 0)
|
|
bPos--;
|
|
if (source.charCodeAt(bPos) === 61) {
|
|
bPos--;
|
|
while (source.charCodeAt(bPos) === 32 && bPos >= 0)
|
|
bPos--;
|
|
let codePoint;
|
|
const id_end = bPos;
|
|
let identifierStart = false;
|
|
while ((codePoint = codePointAtLast(bPos)) && bPos >= 0) {
|
|
if (codePoint === 92)
|
|
return;
|
|
if (!isIdentifierChar(codePoint, true))
|
|
break;
|
|
identifierStart = isIdentifierStart(codePoint, true);
|
|
bPos -= codePointLen(codePoint);
|
|
}
|
|
if (identifierStart && source.charCodeAt(bPos) === 32) {
|
|
const starExportId = source.slice(bPos + 1, id_end + 1);
|
|
while (source.charCodeAt(bPos) === 32 && bPos >= 0)
|
|
bPos--;
|
|
switch (source.charCodeAt(bPos)) {
|
|
case 114:
|
|
if (!source.startsWith("va", bPos - 2))
|
|
return;
|
|
break;
|
|
case 116:
|
|
if (!source.startsWith("le", bPos - 2) && !source.startsWith("cons", bPos - 4))
|
|
return;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
starExportMap[starExportId] = lastStarExportSpecifier;
|
|
}
|
|
}
|
|
}
|
|
function tryParseObjectHasOwnProperty(it_id) {
|
|
ch = commentWhitespace();
|
|
if (ch !== 79 || !source.startsWith("bject", pos + 1)) return false;
|
|
pos += 6;
|
|
ch = commentWhitespace();
|
|
if (ch !== 46) return false;
|
|
pos++;
|
|
ch = commentWhitespace();
|
|
if (ch === 112) {
|
|
if (!source.startsWith("rototype", pos + 1)) return false;
|
|
pos += 9;
|
|
ch = commentWhitespace();
|
|
if (ch !== 46) return false;
|
|
pos++;
|
|
ch = commentWhitespace();
|
|
}
|
|
if (ch !== 104 || !source.startsWith("asOwnProperty", pos + 1)) return false;
|
|
pos += 14;
|
|
ch = commentWhitespace();
|
|
if (ch !== 46) return false;
|
|
pos++;
|
|
ch = commentWhitespace();
|
|
if (ch !== 99 || !source.startsWith("all", pos + 1)) return false;
|
|
pos += 4;
|
|
ch = commentWhitespace();
|
|
if (ch !== 40) return false;
|
|
pos++;
|
|
ch = commentWhitespace();
|
|
if (!identifier()) return false;
|
|
ch = commentWhitespace();
|
|
if (ch !== 44) return false;
|
|
pos++;
|
|
ch = commentWhitespace();
|
|
if (!source.startsWith(it_id, pos)) return false;
|
|
pos += it_id.length;
|
|
ch = commentWhitespace();
|
|
if (ch !== 41) return false;
|
|
pos++;
|
|
return true;
|
|
}
|
|
function tryParseObjectDefineOrKeys(keys) {
|
|
pos += 6;
|
|
let revertPos = pos - 1;
|
|
let ch2 = commentWhitespace();
|
|
if (ch2 === 46) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 100 && source.startsWith("efineProperty", pos + 1)) {
|
|
let expt;
|
|
while (true) {
|
|
pos += 14;
|
|
revertPos = pos - 1;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!readExportsOrModuleDotExports(ch2)) break;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 44) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 39 && ch2 !== 34) break;
|
|
const exportPos = pos;
|
|
stringLiteral(ch2);
|
|
expt = source.slice(exportPos, ++pos);
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 44) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 123) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 101) {
|
|
if (!source.startsWith("numerable", pos + 1)) break;
|
|
pos += 10;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 58) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 116 || !source.startsWith("rue", pos + 1)) break;
|
|
pos += 4;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 44) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 === 118) {
|
|
if (!source.startsWith("alue", pos + 1)) break;
|
|
pos += 5;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 58) break;
|
|
_exports.add(decode(expt));
|
|
pos = revertPos;
|
|
return;
|
|
} else if (ch2 === 103) {
|
|
if (!source.startsWith("et", pos + 1)) break;
|
|
pos += 3;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 58) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 102) break;
|
|
if (!source.startsWith("unction", pos + 1)) break;
|
|
pos += 8;
|
|
let lastPos = pos;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40 && (lastPos === pos || !identifier())) break;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 123) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 114) break;
|
|
if (!source.startsWith("eturn", pos + 1)) break;
|
|
pos += 6;
|
|
ch2 = commentWhitespace();
|
|
if (!identifier()) break;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 46) {
|
|
pos++;
|
|
commentWhitespace();
|
|
if (!identifier()) break;
|
|
ch2 = commentWhitespace();
|
|
} else if (ch2 === 91) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 39 || ch2 === 34) stringLiteral(ch2);
|
|
else break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 93) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 === 59) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 !== 125) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 44) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 !== 125) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
_exports.add(decode(expt));
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
if (expt) {
|
|
unsafeGetters.add(decode(expt));
|
|
}
|
|
} else if (keys && ch2 === 107 && source.startsWith("eys", pos + 1)) {
|
|
while (true) {
|
|
pos += 4;
|
|
revertPos = pos - 1;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
const id_start = pos;
|
|
if (!identifier()) break;
|
|
const id = source.slice(id_start, pos);
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
revertPos = pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 46) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 102 || !source.startsWith("orEach", pos + 1)) break;
|
|
pos += 7;
|
|
ch2 = commentWhitespace();
|
|
revertPos = pos - 1;
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 102 || !source.startsWith("unction", pos + 1)) break;
|
|
pos += 8;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
const it_id_start = pos;
|
|
if (!identifier()) break;
|
|
const it_id = source.slice(it_id_start, pos);
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 123) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 105 || source.charCodeAt(pos + 1) !== 102) break;
|
|
pos += 2;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!source.startsWith(it_id, pos)) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 61) {
|
|
if (!source.startsWith("==", pos + 1)) break;
|
|
pos += 3;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 34 && ch2 !== 39) break;
|
|
let quot = ch2;
|
|
if (!source.startsWith("default", pos + 1)) break;
|
|
pos += 8;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== quot) break;
|
|
pos += 1;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 124 || source.charCodeAt(pos + 1) !== 124) break;
|
|
pos += 2;
|
|
ch2 = commentWhitespace();
|
|
if (source.slice(pos, pos + it_id.length) !== it_id) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 61 || source.slice(pos + 1, pos + 3) !== "==") break;
|
|
pos += 3;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 34 && ch2 !== 39) break;
|
|
quot = ch2;
|
|
if (!source.startsWith("__esModule", pos + 1)) break;
|
|
pos += 11;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== quot) break;
|
|
pos += 1;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
pos += 1;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 114 || !source.startsWith("eturn", pos + 1)) break;
|
|
pos += 6;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 59)
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 105 && source.charCodeAt(pos + 1) === 102) {
|
|
let inIf = true;
|
|
pos += 2;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
const ifInnerPos = pos;
|
|
if (tryParseObjectHasOwnProperty(it_id)) {
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 114 || !source.startsWith("eturn", pos + 1)) break;
|
|
pos += 6;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 59)
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 105 && source.charCodeAt(pos + 1) === 102) {
|
|
pos += 2;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
} else {
|
|
inIf = false;
|
|
}
|
|
} else {
|
|
pos = ifInnerPos;
|
|
}
|
|
if (inIf) {
|
|
if (!source.startsWith(it_id, pos)) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 105 || !source.startsWith("n ", pos + 1)) break;
|
|
pos += 3;
|
|
ch2 = commentWhitespace();
|
|
if (!readExportsOrModuleDotExports(ch2)) break;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 38 || source.charCodeAt(pos + 1) !== 38) break;
|
|
pos += 2;
|
|
ch2 = commentWhitespace();
|
|
if (!readExportsOrModuleDotExports(ch2)) break;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 91) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!source.startsWith(it_id, pos)) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 93) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 61 || !source.startsWith("==", pos + 1)) break;
|
|
pos += 3;
|
|
ch2 = commentWhitespace();
|
|
if (!source.startsWith(id, pos)) break;
|
|
pos += id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 91) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!source.startsWith(it_id, pos)) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 93) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 114 || !source.startsWith("eturn", pos + 1)) break;
|
|
pos += 6;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 59)
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
}
|
|
} else if (ch2 === 33) {
|
|
if (!source.startsWith("==", pos + 1)) break;
|
|
pos += 3;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 34 && ch2 !== 39) break;
|
|
const quot = ch2;
|
|
if (!source.startsWith("default", pos + 1)) break;
|
|
pos += 8;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== quot) break;
|
|
pos += 1;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 38) {
|
|
if (source.charCodeAt(pos + 1) !== 38) break;
|
|
pos += 2;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 33) break;
|
|
pos += 1;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 79 && source.startsWith("bject", pos + 1) && source[pos + 6] === ".") {
|
|
if (!tryParseObjectHasOwnProperty(it_id)) break;
|
|
} else if (identifier()) {
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 46) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 104 || !source.startsWith("asOwnProperty", pos + 1)) break;
|
|
pos += 14;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40) break;
|
|
pos += 1;
|
|
ch2 = commentWhitespace();
|
|
if (!source.startsWith(it_id, pos)) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
pos += 1;
|
|
} else break;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 !== 41) break;
|
|
pos += 1;
|
|
ch2 = commentWhitespace();
|
|
} else break;
|
|
if (readExportsOrModuleDotExports(ch2)) {
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 91) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (source.slice(pos, pos + it_id.length) !== it_id) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 93) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 61) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (source.slice(pos, pos + id.length) !== id) break;
|
|
pos += id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 91) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (source.slice(pos, pos + it_id.length) !== it_id) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 93) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 59) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
} else if (ch2 === 79) {
|
|
if (source.slice(pos + 1, pos + 6) !== "bject") break;
|
|
pos += 6;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 46) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 100 || !source.startsWith("efineProperty", pos + 1)) break;
|
|
pos += 14;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!readExportsOrModuleDotExports(ch2)) break;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 44) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!source.startsWith(it_id, pos)) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 44) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 123) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 101 || !source.startsWith("numerable", pos + 1)) break;
|
|
pos += 10;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 58) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 116 && !source.startsWith("rue", pos + 1)) break;
|
|
pos += 4;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 44) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 103 || !source.startsWith("et", pos + 1)) break;
|
|
pos += 3;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 58) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 102) break;
|
|
if (!source.startsWith("unction", pos + 1)) break;
|
|
pos += 8;
|
|
let lastPos = pos;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 40 && (lastPos === pos || !identifier())) break;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 !== 40) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 123) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 114 || !source.startsWith("eturn", pos + 1)) break;
|
|
pos += 6;
|
|
ch2 = commentWhitespace();
|
|
if (!source.startsWith(id, pos)) break;
|
|
pos += id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 91) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!source.startsWith(it_id, pos)) break;
|
|
pos += it_id.length;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 93) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 59) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 !== 125) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 44) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 !== 125) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 59) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
} else break;
|
|
if (ch2 !== 125) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 41) break;
|
|
const starExportSpecifier = starExportMap[id];
|
|
if (starExportSpecifier) {
|
|
reexports.add(decode(starExportSpecifier));
|
|
pos = revertPos;
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
pos = revertPos;
|
|
}
|
|
function readExportsOrModuleDotExports(ch2) {
|
|
const revertPos = pos;
|
|
if (ch2 === 109 && source.startsWith("odule", pos + 1)) {
|
|
pos += 6;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 46) {
|
|
pos = revertPos;
|
|
return false;
|
|
}
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
}
|
|
if (ch2 === 101 && source.startsWith("xports", pos + 1)) {
|
|
pos += 7;
|
|
return true;
|
|
} else {
|
|
pos = revertPos;
|
|
return false;
|
|
}
|
|
}
|
|
function tryParseModuleExportsDotAssign() {
|
|
pos += 6;
|
|
const revertPos = pos - 1;
|
|
let ch2 = commentWhitespace();
|
|
if (ch2 === 46) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 101 && source.startsWith("xports", pos + 1)) {
|
|
tryParseExportsDotAssign(true);
|
|
return;
|
|
}
|
|
}
|
|
pos = revertPos;
|
|
}
|
|
function tryParseExportsDotAssign(assign) {
|
|
pos += 7;
|
|
const revertPos = pos - 1;
|
|
let ch2 = commentWhitespace();
|
|
switch (ch2) {
|
|
// exports.asdf
|
|
case 46: {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
const startPos = pos;
|
|
if (identifier()) {
|
|
const endPos = pos;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 61) {
|
|
_exports.add(decode(source.slice(startPos, endPos)));
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
// exports['asdf']
|
|
case 91: {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 39 || ch2 === 34) {
|
|
const startPos = pos;
|
|
stringLiteral(ch2);
|
|
const endPos = ++pos;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 93) break;
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 !== 61) break;
|
|
_exports.add(decode(source.slice(startPos, endPos)));
|
|
}
|
|
break;
|
|
}
|
|
// module.exports =
|
|
case 61: {
|
|
if (assign) {
|
|
if (reexports.size)
|
|
reexports = /* @__PURE__ */ new Set();
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 123) {
|
|
tryParseLiteralExports();
|
|
return;
|
|
}
|
|
if (ch2 === 114)
|
|
tryParseRequire(ExportAssign);
|
|
}
|
|
}
|
|
}
|
|
pos = revertPos;
|
|
}
|
|
function tryParseRequire(requireType) {
|
|
const revertPos = pos;
|
|
if (source.startsWith("equire", pos + 1)) {
|
|
pos += 7;
|
|
let ch2 = commentWhitespace();
|
|
if (ch2 === 40) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
const reexportStart = pos;
|
|
if (ch2 === 39 || ch2 === 34) {
|
|
stringLiteral(ch2);
|
|
const reexportEnd = ++pos;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 41) {
|
|
switch (requireType) {
|
|
case ExportAssign:
|
|
reexports.add(decode(source.slice(reexportStart, reexportEnd)));
|
|
return true;
|
|
case ExportStar:
|
|
reexports.add(decode(source.slice(reexportStart, reexportEnd)));
|
|
return true;
|
|
default:
|
|
lastStarExportSpecifier = decode(source.slice(reexportStart, reexportEnd));
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pos = revertPos;
|
|
}
|
|
return false;
|
|
}
|
|
function tryParseLiteralExports() {
|
|
const revertPos = pos - 1;
|
|
while (pos++ < end) {
|
|
let ch2 = commentWhitespace();
|
|
const startPos = pos;
|
|
if (identifier()) {
|
|
const endPos = pos;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 58) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!identifier()) {
|
|
pos = revertPos;
|
|
return;
|
|
}
|
|
ch2 = source.charCodeAt(pos);
|
|
}
|
|
_exports.add(decode(source.slice(startPos, endPos)));
|
|
} else if (ch2 === 46 && source.startsWith("..", pos + 1)) {
|
|
pos += 3;
|
|
if (source.charCodeAt(pos) === 114 && tryParseRequire(ExportAssign)) {
|
|
pos++;
|
|
} else if (!identifier()) {
|
|
pos = revertPos;
|
|
return;
|
|
}
|
|
ch2 = commentWhitespace();
|
|
} else if (ch2 === 39 || ch2 === 34) {
|
|
const startPos2 = pos;
|
|
stringLiteral(ch2);
|
|
const endPos = ++pos;
|
|
ch2 = commentWhitespace();
|
|
if (ch2 === 58) {
|
|
pos++;
|
|
ch2 = commentWhitespace();
|
|
if (!identifier()) {
|
|
pos = revertPos;
|
|
return;
|
|
}
|
|
ch2 = source.charCodeAt(pos);
|
|
_exports.add(decode(source.slice(startPos2, endPos)));
|
|
}
|
|
} else {
|
|
pos = revertPos;
|
|
return;
|
|
}
|
|
if (ch2 === 125)
|
|
return;
|
|
if (ch2 !== 44) {
|
|
pos = revertPos;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
var nonASCIIidentifierStartChars = "\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08C7\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1878\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\u9FFC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7BF\uA7C2-\uA7CA\uA7F5-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC";
|
|
var nonASCIIidentifierChars = "\u200C\u200D\xB7\u0300-\u036F\u0387\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u0669\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u06F0-\u06F9\u0711\u0730-\u074A\u07A6-\u07B0\u07C0-\u07C9\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0966-\u096F\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09E6-\u09EF\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A66-\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AE6-\u0AEF\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B55-\u0B57\u0B62\u0B63\u0B66-\u0B6F\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0BE6-\u0BEF\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0CE6-\u0CEF\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D66-\u0D6F\u0D81-\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0E50-\u0E59\u0EB1\u0EB4-\u0EBC\u0EC8-\u0ECD\u0ED0-\u0ED9\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1040-\u1049\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F-\u109D\u135D-\u135F\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u18A9\u1920-\u192B\u1930-\u193B\u1946-\u194F\u19D0-\u19DA\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AB0-\u1ABD\u1ABF\u1AC0\u1B00-\u1B04\u1B34-\u1B44\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BB0-\u1BB9\u1BE6-\u1BF3\u1C24-\u1C37\u1C40-\u1C49\u1C50-\u1C59\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u203F\u2040\u2054\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA620-\uA629\uA66F\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA82C\uA880\uA881\uA8B4-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F1\uA8FF-\uA909\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9D0-\uA9D9\uA9E5\uA9F0-\uA9F9\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA50-\uAA59\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uABF0-\uABF9\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFF10-\uFF19\uFF3F";
|
|
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
|
|
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
|
|
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;
|
|
var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 107, 20, 28, 22, 13, 52, 76, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 230, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 35, 56, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8952, 286, 50, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 2357, 44, 11, 6, 17, 0, 370, 43, 1301, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42717, 35, 4148, 12, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938];
|
|
var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 176, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 135, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 419, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239];
|
|
function isInAstralSet(code, set) {
|
|
let pos2 = 65536;
|
|
for (let i = 0; i < set.length; i += 2) {
|
|
pos2 += set[i];
|
|
if (pos2 > code) return false;
|
|
pos2 += set[i + 1];
|
|
if (pos2 >= code) return true;
|
|
}
|
|
}
|
|
function isIdentifierStart(code, astral) {
|
|
if (code < 65) return code === 36;
|
|
if (code < 91) return true;
|
|
if (code < 97) return code === 95;
|
|
if (code < 123) return true;
|
|
if (code <= 65535) return code >= 170 && nonASCIIidentifierStart.test(String.fromCharCode(code));
|
|
if (astral === false) return false;
|
|
return isInAstralSet(code, astralIdentifierStartCodes);
|
|
}
|
|
function isIdentifierChar(code, astral) {
|
|
if (code < 48) return code === 36;
|
|
if (code < 58) return true;
|
|
if (code < 65) return false;
|
|
if (code < 91) return true;
|
|
if (code < 97) return code === 95;
|
|
if (code < 123) return true;
|
|
if (code <= 65535) return code >= 170 && nonASCIIidentifier.test(String.fromCharCode(code));
|
|
if (astral === false) return false;
|
|
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
|
|
}
|
|
function identifier() {
|
|
let ch2 = source.codePointAt(pos);
|
|
if (!isIdentifierStart(ch2, true) || ch2 === "\\")
|
|
return false;
|
|
pos += codePointLen(ch2);
|
|
while (ch2 = source.codePointAt(pos)) {
|
|
if (isIdentifierChar(ch2, true)) {
|
|
pos += codePointLen(ch2);
|
|
} else if (ch2 === "\\") {
|
|
return false;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
function codePointLen(ch2) {
|
|
if (ch2 < 65536) return 1;
|
|
return 2;
|
|
}
|
|
function codePointAtLast(bPos) {
|
|
const ch2 = source.charCodeAt(bPos);
|
|
if ((ch2 & 64512) === 56320)
|
|
return ((source.charCodeAt(bPos - 1) & 1023) << 10 | ch2 & 1023) + 65536;
|
|
return ch2;
|
|
}
|
|
function esmSyntaxErr(msg) {
|
|
return Object.assign(new Error(msg), { code: "ERR_LEXER_ESM_SYNTAX" });
|
|
}
|
|
function throwIfImportStatement() {
|
|
const startPos = pos;
|
|
pos += 6;
|
|
const ch2 = commentWhitespace();
|
|
switch (ch2) {
|
|
// dynamic import
|
|
case 40:
|
|
openTokenPosStack[openTokenDepth++] = startPos;
|
|
return;
|
|
// import.meta
|
|
case 46:
|
|
throw esmSyntaxErr("Unexpected import.meta in CJS module.");
|
|
default:
|
|
if (pos === startPos + 6)
|
|
break;
|
|
case 34:
|
|
case 39:
|
|
case 123:
|
|
case 42:
|
|
if (openTokenDepth !== 0) {
|
|
pos--;
|
|
return;
|
|
}
|
|
throw esmSyntaxErr("Unexpected import statement in CJS module.");
|
|
}
|
|
}
|
|
function throwIfExportStatement() {
|
|
pos += 6;
|
|
const curPos = pos;
|
|
const ch2 = commentWhitespace();
|
|
if (pos === curPos && !isPunctuator(ch2))
|
|
return;
|
|
throw esmSyntaxErr("Unexpected export statement in CJS module.");
|
|
}
|
|
function commentWhitespace() {
|
|
let ch2;
|
|
do {
|
|
ch2 = source.charCodeAt(pos);
|
|
if (ch2 === 47) {
|
|
const next_ch = source.charCodeAt(pos + 1);
|
|
if (next_ch === 47)
|
|
lineComment();
|
|
else if (next_ch === 42)
|
|
blockComment();
|
|
else
|
|
return ch2;
|
|
} else if (!isBrOrWs(ch2)) {
|
|
return ch2;
|
|
}
|
|
} while (pos++ < end);
|
|
return ch2;
|
|
}
|
|
function templateString() {
|
|
while (pos++ < end) {
|
|
const ch2 = source.charCodeAt(pos);
|
|
if (ch2 === 36 && source.charCodeAt(pos + 1) === 123) {
|
|
pos++;
|
|
templateStack[templateStackDepth++] = templateDepth;
|
|
templateDepth = ++openTokenDepth;
|
|
return;
|
|
}
|
|
if (ch2 === 96)
|
|
return;
|
|
if (ch2 === 92)
|
|
pos++;
|
|
}
|
|
syntaxError();
|
|
}
|
|
function blockComment() {
|
|
pos++;
|
|
while (pos++ < end) {
|
|
const ch2 = source.charCodeAt(pos);
|
|
if (ch2 === 42 && source.charCodeAt(pos + 1) === 47) {
|
|
pos++;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
function lineComment() {
|
|
while (pos++ < end) {
|
|
const ch2 = source.charCodeAt(pos);
|
|
if (ch2 === 10 || ch2 === 13)
|
|
return;
|
|
}
|
|
}
|
|
function stringLiteral(quote) {
|
|
while (pos++ < end) {
|
|
let ch2 = source.charCodeAt(pos);
|
|
if (ch2 === quote)
|
|
return;
|
|
if (ch2 === 92) {
|
|
ch2 = source.charCodeAt(++pos);
|
|
if (ch2 === 13 && source.charCodeAt(pos + 1) === 10)
|
|
pos++;
|
|
} else if (isBr(ch2))
|
|
break;
|
|
}
|
|
throw new Error("Unterminated string.");
|
|
}
|
|
function regexCharacterClass() {
|
|
while (pos++ < end) {
|
|
let ch2 = source.charCodeAt(pos);
|
|
if (ch2 === 93)
|
|
return ch2;
|
|
if (ch2 === 92)
|
|
pos++;
|
|
else if (ch2 === 10 || ch2 === 13)
|
|
break;
|
|
}
|
|
throw new Error("Syntax error reading regular expression class.");
|
|
}
|
|
function regularExpression() {
|
|
while (pos++ < end) {
|
|
let ch2 = source.charCodeAt(pos);
|
|
if (ch2 === 47)
|
|
return;
|
|
if (ch2 === 91)
|
|
ch2 = regexCharacterClass();
|
|
else if (ch2 === 92)
|
|
pos++;
|
|
else if (ch2 === 10 || ch2 === 13)
|
|
break;
|
|
}
|
|
throw new Error("Syntax error reading regular expression.");
|
|
}
|
|
function isBr(c) {
|
|
return c === 13 || c === 10;
|
|
}
|
|
function isBrOrWs(c) {
|
|
return c > 8 && c < 14 || c === 32 || c === 160;
|
|
}
|
|
function isBrOrWsOrPunctuatorNotDot(c) {
|
|
return c > 8 && c < 14 || c === 32 || c === 160 || isPunctuator(c) && c !== 46;
|
|
}
|
|
function keywordStart(pos2) {
|
|
return pos2 === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos2 - 1));
|
|
}
|
|
function readPrecedingKeyword(pos2, match) {
|
|
if (pos2 < match.length - 1)
|
|
return false;
|
|
return source.startsWith(match, pos2 - match.length + 1) && (pos2 === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos2 - match.length)));
|
|
}
|
|
function readPrecedingKeyword1(pos2, ch2) {
|
|
return source.charCodeAt(pos2) === ch2 && (pos2 === 0 || isBrOrWsOrPunctuatorNotDot(source.charCodeAt(pos2 - 1)));
|
|
}
|
|
function isExpressionKeyword(pos2) {
|
|
switch (source.charCodeAt(pos2)) {
|
|
case 100:
|
|
switch (source.charCodeAt(pos2 - 1)) {
|
|
case 105:
|
|
return readPrecedingKeyword(pos2 - 2, "vo");
|
|
case 108:
|
|
return readPrecedingKeyword(pos2 - 2, "yie");
|
|
default:
|
|
return false;
|
|
}
|
|
case 101:
|
|
switch (source.charCodeAt(pos2 - 1)) {
|
|
case 115:
|
|
switch (source.charCodeAt(pos2 - 2)) {
|
|
case 108:
|
|
return readPrecedingKeyword1(
|
|
pos2 - 3,
|
|
101
|
|
/*e*/
|
|
);
|
|
case 97:
|
|
return readPrecedingKeyword1(
|
|
pos2 - 3,
|
|
99
|
|
/*c*/
|
|
);
|
|
default:
|
|
return false;
|
|
}
|
|
case 116:
|
|
return readPrecedingKeyword(pos2 - 2, "dele");
|
|
default:
|
|
return false;
|
|
}
|
|
case 102:
|
|
if (source.charCodeAt(pos2 - 1) !== 111 || source.charCodeAt(pos2 - 2) !== 101)
|
|
return false;
|
|
switch (source.charCodeAt(pos2 - 3)) {
|
|
case 99:
|
|
return readPrecedingKeyword(pos2 - 4, "instan");
|
|
case 112:
|
|
return readPrecedingKeyword(pos2 - 4, "ty");
|
|
default:
|
|
return false;
|
|
}
|
|
case 110:
|
|
return readPrecedingKeyword1(
|
|
pos2 - 1,
|
|
105
|
|
/*i*/
|
|
) || readPrecedingKeyword(pos2 - 1, "retur");
|
|
case 111:
|
|
return readPrecedingKeyword1(
|
|
pos2 - 1,
|
|
100
|
|
/*d*/
|
|
);
|
|
case 114:
|
|
return readPrecedingKeyword(pos2 - 1, "debugge");
|
|
case 116:
|
|
return readPrecedingKeyword(pos2 - 1, "awai");
|
|
case 119:
|
|
switch (source.charCodeAt(pos2 - 1)) {
|
|
case 101:
|
|
return readPrecedingKeyword1(
|
|
pos2 - 2,
|
|
110
|
|
/*n*/
|
|
);
|
|
case 111:
|
|
return readPrecedingKeyword(pos2 - 2, "thr");
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
function isParenKeyword(curPos) {
|
|
return source.charCodeAt(curPos) === 101 && source.startsWith("whil", curPos - 4) || source.charCodeAt(curPos) === 114 && source.startsWith("fo", curPos - 2) || source.charCodeAt(curPos - 1) === 105 && source.charCodeAt(curPos) === 102;
|
|
}
|
|
function isPunctuator(ch2) {
|
|
return ch2 === 33 || ch2 === 37 || ch2 === 38 || ch2 > 39 && ch2 < 48 || ch2 > 57 && ch2 < 64 || ch2 === 91 || ch2 === 93 || ch2 === 94 || ch2 > 122 && ch2 < 127;
|
|
}
|
|
function isExpressionPunctuator(ch2) {
|
|
return ch2 === 33 || ch2 === 37 || ch2 === 38 || ch2 > 39 && ch2 < 47 && ch2 !== 41 || ch2 > 57 && ch2 < 64 || ch2 === 91 || ch2 === 94 || ch2 > 122 && ch2 < 127 && ch2 !== 125;
|
|
}
|
|
function isExpressionTerminator(curPos) {
|
|
switch (source.charCodeAt(curPos)) {
|
|
case 62:
|
|
return source.charCodeAt(curPos - 1) === 61;
|
|
case 59:
|
|
case 41:
|
|
return true;
|
|
case 104:
|
|
return source.startsWith("catc", curPos - 4);
|
|
case 121:
|
|
return source.startsWith("finall", curPos - 6);
|
|
case 101:
|
|
return source.startsWith("els", curPos - 3);
|
|
}
|
|
return false;
|
|
}
|
|
var initPromise = Promise.resolve();
|
|
module.exports.init = () => initPromise;
|
|
module.exports.initSync = () => {
|
|
};
|
|
module.exports.parse = parseCJS;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/sloppy-module-parser/sloppy-require-parser.js
|
|
var require_sloppy_require_parser = __commonJS({
|
|
"../../node_modules/sloppy-module-parser/sloppy-require-parser.js"(exports, module) {
|
|
var CALL_WITH_STRING = /^\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*\)/;
|
|
var IS_EXTENSION = /^\s*\.(addon|addon\.resolve|asset|resolve)\s*\(\s*(?:('[^']+'|"[^"]+"|`[^`]+`)(?:,\s*__filename)?)?\s*\)/;
|
|
module.exports = parseCJS;
|
|
function parseCJS(src, result) {
|
|
const seenRequires = [];
|
|
const seenAddons = [];
|
|
const seenAssets = [];
|
|
let i = src.indexOf("require");
|
|
let j = i > -1 ? src.indexOf("/*") : -1;
|
|
while (i > -1) {
|
|
if (j > -1 && i > j) {
|
|
j = src.indexOf("*/", j + 2);
|
|
if (j === -1) continue;
|
|
if (i < j) i = src.indexOf("require", j + 2);
|
|
j = src.indexOf("/*", j + 2);
|
|
continue;
|
|
}
|
|
if ((newWord(src, i) || isSpread(src, i)) && !inComment(src, i)) {
|
|
const suffix = src.slice(i + 7);
|
|
const m = suffix.match(CALL_WITH_STRING);
|
|
if (m) {
|
|
const req = m[1].slice(1, -1);
|
|
if (seenRequires.indexOf(req) === -1) {
|
|
seenRequires.push(req);
|
|
result.resolutions.push({ isImport: false, position: null, input: req, output: null });
|
|
}
|
|
} else {
|
|
const m2 = suffix.match(IS_EXTENSION);
|
|
if (m2) {
|
|
const ext = m2[1];
|
|
const isAddon = ext === "addon" || ext === "addon.resolve";
|
|
const isAsset = ext === "asset";
|
|
const isResolve = ext === "resolve";
|
|
const req = m2[2] ? m2[2].slice(1, -1) : ".";
|
|
if (isAddon) {
|
|
if (seenAddons.indexOf(req) === -1) {
|
|
seenAddons.push(req);
|
|
result.addons.push({ input: req, output: null });
|
|
}
|
|
} else if (isAsset && m2[2]) {
|
|
if (seenAssets.indexOf(req) === -1) {
|
|
seenAssets.push(req);
|
|
result.assets.push({ input: req, output: null });
|
|
}
|
|
} else if (isResolve && m2[2]) {
|
|
if (seenRequires.indexOf(req) === -1) {
|
|
seenRequires.push(req);
|
|
result.resolutions.push({ isImport: false, position: null, input: req, output: null });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
i = src.indexOf("require", i + 7);
|
|
}
|
|
}
|
|
function newWord(src, i) {
|
|
const s = i > 0 ? src.slice(i - 1, i) : "";
|
|
return !/^\w|["'`._]/.test(s);
|
|
}
|
|
function isSpread(src, i) {
|
|
const s = i > 0 ? src.slice(i - 3, i) : "";
|
|
return s === "...";
|
|
}
|
|
function inComment(src, i) {
|
|
const pre = src.slice(i > 100 ? i - 100 : 0, i);
|
|
return pre.indexOf("//", Math.max(pre.lastIndexOf("\n"), 0)) > -1 && src.slice(i, i + 100).indexOf("\n") > -1;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/sloppy-module-parser/parse.js
|
|
var require_parse = __commonJS({
|
|
"../../node_modules/sloppy-module-parser/parse.js"(exports) {
|
|
var mjs = (init_lexer(), __toCommonJS(lexer_exports));
|
|
var cjs = require_lexer();
|
|
var srp = require_sloppy_require_parser();
|
|
exports.init = async function init2() {
|
|
await mjs.init;
|
|
};
|
|
exports.parse = function parse2(src, type = "module", strictMode = false) {
|
|
const result = {
|
|
type,
|
|
resolutions: [],
|
|
namedImports: [],
|
|
exports: null,
|
|
addons: [],
|
|
assets: []
|
|
};
|
|
if (type === "json") {
|
|
result.exports = [];
|
|
return result;
|
|
}
|
|
const [imp, exp] = mjsParse(src);
|
|
const esm = type === "module";
|
|
if (!esm && exp.length > 0) {
|
|
if (!strictMode) return parse2(src, "module", true);
|
|
throw new Error("Export expression not allowed in cjs");
|
|
}
|
|
for (const i of imp) {
|
|
if (i.d === -1 && !esm) {
|
|
if (!strictMode) return parse2(src, "module", true);
|
|
throw new Error("Import statement not allowed in cjs");
|
|
}
|
|
if (i.n) {
|
|
const q = i.d > -1 ? 0 : 1;
|
|
const names = [];
|
|
const isWildcard = i.d === -1 && parseNames(src.slice(i.ss + 6, i.s), names);
|
|
const resolution = {
|
|
isImport: true,
|
|
position: [i.ss, i.s - q, i.e + q],
|
|
input: i.n,
|
|
output: null
|
|
};
|
|
result.resolutions.push(resolution);
|
|
if (names.length || isWildcard) {
|
|
result.namedImports.push({
|
|
isWildcard,
|
|
isExport: src.slice(i.ss, i.ss + 6) === "export",
|
|
names,
|
|
from: resolution
|
|
});
|
|
}
|
|
} else if (i.ss !== i.s) {
|
|
result.resolutions.push({
|
|
isImport: true,
|
|
position: [i.ss, i.s - 1, -1],
|
|
input: null,
|
|
output: null
|
|
});
|
|
}
|
|
}
|
|
if (esm) {
|
|
result.exports = exp;
|
|
return result;
|
|
}
|
|
srp(src, result);
|
|
return result;
|
|
};
|
|
exports.exports = function exports2(src, type) {
|
|
if (type === "module") return mjs.parse(src)[1];
|
|
return type === "json" ? [] : cjs.parse(src).exports;
|
|
};
|
|
function mjsParse(src) {
|
|
try {
|
|
return mjs.parse(src);
|
|
} catch {
|
|
return [[], []];
|
|
}
|
|
}
|
|
function parseNames(imp, result) {
|
|
imp = imp.replace(/\/\/[^n]+/g, "").replace(/\/\*[^*]*\*\//g, "");
|
|
const bs = imp.indexOf("{");
|
|
if (bs === -1) {
|
|
return imp.indexOf("*") > -1;
|
|
}
|
|
const be = imp.indexOf("}", bs);
|
|
if (be === -1) return false;
|
|
for (const part of imp.slice(bs + 1, be).split(",")) {
|
|
const name = part.split(/\sas\s/)[0].trim();
|
|
if (!name) break;
|
|
result.push(name);
|
|
}
|
|
return imp.indexOf("*", be + 1) > -1;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dependency-stream/index.js
|
|
var require_dependency_stream = __commonJS({
|
|
"../../node_modules/dependency-stream/index.js"(exports, module) {
|
|
var parse2 = require_parse();
|
|
var b4a = require_b4a();
|
|
var resolveModule = require_bare_module_resolve();
|
|
var resolveAddon = require_bare_addon_resolve();
|
|
var FIFO = require_fast_fifo();
|
|
var runtime = require_which_runtime();
|
|
var { Readable } = require_streamx();
|
|
module.exports = class DependencyStream extends Readable {
|
|
constructor(drive, {
|
|
entrypoint = ".",
|
|
preload = true,
|
|
source = false,
|
|
strict = false,
|
|
packages = false,
|
|
builtins = [],
|
|
runtimes = ["bare", "node"],
|
|
extensions = [".js", ".cjs", ".json", ".mjs"],
|
|
host = runtime.platform + "-" + runtime.arch,
|
|
conditions = runtimes
|
|
} = {}) {
|
|
super({ highWaterMark: 64 * 1024, byteLength: objectByteLength });
|
|
this.drive = drive;
|
|
this.entrypoint = entrypoint;
|
|
this.preload = preload;
|
|
this.source = source;
|
|
this.modules = /* @__PURE__ */ new Map();
|
|
this.strict = strict;
|
|
this.builtins = Array.isArray(builtins) ? new Set(builtins) : builtins;
|
|
this.packages = packages;
|
|
this.extensions = extensions;
|
|
this.host = host;
|
|
this._importConditions = ["module", "import", ...conditions];
|
|
this._requireConditions = ["require", ...conditions];
|
|
this._addonConditions = ["addon", ...conditions];
|
|
this._pending = /* @__PURE__ */ new Map();
|
|
this._packages = /* @__PURE__ */ new Map();
|
|
this._queue = new FIFO();
|
|
}
|
|
async _open(cb) {
|
|
try {
|
|
const entrypoint = /^[./]/.test(this.entrypoint) ? this.entrypoint : "./" + this.entrypoint;
|
|
const entry = entrypoint[0] === "/" && entrypoint !== "/" ? await this.drive.entry(entrypoint) : null;
|
|
await parse2.init();
|
|
const pkg = await this._readPackageCached("/package.json");
|
|
const imp = entry && entry.value && entry.value.metadata && entry.value.metadata.imports;
|
|
const key = await this._resolveModule(entrypoint, "/", !!pkg && pkg.type === "module", imp);
|
|
this._queue.push(key);
|
|
} catch (err) {
|
|
return cb(err);
|
|
}
|
|
cb(null);
|
|
}
|
|
_readPackageCached(key) {
|
|
let p = this._packages.get(key);
|
|
if (p) return p;
|
|
p = this._readPackage(key);
|
|
this._packages.set(key, p);
|
|
return p;
|
|
}
|
|
async _readPackage(key) {
|
|
const buf = await this.drive.get(key);
|
|
if (!buf) return null;
|
|
try {
|
|
return JSON.parse(b4a.toString(buf));
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
async _resolvePackage(key, resolutions) {
|
|
if (resolutions && resolutions["#package"]) {
|
|
const k = resolutions["#package"];
|
|
const pkg = await this._readPackageCached(k);
|
|
if (pkg) return { key: k, package: pkg };
|
|
}
|
|
const basedir = key.slice(0, key.lastIndexOf("/") + 1);
|
|
for (const url of resolveModule.lookupPackageScope(toFileURL(basedir))) {
|
|
const k = fromFileURL(url);
|
|
const pkg = await this._readPackageCached(k);
|
|
if (!pkg) continue;
|
|
return { key: k, package: pkg };
|
|
}
|
|
return null;
|
|
}
|
|
async _resolveAddon(id, basedir, imports) {
|
|
const conditions = this._addonConditions;
|
|
const readPackage = (packageURL) => this._readPackageCached(fromFileURL(packageURL));
|
|
const parentURL = toFileURL(basedir);
|
|
const resolutions = imports ? { [parentURL]: imports } : null;
|
|
for await (const addonURL of resolveAddon(
|
|
id,
|
|
parentURL,
|
|
{ host: this.host, extensions: [".node", ".bare"], conditions, resolutions },
|
|
readPackage
|
|
)) {
|
|
const key = fromFileURL(addonURL);
|
|
if (await this.drive.entry(key)) return key;
|
|
}
|
|
const err = new Error(`Cannot find addon '${id}'`);
|
|
err.code = "ADDON_NOT_FOUND";
|
|
throw err;
|
|
}
|
|
async _resolveModule(id, basedir, isImport, imports) {
|
|
const conditions = isImport ? this._importConditions : this._requireConditions;
|
|
const readPackage = (packageURL) => this._readPackageCached(fromFileURL(packageURL));
|
|
const parentURL = toFileURL(basedir);
|
|
const resolutions = imports ? { [parentURL]: imports } : null;
|
|
for await (const moduleURL of resolveModule(
|
|
id,
|
|
parentURL,
|
|
{ extensions: this.extensions, conditions, resolutions },
|
|
readPackage
|
|
)) {
|
|
const key = fromFileURL(moduleURL);
|
|
if (await this.drive.entry(key)) return key;
|
|
}
|
|
const err = new Error(`Cannot find module '${id}'`);
|
|
err.code = "MODULE_NOT_FOUND";
|
|
throw err;
|
|
}
|
|
async _read(cb) {
|
|
try {
|
|
while (this._queue.length > 0) {
|
|
const key = this._queue.shift();
|
|
if (this.modules.has(key)) continue;
|
|
const data = await this._addOnce(key);
|
|
this.modules.set(key, data);
|
|
this._pending.delete(key);
|
|
if (this.push(data) === false) break;
|
|
}
|
|
} catch (err) {
|
|
return cb(err);
|
|
}
|
|
if (this._queue.length === 0) {
|
|
this.push(null);
|
|
return cb(null);
|
|
}
|
|
cb(null);
|
|
}
|
|
async _addOnce(key) {
|
|
if (this._pending.has(key)) return this._pending.get(key);
|
|
const p = this._add(key);
|
|
this._pending.set(key, p);
|
|
await p;
|
|
return p;
|
|
}
|
|
async _add(key) {
|
|
const entry = await this.drive.entry(key);
|
|
if (entry === null) throw new Error("Key not found: " + key);
|
|
const data = await this.drive.get(entry);
|
|
const source = b4a.toString(data);
|
|
const type = key.endsWith(".json") ? "json" : key.endsWith(".mjs") ? "module" : "script";
|
|
const deps = parse2.parse(source, type, type !== "script");
|
|
const resolutions = entry.value && entry.value.metadata && entry.value.metadata.imports;
|
|
const result = {
|
|
key,
|
|
source: this.source ? source : null,
|
|
type: deps.type,
|
|
resolutions: deps.resolutions,
|
|
namedImports: deps.namedImports,
|
|
exports: deps.exports,
|
|
addons: deps.addons,
|
|
assets: deps.assets
|
|
};
|
|
if (this.packages && type !== "json") {
|
|
const p2 = await this._resolvePackage(key, resolutions);
|
|
if (p2) {
|
|
result.resolutions.push(
|
|
{
|
|
isImport: deps.type === "module",
|
|
position: null,
|
|
input: "bare:package",
|
|
output: p2.key
|
|
},
|
|
{
|
|
isImport: deps.type === "module",
|
|
position: null,
|
|
input: "#package",
|
|
output: p2.key
|
|
}
|
|
);
|
|
}
|
|
}
|
|
const basedir = key.slice(0, key.lastIndexOf("/") + 1);
|
|
const all = [];
|
|
if (deps.importsAttributes) {
|
|
for (const attrInput of deps.importsAttributes) {
|
|
const attrOutput = await this._resolveModule(attrInput, basedir, true, resolutions);
|
|
const data2 = await this.drive.get(attrOutput);
|
|
if (data2 === null) throw new Error("Key not found: " + key);
|
|
const source2 = b4a.toString(data2);
|
|
let imports = {};
|
|
try {
|
|
const obj = JSON.parse(source2);
|
|
if (obj === null || typeof obj !== "object" || Array.isArray(obj)) {
|
|
throw new Error(`Invalid import attribute json file: ${key}`);
|
|
}
|
|
if ("imports" in obj) imports = obj.imports;
|
|
else imports = obj;
|
|
} catch (err) {
|
|
const jsonErr = new Error(`Invalid import attribute json file: ${key}`);
|
|
jsonErr.code = "INVALID_JSON";
|
|
throw jsonErr;
|
|
}
|
|
const modules = Object.values(imports);
|
|
const resolvedModules = [];
|
|
for (const item of modules) {
|
|
try {
|
|
const res = await this._resolveModule(item, basedir);
|
|
resolvedModules.push(res);
|
|
} catch (err) {
|
|
const resolveErr = new Error(`Failed to resolve module ${item}`);
|
|
resolveErr.code = "MODULE_NOT_FOUND";
|
|
throw resolveErr;
|
|
}
|
|
}
|
|
for (const resolvedModule of resolvedModules) {
|
|
if (!result.resolutions.some((item) => item.input === resolvedModule)) {
|
|
result.resolutions.push({
|
|
isImport: false,
|
|
position: null,
|
|
input: resolvedModule,
|
|
output: null
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (const res of result.resolutions) {
|
|
if (isAddonPolyfill(res.input)) {
|
|
result.addons.push({
|
|
input: ".",
|
|
output: null,
|
|
referrer: res.input
|
|
});
|
|
}
|
|
}
|
|
for (const dep of result.addons) {
|
|
if (dep.referrer === "node-gyp-build") {
|
|
dep.input = fromFileURL(toFileURL(basedir + dep.input));
|
|
if (dep.input.endsWith("/")) dep.input = dep.input.slice(0, -1);
|
|
} else if (dep.input === null) {
|
|
continue;
|
|
}
|
|
all.push(this._resolveAddon(dep.input, basedir, resolutions));
|
|
}
|
|
for (const res of result.resolutions) {
|
|
if (res.input === null) continue;
|
|
all.push(res.output || this._resolveModule(res.input, basedir, res.isImport, resolutions));
|
|
}
|
|
const outputs = await Promise.allSettled(all);
|
|
let p = 0;
|
|
for (const dep of result.addons) {
|
|
const { value, reason } = outputs[p++];
|
|
if (reason) {
|
|
if (!this.strict) continue;
|
|
throw reason;
|
|
}
|
|
dep.output = value;
|
|
}
|
|
for (const res of result.resolutions) {
|
|
if (res.input === null) continue;
|
|
const { value, reason } = outputs[p++];
|
|
if (reason) {
|
|
if (!this.strict) continue;
|
|
throw reason;
|
|
}
|
|
res.output = value;
|
|
if (!this.modules.has(res.output)) {
|
|
if (this.preload) this._addOnce(res.output).catch(noop);
|
|
this._queue.push(res.output);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
function objectByteLength() {
|
|
return 1024;
|
|
}
|
|
function toFileURL(path) {
|
|
return new URL("file://" + encodeURI(path));
|
|
}
|
|
function fromFileURL(url) {
|
|
return decodeURI(url.pathname);
|
|
}
|
|
function isAddonPolyfill(name) {
|
|
return name === "node-gyp-build" || name === "require-addon";
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/sodium-native/binding.js
|
|
var require_binding2 = __commonJS({
|
|
"../../node_modules/sodium-native/binding.js"(exports, module) {
|
|
__require.addon = require_node2();
|
|
module.exports = __require.addon(".", __filename);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/sodium-native/index.js
|
|
var require_sodium_native = __commonJS({
|
|
"../../node_modules/sodium-native/index.js"(exports, module) {
|
|
var assert = __require("assert");
|
|
var binding = require_binding2();
|
|
var { isNode } = require_which_runtime();
|
|
var OPTIONAL = Buffer.from(new ArrayBuffer(0));
|
|
module.exports = exports = { ...binding };
|
|
exports.sodium_memzero = function(buf) {
|
|
assert(ArrayBuffer.isView(buf), "buf must be a typed array");
|
|
binding.sodium_memzero(buf);
|
|
};
|
|
exports.sodium_mlock = function(buf) {
|
|
assert(ArrayBuffer.isView(buf), "buf must be a typed array");
|
|
const res = binding.sodium_mlock(buf);
|
|
if (res !== 0) throw new Error("memory lock failed");
|
|
};
|
|
exports.sodium_munlock = function(buf) {
|
|
assert(ArrayBuffer.isView(buf), "buf must be a typed array");
|
|
const res = binding.sodium_munlock(buf);
|
|
if (res !== 0) throw new Error("memory unlock failed");
|
|
};
|
|
exports.sodium_malloc = function(size) {
|
|
assert(size >= 0, "invalid size");
|
|
const buf = Buffer.from(binding.sodium_malloc(size));
|
|
buf.secure = true;
|
|
return buf;
|
|
};
|
|
exports.sodium_free = function(buf) {
|
|
if (!buf || !buf.secure) return;
|
|
binding.sodium_free(buf.buffer);
|
|
};
|
|
exports.sodium_mprotect_noaccess = function(buf) {
|
|
const res = binding.sodium_mprotect_noaccess(buf.buffer);
|
|
if (res !== 0) throw new Error("failed to lock buffer");
|
|
};
|
|
exports.sodium_mprotect_readonly = function(buf) {
|
|
const res = binding.sodium_mprotect_readonly(buf.buffer);
|
|
if (res !== 0) throw new Error("failed to unlock buffer");
|
|
};
|
|
exports.sodium_mprotect_readwrite = function(buf) {
|
|
const res = binding.sodium_mprotect_readwrite(buf.buffer);
|
|
if (res !== 0) throw new Error("failed to unlock buffer");
|
|
};
|
|
exports.randombytes_buf = function(buffer) {
|
|
assert(ArrayBuffer.isView(buffer), "buffer must be a typed array");
|
|
binding.randombytes_buf(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
};
|
|
exports.randombytes_buf_deterministic = function(buffer, seed) {
|
|
assert(ArrayBuffer.isView(buffer), "buffer must be a typed array");
|
|
assert(ArrayBuffer.isView(seed), "seed must be a typed array");
|
|
assert(
|
|
seed.byteLength === binding.randombytes_SEEDBYTES,
|
|
"seed must be 'randombytes_SEEDBYTES' bytes"
|
|
);
|
|
binding.randombytes_buf_deterministic(
|
|
buffer.buffer,
|
|
buffer.byteOffset,
|
|
buffer.byteLength,
|
|
seed.buffer,
|
|
seed.byteOffset,
|
|
seed.byteLength
|
|
);
|
|
};
|
|
exports.sodium_memcmp = function(a, b) {
|
|
assert(ArrayBuffer.isView(a), "a must be a typed array");
|
|
assert(ArrayBuffer.isView(b), "b must be a typed array");
|
|
assert(a.byteLength === b.byteLength, "buffers must be of same length");
|
|
return binding.sodium_memcmp(a, b);
|
|
};
|
|
exports.sodium_add = function(a, b) {
|
|
assert(ArrayBuffer.isView(a), "a must be a typed array");
|
|
assert(ArrayBuffer.isView(b), "b must be a typed array");
|
|
assert(a.byteLength === b.byteLength, "buffers must be of same length");
|
|
binding.sodium_add(a, b);
|
|
};
|
|
exports.sodium_sub = function(a, b) {
|
|
assert(ArrayBuffer.isView(a), "a must be a typed array");
|
|
assert(ArrayBuffer.isView(b), "b must be a typed array");
|
|
assert(a.byteLength === b.byteLength, "buffers must be of same length");
|
|
binding.sodium_sub(a, b);
|
|
};
|
|
exports.sodium_compare = function(a, b) {
|
|
assert(ArrayBuffer.isView(a), "a must be a typed array");
|
|
assert(ArrayBuffer.isView(b), "b must be a typed array");
|
|
assert(a.byteLength === b.byteLength, "buffers must be of same length");
|
|
return binding.sodium_compare(a, b);
|
|
};
|
|
exports.sodium_is_zero = function(buffer, length) {
|
|
if (length === void 0) length = buffer.byteLength;
|
|
assert(ArrayBuffer.isView(buffer), "buffer must be a typed array");
|
|
assert(length >= 0 && length <= buffer.byteLength, "invalid length");
|
|
return binding.sodium_is_zero(buffer, length);
|
|
};
|
|
exports.sodium_pad = function(buffer, unpaddedBuflen, blockSize) {
|
|
assert(ArrayBuffer.isView(buffer), "buffer must be a typed array");
|
|
assert(unpaddedBuflen <= buffer.byteLength, "unpadded length cannot exceed buffer length");
|
|
assert(blockSize <= buffer.byteLength, "block size cannot exceed buffer length");
|
|
assert(blockSize >= 1, "block size must be at least 1 byte");
|
|
assert(
|
|
buffer.byteLength >= unpaddedBuflen + (blockSize - unpaddedBuflen % blockSize),
|
|
"buf not long enough"
|
|
);
|
|
return binding.sodium_pad(buffer, unpaddedBuflen, blockSize);
|
|
};
|
|
exports.sodium_unpad = function(buffer, paddedBuflen, blockSize) {
|
|
assert(ArrayBuffer.isView(buffer), "buffer must be a typed array");
|
|
assert(paddedBuflen <= buffer.byteLength, "unpadded length cannot exceed buffer length");
|
|
assert(blockSize <= buffer.byteLength, "block size cannot exceed buffer length");
|
|
assert(blockSize >= 1, "block size must be at least 1 byte");
|
|
return binding.sodium_unpad(buffer, paddedBuflen, blockSize);
|
|
};
|
|
exports.crypto_sign_keypair = function(pk, sk) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
|
|
"sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_sign_keypair(pk, sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_sign_seed_keypair = function(pk, sk, seed) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(ArrayBuffer.isView(seed), "seed must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
|
|
"sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
seed.byteLength === binding.crypto_sign_SEEDBYTES,
|
|
"seed must be 'crypto_sign_SEEDBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_sign_seed_keypair(pk, sk, seed);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_sign = function(sm, m, sk) {
|
|
assert(ArrayBuffer.isView(sm), "sm must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
sm.byteLength === binding.crypto_sign_BYTES + m.byteLength,
|
|
"sm must be 'm.byteLength + crypto_sign_BYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
|
|
"sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_sign(sm, m, sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_sign_open = function(m, sm, pk) {
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(sm), "sm must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
sm.byteLength >= binding.crypto_sign_BYTES,
|
|
"sm must be at least 'crypto_sign_BYTES' bytes"
|
|
);
|
|
assert(
|
|
m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
|
|
"m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
|
|
);
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_sign_open(m, sm, pk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_sign_open = function(m, sm, pk) {
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(sm), "sm must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
sm.byteLength >= binding.crypto_sign_BYTES,
|
|
"sm must be at least 'crypto_sign_BYTES' bytes"
|
|
);
|
|
assert(
|
|
m.byteLength === sm.byteLength - binding.crypto_sign_BYTES,
|
|
"m must be 'sm.byteLength - crypto_sign_BYTES' bytes"
|
|
);
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
return binding.crypto_sign_open(m, sm, pk);
|
|
};
|
|
exports.crypto_sign_detached = function(sig, m, sk) {
|
|
assert(ArrayBuffer.isView(sig), "sig must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes");
|
|
assert(
|
|
sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
|
|
"sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_sign_detached(sig, m, sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_sign_verify_detached = function(sig, m, pk) {
|
|
assert(ArrayBuffer.isView(sig), "sig must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
sig.byteLength >= binding.crypto_sign_BYTES,
|
|
"sig must be at least 'crypto_sign_BYTES' bytes"
|
|
);
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
return binding.crypto_sign_verify_detached(
|
|
sig.buffer,
|
|
sig.byteOffset,
|
|
sig.byteLength,
|
|
m.buffer,
|
|
m.byteOffset,
|
|
m.byteLength,
|
|
pk.buffer,
|
|
pk.byteOffset,
|
|
pk.byteLength
|
|
);
|
|
};
|
|
exports.crypto_sign_ed25519_sk_to_pk = function(pk, sk) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
|
|
"sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_sign_ed25519_sk_to_pk(pk, sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_sign_ed25519_pk_to_curve25519 = function(x25519pk, ed25519pk) {
|
|
assert(ArrayBuffer.isView(x25519pk), "x25519pk must be a typed array");
|
|
assert(ArrayBuffer.isView(ed25519pk), "ed25519pk must be a typed array");
|
|
assert(
|
|
x25519pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
|
|
"x25519pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
ed25519pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"ed25519pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_sign_ed25519_pk_to_curve25519(x25519pk, ed25519pk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_sign_ed25519_sk_to_curve25519 = function(x25519sk, ed25519sk) {
|
|
assert(ArrayBuffer.isView(x25519sk), "x25519sk must be a typed array");
|
|
assert(ArrayBuffer.isView(ed25519sk), "ed25519sk must be a typed array");
|
|
assert(
|
|
x25519sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
|
|
"x25519sk must be 'crypto_box_SECRETKEYBYTES' bytes"
|
|
);
|
|
const edLen = ed25519sk.byteLength;
|
|
assert(
|
|
edLen === binding.crypto_sign_SECRETKEYBYTES || edLen === binding.crypto_box_SECRETKEYBYTES,
|
|
"ed25519sk must be 'crypto_sign_SECRETKEYBYTES' or 'crypto_sign_SECRETKEYBYTES - crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_sign_ed25519_sk_to_curve25519(x25519sk, ed25519sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_box_keypair = function(pk, sk) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
|
|
"sk must be 'crypto_box_SECRETKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_box_keypair(pk, sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_box_seed_keypair = function(pk, sk, seed) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_box_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
sk.byteLength === binding.crypto_box_SECRETKEYBYTES,
|
|
"sk must be 'crypto_box_SECRETKEYBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(seed), "seed must be a typed array");
|
|
assert(
|
|
seed.byteLength === binding.crypto_box_SEEDBYTES,
|
|
"seed must be 'crypto_box_SEEDBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_box_seed_keypair(pk, sk, seed);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_box_easy = function(c, m, n, pk, sk) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
c.byteLength === m.byteLength + exports.crypto_box_MACBYTES,
|
|
"c must be 'm.byteLength + crypto_box_MACBYTES' bytes"
|
|
);
|
|
assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes");
|
|
assert(
|
|
pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
|
|
"sk must be 'crypto_box_SECRETKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_box_easy(c, m, n, pk, sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_box_detached = function(c, mac, m, n, pk, sk) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(mac), "mac must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes");
|
|
assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes");
|
|
assert(
|
|
pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
|
|
"sk must be 'crypto_box_SECRETKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_box_detached(c, mac, m, n, pk, sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_box_open_easy = function(m, c, n, pk, sk) {
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
c.byteLength >= exports.crypto_box_MACBYTES,
|
|
"c must be at least 'crypto_box_MACBYTES' bytes"
|
|
);
|
|
assert(
|
|
m.byteLength === c.byteLength - exports.crypto_box_MACBYTES,
|
|
"m must be 'c.byteLength - crypto_box_MACBYTES' bytes"
|
|
);
|
|
assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes");
|
|
assert(
|
|
pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
|
|
"sk must be 'crypto_box_SECRETKEYBYTES' bytes"
|
|
);
|
|
return binding.crypto_box_open_easy(m, c, n, pk, sk);
|
|
};
|
|
exports.crypto_box_open_detached = function(m, c, mac, n, pk, sk) {
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(mac), "mac must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes");
|
|
assert(mac.byteLength === exports.crypto_box_MACBYTES, "mac must be 'crypto_box_MACBYTES' bytes");
|
|
assert(n.byteLength === exports.crypto_box_NONCEBYTES, "n must be 'crypto_box_NONCEBYTES' bytes");
|
|
assert(
|
|
pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
|
|
"sk must be 'crypto_box_SECRETKEYBYTES' bytes"
|
|
);
|
|
return binding.crypto_box_open_detached(m, c, mac, n, pk, sk);
|
|
};
|
|
exports.crypto_box_seal = function(c, m, pk) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
c.byteLength === m.byteLength + exports.crypto_box_SEALBYTES,
|
|
"c must be 'm.byteLength + crypto_box_SEALBYTES' bytes"
|
|
);
|
|
assert(
|
|
pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_box_seal(c, m, pk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_box_seal_open = function(m, c, pk, sk) {
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
c.byteLength >= exports.crypto_box_SEALBYTES,
|
|
"c must be at least 'crypto_box_SEALBYTES' bytes"
|
|
);
|
|
assert(
|
|
m.byteLength === c.byteLength - exports.crypto_box_SEALBYTES,
|
|
"m must be 'c.byteLength - crypto_box_SEALBYTES' bytes"
|
|
);
|
|
assert(
|
|
pk.byteLength === exports.crypto_box_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_box_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === exports.crypto_box_SECRETKEYBYTES,
|
|
"sk must be 'crypto_box_SECRETKEYBYTES' bytes"
|
|
);
|
|
return binding.crypto_box_seal_open(
|
|
m.buffer,
|
|
m.byteOffset,
|
|
m.byteLength,
|
|
c.buffer,
|
|
c.byteOffset,
|
|
c.byteLength,
|
|
pk.buffer,
|
|
pk.byteOffset,
|
|
pk.byteLength,
|
|
sk.buffer,
|
|
sk.byteOffset,
|
|
sk.byteLength
|
|
);
|
|
};
|
|
exports.crypto_secretbox_easy = function(c, m, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
c.byteLength === m.byteLength + binding.crypto_secretbox_MACBYTES,
|
|
"c must be 'm.byteLength + crypto_secretbox_MACBYTES' bytes"
|
|
);
|
|
assert(
|
|
n.byteLength === binding.crypto_secretbox_NONCEBYTES,
|
|
"n must be 'crypto_secretbox_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_secretbox_KEYBYTES,
|
|
"k must be 'crypto_secretbox_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_secretbox_easy(c, m, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_secretbox_open_easy = function(m, c, n, k) {
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
c.byteLength >= binding.crypto_secretbox_MACBYTES,
|
|
"c must be at least 'crypto_secretbox_MACBYTES' bytes"
|
|
);
|
|
assert(
|
|
m.byteLength === c.byteLength - binding.crypto_secretbox_MACBYTES,
|
|
"m must be 'c.byteLength - crypto_secretbox_MACBYTES' bytes"
|
|
);
|
|
assert(
|
|
n.byteLength === binding.crypto_secretbox_NONCEBYTES,
|
|
"n must be 'crypto_secretbox_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_secretbox_KEYBYTES,
|
|
"k must be 'crypto_secretbox_KEYBYTES' bytes"
|
|
);
|
|
return binding.crypto_secretbox_open_easy(m, c, n, k);
|
|
};
|
|
exports.crypto_secretbox_detached = function(c, mac, m, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(mac), "mac must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
mac.byteLength === binding.crypto_secretbox_MACBYTES,
|
|
"mac must be 'crypto_secretbox_MACBYTES' bytes"
|
|
);
|
|
assert(
|
|
n.byteLength === binding.crypto_secretbox_NONCEBYTES,
|
|
"n must be 'crypto_secretbox_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_secretbox_KEYBYTES,
|
|
"k must be 'crypto_secretbox_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_secretbox_detached(c, mac, m, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_secretbox_open_detached = function(m, c, mac, n, k) {
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(mac), "mac must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes");
|
|
assert(
|
|
mac.byteLength === binding.crypto_secretbox_MACBYTES,
|
|
"mac must be 'crypto_secretbox_MACBYTES' bytes"
|
|
);
|
|
assert(
|
|
n.byteLength === binding.crypto_secretbox_NONCEBYTES,
|
|
"n must be 'crypto_secretbox_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_secretbox_KEYBYTES,
|
|
"k must be 'crypto_secretbox_KEYBYTES' bytes"
|
|
);
|
|
return binding.crypto_secretbox_open_detached(m, c, mac, n, k);
|
|
};
|
|
exports.crypto_generichash = function(output, input, key) {
|
|
if (!key) key = OPTIONAL;
|
|
assert(ArrayBuffer.isView(output), "output must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(
|
|
output.byteLength >= binding.crypto_generichash_BYTES_MIN && output.byteLength <= binding.crypto_generichash_BYTES_MAX,
|
|
"output must be between crypto_generichash_BYTES_MIN and crypto_generichash_BYTES_MAX bytes"
|
|
);
|
|
if (key !== OPTIONAL) {
|
|
assert(ArrayBuffer.isView(key), "key must be a typed array");
|
|
assert(
|
|
key.byteLength >= binding.crypto_generichash_KEYBYTES_MIN && key.byteLength <= binding.crypto_generichash_KEYBYTES_MAX,
|
|
"key must be between crypto_generichash_KEYBYTES_MIN and crypto_generichash_KEYBYTES_MAX bytes"
|
|
);
|
|
}
|
|
const res = binding.crypto_generichash(
|
|
output.buffer,
|
|
output.byteOffset,
|
|
output.byteLength,
|
|
input.buffer,
|
|
input.byteOffset,
|
|
input.byteLength,
|
|
key.buffer,
|
|
key.byteOffset,
|
|
key.byteLength
|
|
);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_generichash_batch = function(output, batch, key) {
|
|
assert(ArrayBuffer.isView(output), "output must be a typed array");
|
|
if (isNode || batch.length < 4) {
|
|
const res = binding.crypto_generichash_batch(output, batch, !!key, key || OPTIONAL);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
} else {
|
|
const state = Buffer.alloc(binding.crypto_generichash_STATEBYTES);
|
|
exports.crypto_generichash_init(state, key, output.byteLength);
|
|
for (const buf of batch) {
|
|
exports.crypto_generichash_update(state, buf);
|
|
}
|
|
exports.crypto_generichash_final(state, output);
|
|
}
|
|
};
|
|
exports.crypto_generichash_keygen = function(key) {
|
|
assert(ArrayBuffer.isView(key), "key must be a typed array");
|
|
assert(
|
|
key.byteLength === binding.crypto_generichash_KEYBYTES,
|
|
"key must be 'crypto_generichash_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_generichash_keygen(key.buffer, key.byteOffset, key.byteLength);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_generichash_init = function(state, key, outputLength) {
|
|
if (!key) key = OPTIONAL;
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_generichash_STATEBYTES,
|
|
"state must be 'crypto_generichash_STATEBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_generichash_init(
|
|
state.buffer,
|
|
state.byteOffset,
|
|
state.byteLength,
|
|
key.buffer,
|
|
key.byteOffset,
|
|
key.byteLength,
|
|
outputLength
|
|
);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_generichash_update = function(state, input) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_generichash_STATEBYTES,
|
|
"state must be 'crypto_generichash_STATEBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_generichash_update(
|
|
state.buffer,
|
|
state.byteOffset,
|
|
state.byteLength,
|
|
input.buffer,
|
|
input.byteOffset,
|
|
input.byteLength
|
|
);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_generichash_final = function(state, output) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(output), "output must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_generichash_STATEBYTES,
|
|
"state must be 'crypto_generichash_STATEBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_generichash_final(
|
|
state.buffer,
|
|
state.byteOffset,
|
|
state.byteLength,
|
|
output.buffer,
|
|
output.byteOffset,
|
|
output.byteLength
|
|
);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_secretstream_xchacha20poly1305_keygen = function(k) {
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
|
|
"k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
|
|
);
|
|
binding.crypto_secretstream_xchacha20poly1305_keygen(k.buffer, k.byteOffset, k.byteLength);
|
|
};
|
|
exports.crypto_secretstream_xchacha20poly1305_init_push = function(state, header, k) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(header), "header must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
|
"state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
|
|
);
|
|
assert(
|
|
header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
|
|
"header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
|
|
"k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_secretstream_xchacha20poly1305_init_push(
|
|
state.buffer,
|
|
state.byteOffset,
|
|
state.byteLength,
|
|
header.buffer,
|
|
header.byteOffset,
|
|
header.byteLength,
|
|
k.buffer,
|
|
k.byteOffset,
|
|
k.byteLength
|
|
);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_secretstream_xchacha20poly1305_init_pull = function(state, header, k) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(header), "header must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
|
"state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
|
|
);
|
|
assert(
|
|
header.byteLength === binding.crypto_secretstream_xchacha20poly1305_HEADERBYTES,
|
|
"header must be 'crypto_secretstream_xchacha20poly1305_HEADERBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_secretstream_xchacha20poly1305_KEYBYTES,
|
|
"k must be 'crypto_secretstream_xchacha20poly1305_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_secretstream_xchacha20poly1305_init_pull(
|
|
state.buffer,
|
|
state.byteOffset,
|
|
state.byteLength,
|
|
header.buffer,
|
|
header.byteOffset,
|
|
header.byteLength,
|
|
k.buffer,
|
|
k.byteOffset,
|
|
k.byteLength
|
|
);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_secretstream_xchacha20poly1305_push = function(state, c, m, ad, tag) {
|
|
if (!ad) ad = OPTIONAL;
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
|
"state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
|
|
);
|
|
assert(
|
|
c.byteLength === m.byteLength + binding.crypto_secretstream_xchacha20poly1305_ABYTES,
|
|
"c must be 'm.byteLength + crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
|
|
);
|
|
const res = binding.crypto_secretstream_xchacha20poly1305_push(
|
|
state.buffer,
|
|
state.byteOffset,
|
|
state.byteLength,
|
|
c.buffer,
|
|
c.byteOffset,
|
|
c.byteLength,
|
|
m.buffer,
|
|
m.byteOffset,
|
|
m.byteLength,
|
|
ad.buffer,
|
|
ad.byteOffset,
|
|
ad.byteLength,
|
|
tag
|
|
);
|
|
if (res < 0) throw new Error("push failed");
|
|
return res;
|
|
};
|
|
exports.crypto_secretstream_xchacha20poly1305_pull = function(state, m, tag, c, ad) {
|
|
if (!ad) ad = OPTIONAL;
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
|
"state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(tag), "tag must be a typed array");
|
|
assert(tag.byteLength === 1, "tag must be 1 byte");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(
|
|
c.byteLength >= binding.crypto_secretstream_xchacha20poly1305_ABYTES,
|
|
"c must be at least 'crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(
|
|
m.byteLength === c.byteLength - binding.crypto_secretstream_xchacha20poly1305_ABYTES,
|
|
"m must be 'c.byteLength - crypto_secretstream_xchacha20poly1305_ABYTES' bytes"
|
|
);
|
|
const res = binding.crypto_secretstream_xchacha20poly1305_pull(
|
|
state.buffer,
|
|
state.byteOffset,
|
|
state.byteLength,
|
|
m.buffer,
|
|
m.byteOffset,
|
|
m.byteLength,
|
|
tag.buffer,
|
|
tag.byteOffset,
|
|
tag.byteLength,
|
|
c.buffer,
|
|
c.byteOffset,
|
|
c.byteLength,
|
|
ad.buffer,
|
|
ad.byteOffset,
|
|
ad.byteLength
|
|
);
|
|
if (res < 0) throw new Error("pull failed");
|
|
return res;
|
|
};
|
|
exports.crypto_secretstream_xchacha20poly1305_rekey = function(state) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_secretstream_xchacha20poly1305_STATEBYTES,
|
|
"state must be 'crypto_secretstream_xchacha20poly1305_STATEBYTES' bytes"
|
|
);
|
|
binding.crypto_secretstream_xchacha20poly1305_rekey(
|
|
state.buffer,
|
|
state.byteOffset,
|
|
state.byteLength
|
|
);
|
|
};
|
|
exports.crypto_stream = function(c, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_NONCEBYTES,
|
|
"n must be 'crypto_stream_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_KEYBYTES,
|
|
"k must be 'crypto_stream_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream(c, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_xor = function(c, m, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_NONCEBYTES,
|
|
"n must be 'crypto_stream_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_KEYBYTES,
|
|
"k must be 'crypto_stream_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_xor(
|
|
c.buffer,
|
|
c.byteOffset,
|
|
c.byteLength,
|
|
m.buffer,
|
|
m.byteOffset,
|
|
m.byteLength,
|
|
n.buffer,
|
|
n.byteOffset,
|
|
n.byteLength,
|
|
k.buffer,
|
|
k.byteOffset,
|
|
k.byteLength
|
|
);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_chacha20 = function(c, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
|
|
"n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
|
|
"k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_chacha20(c, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_chacha20_xor = function(c, m, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
|
|
"n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
|
|
"k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_chacha20_xor(c, m, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_chacha20_xor_ic = function(c, m, n, ic, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
|
|
"n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
|
|
"k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_chacha20_xor_ic(c, m, n, ic, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_chacha20_ietf = function(c, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
|
|
"n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
|
|
"k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_chacha20_ietf(c, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_chacha20_ietf_xor = function(c, m, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
|
|
"n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
|
|
"k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_chacha20_ietf_xor(c, m, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_chacha20_ietf_xor_ic = function(c, m, n, ic, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
|
|
"n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
|
|
"k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_chacha20_ietf_xor_ic(c, m, n, ic, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_xchacha20 = function(c, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
|
|
"n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
|
|
"k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_xchacha20(c, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_xchacha20_xor = function(c, m, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
|
|
"n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
|
|
"k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_xchacha20_xor(c, m, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_xchacha20_xor_ic = function(c, m, n, ic, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
|
|
"n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
|
|
"k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_xchacha20_xor_ic(c, m, n, ic, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_salsa20 = function(c, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
|
|
"n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
|
|
"k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_salsa20(c, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_salsa20_xor = function(c, m, n, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
|
|
"n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
|
|
"k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_salsa20_xor(c, m, n, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_stream_salsa20_xor_ic = function(c, m, n, ic, k) {
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
|
|
"n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
|
|
"k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_stream_salsa20_xor_ic(c, m, n, ic, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_auth = function(out, input, k) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(out.byteLength === binding.crypto_auth_BYTES, "out must be 'crypto_auth_BYTES' bytes");
|
|
assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes");
|
|
const res = binding.crypto_auth(out, input, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_auth_verify = function(h, input, k) {
|
|
assert(ArrayBuffer.isView(h), "h must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(h.byteLength === binding.crypto_auth_BYTES, "h must be 'crypto_auth_BYTES' bytes");
|
|
assert(k.byteLength === binding.crypto_auth_KEYBYTES, "k must be 'crypto_auth_KEYBYTES' bytes");
|
|
return binding.crypto_auth_verify(h, input, k);
|
|
};
|
|
exports.crypto_onetimeauth = function(out, input, k) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_onetimeauth_BYTES,
|
|
"out must be 'crypto_onetimeauth_BYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
|
|
"k must be 'crypto_onetimeauth_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_onetimeauth(out, input, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_onetimeauth_init = function(state, k) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
|
|
"state must be 'crypto_onetimeauth_STATEBYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
|
|
"k must be 'crypto_onetimeauth_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_onetimeauth_init(state, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_onetimeauth_update = function(state, input) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
|
|
"state must be 'crypto_onetimeauth_STATEBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_onetimeauth_update(state, input);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_onetimeauth_final = function(state, out) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_onetimeauth_STATEBYTES,
|
|
"state must be 'crypto_onetimeauth_STATEBYTES' bytes"
|
|
);
|
|
assert(
|
|
out.byteLength === binding.crypto_onetimeauth_BYTES,
|
|
"out must be 'crypto_onetimeauth_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_onetimeauth_final(state, out);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_onetimeauth_verify = function(h, input, k) {
|
|
assert(ArrayBuffer.isView(h), "h must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
h.byteLength === binding.crypto_onetimeauth_BYTES,
|
|
"h must be 'crypto_onetimeauth_BYTES' bytes"
|
|
);
|
|
assert(
|
|
k.byteLength === binding.crypto_onetimeauth_KEYBYTES,
|
|
"k must be 'crypto_onetimeauth_KEYBYTES' bytes"
|
|
);
|
|
return binding.crypto_onetimeauth_verify(h, input, k);
|
|
};
|
|
exports.crypto_pwhash = function(out, passwd, salt, opslimit, memlimit, alg) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(ArrayBuffer.isView(salt), "salt must be a typed array");
|
|
assert(
|
|
out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
|
|
"out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
|
|
);
|
|
assert(
|
|
out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
|
|
"out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
|
|
);
|
|
assert(
|
|
salt.byteLength === binding.crypto_pwhash_SALTBYTES,
|
|
"salt must be 'crypto_pwhash_SALTBYTES' bytes"
|
|
);
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
|
|
);
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
|
|
);
|
|
assert(alg >= 1 && alg <= 2, "alg must be either Argon2i 1.3 or Argon2id 1.3");
|
|
const res = binding.crypto_pwhash(out, passwd, salt, opslimit, memlimit, alg);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_pwhash_async = function(out, passwd, salt, opslimit, memlimit, alg, callback = void 0) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(ArrayBuffer.isView(salt), "salt must be a typed array");
|
|
assert(
|
|
out.byteLength >= binding.crypto_pwhash_BYTES_MIN,
|
|
"out must be at least 'crypto_pwhash_BYTES_MIN' bytes"
|
|
);
|
|
assert(
|
|
out.byteLength <= binding.crypto_pwhash_BYTES_MAX,
|
|
"out must be at most 'crypto_pwhash_BYTES_MAX' bytes"
|
|
);
|
|
assert(
|
|
salt.byteLength === binding.crypto_pwhash_SALTBYTES,
|
|
"salt must be 'crypto_pwhash_SALTBYTES' bytes"
|
|
);
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
|
|
);
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
|
|
);
|
|
assert(alg >= 1 && alg <= 2, "alg must be either Argon2i 1.3 or Argon2id 1.3");
|
|
const [done, promise] = checkStatus(callback);
|
|
binding.crypto_pwhash_async(
|
|
out.buffer,
|
|
out.byteOffset,
|
|
out.byteLength,
|
|
passwd.buffer,
|
|
passwd.byteOffset,
|
|
passwd.byteLength,
|
|
salt.buffer,
|
|
salt.byteOffset,
|
|
salt.byteLength,
|
|
opslimit,
|
|
memlimit,
|
|
alg,
|
|
done
|
|
);
|
|
return promise;
|
|
};
|
|
exports.crypto_pwhash_str = function(out, passwd, opslimit, memlimit) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_pwhash_STRBYTES,
|
|
"out must be 'crypto_pwhash_STRBYTES' bytes"
|
|
);
|
|
assert(typeof opslimit === "number", "opslimit must be a number");
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
|
|
);
|
|
assert(typeof memlimit === "number", "memlimit must be a number");
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
|
|
);
|
|
const res = binding.crypto_pwhash_str(out, passwd, opslimit, memlimit);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_pwhash_str_async = function(out, passwd, opslimit, memlimit, callback = void 0) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_pwhash_STRBYTES,
|
|
"out must be 'crypto_pwhash_STRBYTES' bytes"
|
|
);
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
assert(typeof opslimit === "number", "opslimit must be a number");
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
|
|
);
|
|
assert(typeof memlimit === "number", "memlimit must be a number");
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
|
|
);
|
|
const [done, promise] = checkStatus(callback);
|
|
binding.crypto_pwhash_str_async(
|
|
out.buffer,
|
|
out.byteOffset,
|
|
out.byteLength,
|
|
passwd.buffer,
|
|
passwd.byteOffset,
|
|
passwd.byteLength,
|
|
opslimit,
|
|
memlimit,
|
|
done
|
|
);
|
|
return promise;
|
|
};
|
|
exports.crypto_pwhash_str_verify = function(str, passwd) {
|
|
assert(ArrayBuffer.isView(str), "str must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(
|
|
str.byteLength === binding.crypto_pwhash_STRBYTES,
|
|
"str must be 'crypto_pwhash_STRBYTES' bytes"
|
|
);
|
|
return binding.crypto_pwhash_str_verify(str, passwd);
|
|
};
|
|
exports.crypto_pwhash_str_verify_async = function(str, passwd, callback = void 0) {
|
|
assert(ArrayBuffer.isView(str), "str must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(
|
|
str.byteLength === binding.crypto_pwhash_STRBYTES,
|
|
"str must be 'crypto_pwhash_STRBYTES' bytes"
|
|
);
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
const [done, promise] = checkStatus(callback, true);
|
|
binding.crypto_pwhash_str_verify_async(
|
|
str.buffer,
|
|
str.byteOffset,
|
|
str.byteLength,
|
|
passwd.buffer,
|
|
passwd.byteOffset,
|
|
passwd.byteLength,
|
|
done
|
|
);
|
|
return promise;
|
|
};
|
|
exports.crypto_pwhash_str_needs_rehash = function(str, opslimit, memlimit) {
|
|
assert(ArrayBuffer.isView(str), "str must be a typed array");
|
|
assert(
|
|
str.byteLength === binding.crypto_pwhash_STRBYTES,
|
|
"str must be 'crypto_pwhash_STRBYTES' bytes"
|
|
);
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_OPSLIMIT_MAX'"
|
|
);
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_MEMLIMIT_MAX'"
|
|
);
|
|
return binding.crypto_pwhash_str_needs_rehash(str, opslimit, memlimit);
|
|
};
|
|
exports.crypto_pwhash_scryptsalsa208sha256 = function(out, passwd, salt, opslimit, memlimit) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(ArrayBuffer.isView(salt), "salt must be a typed array");
|
|
assert(
|
|
out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
|
|
"out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
|
|
);
|
|
assert(
|
|
out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
|
|
"out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
|
|
);
|
|
assert(
|
|
salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
|
|
"salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
|
|
);
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
|
|
);
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
|
|
);
|
|
const res = binding.crypto_pwhash_scryptsalsa208sha256(out, passwd, salt, opslimit, memlimit);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_pwhash_scryptsalsa208sha256_async = function(out, passwd, salt, opslimit, memlimit, callback = void 0) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(ArrayBuffer.isView(salt), "salt must be a typed array");
|
|
assert(
|
|
out.byteLength >= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MIN,
|
|
"out must be at least 'crypto_pwhash_scryptsalsa208sha256_BYTES_MIN' bytes"
|
|
);
|
|
assert(
|
|
out.byteLength <= binding.crypto_pwhash_scryptsalsa208sha256_BYTES_MAX,
|
|
"out must be at most 'crypto_pwhash_scryptsalsa208sha256_BYTES_MAX' bytes"
|
|
);
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
assert(
|
|
salt.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
|
|
"salt must be 'crypto_pwhash_scryptsalsa208sha256_SALTBYTES' bytes"
|
|
);
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
|
|
);
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
|
|
);
|
|
const [done, promise] = checkStatus(callback);
|
|
binding.crypto_pwhash_scryptsalsa208sha256_async(
|
|
out.buffer,
|
|
out.byteOffset,
|
|
out.byteLength,
|
|
passwd.buffer,
|
|
passwd.byteOffset,
|
|
passwd.byteLength,
|
|
salt.buffer,
|
|
salt.byteOffset,
|
|
salt.byteLength,
|
|
opslimit,
|
|
memlimit,
|
|
done
|
|
);
|
|
return promise;
|
|
};
|
|
exports.crypto_pwhash_scryptsalsa208sha256_str_async = function(out, passwd, opslimit, memlimit, callback = void 0) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
|
|
"out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
|
|
);
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
|
|
);
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
|
|
);
|
|
const [done, promise] = checkStatus(callback);
|
|
binding.crypto_pwhash_scryptsalsa208sha256_str_async(
|
|
out.buffer,
|
|
out.byteOffset,
|
|
out.byteLength,
|
|
passwd.buffer,
|
|
passwd.byteOffset,
|
|
passwd.byteLength,
|
|
opslimit,
|
|
memlimit,
|
|
done
|
|
);
|
|
return promise;
|
|
};
|
|
exports.crypto_pwhash_scryptsalsa208sha256_str = function(out, passwd, opslimit, memlimit) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
|
|
"out must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
|
|
);
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
|
|
);
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
|
|
);
|
|
const res = binding.crypto_pwhash_scryptsalsa208sha256_str(out, passwd, opslimit, memlimit);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_pwhash_scryptsalsa208sha256_str_verify_async = function(str, passwd, callback = void 0) {
|
|
assert(ArrayBuffer.isView(str), "str must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(
|
|
str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
|
|
"str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
|
|
);
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
const [done, promise] = checkStatus(callback, true);
|
|
binding.crypto_pwhash_scryptsalsa208sha256_str_verify_async(
|
|
str.buffer,
|
|
str.byteOffset,
|
|
str.byteLength,
|
|
passwd.buffer,
|
|
passwd.byteOffset,
|
|
passwd.byteLength,
|
|
done
|
|
);
|
|
return promise;
|
|
};
|
|
exports.crypto_pwhash_scryptsalsa208sha256_str_verify = function(str, passwd) {
|
|
assert(ArrayBuffer.isView(str), "str must be a typed array");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(
|
|
str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
|
|
"str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
|
|
);
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
return binding.crypto_pwhash_scryptsalsa208sha256_str_verify(str, passwd);
|
|
};
|
|
exports.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash = function(str, opslimit, memlimit) {
|
|
assert(ArrayBuffer.isView(str), "str must be a typed array");
|
|
assert(
|
|
str.byteLength === binding.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
|
|
"str must be 'crypto_pwhash_scryptsalsa208sha256_STRBYTES' bytes"
|
|
);
|
|
assert(
|
|
opslimit >= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN,
|
|
"opslimit must be at least 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
opslimit <= binding.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX,
|
|
"opslimit must be at most 'crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX'"
|
|
);
|
|
assert(
|
|
memlimit >= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN,
|
|
"memlimit must be at least 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN'"
|
|
);
|
|
assert(
|
|
memlimit <= binding.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX,
|
|
"memlimit must be at most 'crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX'"
|
|
);
|
|
return binding.crypto_pwhash_scryptsalsa208sha256_str_needs_rehash(str, opslimit, memlimit);
|
|
};
|
|
exports.crypto_kx_keypair = function(pk, sk) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
|
|
"sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_kx_keypair(pk, sk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_kx_seed_keypair = function(pk, sk, seed) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(ArrayBuffer.isView(seed), "seed must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
sk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
|
|
"sk must be 'crypto_kx_SECRETKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
seed.byteLength === binding.crypto_kx_SEEDBYTES,
|
|
"seed must be 'crypto_kx_SEEDBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_kx_seed_keypair(pk, sk, seed);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_kx_client_session_keys = function(rx, tx, clientPk, clientSk, serverPk) {
|
|
if (!rx) rx = void 0;
|
|
if (!tx) tx = void 0;
|
|
assert(rx || tx, "at least one session key must be specified");
|
|
if (rx) {
|
|
assert(ArrayBuffer.isView(rx), "rx must be a typed array");
|
|
assert(
|
|
rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
|
|
"rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
|
|
);
|
|
}
|
|
if (tx) {
|
|
assert(ArrayBuffer.isView(tx), "tx must be a typed array");
|
|
assert(
|
|
tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
|
|
"tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
|
|
);
|
|
}
|
|
assert(ArrayBuffer.isView(clientPk), "clientPk must be a typed array");
|
|
assert(ArrayBuffer.isView(clientSk), "clientSk must be a typed array");
|
|
assert(ArrayBuffer.isView(serverPk), "serverPk must be a typed array");
|
|
assert(
|
|
clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
|
|
"clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
clientSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
|
|
"clientSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
|
|
"serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_kx_client_session_keys(rx, tx, clientPk, clientSk, serverPk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_kx_server_session_keys = function(rx, tx, serverPk, serverSk, clientPk) {
|
|
if (!rx) rx = void 0;
|
|
if (!tx) tx = void 0;
|
|
assert(rx || tx, "at least one session key must be specified");
|
|
if (rx) {
|
|
assert(ArrayBuffer.isView(rx), "rx must be a typed array");
|
|
assert(
|
|
rx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
|
|
"rx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
|
|
);
|
|
}
|
|
if (tx) {
|
|
assert(ArrayBuffer.isView(tx), "tx must be a typed array");
|
|
assert(
|
|
tx.byteLength === binding.crypto_kx_SESSIONKEYBYTES,
|
|
"tx must be 'crypto_kx_SESSIONKEYBYTES' bytes"
|
|
);
|
|
}
|
|
assert(ArrayBuffer.isView(serverPk), "serverPk must be a typed array");
|
|
assert(ArrayBuffer.isView(serverSk), "serverSk must be a typed array");
|
|
assert(ArrayBuffer.isView(clientPk), "clientPk must be a typed array");
|
|
assert(
|
|
serverPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
|
|
"serverPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
serverSk.byteLength === binding.crypto_kx_SECRETKEYBYTES,
|
|
"serverSk must be 'crypto_kx_SECRETKEYBYTES' bytes"
|
|
);
|
|
assert(
|
|
clientPk.byteLength === binding.crypto_kx_PUBLICKEYBYTES,
|
|
"clientPk must be 'crypto_kx_PUBLICKEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_kx_server_session_keys(rx, tx, serverPk, serverSk, clientPk);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_scalarmult_base = function(q, n) {
|
|
assert(ArrayBuffer.isView(q), "q must be a typed array");
|
|
assert(
|
|
q.byteLength === binding.crypto_scalarmult_BYTES,
|
|
"q must be 'crypto_scalarmult_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
|
|
"n must be 'crypto_scalarmult_SCALARBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_scalarmult_base(q, n);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_scalarmult = function(q, n, p) {
|
|
assert(ArrayBuffer.isView(q), "q must be a typed array");
|
|
assert(
|
|
q.byteLength === binding.crypto_scalarmult_BYTES,
|
|
"q must be 'crypto_scalarmult_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_scalarmult_SCALARBYTES,
|
|
"n must be 'crypto_scalarmult_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.crypto_scalarmult_BYTES,
|
|
"p must be 'crypto_scalarmult_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_scalarmult(q, n, p);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_scalarmult_ed25519_base = function(q, n) {
|
|
assert(ArrayBuffer.isView(q), "q must be a typed array");
|
|
assert(
|
|
q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
|
|
"q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
|
|
"n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_scalarmult_ed25519_base(q, n);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_scalarmult_ed25519 = function(q, n, p) {
|
|
assert(ArrayBuffer.isView(q), "q must be a typed array");
|
|
assert(
|
|
q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
|
|
"q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
|
|
"n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
|
|
"p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_scalarmult_ed25519(q, n, p);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_core_ed25519_is_valid_point = function(p) {
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.crypto_core_ed25519_BYTES,
|
|
"p must be 'crypto_core_ed25519_BYTES' bytes"
|
|
);
|
|
return binding.crypto_core_ed25519_is_valid_point(p);
|
|
};
|
|
exports.crypto_core_ed25519_from_uniform = function(p, r) {
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.crypto_core_ed25519_BYTES,
|
|
"p must be 'crypto_core_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(r), "r must be a typed array");
|
|
assert(
|
|
r.byteLength === binding.crypto_core_ed25519_UNIFORMBYTES,
|
|
"r must be 'crypto_core_ed25519_UNIFORMBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_core_ed25519_from_uniform(p, r);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_scalarmult_ed25519_base_noclamp = function(q, n) {
|
|
assert(ArrayBuffer.isView(q), "q must be a typed array");
|
|
assert(
|
|
q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
|
|
"q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
|
|
"n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_scalarmult_ed25519_base_noclamp(q, n);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_scalarmult_ed25519_noclamp = function(q, n, p) {
|
|
assert(ArrayBuffer.isView(q), "q must be a typed array");
|
|
assert(
|
|
q.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
|
|
"q must be 'crypto_scalarmult_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_scalarmult_ed25519_SCALARBYTES,
|
|
"n must be 'crypto_scalarmult_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.crypto_scalarmult_ed25519_BYTES,
|
|
"p must be 'crypto_scalarmult_ed25519_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_scalarmult_ed25519_noclamp(q, n, p);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_core_ed25519_add = function(r, p, q) {
|
|
assert(ArrayBuffer.isView(r), "r must be a typed array");
|
|
assert(
|
|
r.byteLength === binding.crypto_core_ed25519_BYTES,
|
|
"r must be 'crypto_core_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.crypto_core_ed25519_BYTES,
|
|
"p must be 'crypto_core_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(q), "q must be a typed array");
|
|
assert(
|
|
q.byteLength === binding.crypto_core_ed25519_BYTES,
|
|
"q must be 'crypto_core_ed25519_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_core_ed25519_add(r, p, q);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_core_ed25519_sub = function(r, p, q) {
|
|
assert(ArrayBuffer.isView(r), "r must be a typed array");
|
|
assert(
|
|
r.byteLength === binding.crypto_core_ed25519_BYTES,
|
|
"r must be 'crypto_core_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.crypto_core_ed25519_BYTES,
|
|
"p must be 'crypto_core_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(q), "q must be a typed array");
|
|
assert(
|
|
q.byteLength === binding.crypto_core_ed25519_BYTES,
|
|
"q must be 'crypto_core_ed25519_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_core_ed25519_sub(r, p, q);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_core_ed25519_scalar_random = function(r) {
|
|
assert(ArrayBuffer.isView(r), "r must be a typed array");
|
|
assert(
|
|
r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.crypto_core_ed25519_scalar_random(r);
|
|
};
|
|
exports.crypto_core_ed25519_scalar_reduce = function(r, s) {
|
|
assert(ArrayBuffer.isView(r), "r must be a typed array");
|
|
assert(
|
|
r.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"r must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(s), "s must be a typed array");
|
|
assert(
|
|
s.byteLength === binding.crypto_core_ed25519_NONREDUCEDSCALARBYTES,
|
|
"s must be 'crypto_core_ed25519_NONREDUCEDSCALARBYTES' bytes"
|
|
);
|
|
binding.crypto_core_ed25519_scalar_reduce(r, s);
|
|
};
|
|
exports.crypto_core_ed25519_scalar_invert = function(recip, s) {
|
|
assert(ArrayBuffer.isView(recip), "recip must be a typed array");
|
|
assert(
|
|
recip.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"recip must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(s), "s must be a typed array");
|
|
assert(
|
|
s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.crypto_core_ed25519_scalar_invert(recip, s);
|
|
};
|
|
exports.crypto_core_ed25519_scalar_negate = function(neg, s) {
|
|
assert(ArrayBuffer.isView(neg), "neg must be a typed array");
|
|
assert(
|
|
neg.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"neg must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(s), "s must be a typed array");
|
|
assert(
|
|
s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.crypto_core_ed25519_scalar_negate(neg, s);
|
|
};
|
|
exports.crypto_core_ed25519_scalar_complement = function(comp, s) {
|
|
assert(ArrayBuffer.isView(comp), "comp must be a typed array");
|
|
assert(
|
|
comp.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"comp must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(s), "s must be a typed array");
|
|
assert(
|
|
s.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"s must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.crypto_core_ed25519_scalar_complement(comp, s);
|
|
};
|
|
exports.crypto_core_ed25519_scalar_add = function(z, x, y) {
|
|
assert(ArrayBuffer.isView(z), "z must be a typed array");
|
|
assert(
|
|
z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(x), "x must be a typed array");
|
|
assert(
|
|
x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(y), "y must be a typed array");
|
|
assert(
|
|
y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.crypto_core_ed25519_scalar_add(z, x, y);
|
|
};
|
|
exports.crypto_core_ed25519_scalar_sub = function(z, x, y) {
|
|
assert(ArrayBuffer.isView(z), "z must be a typed array");
|
|
assert(
|
|
z.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"z must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(x), "x must be a typed array");
|
|
assert(
|
|
x.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"x must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(y), "y must be a typed array");
|
|
assert(
|
|
y.byteLength === binding.crypto_core_ed25519_SCALARBYTES,
|
|
"y must be 'crypto_core_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.crypto_core_ed25519_scalar_sub(z, x, y);
|
|
};
|
|
exports.crypto_shorthash = function(out, input, k) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_shorthash_BYTES,
|
|
"out must be 'crypto_shorthash_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_shorthash_KEYBYTES,
|
|
"k must be 'crypto_shorthash_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_shorthash(out, input, k);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_kdf_keygen = function(key) {
|
|
assert(ArrayBuffer.isView(key), "key must be a typed array");
|
|
assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes");
|
|
binding.crypto_kdf_keygen(key);
|
|
};
|
|
exports.crypto_kdf_derive_from_key = function(subkey, subkeyId, ctx, key) {
|
|
assert(ArrayBuffer.isView(subkey), "subkey must be a typed array");
|
|
assert(
|
|
subkey.byteLength >= binding.crypto_kdf_BYTES_MIN,
|
|
"subkey must be at least 'crypto_kdf_BYTES_MIN' bytes"
|
|
);
|
|
assert(
|
|
subkey.byteLength <= binding.crypto_kdf_BYTES_MAX,
|
|
"subkey must be at most 'crypto_kdf_BYTES_MAX' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(ctx), "ctx must be a typed array");
|
|
assert(
|
|
ctx.byteLength === binding.crypto_kdf_CONTEXTBYTES,
|
|
"ctx must be 'crypto_kdf_CONTEXTBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(key), "key must be a typed array");
|
|
assert(key.byteLength === binding.crypto_kdf_KEYBYTES, "key must be 'crypto_kdf_KEYBYTES' bytes");
|
|
const res = binding.crypto_kdf_derive_from_key(subkey, subkeyId, ctx, key);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash = function(out, input) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(out.byteLength === binding.crypto_hash_BYTES, "out must be 'crypto_hash_BYTES' bytes");
|
|
const res = binding.crypto_hash(out, input);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash_sha256 = function(out, input) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_hash_sha256_BYTES,
|
|
"out must be 'crypto_hash_sha256_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_hash_sha256(out, input);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash_sha256_init = function(state) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
|
|
"state must be 'crypto_hash_sha256_STATEBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_hash_sha256_init(state);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash_sha256_update = function(state, input) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
|
|
"state must be 'crypto_hash_sha256_STATEBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_hash_sha256_update(state, input);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash_sha256_final = function(state, out) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_hash_sha256_STATEBYTES,
|
|
"state must be 'crypto_hash_sha256_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_hash_sha256_BYTES,
|
|
"out must be 'crypto_hash_sha256_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_hash_sha256_final(state, out);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash_sha512 = function(out, input) {
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_hash_sha512_BYTES,
|
|
"out must be 'crypto_hash_sha512_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_hash_sha512(out, input);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash_sha512_init = function(state) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
|
|
"state must be 'crypto_hash_sha512_STATEBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_hash_sha512_init(state);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash_sha512_update = function(state, input) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(ArrayBuffer.isView(input), "input must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
|
|
"state must be 'crypto_hash_sha512_STATEBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_hash_sha512_update(state, input);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_hash_sha512_final = function(state, out) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_hash_sha512_STATEBYTES,
|
|
"state must be 'crypto_hash_sha512_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(
|
|
out.byteLength === binding.crypto_hash_sha512_BYTES,
|
|
"out must be 'crypto_hash_sha512_BYTES' bytes"
|
|
);
|
|
const res = binding.crypto_hash_sha512_final(state, out);
|
|
if (res !== 0) throw new Error("status: " + res);
|
|
};
|
|
exports.crypto_aead_xchacha20poly1305_ietf_keygen = function(k) {
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
binding.crypto_aead_xchacha20poly1305_ietf_keygen(k);
|
|
};
|
|
exports.crypto_aead_xchacha20poly1305_ietf_encrypt = function(c, m, ad, nsec, npub, k) {
|
|
if (!ad) ad = void 0;
|
|
assert(nsec === null, "nsec must always be set to null");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(
|
|
c.byteLength === m.byteLength + binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
|
|
"c must be 'm.byteLength + crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
|
|
);
|
|
assert(c.byteLength <= 4294967295, "c.byteLength must be a 32bit integer");
|
|
assert(ArrayBuffer.isView(npub), "npub must be a typed array");
|
|
assert(
|
|
npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
|
|
"npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt(c, m, ad, npub, k);
|
|
if (res < 0) throw new Error("could not encrypt data");
|
|
return res;
|
|
};
|
|
exports.crypto_aead_xchacha20poly1305_ietf_decrypt = function(m, nsec, c, ad, npub, k) {
|
|
if (!ad) ad = void 0;
|
|
assert(nsec === null, "nsec must always be set to null");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(
|
|
m.byteLength === c.byteLength - binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
|
|
"m must be 'c.byteLength - crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
|
|
);
|
|
assert(m.byteLength <= 4294967295, "m.byteLength must be a 32bit integer");
|
|
assert(ArrayBuffer.isView(npub), "npub must be a typed array");
|
|
assert(
|
|
npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
|
|
"npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt(m, c, ad, npub, k);
|
|
if (res < 0) throw new Error("could not verify data");
|
|
return res;
|
|
};
|
|
exports.crypto_aead_xchacha20poly1305_ietf_encrypt_detached = function(c, mac, m, ad, nsec, npub, k) {
|
|
if (!ad) ad = void 0;
|
|
assert(nsec === null, "nsec must always be set to null");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(ArrayBuffer.isView(mac), "mac must be a typed array");
|
|
assert(
|
|
mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
|
|
"mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(npub), "npub must be a typed array");
|
|
assert(
|
|
npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
|
|
"npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_aead_xchacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k);
|
|
if (res < 0) throw new Error("could not encrypt data");
|
|
return res;
|
|
};
|
|
exports.crypto_aead_xchacha20poly1305_ietf_decrypt_detached = function(m, nsec, c, mac, ad, npub, k) {
|
|
if (!ad) ad = void 0;
|
|
assert(nsec === null, "nsec must always be set to null");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes");
|
|
assert(ArrayBuffer.isView(mac), "mac must be a typed array");
|
|
assert(
|
|
mac.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_ABYTES,
|
|
"mac must be 'crypto_aead_xchacha20poly1305_ietf_ABYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(npub), "npub must be a typed array");
|
|
assert(
|
|
npub.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
|
|
"npub must be 'crypto_aead_xchacha20poly1305_ietf_NPUBBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_xchacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_aead_xchacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k);
|
|
if (res !== 0) throw new Error("could not verify data");
|
|
};
|
|
exports.crypto_aead_chacha20poly1305_ietf_keygen = function(k) {
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
binding.crypto_aead_chacha20poly1305_ietf_keygen(k);
|
|
};
|
|
exports.crypto_aead_chacha20poly1305_ietf_encrypt = function(c, m, ad, nsec, npub, k) {
|
|
if (!ad) ad = void 0;
|
|
assert(nsec === null, "nsec must always be set to null");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(
|
|
c.byteLength === m.byteLength + binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
|
|
"c must be 'm.byteLength + crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
|
|
);
|
|
assert(c.byteLength <= 4294967295, "c.byteLength must be a 32bit integer");
|
|
assert(ArrayBuffer.isView(npub), "npub must be a typed array");
|
|
assert(
|
|
npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
|
"npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt(c, m, ad, npub, k);
|
|
if (res < 0) throw new Error("could not encrypt data");
|
|
return res;
|
|
};
|
|
exports.crypto_aead_chacha20poly1305_ietf_decrypt = function(m, nsec, c, ad, npub, k) {
|
|
if (!ad) ad = void 0;
|
|
assert(nsec === null, "nsec must always be set to null");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(
|
|
m.byteLength === c.byteLength - binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
|
|
"m must be 'c.byteLength - crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
|
|
);
|
|
assert(m.byteLength <= 4294967295, "m.byteLength must be a 32bit integer");
|
|
assert(ArrayBuffer.isView(npub), "npub must be a typed array");
|
|
assert(
|
|
npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
|
"npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt(m, c, ad, npub, k);
|
|
if (res < 0) throw new Error("could not verify data");
|
|
return res;
|
|
};
|
|
exports.crypto_aead_chacha20poly1305_ietf_encrypt_detached = function(c, mac, m, ad, nsec, npub, k) {
|
|
if (!ad) ad = void 0;
|
|
assert(nsec === null, "nsec must always be set to null");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
assert(ArrayBuffer.isView(mac), "mac must be a typed array");
|
|
assert(
|
|
mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
|
|
"mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(npub), "npub must be a typed array");
|
|
assert(
|
|
npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
|
"npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_aead_chacha20poly1305_ietf_encrypt_detached(c, mac, m, ad, npub, k);
|
|
if (res < 0) throw new Error("could not encrypt data");
|
|
return res;
|
|
};
|
|
exports.crypto_aead_chacha20poly1305_ietf_decrypt_detached = function(m, nsec, c, mac, ad, npub, k) {
|
|
if (!ad) ad = void 0;
|
|
assert(nsec === null, "nsec must always be set to null");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(m.byteLength === c.byteLength, "m must be 'c.byteLength' bytes");
|
|
assert(ArrayBuffer.isView(mac), "mac must be a typed array");
|
|
assert(
|
|
mac.byteLength === binding.crypto_aead_chacha20poly1305_ietf_ABYTES,
|
|
"mac must be 'crypto_aead_chacha20poly1305_ietf_ABYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(npub), "npub must be a typed array");
|
|
assert(
|
|
npub.byteLength === binding.crypto_aead_chacha20poly1305_ietf_NPUBBYTES,
|
|
"npub must be 'crypto_aead_chacha20poly1305_ietf_NPUBBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_aead_chacha20poly1305_ietf_KEYBYTES,
|
|
"k must be 'crypto_aead_chacha20poly1305_ietf_KEYBYTES' bytes"
|
|
);
|
|
const res = binding.crypto_aead_chacha20poly1305_ietf_decrypt_detached(m, c, mac, ad, npub, k);
|
|
if (res !== 0) throw new Error("could not verify data");
|
|
};
|
|
exports.crypto_stream_xor_wrap_init = function(state, n, k) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
|
|
"state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_NONCEBYTES,
|
|
"n must be 'crypto_stream_NONCEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_KEYBYTES,
|
|
"k must be 'crypto_stream_KEYBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_xor_wrap_init(state, n, k);
|
|
};
|
|
exports.crypto_stream_xor_wrap_update = function(state, c, m) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
|
|
"state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
binding.crypto_stream_xor_wrap_update(state, c, m);
|
|
};
|
|
exports.crypto_stream_xor_wrap_final = function(state) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.sn_crypto_stream_xor_STATEBYTES,
|
|
"state must be 'sn_crypto_stream_xor_STATEBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_xor_wrap_final(state);
|
|
};
|
|
exports.crypto_stream_chacha20_xor_wrap_init = function(state, n, k) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_chacha20_NONCEBYTES,
|
|
"n must be 'crypto_stream_chacha20_NONCEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_chacha20_KEYBYTES,
|
|
"k must be 'crypto_stream_chacha20_KEYBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_chacha20_xor_wrap_init(state, n, k);
|
|
};
|
|
exports.crypto_stream_chacha20_xor_wrap_update = function(state, c, m) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
binding.crypto_stream_chacha20_xor_wrap_update(state, c, m);
|
|
};
|
|
exports.crypto_stream_chacha20_xor_wrap_final = function(state) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_chacha20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_chacha20_xor_STATEBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_chacha20_xor_wrap_final(state);
|
|
};
|
|
exports.crypto_stream_chacha20_ietf_xor_wrap_init = function(state, n, k) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_chacha20_ietf_NONCEBYTES,
|
|
"n must be 'crypto_stream_chacha20_ietf_NONCEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_chacha20_ietf_KEYBYTES,
|
|
"k must be 'crypto_stream_chacha20_ietf_KEYBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_chacha20_ietf_xor_wrap_init(state, n, k);
|
|
};
|
|
exports.crypto_stream_chacha20_ietf_xor_wrap_update = function(state, c, m) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
binding.crypto_stream_chacha20_ietf_xor_wrap_update(state, c, m);
|
|
};
|
|
exports.crypto_stream_chacha20_ietf_xor_wrap_final = function(state) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_chacha20_ietf_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_chacha20_ietf_xor_STATEBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_chacha20_ietf_xor_wrap_final(state);
|
|
};
|
|
exports.crypto_stream_xchacha20_xor_wrap_init = function(state, n, k) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_xchacha20_NONCEBYTES,
|
|
"n must be 'crypto_stream_xchacha20_NONCEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_xchacha20_KEYBYTES,
|
|
"k must be 'crypto_stream_xchacha20_KEYBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_xchacha20_xor_wrap_init(state, n, k);
|
|
};
|
|
exports.crypto_stream_xchacha20_xor_wrap_update = function(state, c, m) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
binding.crypto_stream_xchacha20_xor_wrap_update(state, c, m);
|
|
};
|
|
exports.crypto_stream_xchacha20_xor_wrap_final = function(state) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_xchacha20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_xchacha20_xor_STATEBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_xchacha20_xor_wrap_final(state);
|
|
};
|
|
exports.crypto_stream_salsa20_xor_wrap_init = function(state, n, k) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.crypto_stream_salsa20_NONCEBYTES,
|
|
"n must be 'crypto_stream_salsa20_NONCEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(k), "k must be a typed array");
|
|
assert(
|
|
k.byteLength === binding.crypto_stream_salsa20_KEYBYTES,
|
|
"k must be 'crypto_stream_salsa20_KEYBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_salsa20_xor_wrap_init(state, n, k);
|
|
};
|
|
exports.crypto_stream_salsa20_xor_wrap_update = function(state, c, m) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(c), "c must be a typed array");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(c.byteLength === m.byteLength, "c must be 'm.byteLength' bytes");
|
|
binding.crypto_stream_salsa20_xor_wrap_update(state, c, m);
|
|
};
|
|
exports.crypto_stream_salsa20_xor_wrap_final = function(state) {
|
|
assert(ArrayBuffer.isView(state), "state must be a typed array");
|
|
assert(
|
|
state.byteLength === binding.crypto_stream_salsa20_xor_STATEBYTES,
|
|
"state must be 'crypto_stream_salsa20_xor_STATEBYTES' bytes"
|
|
);
|
|
binding.crypto_stream_salsa20_xor_wrap_final(state);
|
|
};
|
|
exports.extension_tweak_ed25519_base = function(n, p, ns) {
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.extension_tweak_ed25519_BYTES,
|
|
"p must be 'extension_tweak_ed25519_BYTES' bytes"
|
|
);
|
|
binding.extension_tweak_ed25519_base(n, p, ns);
|
|
};
|
|
exports.extension_tweak_ed25519_sign_detached = function(sig, m, scalar, pk) {
|
|
assert(ArrayBuffer.isView(sig), "sig must be a typed array");
|
|
assert(sig.byteLength === binding.crypto_sign_BYTES, "sig must be 'crypto_sign_BYTES' bytes");
|
|
assert(ArrayBuffer.isView(m), "m must be a typed array");
|
|
assert(ArrayBuffer.isView(scalar), "scalar must be a typed array");
|
|
assert(
|
|
scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
if (pk) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
}
|
|
const res = binding.extension_tweak_ed25519_sign_detached(sig, m, scalar, pk);
|
|
if (res !== 0) throw new Error("failed to compute signature");
|
|
};
|
|
exports.extension_tweak_ed25519_sk_to_scalar = function(n, sk) {
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(sk), "sk must be a typed array");
|
|
assert(
|
|
sk.byteLength === binding.crypto_sign_SECRETKEYBYTES,
|
|
"sk must be 'crypto_sign_SECRETKEYBYTES' bytes"
|
|
);
|
|
binding.extension_tweak_ed25519_sk_to_scalar(n, sk);
|
|
};
|
|
exports.extension_tweak_ed25519_scalar = function(scalarOut, scalar, ns) {
|
|
assert(ArrayBuffer.isView(scalarOut), "scalarOut must be a typed array");
|
|
assert(
|
|
scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(scalar), "scalar must be a typed array");
|
|
assert(
|
|
scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.extension_tweak_ed25519_scalar(scalarOut, scalar, ns);
|
|
};
|
|
exports.extension_tweak_ed25519_pk = function(tpk, pk, ns) {
|
|
assert(ArrayBuffer.isView(tpk), "tpk must be a typed array");
|
|
assert(
|
|
tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
const res = binding.extension_tweak_ed25519_pk(tpk, pk, ns);
|
|
if (res !== 0) throw new Error("failed to tweak public key");
|
|
};
|
|
exports.extension_tweak_ed25519_keypair = function(pk, scalarOut, scalarIn, ns) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.extension_tweak_ed25519_BYTES,
|
|
"pk must be 'extension_tweak_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(scalarOut), "scalarOut must be a typed array");
|
|
assert(
|
|
scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(scalarIn), "scalarIn must be a typed array");
|
|
assert(
|
|
scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.extension_tweak_ed25519_keypair(pk, scalarOut, scalarIn, ns);
|
|
};
|
|
exports.extension_tweak_ed25519_scalar_add = function(scalarOut, scalar, n) {
|
|
assert(ArrayBuffer.isView(scalarOut), "scalarOut must be a typed array");
|
|
assert(
|
|
scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(scalar), "scalar must be a typed array");
|
|
assert(
|
|
scalar.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalar must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(n), "n must be a typed array");
|
|
assert(
|
|
n.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"n must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
binding.extension_tweak_ed25519_scalar_add(scalarOut, scalar, n);
|
|
};
|
|
exports.extension_tweak_ed25519_pk_add = function(tpk, pk, p) {
|
|
assert(ArrayBuffer.isView(tpk), "tpk must be a typed array");
|
|
assert(
|
|
tpk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"tpk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"pk must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(p), "p must be a typed array");
|
|
assert(
|
|
p.byteLength === binding.crypto_sign_PUBLICKEYBYTES,
|
|
"p must be 'crypto_sign_PUBLICKEYBYTES' bytes"
|
|
);
|
|
const res = binding.extension_tweak_ed25519_pk_add(tpk, pk, p);
|
|
if (res !== 0) throw new Error("failed to add tweak to public key");
|
|
};
|
|
exports.extension_tweak_ed25519_keypair_add = function(pk, scalarOut, scalarIn, tweak) {
|
|
assert(ArrayBuffer.isView(pk), "pk must be a typed array");
|
|
assert(
|
|
pk.byteLength === binding.extension_tweak_ed25519_BYTES,
|
|
"pk must be 'extension_tweak_ed25519_BYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(scalarOut), "scalarOut must be a typed array");
|
|
assert(
|
|
scalarOut.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalarOut must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(scalarIn), "scalarIn must be a typed array");
|
|
assert(
|
|
scalarIn.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"scalarIn must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
assert(ArrayBuffer.isView(tweak), "tweak must be a typed array");
|
|
assert(
|
|
tweak.byteLength === binding.extension_tweak_ed25519_SCALARBYTES,
|
|
"tweak must be 'extension_tweak_ed25519_SCALARBYTES' bytes"
|
|
);
|
|
const res = binding.extension_tweak_ed25519_keypair_add(pk, scalarOut, scalarIn, tweak);
|
|
if (res !== 0) throw new Error("failed to add tweak to keypair");
|
|
};
|
|
exports.extension_pbkdf2_sha512_async = function(out, passwd, salt, iter, outlen, callback) {
|
|
assert(
|
|
iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
|
|
"iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
|
|
);
|
|
assert(
|
|
outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
|
|
"outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
|
|
);
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes");
|
|
assert(out.byteLength > 0, "out must not be empty");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
assert(ArrayBuffer.isView(salt), "salt must be a typed array");
|
|
assert(salt.byteLength > 0, "salt must not be empty");
|
|
const [done, promise] = checkStatus(callback);
|
|
binding.extension_pbkdf2_sha512_async(
|
|
out.buffer,
|
|
out.byteOffset,
|
|
out.byteLength,
|
|
passwd.buffer,
|
|
passwd.byteOffset,
|
|
passwd.byteLength,
|
|
salt.buffer,
|
|
salt.byteOffset,
|
|
salt.byteLength,
|
|
iter,
|
|
outlen,
|
|
done
|
|
);
|
|
return promise;
|
|
};
|
|
exports.extension_pbkdf2_sha512 = function(out, passwd, salt, iter, outlen) {
|
|
assert(
|
|
iter >= binding.extension_pbkdf2_sha512_ITERATIONS_MIN,
|
|
"iter must be at least 'extension_pbkdf2_sha512_ITERATIONS_MIN'"
|
|
);
|
|
assert(
|
|
outlen <= binding.extension_pbkdf2_sha512_BYTES_MAX,
|
|
"outlen must be at most 'extension_pbkdf2_sha512_BYTES_MAX'"
|
|
);
|
|
assert(ArrayBuffer.isView(out), "out must be a typed array");
|
|
assert(out.byteLength >= outlen, "out must be at least 'outlen' bytes");
|
|
assert(out.byteLength > 0, "out must not be empty");
|
|
assert(ArrayBuffer.isView(passwd), "passwd must be a typed array");
|
|
assert(passwd.byteLength > 0, "passwd must not be empty");
|
|
assert(ArrayBuffer.isView(salt), "salt must be a typed array");
|
|
assert(salt.byteLength > 0, "salt must not be empty");
|
|
const res = binding.extension_pbkdf2_sha512(out, passwd, salt, iter, outlen);
|
|
if (res !== 0) throw new Error("failed to add tweak to public key");
|
|
};
|
|
function checkStatus(callback, booleanResult = false) {
|
|
let done, promise;
|
|
if (typeof callback === "function") {
|
|
done = function(status) {
|
|
if (booleanResult) callback(null, status === 0);
|
|
else if (status === 0) callback(null);
|
|
else callback(new Error("status: " + status));
|
|
};
|
|
} else {
|
|
promise = new Promise(function(resolve, reject) {
|
|
done = function(status) {
|
|
if (booleanResult) resolve(status === 0);
|
|
else if (status === 0) resolve();
|
|
else reject(new Error("status: " + status));
|
|
};
|
|
});
|
|
}
|
|
return [done, promise];
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/url-file-url/index.js
|
|
var require_url_file_url = __commonJS({
|
|
"../../node_modules/url-file-url/index.js"(exports) {
|
|
var path = __require("path");
|
|
var { isWindows } = require_which_runtime();
|
|
exports.fileURLToPath = function fileURLToPath(url) {
|
|
if (typeof url === "string") {
|
|
url = new URL(url);
|
|
}
|
|
if (url.protocol !== "file:") {
|
|
throw new Error("The URL must use the file: protocol");
|
|
}
|
|
if (isWindows) {
|
|
if (/%2f|%5c/i.test(url.pathname)) {
|
|
throw new Error("The file: URL path must not include encoded \\ or / characters");
|
|
}
|
|
} else {
|
|
if (url.hostname) {
|
|
throw new Error("The file: URL host must be 'localhost' or empty");
|
|
}
|
|
if (/%2f/i.test(url.pathname)) {
|
|
throw new Error("The file: URL path must not include encoded / characters");
|
|
}
|
|
}
|
|
const pathname = path.normalize(decodeURIComponent(url.pathname));
|
|
if (isWindows) {
|
|
if (url.hostname) return "\\\\" + url.hostname + pathname;
|
|
const letter = pathname.charCodeAt(1) | 32;
|
|
if (letter < 97 || letter > 122 || pathname.charCodeAt(2) !== 58) {
|
|
throw new Error("The file: URL path must be absolute");
|
|
}
|
|
return pathname.slice(1);
|
|
}
|
|
return pathname;
|
|
};
|
|
exports.pathToFileURL = function pathToFileURL(pathname) {
|
|
let resolved = path.resolve(pathname);
|
|
if (pathname[pathname.length - 1] === "/") {
|
|
resolved += "/";
|
|
} else if (isWindows && pathname[pathname.length - 1] === "\\") {
|
|
resolved += "\\";
|
|
}
|
|
resolved = resolved.replaceAll("%", "%25").replaceAll("#", "%23").replaceAll("?", "%3f").replaceAll("\n", "%0a").replaceAll("\r", "%0d").replaceAll(" ", "%09");
|
|
if (!isWindows) {
|
|
resolved = resolved.replaceAll("\\", "%5c");
|
|
}
|
|
return new URL("file:" + resolved);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/drive-bundler/index.js
|
|
var require_drive_bundler = __commonJS({
|
|
"../../node_modules/drive-bundler/index.js"(exports, module) {
|
|
var fs = __require("fs");
|
|
var path = __require("path");
|
|
var b4a = require_b4a();
|
|
var Deps = require_dependency_stream();
|
|
var mutex = require_promise();
|
|
var sodium = require_sodium_native();
|
|
var unixResolve = require_unix_path_resolve();
|
|
var { pipelinePromise } = require_streamx();
|
|
var { pathToFileURL } = require_url_file_url();
|
|
module.exports = class DriveBundle {
|
|
constructor(drive, {
|
|
cwd = path.resolve("."),
|
|
mount = "",
|
|
cache = null,
|
|
host = __require.addon ? __require.addon.host : process.platform + "-" + process.arch,
|
|
runtimes = ["bare", "node"],
|
|
prebuilds = true,
|
|
assets = true,
|
|
absoluteFiles = !!mount,
|
|
inlineAssets = false,
|
|
packages = true,
|
|
entrypoint = "."
|
|
} = {}) {
|
|
this.drive = drive;
|
|
this.packages = packages;
|
|
this.cwd = cwd;
|
|
this.prebuilds = prebuilds ? path.resolve(cwd, typeof prebuilds === "string" ? prebuilds : "prebuilds") : null;
|
|
this.assets = assets ? path.resolve(cwd, typeof assets === "string" ? assets : "assets") : null;
|
|
this.cache = cache;
|
|
this.mount = typeof mount === "string" ? mount : mount.href.replace(/[/]$/, "");
|
|
this.absoluteFiles = absoluteFiles;
|
|
this.inlineAssets = inlineAssets;
|
|
this.host = host;
|
|
this.runtimes = runtimes;
|
|
this.entrypoint = entrypoint;
|
|
this.lock = mutex();
|
|
}
|
|
static async stringify(drive, opts) {
|
|
const d = new this(drive, opts);
|
|
return await d.stringify();
|
|
}
|
|
async stringify(entrypoint = this.entrypoint) {
|
|
const b = await this.bundle(entrypoint);
|
|
const addons = {};
|
|
let wrap = "";
|
|
for (const [key, source] of Object.entries(b.sources)) {
|
|
if (wrap) wrap += ",\n";
|
|
wrap += JSON.stringify(key) + ": { resolutions: " + JSON.stringify(b.resolutions[key] || {}) + ", ";
|
|
wrap += "source (module, exports, __filename, __dirname, require) {";
|
|
wrap += (key.endsWith(".json") ? "module.exports = " : "") + source;
|
|
wrap += "\n}}";
|
|
}
|
|
for (const [key, map] of Object.entries(b.resolutions)) {
|
|
if (map["bare:addon"]) addons[key] = map["bare:addon"];
|
|
}
|
|
return `{
|
|
const __bundle__ = {
|
|
builtinRequire: typeof require === 'function' ? require : null,
|
|
cache: Object.create(null),
|
|
addons: ${JSON.stringify(addons)},
|
|
bundle: {${wrap}},
|
|
require (filename) {
|
|
let mod = __bundle__.cache[filename]
|
|
if (mod) return mod
|
|
|
|
const b = __bundle__.bundle[filename]
|
|
if (!b) throw new Error('Module not found')
|
|
|
|
mod = __bundle__.cache[filename] = {
|
|
filename,
|
|
dirname: filename.slice(0, filename.lastIndexOf('/')),
|
|
exports: {},
|
|
require
|
|
}
|
|
|
|
require.resolve = function (req) {
|
|
const res = b.resolutions[req]
|
|
if (!res) throw new Error('Could not find module "' + req + '" from "' + mod.filename + '"')
|
|
return res
|
|
}
|
|
|
|
require.addon = function (dir = '.') {
|
|
if (!__bundle__.builtinRequire || !__bundle__.builtinRequire.addon) throw new Error('Addons not supported')
|
|
|
|
let d = dir.startsWith('/') ? dir : mod.dirname + '/' + dir
|
|
let p = 1
|
|
let addon = ''
|
|
|
|
while (p < d.length) {
|
|
let n = d.indexOf('/', p)
|
|
if (n === -1) n = d.length
|
|
|
|
const part = d.slice(p, n)
|
|
|
|
p = n + 1
|
|
|
|
if (part === '.' || part === '') continue
|
|
if (part === '..') {
|
|
addon = addon.slice(0, addon.lastIndexOf('/'))
|
|
continue
|
|
}
|
|
|
|
addon += '/' + part
|
|
}
|
|
|
|
if (!addon.endsWith('/')) addon += '/'
|
|
|
|
const mapped = __bundle__.addons[addon]
|
|
return mapped ? __bundle__.builtinRequire(mapped) : __bundle__.builtinRequire.addon(addon)
|
|
}
|
|
|
|
require.asset = function () {
|
|
const res = b.resolutions[req]
|
|
if (!res || !res.asset) throw new Error('Could not find asset "' + req + '" from "' + mod.filename + '"')
|
|
return res.asset
|
|
}
|
|
|
|
b.source(mod, mod.exports, mod.filename, mod.dirname, require)
|
|
return mod
|
|
|
|
function require (req) {
|
|
return __bundle__.require(require.resolve(req)).exports
|
|
}
|
|
}
|
|
}
|
|
|
|
__bundle__.require(${JSON.stringify(b.entrypoint)})
|
|
}`.replace(/\n[ ]{4}/g, "\n").trim() + "\n";
|
|
}
|
|
static async bundle(drive, opts) {
|
|
const d = new this(drive, opts);
|
|
return await d.bundle();
|
|
}
|
|
static id(bundle) {
|
|
const buffers = [];
|
|
buffers.push(b4a.from("sources\n"));
|
|
for (const [key, data] of Object.entries(bundle.sources)) {
|
|
buffers.push(b4a.from(key + "\n"));
|
|
buffers.push(b4a.from(data));
|
|
}
|
|
buffers.push(b4a.from("assets\n"));
|
|
for (const [key, data] of Object.entries(bundle.assets)) {
|
|
buffers.push(b4a.from(key + "\n"));
|
|
buffers.push(data.value);
|
|
}
|
|
const out = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash_batch(out, buffers);
|
|
return out;
|
|
}
|
|
async bundle(entrypoint = this.entrypoint) {
|
|
let main = null;
|
|
const resolutions = {};
|
|
const imports = {};
|
|
const sources = {};
|
|
const assets = {};
|
|
const stream = new Deps(this.drive, {
|
|
host: this.host,
|
|
runtimes: this.runtimes,
|
|
packages: this.packages,
|
|
source: true,
|
|
entrypoint
|
|
});
|
|
const addonsPending = [];
|
|
const assetsPending = [];
|
|
for await (const data of stream) {
|
|
const u = this._resolutionKey(data.key, false);
|
|
if (!main) main = u;
|
|
if (this.cache && Object.hasOwn(this.cache, u)) continue;
|
|
const r = {};
|
|
let save = false;
|
|
sources[u] = data.source;
|
|
for (const { input, output } of data.resolutions) {
|
|
if (!input || !output) continue;
|
|
r[input] = this._resolutionKey(output, false);
|
|
save = true;
|
|
}
|
|
if (save) resolutions[u] = r;
|
|
if (this.prebuilds) {
|
|
for (const { input, output } of data.addons) {
|
|
if (!input || !output) continue;
|
|
addonsPending.push(this._mapPrebuild(data.key, input, output));
|
|
}
|
|
}
|
|
if (this.assets) {
|
|
for (const { input } of data.assets) {
|
|
assetsPending.push(this._mapAsset(data.key, input));
|
|
}
|
|
}
|
|
}
|
|
for (const addon of await Promise.all(addonsPending)) {
|
|
if (!addon) continue;
|
|
const dir = this._resolutionKey(
|
|
unixResolve(unixResolve(addon.referrer, ".."), addon.input),
|
|
true
|
|
);
|
|
let r = resolutions[dir] = resolutions[dir] || {};
|
|
r["bare:addon"] = addon.output;
|
|
const referrer = this._resolutionKey(addon.referrer, false);
|
|
r = resolutions[referrer] = resolutions[referrer] || {};
|
|
const def = r[addon.input];
|
|
r[addon.input] = { addon: addon.output };
|
|
if (def) r[addon.input].default = def;
|
|
}
|
|
for (const asset of await Promise.all(assetsPending)) {
|
|
if (!asset) continue;
|
|
const referrer = this._resolutionKey(asset.referrer, false);
|
|
const r = resolutions[referrer] = resolutions[referrer] || {};
|
|
const def = r[asset.input];
|
|
r[asset.input] = { asset: asset.output.key };
|
|
if (def) r[asset.input].default = def;
|
|
assets[asset.output.key] = { executable: asset.output.executable, value: asset.output.value };
|
|
}
|
|
return {
|
|
entrypoint: main,
|
|
resolutions,
|
|
imports,
|
|
sources,
|
|
assets
|
|
};
|
|
}
|
|
_resolutionKey(key, dir) {
|
|
const trail = dir && !key.endsWith("/") ? "/" : "";
|
|
return this.mount ? this.mount + encodeURI(key) + trail : key + trail;
|
|
}
|
|
async _extractAssetToDisk(entry) {
|
|
const out = path.join(this.assets, entry.key);
|
|
await fs.promises.mkdir(path.dirname(out), { recursive: true });
|
|
const mode = entry.value.executable ? 484 : 420;
|
|
const driveStream = this.drive.createReadStream(entry);
|
|
const fsStream = fs.createWriteStream(out, { mode });
|
|
await pipelinePromise(driveStream, fsStream);
|
|
const key = this.absoluteFiles ? pathToFileURL(out).href : this._toRelative(out);
|
|
return { key, executable: entry.value.executable, value: null };
|
|
}
|
|
async _extractAndInlineAsset(entry) {
|
|
const value = await this.drive.get(entry);
|
|
return {
|
|
key: entry.key,
|
|
executable: entry.value.executable,
|
|
value
|
|
};
|
|
}
|
|
async extractAsset(key) {
|
|
try {
|
|
const entry = await this.drive.entry(key);
|
|
if (entry === null) return null;
|
|
if (this.inlineAssets) return await this._extractAndInlineAsset(entry);
|
|
if (hasToPath(this.drive)) {
|
|
return { key: pathToFileURL(this.drive.toPath(key)).href, executable: false, value: null };
|
|
}
|
|
return await this._extractAssetToDisk(entry);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
async extractPrebuild(key) {
|
|
const m = key.match(/\/([^/@]+)(@[^/]+)?(\.node|\.bare)$/);
|
|
if (!m) return null;
|
|
const buf = await this.drive.get(key);
|
|
if (!buf) return null;
|
|
const name = hash(buf) + m[3];
|
|
const dir = path.join(this.prebuilds, this.host);
|
|
const out = path.join(dir, name);
|
|
await writeAtomic(dir, out, buf, this.lock);
|
|
return this.absoluteFiles ? pathToFileURL(out).href : this._toRelative(out);
|
|
}
|
|
async _mapAsset(referrer, input) {
|
|
const dir = unixResolve(referrer, "..");
|
|
const key = unixResolve(dir, input);
|
|
const output = await this.extractAsset(key);
|
|
return { referrer, input, output };
|
|
}
|
|
async _mapPrebuild(referrer, input, output) {
|
|
const prebuild = await this.extractPrebuild(output);
|
|
return { referrer, input, output: prebuild };
|
|
}
|
|
_toRelative(out) {
|
|
return "/.." + unixResolve("/", path.relative(this.cwd, out));
|
|
}
|
|
};
|
|
function hash(buf) {
|
|
const out = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(out, buf);
|
|
return b4a.toString(out, "hex");
|
|
}
|
|
async function writeAtomic(dir, out, buf, lock) {
|
|
try {
|
|
await fs.promises.stat(out);
|
|
return;
|
|
} catch {
|
|
}
|
|
const release = await lock();
|
|
try {
|
|
await writeToTmpAndSwap(dir, out, buf);
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
async function writeToTmpAndSwap(dir, out, buf) {
|
|
const tmp = out + ".tmp";
|
|
await fs.promises.mkdir(dir, { recursive: true });
|
|
await fs.promises.writeFile(tmp, buf);
|
|
try {
|
|
await fs.promises.rename(tmp, out);
|
|
} catch {
|
|
await fs.promises.stat(out);
|
|
try {
|
|
await fs.promises.unlink(tmp);
|
|
} catch {
|
|
}
|
|
}
|
|
}
|
|
function hasToPath(drive) {
|
|
return typeof drive.toPath === "function";
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/bundle.js
|
|
var require_bundle = __commonJS({
|
|
"../../node_modules/bare-dev/lib/bundle.js"(exports, module) {
|
|
var fs = __require("fs/promises");
|
|
var os = __require("os");
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var pathResolve = require_unix_path_resolve();
|
|
var includeStatic = require_include_static();
|
|
var Bundle = require_bare_bundle();
|
|
var Localdrive = require_localdrive();
|
|
var DriveBundler = require_drive_bundler();
|
|
module.exports = async function bundle(entry, opts = {}) {
|
|
const {
|
|
config = null,
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
if (config) {
|
|
opts = {
|
|
...opts,
|
|
...__require(path.resolve(cwd, config))
|
|
};
|
|
}
|
|
const {
|
|
platform = os.platform(),
|
|
arch = os.arch(),
|
|
simulator = false,
|
|
out = null,
|
|
format = defaultFormat(out),
|
|
encoding = "utf8",
|
|
packages = true,
|
|
prebuilds = false,
|
|
print = false,
|
|
indent = 2
|
|
} = opts;
|
|
const host = `${platform}-${arch}${simulator ? "-simulator" : ""}`;
|
|
const drive = new Localdrive(cwd, { followLinks: true });
|
|
const bundler = new DriveBundler(drive, {
|
|
cwd,
|
|
host,
|
|
packages,
|
|
prebuilds: prebuilds && out ? path.resolve(cwd, out, "..", "prebuilds") : false,
|
|
inlineAssets: true
|
|
});
|
|
if (bundler.prebuilds) {
|
|
await fs.mkdir(bundler.prebuilds, { recursive: true });
|
|
}
|
|
entry = pathResolve("/", path.relative(cwd, entry));
|
|
let data;
|
|
switch (format) {
|
|
case "bundle":
|
|
case "bundle.js":
|
|
case "bundle.cjs":
|
|
case "bundle.mjs":
|
|
case "bundle.json":
|
|
case "bundle.h": {
|
|
const result = await bundler.bundle(entry);
|
|
const { entrypoint, resolutions, sources, assets } = result;
|
|
const bundle2 = new Bundle();
|
|
bundle2.id = DriveBundler.id(result).toString("hex");
|
|
bundle2.main = entrypoint;
|
|
bundle2.resolutions = resolutions;
|
|
for (const key in sources) {
|
|
bundle2.write(key, sources[key]);
|
|
}
|
|
for (const key in assets) {
|
|
const asset = assets[key];
|
|
bundle2.write(key, asset.value, { executable: asset.executable, asset: true });
|
|
}
|
|
data = bundle2.toBuffer({ indent });
|
|
break;
|
|
}
|
|
case "js":
|
|
case "js.h": {
|
|
const code = await bundler.stringify(entry);
|
|
data = Buffer.from(code);
|
|
break;
|
|
}
|
|
default:
|
|
throw new Error(`unknown format "${format}"`);
|
|
}
|
|
switch (format) {
|
|
case "bundle.js":
|
|
case "bundle.cjs":
|
|
data = `module.exports = ${JSON.stringify(data.toString(encoding))}
|
|
`;
|
|
break;
|
|
case "bundle.mjs":
|
|
data = `export default ${JSON.stringify(data.toString(encoding))}
|
|
`;
|
|
break;
|
|
case "bundle.json":
|
|
data = JSON.stringify(data.toString(encoding)) + "\n";
|
|
break;
|
|
case "bundle.h":
|
|
case "js.h":
|
|
data = includeStatic(defaultName(out), data);
|
|
break;
|
|
}
|
|
if (print || out) {
|
|
if (print) {
|
|
process2.stdout.write(data);
|
|
}
|
|
if (out) {
|
|
await fs.writeFile(path.resolve(cwd, out), data);
|
|
}
|
|
}
|
|
return data;
|
|
};
|
|
function defaultFormat(out) {
|
|
if (out === null) return "bundle";
|
|
if (out.endsWith(".bundle.js")) return "bundle.js";
|
|
if (out.endsWith(".bundle.cjs")) return "bundle.cjs";
|
|
if (out.endsWith(".bundle.mjs")) return "bundle.mjs";
|
|
if (out.endsWith(".bundle.json")) return "bundle.json";
|
|
if (out.endsWith(".bundle.h")) return "bundle.h";
|
|
if (out.endsWith(".js")) return "js";
|
|
if (out.endsWith(".js.h")) return "js.h";
|
|
return "bundle";
|
|
}
|
|
function defaultName(out) {
|
|
if (out === null) return "bundle";
|
|
return path.basename(out).replace(/\.h$/, "").replace(/[-.]+/g, "_").toLowerCase();
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/clean.js
|
|
var require_clean = __commonJS({
|
|
"../../node_modules/bare-dev/lib/clean.js"(exports, module) {
|
|
module.exports = function clean(opts = {}) {
|
|
try {
|
|
require_build()({ ...opts, target: "clean" });
|
|
} catch {
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/android/shared/ndk.js
|
|
var require_ndk = __commonJS({
|
|
"../../node_modules/bare-dev/lib/android/shared/ndk.js"(exports) {
|
|
var { globSync } = require_commonjs5();
|
|
var sdk = require_sdk();
|
|
exports.path = function path(version = "installed", opts = {}) {
|
|
const path2 = __require("path");
|
|
switch (version) {
|
|
case "installed": {
|
|
const candidates = globSync(path2.join(sdk.path, "ndk", "*"), {
|
|
windowsPathsNoEscape: true
|
|
});
|
|
if (candidates.length === 0) throw new Error("no Android NDK installed");
|
|
return candidates[0];
|
|
}
|
|
default:
|
|
sdk.manager.install("ndk", version, opts);
|
|
return path2.join(sdk.path, "ndk", version);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/configure.js
|
|
var require_configure = __commonJS({
|
|
"../../node_modules/bare-dev/lib/configure.js"(exports, module) {
|
|
var os = __require("os");
|
|
var path = __require("path");
|
|
var which = require_bare_which();
|
|
var spawn = require_spawn();
|
|
var cmake = require_cmake();
|
|
var paths = require_paths();
|
|
module.exports = function configure(opts = {}) {
|
|
const {
|
|
source = ".",
|
|
build = "build",
|
|
platform = os.platform(),
|
|
arch = os.arch(),
|
|
simulator = false,
|
|
cache = true,
|
|
generator = defaultGenerator(platform),
|
|
toolchain = null,
|
|
toolset = null,
|
|
sanitize = null,
|
|
debug = !!sanitize,
|
|
define = [],
|
|
cwd = path.resolve("."),
|
|
verbose
|
|
} = opts;
|
|
const args = [
|
|
"-S",
|
|
source,
|
|
"-B",
|
|
path.resolve(cwd, build)
|
|
];
|
|
if (cache === false) {
|
|
args.push("--fresh");
|
|
}
|
|
if (generator) {
|
|
args.push("-G", toGenerator(generator));
|
|
}
|
|
if (toolchain) {
|
|
args.push("--toolchain", path.resolve(cwd, toolchain));
|
|
}
|
|
if (toolset && generator && supportsToolsetSpecification(generator)) {
|
|
args.push(`-DCMAKE_GENERATOR_TOOLSET=${toToolset(toolset, generator)}`);
|
|
}
|
|
args.push(
|
|
`-DCMAKE_MESSAGE_LOG_LEVEL=${verbose ? "VERBOSE" : "NOTICE"}`,
|
|
`-DCMAKE_MODULE_PATH=${cmake.toPath(path.resolve(cwd, "cmake"))};${cmake.toPath(paths.cmake)}`,
|
|
// Export compile commands for use by external tools, such as the Clangd
|
|
// language server (https://clangd.llvm.org).
|
|
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
|
);
|
|
if (generator && supportsMultiConfiguration(generator)) {
|
|
args.push(`-DCMAKE_CONFIGURATION_TYPES=${debug ? "Debug" : "Release"}`);
|
|
} else {
|
|
args.push(`-DCMAKE_BUILD_TYPE=${debug ? "Debug" : "Release"}`);
|
|
}
|
|
args.push(`-DCMAKE_SYSTEM_NAME=${toSystemName(platform)}`);
|
|
const processor = toSystemProcessor(arch, platform);
|
|
if (platform === "darwin" || platform === "ios") {
|
|
args.push(`-DCMAKE_OSX_ARCHITECTURES=${processor}`);
|
|
} else if (platform === "android") {
|
|
args.push(`-DCMAKE_ANDROID_ARCH_ABI=${processor === "armv7-a" ? "armeabi-v7a" : processor === "aarch64" ? "arm64-v8a" : processor === "i686" ? "x86" : processor}`);
|
|
} else if (generator && supportsPlatformSpecification(generator)) {
|
|
args.push(`-DCMAKE_GENERATOR_PLATFORM=${processor}`);
|
|
} else {
|
|
args.push(`-DCMAKE_SYSTEM_PROCESSOR=${processor}`);
|
|
}
|
|
args.push(`-DCMAKE_LIBRARY_ARCHITECTURE=${arch}`);
|
|
if (platform === "darwin") {
|
|
const {
|
|
darwinDeploymentTarget
|
|
} = opts;
|
|
if (darwinDeploymentTarget) args.push(`-DCMAKE_OSX_DEPLOYMENT_TARGET=${darwinDeploymentTarget}`);
|
|
}
|
|
if (platform === "ios") {
|
|
const {
|
|
iosDeploymentTarget
|
|
} = opts;
|
|
args.push(`-DCMAKE_OSX_SYSROOT=iphone${simulator ? "simulator" : "os"}`);
|
|
if (iosDeploymentTarget) args.push(`-DCMAKE_OSX_DEPLOYMENT_TARGET=${iosDeploymentTarget}`);
|
|
}
|
|
if (platform === "android") {
|
|
const ndk = require_ndk();
|
|
const {
|
|
androidNdk,
|
|
androidApi,
|
|
androidStl = "c++_static",
|
|
androidAllowUndefinedSymbols = true
|
|
} = opts;
|
|
args.push(`-DCMAKE_ANDROID_NDK=${ndk.path(androidNdk, opts)}`);
|
|
if (androidApi) args.push(`-DCMAKE_ANDROID_API=${androidApi}`);
|
|
if (androidStl) args.push(`-DCMAKE_ANDROID_STL_TYPE=${androidStl}`);
|
|
if (androidAllowUndefinedSymbols) args.push("-DANDROID_ALLOW_UNDEFINED_SYMBOLS=ON");
|
|
}
|
|
if (platform === "win32" && generator && generator.startsWith("visual-studio")) {
|
|
args.push(`-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded${debug ? "Debug" : ""}`);
|
|
}
|
|
const compilerFlags = [];
|
|
const linkerFlags = [];
|
|
if (debug || sanitize) {
|
|
if (generator && generator.startsWith("visual-studio")) {
|
|
compilerFlags.push("/Oy-");
|
|
} else {
|
|
compilerFlags.push("-fno-omit-frame-pointer");
|
|
}
|
|
}
|
|
if (sanitize) {
|
|
if (generator && generator.startsWith("visual-studio")) {
|
|
compilerFlags.push(`/fsanitize=${sanitize}`);
|
|
} else {
|
|
compilerFlags.push(`-fsanitize=${sanitize}`);
|
|
linkerFlags.push(`-fsanitize=${sanitize}`);
|
|
}
|
|
}
|
|
if (compilerFlags.length) {
|
|
for (const type of ["C"]) {
|
|
args.push(`-DCMAKE_${type}_FLAGS=${compilerFlags.join(" ")}`);
|
|
}
|
|
}
|
|
if (linkerFlags.length) {
|
|
for (const type of ["EXE", "SHARED", "MODULE"]) {
|
|
args.push(`-DCMAKE_${type}_LINKER_FLAGS=${linkerFlags.join(" ")}`);
|
|
}
|
|
}
|
|
for (const entry of define) args.push(`-D${entry}`);
|
|
return spawn(cmake(), args, opts);
|
|
};
|
|
function supportsMultiConfiguration(generator) {
|
|
return generator === "xcode" || generator.startsWith("visual-studio");
|
|
}
|
|
function supportsToolsetSpecification(generator) {
|
|
return generator === "xcode" || generator.startsWith("visual-studio");
|
|
}
|
|
function supportsPlatformSpecification(generator) {
|
|
return generator.startsWith("visual-studio");
|
|
}
|
|
function toGenerator(generator) {
|
|
switch (generator) {
|
|
case "make":
|
|
return "Unix Makefiles";
|
|
case "ninja":
|
|
return "Ninja";
|
|
case "xcode":
|
|
return "Xcode";
|
|
case "visual-studio-2022":
|
|
return "Visual Studio 17 2022";
|
|
default:
|
|
throw new Error(`unsupported generator "${generator}"`);
|
|
}
|
|
}
|
|
function toToolset(toolset, generator) {
|
|
switch (toolset) {
|
|
case "clang-cl":
|
|
return "ClangCL";
|
|
default:
|
|
throw new Error(`unsupported toolset "${toolset}" for generator "${generator}"`);
|
|
}
|
|
}
|
|
function toSystemName(platform) {
|
|
switch (platform) {
|
|
case "darwin":
|
|
return "Darwin";
|
|
case "ios":
|
|
return "iOS";
|
|
case "linux":
|
|
return "Linux";
|
|
case "android":
|
|
return "Android";
|
|
case "win32":
|
|
return "Windows";
|
|
default:
|
|
throw new Error(`unsupported platform "${platform}"`);
|
|
}
|
|
}
|
|
function toSystemProcessor(arch, platform) {
|
|
switch (arch) {
|
|
case "arm64":
|
|
if (platform === "darwin" || platform === "ios") return "arm64";
|
|
if (platform === "linux") return "aarch64";
|
|
if (platform === "android") return "arm64-v8a";
|
|
if (platform === "win32") return "ARM64";
|
|
break;
|
|
case "arm":
|
|
if (platform === "linux") return "arm";
|
|
if (platform === "android") return "armv7-a";
|
|
break;
|
|
case "x64":
|
|
if (platform === "darwin" || platform === "ios" || platform === "linux" || platform === "android") return "x86_64";
|
|
if (platform === "win32") return "x64";
|
|
break;
|
|
case "ia32":
|
|
if (platform === "linux" || platform === "android") return "i686";
|
|
if (platform === "win32") return "X86";
|
|
break;
|
|
}
|
|
throw new Error(`unsupported architecture "${arch}" for platform "${platform}"`);
|
|
}
|
|
function defaultGenerator(platform) {
|
|
if (platform === "win32") return "visual-studio-2022";
|
|
if (has("ninja")) return "ninja";
|
|
if (platform === "darwin" || platform === "ios" || platform === "linux" || platform === "android") return "make";
|
|
return null;
|
|
function has(bin) {
|
|
return which.sync(bin, { nothrow: true }) !== null;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/dependencies.js
|
|
var require_dependencies = __commonJS({
|
|
"../../node_modules/bare-dev/lib/dependencies.js"(exports, module) {
|
|
var fs = __require("fs/promises");
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var pathResolve = require_unix_path_resolve();
|
|
var Localdrive = require_localdrive();
|
|
var DriveBundler = require_drive_bundler();
|
|
module.exports = async function bundle(entry, opts = {}) {
|
|
const {
|
|
config = null,
|
|
cwd = path.resolve("."),
|
|
quiet = true
|
|
} = opts;
|
|
if (config) {
|
|
opts = {
|
|
...opts,
|
|
...__require(path.resolve(cwd, config))
|
|
};
|
|
}
|
|
const {
|
|
packages = true,
|
|
print = false,
|
|
separator = "\n",
|
|
out = null
|
|
} = opts;
|
|
const drive = new Localdrive(cwd, { followLinks: true });
|
|
const bundler = new DriveBundler(drive, { cwd, packages, prebuilds: false });
|
|
entry = pathResolve("/", path.relative(cwd, entry));
|
|
const { sources } = await bundler.bundle(entry);
|
|
const result = Object.keys(sources).map((file) => path.join(cwd, path.normalize(file))).sort();
|
|
if (out) {
|
|
let data;
|
|
switch (path.extname(out)) {
|
|
case ".d":
|
|
data = `${path.resolve(cwd, out.replace(/\.d$/, ""))}: ${result.join(" ")}
|
|
`;
|
|
break;
|
|
default:
|
|
throw new Error(`unsupported extension "${out}"`);
|
|
}
|
|
await fs.writeFile(path.resolve(cwd, out), data);
|
|
}
|
|
if (quiet || !print) return result;
|
|
let first = true;
|
|
for (const file of result) {
|
|
let out2 = file;
|
|
if (/^\s+$/.test(separator)) {
|
|
out2 += separator;
|
|
} else {
|
|
first ? first = false : out2 = separator + out2;
|
|
}
|
|
process2.stdout.write(out2);
|
|
}
|
|
return result;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/codecs/index.js
|
|
var require_codecs = __commonJS({
|
|
"../../node_modules/codecs/index.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
module.exports = codecs;
|
|
codecs.ascii = createString("ascii");
|
|
codecs.utf8 = createString("utf-8");
|
|
codecs.hex = createString("hex");
|
|
codecs.base64 = createString("base64");
|
|
codecs.ucs2 = createString("ucs2");
|
|
codecs.utf16le = createString("utf16le");
|
|
codecs.ndjson = createJSON(true);
|
|
codecs.json = createJSON(false);
|
|
codecs.binary = {
|
|
name: "binary",
|
|
encode: function encodeBinary(obj) {
|
|
return typeof obj === "string" ? b4a.from(obj, "utf-8") : b4a.toBuffer(obj);
|
|
},
|
|
decode: function decodeBinary(buf) {
|
|
return b4a.toBuffer(buf);
|
|
}
|
|
};
|
|
function isCompactEncoding(c) {
|
|
return !!(c.encode && c.decode && c.preencode);
|
|
}
|
|
function fromCompactEncoding(c) {
|
|
return {
|
|
name: "compact-encoding",
|
|
encode: function encodeWithCompact(value) {
|
|
const state = { start: 0, end: 0, buffer: null, cache: null };
|
|
c.preencode(state, value);
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
c.encode(state, value);
|
|
return state.buffer;
|
|
},
|
|
decode: function decodeWithCompact(buffer) {
|
|
return c.decode({ start: 0, end: buffer.byteLength, buffer, cache: null });
|
|
}
|
|
};
|
|
}
|
|
function codecs(fmt, fallback) {
|
|
if (typeof fmt === "object" && fmt) {
|
|
return isCompactEncoding(fmt) ? fromCompactEncoding(fmt) : fmt;
|
|
}
|
|
switch (fmt) {
|
|
case "ndjson":
|
|
return codecs.ndjson;
|
|
case "json":
|
|
return codecs.json;
|
|
case "ascii":
|
|
return codecs.ascii;
|
|
case "utf-8":
|
|
case "utf8":
|
|
return codecs.utf8;
|
|
case "hex":
|
|
return codecs.hex;
|
|
case "base64":
|
|
return codecs.base64;
|
|
case "ucs-2":
|
|
case "ucs2":
|
|
return codecs.ucs2;
|
|
case "utf16-le":
|
|
case "utf16le":
|
|
return codecs.utf16le;
|
|
}
|
|
return fallback !== void 0 ? fallback : codecs.binary;
|
|
}
|
|
function createJSON(newline) {
|
|
return {
|
|
name: newline ? "ndjson" : "json",
|
|
encode: newline ? encodeNDJSON : encodeJSON,
|
|
decode: function decodeJSON(buf) {
|
|
return JSON.parse(b4a.toString(buf));
|
|
}
|
|
};
|
|
function encodeJSON(val) {
|
|
return b4a.from(JSON.stringify(val));
|
|
}
|
|
function encodeNDJSON(val) {
|
|
return b4a.from(JSON.stringify(val) + "\n");
|
|
}
|
|
}
|
|
function createString(type) {
|
|
return {
|
|
name: type,
|
|
encode: function encodeString(val) {
|
|
if (typeof val !== "string") val = val.toString();
|
|
return b4a.from(val, type);
|
|
},
|
|
decode: function decodeString(buf) {
|
|
return b4a.toString(buf, type);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/safety-catch/index.js
|
|
var require_safety_catch = __commonJS({
|
|
"../../node_modules/safety-catch/index.js"(exports, module) {
|
|
module.exports = safetyCatch;
|
|
function isActuallyUncaught(err) {
|
|
if (!err) return false;
|
|
return err instanceof TypeError || err instanceof SyntaxError || err instanceof ReferenceError || err instanceof EvalError || err instanceof RangeError || err instanceof URIError || err.code === "ERR_ASSERTION" || err.name === "AssertionError";
|
|
}
|
|
function throwErrorNT(err) {
|
|
queueMicrotask(() => {
|
|
throw err;
|
|
});
|
|
}
|
|
function safetyCatch(err) {
|
|
if (isActuallyUncaught(err)) {
|
|
throwErrorNT(err);
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/ready-resource/index.js
|
|
var require_ready_resource = __commonJS({
|
|
"../../node_modules/ready-resource/index.js"(exports, module) {
|
|
var EventEmitter = __require("events");
|
|
module.exports = class ReadyResource extends EventEmitter {
|
|
constructor() {
|
|
super();
|
|
this.opening = null;
|
|
this.closing = null;
|
|
this.opened = false;
|
|
this.closed = false;
|
|
}
|
|
ready() {
|
|
if (this.opening !== null) return this.opening;
|
|
this.opening = open(this);
|
|
return this.opening;
|
|
}
|
|
close() {
|
|
if (this.closing !== null) return this.closing;
|
|
this.closing = close(this);
|
|
return this.closing;
|
|
}
|
|
async _open() {
|
|
}
|
|
async _close() {
|
|
}
|
|
};
|
|
async function open(self2) {
|
|
if (self2.closing !== null) return;
|
|
try {
|
|
await self2._open();
|
|
} catch (err) {
|
|
self2.close();
|
|
throw err;
|
|
}
|
|
self2.opened = true;
|
|
self2.emit("ready");
|
|
}
|
|
async function close(self2) {
|
|
try {
|
|
if (self2.opened === false && self2.opening !== null) await self2.opening;
|
|
} catch {
|
|
}
|
|
if (self2.opened === true || self2.opening === null) await self2._close();
|
|
self2.closed = true;
|
|
self2.emit("close");
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/debounceify/index.js
|
|
var require_debounceify = __commonJS({
|
|
"../../node_modules/debounceify/index.js"(exports, module) {
|
|
module.exports = function debounce(worker, context = null) {
|
|
debounced.running = null;
|
|
return debounced;
|
|
async function debounced() {
|
|
if (debounced.running !== null) {
|
|
try {
|
|
await debounced.running;
|
|
} catch (_) {
|
|
}
|
|
}
|
|
if (debounced.running !== null) return debounced.running;
|
|
debounced.running = worker.call(context);
|
|
try {
|
|
return await debounced.running;
|
|
} finally {
|
|
debounced.running = null;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/rache/index.js
|
|
var require_rache = __commonJS({
|
|
"../../node_modules/rache/index.js"(exports, module) {
|
|
var CacheEntry = class {
|
|
constructor(key, index, map) {
|
|
this.key = key;
|
|
this.index = index;
|
|
this.map = map;
|
|
}
|
|
};
|
|
var CacheValue = class {
|
|
constructor(entry, value) {
|
|
this.entry = entry;
|
|
this.value = value;
|
|
}
|
|
};
|
|
var Rache = class _Rache {
|
|
constructor({ maxSize = 65536, parent = null } = {}) {
|
|
this.maxSize = parent?.maxSize || maxSize;
|
|
this._array = parent?._array || [];
|
|
this._map = /* @__PURE__ */ new Map();
|
|
}
|
|
static from(cache) {
|
|
return cache ? new this({ parent: cache }) : new this();
|
|
}
|
|
get globalSize() {
|
|
return this._array.length;
|
|
}
|
|
get size() {
|
|
return this._map.size;
|
|
}
|
|
sub() {
|
|
return new _Rache({ parent: this });
|
|
}
|
|
set(key, value) {
|
|
const existing = this._map.get(key);
|
|
if (existing !== void 0) {
|
|
existing.value = value;
|
|
return;
|
|
}
|
|
if (this._array.length >= this.maxSize) this._gc();
|
|
const entry = new CacheEntry(key, this._array.length, this._map);
|
|
this._array.push(entry);
|
|
const cacheValue = new CacheValue(entry, value);
|
|
this._map.set(key, cacheValue);
|
|
}
|
|
delete(key) {
|
|
const existing = this._map.get(key);
|
|
if (existing === void 0) return false;
|
|
this._delete(existing.entry.index);
|
|
return true;
|
|
}
|
|
get(key) {
|
|
const existing = this._map.get(key);
|
|
return existing === void 0 ? void 0 : existing.value;
|
|
}
|
|
*[Symbol.iterator]() {
|
|
for (const [key, { value }] of this._map) {
|
|
yield [key, value];
|
|
}
|
|
}
|
|
keys() {
|
|
return this._map.keys();
|
|
}
|
|
*values() {
|
|
for (const { value } of this._map.values()) {
|
|
yield value;
|
|
}
|
|
}
|
|
clear() {
|
|
this._map.clear();
|
|
this._map = /* @__PURE__ */ new Map();
|
|
}
|
|
destroy() {
|
|
this._map = null;
|
|
this._array = null;
|
|
}
|
|
_gc() {
|
|
this._delete(Math.floor(Math.random() * this._array.length));
|
|
}
|
|
_delete(index) {
|
|
if (index >= this._array.length) throw new Error("Cannot delete unused index (logic bug?)");
|
|
const head = this._array.pop();
|
|
let removed = head;
|
|
if (index < this._array.length) {
|
|
removed = this._array[index];
|
|
head.index = index;
|
|
this._array[index] = head;
|
|
}
|
|
removed.map.delete(removed.key);
|
|
}
|
|
};
|
|
module.exports = Rache;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/resolve-reject-promise/index.js
|
|
var require_resolve_reject_promise = __commonJS({
|
|
"../../node_modules/resolve-reject-promise/index.js"(exports, module) {
|
|
var tmpResolve = null;
|
|
var tmpReject = null;
|
|
if (Promise.withResolvers) {
|
|
module.exports = Promise.withResolvers.bind(Promise);
|
|
} else {
|
|
module.exports = function resolveRejectPromise() {
|
|
const promise = new Promise(setTmp);
|
|
const result = { promise, resolve: tmpResolve, reject: tmpReject };
|
|
tmpResolve = tmpReject = null;
|
|
return result;
|
|
};
|
|
}
|
|
function setTmp(resolve, reject) {
|
|
tmpResolve = resolve;
|
|
tmpReject = reject;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/unslab/index.js
|
|
var require_unslab = __commonJS({
|
|
"../../node_modules/unslab/index.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
unslab.all = all;
|
|
unslab.is = is;
|
|
module.exports = unslab;
|
|
function unslab(buf) {
|
|
if (buf === null || buf.buffer.byteLength === buf.byteLength) return buf;
|
|
const copy = b4a.allocUnsafeSlow(buf.byteLength);
|
|
copy.set(buf, 0);
|
|
return copy;
|
|
}
|
|
function is(buf) {
|
|
return buf.buffer.byteLength !== buf.byteLength;
|
|
}
|
|
function all(list) {
|
|
let size = 0;
|
|
for (let i = 0; i < list.length; i++) {
|
|
const buf = list[i];
|
|
size += buf === null || buf.buffer.byteLength === buf.byteLength ? 0 : buf.byteLength;
|
|
}
|
|
const copy = b4a.allocUnsafeSlow(size);
|
|
const result = new Array(list.length);
|
|
let offset = 0;
|
|
for (let i = 0; i < list.length; i++) {
|
|
let buf = list[i];
|
|
if (buf !== null && buf.buffer.byteLength !== buf.byteLength) {
|
|
copy.set(buf, offset);
|
|
buf = copy.subarray(offset, offset += buf.byteLength);
|
|
}
|
|
result[i] = buf;
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperbee/iterators/range.js
|
|
var require_range3 = __commonJS({
|
|
"../../node_modules/hyperbee/iterators/range.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
module.exports = class RangeIterator {
|
|
constructor(batch, encoding, opts = {}) {
|
|
this.batch = batch;
|
|
this.stack = [];
|
|
this.opened = false;
|
|
this.encoding = encoding || batch.encoding;
|
|
this._limit = typeof opts.limit === "number" ? opts.limit : -1;
|
|
this._gIncl = !opts.gt;
|
|
this._gKey = opts.gt || opts.gte || null;
|
|
this._lIncl = !opts.lt;
|
|
this._lKey = opts.lt || opts.lte || null;
|
|
this._reverse = !!opts.reverse;
|
|
this._version = 0;
|
|
this._checkpoint = opts.checkpoint && opts.checkpoint.length ? opts.checkpoint : null;
|
|
this._nexting = false;
|
|
this._closed = false;
|
|
}
|
|
snapshot(version = this.batch.version) {
|
|
const checkpoint = [];
|
|
for (const s of this.stack) {
|
|
let { node, i } = s;
|
|
if (this._nexting && s === this.stack[this.stack.length - 1]) {
|
|
i = this._reverse ? i + 1 : i - 1;
|
|
}
|
|
if (!node.block) continue;
|
|
if (i < 0) continue;
|
|
checkpoint.push(node.block.seq, node.offset, i);
|
|
}
|
|
return {
|
|
version,
|
|
gte: this._gIncl ? this._gKey : null,
|
|
gt: this._gIncl ? null : this._gKey,
|
|
lte: this._lIncl ? this._lKey : null,
|
|
lt: this._lIncl ? null : this._lKey,
|
|
limit: this._limit,
|
|
reverse: this._reverse,
|
|
ended: this.opened && !checkpoint.length,
|
|
checkpoint: this.opened ? checkpoint : []
|
|
};
|
|
}
|
|
async open() {
|
|
await this._open();
|
|
this.opened = true;
|
|
}
|
|
async _open() {
|
|
if (this._checkpoint) {
|
|
for (let j = 0; j < this._checkpoint.length; j += 3) {
|
|
const seq = this._checkpoint[j];
|
|
const offset = this._checkpoint[j + 1];
|
|
const i = this._checkpoint[j + 2];
|
|
this.stack.push({
|
|
node: (await this.batch.getBlock(seq)).getTreeNode(offset),
|
|
i
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
this._nexting = true;
|
|
let node = await this.batch.getRoot(false);
|
|
if (!node) {
|
|
this._nexting = false;
|
|
return;
|
|
}
|
|
const incl = this._reverse ? this._lIncl : this._gIncl;
|
|
const start = this._reverse ? this._lKey : this._gKey;
|
|
if (!start) {
|
|
this.stack.push({ node, i: this._reverse ? node.keys.length << 1 : 0 });
|
|
this._nexting = false;
|
|
this._preloadQuery();
|
|
return;
|
|
}
|
|
while (true) {
|
|
const entry = { node, i: this._reverse ? node.keys.length << 1 : 0 };
|
|
let s = 0;
|
|
let e = node.keys.length;
|
|
let c;
|
|
while (s < e) {
|
|
const mid = s + e >> 1;
|
|
c = b4a.compare(start, await node.getKey(mid));
|
|
if (c === 0) {
|
|
if (incl) entry.i = mid * 2 + 1;
|
|
else entry.i = mid * 2 + (this._reverse ? 0 : 2);
|
|
this.stack.push(entry);
|
|
this._nexting = false;
|
|
this._preloadQuery();
|
|
return;
|
|
}
|
|
if (c < 0) e = mid;
|
|
else s = mid + 1;
|
|
}
|
|
const i = c < 0 ? e : s;
|
|
entry.i = 2 * i + (this._reverse ? -1 : 1);
|
|
if (entry.i >= 0 && entry.i <= node.keys.length << 1) this.stack.push(entry);
|
|
if (!node.children.length) {
|
|
this._nexting = false;
|
|
this._preloadQuery();
|
|
return;
|
|
}
|
|
node = await node.getChildNode(i);
|
|
}
|
|
}
|
|
_preloadQuery() {
|
|
const max = { nodes: 0, max: 2048 };
|
|
if (this._limit === -1 && !this._reverse && this.stack.length) {
|
|
for (const s of this.stack) {
|
|
const k = (s.i - (s.i & 1)) / 2;
|
|
this._preload(s.node, k + 1, this._lKey, max).catch(noop);
|
|
}
|
|
}
|
|
}
|
|
async _preload(node, i, end, max) {
|
|
for (; i < node.keys.length; i++) {
|
|
const key = node.keys[i];
|
|
const block = await this.batch.getBlock(key.seq);
|
|
if (this._closed) return;
|
|
const c = end ? b4a.compare(block.key, end) : -1;
|
|
if (c >= 0 || max.nodes >= max.max || i >= node.children.length) return;
|
|
max.nodes++;
|
|
const next = await node.getChildNode(i);
|
|
if (this._closed) return;
|
|
this._preload(next, 0, end, max).catch(noop);
|
|
}
|
|
if (node.children.length && max.nodes < max.max) {
|
|
const next = await node.getChildNode(node.children.length - 1);
|
|
if (this._closed) return;
|
|
this._preload(next, 0, end, max).catch(noop);
|
|
}
|
|
}
|
|
async next() {
|
|
this._nexting = true;
|
|
const end = this._reverse ? this._gKey : this._lKey;
|
|
const incl = this._reverse ? this._gIncl : this._lIncl;
|
|
while (this.stack.length && (this._limit === -1 || this._limit > 0)) {
|
|
const top = this.stack[this.stack.length - 1];
|
|
const isKey = (top.i & 1) === 1;
|
|
const n = this._reverse ? top.i < 0 ? top.node.keys.length : top.i-- >> 1 : top.i++ >> 1;
|
|
if (!isKey) {
|
|
if (!top.node.children.length) continue;
|
|
const node = await top.node.getChildNode(n);
|
|
if (top.node.block.seq < this.batch.core.length) {
|
|
top.node.children[n].value = null;
|
|
}
|
|
this.stack.push({ i: this._reverse ? node.keys.length << 1 : 0, node });
|
|
continue;
|
|
}
|
|
if (n >= top.node.keys.length) {
|
|
this.stack.pop();
|
|
continue;
|
|
}
|
|
const key = top.node.keys[n];
|
|
const block = await this.batch.getBlock(key.seq);
|
|
if (end) {
|
|
const c = b4a.compare(block.key, end);
|
|
if (c === 0 ? !incl : this._reverse ? c < 0 : c > 0) {
|
|
this._limit = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (this._limit > 0) this._limit--;
|
|
this._nexting = false;
|
|
return block.final(this.encoding);
|
|
}
|
|
this._nexting = false;
|
|
return null;
|
|
}
|
|
close() {
|
|
this._closed = true;
|
|
return this.batch._closeSnapshot();
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperbee/iterators/history.js
|
|
var require_history = __commonJS({
|
|
"../../node_modules/hyperbee/iterators/history.js"(exports, module) {
|
|
module.exports = class HistoryIterator {
|
|
constructor(batch, opts = {}) {
|
|
this.batch = batch;
|
|
this.options = opts;
|
|
this.live = !!opts.live;
|
|
this.gte = 0;
|
|
this.lt = 0;
|
|
this.reverse = !!opts.reverse;
|
|
this.limit = typeof opts.limit === "number" ? opts.limit : -1;
|
|
this.encoding = opts.encoding || batch.encoding;
|
|
if (this.live && this.reverse) {
|
|
throw new Error("Cannot have both live and reverse enabled");
|
|
}
|
|
}
|
|
async open() {
|
|
await this.batch.getRoot(false);
|
|
this.gte = gte(this.options, this.batch.version);
|
|
this.lt = this.live ? Infinity : lt(this.options, this.batch.version);
|
|
}
|
|
async next() {
|
|
if (this.limit === 0) return null;
|
|
if (this.limit > 0) this.limit--;
|
|
if (this.gte >= this.lt) return null;
|
|
if (this.reverse) {
|
|
if (this.lt <= 1) return null;
|
|
return final(await this.batch.getBlock(--this.lt), this.encoding);
|
|
}
|
|
return final(await this.batch.getBlock(this.gte++), this.encoding);
|
|
}
|
|
close() {
|
|
return this.batch._closeSnapshot();
|
|
}
|
|
};
|
|
function final(node, encoding) {
|
|
const type = node.isDeletion() ? "del" : "put";
|
|
return { type, ...node.final(encoding) };
|
|
}
|
|
function gte(opts, version) {
|
|
if (opts.gt) return (opts.gt < 0 ? opts.gt + version : opts.gt) + 1;
|
|
const gte2 = opts.gte || opts.since || 1;
|
|
return gte2 < 0 ? gte2 + version : gte2;
|
|
}
|
|
function lt(opts, version) {
|
|
if (opts.lte === 0 || opts.lt === 0 || opts.end === 0) return 0;
|
|
if (opts.lte) return (opts.lte < 0 ? opts.lte + version : opts.lte) + 1;
|
|
const lt2 = opts.lt || opts.end || version;
|
|
return lt2 < 0 ? lt2 + version : lt2;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperbee/iterators/diff.js
|
|
var require_diff = __commonJS({
|
|
"../../node_modules/hyperbee/iterators/diff.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var SubTree = class {
|
|
constructor(node, parent) {
|
|
this.node = node;
|
|
this.parent = parent;
|
|
this.isKey = node.children.length === 0;
|
|
this.i = this.isKey ? 1 : 0;
|
|
this.n = 0;
|
|
const child = this.isKey ? null : this.node.children[0];
|
|
this.seq = child !== null ? child.seq : this.node.keys[0].seq;
|
|
this.offset = child !== null ? child.offset : 0;
|
|
}
|
|
next() {
|
|
this.i++;
|
|
this.isKey = (this.i & 1) === 1;
|
|
if (!this.isKey && !this.node.children.length) this.i++;
|
|
return this.update();
|
|
}
|
|
async bisect(key, incl) {
|
|
let s = 0;
|
|
let e = this.node.keys.length;
|
|
let c;
|
|
while (s < e) {
|
|
const mid = s + e >> 1;
|
|
c = cmp(key, await this.node.getKey(mid));
|
|
if (c === 0) {
|
|
if (incl) this.i = mid * 2 + 1;
|
|
else this.i = mid * 2 + (this.node.children.length ? 2 : 3);
|
|
return true;
|
|
}
|
|
if (c < 0) e = mid;
|
|
else s = mid + 1;
|
|
}
|
|
const i = c < 0 ? e : s;
|
|
this.i = 2 * i + (this.node.children.length ? 0 : 1);
|
|
return this.node.children.length === 0;
|
|
}
|
|
update() {
|
|
this.isKey = (this.i & 1) === 1;
|
|
this.n = this.i >> 1;
|
|
if (this.n >= (this.isKey ? this.node.keys.length : this.node.children.length)) return false;
|
|
const child = this.isKey ? null : this.node.children[this.n];
|
|
this.seq = child !== null ? child.seq : this.node.keys[this.n].seq;
|
|
this.offset = child !== null ? child.offset : 0;
|
|
return true;
|
|
}
|
|
async key() {
|
|
return this.n < this.node.keys.length ? this.node.getKey(this.n) : this.parent && this.parent.key();
|
|
}
|
|
async compare(tree) {
|
|
const [a, b] = await Promise.all([this.key(), tree.key()]);
|
|
return cmp(a, b);
|
|
}
|
|
};
|
|
var TreeIterator = class {
|
|
constructor(batch, opts) {
|
|
this.batch = batch;
|
|
this.stack = [];
|
|
this.lt = opts.lt || opts.lte || null;
|
|
this.lte = !!opts.lte;
|
|
this.gt = opts.gt || opts.gte || null;
|
|
this.gte = !!opts.gte;
|
|
this.seeking = !!this.gt;
|
|
this.encoding = opts.encoding || batch.encoding;
|
|
}
|
|
async open() {
|
|
const node = await this.batch.getRoot(false);
|
|
if (!node || !node.keys.length) return;
|
|
const tree = new SubTree(node, null);
|
|
if (this.seeking && !await this._seek(tree)) return;
|
|
this.stack.push(tree);
|
|
}
|
|
async _seek(tree) {
|
|
const done = await tree.bisect(this.gt, this.gte);
|
|
const oob = !tree.update();
|
|
if (done || oob) {
|
|
this.seeking = false;
|
|
if (oob) return false;
|
|
}
|
|
return true;
|
|
}
|
|
peek() {
|
|
if (!this.stack.length) return null;
|
|
return this.stack[this.stack.length - 1];
|
|
}
|
|
skip() {
|
|
if (!this.stack.length) return;
|
|
if (!this.stack[this.stack.length - 1].next()) this.stack.pop();
|
|
}
|
|
async nextKey() {
|
|
let n = null;
|
|
while (this.stack.length && n === null) n = await this.next();
|
|
if (n === null) return null;
|
|
if (!this.lt) return n.final(this.encoding);
|
|
const c = cmp(n.key, this.lt);
|
|
if (this.lte ? c <= 0 : c < 0) return n.final(this.encoding);
|
|
this.stack = [];
|
|
return null;
|
|
}
|
|
async next() {
|
|
if (!this.stack.length) return null;
|
|
const top = this.stack[this.stack.length - 1];
|
|
const { isKey, n, seq } = top;
|
|
if (!top.next()) {
|
|
this.stack.pop();
|
|
}
|
|
if (isKey) {
|
|
this.seeking = false;
|
|
return this.batch.getBlock(seq);
|
|
}
|
|
const child = await top.node.getChildNode(n);
|
|
top.node.children[n] = null;
|
|
const tree = new SubTree(child, top);
|
|
if (this.seeking && !await this._seek(tree)) return null;
|
|
this.stack.push(tree);
|
|
return null;
|
|
}
|
|
close() {
|
|
return this.batch._closeSnapshot();
|
|
}
|
|
};
|
|
module.exports = class DiffIterator {
|
|
constructor(left, right, opts = {}) {
|
|
this.left = new TreeIterator(left, opts);
|
|
this.right = new TreeIterator(right, opts);
|
|
this.limit = typeof opts.limit === "number" ? opts.limit : -1;
|
|
}
|
|
async open() {
|
|
await Promise.all([this.left.open(), this.right.open()]);
|
|
}
|
|
async next() {
|
|
if (this.limit === 0) return null;
|
|
const res = await this._next();
|
|
if (!res || res.left === null && res.right === null) return null;
|
|
this.limit--;
|
|
return res;
|
|
}
|
|
async _next() {
|
|
const a = this.left;
|
|
const b = this.right;
|
|
while (true) {
|
|
const [l, r] = await Promise.all([a.peek(), b.peek()]);
|
|
if (!l && !r) return null;
|
|
if (!l) return { left: null, right: await b.nextKey() };
|
|
if (!r) return { left: await a.nextKey(), right: null };
|
|
if (l.seq === r.seq && l.isKey === r.isKey && l.offset === r.offset) {
|
|
a.skip();
|
|
b.skip();
|
|
continue;
|
|
}
|
|
const c = await l.compare(r);
|
|
if (l.isKey && !r.isKey) {
|
|
await b.next();
|
|
continue;
|
|
}
|
|
if (!l.isKey && r.isKey) {
|
|
await a.next();
|
|
continue;
|
|
}
|
|
if (l.isKey && r.isKey) {
|
|
if (c === 0) return { left: await a.nextKey(), right: await b.nextKey() };
|
|
if (c < 0) return { left: await a.nextKey(), right: null };
|
|
return { left: null, right: await b.nextKey() };
|
|
}
|
|
if (c === 0) await Promise.all([a.next(), b.next()]);
|
|
else if (c < 0) await b.next();
|
|
else await a.next();
|
|
}
|
|
}
|
|
async close() {
|
|
await Promise.all([this.left.close(), this.right.close()]);
|
|
}
|
|
};
|
|
function cmp(a, b) {
|
|
if (!a) return b ? 1 : 0;
|
|
if (!b) return a ? -1 : 0;
|
|
return b4a.compare(a, b);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperbee/iterators/local.js
|
|
var require_local = __commonJS({
|
|
"../../node_modules/hyperbee/iterators/local.js"(exports, module) {
|
|
module.exports = class LocalBlocksIterator {
|
|
constructor(batch, opts = {}) {
|
|
this.batch = batch;
|
|
this.options = opts;
|
|
this.gte = 0;
|
|
this.lt = 0;
|
|
this.limit = typeof opts.limit === "number" ? opts.limit : -1;
|
|
}
|
|
async open() {
|
|
await this.batch.getRoot(false);
|
|
this.gte = gte(this.options, this.batch.version);
|
|
this.lt = lt(this.options, this.batch.version);
|
|
}
|
|
async next() {
|
|
if (this.limit === 0) return null;
|
|
if (this.limit > 0) this.limit--;
|
|
while (this.gte < this.lt) {
|
|
try {
|
|
return await this.batch.getBlock(this.gte++);
|
|
} catch {
|
|
continue;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
close() {
|
|
return this.batch._closeSnapshot();
|
|
}
|
|
};
|
|
function gte(opts, version) {
|
|
if (opts.gt) return (opts.gt < 0 ? opts.gt + version : opts.gt) + 1;
|
|
const gte2 = opts.gte || opts.since || 1;
|
|
return gte2 < 0 ? gte2 + version : gte2;
|
|
}
|
|
function lt(opts, version) {
|
|
if (opts.lte === 0 || opts.lt === 0 || opts.end === 0) return 0;
|
|
if (opts.lte) return (opts.lte < 0 ? opts.lte + version : opts.lte) + 1;
|
|
const lt2 = opts.lt || opts.end || version;
|
|
return lt2 < 0 ? lt2 + version : lt2;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/varint/encode.js
|
|
var require_encode = __commonJS({
|
|
"../../node_modules/varint/encode.js"(exports, module) {
|
|
module.exports = encode;
|
|
var MSB = 128;
|
|
var REST = 127;
|
|
var MSBALL = ~REST;
|
|
var INT = Math.pow(2, 31);
|
|
function encode(num, out, offset) {
|
|
out = out || [];
|
|
offset = offset || 0;
|
|
var oldOffset = offset;
|
|
while (num >= INT) {
|
|
out[offset++] = num & 255 | MSB;
|
|
num /= 128;
|
|
}
|
|
while (num & MSBALL) {
|
|
out[offset++] = num & 255 | MSB;
|
|
num >>>= 7;
|
|
}
|
|
out[offset] = num | 0;
|
|
encode.bytes = offset - oldOffset + 1;
|
|
return out;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/varint/decode.js
|
|
var require_decode = __commonJS({
|
|
"../../node_modules/varint/decode.js"(exports, module) {
|
|
module.exports = read;
|
|
var MSB = 128;
|
|
var REST = 127;
|
|
function read(buf, offset) {
|
|
var res = 0, offset = offset || 0, shift = 0, counter = offset, b, l = buf.length;
|
|
do {
|
|
if (counter >= l) {
|
|
read.bytes = 0;
|
|
throw new RangeError("Could not decode varint");
|
|
}
|
|
b = buf[counter++];
|
|
res += shift < 28 ? (b & REST) << shift : (b & REST) * Math.pow(2, shift);
|
|
shift += 7;
|
|
} while (b >= MSB);
|
|
read.bytes = counter - offset;
|
|
return res;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/varint/length.js
|
|
var require_length = __commonJS({
|
|
"../../node_modules/varint/length.js"(exports, module) {
|
|
var N1 = Math.pow(2, 7);
|
|
var N2 = Math.pow(2, 14);
|
|
var N3 = Math.pow(2, 21);
|
|
var N4 = Math.pow(2, 28);
|
|
var N5 = Math.pow(2, 35);
|
|
var N6 = Math.pow(2, 42);
|
|
var N7 = Math.pow(2, 49);
|
|
var N8 = Math.pow(2, 56);
|
|
var N9 = Math.pow(2, 63);
|
|
module.exports = function(value) {
|
|
return value < N1 ? 1 : value < N2 ? 2 : value < N3 ? 3 : value < N4 ? 4 : value < N5 ? 5 : value < N6 ? 6 : value < N7 ? 7 : value < N8 ? 8 : value < N9 ? 9 : 10;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/varint/index.js
|
|
var require_varint = __commonJS({
|
|
"../../node_modules/varint/index.js"(exports, module) {
|
|
module.exports = {
|
|
encode: require_encode(),
|
|
decode: require_decode(),
|
|
encodingLength: require_length()
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/signed-varint/index.js
|
|
var require_signed_varint = __commonJS({
|
|
"../../node_modules/signed-varint/index.js"(exports) {
|
|
var varint = require_varint();
|
|
exports.encode = function encode(v, b, o) {
|
|
v = v >= 0 ? v * 2 : v * -2 - 1;
|
|
var r = varint.encode(v, b, o);
|
|
encode.bytes = varint.encode.bytes;
|
|
return r;
|
|
};
|
|
exports.decode = function decode(b, o) {
|
|
var v = varint.decode(b, o);
|
|
decode.bytes = varint.decode.bytes;
|
|
return v & 1 ? (v + 1) / -2 : v / 2;
|
|
};
|
|
exports.encodingLength = function(v) {
|
|
return varint.encodingLength(v >= 0 ? v * 2 : v * -2 - 1);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/protocol-buffers-encodings/index.js
|
|
var require_protocol_buffers_encodings = __commonJS({
|
|
"../../node_modules/protocol-buffers-encodings/index.js"(exports) {
|
|
var varint = require_varint();
|
|
var svarint = require_signed_varint();
|
|
var b4a = require_b4a();
|
|
exports.make = encoder;
|
|
exports.name = function(enc) {
|
|
var keys = Object.keys(exports);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
if (exports[keys[i]] === enc) return keys[i];
|
|
}
|
|
return null;
|
|
};
|
|
exports.skip = function(type, buffer, offset) {
|
|
switch (type) {
|
|
case 0:
|
|
varint.decode(buffer, offset);
|
|
return offset + varint.decode.bytes;
|
|
case 1:
|
|
return offset + 8;
|
|
case 2:
|
|
var len = varint.decode(buffer, offset);
|
|
return offset + varint.decode.bytes + len;
|
|
case 3:
|
|
case 4:
|
|
throw new Error("Groups are not supported");
|
|
case 5:
|
|
return offset + 4;
|
|
}
|
|
throw new Error("Unknown wire type: " + type);
|
|
};
|
|
exports.bytes = encoder(
|
|
2,
|
|
function encode(val, buffer, offset) {
|
|
var oldOffset = offset;
|
|
var len = bufferLength(val);
|
|
varint.encode(len, buffer, offset);
|
|
offset += varint.encode.bytes;
|
|
if (b4a.isBuffer(val)) b4a.copy(val, buffer, offset);
|
|
else b4a.write(buffer, val, offset, len);
|
|
offset += len;
|
|
encode.bytes = offset - oldOffset;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var oldOffset = offset;
|
|
var len = varint.decode(buffer, offset);
|
|
offset += varint.decode.bytes;
|
|
var val = buffer.subarray(offset, offset + len);
|
|
offset += val.length;
|
|
decode.bytes = offset - oldOffset;
|
|
return val;
|
|
},
|
|
function encodingLength(val) {
|
|
var len = bufferLength(val);
|
|
return varint.encodingLength(len) + len;
|
|
}
|
|
);
|
|
exports.string = encoder(
|
|
2,
|
|
function encode(val, buffer, offset) {
|
|
var oldOffset = offset;
|
|
var len = b4a.byteLength(val);
|
|
varint.encode(len, buffer, offset, "utf-8");
|
|
offset += varint.encode.bytes;
|
|
b4a.write(buffer, val, offset, len);
|
|
offset += len;
|
|
encode.bytes = offset - oldOffset;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var oldOffset = offset;
|
|
var len = varint.decode(buffer, offset);
|
|
offset += varint.decode.bytes;
|
|
var val = b4a.toString(buffer, "utf-8", offset, offset + len);
|
|
offset += len;
|
|
decode.bytes = offset - oldOffset;
|
|
return val;
|
|
},
|
|
function encodingLength(val) {
|
|
var len = b4a.byteLength(val);
|
|
return varint.encodingLength(len) + len;
|
|
}
|
|
);
|
|
exports.bool = encoder(
|
|
0,
|
|
function encode(val, buffer, offset) {
|
|
buffer[offset] = val ? 1 : 0;
|
|
encode.bytes = 1;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var bool = buffer[offset] > 0;
|
|
decode.bytes = 1;
|
|
return bool;
|
|
},
|
|
function encodingLength() {
|
|
return 1;
|
|
}
|
|
);
|
|
exports.int32 = encoder(
|
|
0,
|
|
function encode(val, buffer, offset) {
|
|
varint.encode(val < 0 ? val + 4294967296 : val, buffer, offset);
|
|
encode.bytes = varint.encode.bytes;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var val = varint.decode(buffer, offset);
|
|
decode.bytes = varint.decode.bytes;
|
|
return val > 2147483647 ? val - 4294967296 : val;
|
|
},
|
|
function encodingLength(val) {
|
|
return varint.encodingLength(val < 0 ? val + 4294967296 : val);
|
|
}
|
|
);
|
|
exports.int64 = encoder(
|
|
0,
|
|
function encode(val, buffer, offset) {
|
|
if (val < 0) {
|
|
var last = offset + 9;
|
|
varint.encode(val * -1, buffer, offset);
|
|
offset += varint.encode.bytes - 1;
|
|
buffer[offset] = buffer[offset] | 128;
|
|
while (offset < last - 1) {
|
|
offset++;
|
|
buffer[offset] = 255;
|
|
}
|
|
buffer[last] = 1;
|
|
encode.bytes = 10;
|
|
} else {
|
|
varint.encode(val, buffer, offset);
|
|
encode.bytes = varint.encode.bytes;
|
|
}
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var val = varint.decode(buffer, offset);
|
|
if (val >= Math.pow(2, 63)) {
|
|
var limit = 9;
|
|
while (buffer[offset + limit - 1] === 255) limit--;
|
|
limit = limit || 9;
|
|
var subset = b4a.allocUnsafe(limit);
|
|
b4a.copy(buffer, subset, 0, offset, offset + limit);
|
|
subset[limit - 1] = subset[limit - 1] & 127;
|
|
val = -1 * varint.decode(subset, 0);
|
|
decode.bytes = 10;
|
|
} else {
|
|
decode.bytes = varint.decode.bytes;
|
|
}
|
|
return val;
|
|
},
|
|
function encodingLength(val) {
|
|
return val < 0 ? 10 : varint.encodingLength(val);
|
|
}
|
|
);
|
|
exports.sint32 = exports.sint64 = encoder(
|
|
0,
|
|
svarint.encode,
|
|
svarint.decode,
|
|
svarint.encodingLength
|
|
);
|
|
exports.uint32 = exports.uint64 = exports.enum = exports.varint = encoder(
|
|
0,
|
|
varint.encode,
|
|
varint.decode,
|
|
varint.encodingLength
|
|
);
|
|
exports.fixed64 = exports.sfixed64 = encoder(
|
|
1,
|
|
function encode(val, buffer, offset) {
|
|
b4a.copy(val, buffer, offset);
|
|
encode.bytes = 8;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var val = buffer.subarray(offset, offset + 8);
|
|
decode.bytes = 8;
|
|
return val;
|
|
},
|
|
function encodingLength() {
|
|
return 8;
|
|
}
|
|
);
|
|
exports.double = encoder(
|
|
1,
|
|
function encode(val, buffer, offset) {
|
|
b4a.writeDoubleLE(buffer, val, offset);
|
|
encode.bytes = 8;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var val = b4a.readDoubleLE(buffer, offset);
|
|
decode.bytes = 8;
|
|
return val;
|
|
},
|
|
function encodingLength() {
|
|
return 8;
|
|
}
|
|
);
|
|
exports.fixed32 = encoder(
|
|
5,
|
|
function encode(val, buffer, offset) {
|
|
b4a.writeUInt32LE(buffer, val, offset);
|
|
encode.bytes = 4;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var val = b4a.readUInt32LE(buffer, offset);
|
|
decode.bytes = 4;
|
|
return val;
|
|
},
|
|
function encodingLength() {
|
|
return 4;
|
|
}
|
|
);
|
|
exports.sfixed32 = encoder(
|
|
5,
|
|
function encode(val, buffer, offset) {
|
|
b4a.writeInt32LE(buffer, val, offset);
|
|
encode.bytes = 4;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var val = b4a.readInt32LE(buffer, offset);
|
|
decode.bytes = 4;
|
|
return val;
|
|
},
|
|
function encodingLength() {
|
|
return 4;
|
|
}
|
|
);
|
|
exports.float = encoder(
|
|
5,
|
|
function encode(val, buffer, offset) {
|
|
b4a.writeFloatLE(buffer, val, offset);
|
|
encode.bytes = 4;
|
|
return buffer;
|
|
},
|
|
function decode(buffer, offset) {
|
|
var val = b4a.readFloatLE(buffer, offset);
|
|
decode.bytes = 4;
|
|
return val;
|
|
},
|
|
function encodingLength() {
|
|
return 4;
|
|
}
|
|
);
|
|
function encoder(type, encode, decode, encodingLength) {
|
|
encode.bytes = decode.bytes = 0;
|
|
return {
|
|
type,
|
|
encode,
|
|
decode,
|
|
encodingLength
|
|
};
|
|
}
|
|
function bufferLength(val) {
|
|
return b4a.isBuffer(val) ? val.length : b4a.byteLength(val);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperbee/lib/messages.js
|
|
var require_messages = __commonJS({
|
|
"../../node_modules/hyperbee/lib/messages.js"(exports) {
|
|
var encodings = require_protocol_buffers_encodings();
|
|
var b4a = require_b4a();
|
|
var varint = encodings.varint;
|
|
var skip = encodings.skip;
|
|
var YoloIndex = exports.YoloIndex = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
var Header = exports.Header = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
var Node = exports.Node = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
var Extension = exports.Extension = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
defineYoloIndex();
|
|
defineHeader();
|
|
defineNode();
|
|
defineExtension();
|
|
function defineYoloIndex() {
|
|
var Level = YoloIndex.Level = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
defineLevel();
|
|
function defineLevel() {
|
|
Level.encodingLength = encodingLength2;
|
|
Level.encode = encode2;
|
|
Level.decode = decode2;
|
|
function encodingLength2(obj) {
|
|
var length = 0;
|
|
if (defined(obj.keys)) {
|
|
var packedLen = 0;
|
|
for (var i = 0; i < obj.keys.length; i++) {
|
|
if (!defined(obj.keys[i])) continue;
|
|
var len = encodings.varint.encodingLength(obj.keys[i]);
|
|
packedLen += len;
|
|
}
|
|
if (packedLen) {
|
|
length += 1 + packedLen + varint.encodingLength(packedLen);
|
|
}
|
|
}
|
|
if (defined(obj.children)) {
|
|
var packedLen = 0;
|
|
for (var i = 0; i < obj.children.length; i++) {
|
|
if (!defined(obj.children[i])) continue;
|
|
var len = encodings.varint.encodingLength(obj.children[i]);
|
|
packedLen += len;
|
|
}
|
|
if (packedLen) {
|
|
length += 1 + packedLen + varint.encodingLength(packedLen);
|
|
}
|
|
}
|
|
return length;
|
|
}
|
|
function encode2(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength2(obj));
|
|
var oldOffset = offset;
|
|
if (defined(obj.keys)) {
|
|
var packedLen = 0;
|
|
for (var i = 0; i < obj.keys.length; i++) {
|
|
if (!defined(obj.keys[i])) continue;
|
|
packedLen += encodings.varint.encodingLength(obj.keys[i]);
|
|
}
|
|
if (packedLen) {
|
|
buf[offset++] = 10;
|
|
varint.encode(packedLen, buf, offset);
|
|
offset += varint.encode.bytes;
|
|
}
|
|
for (var i = 0; i < obj.keys.length; i++) {
|
|
if (!defined(obj.keys[i])) continue;
|
|
encodings.varint.encode(obj.keys[i], buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
}
|
|
}
|
|
if (defined(obj.children)) {
|
|
var packedLen = 0;
|
|
for (var i = 0; i < obj.children.length; i++) {
|
|
if (!defined(obj.children[i])) continue;
|
|
packedLen += encodings.varint.encodingLength(obj.children[i]);
|
|
}
|
|
if (packedLen) {
|
|
buf[offset++] = 18;
|
|
varint.encode(packedLen, buf, offset);
|
|
offset += varint.encode.bytes;
|
|
}
|
|
for (var i = 0; i < obj.children.length; i++) {
|
|
if (!defined(obj.children[i])) continue;
|
|
encodings.varint.encode(obj.children[i], buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
}
|
|
}
|
|
encode2.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode2(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
keys: [],
|
|
children: []
|
|
};
|
|
while (true) {
|
|
if (end <= offset) {
|
|
decode2.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
var packedEnd = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
packedEnd += offset;
|
|
while (offset < packedEnd) {
|
|
obj.keys.push(encodings.varint.decode(buf, offset));
|
|
offset += encodings.varint.decode.bytes;
|
|
}
|
|
break;
|
|
case 2:
|
|
var packedEnd = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
packedEnd += offset;
|
|
while (offset < packedEnd) {
|
|
obj.children.push(encodings.varint.decode(buf, offset));
|
|
offset += encodings.varint.decode.bytes;
|
|
}
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
YoloIndex.encodingLength = encodingLength;
|
|
YoloIndex.encode = encode;
|
|
YoloIndex.decode = decode;
|
|
function encodingLength(obj) {
|
|
var length = 0;
|
|
if (defined(obj.levels)) {
|
|
for (var i = 0; i < obj.levels.length; i++) {
|
|
if (!defined(obj.levels[i])) continue;
|
|
var len = Level.encodingLength(obj.levels[i]);
|
|
length += varint.encodingLength(len);
|
|
length += 1 + len;
|
|
}
|
|
}
|
|
return length;
|
|
}
|
|
function encode(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength(obj));
|
|
var oldOffset = offset;
|
|
if (defined(obj.levels)) {
|
|
for (var i = 0; i < obj.levels.length; i++) {
|
|
if (!defined(obj.levels[i])) continue;
|
|
buf[offset++] = 10;
|
|
varint.encode(Level.encodingLength(obj.levels[i]), buf, offset);
|
|
offset += varint.encode.bytes;
|
|
Level.encode(obj.levels[i], buf, offset);
|
|
offset += Level.encode.bytes;
|
|
}
|
|
}
|
|
encode.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
levels: []
|
|
};
|
|
while (true) {
|
|
if (end <= offset) {
|
|
decode.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
var len = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
obj.levels.push(Level.decode(buf, offset, offset + len));
|
|
offset += Level.decode.bytes;
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function defineHeader() {
|
|
var Metadata = Header.Metadata = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
defineMetadata();
|
|
function defineMetadata() {
|
|
Metadata.encodingLength = encodingLength2;
|
|
Metadata.encode = encode2;
|
|
Metadata.decode = decode2;
|
|
function encodingLength2(obj) {
|
|
var length = 0;
|
|
if (defined(obj.contentFeed)) {
|
|
var len = encodings.bytes.encodingLength(obj.contentFeed);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.userData)) {
|
|
var len = encodings.bytes.encodingLength(obj.userData);
|
|
length += 1 + len;
|
|
}
|
|
return length;
|
|
}
|
|
function encode2(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength2(obj));
|
|
var oldOffset = offset;
|
|
if (defined(obj.contentFeed)) {
|
|
buf[offset++] = 10;
|
|
encodings.bytes.encode(obj.contentFeed, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
}
|
|
if (defined(obj.userData)) {
|
|
buf[offset++] = 18;
|
|
encodings.bytes.encode(obj.userData, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
}
|
|
encode2.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode2(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
contentFeed: null,
|
|
userData: null
|
|
};
|
|
while (true) {
|
|
if (end <= offset) {
|
|
decode2.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
obj.contentFeed = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
break;
|
|
case 2:
|
|
obj.userData = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Header.encodingLength = encodingLength;
|
|
Header.encode = encode;
|
|
Header.decode = decode;
|
|
function encodingLength(obj) {
|
|
var length = 0;
|
|
if (!defined(obj.protocol)) throw new Error("protocol is required");
|
|
var len = encodings.string.encodingLength(obj.protocol);
|
|
length += 1 + len;
|
|
if (defined(obj.metadata)) {
|
|
var len = Metadata.encodingLength(obj.metadata);
|
|
length += varint.encodingLength(len);
|
|
length += 1 + len;
|
|
}
|
|
return length;
|
|
}
|
|
function encode(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength(obj));
|
|
var oldOffset = offset;
|
|
if (!defined(obj.protocol)) throw new Error("protocol is required");
|
|
buf[offset++] = 10;
|
|
encodings.string.encode(obj.protocol, buf, offset);
|
|
offset += encodings.string.encode.bytes;
|
|
if (defined(obj.metadata)) {
|
|
buf[offset++] = 18;
|
|
varint.encode(Metadata.encodingLength(obj.metadata), buf, offset);
|
|
offset += varint.encode.bytes;
|
|
Metadata.encode(obj.metadata, buf, offset);
|
|
offset += Metadata.encode.bytes;
|
|
}
|
|
encode.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
protocol: "",
|
|
metadata: null
|
|
};
|
|
var found0 = false;
|
|
while (true) {
|
|
if (end <= offset) {
|
|
if (!found0) throw new Error("Decoded message is not valid");
|
|
decode.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
obj.protocol = encodings.string.decode(buf, offset);
|
|
offset += encodings.string.decode.bytes;
|
|
found0 = true;
|
|
break;
|
|
case 2:
|
|
var len = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
obj.metadata = Metadata.decode(buf, offset, offset + len);
|
|
offset += Metadata.decode.bytes;
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function defineNode() {
|
|
Node.encodingLength = encodingLength;
|
|
Node.encode = encode;
|
|
Node.decode = decode;
|
|
function encodingLength(obj) {
|
|
var length = 0;
|
|
if (!defined(obj.index)) throw new Error("index is required");
|
|
var len = encodings.bytes.encodingLength(obj.index);
|
|
length += 1 + len;
|
|
if (!defined(obj.key)) throw new Error("key is required");
|
|
var len = encodings.bytes.encodingLength(obj.key);
|
|
length += 1 + len;
|
|
if (defined(obj.value)) {
|
|
var len = encodings.bytes.encodingLength(obj.value);
|
|
length += 1 + len;
|
|
}
|
|
return length;
|
|
}
|
|
function encode(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength(obj));
|
|
var oldOffset = offset;
|
|
if (!defined(obj.index)) throw new Error("index is required");
|
|
buf[offset++] = 10;
|
|
encodings.bytes.encode(obj.index, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
if (!defined(obj.key)) throw new Error("key is required");
|
|
buf[offset++] = 18;
|
|
encodings.bytes.encode(obj.key, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
if (defined(obj.value)) {
|
|
buf[offset++] = 26;
|
|
encodings.bytes.encode(obj.value, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
}
|
|
encode.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
index: null,
|
|
key: null,
|
|
value: null
|
|
};
|
|
var found0 = false;
|
|
var found1 = false;
|
|
while (true) {
|
|
if (end <= offset) {
|
|
if (!found0 || !found1) throw new Error("Decoded message is not valid");
|
|
decode.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
obj.index = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
found0 = true;
|
|
break;
|
|
case 2:
|
|
obj.key = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
found1 = true;
|
|
break;
|
|
case 3:
|
|
obj.value = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function defineExtension() {
|
|
var Get = Extension.Get = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
var Iterator = Extension.Iterator = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
var Cache = Extension.Cache = {
|
|
buffer: true,
|
|
encodingLength: null,
|
|
encode: null,
|
|
decode: null
|
|
};
|
|
defineGet();
|
|
defineIterator();
|
|
defineCache();
|
|
function defineGet() {
|
|
Get.encodingLength = encodingLength2;
|
|
Get.encode = encode2;
|
|
Get.decode = decode2;
|
|
function encodingLength2(obj) {
|
|
var length = 0;
|
|
if (defined(obj.version)) {
|
|
var len = encodings.varint.encodingLength(obj.version);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.key)) {
|
|
var len = encodings.bytes.encodingLength(obj.key);
|
|
length += 1 + len;
|
|
}
|
|
return length;
|
|
}
|
|
function encode2(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength2(obj));
|
|
var oldOffset = offset;
|
|
if (defined(obj.version)) {
|
|
buf[offset++] = 8;
|
|
encodings.varint.encode(obj.version, buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
}
|
|
if (defined(obj.key)) {
|
|
buf[offset++] = 18;
|
|
encodings.bytes.encode(obj.key, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
}
|
|
encode2.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode2(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
version: 0,
|
|
key: null
|
|
};
|
|
while (true) {
|
|
if (end <= offset) {
|
|
decode2.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
obj.version = encodings.varint.decode(buf, offset);
|
|
offset += encodings.varint.decode.bytes;
|
|
break;
|
|
case 2:
|
|
obj.key = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function defineIterator() {
|
|
Iterator.encodingLength = encodingLength2;
|
|
Iterator.encode = encode2;
|
|
Iterator.decode = decode2;
|
|
function encodingLength2(obj) {
|
|
var length = 0;
|
|
if (defined(obj.version)) {
|
|
var len = encodings.varint.encodingLength(obj.version);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.gte)) {
|
|
var len = encodings.bytes.encodingLength(obj.gte);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.gt)) {
|
|
var len = encodings.bytes.encodingLength(obj.gt);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.lte)) {
|
|
var len = encodings.bytes.encodingLength(obj.lte);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.lt)) {
|
|
var len = encodings.bytes.encodingLength(obj.lt);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.limit)) {
|
|
var len = encodings.varint.encodingLength(obj.limit);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.reverse)) {
|
|
var len = encodings.bool.encodingLength(obj.reverse);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.checkpoint)) {
|
|
var packedLen = 0;
|
|
for (var i = 0; i < obj.checkpoint.length; i++) {
|
|
if (!defined(obj.checkpoint[i])) continue;
|
|
var len = encodings.varint.encodingLength(obj.checkpoint[i]);
|
|
packedLen += len;
|
|
}
|
|
if (packedLen) {
|
|
length += 1 + packedLen + varint.encodingLength(packedLen);
|
|
}
|
|
}
|
|
return length;
|
|
}
|
|
function encode2(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength2(obj));
|
|
var oldOffset = offset;
|
|
if (defined(obj.version)) {
|
|
buf[offset++] = 8;
|
|
encodings.varint.encode(obj.version, buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
}
|
|
if (defined(obj.gte)) {
|
|
buf[offset++] = 18;
|
|
encodings.bytes.encode(obj.gte, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
}
|
|
if (defined(obj.gt)) {
|
|
buf[offset++] = 26;
|
|
encodings.bytes.encode(obj.gt, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
}
|
|
if (defined(obj.lte)) {
|
|
buf[offset++] = 34;
|
|
encodings.bytes.encode(obj.lte, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
}
|
|
if (defined(obj.lt)) {
|
|
buf[offset++] = 42;
|
|
encodings.bytes.encode(obj.lt, buf, offset);
|
|
offset += encodings.bytes.encode.bytes;
|
|
}
|
|
if (defined(obj.limit)) {
|
|
buf[offset++] = 48;
|
|
encodings.varint.encode(obj.limit, buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
}
|
|
if (defined(obj.reverse)) {
|
|
buf[offset++] = 56;
|
|
encodings.bool.encode(obj.reverse, buf, offset);
|
|
offset += encodings.bool.encode.bytes;
|
|
}
|
|
if (defined(obj.checkpoint)) {
|
|
var packedLen = 0;
|
|
for (var i = 0; i < obj.checkpoint.length; i++) {
|
|
if (!defined(obj.checkpoint[i])) continue;
|
|
packedLen += encodings.varint.encodingLength(obj.checkpoint[i]);
|
|
}
|
|
if (packedLen) {
|
|
buf[offset++] = 66;
|
|
varint.encode(packedLen, buf, offset);
|
|
offset += varint.encode.bytes;
|
|
}
|
|
for (var i = 0; i < obj.checkpoint.length; i++) {
|
|
if (!defined(obj.checkpoint[i])) continue;
|
|
encodings.varint.encode(obj.checkpoint[i], buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
}
|
|
}
|
|
encode2.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode2(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
version: 0,
|
|
gte: null,
|
|
gt: null,
|
|
lte: null,
|
|
lt: null,
|
|
limit: 0,
|
|
reverse: false,
|
|
checkpoint: []
|
|
};
|
|
while (true) {
|
|
if (end <= offset) {
|
|
decode2.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
obj.version = encodings.varint.decode(buf, offset);
|
|
offset += encodings.varint.decode.bytes;
|
|
break;
|
|
case 2:
|
|
obj.gte = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
break;
|
|
case 3:
|
|
obj.gt = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
break;
|
|
case 4:
|
|
obj.lte = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
break;
|
|
case 5:
|
|
obj.lt = encodings.bytes.decode(buf, offset);
|
|
offset += encodings.bytes.decode.bytes;
|
|
break;
|
|
case 6:
|
|
obj.limit = encodings.varint.decode(buf, offset);
|
|
offset += encodings.varint.decode.bytes;
|
|
break;
|
|
case 7:
|
|
obj.reverse = encodings.bool.decode(buf, offset);
|
|
offset += encodings.bool.decode.bytes;
|
|
break;
|
|
case 8:
|
|
var packedEnd = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
packedEnd += offset;
|
|
while (offset < packedEnd) {
|
|
obj.checkpoint.push(encodings.varint.decode(buf, offset));
|
|
offset += encodings.varint.decode.bytes;
|
|
}
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function defineCache() {
|
|
Cache.encodingLength = encodingLength2;
|
|
Cache.encode = encode2;
|
|
Cache.decode = decode2;
|
|
function encodingLength2(obj) {
|
|
var length = 0;
|
|
if (!defined(obj.start)) throw new Error("start is required");
|
|
var len = encodings.varint.encodingLength(obj.start);
|
|
length += 1 + len;
|
|
if (!defined(obj.end)) throw new Error("end is required");
|
|
var len = encodings.varint.encodingLength(obj.end);
|
|
length += 1 + len;
|
|
if (defined(obj.blocks)) {
|
|
var packedLen = 0;
|
|
for (var i = 0; i < obj.blocks.length; i++) {
|
|
if (!defined(obj.blocks[i])) continue;
|
|
var len = encodings.varint.encodingLength(obj.blocks[i]);
|
|
packedLen += len;
|
|
}
|
|
if (packedLen) {
|
|
length += 1 + packedLen + varint.encodingLength(packedLen);
|
|
}
|
|
}
|
|
return length;
|
|
}
|
|
function encode2(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength2(obj));
|
|
var oldOffset = offset;
|
|
if (!defined(obj.start)) throw new Error("start is required");
|
|
buf[offset++] = 8;
|
|
encodings.varint.encode(obj.start, buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
if (!defined(obj.end)) throw new Error("end is required");
|
|
buf[offset++] = 16;
|
|
encodings.varint.encode(obj.end, buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
if (defined(obj.blocks)) {
|
|
var packedLen = 0;
|
|
for (var i = 0; i < obj.blocks.length; i++) {
|
|
if (!defined(obj.blocks[i])) continue;
|
|
packedLen += encodings.varint.encodingLength(obj.blocks[i]);
|
|
}
|
|
if (packedLen) {
|
|
buf[offset++] = 26;
|
|
varint.encode(packedLen, buf, offset);
|
|
offset += varint.encode.bytes;
|
|
}
|
|
for (var i = 0; i < obj.blocks.length; i++) {
|
|
if (!defined(obj.blocks[i])) continue;
|
|
encodings.varint.encode(obj.blocks[i], buf, offset);
|
|
offset += encodings.varint.encode.bytes;
|
|
}
|
|
}
|
|
encode2.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode2(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
start: 0,
|
|
end: 0,
|
|
blocks: []
|
|
};
|
|
var found0 = false;
|
|
var found1 = false;
|
|
while (true) {
|
|
if (end <= offset) {
|
|
if (!found0 || !found1) throw new Error("Decoded message is not valid");
|
|
decode2.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
obj.start = encodings.varint.decode(buf, offset);
|
|
offset += encodings.varint.decode.bytes;
|
|
found0 = true;
|
|
break;
|
|
case 2:
|
|
obj.end = encodings.varint.decode(buf, offset);
|
|
offset += encodings.varint.decode.bytes;
|
|
found1 = true;
|
|
break;
|
|
case 3:
|
|
var packedEnd = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
packedEnd += offset;
|
|
while (offset < packedEnd) {
|
|
obj.blocks.push(encodings.varint.decode(buf, offset));
|
|
offset += encodings.varint.decode.bytes;
|
|
}
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Extension.encodingLength = encodingLength;
|
|
Extension.encode = encode;
|
|
Extension.decode = decode;
|
|
function encodingLength(obj) {
|
|
var length = 0;
|
|
if (defined(obj.cache)) {
|
|
var len = Cache.encodingLength(obj.cache);
|
|
length += varint.encodingLength(len);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.get)) {
|
|
var len = Get.encodingLength(obj.get);
|
|
length += varint.encodingLength(len);
|
|
length += 1 + len;
|
|
}
|
|
if (defined(obj.iterator)) {
|
|
var len = Iterator.encodingLength(obj.iterator);
|
|
length += varint.encodingLength(len);
|
|
length += 1 + len;
|
|
}
|
|
return length;
|
|
}
|
|
function encode(obj, buf, offset) {
|
|
if (!offset) offset = 0;
|
|
if (!buf) buf = b4a.allocUnsafe(encodingLength(obj));
|
|
var oldOffset = offset;
|
|
if (defined(obj.cache)) {
|
|
buf[offset++] = 10;
|
|
varint.encode(Cache.encodingLength(obj.cache), buf, offset);
|
|
offset += varint.encode.bytes;
|
|
Cache.encode(obj.cache, buf, offset);
|
|
offset += Cache.encode.bytes;
|
|
}
|
|
if (defined(obj.get)) {
|
|
buf[offset++] = 18;
|
|
varint.encode(Get.encodingLength(obj.get), buf, offset);
|
|
offset += varint.encode.bytes;
|
|
Get.encode(obj.get, buf, offset);
|
|
offset += Get.encode.bytes;
|
|
}
|
|
if (defined(obj.iterator)) {
|
|
buf[offset++] = 26;
|
|
varint.encode(Iterator.encodingLength(obj.iterator), buf, offset);
|
|
offset += varint.encode.bytes;
|
|
Iterator.encode(obj.iterator, buf, offset);
|
|
offset += Iterator.encode.bytes;
|
|
}
|
|
encode.bytes = offset - oldOffset;
|
|
return buf;
|
|
}
|
|
function decode(buf, offset, end) {
|
|
if (!offset) offset = 0;
|
|
if (!end) end = buf.length;
|
|
if (!(end <= buf.length && offset <= buf.length)) throw new Error("Decoded message is not valid");
|
|
var oldOffset = offset;
|
|
var obj = {
|
|
cache: null,
|
|
get: null,
|
|
iterator: null
|
|
};
|
|
while (true) {
|
|
if (end <= offset) {
|
|
decode.bytes = offset - oldOffset;
|
|
return obj;
|
|
}
|
|
var prefix = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
var tag = prefix >> 3;
|
|
switch (tag) {
|
|
case 1:
|
|
var len = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
obj.cache = Cache.decode(buf, offset, offset + len);
|
|
offset += Cache.decode.bytes;
|
|
break;
|
|
case 2:
|
|
var len = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
obj.get = Get.decode(buf, offset, offset + len);
|
|
offset += Get.decode.bytes;
|
|
break;
|
|
case 3:
|
|
var len = varint.decode(buf, offset);
|
|
offset += varint.decode.bytes;
|
|
obj.iterator = Iterator.decode(buf, offset, offset + len);
|
|
offset += Iterator.decode.bytes;
|
|
break;
|
|
default:
|
|
offset = skip(prefix & 7, buf, offset);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function defined(val) {
|
|
return val !== null && val !== void 0 && (typeof val !== "number" || !isNaN(val));
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperbee/lib/extension.js
|
|
var require_extension = __commonJS({
|
|
"../../node_modules/hyperbee/lib/extension.js"(exports, module) {
|
|
var { Extension } = require_messages();
|
|
var FLUSH_BATCH = 128;
|
|
var MAX_PASSIVE_BATCH = 2048;
|
|
var MAX_ACTIVE_BATCH = MAX_PASSIVE_BATCH + FLUSH_BATCH;
|
|
var Batch = class {
|
|
constructor(outgoing, from) {
|
|
this.blocks = [];
|
|
this.start = 0;
|
|
this.end = 0;
|
|
this.outgoing = outgoing;
|
|
this.from = from;
|
|
}
|
|
push(seq) {
|
|
const len = this.blocks.push(seq);
|
|
if (len === 1 || seq < this.start) this.start = seq;
|
|
if (len === 1 || seq >= this.end) this.end = seq + 1;
|
|
if (len >= FLUSH_BATCH) {
|
|
this.send();
|
|
this.clear();
|
|
}
|
|
}
|
|
send() {
|
|
if (!this.blocks.length) return;
|
|
this.outgoing.send(
|
|
Extension.encode({
|
|
cache: { blocks: this.blocks, start: this.start, end: this.end }
|
|
}),
|
|
this.from
|
|
);
|
|
}
|
|
clear() {
|
|
this.start = this.end = 0;
|
|
this.blocks = [];
|
|
}
|
|
};
|
|
var HyperbeeExtension = class {
|
|
constructor(db) {
|
|
this.encoding = null;
|
|
this.outgoing = null;
|
|
this.db = db;
|
|
this.active = 0;
|
|
}
|
|
get(version, key) {
|
|
this.outgoing.broadcast(Extension.encode({ get: { version, key } }));
|
|
}
|
|
iterator(snapshot) {
|
|
if (snapshot.ended) return;
|
|
if (snapshot.limit === 0) return;
|
|
if (snapshot.limit === -1) snapshot.limit = 0;
|
|
this.outgoing.broadcast(Extension.encode({ iterator: snapshot }));
|
|
}
|
|
onmessage(buf, from) {
|
|
const message = decode(buf);
|
|
if (!message) return;
|
|
if (message.cache) this.oncache(message.cache, from);
|
|
if (message.get) this.onget(message.get, from);
|
|
if (message.iterator) this.oniterator(message.iterator, from);
|
|
}
|
|
oncache(message, from) {
|
|
if (!message.blocks.length) return;
|
|
this.db.core.download(message);
|
|
}
|
|
onget(message, from) {
|
|
if (!message.version || message.version > this.db.version) return;
|
|
const b = new Batch(this.outgoing, from);
|
|
const db = this.db.checkout(message.version);
|
|
db.get(message.key, {
|
|
extension: false,
|
|
wait: false,
|
|
update: false,
|
|
onseq
|
|
}).then(done, done);
|
|
function done() {
|
|
db.close().catch(noop);
|
|
b.send();
|
|
}
|
|
function onseq(seq) {
|
|
b.push(seq);
|
|
}
|
|
}
|
|
async oniterator(message, from) {
|
|
if (!message.version || message.version > this.db.version) return;
|
|
const b = new Batch(this.outgoing, from);
|
|
const seqs = /* @__PURE__ */ new Set();
|
|
let skip = message.checkpoint.length;
|
|
let work = 0;
|
|
const db = this.db.checkout(message.version);
|
|
const ite = db.createRangeIterator({
|
|
...message,
|
|
wait: false,
|
|
extension: false,
|
|
update: false,
|
|
limit: message.limit === 0 ? -1 : message.limit,
|
|
onseq(seq) {
|
|
if (skip && skip--) return;
|
|
if (seqs.has(seq)) return;
|
|
work++;
|
|
seqs.add(seq);
|
|
b.push(seq);
|
|
}
|
|
});
|
|
try {
|
|
await ite.open();
|
|
while (work < MAX_ACTIVE_BATCH) {
|
|
if (!await ite.next()) break;
|
|
}
|
|
} catch (_) {
|
|
} finally {
|
|
ite.close().catch(noop);
|
|
db.close().catch(noop);
|
|
b.send();
|
|
}
|
|
}
|
|
static register(db) {
|
|
const e = new this(db);
|
|
e.outgoing = db.core.registerExtension("hyperbee", e);
|
|
return e;
|
|
}
|
|
};
|
|
HyperbeeExtension.BATCH_SIZE = MAX_PASSIVE_BATCH;
|
|
module.exports = HyperbeeExtension;
|
|
function decode(buf) {
|
|
try {
|
|
return Extension.decode(buf);
|
|
} catch (err) {
|
|
return null;
|
|
}
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/z32/index.js
|
|
var require_z32 = __commonJS({
|
|
"../../node_modules/z32/index.js"(exports) {
|
|
var b4a = require_b4a();
|
|
var ALPHABET = "ybndrfg8ejkmcpqxot1uwisza345h769";
|
|
var MIN = 49;
|
|
var MAX = 122;
|
|
var REVERSE = new Int8Array(1 + MAX - MIN);
|
|
REVERSE.fill(-1);
|
|
for (let i = 0; i < ALPHABET.length; i++) {
|
|
const v = ALPHABET.charCodeAt(i) - MIN;
|
|
REVERSE[v] = i;
|
|
}
|
|
exports.encode = encode;
|
|
exports.decode = decode;
|
|
exports.ALPHABET = ALPHABET;
|
|
function decode(s, out) {
|
|
let pb = 0;
|
|
let ps = 0;
|
|
const r = s.length & 7;
|
|
const q = (s.length - r) / 8;
|
|
if (!out) out = b4a.allocUnsafe(Math.ceil(s.length * 5 / 8));
|
|
for (let i = 0; i < q; i++) {
|
|
const a2 = quintet(s, ps++);
|
|
const b2 = quintet(s, ps++);
|
|
const c2 = quintet(s, ps++);
|
|
const d2 = quintet(s, ps++);
|
|
const e2 = quintet(s, ps++);
|
|
const f2 = quintet(s, ps++);
|
|
const g2 = quintet(s, ps++);
|
|
const h2 = quintet(s, ps++);
|
|
out[pb++] = a2 << 3 | b2 >>> 2;
|
|
out[pb++] = (b2 & 3) << 6 | c2 << 1 | d2 >>> 4;
|
|
out[pb++] = (d2 & 15) << 4 | e2 >>> 1;
|
|
out[pb++] = (e2 & 1) << 7 | f2 << 2 | g2 >>> 3;
|
|
out[pb++] = (g2 & 7) << 5 | h2;
|
|
}
|
|
if (r === 0) return out.subarray(0, pb);
|
|
const a = quintet(s, ps++);
|
|
const b = quintet(s, ps++);
|
|
out[pb++] = a << 3 | b >>> 2;
|
|
if (r <= 2) return out.subarray(0, pb);
|
|
const c = quintet(s, ps++);
|
|
const d = quintet(s, ps++);
|
|
out[pb++] = (b & 3) << 6 | c << 1 | d >>> 4;
|
|
if (r <= 4) return out.subarray(0, pb);
|
|
const e = quintet(s, ps++);
|
|
out[pb++] = (d & 15) << 4 | e >>> 1;
|
|
if (r <= 5) return out.subarray(0, pb);
|
|
const f = quintet(s, ps++);
|
|
const g = quintet(s, ps++);
|
|
out[pb++] = (e & 1) << 7 | f << 2 | g >>> 3;
|
|
if (r <= 7) return out.subarray(0, pb);
|
|
const h = quintet(s, ps++);
|
|
out[pb++] = (g & 7) << 5 | h;
|
|
return out.subarray(0, pb);
|
|
}
|
|
function encode(buf) {
|
|
if (typeof buf === "string") buf = b4a.from(buf);
|
|
const max = buf.byteLength * 8;
|
|
let s = "";
|
|
for (let p = 0; p < max; p += 5) {
|
|
const i = p >>> 3;
|
|
const j = p & 7;
|
|
if (j <= 3) {
|
|
s += ALPHABET[buf[i] >>> 3 - j & 31];
|
|
continue;
|
|
}
|
|
const of = j - 3;
|
|
const h = buf[i] << of & 31;
|
|
const l = (i >= buf.byteLength ? 0 : buf[i + 1]) >>> 8 - of;
|
|
s += ALPHABET[h | l];
|
|
}
|
|
return s;
|
|
}
|
|
function quintet(s, i) {
|
|
if (i > s.length) {
|
|
return 0;
|
|
}
|
|
const v = s.charCodeAt(i);
|
|
if (v < MIN || v > MAX) {
|
|
throw Error('Invalid character in base32 input: "' + s[i] + '" at position ' + i);
|
|
}
|
|
const bits = REVERSE[v - MIN];
|
|
if (bits === -1) {
|
|
throw Error('Invalid character in base32 input: "' + s[i] + '" at position ' + i);
|
|
}
|
|
return bits;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hypercore-id-encoding/index.js
|
|
var require_hypercore_id_encoding = __commonJS({
|
|
"../../node_modules/hypercore-id-encoding/index.js"(exports, module) {
|
|
var z32 = require_z32();
|
|
var b4a = require_b4a();
|
|
module.exports = {
|
|
encode,
|
|
decode,
|
|
normalize,
|
|
isValid
|
|
};
|
|
function encode(key) {
|
|
if (!b4a.isBuffer(key)) throw new Error("Key must be a Buffer");
|
|
if (key.byteLength !== 32) throw new Error("Key must be 32-bytes long");
|
|
return z32.encode(key);
|
|
}
|
|
function decode(id) {
|
|
if (b4a.isBuffer(id)) {
|
|
if (id.byteLength !== 32) throw new Error("ID must be 32-bytes long");
|
|
return id;
|
|
}
|
|
if (typeof id === "string") {
|
|
if (id.startsWith("pear://")) id = id.slice(7).split("/")[0];
|
|
if (id.length === 52) return z32.decode(id);
|
|
if (id.length === 64) {
|
|
const buf = b4a.from(id, "hex");
|
|
if (buf.byteLength === 32) return buf;
|
|
}
|
|
}
|
|
throw new Error("Invalid Hypercore key");
|
|
}
|
|
function normalize(any) {
|
|
return encode(decode(any));
|
|
}
|
|
function isValid(any) {
|
|
try {
|
|
decode(any);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hypercore-errors/index.js
|
|
var require_hypercore_errors = __commonJS({
|
|
"../../node_modules/hypercore-errors/index.js"(exports, module) {
|
|
var IdEnc = require_hypercore_id_encoding();
|
|
module.exports = class HypercoreError extends Error {
|
|
constructor(msg, code, fn = HypercoreError, discoveryKey = null) {
|
|
if (discoveryKey) msg = `${msg} (discovery key: ${IdEnc.normalize(discoveryKey)})`;
|
|
super(`${code}: ${msg}`);
|
|
this.code = code;
|
|
this.discoveryKey = discoveryKey;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, fn);
|
|
}
|
|
}
|
|
get name() {
|
|
return "HypercoreError";
|
|
}
|
|
static ASSERTION(msg, discoveryKey = null) {
|
|
return new HypercoreError(msg, "ERR_ASSERTION", HypercoreError.ASSERT, discoveryKey);
|
|
}
|
|
static BAD_ARGUMENT(msg, discoveryKey = null) {
|
|
return new HypercoreError(msg, "BAD_ARGUMENT", HypercoreError.BAD_ARGUMENT, discoveryKey);
|
|
}
|
|
static STORAGE_EMPTY(msg, discoveryKey = null) {
|
|
return new HypercoreError(msg, "STORAGE_EMPTY", HypercoreError.STORAGE_EMPTY, discoveryKey);
|
|
}
|
|
static STORAGE_CONFLICT(msg, discoveryKey = null) {
|
|
return new HypercoreError(msg, "STORAGE_CONFLICT", HypercoreError.STORAGE_CONFLICT, discoveryKey);
|
|
}
|
|
static INVALID_SIGNATURE(msg, discoveryKey = null) {
|
|
return new HypercoreError(msg, "INVALID_SIGNATURE", HypercoreError.INVALID_SIGNATURE, discoveryKey);
|
|
}
|
|
static INVALID_CAPABILITY(msg, discoveryKey = null) {
|
|
return new HypercoreError(msg, "INVALID_CAPABILITY", HypercoreError.INVALID_CAPABILITY, discoveryKey);
|
|
}
|
|
static INVALID_CHECKSUM(msg = "Invalid checksum", discoveryKey = null) {
|
|
return new HypercoreError(msg, "INVALID_CHECKSUM", HypercoreError.INVALID_CHECKSUM, discoveryKey);
|
|
}
|
|
static INVALID_OPERATION(msg, discoveryKey = null) {
|
|
return new HypercoreError(msg, "INVALID_OPERATION", HypercoreError.INVALID_OPERATION, discoveryKey);
|
|
}
|
|
static INVALID_PROOF(msg = "Proof not verifiable", discoveryKey = null) {
|
|
return new HypercoreError(msg, "INVALID_PROOF", HypercoreError.INVALID_PROOF, discoveryKey);
|
|
}
|
|
static BLOCK_NOT_AVAILABLE(msg = "Block is not available", discoveryKey = null) {
|
|
return new HypercoreError(msg, "BLOCK_NOT_AVAILABLE", HypercoreError.BLOCK_NOT_AVAILABLE, discoveryKey);
|
|
}
|
|
static SNAPSHOT_NOT_AVAILABLE(msg = "Snapshot is not available", discoveryKey = null) {
|
|
return new HypercoreError(msg, "SNAPSHOT_NOT_AVAILABLE", HypercoreError.SNAPSHOT_NOT_AVAILABLE, discoveryKey);
|
|
}
|
|
static REQUEST_CANCELLED(msg = "Request was cancelled", discoveryKey = null) {
|
|
return new HypercoreError(msg, "REQUEST_CANCELLED", HypercoreError.REQUEST_CANCELLED, discoveryKey);
|
|
}
|
|
static REQUEST_TIMEOUT(msg = "Request timed out", discoveryKey = null) {
|
|
return new HypercoreError(msg, "REQUEST_TIMEOUT", HypercoreError.REQUEST_TIMEOUT, discoveryKey);
|
|
}
|
|
static SESSION_NOT_WRITABLE(msg = "Session is not writable", discoveryKey = null) {
|
|
return new HypercoreError(msg, "SESSION_NOT_WRITABLE", HypercoreError.SESSION_NOT_WRITABLE, discoveryKey);
|
|
}
|
|
static SESSION_CLOSED(msg = "Session is closed", discoveryKey = null) {
|
|
return new HypercoreError(msg, "SESSION_CLOSED", HypercoreError.SESSION_CLOSED, discoveryKey);
|
|
}
|
|
static BATCH_UNFLUSHED(msg = "Batch not yet flushed", discoveryKey = null) {
|
|
return new HypercoreError(msg, "BATCH_UNFLUSHED", HypercoreError.BATCH_UNFLUSHED, discoveryKey);
|
|
}
|
|
static BATCH_ALREADY_EXISTS(msg = "Batch already exists", discoveryKey = null) {
|
|
return new HypercoreError(msg, "BATCH_ALREADY_EXISTS", HypercoreError.BATCH_ALREADY_EXISTS, discoveryKey);
|
|
}
|
|
static BATCH_ALREADY_FLUSHED(msg = "Batch has already been flushed", discoveryKey = null) {
|
|
return new HypercoreError(msg, "BATCH_ALREADY_FLUSHED", HypercoreError.BATCH_ALREADY_FLUSHED, discoveryKey);
|
|
}
|
|
static OPLOG_CORRUPT(msg = "Oplog file appears corrupt or out of date", discoveryKey = null) {
|
|
return new HypercoreError(msg, "OPLOG_CORRUPT", HypercoreError.OPLOG_CORRUPT, discoveryKey);
|
|
}
|
|
static OPLOG_HEADER_OVERFLOW(msg = "Oplog header exceeds page size", discoveryKey = null) {
|
|
return new HypercoreError(msg, "OPLOG_HEADER_OVERFLOW", HypercoreError.OPLOG_HEADER_OVERFLOW, discoveryKey);
|
|
}
|
|
static INVALID_OPLOG_VERSION(msg = "Invalid header version", discoveryKey = null) {
|
|
return new HypercoreError(msg, "INVALID_OPLOG_VERSION", HypercoreError.INVALID_OPLOG_VERSION, discoveryKey);
|
|
}
|
|
static WRITE_FAILED(msg = "Write to storage failed", discoveryKey = null) {
|
|
return new HypercoreError(msg, "WRITE_FAILED", HypercoreError.WRITE_FAILED, discoveryKey);
|
|
}
|
|
static DECODING_ERROR(msg = "Decoding error", discoveryKey = null) {
|
|
return new HypercoreError(msg, "DECODING_ERROR", HypercoreError.DECODING_ERROR, discoveryKey);
|
|
}
|
|
static SESSION_MOVED(msg = "Session moved", discoveryKey = null) {
|
|
return new HypercoreError(msg, "SESSION_MOVED", HypercoreError.SESSION_MOVED, discoveryKey);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperbee/index.js
|
|
var require_hyperbee = __commonJS({
|
|
"../../node_modules/hyperbee/index.js"(exports, module) {
|
|
var codecs = require_codecs();
|
|
var { Readable } = require_streamx();
|
|
var mutexify = require_promise();
|
|
var b4a = require_b4a();
|
|
var safetyCatch = require_safety_catch();
|
|
var ReadyResource = require_ready_resource();
|
|
var debounce = require_debounceify();
|
|
var Rache = require_rache();
|
|
var rrp = require_resolve_reject_promise();
|
|
var { all: unslabAll } = require_unslab();
|
|
var RangeIterator = require_range3();
|
|
var HistoryIterator = require_history();
|
|
var DiffIterator = require_diff();
|
|
var LocalBlockIterator = require_local();
|
|
var Extension = require_extension();
|
|
var { YoloIndex, Node, Header } = require_messages();
|
|
var { BLOCK_NOT_AVAILABLE, DECODING_ERROR } = require_hypercore_errors();
|
|
var T = 5;
|
|
var MIN_KEYS = T - 1;
|
|
var MAX_CHILDREN = MIN_KEYS * 2 + 1;
|
|
var SEP = b4a.alloc(1);
|
|
var EMPTY = b4a.alloc(0);
|
|
var Key = class {
|
|
constructor(seq, value) {
|
|
this.seq = seq;
|
|
this.value = value;
|
|
}
|
|
};
|
|
var Child = class {
|
|
constructor(seq, offset, value) {
|
|
this.seq = seq;
|
|
this.offset = offset;
|
|
this.value = value;
|
|
}
|
|
};
|
|
var Cache = class {
|
|
constructor(rache) {
|
|
this.keys = rache;
|
|
this.length = 0;
|
|
}
|
|
get(seq) {
|
|
return this.keys.get(seq) || null;
|
|
}
|
|
set(seq, key) {
|
|
this.keys.set(seq, key);
|
|
if (seq >= this.length) this.length = seq + 1;
|
|
}
|
|
gc(length) {
|
|
if (this.length - length > 128) {
|
|
this.keys.clear();
|
|
} else {
|
|
for (let i = length; i < this.length; i++) {
|
|
this.keys.delete(i);
|
|
}
|
|
}
|
|
this.length = length;
|
|
}
|
|
clear() {
|
|
this.keys.clear();
|
|
}
|
|
};
|
|
var Pointers = class {
|
|
constructor(decoded) {
|
|
this.levels = decoded.levels.map((l) => {
|
|
const children = [];
|
|
const keys = [];
|
|
for (let i = 0; i < l.keys.length; i++) {
|
|
keys.push(new Key(l.keys[i], null));
|
|
}
|
|
for (let i = 0; i < l.children.length; i += 2) {
|
|
children.push(new Child(l.children[i], l.children[i + 1], null));
|
|
}
|
|
return { keys, children };
|
|
});
|
|
}
|
|
get(i) {
|
|
return this.levels[i];
|
|
}
|
|
hasKey(seq) {
|
|
for (const lvl of this.levels) {
|
|
for (const key of lvl.keys) {
|
|
if (key.seq === seq) return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
function inflate(entry) {
|
|
if (entry.inflated === null) {
|
|
entry.inflated = YoloIndex.decode(entry.index);
|
|
entry.index = null;
|
|
}
|
|
return new Pointers(entry.inflated);
|
|
}
|
|
function deflate(index) {
|
|
const levels = index.map((l) => {
|
|
const keys = [];
|
|
const children = [];
|
|
for (let i = 0; i < l.value.keys.length; i++) {
|
|
keys.push(l.value.keys[i].seq);
|
|
}
|
|
for (let i = 0; i < l.value.children.length; i++) {
|
|
children.push(l.value.children[i].seq, l.value.children[i].offset);
|
|
}
|
|
return { keys, children };
|
|
});
|
|
return YoloIndex.encode({ levels });
|
|
}
|
|
var TreeNode = class _TreeNode {
|
|
constructor(block, keys, children, offset) {
|
|
this.block = block;
|
|
this.offset = offset;
|
|
this.keys = keys;
|
|
this.children = children;
|
|
this.changed = false;
|
|
this.preload();
|
|
}
|
|
preload() {
|
|
if (this.block === null) return;
|
|
const core = getBackingCore(this.block.tree.core);
|
|
if (!core) return;
|
|
const bitfield = core.core.bitfield;
|
|
const blocks = [];
|
|
for (let i = 0; i < this.keys.length; i++) {
|
|
const k = this.keys[i];
|
|
if (k.value) continue;
|
|
if (k.seq >= core.signedLength || bitfield && bitfield.get(k.seq)) continue;
|
|
blocks.push(k.seq);
|
|
}
|
|
for (let i = 0; i < this.children.length; i++) {
|
|
const c = this.children[i];
|
|
if (c.value) continue;
|
|
if (c.seq >= core.signedLength || bitfield && bitfield.get(c.seq)) continue;
|
|
blocks.push(c.seq);
|
|
}
|
|
if (blocks.length) core.download({ blocks });
|
|
}
|
|
async insertKey(key, value, child, node, encoding, cas) {
|
|
let s = 0;
|
|
let e = this.keys.length;
|
|
let c;
|
|
while (s < e) {
|
|
const mid = s + e >> 1;
|
|
c = b4a.compare(key.value, await this.getKey(mid));
|
|
if (c === 0) {
|
|
if (cas) {
|
|
const prev = await this.getKeyNode(mid);
|
|
if (!await cas(prev.final(encoding), node)) return true;
|
|
}
|
|
if (!this.block.tree.tree.alwaysDuplicate) {
|
|
const prev = await this.getKeyNode(mid);
|
|
if (sameValue(prev.value, value)) return true;
|
|
}
|
|
this.changed = true;
|
|
this.keys[mid] = key;
|
|
return true;
|
|
}
|
|
if (c < 0) e = mid;
|
|
else s = mid + 1;
|
|
}
|
|
const i = c < 0 ? e : s;
|
|
this.keys.splice(i, 0, key);
|
|
if (child) this.children.splice(i + 1, 0, new Child(0, 0, child));
|
|
this.changed = true;
|
|
return this.keys.length < MAX_CHILDREN;
|
|
}
|
|
removeKey(index) {
|
|
this.keys.splice(index, 1);
|
|
if (this.children.length) {
|
|
this.children[index + 1].seq = 0;
|
|
this.children.splice(index + 1, 1);
|
|
}
|
|
this.changed = true;
|
|
}
|
|
async siblings(parent) {
|
|
for (let i = 0; i < parent.children.length; i++) {
|
|
if (parent.children[i].value === this) {
|
|
const [left, right] = await Promise.all([
|
|
i ? parent.getChildNode(i - 1) : null,
|
|
i < parent.children.length - 1 ? parent.getChildNode(i + 1) : null
|
|
]);
|
|
return { left, index: i, right };
|
|
}
|
|
}
|
|
throw new Error("Bad parent");
|
|
}
|
|
merge(node, median) {
|
|
this.changed = true;
|
|
this.keys.push(median);
|
|
for (let i = 0; i < node.keys.length; i++) this.keys.push(node.keys[i]);
|
|
for (let i = 0; i < node.children.length; i++) this.children.push(node.children[i]);
|
|
}
|
|
async split() {
|
|
const len = this.keys.length >> 1;
|
|
const right = _TreeNode.create(this.block);
|
|
while (right.keys.length < len) right.keys.push(this.keys.pop());
|
|
right.keys.reverse();
|
|
await this.getKey(this.keys.length - 1);
|
|
const median = this.keys.pop();
|
|
if (this.children.length) {
|
|
while (right.children.length < len + 1) right.children.push(this.children.pop());
|
|
right.children.reverse();
|
|
}
|
|
this.changed = true;
|
|
return {
|
|
left: this,
|
|
median,
|
|
right
|
|
};
|
|
}
|
|
getKeyNode(index) {
|
|
return this.block.tree.getBlock(this.keys[index].seq);
|
|
}
|
|
async getChildNode(index) {
|
|
const child = this.children[index];
|
|
if (child.value) return child.value;
|
|
const block = child.seq === this.block.seq ? this.block : await this.block.tree.getBlock(child.seq);
|
|
return child.value = block.getTreeNode(child.offset);
|
|
}
|
|
setKey(index, key) {
|
|
this.keys[index] = key;
|
|
this.changed = true;
|
|
}
|
|
async getKey(index) {
|
|
const key = this.keys[index];
|
|
if (key.value) return key.value;
|
|
const k = key.seq === this.block.seq ? this.block.key : await this.block.tree.getKey(key.seq);
|
|
return key.value = k;
|
|
}
|
|
indexChanges(index, seq) {
|
|
const offset = index.push(null) - 1;
|
|
this.changed = false;
|
|
for (const child of this.children) {
|
|
if (!child.value || !child.value.changed) continue;
|
|
child.seq = seq;
|
|
child.offset = child.value.indexChanges(index, seq);
|
|
index[child.offset] = child;
|
|
}
|
|
return offset;
|
|
}
|
|
updateChildren(seq, block) {
|
|
for (const child of this.children) {
|
|
if (!child.value || child.seq !== seq) continue;
|
|
child.value.block = block;
|
|
child.value.updateChildren(seq, block);
|
|
}
|
|
}
|
|
static create(block) {
|
|
const node = new _TreeNode(block, [], [], 0);
|
|
node.changed = true;
|
|
return node;
|
|
}
|
|
};
|
|
var BlockEntry = class {
|
|
constructor(seq, tree, entry) {
|
|
this.seq = seq;
|
|
this.tree = tree;
|
|
this.index = null;
|
|
this.entry = entry;
|
|
this.key = entry.key;
|
|
this.value = entry.value;
|
|
}
|
|
isTarget(key) {
|
|
return b4a.equals(this.key, key);
|
|
}
|
|
inflate() {
|
|
if (this.index === null) {
|
|
this.index = inflate(this.entry);
|
|
}
|
|
}
|
|
isDeletion() {
|
|
if (this.value !== null) return false;
|
|
if (this.index === null) {
|
|
this.index = inflate(this.entry);
|
|
}
|
|
return !this.index.hasKey(this.seq);
|
|
}
|
|
final(encoding) {
|
|
return {
|
|
seq: this.seq,
|
|
key: encoding.key ? encoding.key.decode(this.key) : this.key,
|
|
value: this.value && (encoding.value ? encoding.value.decode(this.value) : this.value)
|
|
};
|
|
}
|
|
getTreeNode(offset) {
|
|
if (this.index === null) {
|
|
this.index = inflate(this.entry);
|
|
}
|
|
const entry = this.index.get(offset);
|
|
return new TreeNode(this, entry.keys, entry.children, offset);
|
|
}
|
|
};
|
|
var CacheLock = class {
|
|
constructor() {
|
|
this.map = /* @__PURE__ */ new Map();
|
|
}
|
|
enter(seq) {
|
|
const pending = this.map.get(seq);
|
|
if (!pending) {
|
|
this.map.set(seq, []);
|
|
return Promise.resolve();
|
|
}
|
|
const { resolve, promise } = rrp();
|
|
pending.push(resolve);
|
|
return promise;
|
|
}
|
|
exit(seq) {
|
|
const pending = this.map.get(seq);
|
|
if (!pending.length) {
|
|
this.map.delete(seq);
|
|
return;
|
|
}
|
|
pending.pop()();
|
|
}
|
|
};
|
|
var BatchEntry = class extends BlockEntry {
|
|
constructor(seq, tree, key, value, index) {
|
|
super(seq, tree, { key, value, index: null, inflated: null });
|
|
this.pendingIndex = index;
|
|
}
|
|
isTarget(key) {
|
|
return false;
|
|
}
|
|
getTreeNode(offset) {
|
|
return this.pendingIndex[offset].value;
|
|
}
|
|
};
|
|
var Hyperbee = class _Hyperbee extends ReadyResource {
|
|
constructor(core, opts = {}) {
|
|
super();
|
|
this.feed = core;
|
|
this.core = core;
|
|
this.keyEncoding = opts.keyEncoding ? codecs(opts.keyEncoding) : null;
|
|
this.valueEncoding = opts.valueEncoding ? codecs(opts.valueEncoding) : null;
|
|
this.extension = opts.extension !== false ? getExtension(this, opts) : null;
|
|
this.metadata = opts.metadata || null;
|
|
this.lock = opts.lock || mutexify();
|
|
this.sep = opts.sep || SEP;
|
|
this.readonly = !!opts.readonly;
|
|
this.prefix = opts.prefix || null;
|
|
this.alwaysDuplicate = opts.alwaysDuplicate !== false;
|
|
this._unprefixedKeyEncoding = this.keyEncoding;
|
|
this._sub = !!this.prefix;
|
|
this._checkout = opts.checkout || 0;
|
|
this._view = !!opts._view;
|
|
this._onappendBound = this._view ? null : this._onappend.bind(this);
|
|
this._ontruncateBound = this._view ? null : this._ontruncate.bind(this);
|
|
this._watchers = this._onappendBound ? [] : null;
|
|
this._entryWatchers = this._onappendBound ? [] : null;
|
|
this._sessions = opts.sessions !== false;
|
|
this._keyCache = null;
|
|
this._nodeCache = null;
|
|
this._cacheLock = new CacheLock();
|
|
this._batches = [];
|
|
if (this._watchers) {
|
|
this.core.on("append", this._onappendBound);
|
|
this.core.on("truncate", this._ontruncateBound);
|
|
}
|
|
if (this.prefix && opts._sub) {
|
|
this.keyEncoding = prefixEncoding(this.prefix, this.keyEncoding);
|
|
}
|
|
this.ready().catch(safetyCatch);
|
|
}
|
|
async _open() {
|
|
if (this.core.opened === false) await this.core.ready();
|
|
if (this._watchers && this.core.replicator.setInflightRange) {
|
|
this.core.replicator.setInflightRange(256, 512);
|
|
}
|
|
if (this._checkout === -1) this._checkout = Math.max(1, this.core.length);
|
|
const baseCache = Rache.from(this.core.globalCache);
|
|
this._keyCache = new Cache(baseCache);
|
|
this._nodeCache = new Cache(Rache.from(baseCache));
|
|
}
|
|
get version() {
|
|
return Math.max(1, this._checkout || this.core.length);
|
|
}
|
|
get id() {
|
|
return this.core.id;
|
|
}
|
|
get key() {
|
|
return this.core.key;
|
|
}
|
|
get discoveryKey() {
|
|
return this.core.discoveryKey;
|
|
}
|
|
get writable() {
|
|
return this.core.writable;
|
|
}
|
|
get readable() {
|
|
return this.core.readable;
|
|
}
|
|
replicate(isInitiator, opts) {
|
|
return this.core.replicate(isInitiator, opts);
|
|
}
|
|
update(opts) {
|
|
return this.core.update(opts);
|
|
}
|
|
peek(range, opts) {
|
|
return iteratorPeek(this.createRangeIterator(range, { ...opts, limit: 1 }));
|
|
}
|
|
createRangeIterator(range, opts = {}) {
|
|
opts = opts ? { ...opts, ...range } : range;
|
|
const extension = opts.extension === false && opts.limit !== 0 ? null : this.extension;
|
|
const keyEncoding = opts.keyEncoding ? codecs(opts.keyEncoding) : this.keyEncoding;
|
|
if (extension) {
|
|
const { onseq, onwait } = opts;
|
|
let version = 0;
|
|
let next = 0;
|
|
opts = encRange(keyEncoding, {
|
|
...opts,
|
|
sub: this._sub,
|
|
onseq(seq) {
|
|
if (!version) version = seq + 1;
|
|
if (next) next--;
|
|
if (onseq) onseq(seq);
|
|
},
|
|
onwait(seq) {
|
|
if (!next) {
|
|
next = Extension.BATCH_SIZE;
|
|
extension.iterator(ite.snapshot(version));
|
|
}
|
|
if (onwait) onwait(seq);
|
|
}
|
|
});
|
|
} else {
|
|
opts = encRange(keyEncoding, { ...opts, sub: this._sub });
|
|
}
|
|
const ite = new RangeIterator(
|
|
new Batch(this, this._makeSnapshot(), null, false, opts),
|
|
null,
|
|
opts
|
|
);
|
|
return ite;
|
|
}
|
|
createReadStream(range, opts) {
|
|
const signal = opts && opts.signal || null;
|
|
return iteratorToStream(this.createRangeIterator(range, opts), signal);
|
|
}
|
|
createHistoryStream(opts) {
|
|
const session = opts && opts.live ? this.core.session() : this._makeSnapshot();
|
|
const signal = opts && opts.signal || null;
|
|
return iteratorToStream(
|
|
new HistoryIterator(new Batch(this, session, null, false, opts), opts),
|
|
signal
|
|
);
|
|
}
|
|
createDiffStream(right, range, opts) {
|
|
if (typeof right === "number") right = this.checkout(Math.max(1, right), { reuseSession: true });
|
|
opts = opts ? { ...opts, ...range } : range;
|
|
const signal = opts && opts.signal || null;
|
|
const keyEncoding = opts && opts.keyEncoding ? codecs(opts.keyEncoding) : this.keyEncoding;
|
|
if (keyEncoding) opts = encRange(keyEncoding, { ...opts, sub: this._sub });
|
|
let done;
|
|
let closing;
|
|
let ite;
|
|
const left = this;
|
|
const rs = new Readable({
|
|
signal,
|
|
eagerOpen: true,
|
|
async open(cb) {
|
|
try {
|
|
if (right.opened === false) await right.ready();
|
|
if (left.opened === false) await left.ready();
|
|
} catch (err) {
|
|
cb(err);
|
|
return;
|
|
}
|
|
if (closing) {
|
|
cb(null);
|
|
return;
|
|
}
|
|
if (left.core.closing || right.core.closing) {
|
|
cb(new Error("Bee closed"));
|
|
return;
|
|
}
|
|
const snapshot = right.version > left.version ? right._makeSnapshot() : left._makeSnapshot();
|
|
done = cb;
|
|
ite = new DiffIterator(
|
|
new Batch(left, snapshot, null, false, opts),
|
|
new Batch(right, snapshot, null, false, opts),
|
|
opts
|
|
);
|
|
ite.open().then(fin, fin);
|
|
},
|
|
read(cb) {
|
|
done = cb;
|
|
ite.next().then(push, fin);
|
|
},
|
|
predestroy() {
|
|
if (!ite) {
|
|
closing = Promise.resolve();
|
|
} else {
|
|
closing = ite.close();
|
|
closing.catch(noop);
|
|
}
|
|
},
|
|
destroy(cb) {
|
|
done = cb;
|
|
if (!closing) closing = ite.close();
|
|
closing.then(fin, fin);
|
|
}
|
|
});
|
|
return rs;
|
|
function fin(err) {
|
|
done(err);
|
|
}
|
|
function push(val) {
|
|
rs.push(val);
|
|
done(null);
|
|
}
|
|
}
|
|
get(key, opts) {
|
|
const b = new Batch(this, this._makeSnapshot(), null, true, opts);
|
|
return b.get(key);
|
|
}
|
|
getBySeq(seq, opts) {
|
|
const b = new Batch(this, this._makeSnapshot(), null, true, opts);
|
|
return b.getBySeq(seq);
|
|
}
|
|
put(key, value, opts) {
|
|
const b = new Batch(this, this.core, null, true, opts);
|
|
return b.put(key, value, opts);
|
|
}
|
|
batch(opts) {
|
|
return new Batch(this, this.core, mutexify(), true, opts);
|
|
}
|
|
del(key, opts) {
|
|
const b = new Batch(this, this.core, null, true, opts);
|
|
return b.del(key, opts);
|
|
}
|
|
watch(range, opts) {
|
|
if (!this._watchers) throw new Error("Can only watch the main bee instance");
|
|
return new Watcher(this, range, opts);
|
|
}
|
|
async getAndWatch(key, opts) {
|
|
if (!this._watchers) throw new Error("Can only watch the main bee instance");
|
|
const watcher = new EntryWatcher(this, key, opts);
|
|
await watcher._debouncedUpdate();
|
|
if (this.closing) {
|
|
await watcher.close();
|
|
throw new Error("Bee closed");
|
|
}
|
|
return watcher;
|
|
}
|
|
_onappend() {
|
|
for (const watcher of this._watchers) {
|
|
watcher._onappend();
|
|
}
|
|
for (const watcher of this._entryWatchers) {
|
|
watcher._onappend();
|
|
}
|
|
}
|
|
_ontruncate(length) {
|
|
for (const watcher of this._watchers) {
|
|
watcher._ontruncate();
|
|
}
|
|
for (const watcher of this._entryWatchers) {
|
|
watcher._ontruncate();
|
|
}
|
|
this._nodeCache.gc(length);
|
|
this._keyCache.gc(length);
|
|
}
|
|
_makeSnapshot() {
|
|
if (this._sessions === false) return this.core;
|
|
return this._checkout <= this.core.length || this._checkout <= 1 ? this.core.snapshot() : this.core.session({ snapshot: false });
|
|
}
|
|
async clearUnlinked(options = {}) {
|
|
await this.ready();
|
|
const { gte = 0, lt = this.version - 1, batchSize = 4096, wait = true } = options;
|
|
const checkout = this.version;
|
|
let prev = this.batch({ wait: false, checkout: gte });
|
|
let b = this.batch({ wait, checkout });
|
|
const iteBatch = this.batch({ wait: false, checkout });
|
|
const ite = new LocalBlockIterator(iteBatch, { gte, lt });
|
|
await ite.open();
|
|
let ticks = 0;
|
|
while (true) {
|
|
const data = await ite.next();
|
|
if (!data) break;
|
|
if (!await isLinked(b, data)) {
|
|
if (b.core.closing || this.core.closing || this.closing) break;
|
|
await this.core.clear(data.seq);
|
|
}
|
|
const prevNode = await prev.get(data.key, { finalize: false }).catch(toNull);
|
|
if (prevNode && !await isLinked(b, prevNode)) {
|
|
if (b.core.closing || this.core.closing || this.closing) break;
|
|
await this.core.clear(prevNode.seq);
|
|
}
|
|
if (ticks++ >= batchSize) {
|
|
ticks = 0;
|
|
await prev.close();
|
|
await b.close();
|
|
prev = this.batch({ wait: false, checkout: gte });
|
|
b = this.batch({ wait, checkout });
|
|
}
|
|
}
|
|
if (b.core.closing || this.core.closing || this.closing) throw new Error("Core is closed");
|
|
await b.close();
|
|
await prev.close();
|
|
await ite.close();
|
|
await iteBatch.close();
|
|
return lt;
|
|
}
|
|
checkout(version, opts = {}) {
|
|
if (version === 0) version = 1;
|
|
const snap = opts.reuseSession || this._sessions === false ? this.core : version <= this.core.length || version <= 1 ? this.core.snapshot() : this.core.session({ snapshot: false });
|
|
return new _Hyperbee(snap, {
|
|
_view: true,
|
|
_sub: false,
|
|
prefix: this.prefix,
|
|
sep: this.sep,
|
|
lock: this.lock,
|
|
checkout: version,
|
|
keyEncoding: opts.keyEncoding || this.keyEncoding,
|
|
valueEncoding: opts.valueEncoding || this.valueEncoding,
|
|
extension: this.extension !== null ? this.extension : false
|
|
});
|
|
}
|
|
snapshot(opts) {
|
|
return this.checkout(
|
|
this.core.opened === false || this._checkout <= 0 ? -1 : Math.max(1, this.version),
|
|
opts
|
|
);
|
|
}
|
|
sub(prefix, opts = {}) {
|
|
let sep = opts.sep || this.sep;
|
|
if (!b4a.isBuffer(sep)) sep = b4a.from(sep);
|
|
prefix = b4a.concat([this.prefix || EMPTY, b4a.from(prefix), sep]);
|
|
const valueEncoding = codecs(opts.valueEncoding || this.valueEncoding);
|
|
const keyEncoding = codecs(opts.keyEncoding || this._unprefixedKeyEncoding);
|
|
return new _Hyperbee(this.core, {
|
|
_view: true,
|
|
_sub: true,
|
|
prefix,
|
|
sep: this.sep,
|
|
lock: this.lock,
|
|
checkout: this._checkout,
|
|
valueEncoding,
|
|
keyEncoding,
|
|
extension: this.extension !== null ? this.extension : false,
|
|
metadata: this.metadata
|
|
});
|
|
}
|
|
async getHeader(opts) {
|
|
const blk = await this.core.get(0, opts);
|
|
try {
|
|
return blk && Header.decode(blk);
|
|
} catch {
|
|
throw DECODING_ERROR();
|
|
}
|
|
}
|
|
async _close() {
|
|
if (!this._view) {
|
|
if (this._keyCache) this._keyCache.clear();
|
|
if (this._nodeCache) this._nodeCache.clear();
|
|
}
|
|
if (this._watchers) {
|
|
this.core.off("append", this._onappendBound);
|
|
this.core.off("truncate", this._ontruncateBound);
|
|
while (this._watchers.length) {
|
|
await this._watchers[this._watchers.length - 1].close();
|
|
}
|
|
}
|
|
if (this._entryWatchers) {
|
|
while (this._entryWatchers.length) {
|
|
await this._entryWatchers[this._entryWatchers.length - 1].close();
|
|
}
|
|
}
|
|
while (this._batches.length) {
|
|
await this._batches[this._batches.length - 1].close();
|
|
}
|
|
return this.core.close();
|
|
}
|
|
static async isHyperbee(core, opts) {
|
|
await core.ready();
|
|
const blk0 = await core.get(0, opts);
|
|
if (blk0 === null) throw BLOCK_NOT_AVAILABLE();
|
|
try {
|
|
return Header.decode(blk0).protocol === "hyperbee";
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
var Batch = class {
|
|
constructor(tree, core, batchLock, cache, options = {}) {
|
|
this.tree = tree;
|
|
this.feed = core;
|
|
this.core = core;
|
|
this.index = tree._batches.push(this) - 1;
|
|
this.blocks = cache ? /* @__PURE__ */ new Map() : null;
|
|
this.autoFlush = !batchLock;
|
|
this.maxBlocksCached = options.maxBlocksCached || 128;
|
|
this.rootSeq = 0;
|
|
this.root = null;
|
|
this.length = 0;
|
|
this.checkout = options.checkout === void 0 ? -1 : options.checkout;
|
|
this.options = options;
|
|
this.locked = null;
|
|
this.batchLock = batchLock;
|
|
this.onseq = this.options.onseq || noop;
|
|
this.appending = null;
|
|
this.isSnapshot = this.core !== this.tree.core;
|
|
this.shouldUpdate = this.options.update !== false;
|
|
this.updating = null;
|
|
this.encoding = {
|
|
key: options.keyEncoding ? codecs(options.keyEncoding) : tree.keyEncoding,
|
|
value: options.valueEncoding ? codecs(options.valueEncoding) : tree.valueEncoding
|
|
};
|
|
}
|
|
async ready() {
|
|
if (this.core.opened === false) await this.core.ready();
|
|
if (this.tree.opened === false) await this.tree.ready();
|
|
}
|
|
async lock() {
|
|
if (this.tree.readonly) throw new Error("Hyperbee is marked as read-only");
|
|
if (this.locked === null) this.locked = await this.tree.lock();
|
|
}
|
|
get version() {
|
|
if (this.checkout !== -1) return Math.max(1, this.checkout);
|
|
return Math.max(1, this.tree._checkout || this.core.length + this.length);
|
|
}
|
|
async getRoot(ensureHeader) {
|
|
await this.ready();
|
|
if (ensureHeader) {
|
|
if (this.core.length === 0 && this.core.writable && !this.tree.readonly) {
|
|
await this.core.append(
|
|
Header.encode({
|
|
protocol: "hyperbee",
|
|
metadata: this.tree.metadata
|
|
})
|
|
);
|
|
}
|
|
}
|
|
if (this.tree._checkout === 0 && this.checkout === -1 && this.shouldUpdate) {
|
|
if (this.updating === null) this.updating = this.core.update();
|
|
await this.updating;
|
|
}
|
|
if (this.version < 2) return null;
|
|
return (await this.getBlock(this.version - 1)).getTreeNode(0);
|
|
}
|
|
async getKey(seq) {
|
|
await this.tree._cacheLock.enter(seq);
|
|
try {
|
|
const k = this.core.fork === this.tree.core.fork ? this.tree._keyCache.get(seq) : null;
|
|
if (k !== null) return k;
|
|
const key = (await this._getBlock(seq)).key;
|
|
if (this.core.fork === this.tree.core.fork) this.tree._keyCache.set(seq, key);
|
|
return key;
|
|
} finally {
|
|
this.tree._cacheLock.exit(seq);
|
|
}
|
|
}
|
|
async _getNode(seq) {
|
|
const cached = this.tree._nodeCache !== null && this.core.fork === this.tree.core.fork ? this.tree._nodeCache.get(seq) : null;
|
|
if (cached !== null) return cached;
|
|
const entry = await this.core.get(seq, {
|
|
...this.options,
|
|
valueEncoding: Node
|
|
});
|
|
if (entry === null) throw BLOCK_NOT_AVAILABLE();
|
|
const wrap = copyEntry(entry);
|
|
if (this.core.fork === this.tree.core.fork && this.tree._nodeCache !== null) {
|
|
this.tree._nodeCache.set(seq, wrap);
|
|
}
|
|
return wrap;
|
|
}
|
|
async getBlock(seq) {
|
|
if (this.rootSeq === 0) this.rootSeq = seq;
|
|
await this.tree._cacheLock.enter(seq);
|
|
try {
|
|
return await this._getBlock(seq);
|
|
} finally {
|
|
this.tree._cacheLock.exit(seq);
|
|
}
|
|
}
|
|
async _getBlock(seq) {
|
|
let b = this.blocks && this.blocks.get(seq);
|
|
if (b) return b;
|
|
this.onseq(seq);
|
|
const entry = await this._getNode(seq);
|
|
b = this.blocks && this.blocks.get(seq);
|
|
if (b) return b;
|
|
b = new BlockEntry(seq, this, entry);
|
|
if (this.blocks && this.blocks.size - this.length < this.maxBlocksCached) {
|
|
this.blocks.set(seq, b);
|
|
}
|
|
return b;
|
|
}
|
|
_onwait(key) {
|
|
this.options.onwait = null;
|
|
this.tree.extension.get(this.rootSeq + 1, key);
|
|
}
|
|
_getEncoding(opts) {
|
|
if (!opts) return this.encoding;
|
|
return {
|
|
key: opts.keyEncoding ? codecs(opts.keyEncoding) : this.encoding.key,
|
|
value: opts.valueEncoding ? codecs(opts.valueEncoding) : this.encoding.value
|
|
};
|
|
}
|
|
peek(range, opts) {
|
|
return iteratorPeek(this.createRangeIterator(range, { ...opts, limit: 1 }));
|
|
}
|
|
createRangeIterator(range, opts = {}) {
|
|
opts = opts ? { ...opts, ...range } : range;
|
|
const encoding = this._getEncoding(opts);
|
|
return new RangeIterator(
|
|
this,
|
|
encoding,
|
|
encRange(encoding.key, { ...opts, sub: this.tree._sub })
|
|
);
|
|
}
|
|
createReadStream(range, opts) {
|
|
const signal = opts && opts.signal || null;
|
|
return iteratorToStream(this.createRangeIterator(range, opts), signal);
|
|
}
|
|
async getBySeq(seq, opts) {
|
|
const encoding = this._getEncoding(opts);
|
|
try {
|
|
const block = (await this.getBlock(seq)).final(encoding);
|
|
return { key: block.key, value: block.value };
|
|
} finally {
|
|
await this._closeSnapshot();
|
|
}
|
|
}
|
|
async get(key, opts) {
|
|
const encoding = this._getEncoding(opts);
|
|
const finalize = opts ? opts.finalize !== false : true;
|
|
try {
|
|
return await this._get(key, encoding, finalize);
|
|
} finally {
|
|
await this._closeSnapshot();
|
|
}
|
|
}
|
|
async _get(key, encoding, finalize) {
|
|
key = enc(encoding.key, key);
|
|
if (this.tree.extension !== null && this.options.extension !== false) {
|
|
this.options.onwait = this._onwait.bind(this, key);
|
|
}
|
|
let node = await this.getRoot(false);
|
|
if (!node) return null;
|
|
while (true) {
|
|
if (node.block.isTarget(key)) {
|
|
return node.block.isDeletion() ? null : finalize ? node.block.final(encoding) : node.block;
|
|
}
|
|
let s = 0;
|
|
let e = node.keys.length;
|
|
let c;
|
|
while (s < e) {
|
|
const mid = s + e >> 1;
|
|
c = b4a.compare(key, await node.getKey(mid));
|
|
if (c === 0) {
|
|
const block = await this.getBlock(node.keys[mid].seq);
|
|
return finalize ? block.final(encoding) : block;
|
|
}
|
|
if (c < 0) e = mid;
|
|
else s = mid + 1;
|
|
}
|
|
if (!node.children.length) return null;
|
|
const i = c < 0 ? e : s;
|
|
node = await node.getChildNode(i);
|
|
}
|
|
}
|
|
async links(key, seq) {
|
|
let node = await this.getRoot(false);
|
|
if (!node) return false;
|
|
if (node.block.seq === seq) return true;
|
|
while (true) {
|
|
if (node.block.isTarget(key)) return false;
|
|
let s = 0;
|
|
let e = node.keys.length;
|
|
let c;
|
|
while (s < e) {
|
|
const mid = s + e >> 1;
|
|
if (node.keys[mid].seq === seq) return true;
|
|
c = b4a.compare(key, await node.getKey(mid));
|
|
if (c === 0) return false;
|
|
if (c < 0) e = mid;
|
|
else s = mid + 1;
|
|
}
|
|
if (!node.children.length) return false;
|
|
const i = c < 0 ? e : s;
|
|
node = await node.getChildNode(i);
|
|
if (node.block.seq === seq) return true;
|
|
}
|
|
}
|
|
async put(key, value, opts) {
|
|
const release = this.batchLock ? await this.batchLock() : null;
|
|
const cas = opts && opts.cas || null;
|
|
const encoding = this._getEncoding(opts);
|
|
if (!this.locked) await this.lock();
|
|
if (!release) return this._put(key, value, encoding, cas);
|
|
try {
|
|
return await this._put(key, value, encoding, cas);
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
async _put(key, value, encoding, cas) {
|
|
const newNode = {
|
|
seq: 0,
|
|
key,
|
|
value
|
|
};
|
|
key = enc(encoding.key, key);
|
|
value = enc(encoding.value, value);
|
|
const stack = [];
|
|
let root;
|
|
let node = root = await this.getRoot(true);
|
|
if (!node) node = root = TreeNode.create(null);
|
|
const seq = newNode.seq = this.core.length + this.length;
|
|
const target = new Key(seq, key);
|
|
while (node.children.length) {
|
|
stack.push(node);
|
|
node.changed = true;
|
|
let s = 0;
|
|
let e = node.keys.length;
|
|
let c;
|
|
while (s < e) {
|
|
const mid = s + e >> 1;
|
|
c = b4a.compare(target.value, await node.getKey(mid));
|
|
if (c === 0) {
|
|
if (cas) {
|
|
const prev = await node.getKeyNode(mid);
|
|
if (!await cas(prev.final(encoding), newNode)) return this._unlockMaybe();
|
|
}
|
|
if (!this.tree.alwaysDuplicate) {
|
|
const prev = await node.getKeyNode(mid);
|
|
if (sameValue(prev.value, value)) return this._unlockMaybe();
|
|
}
|
|
node.setKey(mid, target);
|
|
return this._append(root, seq, key, value);
|
|
}
|
|
if (c < 0) e = mid;
|
|
else s = mid + 1;
|
|
}
|
|
const i = c < 0 ? e : s;
|
|
node = await node.getChildNode(i);
|
|
}
|
|
let needsSplit = !await node.insertKey(target, value, null, newNode, encoding, cas);
|
|
if (!node.changed) return this._unlockMaybe();
|
|
while (needsSplit) {
|
|
const parent = stack.pop();
|
|
const { median, right } = await node.split();
|
|
if (parent) {
|
|
needsSplit = !await parent.insertKey(median, value, right, null, encoding, null);
|
|
node = parent;
|
|
} else {
|
|
root = TreeNode.create(node.block);
|
|
root.changed = true;
|
|
root.keys.push(median);
|
|
root.children.push(new Child(0, 0, node), new Child(0, 0, right));
|
|
needsSplit = false;
|
|
}
|
|
}
|
|
return this._append(root, seq, key, value);
|
|
}
|
|
async del(key, opts) {
|
|
const release = this.batchLock ? await this.batchLock() : null;
|
|
const cas = opts && opts.cas || null;
|
|
const encoding = this._getEncoding(opts);
|
|
if (!this.locked) await this.lock();
|
|
if (!release) return this._del(key, encoding, cas);
|
|
try {
|
|
return await this._del(key, encoding, cas);
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
async _del(key, encoding, cas) {
|
|
const delNode = {
|
|
seq: 0,
|
|
key,
|
|
value: null
|
|
};
|
|
key = enc(encoding.key, key);
|
|
const stack = [];
|
|
let node = await this.getRoot(true);
|
|
if (!node) return this._unlockMaybe();
|
|
const seq = delNode.seq = this.core.length + this.length;
|
|
while (true) {
|
|
stack.push(node);
|
|
let s = 0;
|
|
let e = node.keys.length;
|
|
let c;
|
|
while (s < e) {
|
|
const mid = s + e >> 1;
|
|
c = b4a.compare(key, await node.getKey(mid));
|
|
if (c === 0) {
|
|
if (cas) {
|
|
const prev = await node.getKeyNode(mid);
|
|
if (!await cas(prev.final(encoding), delNode)) return this._unlockMaybe();
|
|
}
|
|
if (node.children.length) await setKeyToNearestLeaf(node, mid, stack);
|
|
else node.removeKey(mid);
|
|
for (const node2 of stack) node2.changed = true;
|
|
return this._append(await rebalance(stack), seq, key, null);
|
|
}
|
|
if (c < 0) e = mid;
|
|
else s = mid + 1;
|
|
}
|
|
if (!node.children.length) return this._unlockMaybe();
|
|
const i = c < 0 ? e : s;
|
|
node = await node.getChildNode(i);
|
|
}
|
|
}
|
|
async _closeSnapshot() {
|
|
if (this.isSnapshot) {
|
|
await this.core.close();
|
|
this._finalize();
|
|
}
|
|
}
|
|
async close() {
|
|
if (this.isSnapshot) return this._closeSnapshot();
|
|
this.root = null;
|
|
if (this.blocks) this.blocks.clear();
|
|
this.length = 0;
|
|
this._unlock();
|
|
}
|
|
destroy() {
|
|
this.close().catch(noop);
|
|
}
|
|
toBlocks() {
|
|
if (this.appending) return this.appending;
|
|
const batch = new Array(this.length);
|
|
for (let i = 0; i < this.length; i++) {
|
|
const seq = this.core.length + i;
|
|
const { pendingIndex, key, value } = this.blocks.get(seq);
|
|
if (i < this.length - 1) {
|
|
pendingIndex[0] = null;
|
|
let j = 0;
|
|
while (j < pendingIndex.length) {
|
|
const idx = pendingIndex[j];
|
|
if (idx !== null && idx.seq === seq) {
|
|
idx.offset = j++;
|
|
continue;
|
|
}
|
|
if (j === pendingIndex.length - 1) pendingIndex.pop();
|
|
else pendingIndex[j] = pendingIndex.pop();
|
|
}
|
|
}
|
|
batch[i] = Node.encode({
|
|
key,
|
|
value,
|
|
index: deflate(pendingIndex)
|
|
});
|
|
}
|
|
this.appending = batch;
|
|
return batch;
|
|
}
|
|
flush() {
|
|
if (!this.length) return this.close();
|
|
const batch = this.toBlocks();
|
|
this.root = null;
|
|
this.blocks.clear();
|
|
this.length = 0;
|
|
return this._appendBatch(batch);
|
|
}
|
|
_unlockMaybe() {
|
|
if (this.autoFlush) this._unlock();
|
|
}
|
|
_unlock() {
|
|
const locked = this.locked;
|
|
this.locked = null;
|
|
if (locked !== null) locked();
|
|
this._finalize();
|
|
}
|
|
_finalize() {
|
|
if (this.index >= this.tree._batches.length || this.tree._batches[this.index] !== this) return;
|
|
const top = this.tree._batches.pop();
|
|
if (top === this) return;
|
|
top.index = this.index;
|
|
this.tree._batches[top.index] = top;
|
|
}
|
|
_append(root, seq, key, value) {
|
|
const index = [];
|
|
root.indexChanges(index, seq);
|
|
index[0] = new Child(seq, 0, root);
|
|
if (!this.autoFlush) {
|
|
const block = new BatchEntry(seq, this, key, value, index);
|
|
root.block = block;
|
|
this.root = root;
|
|
this.length++;
|
|
this.blocks.set(seq, block);
|
|
root.updateChildren(seq, block);
|
|
return;
|
|
}
|
|
return this._appendBatch(
|
|
Node.encode({
|
|
key,
|
|
value,
|
|
index: deflate(index)
|
|
})
|
|
);
|
|
}
|
|
async _appendBatch(raw) {
|
|
try {
|
|
await this.core.append(raw);
|
|
} finally {
|
|
this._unlock();
|
|
}
|
|
}
|
|
};
|
|
var EntryWatcher = class extends ReadyResource {
|
|
constructor(bee, key, opts = {}) {
|
|
super();
|
|
this.keyEncoding = opts.keyEncoding || bee.keyEncoding;
|
|
this.valueEncoding = opts.valueEncoding || bee.valueEncoding;
|
|
this.index = bee._entryWatchers.push(this) - 1;
|
|
this.bee = bee;
|
|
this.key = key;
|
|
this.node = null;
|
|
this._forceUpdate = false;
|
|
this._debouncedUpdate = debounce(this._processUpdate.bind(this));
|
|
}
|
|
_close() {
|
|
const top = this.bee._entryWatchers.pop();
|
|
if (top !== this) {
|
|
top.index = this.index;
|
|
this.bee._entryWatchers[top.index] = top;
|
|
}
|
|
}
|
|
_onappend() {
|
|
this._debouncedUpdate();
|
|
}
|
|
_ontruncate() {
|
|
this._forceUpdate = true;
|
|
this._debouncedUpdate();
|
|
}
|
|
async _processUpdate() {
|
|
const force = this._forceUpdate;
|
|
this._forceUpdate = false;
|
|
let newNode;
|
|
try {
|
|
newNode = await this.bee.get(this.key, {
|
|
keyEncoding: this.keyEncoding,
|
|
valueEncoding: this.valueEncoding
|
|
});
|
|
} catch (e) {
|
|
if (e.code === "SNAPSHOT_NOT_AVAILABLE") {
|
|
return;
|
|
} else if (this.bee.closing) {
|
|
this.close().catch(safetyCatch);
|
|
return;
|
|
}
|
|
this.emit("error", e);
|
|
return;
|
|
}
|
|
if (force || newNode?.seq !== this.node?.seq) {
|
|
this.node = newNode;
|
|
this.emit("update");
|
|
}
|
|
}
|
|
};
|
|
var Watcher = class extends ReadyResource {
|
|
constructor(bee, range, opts = {}) {
|
|
super();
|
|
this.keyEncoding = opts.keyEncoding || bee.keyEncoding;
|
|
this.valueEncoding = opts.valueEncoding || bee.valueEncoding;
|
|
this.index = bee._watchers.push(this) - 1;
|
|
this.bee = bee;
|
|
this.core = bee.core;
|
|
this.latestDiff = 0;
|
|
this.range = range;
|
|
this.map = opts.map || defaultWatchMap;
|
|
this.current = null;
|
|
this.previous = null;
|
|
this.currentMapped = null;
|
|
this.previousMapped = null;
|
|
this.stream = null;
|
|
this._lock = mutexify();
|
|
this._flowing = false;
|
|
this._resolveOnChange = null;
|
|
this._differ = opts.differ || defaultDiffer;
|
|
this._eager = !!opts.eager;
|
|
this._onchange = opts.onchange || null;
|
|
this.on("newListener", autoFlowOnUpdate);
|
|
this.ready().catch(safetyCatch);
|
|
}
|
|
async _consume() {
|
|
if (this._flowing) return;
|
|
try {
|
|
for await (const _ of this) {
|
|
}
|
|
} catch {
|
|
}
|
|
}
|
|
async _open() {
|
|
await this.bee.ready();
|
|
const opts = {
|
|
keyEncoding: this.keyEncoding,
|
|
valueEncoding: this.valueEncoding
|
|
};
|
|
this.current = this._eager ? this.bee.checkout(1, opts) : this.bee.snapshot(opts);
|
|
await this.current.ready();
|
|
if (this._onchange) {
|
|
if (this._eager) await this._onchange();
|
|
this._consume();
|
|
}
|
|
}
|
|
[Symbol.asyncIterator]() {
|
|
this._flowing = true;
|
|
return this;
|
|
}
|
|
_ontruncate() {
|
|
this._onappend();
|
|
}
|
|
_onappend() {
|
|
const resolve = this._resolveOnChange;
|
|
this._resolveOnChange = null;
|
|
if (resolve) resolve();
|
|
}
|
|
async _waitForChanges() {
|
|
if (this.current.version < this.bee.version || this.closing) return;
|
|
await new Promise((resolve) => {
|
|
this._resolveOnChange = resolve;
|
|
});
|
|
}
|
|
async next() {
|
|
try {
|
|
return await this._next();
|
|
} catch (err) {
|
|
if (this.closing) return { value: void 0, done: true };
|
|
await this.close();
|
|
throw err;
|
|
}
|
|
}
|
|
async _next() {
|
|
const release = await this._lock();
|
|
try {
|
|
if (this.closing) return { value: void 0, done: true };
|
|
if (!this.opened) await this.ready();
|
|
while (true) {
|
|
await this._waitForChanges();
|
|
if (this.closing) return { value: void 0, done: true };
|
|
await this._closePrevious();
|
|
this.previous = this.current.snapshot();
|
|
await this._closeCurrent();
|
|
this.current = this.bee.snapshot({
|
|
keyEncoding: this.keyEncoding,
|
|
valueEncoding: this.valueEncoding
|
|
});
|
|
await this.current.ready();
|
|
await this.previous.ready();
|
|
if (this.current.core.fork !== this.previous.core.fork) {
|
|
return await this._yield();
|
|
}
|
|
this.stream = this._differ(this.current, this.previous, this.range);
|
|
try {
|
|
for await (const data of this.stream) {
|
|
return await this._yield();
|
|
}
|
|
} finally {
|
|
this.stream = null;
|
|
}
|
|
}
|
|
} finally {
|
|
release();
|
|
}
|
|
}
|
|
async _yield() {
|
|
this.currentMapped = this.map(this.current);
|
|
this.previousMapped = this.map(this.previous);
|
|
if (this._onchange) {
|
|
try {
|
|
await this._onchange();
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
}
|
|
}
|
|
this.emit("update");
|
|
return { done: false, value: [this.currentMapped, this.previousMapped] };
|
|
}
|
|
async return() {
|
|
await this.close();
|
|
return { done: true };
|
|
}
|
|
async _close() {
|
|
const top = this.bee._watchers.pop();
|
|
if (top !== this) {
|
|
top.index = this.index;
|
|
this.bee._watchers[top.index] = top;
|
|
}
|
|
if (this.stream && !this.stream.destroying) {
|
|
this.stream.destroy();
|
|
}
|
|
this._onappend();
|
|
await this._closeCurrent().catch(safetyCatch);
|
|
await this._closePrevious().catch(safetyCatch);
|
|
const release = await this._lock();
|
|
release();
|
|
}
|
|
destroy() {
|
|
return this.close();
|
|
}
|
|
async _closeCurrent() {
|
|
if (this.currentMapped) await this.currentMapped.close();
|
|
if (this.current) await this.current.close();
|
|
this.current = this.currentMapped = null;
|
|
}
|
|
async _closePrevious() {
|
|
if (this.previousMapped) await this.previousMapped.close();
|
|
if (this.previous) await this.previous.close();
|
|
this.previous = this.previousMapped = null;
|
|
}
|
|
};
|
|
function autoFlowOnUpdate(name) {
|
|
if (name === "update") this._consume();
|
|
}
|
|
function defaultWatchMap(snapshot) {
|
|
return snapshot;
|
|
}
|
|
async function leafSize(node, goLeft) {
|
|
while (node.children.length) node = await node.getChildNode(goLeft ? 0 : node.children.length - 1);
|
|
return node.keys.length;
|
|
}
|
|
async function setKeyToNearestLeaf(node, index, stack) {
|
|
let [left, right] = await Promise.all([node.getChildNode(index), node.getChildNode(index + 1)]);
|
|
const [ls, rs] = await Promise.all([leafSize(left, false), leafSize(right, true)]);
|
|
if (ls < rs) {
|
|
stack.push(right);
|
|
while (right.children.length) stack.push(right = right.children[0].value);
|
|
node.keys[index] = right.keys.shift();
|
|
} else {
|
|
stack.push(left);
|
|
while (left.children.length) stack.push(left = left.children[left.children.length - 1].value);
|
|
node.keys[index] = left.keys.pop();
|
|
}
|
|
}
|
|
async function rebalance(stack) {
|
|
const root = stack[0];
|
|
while (stack.length > 1) {
|
|
const node = stack.pop();
|
|
const parent = stack[stack.length - 1];
|
|
if (node.keys.length >= MIN_KEYS) return root;
|
|
let { left, index, right } = await node.siblings(parent);
|
|
if (left && left.keys.length > MIN_KEYS) {
|
|
left.changed = true;
|
|
node.keys.unshift(parent.keys[index - 1]);
|
|
if (left.children.length) node.children.unshift(left.children.pop());
|
|
parent.keys[index - 1] = left.keys.pop();
|
|
return root;
|
|
}
|
|
if (right && right.keys.length > MIN_KEYS) {
|
|
right.changed = true;
|
|
node.keys.push(parent.keys[index]);
|
|
if (right.children.length) node.children.push(right.children.shift());
|
|
parent.keys[index] = right.keys.shift();
|
|
return root;
|
|
}
|
|
if (left) {
|
|
index--;
|
|
right = node;
|
|
} else {
|
|
left = node;
|
|
}
|
|
left.merge(right, parent.keys[index]);
|
|
parent.removeKey(index);
|
|
}
|
|
if (!root.keys.length && root.children.length) return root.getChildNode(0);
|
|
return root;
|
|
}
|
|
function iteratorToStream(ite, signal) {
|
|
let done;
|
|
let closing;
|
|
const rs = new Readable({
|
|
signal,
|
|
open(cb) {
|
|
done = cb;
|
|
ite.open().then(fin, fin);
|
|
},
|
|
read(cb) {
|
|
done = cb;
|
|
ite.next().then(push, fin);
|
|
},
|
|
predestroy() {
|
|
closing = ite.close();
|
|
closing.catch(noop);
|
|
},
|
|
destroy(cb) {
|
|
done = cb;
|
|
if (!closing) closing = ite.close();
|
|
closing.then(fin, fin);
|
|
}
|
|
});
|
|
return rs;
|
|
function fin(err) {
|
|
done(err);
|
|
}
|
|
function push(val) {
|
|
rs.push(val);
|
|
done(null);
|
|
}
|
|
}
|
|
async function iteratorPeek(ite) {
|
|
try {
|
|
await ite.open();
|
|
return await ite.next();
|
|
} finally {
|
|
await ite.close();
|
|
}
|
|
}
|
|
function encRange(e, opts) {
|
|
if (!e) return opts;
|
|
if (e.encodeRange) {
|
|
const r = e.encodeRange({
|
|
gt: opts.gt,
|
|
gte: opts.gte,
|
|
lt: opts.lt,
|
|
lte: opts.lte
|
|
});
|
|
opts.gt = r.gt;
|
|
opts.gte = r.gte;
|
|
opts.lt = r.lt;
|
|
opts.lte = r.lte;
|
|
return opts;
|
|
}
|
|
if (opts.gt !== void 0) opts.gt = enc(e, opts.gt);
|
|
if (opts.gte !== void 0) opts.gte = enc(e, opts.gte);
|
|
if (opts.lt !== void 0) opts.lt = enc(e, opts.lt);
|
|
if (opts.lte !== void 0) opts.lte = enc(e, opts.lte);
|
|
if (opts.sub && !opts.gt && !opts.gte) opts.gt = enc(e, SEP);
|
|
if (opts.sub && !opts.lt && !opts.lte) opts.lt = bump(enc(e, EMPTY));
|
|
return opts;
|
|
}
|
|
function bump(key) {
|
|
key[key.length - 1]++;
|
|
return key;
|
|
}
|
|
function enc(e, v) {
|
|
if (v === void 0 || v === null) return null;
|
|
if (e !== null) return e.encode(v);
|
|
if (typeof v === "string") return b4a.from(v);
|
|
return v;
|
|
}
|
|
function prefixEncoding(prefix, keyEncoding) {
|
|
return {
|
|
encode(key) {
|
|
return b4a.concat([prefix, b4a.isBuffer(key) ? key : enc(keyEncoding, key)]);
|
|
},
|
|
decode(key) {
|
|
const sliced = key.slice(prefix.length, key.length);
|
|
return keyEncoding ? keyEncoding.decode(sliced) : sliced;
|
|
}
|
|
};
|
|
}
|
|
function copyEntry(entry) {
|
|
let key = entry.key;
|
|
let value = entry.value;
|
|
let index = entry.index;
|
|
const size = key.byteLength + (value === null ? 0 : value.byteLength) + (index === null ? 0 : index.byteLength);
|
|
if (2 * size < key.buffer.byteLength) {
|
|
const [newKey, newValue, newIndex] = unslabAll([entry.key, entry.value, entry.index]);
|
|
key = newKey;
|
|
value = newValue;
|
|
index = newIndex;
|
|
}
|
|
return {
|
|
key,
|
|
value,
|
|
index,
|
|
inflated: null
|
|
};
|
|
}
|
|
function defaultDiffer(currentSnap, previousSnap, opts) {
|
|
return currentSnap.createDiffStream(previousSnap, opts);
|
|
}
|
|
function toNull() {
|
|
return null;
|
|
}
|
|
function getBackingCore(core) {
|
|
if (core.core) return core;
|
|
if (core.getBackingCore) return core.getBackingCore().session;
|
|
return null;
|
|
}
|
|
function sameValue(a, b) {
|
|
return a === b || a !== null && b !== null && b4a.equals(a, b);
|
|
}
|
|
function noop() {
|
|
}
|
|
function getExtension(db, opts) {
|
|
if (opts.extension === false) return null;
|
|
if (opts.extension && opts.extension !== true) return opts.extension;
|
|
return Extension.register(db);
|
|
}
|
|
async function isLinked(batch, block) {
|
|
const seq = block.seq;
|
|
block.inflate();
|
|
const keys = [block.key];
|
|
const wait = batch.options.wait;
|
|
for (const l of block.index.levels) {
|
|
if (!l.keys.length) continue;
|
|
batch.options.wait = false;
|
|
try {
|
|
keys.push(await batch.getKey(l.keys[0].seq));
|
|
} catch {
|
|
}
|
|
batch.options.wait = wait;
|
|
}
|
|
for (const k of keys) {
|
|
if (await batch.links(k, seq)) return true;
|
|
}
|
|
if (batch.core.closing) throw new Error("Core is closed");
|
|
return false;
|
|
}
|
|
module.exports = Hyperbee;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperblobs/lib/prefetcher.js
|
|
var require_prefetcher = __commonJS({
|
|
"../../node_modules/hyperblobs/lib/prefetcher.js"(exports, module) {
|
|
var MAX_READAHEAD_TARGET = 0.05;
|
|
module.exports = class Prefetcher {
|
|
constructor(core, { max = 64, start = 0, end = core.length, linear = true } = {}) {
|
|
this.core = core;
|
|
this.max = max;
|
|
this.range = null;
|
|
this.startBound = start;
|
|
this.endBound = end;
|
|
this.maxReadAhead = Math.max(max * 2, Math.floor((end - start) * MAX_READAHEAD_TARGET));
|
|
this.start = start;
|
|
this.end = start;
|
|
this.linear = linear;
|
|
this.missing = 0;
|
|
this._ondownloadBound = this._ondownload.bind(this);
|
|
this.core.on("download", this._ondownloadBound);
|
|
}
|
|
_ondownload(index) {
|
|
if (this.range && index < this.end && this.start <= index) {
|
|
this.missing--;
|
|
this._update();
|
|
}
|
|
}
|
|
destroy() {
|
|
this.core.off("download", this._ondownloadBound);
|
|
if (this.range) this.range.destroy();
|
|
this.range = null;
|
|
this.max = 0;
|
|
}
|
|
update(position) {
|
|
this.start = position;
|
|
if (!this.range) this._update();
|
|
}
|
|
_update() {
|
|
if (this.missing >= this.max) return;
|
|
if (this.range) this.range.destroy();
|
|
let end = this.end;
|
|
while (end < this.endBound && this.missing < this.max) {
|
|
end = this.core.core.bitfield.firstUnset(end) + 1;
|
|
if (end >= this.endBound) break;
|
|
this.missing++;
|
|
}
|
|
if (end > this.start + this.maxReadAhead) end = this.start + this.maxReadAhead;
|
|
if (end >= this.endBound) end = this.endBound;
|
|
this.end = end;
|
|
if (this.start >= this.end) return;
|
|
this.range = this.core.download({
|
|
start: this.start,
|
|
end: this.end,
|
|
linear: this.linear
|
|
});
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/compact-encoding/endian.js
|
|
var require_endian = __commonJS({
|
|
"../../node_modules/compact-encoding/endian.js"(exports) {
|
|
var LE = exports.LE = new Uint8Array(new Uint16Array([255]).buffer)[0] === 255;
|
|
exports.BE = !LE;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/compact-encoding/raw.js
|
|
var require_raw = __commonJS({
|
|
"../../node_modules/compact-encoding/raw.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var { BE } = require_endian();
|
|
exports = module.exports = {
|
|
preencode(state, b) {
|
|
state.end += b.byteLength;
|
|
},
|
|
encode(state, b) {
|
|
state.buffer.set(b, state.start);
|
|
state.start += b.byteLength;
|
|
},
|
|
decode(state) {
|
|
const b = state.buffer.subarray(state.start, state.end);
|
|
state.start = state.end;
|
|
return b;
|
|
}
|
|
};
|
|
var buffer = exports.buffer = {
|
|
preencode(state, b) {
|
|
if (b) uint8array.preencode(state, b);
|
|
else state.end++;
|
|
},
|
|
encode(state, b) {
|
|
if (b) uint8array.encode(state, b);
|
|
else state.buffer[state.start++] = 0;
|
|
},
|
|
decode(state) {
|
|
const b = state.buffer.subarray(state.start);
|
|
if (b.byteLength === 0) return null;
|
|
state.start = state.end;
|
|
return b;
|
|
}
|
|
};
|
|
exports.binary = {
|
|
...buffer,
|
|
preencode(state, b) {
|
|
if (typeof b === "string") utf8.preencode(state, b);
|
|
else buffer.preencode(state, b);
|
|
},
|
|
encode(state, b) {
|
|
if (typeof b === "string") utf8.encode(state, b);
|
|
else buffer.encode(state, b);
|
|
}
|
|
};
|
|
exports.arraybuffer = {
|
|
preencode(state, b) {
|
|
state.end += b.byteLength;
|
|
},
|
|
encode(state, b) {
|
|
const view = new Uint8Array(b);
|
|
state.buffer.set(view, state.start);
|
|
state.start += b.byteLength;
|
|
},
|
|
decode(state) {
|
|
const b = new ArrayBuffer(state.end - state.start);
|
|
const view = new Uint8Array(b);
|
|
view.set(state.buffer.subarray(state.start));
|
|
state.start = state.end;
|
|
return b;
|
|
}
|
|
};
|
|
function typedarray(TypedArray, swap) {
|
|
const n = TypedArray.BYTES_PER_ELEMENT;
|
|
return {
|
|
preencode(state, b) {
|
|
state.end += b.byteLength;
|
|
},
|
|
encode(state, b) {
|
|
const view = new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
|
|
if (BE && swap) swap(view);
|
|
state.buffer.set(view, state.start);
|
|
state.start += b.byteLength;
|
|
},
|
|
decode(state) {
|
|
let b = state.buffer.subarray(state.start);
|
|
if (b.byteOffset % n !== 0) b = new Uint8Array(b);
|
|
if (BE && swap) swap(b);
|
|
state.start = state.end;
|
|
return new TypedArray(b.buffer, b.byteOffset, b.byteLength / n);
|
|
}
|
|
};
|
|
}
|
|
var uint8array = exports.uint8array = typedarray(Uint8Array);
|
|
exports.uint16array = typedarray(Uint16Array, b4a.swap16);
|
|
exports.uint32array = typedarray(Uint32Array, b4a.swap32);
|
|
exports.int8array = typedarray(Int8Array);
|
|
exports.int16array = typedarray(Int16Array, b4a.swap16);
|
|
exports.int32array = typedarray(Int32Array, b4a.swap32);
|
|
exports.biguint64array = typedarray(BigUint64Array, b4a.swap64);
|
|
exports.bigint64array = typedarray(BigInt64Array, b4a.swap64);
|
|
exports.float32array = typedarray(Float32Array, b4a.swap32);
|
|
exports.float64array = typedarray(Float64Array, b4a.swap64);
|
|
function string(encoding) {
|
|
return {
|
|
preencode(state, s) {
|
|
state.end += b4a.byteLength(s, encoding);
|
|
},
|
|
encode(state, s) {
|
|
state.start += b4a.write(state.buffer, s, state.start, encoding);
|
|
},
|
|
decode(state) {
|
|
const s = b4a.toString(state.buffer, encoding, state.start);
|
|
state.start = state.end;
|
|
return s;
|
|
}
|
|
};
|
|
}
|
|
var utf8 = exports.string = exports.utf8 = string("utf-8");
|
|
exports.ascii = string("ascii");
|
|
exports.hex = string("hex");
|
|
exports.base64 = string("base64");
|
|
exports.ucs2 = exports.utf16le = string("utf16le");
|
|
exports.array = function array(enc) {
|
|
return {
|
|
preencode(state, list) {
|
|
for (const value of list) enc.preencode(state, value);
|
|
},
|
|
encode(state, list) {
|
|
for (const value of list) enc.encode(state, value);
|
|
},
|
|
decode(state) {
|
|
const arr = [];
|
|
while (state.start < state.end) arr.push(enc.decode(state));
|
|
return arr;
|
|
}
|
|
};
|
|
};
|
|
exports.json = {
|
|
preencode(state, v) {
|
|
utf8.preencode(state, JSON.stringify(v));
|
|
},
|
|
encode(state, v) {
|
|
utf8.encode(state, JSON.stringify(v));
|
|
},
|
|
decode(state) {
|
|
return JSON.parse(utf8.decode(state));
|
|
}
|
|
};
|
|
exports.ndjson = {
|
|
preencode(state, v) {
|
|
utf8.preencode(state, JSON.stringify(v) + "\n");
|
|
},
|
|
encode(state, v) {
|
|
utf8.encode(state, JSON.stringify(v) + "\n");
|
|
},
|
|
decode(state) {
|
|
return JSON.parse(utf8.decode(state));
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/compact-encoding/lexint.js
|
|
var require_lexint = __commonJS({
|
|
"../../node_modules/compact-encoding/lexint.js"(exports, module) {
|
|
module.exports = {
|
|
preencode,
|
|
encode,
|
|
decode
|
|
};
|
|
function preencode(state, num) {
|
|
if (num < 251) {
|
|
state.end++;
|
|
} else if (num < 256) {
|
|
state.end += 2;
|
|
} else if (num < 65536) {
|
|
state.end += 3;
|
|
} else if (num < 16777216) {
|
|
state.end += 4;
|
|
} else if (num < 4294967296) {
|
|
state.end += 5;
|
|
} else {
|
|
state.end++;
|
|
const exp = Math.floor(Math.log(num) / Math.log(2)) - 32;
|
|
preencode(state, exp);
|
|
state.end += 6;
|
|
}
|
|
}
|
|
function encode(state, num) {
|
|
const max = 251;
|
|
const x = num - max;
|
|
if (num < max) {
|
|
state.buffer[state.start++] = num;
|
|
} else if (num < 256) {
|
|
state.buffer[state.start++] = max;
|
|
state.buffer[state.start++] = x;
|
|
} else if (num < 65536) {
|
|
state.buffer[state.start++] = max + 1;
|
|
state.buffer[state.start++] = x >> 8 & 255;
|
|
state.buffer[state.start++] = x & 255;
|
|
} else if (num < 16777216) {
|
|
state.buffer[state.start++] = max + 2;
|
|
state.buffer[state.start++] = x >> 16;
|
|
state.buffer[state.start++] = x >> 8 & 255;
|
|
state.buffer[state.start++] = x & 255;
|
|
} else if (num < 4294967296) {
|
|
state.buffer[state.start++] = max + 3;
|
|
state.buffer[state.start++] = x >> 24;
|
|
state.buffer[state.start++] = x >> 16 & 255;
|
|
state.buffer[state.start++] = x >> 8 & 255;
|
|
state.buffer[state.start++] = x & 255;
|
|
} else {
|
|
const exp = Math.floor(Math.log(x) / Math.log(2)) - 32;
|
|
state.buffer[state.start++] = 255;
|
|
encode(state, exp);
|
|
const rem = x / Math.pow(2, exp - 11);
|
|
for (let i = 5; i >= 0; i--) {
|
|
state.buffer[state.start++] = rem / Math.pow(2, 8 * i) & 255;
|
|
}
|
|
}
|
|
}
|
|
function decode(state) {
|
|
const max = 251;
|
|
if (state.end - state.start < 1) throw new Error("Out of bounds");
|
|
const flag = state.buffer[state.start++];
|
|
if (flag < max) return flag;
|
|
if (state.end - state.start < flag - max + 1) {
|
|
throw new Error("Out of bounds.");
|
|
}
|
|
if (flag < 252) {
|
|
return state.buffer[state.start++] + max;
|
|
}
|
|
if (flag < 253) {
|
|
return (state.buffer[state.start++] << 8) + state.buffer[state.start++] + max;
|
|
}
|
|
if (flag < 254) {
|
|
return (state.buffer[state.start++] << 16) + (state.buffer[state.start++] << 8) + state.buffer[state.start++] + max;
|
|
}
|
|
if (flag < 255) {
|
|
return state.buffer[state.start++] * 16777216 + (state.buffer[state.start++] << 16) + (state.buffer[state.start++] << 8) + state.buffer[state.start++] + max;
|
|
}
|
|
const exp = decode(state);
|
|
if (state.end - state.start < 6) throw new Error("Out of bounds");
|
|
let rem = 0;
|
|
for (let i = 5; i >= 0; i--) {
|
|
rem += state.buffer[state.start++] * Math.pow(2, 8 * i);
|
|
}
|
|
return rem * Math.pow(2, exp - 11) + max;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/compact-encoding/index.js
|
|
var require_compact_encoding = __commonJS({
|
|
"../../node_modules/compact-encoding/index.js"(exports) {
|
|
var b4a = require_b4a();
|
|
var { BE } = require_endian();
|
|
exports.state = function(start = 0, end = 0, buffer2 = null) {
|
|
return { start, end, buffer: buffer2 };
|
|
};
|
|
var raw = exports.raw = require_raw();
|
|
var uint = exports.uint = {
|
|
preencode(state, n) {
|
|
state.end += n <= 252 ? 1 : n <= 65535 ? 3 : n <= 4294967295 ? 5 : 9;
|
|
},
|
|
encode(state, n) {
|
|
if (n <= 252) uint8.encode(state, n);
|
|
else if (n <= 65535) {
|
|
state.buffer[state.start++] = 253;
|
|
uint16.encode(state, n);
|
|
} else if (n <= 4294967295) {
|
|
state.buffer[state.start++] = 254;
|
|
uint32.encode(state, n);
|
|
} else {
|
|
state.buffer[state.start++] = 255;
|
|
uint64.encode(state, n);
|
|
}
|
|
},
|
|
decode(state) {
|
|
const a = uint8.decode(state);
|
|
if (a <= 252) return a;
|
|
if (a === 253) return uint16.decode(state);
|
|
if (a === 254) return uint32.decode(state);
|
|
return uint64.decode(state);
|
|
}
|
|
};
|
|
var uint8 = exports.uint8 = {
|
|
preencode(state, n) {
|
|
state.end += 1;
|
|
},
|
|
encode(state, n) {
|
|
validateUint(n);
|
|
state.buffer[state.start++] = n;
|
|
},
|
|
decode(state) {
|
|
if (state.start >= state.end) throw new Error("Out of bounds");
|
|
return state.buffer[state.start++];
|
|
}
|
|
};
|
|
var uint16 = exports.uint16 = {
|
|
preencode(state, n) {
|
|
state.end += 2;
|
|
},
|
|
encode(state, n) {
|
|
validateUint(n);
|
|
state.buffer[state.start++] = n;
|
|
state.buffer[state.start++] = n >>> 8;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 2) throw new Error("Out of bounds");
|
|
return state.buffer[state.start++] + state.buffer[state.start++] * 256;
|
|
}
|
|
};
|
|
var uint24 = exports.uint24 = {
|
|
preencode(state, n) {
|
|
state.end += 3;
|
|
},
|
|
encode(state, n) {
|
|
validateUint(n);
|
|
state.buffer[state.start++] = n;
|
|
state.buffer[state.start++] = n >>> 8;
|
|
state.buffer[state.start++] = n >>> 16;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 3) throw new Error("Out of bounds");
|
|
return state.buffer[state.start++] + state.buffer[state.start++] * 256 + state.buffer[state.start++] * 65536;
|
|
}
|
|
};
|
|
var uint32 = exports.uint32 = {
|
|
preencode(state, n) {
|
|
state.end += 4;
|
|
},
|
|
encode(state, n) {
|
|
validateUint(n);
|
|
state.buffer[state.start++] = n;
|
|
state.buffer[state.start++] = n >>> 8;
|
|
state.buffer[state.start++] = n >>> 16;
|
|
state.buffer[state.start++] = n >>> 24;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 4) throw new Error("Out of bounds");
|
|
return state.buffer[state.start++] + state.buffer[state.start++] * 256 + state.buffer[state.start++] * 65536 + state.buffer[state.start++] * 16777216;
|
|
}
|
|
};
|
|
var uint40 = exports.uint40 = {
|
|
preencode(state, n) {
|
|
state.end += 5;
|
|
},
|
|
encode(state, n) {
|
|
validateUint(n);
|
|
const r = Math.floor(n / 256);
|
|
uint8.encode(state, n);
|
|
uint32.encode(state, r);
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 5) throw new Error("Out of bounds");
|
|
return uint8.decode(state) + 256 * uint32.decode(state);
|
|
}
|
|
};
|
|
var uint48 = exports.uint48 = {
|
|
preencode(state, n) {
|
|
state.end += 6;
|
|
},
|
|
encode(state, n) {
|
|
validateUint(n);
|
|
const r = Math.floor(n / 65536);
|
|
uint16.encode(state, n);
|
|
uint32.encode(state, r);
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 6) throw new Error("Out of bounds");
|
|
return uint16.decode(state) + 65536 * uint32.decode(state);
|
|
}
|
|
};
|
|
var uint56 = exports.uint56 = {
|
|
preencode(state, n) {
|
|
state.end += 7;
|
|
},
|
|
encode(state, n) {
|
|
validateUint(n);
|
|
const r = Math.floor(n / 16777216);
|
|
uint24.encode(state, n);
|
|
uint32.encode(state, r);
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 7) throw new Error("Out of bounds");
|
|
return uint24.decode(state) + 16777216 * uint32.decode(state);
|
|
}
|
|
};
|
|
var uint64 = exports.uint64 = {
|
|
preencode(state, n) {
|
|
state.end += 8;
|
|
},
|
|
encode(state, n) {
|
|
validateUint(n);
|
|
const r = Math.floor(n / 4294967296);
|
|
uint32.encode(state, n);
|
|
uint32.encode(state, r);
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 8) throw new Error("Out of bounds");
|
|
return uint32.decode(state) + 4294967296 * uint32.decode(state);
|
|
}
|
|
};
|
|
var int = exports.int = zigZagInt(uint);
|
|
exports.int8 = zigZagInt(uint8);
|
|
exports.int16 = zigZagInt(uint16);
|
|
exports.int24 = zigZagInt(uint24);
|
|
exports.int32 = zigZagInt(uint32);
|
|
exports.int40 = zigZagInt(uint40);
|
|
exports.int48 = zigZagInt(uint48);
|
|
exports.int56 = zigZagInt(uint56);
|
|
exports.int64 = zigZagInt(uint64);
|
|
var biguint64 = exports.biguint64 = {
|
|
preencode(state, n) {
|
|
state.end += 8;
|
|
},
|
|
encode(state, n) {
|
|
const view = new DataView(
|
|
state.buffer.buffer,
|
|
state.start + state.buffer.byteOffset,
|
|
8
|
|
);
|
|
view.setBigUint64(0, n, true);
|
|
state.start += 8;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 8) throw new Error("Out of bounds");
|
|
const view = new DataView(
|
|
state.buffer.buffer,
|
|
state.start + state.buffer.byteOffset,
|
|
8
|
|
);
|
|
const n = view.getBigUint64(0, true);
|
|
state.start += 8;
|
|
return n;
|
|
}
|
|
};
|
|
exports.bigint64 = zigZagBigInt(biguint64);
|
|
var biguint = exports.biguint = {
|
|
preencode(state, n) {
|
|
let len = 0;
|
|
for (let m = n; m; m = m >> 64n) len++;
|
|
uint.preencode(state, len);
|
|
state.end += 8 * len;
|
|
},
|
|
encode(state, n) {
|
|
let len = 0;
|
|
for (let m = n; m; m = m >> 64n) len++;
|
|
uint.encode(state, len);
|
|
const view = new DataView(
|
|
state.buffer.buffer,
|
|
state.start + state.buffer.byteOffset,
|
|
8 * len
|
|
);
|
|
for (let m = n, i = 0; m; m = m >> 64n, i += 8) {
|
|
view.setBigUint64(i, BigInt.asUintN(64, m), true);
|
|
}
|
|
state.start += 8 * len;
|
|
},
|
|
decode(state) {
|
|
const len = uint.decode(state);
|
|
if (state.end - state.start < 8 * len) throw new Error("Out of bounds");
|
|
const view = new DataView(
|
|
state.buffer.buffer,
|
|
state.start + state.buffer.byteOffset,
|
|
8 * len
|
|
);
|
|
let n = 0n;
|
|
for (let i = len - 1; i >= 0; i--)
|
|
n = (n << 64n) + view.getBigUint64(i * 8, true);
|
|
state.start += 8 * len;
|
|
return n;
|
|
}
|
|
};
|
|
exports.bigint = zigZagBigInt(biguint);
|
|
exports.lexint = require_lexint();
|
|
exports.float32 = {
|
|
preencode(state, n) {
|
|
state.end += 4;
|
|
},
|
|
encode(state, n) {
|
|
const view = new DataView(
|
|
state.buffer.buffer,
|
|
state.start + state.buffer.byteOffset,
|
|
4
|
|
);
|
|
view.setFloat32(0, n, true);
|
|
state.start += 4;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 4) throw new Error("Out of bounds");
|
|
const view = new DataView(
|
|
state.buffer.buffer,
|
|
state.start + state.buffer.byteOffset,
|
|
4
|
|
);
|
|
const float = view.getFloat32(0, true);
|
|
state.start += 4;
|
|
return float;
|
|
}
|
|
};
|
|
exports.float64 = {
|
|
preencode(state, n) {
|
|
state.end += 8;
|
|
},
|
|
encode(state, n) {
|
|
const view = new DataView(
|
|
state.buffer.buffer,
|
|
state.start + state.buffer.byteOffset,
|
|
8
|
|
);
|
|
view.setFloat64(0, n, true);
|
|
state.start += 8;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 8) throw new Error("Out of bounds");
|
|
const view = new DataView(
|
|
state.buffer.buffer,
|
|
state.start + state.buffer.byteOffset,
|
|
8
|
|
);
|
|
const float = view.getFloat64(0, true);
|
|
state.start += 8;
|
|
return float;
|
|
}
|
|
};
|
|
var buffer = exports.buffer = {
|
|
preencode(state, b) {
|
|
if (b) uint8array.preencode(state, b);
|
|
else state.end++;
|
|
},
|
|
encode(state, b) {
|
|
if (b) uint8array.encode(state, b);
|
|
else state.buffer[state.start++] = 0;
|
|
},
|
|
decode(state) {
|
|
const len = uint.decode(state);
|
|
if (len === 0) return null;
|
|
if (state.end - state.start < len) throw new Error("Out of bounds");
|
|
return state.buffer.subarray(state.start, state.start += len);
|
|
}
|
|
};
|
|
exports.binary = {
|
|
...buffer,
|
|
preencode(state, b) {
|
|
if (typeof b === "string") utf8.preencode(state, b);
|
|
else buffer.preencode(state, b);
|
|
},
|
|
encode(state, b) {
|
|
if (typeof b === "string") utf8.encode(state, b);
|
|
else buffer.encode(state, b);
|
|
}
|
|
};
|
|
exports.arraybuffer = {
|
|
preencode(state, b) {
|
|
uint.preencode(state, b.byteLength);
|
|
state.end += b.byteLength;
|
|
},
|
|
encode(state, b) {
|
|
uint.encode(state, b.byteLength);
|
|
const view = new Uint8Array(b);
|
|
state.buffer.set(view, state.start);
|
|
state.start += b.byteLength;
|
|
},
|
|
decode(state) {
|
|
const len = uint.decode(state);
|
|
const b = new ArrayBuffer(len);
|
|
const view = new Uint8Array(b);
|
|
view.set(state.buffer.subarray(state.start, state.start += len));
|
|
return b;
|
|
}
|
|
};
|
|
function typedarray(TypedArray, swap) {
|
|
const n = TypedArray.BYTES_PER_ELEMENT;
|
|
return {
|
|
preencode(state, b) {
|
|
uint.preencode(state, b.length);
|
|
state.end += b.byteLength;
|
|
},
|
|
encode(state, b) {
|
|
uint.encode(state, b.length);
|
|
const view = new Uint8Array(b.buffer, b.byteOffset, b.byteLength);
|
|
if (BE && swap) swap(view);
|
|
state.buffer.set(view, state.start);
|
|
state.start += b.byteLength;
|
|
},
|
|
decode(state) {
|
|
const len = uint.decode(state);
|
|
let b = state.buffer.subarray(state.start, state.start += len * n);
|
|
if (b.byteLength !== len * n) throw new Error("Out of bounds");
|
|
if (b.byteOffset % n !== 0) b = new Uint8Array(b);
|
|
if (BE && swap) swap(b);
|
|
return new TypedArray(b.buffer, b.byteOffset, b.byteLength / n);
|
|
}
|
|
};
|
|
}
|
|
var uint8array = exports.uint8array = typedarray(Uint8Array);
|
|
exports.uint16array = typedarray(Uint16Array, b4a.swap16);
|
|
exports.uint32array = typedarray(Uint32Array, b4a.swap32);
|
|
exports.int8array = typedarray(Int8Array);
|
|
exports.int16array = typedarray(Int16Array, b4a.swap16);
|
|
exports.int32array = typedarray(Int32Array, b4a.swap32);
|
|
exports.biguint64array = typedarray(BigUint64Array, b4a.swap64);
|
|
exports.bigint64array = typedarray(BigInt64Array, b4a.swap64);
|
|
exports.float32array = typedarray(Float32Array, b4a.swap32);
|
|
exports.float64array = typedarray(Float64Array, b4a.swap64);
|
|
function string(encoding) {
|
|
return {
|
|
preencode(state, s) {
|
|
const len = b4a.byteLength(s, encoding);
|
|
uint.preencode(state, len);
|
|
state.end += len;
|
|
},
|
|
encode(state, s) {
|
|
const len = b4a.byteLength(s, encoding);
|
|
uint.encode(state, len);
|
|
b4a.write(state.buffer, s, state.start, encoding);
|
|
state.start += len;
|
|
},
|
|
decode(state) {
|
|
const len = uint.decode(state);
|
|
if (state.end - state.start < len) throw new Error("Out of bounds");
|
|
return b4a.toString(
|
|
state.buffer,
|
|
encoding,
|
|
state.start,
|
|
state.start += len
|
|
);
|
|
},
|
|
fixed(n) {
|
|
return {
|
|
preencode(state) {
|
|
state.end += n;
|
|
},
|
|
encode(state, s) {
|
|
b4a.write(state.buffer, s, state.start, n, encoding);
|
|
state.start += n;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < n) throw new Error("Out of bounds");
|
|
return b4a.toString(
|
|
state.buffer,
|
|
encoding,
|
|
state.start,
|
|
state.start += n
|
|
);
|
|
}
|
|
};
|
|
}
|
|
};
|
|
}
|
|
var utf8 = exports.string = exports.utf8 = string("utf-8");
|
|
exports.ascii = string("ascii");
|
|
exports.hex = string("hex");
|
|
exports.base64 = string("base64");
|
|
exports.ucs2 = exports.utf16le = string("utf16le");
|
|
exports.bool = {
|
|
preencode(state, b) {
|
|
state.end++;
|
|
},
|
|
encode(state, b) {
|
|
state.buffer[state.start++] = b ? 1 : 0;
|
|
},
|
|
decode(state) {
|
|
if (state.start >= state.end) throw Error("Out of bounds");
|
|
return state.buffer[state.start++] === 1;
|
|
}
|
|
};
|
|
var fixed = exports.fixed = function fixed2(n) {
|
|
return {
|
|
preencode(state, s) {
|
|
if (s.byteLength !== n) throw new Error("Incorrect buffer size");
|
|
state.end += n;
|
|
},
|
|
encode(state, s) {
|
|
state.buffer.set(s, state.start);
|
|
state.start += n;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < n) throw new Error("Out of bounds");
|
|
return state.buffer.subarray(state.start, state.start += n);
|
|
}
|
|
};
|
|
};
|
|
exports.fixed32 = fixed(32);
|
|
exports.fixed64 = fixed(64);
|
|
exports.array = function array(enc) {
|
|
return {
|
|
preencode(state, list) {
|
|
uint.preencode(state, list.length);
|
|
for (let i = 0; i < list.length; i++) enc.preencode(state, list[i]);
|
|
},
|
|
encode(state, list) {
|
|
uint.encode(state, list.length);
|
|
for (let i = 0; i < list.length; i++) enc.encode(state, list[i]);
|
|
},
|
|
decode(state) {
|
|
const len = uint.decode(state);
|
|
if (len > 1048576) throw new Error("Array is too big");
|
|
const arr = new Array(len);
|
|
for (let i = 0; i < len; i++) arr[i] = enc.decode(state);
|
|
return arr;
|
|
}
|
|
};
|
|
};
|
|
exports.frame = function frame(enc) {
|
|
const dummy = exports.state();
|
|
return {
|
|
preencode(state, m) {
|
|
const end = state.end;
|
|
enc.preencode(state, m);
|
|
uint.preencode(state, state.end - end);
|
|
},
|
|
encode(state, m) {
|
|
dummy.end = 0;
|
|
enc.preencode(dummy, m);
|
|
uint.encode(state, dummy.end);
|
|
enc.encode(state, m);
|
|
},
|
|
decode(state) {
|
|
const end = state.end;
|
|
const len = uint.decode(state);
|
|
state.end = state.start + len;
|
|
const m = enc.decode(state);
|
|
state.start = state.end;
|
|
state.end = end;
|
|
return m;
|
|
}
|
|
};
|
|
};
|
|
exports.date = {
|
|
preencode(state, d) {
|
|
int.preencode(state, d.getTime());
|
|
},
|
|
encode(state, d) {
|
|
int.encode(state, d.getTime());
|
|
},
|
|
decode(state, d) {
|
|
return new Date(int.decode(state));
|
|
}
|
|
};
|
|
exports.json = {
|
|
preencode(state, v) {
|
|
utf8.preencode(state, JSON.stringify(v));
|
|
},
|
|
encode(state, v) {
|
|
utf8.encode(state, JSON.stringify(v));
|
|
},
|
|
decode(state) {
|
|
return JSON.parse(utf8.decode(state));
|
|
}
|
|
};
|
|
exports.ndjson = {
|
|
preencode(state, v) {
|
|
utf8.preencode(state, JSON.stringify(v) + "\n");
|
|
},
|
|
encode(state, v) {
|
|
utf8.encode(state, JSON.stringify(v) + "\n");
|
|
},
|
|
decode(state) {
|
|
return JSON.parse(utf8.decode(state));
|
|
}
|
|
};
|
|
exports.none = {
|
|
preencode(state, n) {
|
|
},
|
|
encode(state, n) {
|
|
},
|
|
decode(state) {
|
|
return null;
|
|
}
|
|
};
|
|
var anyArray = {
|
|
preencode(state, arr) {
|
|
uint.preencode(state, arr.length);
|
|
for (let i = 0; i < arr.length; i++) {
|
|
any.preencode(state, arr[i]);
|
|
}
|
|
},
|
|
encode(state, arr) {
|
|
uint.encode(state, arr.length);
|
|
for (let i = 0; i < arr.length; i++) {
|
|
any.encode(state, arr[i]);
|
|
}
|
|
},
|
|
decode(state) {
|
|
const arr = [];
|
|
let len = uint.decode(state);
|
|
while (len-- > 0) {
|
|
arr.push(any.decode(state));
|
|
}
|
|
return arr;
|
|
}
|
|
};
|
|
var anyObject = {
|
|
preencode(state, o) {
|
|
const keys = Object.keys(o);
|
|
uint.preencode(state, keys.length);
|
|
for (const key of keys) {
|
|
utf8.preencode(state, key);
|
|
any.preencode(state, o[key]);
|
|
}
|
|
},
|
|
encode(state, o) {
|
|
const keys = Object.keys(o);
|
|
uint.encode(state, keys.length);
|
|
for (const key of keys) {
|
|
utf8.encode(state, key);
|
|
any.encode(state, o[key]);
|
|
}
|
|
},
|
|
decode(state) {
|
|
let len = uint.decode(state);
|
|
const o = {};
|
|
while (len-- > 0) {
|
|
const key = utf8.decode(state);
|
|
o[key] = any.decode(state);
|
|
}
|
|
return o;
|
|
}
|
|
};
|
|
var anyTypes = [
|
|
exports.none,
|
|
exports.bool,
|
|
exports.string,
|
|
exports.buffer,
|
|
exports.uint,
|
|
exports.int,
|
|
exports.float64,
|
|
anyArray,
|
|
anyObject,
|
|
exports.date
|
|
];
|
|
var any = exports.any = {
|
|
preencode(state, o) {
|
|
const t = getType(o);
|
|
uint.preencode(state, t);
|
|
anyTypes[t].preencode(state, o);
|
|
},
|
|
encode(state, o) {
|
|
const t = getType(o);
|
|
uint.encode(state, t);
|
|
anyTypes[t].encode(state, o);
|
|
},
|
|
decode(state) {
|
|
const t = uint.decode(state);
|
|
if (t >= anyTypes.length) throw new Error("Unknown type: " + t);
|
|
return anyTypes[t].decode(state);
|
|
}
|
|
};
|
|
var port = exports.port = uint16;
|
|
var address = (host, family) => {
|
|
return {
|
|
preencode(state, m) {
|
|
host.preencode(state, m.host);
|
|
port.preencode(state, m.port);
|
|
},
|
|
encode(state, m) {
|
|
host.encode(state, m.host);
|
|
port.encode(state, m.port);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
host: host.decode(state),
|
|
family,
|
|
port: port.decode(state)
|
|
};
|
|
}
|
|
};
|
|
};
|
|
var ipv4 = exports.ipv4 = {
|
|
preencode(state) {
|
|
state.end += 4;
|
|
},
|
|
encode(state, string2) {
|
|
const start = state.start;
|
|
const end = start + 4;
|
|
let i = 0;
|
|
while (i < string2.length) {
|
|
let n = 0;
|
|
let c;
|
|
while (i < string2.length && (c = string2.charCodeAt(i++)) !== /* . */
|
|
46) {
|
|
n = n * 10 + (c - /* 0 */
|
|
48);
|
|
}
|
|
state.buffer[state.start++] = n;
|
|
}
|
|
state.start = end;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 4) throw new Error("Out of bounds");
|
|
return state.buffer[state.start++] + "." + state.buffer[state.start++] + "." + state.buffer[state.start++] + "." + state.buffer[state.start++];
|
|
}
|
|
};
|
|
exports.ipv4Address = address(ipv4, 4);
|
|
var ipv6 = exports.ipv6 = {
|
|
preencode(state) {
|
|
state.end += 16;
|
|
},
|
|
encode(state, string2) {
|
|
const start = state.start;
|
|
const end = start + 16;
|
|
let i = 0;
|
|
let split = null;
|
|
while (i < string2.length) {
|
|
let n = 0;
|
|
let c;
|
|
while (i < string2.length && (c = string2.charCodeAt(i++)) !== /* : */
|
|
58) {
|
|
if (c >= 48 && c <= 57) n = n * 16 + (c - /* 0 */
|
|
48);
|
|
else if (c >= 65 && c <= 70) n = n * 16 + (c - /* A */
|
|
65 + 10);
|
|
else if (c >= 97 && c <= 102) n = n * 16 + (c - /* a */
|
|
97 + 10);
|
|
}
|
|
state.buffer[state.start++] = n >>> 8;
|
|
state.buffer[state.start++] = n;
|
|
if (i < string2.length && string2.charCodeAt(i) === /* : */
|
|
58) {
|
|
i++;
|
|
split = state.start;
|
|
}
|
|
}
|
|
if (split !== null) {
|
|
const offset = end - state.start;
|
|
state.buffer.copyWithin(split + offset, split).fill(0, split, split + offset);
|
|
}
|
|
state.start = end;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 16) throw new Error("Out of bounds");
|
|
return (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16);
|
|
}
|
|
};
|
|
exports.ipv6Address = address(ipv6, 6);
|
|
var ip = exports.ip = {
|
|
preencode(state, string2) {
|
|
const family = string2.includes(":") ? 6 : 4;
|
|
uint8.preencode(state, family);
|
|
if (family === 4) ipv4.preencode(state);
|
|
else ipv6.preencode(state);
|
|
},
|
|
encode(state, string2) {
|
|
const family = string2.includes(":") ? 6 : 4;
|
|
uint8.encode(state, family);
|
|
if (family === 4) ipv4.encode(state, string2);
|
|
else ipv6.encode(state, string2);
|
|
},
|
|
decode(state) {
|
|
const family = uint8.decode(state);
|
|
if (family === 4) return ipv4.decode(state);
|
|
else return ipv6.decode(state);
|
|
}
|
|
};
|
|
exports.ipAddress = {
|
|
preencode(state, m) {
|
|
ip.preencode(state, m.host);
|
|
port.preencode(state, m.port);
|
|
},
|
|
encode(state, m) {
|
|
ip.encode(state, m.host);
|
|
port.encode(state, m.port);
|
|
},
|
|
decode(state) {
|
|
const family = uint8.decode(state);
|
|
return {
|
|
host: family === 4 ? ipv4.decode(state) : ipv6.decode(state),
|
|
family,
|
|
port: port.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var record = exports.record = function(keyEncoding, valueEncoding) {
|
|
return {
|
|
preencode(state, v) {
|
|
const keys = Object.keys(v);
|
|
uint.preencode(state, keys.length);
|
|
for (const k of keys) {
|
|
keyEncoding.preencode(state, k);
|
|
valueEncoding.preencode(state, v[k]);
|
|
}
|
|
},
|
|
encode(state, v) {
|
|
const keys = Object.keys(v);
|
|
uint.encode(state, keys.length);
|
|
for (const k of keys) {
|
|
keyEncoding.encode(state, k);
|
|
valueEncoding.encode(state, v[k]);
|
|
}
|
|
},
|
|
decode(state) {
|
|
const out = /* @__PURE__ */ Object.create(null);
|
|
const keys = uint.decode(state);
|
|
for (let i = 0; i < keys; i++) {
|
|
out[keyEncoding.decode(state)] = valueEncoding.decode(state);
|
|
}
|
|
return out;
|
|
}
|
|
};
|
|
};
|
|
exports.stringRecord = record(utf8, utf8);
|
|
function getType(o) {
|
|
if (o === null || o === void 0) return 0;
|
|
if (typeof o === "boolean") return 1;
|
|
if (typeof o === "string") return 2;
|
|
if (b4a.isBuffer(o)) return 3;
|
|
if (typeof o === "number") {
|
|
if (Number.isInteger(o)) return o >= 0 ? 4 : 5;
|
|
return 6;
|
|
}
|
|
if (Array.isArray(o)) return 7;
|
|
if (o instanceof Date) return 9;
|
|
if (typeof o === "object") return 8;
|
|
throw new Error("Unsupported type for " + o);
|
|
}
|
|
exports.from = function from(enc) {
|
|
if (typeof enc === "string") return fromNamed(enc);
|
|
if (enc.preencode) return enc;
|
|
if (enc.encodingLength) return fromAbstractEncoder(enc);
|
|
return fromCodec(enc);
|
|
};
|
|
function fromNamed(enc) {
|
|
switch (enc) {
|
|
case "ascii":
|
|
return raw.ascii;
|
|
case "utf-8":
|
|
case "utf8":
|
|
return raw.utf8;
|
|
case "hex":
|
|
return raw.hex;
|
|
case "base64":
|
|
return raw.base64;
|
|
case "utf16-le":
|
|
case "utf16le":
|
|
case "ucs-2":
|
|
case "ucs2":
|
|
return raw.ucs2;
|
|
case "ndjson":
|
|
return raw.ndjson;
|
|
case "json":
|
|
return raw.json;
|
|
case "binary":
|
|
default:
|
|
return raw.binary;
|
|
}
|
|
}
|
|
function fromCodec(enc) {
|
|
let tmpM = null;
|
|
let tmpBuf = null;
|
|
return {
|
|
preencode(state, m) {
|
|
tmpM = m;
|
|
tmpBuf = enc.encode(m);
|
|
state.end += tmpBuf.byteLength;
|
|
},
|
|
encode(state, m) {
|
|
raw.encode(state, m === tmpM ? tmpBuf : enc.encode(m));
|
|
tmpM = tmpBuf = null;
|
|
},
|
|
decode(state) {
|
|
return enc.decode(raw.decode(state));
|
|
}
|
|
};
|
|
}
|
|
function fromAbstractEncoder(enc) {
|
|
return {
|
|
preencode(state, m) {
|
|
state.end += enc.encodingLength(m);
|
|
},
|
|
encode(state, m) {
|
|
enc.encode(m, state.buffer, state.start);
|
|
state.start += enc.encode.bytes;
|
|
},
|
|
decode(state) {
|
|
const m = enc.decode(state.buffer, state.start, state.end);
|
|
state.start += enc.decode.bytes;
|
|
return m;
|
|
}
|
|
};
|
|
}
|
|
exports.encode = function encode(enc, m) {
|
|
const state = exports.state();
|
|
enc.preencode(state, m);
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
enc.encode(state, m);
|
|
return state.buffer;
|
|
};
|
|
exports.decode = function decode(enc, buffer2) {
|
|
return enc.decode(exports.state(0, buffer2.byteLength, buffer2));
|
|
};
|
|
function zigZagInt(enc) {
|
|
return {
|
|
preencode(state, n) {
|
|
enc.preencode(state, zigZagEncodeInt(n));
|
|
},
|
|
encode(state, n) {
|
|
enc.encode(state, zigZagEncodeInt(n));
|
|
},
|
|
decode(state) {
|
|
return zigZagDecodeInt(enc.decode(state));
|
|
}
|
|
};
|
|
}
|
|
function zigZagDecodeInt(n) {
|
|
return n === 0 ? n : (n & 1) === 0 ? n / 2 : -(n + 1) / 2;
|
|
}
|
|
function zigZagEncodeInt(n) {
|
|
return n < 0 ? 2 * -n - 1 : n === 0 ? 0 : 2 * n;
|
|
}
|
|
function zigZagBigInt(enc) {
|
|
return {
|
|
preencode(state, n) {
|
|
enc.preencode(state, zigZagEncodeBigInt(n));
|
|
},
|
|
encode(state, n) {
|
|
enc.encode(state, zigZagEncodeBigInt(n));
|
|
},
|
|
decode(state) {
|
|
return zigZagDecodeBigInt(enc.decode(state));
|
|
}
|
|
};
|
|
}
|
|
function zigZagDecodeBigInt(n) {
|
|
return n === 0n ? n : (n & 1n) === 0n ? n / 2n : -(n + 1n) / 2n;
|
|
}
|
|
function zigZagEncodeBigInt(n) {
|
|
return n < 0n ? 2n * -n - 1n : n === 0n ? 0n : 2n * n;
|
|
}
|
|
function validateUint(n) {
|
|
if (n >= 0 === false)
|
|
throw new Error("uint must be positive");
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/sodium-universal/index.js
|
|
var require_sodium_universal = __commonJS({
|
|
"../../node_modules/sodium-universal/index.js"(exports, module) {
|
|
module.exports = require_sodium_native();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hypercore-crypto/index.js
|
|
var require_hypercore_crypto = __commonJS({
|
|
"../../node_modules/hypercore-crypto/index.js"(exports) {
|
|
var sodium = require_sodium_universal();
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var LEAF_TYPE = b4a.from([0]);
|
|
var PARENT_TYPE = b4a.from([1]);
|
|
var ROOT_TYPE = b4a.from([2]);
|
|
var HYPERCORE = b4a.from("hypercore");
|
|
exports.keyPair = function(seed) {
|
|
const slab = b4a.allocUnsafeSlow(sodium.crypto_sign_PUBLICKEYBYTES + sodium.crypto_sign_SECRETKEYBYTES);
|
|
const publicKey = slab.subarray(0, sodium.crypto_sign_PUBLICKEYBYTES);
|
|
const secretKey = slab.subarray(sodium.crypto_sign_PUBLICKEYBYTES);
|
|
if (seed) sodium.crypto_sign_seed_keypair(publicKey, secretKey, seed);
|
|
else sodium.crypto_sign_keypair(publicKey, secretKey);
|
|
return {
|
|
publicKey,
|
|
secretKey
|
|
};
|
|
};
|
|
exports.validateKeyPair = function(keyPair) {
|
|
const pk = b4a.allocUnsafe(sodium.crypto_sign_PUBLICKEYBYTES);
|
|
sodium.crypto_sign_ed25519_sk_to_pk(pk, keyPair.secretKey);
|
|
return b4a.equals(pk, keyPair.publicKey);
|
|
};
|
|
exports.sign = function(message, secretKey) {
|
|
const signature = b4a.allocUnsafeSlow(sodium.crypto_sign_BYTES);
|
|
sodium.crypto_sign_detached(signature, message, secretKey);
|
|
return signature;
|
|
};
|
|
exports.verify = function(message, signature, publicKey) {
|
|
if (signature.byteLength !== sodium.crypto_sign_BYTES) return false;
|
|
if (publicKey.byteLength !== sodium.crypto_sign_PUBLICKEYBYTES) return false;
|
|
return sodium.crypto_sign_verify_detached(signature, message, publicKey);
|
|
};
|
|
exports.encrypt = function(message, publicKey) {
|
|
const ciphertext = b4a.alloc(message.byteLength + sodium.crypto_box_SEALBYTES);
|
|
sodium.crypto_box_seal(ciphertext, message, publicKey);
|
|
return ciphertext;
|
|
};
|
|
exports.decrypt = function(ciphertext, keyPair) {
|
|
if (ciphertext.byteLength < sodium.crypto_box_SEALBYTES) return null;
|
|
const plaintext = b4a.alloc(ciphertext.byteLength - sodium.crypto_box_SEALBYTES);
|
|
if (!sodium.crypto_box_seal_open(plaintext, ciphertext, keyPair.publicKey, keyPair.secretKey)) {
|
|
return null;
|
|
}
|
|
return plaintext;
|
|
};
|
|
exports.encryptionKeyPair = function(seed) {
|
|
const publicKey = b4a.alloc(sodium.crypto_box_PUBLICKEYBYTES);
|
|
const secretKey = b4a.alloc(sodium.crypto_box_SECRETKEYBYTES);
|
|
if (seed) {
|
|
sodium.crypto_box_seed_keypair(publicKey, secretKey, seed);
|
|
} else {
|
|
sodium.crypto_box_keypair(publicKey, secretKey);
|
|
}
|
|
return {
|
|
publicKey,
|
|
secretKey
|
|
};
|
|
};
|
|
exports.data = function(data) {
|
|
const out = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash_batch(out, [
|
|
LEAF_TYPE,
|
|
c.encode(c.uint64, data.byteLength),
|
|
data
|
|
]);
|
|
return out;
|
|
};
|
|
exports.parent = function(a, b) {
|
|
if (a.index > b.index) {
|
|
const tmp = a;
|
|
a = b;
|
|
b = tmp;
|
|
}
|
|
const out = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash_batch(out, [
|
|
PARENT_TYPE,
|
|
c.encode(c.uint64, a.size + b.size),
|
|
a.hash,
|
|
b.hash
|
|
]);
|
|
return out;
|
|
};
|
|
exports.tree = function(roots, out) {
|
|
const buffers = new Array(3 * roots.length + 1);
|
|
let j = 0;
|
|
buffers[j++] = ROOT_TYPE;
|
|
for (let i = 0; i < roots.length; i++) {
|
|
const r = roots[i];
|
|
buffers[j++] = r.hash;
|
|
buffers[j++] = c.encode(c.uint64, r.index);
|
|
buffers[j++] = c.encode(c.uint64, r.size);
|
|
}
|
|
if (!out) out = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash_batch(out, buffers);
|
|
return out;
|
|
};
|
|
exports.hash = function(data, out) {
|
|
if (!out) out = b4a.allocUnsafe(32);
|
|
if (!Array.isArray(data)) data = [data];
|
|
sodium.crypto_generichash_batch(out, data);
|
|
return out;
|
|
};
|
|
exports.randomBytes = function(n) {
|
|
const buf = b4a.allocUnsafe(n);
|
|
sodium.randombytes_buf(buf);
|
|
return buf;
|
|
};
|
|
exports.discoveryKey = function(key) {
|
|
if (!key || key.byteLength !== 32) throw new Error("Must pass a 32 byte buffer");
|
|
const digest = b4a.allocUnsafeSlow(32);
|
|
sodium.crypto_generichash(digest, HYPERCORE, key);
|
|
return digest;
|
|
};
|
|
if (sodium.sodium_free) {
|
|
exports.free = function(secureBuf) {
|
|
if (secureBuf.secure) sodium.sodium_free(secureBuf);
|
|
};
|
|
} else {
|
|
exports.free = function() {
|
|
};
|
|
}
|
|
exports.namespace = function(name, count) {
|
|
const ids = typeof count === "number" ? range(count) : count;
|
|
const buf = b4a.allocUnsafeSlow(32 * ids.length);
|
|
const list = new Array(ids.length);
|
|
const ns = b4a.allocUnsafe(33);
|
|
sodium.crypto_generichash(ns.subarray(0, 32), typeof name === "string" ? b4a.from(name) : name);
|
|
for (let i = 0; i < list.length; i++) {
|
|
list[i] = buf.subarray(32 * i, 32 * i + 32);
|
|
ns[32] = ids[i];
|
|
sodium.crypto_generichash(list[i], ns);
|
|
}
|
|
return list;
|
|
};
|
|
function range(count) {
|
|
const arr = new Array(count);
|
|
for (let i = 0; i < count; i++) arr[i] = i;
|
|
return arr;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperblobs/lib/block-map.js
|
|
var require_block_map = __commonJS({
|
|
"../../node_modules/hyperblobs/lib/block-map.js"(exports) {
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var crypto = require_hypercore_crypto();
|
|
var block = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.index);
|
|
c.uint.preencode(state, m.byteLength);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.index);
|
|
c.uint.encode(state, m.byteLength);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
index: c.uint.decode(state),
|
|
byteLength: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var list = c.array(block);
|
|
var map = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, 0);
|
|
list.preencode(state, m.blocks);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, 0);
|
|
list.encode(state, m.blocks);
|
|
},
|
|
decode(state) {
|
|
const version = c.uint.decode(state);
|
|
if (version > 0) throw new Error("Unsupported block map version");
|
|
return {
|
|
version,
|
|
blocks: list.decode(state)
|
|
};
|
|
}
|
|
};
|
|
exports.hash = hashId;
|
|
function hashId(block2) {
|
|
return b4a.toString(crypto.hash(block2), "hex");
|
|
}
|
|
exports.get = getBlockMap;
|
|
async function inferBlockMap(core, id, opts = {}) {
|
|
const hashes = !!opts.hashes;
|
|
const map2 = {
|
|
hashes: hashes ? /* @__PURE__ */ new Map() : null,
|
|
blocks: []
|
|
};
|
|
for (let i = id.blockOffset; i < id.blockOffset + id.blockLength; i++) {
|
|
const block2 = await core.get(i);
|
|
const entry = { index: i, byteLength: block2.byteLength };
|
|
map2.blocks.push(entry);
|
|
if (hashes) map2.hashes.set(hashId(block2), entry);
|
|
}
|
|
return map2;
|
|
}
|
|
async function getBlockMap(core, id, opts = {}) {
|
|
if (!id.blockMap) return inferBlockMap(core, id, opts);
|
|
if (id.blockLength > 64) {
|
|
throw new Error("Block map is too large");
|
|
}
|
|
const hashes = !!opts.hashes;
|
|
const map2 = {
|
|
hashes: hashes ? /* @__PURE__ */ new Map() : null,
|
|
blocks: null
|
|
};
|
|
const promises = [];
|
|
for (let i = id.blockOffset; i < id.blockOffset + id.blockLength; i++) {
|
|
promises.push(core.get(i));
|
|
}
|
|
const buffers = await Promise.all(promises);
|
|
const m = decodeBlockMap(buffers);
|
|
if (!m) return null;
|
|
map2.blocks = m.blocks;
|
|
if (hashes && !core.writable) {
|
|
const blocks = [];
|
|
for (let i = 0; i < map2.blocks.length; i++) blocks.push(map2.blocks[i].index);
|
|
core.download({ blocks });
|
|
}
|
|
if (hashes) {
|
|
for (let i = 0; i < map2.blocks.length; i++) {
|
|
const b = map2.blocks[i];
|
|
const block2 = await core.get(b.index);
|
|
if (block2 === null) return null;
|
|
map2.hashes.set(hashId(block2), b);
|
|
}
|
|
}
|
|
return map2;
|
|
}
|
|
exports.encode = encodeBlockMap;
|
|
function encodeBlockMap(header) {
|
|
const result = [];
|
|
for (let i = 0; i < header.blocks.length; i += 8192) {
|
|
const blocks = i === 0 && header.blocks.length < 8192 ? header.blocks : header.blocks.slice(i, i + 8192);
|
|
const state = { start: 0, end: 0, buffer: null };
|
|
const m = { version: 0, blocks };
|
|
map.preencode(state, m);
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
map.encode(state, m);
|
|
result.push(state.buffer);
|
|
}
|
|
return result;
|
|
}
|
|
exports.decode = decodeBlockMap;
|
|
function decodeBlockMap(buffers) {
|
|
const result = {
|
|
version: 0,
|
|
blocks: null
|
|
};
|
|
for (let i = 0; i < buffers.length; i++) {
|
|
if (!buffers[i]) return null;
|
|
const state = { start: 0, end: buffers[i].byteLength, buffer: buffers[i] };
|
|
const r = map.decode(state);
|
|
result.version = r.version;
|
|
if (result.blocks) result.blocks.push(...r.blocks);
|
|
else result.blocks = r.blocks;
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperblobs/lib/streams.js
|
|
var require_streams2 = __commonJS({
|
|
"../../node_modules/hyperblobs/lib/streams.js"(exports, module) {
|
|
var { Readable, Writable } = require_streamx();
|
|
var { BLOCK_NOT_AVAILABLE } = require_hypercore_errors();
|
|
var Prefetcher = require_prefetcher();
|
|
var blockMap = require_block_map();
|
|
var BlobWriteStream = class extends Writable {
|
|
constructor(core, lock, opts = {}) {
|
|
super(opts);
|
|
this.id = { blockOffset: 0, byteOffset: 0, blockLength: 0, byteLength: 0 };
|
|
this.core = core;
|
|
this._dedup = !!opts.dedup;
|
|
this._blob = opts.blob || null;
|
|
this._hashes = null;
|
|
this._addBlockMap = !!opts.blockMap || this._dedup;
|
|
this._blockMap = this._addBlockMap ? { version: 0, blocks: [] } : null;
|
|
this._lock = lock;
|
|
this._release = null;
|
|
this._batch = [];
|
|
if (this._addBlockMap) this.id.blockMap = true;
|
|
}
|
|
async _openp() {
|
|
await this.core.ready();
|
|
const release = await new Promise((resolve) => this._lock(resolve));
|
|
this._release = release;
|
|
this.id.byteOffset = this.core.byteLength;
|
|
this.id.blockOffset = this.core.length;
|
|
if (!this._dedup) return;
|
|
if (this._blob) {
|
|
const map = await blockMap.get(this.core, this._blob, { hashes: true });
|
|
this._hashes = map.hashes;
|
|
} else {
|
|
this._hashes = /* @__PURE__ */ new Map();
|
|
}
|
|
}
|
|
_open(cb) {
|
|
this._openp().then(cb, cb);
|
|
}
|
|
async _finalp() {
|
|
await this._append();
|
|
if (this._blockMap) {
|
|
const buffers = await blockMap.encode(this._blockMap);
|
|
this.id.blockOffset = this.core.length;
|
|
this.id.byteOffset = this.core.byteLength;
|
|
await this.core.append(buffers);
|
|
}
|
|
this.id.blockLength = this.core.length - this.id.blockOffset;
|
|
this.id.byteLength = this.core.byteLength - this.id.byteOffset;
|
|
}
|
|
_final(cb) {
|
|
this._finalp().then(cb, cb);
|
|
}
|
|
_destroy(cb) {
|
|
if (this._release) this._release();
|
|
cb(null);
|
|
}
|
|
async _append() {
|
|
if (!this._batch.length) return;
|
|
const batch = this._batch;
|
|
this._batch = [];
|
|
await this.core.append(batch);
|
|
}
|
|
_write(data, cb) {
|
|
let dup = false;
|
|
if (this._blockMap) {
|
|
let entry = {
|
|
index: this.core.length + this._batch.length,
|
|
byteLength: data.byteLength
|
|
};
|
|
if (this._hashes) {
|
|
const id = blockMap.hash(data);
|
|
const existing = this._hashes.get(id);
|
|
if (existing) {
|
|
entry = existing;
|
|
dup = true;
|
|
} else {
|
|
this._hashes.set(id, entry);
|
|
}
|
|
}
|
|
this._blockMap.blocks.push(entry);
|
|
}
|
|
if (dup) return cb();
|
|
this._batch.push(data);
|
|
if (this._batch.length >= 16) {
|
|
this._append().then(cb, cb);
|
|
return;
|
|
}
|
|
return cb();
|
|
}
|
|
};
|
|
var BlockMapReadStream = class extends Readable {
|
|
constructor(core, id, opts = {}) {
|
|
super(opts);
|
|
this.id = id;
|
|
this.core = core.session({ wait: opts.wait, timeout: opts.timeout });
|
|
const noPrefetch = opts.wait === false || opts.prefetch === false || !core.core;
|
|
const start = opts.start || 0;
|
|
const end = opts.end === void 0 ? opts.length === void 0 ? -1 : start + opts.length : opts.end + 1;
|
|
this._blockMap = null;
|
|
this._rangeStart = start;
|
|
this._rangeEnd = end;
|
|
this._startIndex = 0;
|
|
this._startOffset = 0;
|
|
this._endIndex = -1;
|
|
this._endOffset = -1;
|
|
this._range = null;
|
|
this._noPrefetch = noPrefetch;
|
|
}
|
|
async _openp() {
|
|
this._blockMap = await blockMap.get(this.core, this.id);
|
|
const [startIndex, startOffset, endIndex, endLength] = seekBlockMap(
|
|
this._blockMap,
|
|
this._rangeStart,
|
|
this._rangeEnd
|
|
);
|
|
this._startIndex = startIndex;
|
|
this._startOffset = startOffset;
|
|
this._endIndex = endIndex;
|
|
this._endOffset = endLength;
|
|
if (this._endIndex === -1) {
|
|
this._endIndex = this._blockMap.blocks.length;
|
|
this._endOffset = 0;
|
|
}
|
|
}
|
|
_open(cb) {
|
|
this._openp().then(cb, cb);
|
|
}
|
|
_predestroy() {
|
|
if (this._range) this._range.destroy();
|
|
this.core.close().then(noop, noop);
|
|
}
|
|
_destroy(cb) {
|
|
if (this._range) this._range.destroy();
|
|
this.core.close().then(cb, cb);
|
|
}
|
|
_prefetch(index) {
|
|
const blocks = [];
|
|
for (; index < this._endIndex; index++) blocks.push(this._blockMap.blocks[index].index);
|
|
this._range = this.core.download({ blocks });
|
|
}
|
|
async _readp() {
|
|
if (this._startIndex >= this._endIndex) {
|
|
this.push(null);
|
|
return;
|
|
}
|
|
let block = null;
|
|
const index = this._startIndex++;
|
|
const b = this._blockMap.blocks[index];
|
|
if (!this._range && !this._noPrefetch) {
|
|
block = await this.core.get(b.index, { wait: false });
|
|
if (!block) this._prefetch(index);
|
|
}
|
|
if (!block) {
|
|
block = await this.core.get(b.index);
|
|
}
|
|
if (!block) throw BLOCK_NOT_AVAILABLE();
|
|
if (this._startOffset) {
|
|
block = block.subarray(this._startOffset);
|
|
this._startOffset = 0;
|
|
}
|
|
if (this._startIndex === this._endIndex && this._endOffset) {
|
|
block = block.subarray(0, block.byteLength - this._endOffset);
|
|
}
|
|
this.push(block);
|
|
}
|
|
_read(cb) {
|
|
this._readp().then(cb, cb);
|
|
}
|
|
};
|
|
var BlobReadStream = class extends Readable {
|
|
constructor(core, id, opts = {}) {
|
|
super(opts);
|
|
this.id = id;
|
|
this.core = core.session({ wait: opts.wait, timeout: opts.timeout });
|
|
const start = id.blockOffset;
|
|
const end = id.blockOffset + id.blockLength;
|
|
const noPrefetch = opts.wait === false || opts.prefetch === false || !core.core;
|
|
this._prefetch = noPrefetch ? null : new Prefetcher(this.core, { max: opts.prefetch, start, end });
|
|
this._lastPrefetch = null;
|
|
this._pos = opts.start !== void 0 ? id.byteOffset + opts.start : id.byteOffset;
|
|
if (opts.length !== void 0) this._end = this._pos + opts.length;
|
|
else if (opts.end !== void 0) this._end = id.byteOffset + opts.end + 1;
|
|
else this._end = id.byteOffset + id.byteLength;
|
|
this._index = 0;
|
|
this._relativeOffset = 0;
|
|
this._bytesRead = 0;
|
|
}
|
|
async _openp() {
|
|
if (this._pos === this.id.byteOffset) {
|
|
this._index = this.id.blockOffset;
|
|
this._relativeOffset = 0;
|
|
return;
|
|
}
|
|
const result = await this.core.seek(this._pos, {
|
|
start: this.id.blockOffset,
|
|
end: this.id.blockOffset + this.id.blockLength
|
|
});
|
|
if (!result) throw BLOCK_NOT_AVAILABLE();
|
|
this._index = result[0];
|
|
this._relativeOffset = result[1];
|
|
}
|
|
_open(cb) {
|
|
this._openp().then(cb, cb);
|
|
}
|
|
_predestroy() {
|
|
if (this._prefetch) this._prefetch.destroy();
|
|
this.core.close().then(noop, noop);
|
|
}
|
|
_destroy(cb) {
|
|
if (this._prefetch) this._prefetch.destroy();
|
|
this.core.close().then(cb, cb);
|
|
}
|
|
async _readp() {
|
|
if (this._pos >= this._end) {
|
|
this.push(null);
|
|
return;
|
|
}
|
|
if (this._prefetch) this._prefetch.update(this._index);
|
|
let block = await this.core.get(this._index);
|
|
if (!block) throw BLOCK_NOT_AVAILABLE();
|
|
const remainder = this._end - this._pos;
|
|
if (this._relativeOffset || remainder < block.length) {
|
|
block = block.subarray(this._relativeOffset, this._relativeOffset + remainder);
|
|
}
|
|
this._index++;
|
|
this._relativeOffset = 0;
|
|
this._pos += block.length;
|
|
this._bytesRead += block.length;
|
|
this.push(block);
|
|
}
|
|
_read(cb) {
|
|
this._readp().then(cb, cb);
|
|
}
|
|
};
|
|
module.exports = {
|
|
BlockMapReadStream,
|
|
BlobReadStream,
|
|
BlobWriteStream
|
|
};
|
|
function noop() {
|
|
}
|
|
function seekBlockMap(map, start, end) {
|
|
let s = -1;
|
|
let so = -1;
|
|
let e = -1;
|
|
let eo = -1;
|
|
for (let i = 0; i < map.blocks.length; i++) {
|
|
const b = map.blocks[i];
|
|
if (s === -1) {
|
|
if (start < b.byteLength) {
|
|
s = i;
|
|
so = start;
|
|
} else {
|
|
start -= b.byteLength;
|
|
}
|
|
}
|
|
if (e === -1 && end > -1) {
|
|
if (end <= b.byteLength) {
|
|
e = i + 1;
|
|
eo = b.byteLength - end;
|
|
} else {
|
|
end -= b.byteLength;
|
|
}
|
|
}
|
|
}
|
|
return [s, so, e, eo];
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperblobs/lib/monitor.js
|
|
var require_monitor = __commonJS({
|
|
"../../node_modules/hyperblobs/lib/monitor.js"(exports, module) {
|
|
var EventEmitter = __require("events");
|
|
var speedometer = require_speedometer();
|
|
module.exports = class Monitor extends EventEmitter {
|
|
constructor(blobs, id) {
|
|
super();
|
|
if (!id) throw new Error("id is required");
|
|
this.blobs = blobs;
|
|
this.id = id;
|
|
this.peers = 0;
|
|
this.uploadSpeedometer = null;
|
|
this.downloadSpeedometer = null;
|
|
const stats = {
|
|
startTime: 0,
|
|
percentage: 0,
|
|
peers: 0,
|
|
speed: 0,
|
|
blocks: 0,
|
|
totalBytes: 0,
|
|
// local + bytes loaded during monitoring
|
|
monitoringBytes: 0,
|
|
// bytes loaded during monitoring
|
|
targetBytes: 0,
|
|
targetBlocks: 0
|
|
};
|
|
this.uploadStats = { ...stats };
|
|
this.downloadStats = { ...stats };
|
|
this.uploadStats.targetBytes = this.downloadStats.targetBytes = this.id.byteLength;
|
|
this.uploadStats.targetBlocks = this.downloadStats.targetBlocks = this.id.blockLength;
|
|
this.uploadStats.peers = this.downloadStats.peers = this.peers = this.blobs.core.peers.length;
|
|
this.uploadSpeedometer = speedometer();
|
|
this.downloadSpeedometer = speedometer();
|
|
}
|
|
// just an alias
|
|
destroy() {
|
|
return this.close();
|
|
}
|
|
close() {
|
|
this.blobs._removeMonitor(this);
|
|
}
|
|
_onUpload(index, bytes, from) {
|
|
this._updateStats(this.uploadSpeedometer, this.uploadStats, index, bytes, from);
|
|
}
|
|
_onDownload(index, bytes, from) {
|
|
this._updateStats(this.downloadSpeedometer, this.downloadStats, index, bytes, from);
|
|
}
|
|
_updatePeers() {
|
|
this.uploadStats.peers = this.downloadStats.peers = this.peers = this.blobs.core.peers.length;
|
|
this.emit("update");
|
|
}
|
|
_updateStats(speed, stats, index, bytes) {
|
|
if (this.closing) return;
|
|
if (!isWithinRange(index, this.id)) return;
|
|
if (!stats.startTime) stats.startTime = Date.now();
|
|
stats.speed = speed(bytes);
|
|
stats.blocks++;
|
|
stats.totalBytes += bytes;
|
|
stats.monitoringBytes += bytes;
|
|
stats.percentage = toFixed(stats.blocks / stats.targetBlocks * 100);
|
|
this.emit("update");
|
|
}
|
|
downloadSpeed() {
|
|
return this.downloadSpeedometer ? this.downloadSpeedometer() : 0;
|
|
}
|
|
uploadSpeed() {
|
|
return this.uploadSpeedometer ? this.uploadSpeedometer() : 0;
|
|
}
|
|
};
|
|
function isWithinRange(index, { blockOffset, blockLength }) {
|
|
return index >= blockOffset && index < blockOffset + blockLength;
|
|
}
|
|
function toFixed(n) {
|
|
return Math.round(n * 100) / 100;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperblobs/index.js
|
|
var require_hyperblobs = __commonJS({
|
|
"../../node_modules/hyperblobs/index.js"(exports, module) {
|
|
var mutexify = require_mutexify();
|
|
var b4a = require_b4a();
|
|
var { BlockMapReadStream, BlobReadStream, BlobWriteStream } = require_streams2();
|
|
var Monitor = require_monitor();
|
|
var blockMap = require_block_map();
|
|
var DEFAULT_BLOCK_SIZE = 2 ** 16;
|
|
var HyperBlobsBatch = class {
|
|
constructor(blobs) {
|
|
this.blobs = blobs;
|
|
this.blocks = [];
|
|
this.bytes = 0;
|
|
}
|
|
ready() {
|
|
return this.blobs.ready();
|
|
}
|
|
async put(buffer) {
|
|
if (!this.blobs.core.opened) await this.blobs.core.ready();
|
|
const blockSize = this.blobs.blockSize;
|
|
const result = {
|
|
blockOffset: this.blobs.core.length + this.blocks.length,
|
|
blockLength: 0,
|
|
byteOffset: this.blobs.core.byteLength + this.bytes,
|
|
byteLength: 0
|
|
};
|
|
let offset = 0;
|
|
while (offset < buffer.byteLength) {
|
|
const blk = buffer.subarray(offset, offset + blockSize);
|
|
offset += blockSize;
|
|
result.blockLength++;
|
|
result.byteLength += blk.byteLength;
|
|
this.bytes += blk.byteLength;
|
|
this.blocks.push(blk);
|
|
}
|
|
return result;
|
|
}
|
|
async get(id) {
|
|
if (id.blockOffset < this.blobs.core.length) {
|
|
return this.blobs.get(id);
|
|
}
|
|
const bufs = [];
|
|
for (let i = id.blockOffset - this.blobs.core.length; i < id.blockOffset + id.blockLength; i++) {
|
|
if (i >= this.blocks.length) return null;
|
|
bufs.push(this.blocks[i]);
|
|
}
|
|
return bufs.length === 1 ? bufs[0] : b4a.concat(bufs);
|
|
}
|
|
async flush() {
|
|
await this.blobs.core.append(this.blocks);
|
|
this.blocks = [];
|
|
this.bytes = 0;
|
|
}
|
|
close() {
|
|
}
|
|
};
|
|
var Hyperblobs = class _Hyperblobs {
|
|
constructor(core, opts = {}) {
|
|
this.core = core;
|
|
this.blockSize = opts.blockSize || DEFAULT_BLOCK_SIZE;
|
|
this._lock = mutexify();
|
|
this._monitors = /* @__PURE__ */ new Set();
|
|
this._boundUpdatePeers = this._updatePeers.bind(this);
|
|
this._boundOnUpload = this._onUpload.bind(this);
|
|
this._boundOnDownload = this._onDownload.bind(this);
|
|
}
|
|
get key() {
|
|
return this.core.key;
|
|
}
|
|
get discoveryKey() {
|
|
return this.core.discoveryKey;
|
|
}
|
|
get feed() {
|
|
return this.core;
|
|
}
|
|
get locked() {
|
|
return this._lock.locked;
|
|
}
|
|
replicate(isInitiator, opts) {
|
|
return this.core.replicate(isInitiator, opts);
|
|
}
|
|
ready() {
|
|
return this.core.ready();
|
|
}
|
|
close() {
|
|
return this.core.close();
|
|
}
|
|
batch() {
|
|
return new HyperBlobsBatch(this);
|
|
}
|
|
snapshot() {
|
|
return new _Hyperblobs(this.core.snapshot());
|
|
}
|
|
async put(blob, opts) {
|
|
if (!b4a.isBuffer(blob)) blob = b4a.from(blob);
|
|
const blockSize = opts && opts.blockSize || this.blockSize;
|
|
const stream = this.createWriteStream(opts);
|
|
for (let i = 0; i < blob.length; i += blockSize) {
|
|
stream.write(blob.subarray(i, i + blockSize));
|
|
}
|
|
stream.end();
|
|
return new Promise((resolve, reject) => {
|
|
stream.once("error", reject);
|
|
stream.once("close", () => resolve(stream.id));
|
|
});
|
|
}
|
|
async _getAll(id, opts) {
|
|
if (id.blockLength === 1) return this.core.get(id.blockOffset, opts);
|
|
const promises = new Array(id.blockLength);
|
|
for (let i = 0; i < id.blockLength; i++) {
|
|
promises[i] = this.core.get(id.blockOffset + i, opts);
|
|
}
|
|
const blocks = await Promise.all(promises);
|
|
for (let i = 0; i < id.blockLength; i++) {
|
|
if (blocks[i] === null) return null;
|
|
}
|
|
return b4a.concat(blocks);
|
|
}
|
|
async get(id, opts) {
|
|
if (isAll(id, opts)) return this._getAll(id, opts);
|
|
const res = [];
|
|
try {
|
|
for await (const block of this.createReadStream(id, opts)) {
|
|
res.push(block);
|
|
}
|
|
} catch (error) {
|
|
if (error.code === "BLOCK_NOT_AVAILABLE") return null;
|
|
throw error;
|
|
}
|
|
if (res.length === 1) return res[0];
|
|
return b4a.concat(res);
|
|
}
|
|
getBlockMap(id) {
|
|
return id.blockMap ? blockMap.get(this.core, id) : null;
|
|
}
|
|
async getByteLength(id) {
|
|
if (!id.blockMap || id.byteLength === 0) return id.byteLength;
|
|
const map = await this.getBlockMap(id);
|
|
let size = 0;
|
|
for (const b of map.blocks) size += b.byteLength;
|
|
return size;
|
|
}
|
|
async clear(id, opts) {
|
|
if (id.blockMap) {
|
|
const map = await blockMap.get(this.core, id, { wait: false });
|
|
if (map) {
|
|
for (const b of map.blocks) await this.core.clear(b.index, b.index + 1, opts);
|
|
}
|
|
}
|
|
return this.core.clear(id.blockOffset, id.blockOffset + id.blockLength, opts);
|
|
}
|
|
createReadStream(id, opts) {
|
|
const core = opts && opts.core ? opts.core : this.core;
|
|
return id.blockMap ? new BlockMapReadStream(core, id, opts) : new BlobReadStream(core, id, opts);
|
|
}
|
|
createWriteStream(opts) {
|
|
const core = opts && opts.core ? opts.core : this.core;
|
|
return new BlobWriteStream(core, this._lock, opts);
|
|
}
|
|
monitor(id) {
|
|
const monitor = new Monitor(this, id);
|
|
if (this._monitors.size === 0) this._startListening();
|
|
this._monitors.add(monitor);
|
|
return monitor;
|
|
}
|
|
_removeMonitor(mon) {
|
|
this._monitors.delete(mon);
|
|
if (this._monitors.size === 0) this._stopListening();
|
|
}
|
|
_updatePeers() {
|
|
for (const m of this._monitors) m._updatePeers();
|
|
}
|
|
_onUpload(index, bytes, from) {
|
|
for (const m of this._monitors) m._onUpload(index, bytes, from);
|
|
}
|
|
_onDownload(index, bytes, from) {
|
|
for (const m of this._monitors) m._onDownload(index, bytes, from);
|
|
}
|
|
_startListening() {
|
|
this.core.on("peer-add", this._boundUpdatePeers);
|
|
this.core.on("peer-remove", this._boundUpdatePeers);
|
|
this.core.on("upload", this._boundOnUpload);
|
|
this.core.on("download", this._boundOnDownload);
|
|
}
|
|
_stopListening() {
|
|
this.core.off("peer-add", this._boundUpdatePeers);
|
|
this.core.off("peer-remove", this._boundUpdatePeers);
|
|
this.core.off("upload", this._boundOnUpload);
|
|
this.core.off("download", this._boundOnDownload);
|
|
}
|
|
};
|
|
module.exports = Hyperblobs;
|
|
function isAll(id, opts) {
|
|
if (id.blockMap) return false;
|
|
if (!opts) return true;
|
|
if (opts.start) return false;
|
|
if (opts.length !== void 0 || opts.end !== void 0) return false;
|
|
if (opts.core) return false;
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/is-options/index.js
|
|
var require_is_options = __commonJS({
|
|
"../../node_modules/is-options/index.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
module.exports = function isOptions(opts) {
|
|
return typeof opts === "object" && opts && !b4a.isBuffer(opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/sub-encoder/index.js
|
|
var require_sub_encoder = __commonJS({
|
|
"../../node_modules/sub-encoder/index.js"(exports, module) {
|
|
var codecs = require_codecs();
|
|
var b = require_b4a();
|
|
var SEP = b.alloc(1);
|
|
var SEP_BUMPED = b.from([1]);
|
|
var EMPTY = b.alloc(0);
|
|
module.exports = class SubEncoder {
|
|
constructor(prefix, encoding, parent = null) {
|
|
this.userEncoding = codecs(encoding);
|
|
this.prefix = prefix != null ? createPrefix(prefix, parent) : null;
|
|
this.lt = this.prefix && b.concat([this.prefix.subarray(0, this.prefix.byteLength - 1), SEP_BUMPED]);
|
|
}
|
|
_encodeRangeUser(r) {
|
|
if (this.userEncoding.encodeRange) return this.userEncoding.encodeRange(r);
|
|
const res = {};
|
|
if (r.gt != null) res.gt = this.userEncoding.encode(r.gt);
|
|
if (r.gte != null) res.gte = this.userEncoding.encode(r.gte);
|
|
if (r.lte != null) res.lte = this.userEncoding.encode(r.lte);
|
|
if (r.lt != null) res.lt = this.userEncoding.encode(r.lt);
|
|
return res;
|
|
}
|
|
_addPrefix(key) {
|
|
return this.prefix ? b.concat([this.prefix, key]) : key;
|
|
}
|
|
encode(key) {
|
|
return this._addPrefix(this.userEncoding.encode(key));
|
|
}
|
|
encodeRange(range) {
|
|
const r = this._encodeRangeUser(range);
|
|
if (r.gt) r.gt = this._addPrefix(r.gt);
|
|
else if (r.gte) r.gte = this._addPrefix(r.gte);
|
|
else if (this.prefix) r.gte = this.prefix;
|
|
if (r.lt) r.lt = this._addPrefix(r.lt);
|
|
else if (r.lte) r.lte = this._addPrefix(r.lte);
|
|
else if (this.prefix) r.lt = this.lt;
|
|
return r;
|
|
}
|
|
decode(key) {
|
|
return this.userEncoding.decode(this.prefix ? key.subarray(this.prefix.byteLength) : key);
|
|
}
|
|
sub(prefix, encoding) {
|
|
return new SubEncoder(prefix || EMPTY, compat(encoding), this.prefix);
|
|
}
|
|
};
|
|
function createPrefix(prefix, parent) {
|
|
prefix = typeof prefix === "string" ? b.from(prefix) : prefix;
|
|
if (prefix && parent) return b.concat([parent, prefix, SEP]);
|
|
if (prefix) return b.concat([prefix, SEP]);
|
|
if (parent) return b.concat([parent, SEP]);
|
|
return SEP;
|
|
}
|
|
function compat(enc) {
|
|
if (enc && enc.keyEncoding) return enc.keyEncoding;
|
|
return enc;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/random-access-storage/index.js
|
|
var require_random_access_storage = __commonJS({
|
|
"../../node_modules/random-access-storage/index.js"(exports, module) {
|
|
var EventEmitter = __require("events");
|
|
var queueTick = require_process_next_tick();
|
|
var NOT_READABLE = defaultImpl(new Error("Not readable"));
|
|
var NOT_WRITABLE = defaultImpl(new Error("Not writable"));
|
|
var NOT_DELETABLE = defaultImpl(new Error("Not deletable"));
|
|
var NOT_STATABLE = defaultImpl(new Error("Not statable"));
|
|
var DEFAULT_OPEN = defaultImpl(null);
|
|
var DEFAULT_CLOSE = defaultImpl(null);
|
|
var DEFAULT_UNLINK = defaultImpl(null);
|
|
var READ_OP = 0;
|
|
var WRITE_OP = 1;
|
|
var DEL_OP = 2;
|
|
var TRUNCATE_OP = 3;
|
|
var STAT_OP = 4;
|
|
var OPEN_OP = 5;
|
|
var SUSPEND_OP = 6;
|
|
var CLOSE_OP = 7;
|
|
var UNLINK_OP = 8;
|
|
module.exports = class RandomAccessStorage extends EventEmitter {
|
|
constructor(opts) {
|
|
super();
|
|
this._queued = [];
|
|
this._pending = 0;
|
|
this._needsOpen = true;
|
|
this.opened = false;
|
|
this.suspended = false;
|
|
this.closed = false;
|
|
this.unlinked = false;
|
|
this.writing = false;
|
|
if (opts) {
|
|
if (opts.open) this._open = opts.open;
|
|
if (opts.read) this._read = opts.read;
|
|
if (opts.write) this._write = opts.write;
|
|
if (opts.del) this._del = opts.del;
|
|
if (opts.truncate) this._truncate = opts.truncate;
|
|
if (opts.stat) this._stat = opts.stat;
|
|
if (opts.suspend) this._suspend = opts.suspend;
|
|
if (opts.close) this._close = opts.close;
|
|
if (opts.unlink) this._unlink = opts.unlink;
|
|
}
|
|
this.readable = this._read !== RandomAccessStorage.prototype._read;
|
|
this.writable = this._write !== RandomAccessStorage.prototype._write;
|
|
this.deletable = this._del !== RandomAccessStorage.prototype._del;
|
|
this.truncatable = this._truncate !== RandomAccessStorage.prototype._truncate || this.deletable;
|
|
this.statable = this._stat !== RandomAccessStorage.prototype._stat;
|
|
}
|
|
read(offset, size, cb) {
|
|
this.run(new Request(this, READ_OP, offset, size, null, cb), false);
|
|
}
|
|
_read(req) {
|
|
return NOT_READABLE(req);
|
|
}
|
|
write(offset, data, cb) {
|
|
if (!cb) cb = noop;
|
|
this.run(new Request(this, WRITE_OP, offset, data.length, data, cb), true);
|
|
}
|
|
_write(req) {
|
|
return NOT_WRITABLE(req);
|
|
}
|
|
del(offset, size, cb) {
|
|
if (!cb) cb = noop;
|
|
this.run(new Request(this, DEL_OP, offset, size, null, cb), true);
|
|
}
|
|
_del(req) {
|
|
return NOT_DELETABLE(req);
|
|
}
|
|
truncate(offset, cb) {
|
|
if (!cb) cb = noop;
|
|
this.run(new Request(this, TRUNCATE_OP, offset, 0, null, cb), true);
|
|
}
|
|
_truncate(req) {
|
|
req.size = Infinity;
|
|
this._del(req);
|
|
}
|
|
stat(cb) {
|
|
this.run(new Request(this, STAT_OP, 0, 0, null, cb), false);
|
|
}
|
|
_stat(req) {
|
|
return NOT_STATABLE(req);
|
|
}
|
|
open(cb) {
|
|
if (!cb) cb = noop;
|
|
if (this.opened && !this._needsOpen) return nextTickCallback(cb);
|
|
this._needsOpen = false;
|
|
queueAndRun(this, new Request(this, OPEN_OP, 0, 0, null, cb));
|
|
}
|
|
_open(req) {
|
|
return DEFAULT_OPEN(req);
|
|
}
|
|
suspend(cb) {
|
|
if (!cb) cb = noop;
|
|
if (this.closed || this.suspended) return nextTickCallback(cb);
|
|
this._needsOpen = true;
|
|
queueAndRun(this, new Request(this, SUSPEND_OP, 0, 0, null, cb));
|
|
}
|
|
_suspend(req) {
|
|
this._close(req);
|
|
}
|
|
close(cb) {
|
|
if (!cb) cb = noop;
|
|
if (this.closed) return nextTickCallback(cb);
|
|
queueAndRun(this, new Request(this, CLOSE_OP, 0, 0, null, cb));
|
|
}
|
|
_close(req) {
|
|
return DEFAULT_CLOSE(req);
|
|
}
|
|
unlink(cb) {
|
|
if (!cb) cb = noop;
|
|
if (!this.closed) this.close(noop);
|
|
queueAndRun(this, new Request(this, UNLINK_OP, 0, 0, null, cb));
|
|
}
|
|
_unlink(req) {
|
|
return DEFAULT_UNLINK(req);
|
|
}
|
|
run(req, writing) {
|
|
if (writing && !this.writing) {
|
|
this.writing = true;
|
|
this._needsOpen = true;
|
|
}
|
|
if (this._needsOpen) this.open(noop);
|
|
if (this._queued.length) this._queued.push(req);
|
|
else req._run();
|
|
}
|
|
};
|
|
var Request = class {
|
|
constructor(self2, type, offset, size, data, cb) {
|
|
this.type = type;
|
|
this.offset = offset;
|
|
this.size = size;
|
|
this.data = data;
|
|
this.storage = self2;
|
|
this._sync = false;
|
|
this._callback = cb;
|
|
this._openError = null;
|
|
}
|
|
_maybeOpenError(err) {
|
|
if (this.type !== OPEN_OP) return;
|
|
const queued = this.storage._queued;
|
|
for (let i = 1; i < queued.length; i++) {
|
|
const q = queued[i];
|
|
if (q.type === OPEN_OP) break;
|
|
q._openError = err;
|
|
}
|
|
}
|
|
_unqueue(err) {
|
|
const ra = this.storage;
|
|
const queued = ra._queued;
|
|
if (err) {
|
|
this._maybeOpenError(err);
|
|
} else if (this.type > 4) {
|
|
switch (this.type) {
|
|
case OPEN_OP:
|
|
if (ra.suspended) {
|
|
ra.suspended = false;
|
|
ra.emit("unsuspend");
|
|
}
|
|
if (!ra.opened) {
|
|
ra.opened = true;
|
|
ra.emit("open");
|
|
}
|
|
break;
|
|
case SUSPEND_OP:
|
|
if (!ra.suspended) {
|
|
ra.suspended = true;
|
|
ra.emit("suspend");
|
|
}
|
|
break;
|
|
case CLOSE_OP:
|
|
if (!ra.closed) {
|
|
ra.closed = true;
|
|
ra.emit("close");
|
|
}
|
|
break;
|
|
case UNLINK_OP:
|
|
if (!ra.unlinked) {
|
|
ra.unlinked = true;
|
|
ra.emit("unlink");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (queued.length && queued[0] === this) queued.shift();
|
|
if (!--ra._pending) drainQueue(ra);
|
|
}
|
|
callback(err, val) {
|
|
if (this._sync) return nextTick(this, err, val);
|
|
this._unqueue(err);
|
|
this._callback(err, val);
|
|
}
|
|
_openAndNotClosed() {
|
|
const ra = this.storage;
|
|
if (ra.opened && !ra.closed && !ra.suspended) return true;
|
|
if (!ra.opened || ra.suspended) nextTick(this, this._openError || new Error("Not opened"));
|
|
else if (ra.closed) nextTick(this, new Error("Closed"));
|
|
return false;
|
|
}
|
|
_open() {
|
|
const ra = this.storage;
|
|
if (ra.opened && !ra.suspended) return nextTick(this, null);
|
|
if (ra.closed) return nextTick(this, new Error("Closed"));
|
|
ra._open(this);
|
|
}
|
|
_run() {
|
|
const ra = this.storage;
|
|
ra._pending++;
|
|
this._sync = true;
|
|
switch (this.type) {
|
|
case READ_OP:
|
|
if (this._openAndNotClosed()) ra._read(this);
|
|
break;
|
|
case WRITE_OP:
|
|
if (this._openAndNotClosed()) ra._write(this);
|
|
break;
|
|
case DEL_OP:
|
|
if (this._openAndNotClosed()) ra._del(this);
|
|
break;
|
|
case TRUNCATE_OP:
|
|
if (this._openAndNotClosed()) ra._truncate(this);
|
|
break;
|
|
case STAT_OP:
|
|
if (this._openAndNotClosed()) ra._stat(this);
|
|
break;
|
|
case OPEN_OP:
|
|
this._open();
|
|
break;
|
|
case SUSPEND_OP:
|
|
if (ra.closed || !ra.opened || ra.suspended) nextTick(this, null);
|
|
else ra._suspend(this);
|
|
break;
|
|
case CLOSE_OP:
|
|
if (ra.closed || !ra.opened || ra.suspended) nextTick(this, null);
|
|
else ra._close(this);
|
|
break;
|
|
case UNLINK_OP:
|
|
if (ra.unlinked) nextTick(this, null);
|
|
else ra._unlink(this);
|
|
break;
|
|
}
|
|
this._sync = false;
|
|
}
|
|
};
|
|
function queueAndRun(self2, req) {
|
|
self2._queued.push(req);
|
|
if (!self2._pending) req._run();
|
|
}
|
|
function drainQueue(self2) {
|
|
const queued = self2._queued;
|
|
while (queued.length > 0) {
|
|
const blocking = queued[0].type > 4;
|
|
if (!blocking || !self2._pending) queued[0]._run();
|
|
if (blocking) return;
|
|
queued.shift();
|
|
}
|
|
}
|
|
function defaultImpl(err) {
|
|
return overridable;
|
|
function overridable(req) {
|
|
nextTick(req, err);
|
|
}
|
|
}
|
|
function nextTick(req, err, val) {
|
|
queueTick(() => req.callback(err, val));
|
|
}
|
|
function nextTickCallback(cb) {
|
|
queueTick(() => cb(null));
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/fs-native-extensions/binding.js
|
|
var require_binding3 = __commonJS({
|
|
"../../node_modules/fs-native-extensions/binding.js"(exports, module) {
|
|
__require.addon = require_node2();
|
|
module.exports = __require.addon(".", __filename);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/fs-native-extensions/index.js
|
|
var require_fs_native_extensions = __commonJS({
|
|
"../../node_modules/fs-native-extensions/index.js"(exports) {
|
|
var { isWindows } = require_which_runtime();
|
|
var binding = require_binding3();
|
|
function onwork(err, result) {
|
|
if (err) this.reject(err);
|
|
else this.resolve(result);
|
|
}
|
|
exports.tryLock = function tryLock(fd, offset = 0, length = 0, opts = {}) {
|
|
if (typeof offset === "object") {
|
|
opts = offset;
|
|
offset = 0;
|
|
}
|
|
if (typeof length === "object") {
|
|
opts = length;
|
|
length = 0;
|
|
}
|
|
if (typeof opts !== "object" || opts === null) {
|
|
opts = {};
|
|
}
|
|
try {
|
|
binding.tryLock(fd, offset, length, opts.shared !== true);
|
|
} catch (err) {
|
|
if (err.code === "EAGAIN") return false;
|
|
throw err;
|
|
}
|
|
return true;
|
|
};
|
|
exports.waitForLock = function waitForLock(fd, offset = 0, length = 0, opts = {}) {
|
|
if (typeof offset === "object") {
|
|
opts = offset;
|
|
offset = 0;
|
|
}
|
|
if (typeof length === "object") {
|
|
opts = length;
|
|
length = 0;
|
|
}
|
|
if (typeof opts !== "object" || opts === null) {
|
|
opts = {};
|
|
}
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.waitForLock(
|
|
fd,
|
|
offset,
|
|
length,
|
|
opts.shared !== true,
|
|
req,
|
|
onwork
|
|
);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
exports.tryDowngradeLock = function tryDowngradeLock(fd, offset = 0, length = 0) {
|
|
try {
|
|
binding.tryDowngradeLock(fd, offset, length);
|
|
} catch (err) {
|
|
if (err.code === "EAGAIN") return false;
|
|
throw err;
|
|
}
|
|
return true;
|
|
};
|
|
exports.waitForDowngradeLock = function downgradeLock(fd, offset = 0, length = 0) {
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.waitForDowngradeLock(fd, offset, length, req, onwork);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
exports.tryUpgradeLock = function tryUpgradeLock(fd, offset = 0, length = 0) {
|
|
try {
|
|
binding.tryUpgradeLock(fd, offset, length);
|
|
} catch (err) {
|
|
if (err.code === "EAGAIN") return false;
|
|
throw err;
|
|
}
|
|
return true;
|
|
};
|
|
exports.waitForUpgradeLock = function upgradeLock(fd, offset = 0, length = 0) {
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.waitForUpgradeLock(fd, offset, length, req, onwork);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
exports.unlock = function unlock(fd, offset = 0, length = 0) {
|
|
binding.unlock(fd, offset, length);
|
|
};
|
|
exports.trim = function trim(fd, offset, length) {
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.trim(fd, offset, length, req, onwork);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
exports.sparse = function sparse(fd) {
|
|
if (!isWindows) return Promise.resolve();
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.sparse(fd, req, onwork);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
exports.swap = function swap(from, to) {
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.swap(from, to, req, onwork);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
exports.getAttr = function getAttr(fd, name) {
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.getAttr(fd, name, req, onwork);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise.then(
|
|
(buffer) => buffer === null ? null : Buffer.from(buffer)
|
|
);
|
|
};
|
|
exports.setAttr = function setAttr(fd, name, value, encoding) {
|
|
if (typeof value === "string") value = Buffer.from(value, encoding);
|
|
const req = {
|
|
value,
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.setAttr(
|
|
fd,
|
|
name,
|
|
value.buffer,
|
|
value.byteOffset,
|
|
value.byteLength,
|
|
req,
|
|
onwork
|
|
);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
exports.removeAttr = function removeAttr(fd, name) {
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.removeAttr(fd, name, req, onwork);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
exports.listAttrs = function listAttrs(fd) {
|
|
const req = {
|
|
handle: null,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
req.resolve = resolve;
|
|
req.reject = reject;
|
|
});
|
|
try {
|
|
req.handle = binding.listAttrs(fd, req, onwork);
|
|
} catch (err) {
|
|
return Promise.reject(err);
|
|
}
|
|
return promise;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/random-access-file/index.js
|
|
var require_random_access_file = __commonJS({
|
|
"../../node_modules/random-access-file/index.js"(exports, module) {
|
|
var RandomAccessStorage = require_random_access_storage();
|
|
var fs = __require("fs");
|
|
var path = __require("path");
|
|
var constants = fs.constants;
|
|
var fsext = null;
|
|
try {
|
|
fsext = require_fs_native_extensions();
|
|
} catch {
|
|
}
|
|
var RDWR = constants.O_RDWR;
|
|
var RDONLY = constants.O_RDONLY;
|
|
var WRONLY = constants.O_WRONLY;
|
|
var CREAT = constants.O_CREAT;
|
|
var Pool = class {
|
|
constructor(maxSize) {
|
|
this.maxSize = maxSize;
|
|
this.active = [];
|
|
}
|
|
_onactive(file) {
|
|
if (this.active.length >= this.maxSize) {
|
|
const r = Math.floor(Math.random() * this.active.length);
|
|
this.active[r].suspend();
|
|
}
|
|
file._pi = this.active.push(file) - 1;
|
|
}
|
|
_oninactive(file) {
|
|
const head = this.active.pop();
|
|
if (head !== file) {
|
|
head._pi = file._pi;
|
|
this.active[head._pi] = head;
|
|
}
|
|
}
|
|
};
|
|
module.exports = class RandomAccessFile extends RandomAccessStorage {
|
|
constructor(filename, opts = {}) {
|
|
const size = opts.size || (opts.truncate ? 0 : -1);
|
|
super();
|
|
if (opts.directory) filename = path.join(opts.directory, path.resolve("/", filename).replace(/^\w+:\\/, ""));
|
|
this.directory = opts.directory || null;
|
|
this.filename = filename;
|
|
this.fd = 0;
|
|
const {
|
|
readable = true,
|
|
writable = true
|
|
} = opts;
|
|
this.mode = readable && writable ? RDWR : readable ? RDONLY : WRONLY;
|
|
this._pi = 0;
|
|
this._pool = opts.pool || null;
|
|
this._size = size;
|
|
this._rmdir = !!opts.rmdir;
|
|
this._lock = opts.lock === true;
|
|
this._sparse = opts.sparse === true;
|
|
this._alloc = opts.alloc || Buffer.allocUnsafe;
|
|
this._alwaysCreate = size >= 0;
|
|
}
|
|
static createPool(maxSize) {
|
|
return new Pool(maxSize);
|
|
}
|
|
_open(req) {
|
|
const create = this._alwaysCreate || this.writing;
|
|
const self2 = this;
|
|
const mode = this.mode | (create ? CREAT : 0);
|
|
if (create) fs.mkdir(path.dirname(this.filename), { recursive: true }, ondir);
|
|
else ondir(null);
|
|
function ondir(err) {
|
|
if (err) return req.callback(err);
|
|
fs.open(self2.filename, mode, onopen);
|
|
}
|
|
function onopen(err, fd) {
|
|
if (err) return onerror(err);
|
|
self2.fd = fd;
|
|
if (!self2._lock || !fsext) return onlock(null);
|
|
const shared = self2.mode === RDONLY;
|
|
if (fsext.tryLock(self2.fd, { shared })) onlock(null);
|
|
else onlock(createLockError(self2.filename));
|
|
}
|
|
function onlock(err) {
|
|
if (err) return onerrorafteropen(err);
|
|
if (!self2._sparse || !fsext || self2.mode === RDONLY) return onsparse(null);
|
|
fsext.sparse(self2.fd).then(onsparse, onsparse);
|
|
}
|
|
function onsparse(err) {
|
|
if (err) return onerrorafteropen(err);
|
|
if (self2._size < 0) return ontruncate(null);
|
|
fs.ftruncate(self2.fd, self2._size, ontruncate);
|
|
}
|
|
function ontruncate(err) {
|
|
if (err) return onerrorafteropen(err);
|
|
if (self2._pool !== null) self2._pool._onactive(self2);
|
|
req.callback(null);
|
|
}
|
|
function onerror(err) {
|
|
req.callback(err);
|
|
}
|
|
function onerrorafteropen(err) {
|
|
fs.close(self2.fd, function() {
|
|
self2.fd = 0;
|
|
onerror(err);
|
|
});
|
|
}
|
|
}
|
|
_write(req) {
|
|
const data = req.data;
|
|
const fd = this.fd;
|
|
fs.write(fd, data, 0, req.size, req.offset, onwrite);
|
|
function onwrite(err, wrote) {
|
|
if (err) return req.callback(err);
|
|
req.size -= wrote;
|
|
req.offset += wrote;
|
|
if (!req.size) return req.callback(null);
|
|
fs.write(fd, data, data.length - req.size, req.size, req.offset, onwrite);
|
|
}
|
|
}
|
|
_read(req) {
|
|
const self2 = this;
|
|
const data = req.data || this._alloc(req.size);
|
|
const fd = this.fd;
|
|
if (!req.size) return process.nextTick(readEmpty, req);
|
|
fs.read(fd, data, 0, req.size, req.offset, onread);
|
|
function onread(err, read) {
|
|
if (err) return req.callback(err);
|
|
if (!read) return req.callback(createReadError(self2.filename, req.offset, req.size));
|
|
req.size -= read;
|
|
req.offset += read;
|
|
if (!req.size) return req.callback(null, data);
|
|
fs.read(fd, data, data.length - req.size, req.size, req.offset, onread);
|
|
}
|
|
}
|
|
_del(req) {
|
|
if (req.size === Infinity) return this._truncate(req);
|
|
if (!fsext) return req.callback(null);
|
|
fsext.trim(this.fd, req.offset, req.size).then(ontrim, ontrim);
|
|
function ontrim(err) {
|
|
req.callback(err);
|
|
}
|
|
}
|
|
_truncate(req) {
|
|
fs.ftruncate(this.fd, req.offset, ontruncate);
|
|
function ontruncate(err) {
|
|
req.callback(err);
|
|
}
|
|
}
|
|
_stat(req) {
|
|
fs.fstat(this.fd, onstat);
|
|
function onstat(err, st) {
|
|
req.callback(err, st);
|
|
}
|
|
}
|
|
_close(req) {
|
|
const self2 = this;
|
|
fs.close(this.fd, onclose);
|
|
function onclose(err) {
|
|
if (err) return req.callback(err);
|
|
if (self2._pool !== null) self2._pool._oninactive(self2);
|
|
self2.fd = 0;
|
|
req.callback(null);
|
|
}
|
|
}
|
|
_unlink(req) {
|
|
const self2 = this;
|
|
const root = this.directory && path.resolve(path.join(this.directory, "."));
|
|
let dir = path.resolve(path.dirname(this.filename));
|
|
fs.unlink(this.filename, onunlink);
|
|
function onunlink(err) {
|
|
if (err && err.code === "ENOENT") err = null;
|
|
if (err || !self2._rmdir || !root || dir === root) return req.callback(err);
|
|
fs.rmdir(dir, onrmdir);
|
|
}
|
|
function onrmdir(err) {
|
|
dir = path.join(dir, "..");
|
|
if (err || dir === root) return req.callback(null);
|
|
fs.rmdir(dir, onrmdir);
|
|
}
|
|
}
|
|
};
|
|
function readEmpty(req) {
|
|
req.callback(null, Buffer.alloc(0));
|
|
}
|
|
function createLockError(path2) {
|
|
const err = new Error("ELOCKED: File is locked");
|
|
err.code = "ELOCKED";
|
|
err.path = path2;
|
|
return err;
|
|
}
|
|
function createReadError(path2, offset, size) {
|
|
const err = new Error("EPARTIALREAD: Could not satisfy length");
|
|
err.code = "EPARTIALREAD";
|
|
err.path = path2;
|
|
err.offset = offset;
|
|
err.size = size;
|
|
return err;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/xache/index.js
|
|
var require_xache = __commonJS({
|
|
"../../node_modules/xache/index.js"(exports, module) {
|
|
module.exports = class MaxCache {
|
|
constructor({ maxSize, maxAge, createMap, ongc }) {
|
|
this.maxSize = maxSize;
|
|
this.maxAge = maxAge;
|
|
this.ongc = ongc || null;
|
|
this._createMap = createMap || defaultCreateMap;
|
|
this._latest = this._createMap();
|
|
this._oldest = this._createMap();
|
|
this._retained = this._createMap();
|
|
this._gced = false;
|
|
this._interval = null;
|
|
if (this.maxAge > 0 && this.maxAge < Infinity) {
|
|
const tick = Math.ceil(2 / 3 * this.maxAge);
|
|
this._interval = setInterval(this._gcAuto.bind(this), tick);
|
|
if (this._interval.unref) this._interval.unref();
|
|
}
|
|
}
|
|
*[Symbol.iterator]() {
|
|
for (const it of [this._latest, this._oldest, this._retained]) {
|
|
yield* it;
|
|
}
|
|
}
|
|
*keys() {
|
|
for (const it of [this._latest, this._oldest, this._retained]) {
|
|
yield* it.keys();
|
|
}
|
|
}
|
|
*values() {
|
|
for (const it of [this._latest, this._oldest, this._retained]) {
|
|
yield* it.values();
|
|
}
|
|
}
|
|
destroy() {
|
|
this.clear();
|
|
clearInterval(this._interval);
|
|
this._interval = null;
|
|
}
|
|
clear() {
|
|
this._gced = true;
|
|
this._latest.clear();
|
|
this._oldest.clear();
|
|
this._retained.clear();
|
|
}
|
|
set(k, v) {
|
|
if (this._retained.has(k)) return this;
|
|
this._latest.set(k, v);
|
|
this._oldest.delete(k) || this._retained.delete(k);
|
|
if (this._latest.size >= this.maxSize) this._gc();
|
|
return this;
|
|
}
|
|
retain(k, v) {
|
|
this._retained.set(k, v);
|
|
this._latest.delete(k) || this._oldest.delete(k);
|
|
return this;
|
|
}
|
|
delete(k) {
|
|
return this._latest.delete(k) || this._oldest.delete(k) || this._retained.delete(k);
|
|
}
|
|
has(k) {
|
|
return this._latest.has(k) || this._oldest.has(k) || this._retained.has(k);
|
|
}
|
|
get(k) {
|
|
if (this._latest.has(k)) {
|
|
return this._latest.get(k);
|
|
}
|
|
if (this._oldest.has(k)) {
|
|
const v = this._oldest.get(k);
|
|
this._latest.set(k, v);
|
|
this._oldest.delete(k);
|
|
return v;
|
|
}
|
|
if (this._retained.has(k)) {
|
|
return this._retained.get(k);
|
|
}
|
|
return null;
|
|
}
|
|
_gcAuto() {
|
|
if (!this._gced) this._gc();
|
|
this._gced = false;
|
|
}
|
|
_gc() {
|
|
this._gced = true;
|
|
if (this.ongc !== null && this._oldest.size > 0) this.ongc(this._oldest);
|
|
this._oldest = this._latest;
|
|
this._latest = this._createMap();
|
|
}
|
|
};
|
|
function defaultCreateMap() {
|
|
return /* @__PURE__ */ new Map();
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/sodium-secretstream/index.js
|
|
var require_sodium_secretstream = __commonJS({
|
|
"../../node_modules/sodium-secretstream/index.js"(exports, module) {
|
|
var sodium = require_sodium_universal();
|
|
var b4a = require_b4a();
|
|
var ABYTES = sodium.crypto_secretstream_xchacha20poly1305_ABYTES;
|
|
var TAG_MESSAGE = sodium.crypto_secretstream_xchacha20poly1305_TAG_MESSAGE;
|
|
var TAG_FINAL = sodium.crypto_secretstream_xchacha20poly1305_TAG_FINAL;
|
|
var STATEBYTES = sodium.crypto_secretstream_xchacha20poly1305_STATEBYTES;
|
|
var HEADERBYTES = sodium.crypto_secretstream_xchacha20poly1305_HEADERBYTES;
|
|
var KEYBYTES = sodium.crypto_secretstream_xchacha20poly1305_KEYBYTES;
|
|
var TAG_FINAL_BYTE = b4a.isBuffer(TAG_FINAL) ? TAG_FINAL[0] : TAG_FINAL;
|
|
var EMPTY = b4a.alloc(0);
|
|
var TAG = b4a.alloc(1);
|
|
var Push = class {
|
|
constructor(key, state = b4a.allocUnsafeSlow(STATEBYTES), header = b4a.allocUnsafeSlow(HEADERBYTES)) {
|
|
if (!TAG_FINAL) throw new Error("JavaScript sodium version needs to support crypto_secretstream_xchacha20poly");
|
|
this.key = key;
|
|
this.state = state;
|
|
this.header = header;
|
|
sodium.crypto_secretstream_xchacha20poly1305_init_push(this.state, this.header, this.key);
|
|
}
|
|
next(message, cipher = b4a.allocUnsafe(message.byteLength + ABYTES)) {
|
|
sodium.crypto_secretstream_xchacha20poly1305_push(this.state, cipher, message, null, TAG_MESSAGE);
|
|
return cipher;
|
|
}
|
|
final(message = EMPTY, cipher = b4a.allocUnsafe(ABYTES)) {
|
|
sodium.crypto_secretstream_xchacha20poly1305_push(this.state, cipher, message, null, TAG_FINAL);
|
|
return cipher;
|
|
}
|
|
};
|
|
var Pull = class {
|
|
constructor(key, state = b4a.allocUnsafeSlow(STATEBYTES)) {
|
|
if (!TAG_FINAL) throw new Error("JavaScript sodium version needs to support crypto_secretstream_xchacha20poly");
|
|
this.key = key;
|
|
this.state = state;
|
|
this.final = false;
|
|
}
|
|
init(header) {
|
|
sodium.crypto_secretstream_xchacha20poly1305_init_pull(this.state, header, this.key);
|
|
}
|
|
next(cipher, message = b4a.allocUnsafe(cipher.byteLength - ABYTES)) {
|
|
sodium.crypto_secretstream_xchacha20poly1305_pull(this.state, message, TAG, cipher, null);
|
|
this.final = TAG[0] === TAG_FINAL_BYTE;
|
|
return message;
|
|
}
|
|
};
|
|
function keygen(buf = b4a.alloc(KEYBYTES)) {
|
|
sodium.crypto_secretstream_xchacha20poly1305_keygen(buf);
|
|
return buf;
|
|
}
|
|
module.exports = {
|
|
keygen,
|
|
KEYBYTES,
|
|
ABYTES,
|
|
STATEBYTES,
|
|
HEADERBYTES,
|
|
Push,
|
|
Pull
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/timeout-refresh/node.js
|
|
var require_node3 = __commonJS({
|
|
"../../node_modules/timeout-refresh/node.js"(exports, module) {
|
|
module.exports = class Timer {
|
|
constructor(ms, fn, ctx = null, interval = false) {
|
|
this.ms = ms;
|
|
this.ontimeout = fn;
|
|
this.context = ctx;
|
|
this.interval = interval;
|
|
this.done = false;
|
|
this._timer = interval ? setInterval(callInterval, ms, this) : setTimeout(callTimeout, ms, this);
|
|
}
|
|
unref() {
|
|
this._timer.unref();
|
|
}
|
|
ref() {
|
|
this._timer.ref();
|
|
}
|
|
refresh() {
|
|
if (this.done !== true) this._timer.refresh();
|
|
}
|
|
destroy() {
|
|
this.done = true;
|
|
this.ontimeout = null;
|
|
if (this.interval) clearInterval(this._timer);
|
|
else clearTimeout(this._timer);
|
|
}
|
|
static once(ms, fn, ctx) {
|
|
return new this(ms, fn, ctx, false);
|
|
}
|
|
static on(ms, fn, ctx) {
|
|
return new this(ms, fn, ctx, true);
|
|
}
|
|
};
|
|
function callTimeout(self2) {
|
|
self2.done = true;
|
|
self2.ontimeout.call(self2.context);
|
|
}
|
|
function callInterval(self2) {
|
|
self2.ontimeout.call(self2.context);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/timeout-refresh/browser.js
|
|
var require_browser = __commonJS({
|
|
"../../node_modules/timeout-refresh/browser.js"(exports, module) {
|
|
module.exports = class TimerBrowser {
|
|
constructor(ms, fn, ctx = null, interval = false) {
|
|
this.ms = ms;
|
|
this.ontimeout = fn;
|
|
this.context = ctx || null;
|
|
this.interval = interval;
|
|
this.done = false;
|
|
this._timer = interval ? setInterval(callInterval, ms, this) : setTimeout(callTimeout, ms, this);
|
|
}
|
|
unref() {
|
|
}
|
|
ref() {
|
|
}
|
|
refresh() {
|
|
if (this.done) return;
|
|
if (this.interval) {
|
|
clearInterval(this._timer);
|
|
this._timer = setInterval(callInterval, this.ms, this);
|
|
} else {
|
|
clearTimeout(this._timer);
|
|
this._timer = setTimeout(callTimeout, this.ms, this);
|
|
}
|
|
}
|
|
destroy() {
|
|
this.done = true;
|
|
this.ontimeout = null;
|
|
if (this.interval) clearInterval(this._timer);
|
|
else clearTimeout(this._timer);
|
|
}
|
|
static once(ms, fn, ctx) {
|
|
return new this(ms, fn, ctx, false);
|
|
}
|
|
static on(ms, fn, ctx) {
|
|
return new this(ms, fn, ctx, true);
|
|
}
|
|
};
|
|
function callTimeout(self2) {
|
|
self2.done = true;
|
|
self2.ontimeout.call(self2.context);
|
|
}
|
|
function callInterval(self2) {
|
|
self2.ontimeout.call(self2.context);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/timeout-refresh/index.js
|
|
var require_timeout_refresh = __commonJS({
|
|
"../../node_modules/timeout-refresh/index.js"(exports, module) {
|
|
module.exports = isNode() ? require_node3() : require_browser();
|
|
function isNode() {
|
|
const to = setTimeout(function() {
|
|
}, 1e3);
|
|
clearTimeout(to);
|
|
return !!to.refresh;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/@hyperswarm/secret-stream/lib/bridge.js
|
|
var require_bridge = __commonJS({
|
|
"../../node_modules/@hyperswarm/secret-stream/lib/bridge.js"(exports, module) {
|
|
var { Duplex, Writable } = require_streamx();
|
|
var ReversePassThrough = class extends Duplex {
|
|
constructor(s) {
|
|
super();
|
|
this._stream = s;
|
|
this._ondrain = null;
|
|
}
|
|
_write(data, cb) {
|
|
if (this._stream.push(data) === false) {
|
|
this._stream._ondrain = cb;
|
|
} else {
|
|
cb(null);
|
|
}
|
|
}
|
|
_final(cb) {
|
|
this._stream.push(null);
|
|
cb(null);
|
|
}
|
|
_read(cb) {
|
|
const ondrain = this._ondrain;
|
|
this._ondrain = null;
|
|
if (ondrain) ondrain();
|
|
cb(null);
|
|
}
|
|
};
|
|
module.exports = class Bridge extends Duplex {
|
|
constructor(noiseStream) {
|
|
super();
|
|
this.noiseStream = noiseStream;
|
|
this._ondrain = null;
|
|
this.reverse = new ReversePassThrough(this);
|
|
}
|
|
get publicKey() {
|
|
return this.noiseStream.publicKey;
|
|
}
|
|
get remotePublicKey() {
|
|
return this.noiseStream.remotePublicKey;
|
|
}
|
|
get handshakeHash() {
|
|
return this.noiseStream.handshakeHash;
|
|
}
|
|
flush() {
|
|
return Writable.drained(this);
|
|
}
|
|
_read(cb) {
|
|
const ondrain = this._ondrain;
|
|
this._ondrain = null;
|
|
if (ondrain) ondrain();
|
|
cb(null);
|
|
}
|
|
_write(data, cb) {
|
|
if (this.reverse.push(data) === false) {
|
|
this.reverse._ondrain = cb;
|
|
} else {
|
|
cb(null);
|
|
}
|
|
}
|
|
_final(cb) {
|
|
this.reverse.push(null);
|
|
cb(null);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/nanoassert/index.js
|
|
var require_nanoassert = __commonJS({
|
|
"../../node_modules/nanoassert/index.js"(exports, module) {
|
|
module.exports = assert;
|
|
var AssertionError = class extends Error {
|
|
};
|
|
AssertionError.prototype.name = "AssertionError";
|
|
function assert(t, m) {
|
|
if (!t) {
|
|
var err = new AssertionError(m);
|
|
if (Error.captureStackTrace) Error.captureStackTrace(err, assert);
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/noise-curve-ed/index.js
|
|
var require_noise_curve_ed = __commonJS({
|
|
"../../node_modules/noise-curve-ed/index.js"(exports, module) {
|
|
var sodium = require_sodium_universal();
|
|
var assert = require_nanoassert();
|
|
var b4a = require_b4a();
|
|
var DHLEN = sodium.crypto_scalarmult_ed25519_BYTES;
|
|
var PKLEN = sodium.crypto_scalarmult_ed25519_BYTES;
|
|
var SCALARLEN = sodium.crypto_scalarmult_ed25519_BYTES;
|
|
var SKLEN = sodium.crypto_sign_SECRETKEYBYTES;
|
|
var ALG = "Ed25519";
|
|
module.exports = {
|
|
DHLEN,
|
|
PKLEN,
|
|
SCALARLEN,
|
|
SKLEN,
|
|
ALG,
|
|
name: ALG,
|
|
generateKeyPair,
|
|
dh
|
|
};
|
|
function generateKeyPair(privKey) {
|
|
if (privKey) return generateSeedKeyPair(privKey.subarray(0, 32));
|
|
const keyPair = {};
|
|
keyPair.secretKey = b4a.alloc(SKLEN);
|
|
keyPair.publicKey = b4a.alloc(PKLEN);
|
|
sodium.crypto_sign_keypair(keyPair.publicKey, keyPair.secretKey);
|
|
return keyPair;
|
|
}
|
|
function generateSeedKeyPair(seed) {
|
|
const keyPair = {};
|
|
keyPair.secretKey = b4a.alloc(SKLEN);
|
|
keyPair.publicKey = b4a.alloc(PKLEN);
|
|
sodium.crypto_sign_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed);
|
|
return keyPair;
|
|
}
|
|
function dh(publicKey, { scalar, secretKey }) {
|
|
if (!scalar) {
|
|
assert(secretKey.byteLength === SKLEN);
|
|
const sk = b4a.alloc(64);
|
|
sodium.crypto_hash_sha512(sk, secretKey.subarray(0, 32));
|
|
sk[0] &= 248;
|
|
sk[31] &= 127;
|
|
sk[31] |= 64;
|
|
scalar = sk.subarray(0, 32);
|
|
}
|
|
assert(scalar.byteLength === SCALARLEN);
|
|
assert(publicKey.byteLength === PKLEN);
|
|
const output = b4a.alloc(DHLEN);
|
|
sodium.crypto_scalarmult_ed25519_noclamp(
|
|
output,
|
|
scalar,
|
|
publicKey
|
|
);
|
|
return output;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/noise-handshake/cipher.js
|
|
var require_cipher = __commonJS({
|
|
"../../node_modules/noise-handshake/cipher.js"(exports, module) {
|
|
var sodium = require_sodium_universal();
|
|
var b4a = require_b4a();
|
|
module.exports = class CipherState {
|
|
constructor(key) {
|
|
this.key = key || null;
|
|
this.nonce = 0;
|
|
this.CIPHER_ALG = "ChaChaPoly";
|
|
}
|
|
initialiseKey(key) {
|
|
this.key = key;
|
|
this.nonce = 0;
|
|
}
|
|
setNonce(nonce) {
|
|
this.nonce = nonce;
|
|
}
|
|
encrypt(plaintext, ad) {
|
|
if (!this.hasKey) return plaintext;
|
|
if (!ad) ad = b4a.alloc(0);
|
|
const ciphertext = encryptWithAD(this.key, this.nonce, ad, plaintext);
|
|
if (ciphertext.length > 65535) throw new Error(`ciphertext length of ${ciphertext.length} exceeds maximum Noise message length of 65535`);
|
|
this.nonce++;
|
|
return ciphertext;
|
|
}
|
|
decrypt(ciphertext, ad) {
|
|
if (!this.hasKey) return ciphertext;
|
|
if (!ad) ad = b4a.alloc(0);
|
|
if (ciphertext.length > 65535) throw new Error(`ciphertext length of ${ciphertext.length} exceeds maximum Noise message length of 65535`);
|
|
const plaintext = decryptWithAD(this.key, this.nonce, ad, ciphertext);
|
|
this.nonce++;
|
|
return plaintext;
|
|
}
|
|
get hasKey() {
|
|
return this.key !== null;
|
|
}
|
|
_clear() {
|
|
sodium.sodium_memzero(this.key);
|
|
this.key = null;
|
|
this.nonce = null;
|
|
}
|
|
static get MACBYTES() {
|
|
return 16;
|
|
}
|
|
static get NONCEBYTES() {
|
|
return 8;
|
|
}
|
|
static get KEYBYTES() {
|
|
return 32;
|
|
}
|
|
};
|
|
function encryptWithAD(key, counter, additionalData, plaintext) {
|
|
if (!b4a.isBuffer(additionalData)) additionalData = b4a.from(additionalData, "hex");
|
|
if (!b4a.isBuffer(plaintext)) plaintext = b4a.from(plaintext, "hex");
|
|
const nonce = b4a.alloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
|
|
const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength);
|
|
view.setUint32(4, counter, true);
|
|
const ciphertext = b4a.alloc(plaintext.byteLength + sodium.crypto_aead_chacha20poly1305_ietf_ABYTES);
|
|
sodium.crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext, plaintext, additionalData, null, nonce, key);
|
|
return ciphertext;
|
|
}
|
|
function decryptWithAD(key, counter, additionalData, ciphertext) {
|
|
if (!b4a.isBuffer(additionalData)) additionalData = b4a.from(additionalData, "hex");
|
|
if (!b4a.isBuffer(ciphertext)) ciphertext = b4a.from(ciphertext, "hex");
|
|
const nonce = b4a.alloc(sodium.crypto_aead_chacha20poly1305_ietf_NPUBBYTES);
|
|
const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength);
|
|
view.setUint32(4, counter, true);
|
|
const plaintext = b4a.alloc(ciphertext.byteLength - sodium.crypto_aead_chacha20poly1305_ietf_ABYTES);
|
|
sodium.crypto_aead_chacha20poly1305_ietf_decrypt(plaintext, null, ciphertext, additionalData, nonce, key);
|
|
return plaintext;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/noise-handshake/dh.js
|
|
var require_dh = __commonJS({
|
|
"../../node_modules/noise-handshake/dh.js"(exports, module) {
|
|
var {
|
|
crypto_kx_SEEDBYTES,
|
|
crypto_kx_keypair,
|
|
crypto_kx_seed_keypair,
|
|
crypto_scalarmult_BYTES,
|
|
crypto_scalarmult_SCALARBYTES,
|
|
crypto_scalarmult,
|
|
crypto_scalarmult_base
|
|
} = require_sodium_universal();
|
|
var assert = require_nanoassert();
|
|
var b4a = require_b4a();
|
|
var DHLEN = crypto_scalarmult_BYTES;
|
|
var PKLEN = crypto_scalarmult_BYTES;
|
|
var SKLEN = crypto_scalarmult_SCALARBYTES;
|
|
var SEEDLEN = crypto_kx_SEEDBYTES;
|
|
var ALG = "25519";
|
|
module.exports = {
|
|
DHLEN,
|
|
PKLEN,
|
|
SKLEN,
|
|
SEEDLEN,
|
|
ALG,
|
|
generateKeyPair,
|
|
generateSeedKeyPair,
|
|
dh
|
|
};
|
|
function generateKeyPair(privKey) {
|
|
const keyPair = {};
|
|
keyPair.secretKey = privKey || b4a.alloc(SKLEN);
|
|
keyPair.publicKey = b4a.alloc(PKLEN);
|
|
if (privKey) {
|
|
crypto_scalarmult_base(keyPair.publicKey, keyPair.secretKey);
|
|
} else {
|
|
crypto_kx_keypair(keyPair.publicKey, keyPair.secretKey);
|
|
}
|
|
return keyPair;
|
|
}
|
|
function generateSeedKeyPair(seed) {
|
|
assert(seed.byteLength === SKLEN);
|
|
const keyPair = {};
|
|
keyPair.secretKey = b4a.alloc(SKLEN);
|
|
keyPair.publicKey = b4a.alloc(PKLEN);
|
|
crypto_kx_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed);
|
|
return keyPair;
|
|
}
|
|
function dh(publicKey, { secretKey }) {
|
|
assert(secretKey.byteLength === SKLEN);
|
|
assert(publicKey.byteLength === PKLEN);
|
|
const output = b4a.alloc(DHLEN);
|
|
crypto_scalarmult(
|
|
output,
|
|
secretKey,
|
|
publicKey
|
|
);
|
|
return output;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/noise-handshake/hmac.js
|
|
var require_hmac = __commonJS({
|
|
"../../node_modules/noise-handshake/hmac.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var { sodium_memzero, crypto_generichash, crypto_generichash_batch } = require_sodium_universal();
|
|
var HASHLEN = 64;
|
|
var BLOCKLEN = 128;
|
|
var scratch = b4a.alloc(BLOCKLEN * 3);
|
|
var HMACKey = scratch.subarray(BLOCKLEN * 0, BLOCKLEN * 1);
|
|
var OuterKeyPad = scratch.subarray(BLOCKLEN * 1, BLOCKLEN * 2);
|
|
var InnerKeyPad = scratch.subarray(BLOCKLEN * 2, BLOCKLEN * 3);
|
|
module.exports = function hmac(out, batch, key) {
|
|
if (key.byteLength > BLOCKLEN) {
|
|
crypto_generichash(HMACKey.subarray(0, HASHLEN), key);
|
|
sodium_memzero(HMACKey.subarray(HASHLEN));
|
|
} else {
|
|
HMACKey.set(key);
|
|
sodium_memzero(HMACKey.subarray(key.byteLength));
|
|
}
|
|
for (let i = 0; i < HMACKey.byteLength; i++) {
|
|
OuterKeyPad[i] = 92 ^ HMACKey[i];
|
|
InnerKeyPad[i] = 54 ^ HMACKey[i];
|
|
}
|
|
sodium_memzero(HMACKey);
|
|
crypto_generichash_batch(out, [InnerKeyPad].concat(batch));
|
|
sodium_memzero(InnerKeyPad);
|
|
crypto_generichash_batch(out, [OuterKeyPad, out]);
|
|
sodium_memzero(OuterKeyPad);
|
|
};
|
|
module.exports.BYTES = HASHLEN;
|
|
module.exports.KEYBYTES = BLOCKLEN;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/noise-handshake/hkdf.js
|
|
var require_hkdf = __commonJS({
|
|
"../../node_modules/noise-handshake/hkdf.js"(exports, module) {
|
|
var hmacBlake2b = require_hmac();
|
|
var b4a = require_b4a();
|
|
var HASHLEN = 64;
|
|
module.exports = {
|
|
hkdf,
|
|
HASHLEN
|
|
};
|
|
function hkdf(salt, inputKeyMaterial, info = "", length = 2 * HASHLEN) {
|
|
const pseudoRandomKey = hkdfExtract(salt, inputKeyMaterial);
|
|
return hkdfExpand(pseudoRandomKey, info, length);
|
|
}
|
|
function hkdfExtract(salt, inputKeyMaterial) {
|
|
const hmac = b4a.alloc(HASHLEN);
|
|
return hmacDigest(hmac, salt, inputKeyMaterial);
|
|
}
|
|
function hkdfExpand(key, info, length) {
|
|
const buffer = b4a.allocUnsafeSlow(length);
|
|
const infoBuf = b4a.from(info);
|
|
let prev = infoBuf;
|
|
const result = [];
|
|
for (let i = 0; i < length; i += HASHLEN) {
|
|
const pos = b4a.from([i / HASHLEN + 1]);
|
|
const out = buffer.subarray(i, i + HASHLEN);
|
|
result.push(out);
|
|
prev = hmacDigest(out, key, [prev, infoBuf, pos]);
|
|
}
|
|
return result;
|
|
}
|
|
function hmacDigest(out, key, input) {
|
|
hmacBlake2b(out, input, key);
|
|
return out;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/noise-handshake/symmetric-state.js
|
|
var require_symmetric_state = __commonJS({
|
|
"../../node_modules/noise-handshake/symmetric-state.js"(exports, module) {
|
|
var sodium = require_sodium_universal();
|
|
var assert = require_nanoassert();
|
|
var b4a = require_b4a();
|
|
var CipherState = require_cipher();
|
|
var curve = require_dh();
|
|
var { HASHLEN, hkdf } = require_hkdf();
|
|
module.exports = class SymmetricState extends CipherState {
|
|
constructor(opts = {}) {
|
|
super();
|
|
this.curve = opts.curve || curve;
|
|
this.digest = b4a.alloc(HASHLEN);
|
|
this.chainingKey = null;
|
|
this.offset = 0;
|
|
this.DH_ALG = this.curve.ALG;
|
|
}
|
|
mixHash(data) {
|
|
accumulateDigest(this.digest, data);
|
|
}
|
|
mixKeyAndHash(key) {
|
|
const [ck, tempH, tempK] = hkdf(this.chainingKey, key, "", 3 * HASHLEN);
|
|
this.chainingKey = ck;
|
|
this.mixHash(tempH);
|
|
this.initialiseKey(tempK.subarray(0, 32));
|
|
}
|
|
mixKeyNormal(key) {
|
|
const [ck, tempK] = hkdf(this.chainingKey, key);
|
|
this.chainingKey = ck;
|
|
this.initialiseKey(tempK.subarray(0, 32));
|
|
}
|
|
mixKey(remoteKey, localKey) {
|
|
const dh = this.curve.dh(remoteKey, localKey);
|
|
const hkdfResult = hkdf(this.chainingKey, dh);
|
|
this.chainingKey = hkdfResult[0];
|
|
this.initialiseKey(hkdfResult[1].subarray(0, 32));
|
|
}
|
|
encryptAndHash(plaintext) {
|
|
const ciphertext = this.encrypt(plaintext, this.digest);
|
|
accumulateDigest(this.digest, ciphertext);
|
|
return ciphertext;
|
|
}
|
|
decryptAndHash(ciphertext) {
|
|
const plaintext = this.decrypt(ciphertext, this.digest);
|
|
accumulateDigest(this.digest, ciphertext);
|
|
return plaintext;
|
|
}
|
|
getHandshakeHash(out) {
|
|
if (!out) return this.getHandshakeHash(b4a.alloc(HASHLEN));
|
|
assert(out.byteLength === HASHLEN, `output must be ${HASHLEN} bytes`);
|
|
out.set(this.digest);
|
|
return out;
|
|
}
|
|
split() {
|
|
const res = hkdf(this.chainingKey, b4a.alloc(0));
|
|
return res.map((k) => k.subarray(0, 32));
|
|
}
|
|
_clear() {
|
|
super._clear();
|
|
sodium.sodium_memzero(this.digest);
|
|
sodium.sodium_memzero(this.chainingKey);
|
|
this.digest = null;
|
|
this.chainingKey = null;
|
|
this.offset = null;
|
|
this.curve = null;
|
|
}
|
|
static get alg() {
|
|
return CipherState.alg + "_BLAKE2b";
|
|
}
|
|
};
|
|
function accumulateDigest(digest, input) {
|
|
const toHash = b4a.concat([digest, input]);
|
|
sodium.crypto_generichash(digest, toHash);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/noise-handshake/noise.js
|
|
var require_noise = __commonJS({
|
|
"../../node_modules/noise-handshake/noise.js"(exports, module) {
|
|
var assert = require_nanoassert();
|
|
var b4a = require_b4a();
|
|
var SymmetricState = require_symmetric_state();
|
|
var { HASHLEN } = require_hkdf();
|
|
var PRESHARE_IS = Symbol("initiator static key preshared");
|
|
var PRESHARE_RS = Symbol("responder static key preshared");
|
|
var TOK_PSK = Symbol("psk");
|
|
var TOK_S = Symbol("s");
|
|
var TOK_E = Symbol("e");
|
|
var TOK_ES = Symbol("es");
|
|
var TOK_SE = Symbol("se");
|
|
var TOK_EE = Symbol("ee");
|
|
var TOK_SS = Symbol("ss");
|
|
var HANDSHAKES = Object.freeze({
|
|
NN: [
|
|
[TOK_E],
|
|
[TOK_E, TOK_EE]
|
|
],
|
|
NNpsk0: [
|
|
[TOK_PSK, TOK_E],
|
|
[TOK_E, TOK_EE]
|
|
],
|
|
XX: [
|
|
[TOK_E],
|
|
[TOK_E, TOK_EE, TOK_S, TOK_ES],
|
|
[TOK_S, TOK_SE]
|
|
],
|
|
XXpsk0: [
|
|
[TOK_PSK, TOK_E],
|
|
[TOK_E, TOK_EE, TOK_S, TOK_ES],
|
|
[TOK_S, TOK_SE]
|
|
],
|
|
IK: [
|
|
PRESHARE_RS,
|
|
[TOK_E, TOK_ES, TOK_S, TOK_SS],
|
|
[TOK_E, TOK_EE, TOK_SE]
|
|
],
|
|
XK: [
|
|
PRESHARE_RS,
|
|
[TOK_E, TOK_ES],
|
|
[TOK_E, TOK_EE],
|
|
[TOK_S, TOK_SE]
|
|
]
|
|
});
|
|
var Writer = class {
|
|
constructor() {
|
|
this.size = 0;
|
|
this.buffers = [];
|
|
}
|
|
push(b) {
|
|
this.size += b.byteLength;
|
|
this.buffers.push(b);
|
|
}
|
|
end() {
|
|
const all = b4a.alloc(this.size);
|
|
let offset = 0;
|
|
for (const b of this.buffers) {
|
|
all.set(b, offset);
|
|
offset += b.byteLength;
|
|
}
|
|
return all;
|
|
}
|
|
};
|
|
var Reader = class {
|
|
constructor(buf) {
|
|
this.offset = 0;
|
|
this.buffer = buf;
|
|
}
|
|
shift(n) {
|
|
const start = this.offset;
|
|
const end = this.offset += n;
|
|
if (end > this.buffer.byteLength) throw new Error("Insufficient bytes");
|
|
return this.buffer.subarray(start, end);
|
|
}
|
|
end() {
|
|
return this.shift(this.buffer.byteLength - this.offset);
|
|
}
|
|
};
|
|
module.exports = class NoiseState extends SymmetricState {
|
|
constructor(pattern, initiator, staticKeypair, opts = {}) {
|
|
super(opts);
|
|
this.s = staticKeypair || this.curve.generateKeyPair();
|
|
this.e = null;
|
|
this.psk = null;
|
|
if (opts && opts.psk) this.psk = opts.psk;
|
|
this.re = null;
|
|
this.rs = null;
|
|
this.pattern = pattern;
|
|
this.handshake = HANDSHAKES[this.pattern].slice();
|
|
this.isPskHandshake = !!this.psk && hasPskToken(this.handshake);
|
|
this.protocol = b4a.from([
|
|
"Noise",
|
|
this.pattern,
|
|
this.DH_ALG,
|
|
this.CIPHER_ALG,
|
|
"BLAKE2b"
|
|
].join("_"));
|
|
this.initiator = initiator;
|
|
this.complete = false;
|
|
this.rx = null;
|
|
this.tx = null;
|
|
this.hash = null;
|
|
}
|
|
initialise(prologue, remoteStatic) {
|
|
if (this.protocol.byteLength <= HASHLEN) this.digest.set(this.protocol);
|
|
else this.mixHash(this.protocol);
|
|
this.chainingKey = b4a.from(this.digest);
|
|
this.mixHash(prologue);
|
|
while (!Array.isArray(this.handshake[0])) {
|
|
const message = this.handshake.shift();
|
|
assert(
|
|
message === PRESHARE_RS || message === PRESHARE_IS,
|
|
"Unexpected pattern"
|
|
);
|
|
const takeRemoteKey = this.initiator ? message === PRESHARE_RS : message === PRESHARE_IS;
|
|
if (takeRemoteKey) this.rs = remoteStatic;
|
|
const key = takeRemoteKey ? this.rs : this.s.publicKey;
|
|
assert(key != null, "Remote pubkey required");
|
|
this.mixHash(key);
|
|
}
|
|
}
|
|
final() {
|
|
const [k1, k2] = this.split();
|
|
this.tx = this.initiator ? k1 : k2;
|
|
this.rx = this.initiator ? k2 : k1;
|
|
this.complete = true;
|
|
this.hash = this.getHandshakeHash();
|
|
this._clear();
|
|
}
|
|
recv(buf) {
|
|
const r = new Reader(buf);
|
|
for (const pattern of this.handshake.shift()) {
|
|
switch (pattern) {
|
|
case TOK_PSK:
|
|
this.mixKeyAndHash(this.psk);
|
|
break;
|
|
case TOK_E:
|
|
this.re = r.shift(this.curve.PKLEN);
|
|
this.mixHash(this.re);
|
|
if (this.isPskHandshake) this.mixKeyNormal(this.re);
|
|
break;
|
|
case TOK_S: {
|
|
const klen = this.hasKey ? this.curve.PKLEN + 16 : this.curve.PKLEN;
|
|
this.rs = this.decryptAndHash(r.shift(klen));
|
|
break;
|
|
}
|
|
case TOK_EE:
|
|
case TOK_ES:
|
|
case TOK_SE:
|
|
case TOK_SS: {
|
|
const useStatic = keyPattern(pattern, this.initiator);
|
|
const localKey = useStatic.local ? this.s : this.e;
|
|
const remoteKey = useStatic.remote ? this.rs : this.re;
|
|
this.mixKey(remoteKey, localKey);
|
|
break;
|
|
}
|
|
default:
|
|
throw new Error("Unexpected message");
|
|
}
|
|
}
|
|
const payload = this.decryptAndHash(r.end());
|
|
if (!this.handshake.length) this.final();
|
|
return payload;
|
|
}
|
|
send(payload = b4a.alloc(0)) {
|
|
const w = new Writer();
|
|
for (const pattern of this.handshake.shift()) {
|
|
switch (pattern) {
|
|
case TOK_PSK:
|
|
this.mixKeyAndHash(this.psk);
|
|
break;
|
|
case TOK_E:
|
|
if (this.e === null) this.e = this.curve.generateKeyPair();
|
|
this.mixHash(this.e.publicKey);
|
|
if (this.isPskHandshake) this.mixKeyNormal(this.e.publicKey);
|
|
w.push(this.e.publicKey);
|
|
break;
|
|
case TOK_S:
|
|
w.push(this.encryptAndHash(this.s.publicKey));
|
|
break;
|
|
case TOK_ES:
|
|
case TOK_SE:
|
|
case TOK_EE:
|
|
case TOK_SS: {
|
|
const useStatic = keyPattern(pattern, this.initiator);
|
|
const localKey = useStatic.local ? this.s : this.e;
|
|
const remoteKey = useStatic.remote ? this.rs : this.re;
|
|
this.mixKey(remoteKey, localKey);
|
|
break;
|
|
}
|
|
default:
|
|
throw new Error("Unexpected message");
|
|
}
|
|
}
|
|
w.push(this.encryptAndHash(payload));
|
|
const response = w.end();
|
|
if (!this.handshake.length) this.final();
|
|
return response;
|
|
}
|
|
_clear() {
|
|
super._clear();
|
|
this.e.secretKey.fill(0);
|
|
this.e.publicKey.fill(0);
|
|
this.re.fill(0);
|
|
this.e = null;
|
|
this.re = null;
|
|
}
|
|
};
|
|
function keyPattern(pattern, initiator) {
|
|
const ret = {
|
|
local: false,
|
|
remote: false
|
|
};
|
|
switch (pattern) {
|
|
case TOK_EE:
|
|
return ret;
|
|
case TOK_ES:
|
|
ret.local ^= !initiator;
|
|
ret.remote ^= initiator;
|
|
return ret;
|
|
case TOK_SE:
|
|
ret.local ^= initiator;
|
|
ret.remote ^= !initiator;
|
|
return ret;
|
|
case TOK_SS:
|
|
ret.local ^= 1;
|
|
ret.remote ^= 1;
|
|
return ret;
|
|
}
|
|
}
|
|
function hasPskToken(handshake) {
|
|
return handshake.some((x) => {
|
|
return Array.isArray(x) && x.indexOf(TOK_PSK) !== -1;
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/@hyperswarm/secret-stream/lib/handshake.js
|
|
var require_handshake = __commonJS({
|
|
"../../node_modules/@hyperswarm/secret-stream/lib/handshake.js"(exports, module) {
|
|
var sodium = require_sodium_universal();
|
|
var curve = require_noise_curve_ed();
|
|
var Noise = require_noise();
|
|
var b4a = require_b4a();
|
|
var EMPTY = b4a.alloc(0);
|
|
module.exports = class Handshake {
|
|
constructor(isInitiator, keyPair, remotePublicKey, pattern) {
|
|
this.isInitiator = isInitiator;
|
|
this.keyPair = keyPair;
|
|
this.noise = new Noise(pattern, isInitiator, keyPair, { curve });
|
|
this.noise.initialise(EMPTY, remotePublicKey);
|
|
this.destroyed = false;
|
|
}
|
|
static keyPair(seed) {
|
|
const publicKey = b4a.alloc(32);
|
|
const secretKey = b4a.alloc(64);
|
|
if (seed) sodium.crypto_sign_seed_keypair(publicKey, secretKey, seed);
|
|
else sodium.crypto_sign_keypair(publicKey, secretKey);
|
|
return { publicKey, secretKey };
|
|
}
|
|
recv(data) {
|
|
try {
|
|
this.noise.recv(data);
|
|
if (this.noise.complete) return this._return(null);
|
|
return this.send();
|
|
} catch {
|
|
this.destroy();
|
|
return null;
|
|
}
|
|
}
|
|
// note that the data returned here is framed so we don't have to do an extra copy
|
|
// when sending it...
|
|
send() {
|
|
try {
|
|
const data = this.noise.send();
|
|
const wrap = b4a.allocUnsafe(data.byteLength + 3);
|
|
writeUint24le(data.byteLength, wrap);
|
|
wrap.set(data, 3);
|
|
return this._return(wrap);
|
|
} catch {
|
|
this.destroy();
|
|
return null;
|
|
}
|
|
}
|
|
destroy() {
|
|
if (this.destroyed) return;
|
|
this.destroyed = true;
|
|
}
|
|
_return(data) {
|
|
const tx = this.noise.complete ? b4a.toBuffer(this.noise.tx) : null;
|
|
const rx = this.noise.complete ? b4a.toBuffer(this.noise.rx) : null;
|
|
const hash = this.noise.complete ? b4a.toBuffer(this.noise.hash) : null;
|
|
const remotePublicKey = this.noise.complete ? b4a.toBuffer(this.noise.rs) : null;
|
|
return {
|
|
data,
|
|
remotePublicKey,
|
|
hash,
|
|
tx,
|
|
rx
|
|
};
|
|
}
|
|
};
|
|
function writeUint24le(n, buf) {
|
|
buf[0] = n & 255;
|
|
buf[1] = n >>> 8 & 255;
|
|
buf[2] = n >>> 16 & 255;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/@hyperswarm/secret-stream/index.js
|
|
var require_secret_stream = __commonJS({
|
|
"../../node_modules/@hyperswarm/secret-stream/index.js"(exports, module) {
|
|
var { Pull, Push, HEADERBYTES, KEYBYTES, ABYTES } = require_sodium_secretstream();
|
|
var sodium = require_sodium_universal();
|
|
var crypto = require_hypercore_crypto();
|
|
var { Duplex, Writable, getStreamError } = require_streamx();
|
|
var b4a = require_b4a();
|
|
var Timeout = require_timeout_refresh();
|
|
var unslab = require_unslab();
|
|
var Bridge = require_bridge();
|
|
var Handshake = require_handshake();
|
|
var IDHEADERBYTES = HEADERBYTES + 32;
|
|
var [NS_INITIATOR, NS_RESPONDER, NS_SEND] = crypto.namespace("hyperswarm/secret-stream", 3);
|
|
var MAX_ATOMIC_WRITE = 256 * 256 * 256 - 1;
|
|
module.exports = class NoiseSecretStream extends Duplex {
|
|
constructor(isInitiator, rawStream, opts = {}) {
|
|
super({ mapWritable: toBuffer });
|
|
if (typeof isInitiator !== "boolean") {
|
|
throw new Error("isInitiator should be a boolean");
|
|
}
|
|
this.noiseStream = this;
|
|
this.isInitiator = isInitiator;
|
|
this.rawStream = null;
|
|
this.publicKey = opts.publicKey || null;
|
|
this.remotePublicKey = opts.remotePublicKey || null;
|
|
this.handshakeHash = null;
|
|
this.connected = false;
|
|
this.keepAlive = opts.keepAlive || 0;
|
|
this.timeout = 0;
|
|
this.enableSend = opts.enableSend !== false;
|
|
this.userData = null;
|
|
let openedDone = null;
|
|
this.opened = new Promise((resolve) => {
|
|
openedDone = resolve;
|
|
});
|
|
this.rawBytesWritten = 0;
|
|
this.rawBytesRead = 0;
|
|
this.relay = null;
|
|
this.puncher = null;
|
|
this._rawStream = null;
|
|
this._handshake = null;
|
|
this._handshakePattern = opts.pattern || null;
|
|
this._handshakeDone = null;
|
|
this._state = 0;
|
|
this._len = 0;
|
|
this._tmp = 1;
|
|
this._message = null;
|
|
this._openedDone = openedDone;
|
|
this._startDone = null;
|
|
this._drainDone = null;
|
|
this._outgoingPlain = null;
|
|
this._outgoingWrapped = null;
|
|
this._utp = null;
|
|
this._setup = true;
|
|
this._ended = 2;
|
|
this._encrypt = null;
|
|
this._decrypt = null;
|
|
this._timeoutTimer = null;
|
|
this._keepAliveTimer = null;
|
|
this._sendState = null;
|
|
if (opts.autoStart !== false) this.start(rawStream, opts);
|
|
this.resume();
|
|
this.pause();
|
|
}
|
|
static keyPair(seed) {
|
|
return Handshake.keyPair(seed);
|
|
}
|
|
static id(handshakeHash, isInitiator, id) {
|
|
return streamId(handshakeHash, isInitiator, id);
|
|
}
|
|
setTimeout(ms) {
|
|
if (!ms) ms = 0;
|
|
this._clearTimeout();
|
|
this.timeout = ms;
|
|
if (!ms || this.rawStream === null) return;
|
|
this._timeoutTimer = Timeout.once(ms, destroyTimeout, this);
|
|
this._timeoutTimer.unref();
|
|
}
|
|
setKeepAlive(ms) {
|
|
if (!ms) ms = 0;
|
|
this._clearKeepAlive();
|
|
this.keepAlive = ms;
|
|
if (!ms || this.rawStream === null) return;
|
|
this._keepAliveTimer = Timeout.on(ms, sendKeepAlive, this);
|
|
this._keepAliveTimer.unref();
|
|
}
|
|
sendKeepAlive() {
|
|
const empty = this.alloc(0);
|
|
this.write(empty);
|
|
}
|
|
start(rawStream, opts = {}) {
|
|
if (rawStream) {
|
|
this.rawStream = rawStream;
|
|
this._rawStream = rawStream;
|
|
if (typeof this.rawStream.setContentSize === "function") {
|
|
this._utp = rawStream;
|
|
}
|
|
} else {
|
|
this.rawStream = new Bridge(this);
|
|
this._rawStream = this.rawStream.reverse;
|
|
}
|
|
this.rawStream.on("error", this._onrawerror.bind(this));
|
|
this.rawStream.on("close", this._onrawclose.bind(this));
|
|
this._startHandshake(opts.handshake, opts.keyPair || null);
|
|
this._continueOpen(null);
|
|
if (this.destroying) return;
|
|
if (opts.data) this._onrawdata(opts.data);
|
|
if (opts.ended) this._onrawend();
|
|
if (this.keepAlive > 0 && this._keepAliveTimer === null) {
|
|
this.setKeepAlive(this.keepAlive);
|
|
}
|
|
if (this.timeout > 0 && this._timeoutTimer === null) {
|
|
this.setTimeout(this.timeout);
|
|
}
|
|
}
|
|
async flush() {
|
|
if (await this.opened === false) return false;
|
|
if (await Writable.drained(this) === false) return false;
|
|
if (this.destroying) return false;
|
|
if (this.rawStream !== null && this.rawStream.flush) {
|
|
return await this.rawStream.flush();
|
|
}
|
|
return true;
|
|
}
|
|
_continueOpen(err) {
|
|
if (err) this.destroy(err);
|
|
if (this._startDone === null) return;
|
|
const done = this._startDone;
|
|
this._startDone = null;
|
|
this._open(done);
|
|
}
|
|
_onkeypairpromise(p) {
|
|
const self2 = this;
|
|
const cont = this._continueOpen.bind(this);
|
|
p.then(onkeypair, cont);
|
|
function onkeypair(kp) {
|
|
self2._onkeypair(kp);
|
|
cont(null);
|
|
}
|
|
}
|
|
_onkeypair(keyPair) {
|
|
const pattern = this._handshakePattern || "XX";
|
|
const remotePublicKey = this.remotePublicKey;
|
|
this._handshake = new Handshake(this.isInitiator, keyPair, remotePublicKey, pattern);
|
|
this.publicKey = this._handshake.keyPair.publicKey;
|
|
}
|
|
_startHandshake(handshake, keyPair) {
|
|
if (handshake) {
|
|
const { tx, rx, hash, publicKey, remotePublicKey } = handshake;
|
|
this._setupSecretStream(tx, rx, hash, publicKey, remotePublicKey);
|
|
return;
|
|
}
|
|
if (!keyPair) keyPair = Handshake.keyPair();
|
|
if (typeof keyPair.then === "function") {
|
|
this._onkeypairpromise(keyPair);
|
|
} else {
|
|
this._onkeypair(keyPair);
|
|
}
|
|
}
|
|
_onrawerror(err) {
|
|
this.destroy(err);
|
|
}
|
|
_onrawclose() {
|
|
if (this._ended !== 0) this.destroy();
|
|
}
|
|
_onrawdata(data) {
|
|
let offset = 0;
|
|
if (this._timeoutTimer !== null) {
|
|
this._timeoutTimer.refresh();
|
|
}
|
|
do {
|
|
switch (this._state) {
|
|
case 0: {
|
|
while (this._tmp !== 16777216 && offset < data.byteLength) {
|
|
const v = data[offset++];
|
|
this._len += this._tmp * v;
|
|
this._tmp *= 256;
|
|
}
|
|
if (this._tmp === 16777216) {
|
|
this._tmp = 0;
|
|
this._state = 1;
|
|
const unprocessed = data.byteLength - offset;
|
|
if (unprocessed < this._len && this._utp !== null)
|
|
this._utp.setContentSize(this._len - unprocessed);
|
|
}
|
|
break;
|
|
}
|
|
case 1: {
|
|
const missing = this._len - this._tmp;
|
|
const end = missing + offset;
|
|
if (this._message === null && end <= data.byteLength) {
|
|
this._message = data.subarray(offset, end);
|
|
offset += missing;
|
|
this._incoming();
|
|
break;
|
|
}
|
|
const unprocessed = data.byteLength - offset;
|
|
if (this._message === null) {
|
|
this._message = b4a.allocUnsafe(this._len);
|
|
}
|
|
b4a.copy(data, this._message, this._tmp, offset);
|
|
this._tmp += unprocessed;
|
|
if (end <= data.byteLength) {
|
|
offset += missing;
|
|
this._incoming();
|
|
} else {
|
|
offset += unprocessed;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} while (offset < data.byteLength && !this.destroying);
|
|
}
|
|
_onrawend() {
|
|
this._ended--;
|
|
this.push(null);
|
|
}
|
|
_onrawdrain() {
|
|
const drain = this._drainDone;
|
|
if (drain === null) return;
|
|
this._drainDone = null;
|
|
drain();
|
|
}
|
|
_read(cb) {
|
|
this.rawStream.resume();
|
|
cb(null);
|
|
}
|
|
_incoming() {
|
|
const message = this._message;
|
|
this._state = 0;
|
|
this._len = 0;
|
|
this._tmp = 1;
|
|
this._message = null;
|
|
if (this._setup === true) {
|
|
if (this._handshake) {
|
|
this._onhandshakert(this._handshake.recv(message));
|
|
} else {
|
|
if (message.byteLength !== IDHEADERBYTES) {
|
|
this.destroy(new Error("Invalid header message received"));
|
|
return;
|
|
}
|
|
const remoteId = message.subarray(0, 32);
|
|
const expectedId = streamId(this.handshakeHash, !this.isInitiator);
|
|
const header = message.subarray(32);
|
|
if (!b4a.equals(expectedId, remoteId)) {
|
|
this.destroy(new Error("Invalid header received"));
|
|
return;
|
|
}
|
|
this._decrypt.init(header);
|
|
this._setup = false;
|
|
}
|
|
return;
|
|
}
|
|
if (message.byteLength < ABYTES) {
|
|
this.destroy(new Error("Invalid message received"));
|
|
return;
|
|
}
|
|
this.rawBytesRead += message.byteLength;
|
|
const plain = message.subarray(1, message.byteLength - ABYTES + 1);
|
|
try {
|
|
this._decrypt.next(message, plain);
|
|
} catch (err) {
|
|
this.destroy(err);
|
|
return;
|
|
}
|
|
if (plain.byteLength === 0 && this.keepAlive !== 0) return;
|
|
if (this.push(plain) === false) {
|
|
this.rawStream.pause();
|
|
}
|
|
}
|
|
_onhandshakert(h) {
|
|
if (this._handshakeDone === null) return;
|
|
if (h !== null) {
|
|
if (h.data) this._rawStream.write(h.data);
|
|
if (!h.tx) return;
|
|
}
|
|
const done = this._handshakeDone;
|
|
const publicKey = this._handshake.keyPair.publicKey;
|
|
this._handshakeDone = null;
|
|
this._handshake = null;
|
|
if (h === null) return done(new Error("Noise handshake failed"));
|
|
this._setupSecretStream(h.tx, h.rx, h.hash, publicKey, h.remotePublicKey);
|
|
this._resolveOpened(true);
|
|
done(null);
|
|
}
|
|
_setupSecretStream(tx, rx, handshakeHash, publicKey, remotePublicKey) {
|
|
const buf = b4a.allocUnsafeSlow(3 + IDHEADERBYTES);
|
|
writeUint24le(IDHEADERBYTES, buf);
|
|
this._encrypt = new Push(unslab(tx.subarray(0, KEYBYTES)), void 0, buf.subarray(3 + 32));
|
|
this._decrypt = new Pull(unslab(rx.subarray(0, KEYBYTES)));
|
|
this.publicKey = publicKey;
|
|
this.remotePublicKey = remotePublicKey;
|
|
this.handshakeHash = handshakeHash;
|
|
const id = buf.subarray(3, 3 + 32);
|
|
streamId(handshakeHash, this.isInitiator, id);
|
|
this._setupSecretSend(handshakeHash);
|
|
this.emit("handshake");
|
|
if (this.rawStream !== this._rawStream) this.rawStream.emit("handshake");
|
|
if (this.destroying) return;
|
|
this._rawStream.write(buf);
|
|
}
|
|
_setupSecretSend(handshakeHash) {
|
|
this._sendState = b4a.allocUnsafeSlow(32 + 32 + 8 + 8);
|
|
const encrypt = this._sendState.subarray(0, 32);
|
|
const decrypt = this._sendState.subarray(32, 64);
|
|
const counter = this._sendState.subarray(64, 72);
|
|
const initial = this._sendState.subarray(72);
|
|
const inputs = this.isInitiator ? [
|
|
[NS_INITIATOR, NS_SEND],
|
|
[NS_RESPONDER, NS_SEND]
|
|
] : [
|
|
[NS_RESPONDER, NS_SEND],
|
|
[NS_INITIATOR, NS_SEND]
|
|
];
|
|
sodium.crypto_generichash_batch(encrypt, inputs[0], handshakeHash);
|
|
sodium.crypto_generichash_batch(decrypt, inputs[1], handshakeHash);
|
|
sodium.randombytes_buf(initial);
|
|
counter.set(initial);
|
|
}
|
|
_open(cb) {
|
|
if (this._rawStream === null || this._handshake === null && this._encrypt === null) {
|
|
this._startDone = cb;
|
|
return;
|
|
}
|
|
this._rawStream.on("data", this._onrawdata.bind(this));
|
|
this._rawStream.on("end", this._onrawend.bind(this));
|
|
this._rawStream.on("drain", this._onrawdrain.bind(this));
|
|
if (this.enableSend) this._rawStream.on("message", this._onmessage.bind(this));
|
|
if (this._encrypt !== null) {
|
|
this._resolveOpened(true);
|
|
return cb(null);
|
|
}
|
|
this._handshakeDone = cb;
|
|
if (this.isInitiator) this._onhandshakert(this._handshake.send());
|
|
}
|
|
_predestroy() {
|
|
if (this.rawStream) {
|
|
const error = getStreamError(this);
|
|
this.rawStream.destroy(error);
|
|
}
|
|
if (this._startDone !== null) {
|
|
const done = this._startDone;
|
|
this._startDone = null;
|
|
done(new Error("Stream destroyed"));
|
|
}
|
|
if (this._handshakeDone !== null) {
|
|
const done = this._handshakeDone;
|
|
this._handshakeDone = null;
|
|
done(new Error("Stream destroyed"));
|
|
}
|
|
if (this._drainDone !== null) {
|
|
const done = this._drainDone;
|
|
this._drainDone = null;
|
|
done(new Error("Stream destroyed"));
|
|
}
|
|
}
|
|
_write(data, cb) {
|
|
let wrapped = this._outgoingWrapped;
|
|
if (data !== this._outgoingPlain) {
|
|
wrapped = b4a.allocUnsafe(data.byteLength + 3 + ABYTES);
|
|
wrapped.set(data, 4);
|
|
} else {
|
|
this._outgoingWrapped = this._outgoingPlain = null;
|
|
}
|
|
if (wrapped.byteLength - 3 > MAX_ATOMIC_WRITE) {
|
|
return cb(
|
|
new Error(
|
|
"Message is too large for an atomic write. Max size is " + MAX_ATOMIC_WRITE + " bytes."
|
|
)
|
|
);
|
|
}
|
|
this.rawBytesWritten += wrapped.byteLength;
|
|
writeUint24le(wrapped.byteLength - 3, wrapped);
|
|
this._encrypt.next(wrapped.subarray(4, 4 + data.byteLength), wrapped.subarray(3));
|
|
if (this._keepAliveTimer !== null) this._keepAliveTimer.refresh();
|
|
if (this._rawStream.write(wrapped) === false) {
|
|
this._drainDone = cb;
|
|
} else {
|
|
cb(null);
|
|
}
|
|
}
|
|
_final(cb) {
|
|
this._clearKeepAlive();
|
|
this._ended--;
|
|
this._rawStream.end();
|
|
cb(null);
|
|
}
|
|
_resolveOpened(val) {
|
|
if (this._openedDone === null) return;
|
|
const opened = this._openedDone;
|
|
this._openedDone = null;
|
|
opened(val);
|
|
if (!val) return;
|
|
this.connected = true;
|
|
this.emit("connect");
|
|
}
|
|
_clearTimeout() {
|
|
if (this._timeoutTimer === null) return;
|
|
this._timeoutTimer.destroy();
|
|
this._timeoutTimer = null;
|
|
this.timeout = 0;
|
|
}
|
|
_clearKeepAlive() {
|
|
if (this._keepAliveTimer === null) return;
|
|
this._keepAliveTimer.destroy();
|
|
this._keepAliveTimer = null;
|
|
this.keepAlive = 0;
|
|
}
|
|
_destroy(cb) {
|
|
this._clearKeepAlive();
|
|
this._clearTimeout();
|
|
this._resolveOpened(false);
|
|
cb(null);
|
|
}
|
|
_boxMessage(buffer) {
|
|
const MB = sodium.crypto_secretbox_MACBYTES;
|
|
const NB = sodium.crypto_secretbox_NONCEBYTES;
|
|
const counter = this._sendState.subarray(64, 72);
|
|
sodium.sodium_increment(counter);
|
|
if (b4a.equals(counter, this._sendState.subarray(72))) {
|
|
this.destroy(new Error("udp send nonce exchausted"));
|
|
return;
|
|
}
|
|
const secret = this._sendState.subarray(0, 32);
|
|
const envelope = b4a.allocUnsafe(8 + MB + buffer.byteLength);
|
|
const nonce = envelope.subarray(0, NB);
|
|
const ciphertext = envelope.subarray(8);
|
|
b4a.fill(nonce, 0);
|
|
nonce.set(counter);
|
|
sodium.crypto_secretbox_easy(ciphertext, buffer, nonce, secret);
|
|
return envelope;
|
|
}
|
|
send(buffer) {
|
|
if (!this._sendState) return;
|
|
if (!this.rawStream?.send) return;
|
|
const message = this._boxMessage(buffer);
|
|
return this.rawStream.send(message);
|
|
}
|
|
trySend(buffer) {
|
|
if (!this._sendState) return;
|
|
if (!this.rawStream?.trySend) return;
|
|
const message = this._boxMessage(buffer);
|
|
this.rawStream.trySend(message);
|
|
}
|
|
_onmessage(buffer) {
|
|
if (!this._sendState) return;
|
|
const MB = sodium.crypto_secretbox_MACBYTES;
|
|
const NB = sodium.crypto_secretbox_NONCEBYTES;
|
|
if (buffer.byteLength < NB) return;
|
|
const nonce = b4a.allocUnsafe(NB);
|
|
b4a.fill(nonce, 0);
|
|
nonce.set(buffer.subarray(0, 8));
|
|
const secret = this._sendState.subarray(32, 64);
|
|
const ciphertext = buffer.subarray(8);
|
|
const plain = buffer.subarray(8, buffer.byteLength - MB);
|
|
if (ciphertext.byteLength < MB) return;
|
|
const success = sodium.crypto_secretbox_open_easy(plain, ciphertext, nonce, secret);
|
|
if (success) this.emit("message", plain);
|
|
}
|
|
alloc(len) {
|
|
const buf = b4a.allocUnsafe(len + 3 + ABYTES);
|
|
this._outgoingWrapped = buf;
|
|
this._outgoingPlain = buf.subarray(4, buf.byteLength - ABYTES + 1);
|
|
return this._outgoingPlain;
|
|
}
|
|
toJSON() {
|
|
return {
|
|
isInitiator: this.isInitiator,
|
|
publicKey: this.publicKey && b4a.toString(this.publicKey, "hex"),
|
|
remotePublicKey: this.remotePublicKey && b4a.toString(this.remotePublicKey, "hex"),
|
|
connected: this.connected,
|
|
destroying: this.destroying,
|
|
destroyed: this.destroyed,
|
|
rawStream: this.rawStream && this.rawStream.toJSON ? this.rawStream.toJSON() : null
|
|
};
|
|
}
|
|
};
|
|
function writeUint24le(n, buf) {
|
|
buf[0] = n & 255;
|
|
buf[1] = n >>> 8 & 255;
|
|
buf[2] = n >>> 16 & 255;
|
|
}
|
|
function streamId(handshakeHash, isInitiator, out = b4a.allocUnsafe(32)) {
|
|
sodium.crypto_generichash(out, isInitiator ? NS_INITIATOR : NS_RESPONDER, handshakeHash);
|
|
return out;
|
|
}
|
|
function toBuffer(data) {
|
|
return typeof data === "string" ? b4a.from(data) : data;
|
|
}
|
|
function destroyTimeout() {
|
|
this.destroy(new Error("Stream timed out"));
|
|
}
|
|
function sendKeepAlive() {
|
|
const empty = this.alloc(0);
|
|
this.write(empty);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/protomux/index.js
|
|
var require_protomux = __commonJS({
|
|
"../../node_modules/protomux/index.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var c = require_compact_encoding();
|
|
var queueTick = require_process_next_tick();
|
|
var safetyCatch = require_safety_catch();
|
|
var unslab = require_unslab();
|
|
var MAX_BUFFERED = 32768;
|
|
var MAX_BACKLOG = Infinity;
|
|
var MAX_BATCH = 8 * 1024 * 1024;
|
|
var Channel = class {
|
|
constructor(mux, info, userData, protocol, aliases, id, handshake, messages, onopen, onclose, ondestroy, ondrain) {
|
|
this.userData = userData;
|
|
this.protocol = protocol;
|
|
this.aliases = aliases;
|
|
this.id = id;
|
|
this.handshake = null;
|
|
this.messages = [];
|
|
this.opened = false;
|
|
this.closed = false;
|
|
this.destroyed = false;
|
|
this.onopen = onopen;
|
|
this.onclose = onclose;
|
|
this.ondestroy = ondestroy;
|
|
this.ondrain = ondrain;
|
|
this._handshake = handshake;
|
|
this._mux = mux;
|
|
this._info = info;
|
|
this._localId = 0;
|
|
this._remoteId = 0;
|
|
this._active = 0;
|
|
this._extensions = null;
|
|
this._decBound = this._dec.bind(this);
|
|
this._decAndDestroyBound = this._decAndDestroy.bind(this);
|
|
this._openedPromise = null;
|
|
this._openedResolve = null;
|
|
this._destroyedPromise = null;
|
|
this._destroyedResolve = null;
|
|
for (const m of messages) this.addMessage(m);
|
|
}
|
|
get drained() {
|
|
return this._mux.drained;
|
|
}
|
|
fullyOpened() {
|
|
if (this.opened) return Promise.resolve(true);
|
|
if (this.closed) return Promise.resolve(false);
|
|
if (this._openedPromise) return this._openedPromise;
|
|
this._openedPromise = new Promise((resolve) => {
|
|
this._openedResolve = resolve;
|
|
});
|
|
return this._openedPromise;
|
|
}
|
|
fullyClosed() {
|
|
if (this.destroyed) return Promise.resolve();
|
|
if (this._destroyedPromise) return this._destroyedPromise;
|
|
this._destroyedPromise = new Promise((resolve) => {
|
|
this._destroyedResolve = resolve;
|
|
});
|
|
return this._destroyedPromise;
|
|
}
|
|
open(handshake) {
|
|
const id = this._mux._free.length > 0 ? this._mux._free.pop() : this._mux._local.push(null) - 1;
|
|
this._info.opened++;
|
|
this._info.lastChannel = this;
|
|
this._localId = id + 1;
|
|
this._mux._local[id] = this;
|
|
if (this._remoteId === 0) {
|
|
this._info.outgoing.push(this._localId);
|
|
}
|
|
const state = { buffer: null, start: 2, end: 2 };
|
|
c.uint.preencode(state, this._localId);
|
|
c.string.preencode(state, this.protocol);
|
|
c.buffer.preencode(state, this.id);
|
|
if (this._handshake) this._handshake.preencode(state, handshake);
|
|
state.buffer = this._mux._alloc(state.end);
|
|
state.buffer[0] = 0;
|
|
state.buffer[1] = 1;
|
|
c.uint.encode(state, this._localId);
|
|
c.string.encode(state, this.protocol);
|
|
c.buffer.encode(state, this.id);
|
|
if (this._handshake) this._handshake.encode(state, handshake);
|
|
this._mux._write0(state.buffer);
|
|
}
|
|
_dec() {
|
|
if (--this._active === 0 && this.closed === true) this._destroy();
|
|
}
|
|
_decAndDestroy(err) {
|
|
this._dec();
|
|
this._mux._safeDestroy(err);
|
|
}
|
|
_fullyOpenSoon() {
|
|
this._mux._remote[this._remoteId - 1].session = this;
|
|
queueTick(this._fullyOpen.bind(this));
|
|
}
|
|
_fullyOpen() {
|
|
if (this.opened === true || this.closed === true) return;
|
|
const remote = this._mux._remote[this._remoteId - 1];
|
|
this.opened = true;
|
|
this.handshake = this._handshake ? this._handshake.decode(remote.state) : null;
|
|
this._track(this.onopen(this.handshake, this));
|
|
remote.session = this;
|
|
remote.state = null;
|
|
if (remote.pending !== null) this._drain(remote);
|
|
this._resolveOpen(true);
|
|
}
|
|
_resolveOpen(opened) {
|
|
if (this._openedResolve !== null) {
|
|
this._openedResolve(opened);
|
|
this._openedResolve = this._openedPromise = null;
|
|
}
|
|
}
|
|
_resolveDestroyed() {
|
|
if (this._destroyedResolve !== null) {
|
|
this._destroyedResolve();
|
|
this._destroyedResolve = this._destroyedPromise = null;
|
|
}
|
|
}
|
|
_drain(remote) {
|
|
for (let i = 0; i < remote.pending.length; i++) {
|
|
const p = remote.pending[i];
|
|
this._mux._buffered -= byteSize(p.state);
|
|
this._recv(p.type, p.state);
|
|
}
|
|
remote.pending = null;
|
|
this._mux._resumeMaybe();
|
|
}
|
|
_track(p) {
|
|
if (isPromise(p) === true) {
|
|
this._active++;
|
|
return p.then(this._decBound, this._decAndDestroyBound);
|
|
}
|
|
return null;
|
|
}
|
|
_close(isRemote) {
|
|
if (this.closed === true) return;
|
|
this.closed = true;
|
|
this._info.opened--;
|
|
if (this._info.lastChannel === this) this._info.lastChannel = null;
|
|
if (this._remoteId > 0) {
|
|
this._mux._remote[this._remoteId - 1] = null;
|
|
this._remoteId = 0;
|
|
this._mux._free.push(this._localId - 1);
|
|
}
|
|
this._mux._local[this._localId - 1] = null;
|
|
this._localId = 0;
|
|
this._mux._gc(this._info);
|
|
this._track(this.onclose(isRemote, this));
|
|
if (this._active === 0) this._destroy();
|
|
this._resolveOpen(false);
|
|
}
|
|
_destroy() {
|
|
if (this.destroyed === true) return;
|
|
this.destroyed = true;
|
|
this._track(this.ondestroy(this));
|
|
this._resolveDestroyed();
|
|
}
|
|
_recv(type, state) {
|
|
if (type < this.messages.length) {
|
|
const m = this.messages[type];
|
|
const p = m.recv(state, this);
|
|
if (m.autoBatch === true) return p;
|
|
}
|
|
return null;
|
|
}
|
|
cork() {
|
|
this._mux.cork();
|
|
}
|
|
uncork() {
|
|
this._mux.uncork();
|
|
}
|
|
close() {
|
|
if (this.closed === true) return;
|
|
const state = { buffer: null, start: 2, end: 2 };
|
|
c.uint.preencode(state, this._localId);
|
|
state.buffer = this._mux._alloc(state.end);
|
|
state.buffer[0] = 0;
|
|
state.buffer[1] = 3;
|
|
c.uint.encode(state, this._localId);
|
|
this._close(false);
|
|
this._mux._write0(state.buffer);
|
|
}
|
|
addMessage(opts) {
|
|
if (!opts) return this._skipMessage();
|
|
const type = this.messages.length;
|
|
const autoBatch = opts.autoBatch !== false;
|
|
const encoding = opts.encoding || c.raw;
|
|
const onmessage = opts.onmessage || noop;
|
|
const s = this;
|
|
const typeLen = encodingLength(c.uint, type);
|
|
const m = {
|
|
type,
|
|
autoBatch,
|
|
encoding,
|
|
onmessage,
|
|
recv(state, session) {
|
|
return session._track(m.onmessage(encoding.decode(state), session));
|
|
},
|
|
send(m2, session = s) {
|
|
if (session.closed === true) return false;
|
|
const mux = session._mux;
|
|
const state = { buffer: null, start: 0, end: typeLen };
|
|
if (mux._batch !== null) {
|
|
encoding.preencode(state, m2);
|
|
state.buffer = mux._alloc(state.end);
|
|
c.uint.encode(state, type);
|
|
encoding.encode(state, m2);
|
|
mux._pushBatch(session._localId, state.buffer);
|
|
return true;
|
|
}
|
|
c.uint.preencode(state, session._localId);
|
|
encoding.preencode(state, m2);
|
|
state.buffer = mux._alloc(state.end);
|
|
c.uint.encode(state, session._localId);
|
|
c.uint.encode(state, type);
|
|
encoding.encode(state, m2);
|
|
mux.drained = mux.stream.write(state.buffer);
|
|
return mux.drained;
|
|
}
|
|
};
|
|
this.messages.push(m);
|
|
return m;
|
|
}
|
|
_skipMessage() {
|
|
const type = this.messages.length;
|
|
const m = {
|
|
type,
|
|
encoding: c.raw,
|
|
onmessage: noop,
|
|
recv(state, session) {
|
|
},
|
|
send(m2, session) {
|
|
}
|
|
};
|
|
this.messages.push(m);
|
|
return m;
|
|
}
|
|
};
|
|
module.exports = class Protomux {
|
|
constructor(stream, { alloc } = {}) {
|
|
if (stream.userData === null) stream.userData = this;
|
|
this.isProtomux = true;
|
|
this.stream = stream;
|
|
this.corked = 0;
|
|
this.drained = true;
|
|
this._alloc = alloc || (typeof stream.alloc === "function" ? stream.alloc.bind(stream) : b4a.allocUnsafe);
|
|
this._safeDestroyBound = this._safeDestroy.bind(this);
|
|
this._uncorkBound = this.uncork.bind(this);
|
|
this._remoteBacklog = 0;
|
|
this._buffered = 0;
|
|
this._paused = false;
|
|
this._remote = [];
|
|
this._local = [];
|
|
this._free = [];
|
|
this._batch = null;
|
|
this._batchState = null;
|
|
this._infos = /* @__PURE__ */ new Map();
|
|
this._notify = /* @__PURE__ */ new Map();
|
|
this.stream.on("data", this._ondata.bind(this));
|
|
this.stream.on("drain", this._ondrain.bind(this));
|
|
this.stream.on("end", this._onend.bind(this));
|
|
this.stream.on("error", noop);
|
|
this.stream.on("close", this._shutdown.bind(this));
|
|
}
|
|
static from(stream, opts) {
|
|
if (stream.userData && stream.userData.isProtomux) return stream.userData;
|
|
if (stream.isProtomux) return stream;
|
|
return new this(stream, opts);
|
|
}
|
|
static isProtomux(mux) {
|
|
return typeof mux === "object" && mux.isProtomux === true;
|
|
}
|
|
*[Symbol.iterator]() {
|
|
for (const session of this._local) {
|
|
if (session !== null) yield session;
|
|
}
|
|
}
|
|
isIdle() {
|
|
return this._local.length === this._free.length;
|
|
}
|
|
cork() {
|
|
if (++this.corked === 1) {
|
|
this._batch = [];
|
|
this._batchState = { buffer: null, start: 0, end: 1 };
|
|
}
|
|
}
|
|
uncork() {
|
|
if (--this.corked === 0) {
|
|
this._sendBatch(this._batch, this._batchState);
|
|
this._batch = null;
|
|
this._batchState = null;
|
|
}
|
|
}
|
|
getLastChannel({ protocol, id = null }) {
|
|
const key = toKey(protocol, id);
|
|
const info = this._infos.get(key);
|
|
if (info) return info.lastChannel;
|
|
return null;
|
|
}
|
|
pair({ protocol, id = null }, notify) {
|
|
this._notify.set(toKey(protocol, id), notify);
|
|
}
|
|
unpair({ protocol, id = null }) {
|
|
this._notify.delete(toKey(protocol, id));
|
|
}
|
|
opened({ protocol, id = null }) {
|
|
const key = toKey(protocol, id);
|
|
const info = this._infos.get(key);
|
|
return info ? info.opened > 0 : false;
|
|
}
|
|
createChannel({ userData = null, protocol, aliases = [], id = null, unique = true, handshake = null, messages = [], onopen = noop, onclose = noop, ondestroy = noop, ondrain = noop }) {
|
|
if (this.stream.destroyed) return null;
|
|
const info = this._get(protocol, id, aliases);
|
|
if (unique && info.opened > 0) return null;
|
|
if (info.incoming.length === 0) {
|
|
return new Channel(this, info, userData, protocol, aliases, id, handshake, messages, onopen, onclose, ondestroy, ondrain);
|
|
}
|
|
this._remoteBacklog--;
|
|
const remoteId = info.incoming.shift();
|
|
const r = this._remote[remoteId - 1];
|
|
if (r === null) return null;
|
|
const session = new Channel(this, info, userData, protocol, aliases, id, handshake, messages, onopen, onclose, ondestroy, ondrain);
|
|
session._remoteId = remoteId;
|
|
session._fullyOpenSoon();
|
|
return session;
|
|
}
|
|
_pushBatch(localId, buffer) {
|
|
if (this._batchState.end >= MAX_BATCH) {
|
|
this._sendBatch(this._batch, this._batchState);
|
|
this._batch = [];
|
|
this._batchState = { buffer: null, start: 0, end: 1 };
|
|
}
|
|
if (this._batch.length === 0 || this._batch[this._batch.length - 1].localId !== localId) {
|
|
this._batchState.end++;
|
|
c.uint.preencode(this._batchState, localId);
|
|
}
|
|
c.buffer.preencode(this._batchState, buffer);
|
|
this._batch.push({ localId, buffer });
|
|
}
|
|
_sendBatch(batch, state) {
|
|
if (batch.length === 0) return;
|
|
let prev = batch[0].localId;
|
|
state.buffer = this._alloc(state.end);
|
|
state.buffer[state.start++] = 0;
|
|
state.buffer[state.start++] = 0;
|
|
c.uint.encode(state, prev);
|
|
for (let i = 0; i < batch.length; i++) {
|
|
const b = batch[i];
|
|
if (prev !== b.localId) {
|
|
state.buffer[state.start++] = 0;
|
|
c.uint.encode(state, prev = b.localId);
|
|
}
|
|
c.buffer.encode(state, b.buffer);
|
|
}
|
|
this.drained = this.stream.write(state.buffer);
|
|
}
|
|
_get(protocol, id, aliases = []) {
|
|
const key = toKey(protocol, id);
|
|
let info = this._infos.get(key);
|
|
if (info) return info;
|
|
info = { key, protocol, aliases: [], id, pairing: 0, opened: 0, incoming: [], outgoing: [], lastChannel: null };
|
|
this._infos.set(key, info);
|
|
for (const alias of aliases) {
|
|
const key2 = toKey(alias, id);
|
|
info.aliases.push(key2);
|
|
this._infos.set(key2, info);
|
|
}
|
|
return info;
|
|
}
|
|
_gc(info) {
|
|
if (info.opened === 0 && info.outgoing.length === 0 && info.incoming.length === 0) {
|
|
this._infos.delete(info.key);
|
|
for (const alias of info.aliases) this._infos.delete(alias);
|
|
}
|
|
}
|
|
_ondata(buffer) {
|
|
if (buffer.byteLength === 0) return;
|
|
try {
|
|
const state = { buffer, start: 0, end: buffer.byteLength };
|
|
this._decode(c.uint.decode(state), state);
|
|
} catch (err) {
|
|
this._safeDestroy(err);
|
|
}
|
|
}
|
|
_ondrain() {
|
|
this.drained = true;
|
|
for (const s of this._local) {
|
|
if (s !== null) s._track(s.ondrain(s));
|
|
}
|
|
}
|
|
_onend() {
|
|
this.stream.end();
|
|
}
|
|
_decode(remoteId, state) {
|
|
const type = c.uint.decode(state);
|
|
if (remoteId === 0) {
|
|
return this._oncontrolsession(type, state);
|
|
}
|
|
const r = remoteId <= this._remote.length ? this._remote[remoteId - 1] : null;
|
|
if (r === null) return null;
|
|
if (r.pending !== null) {
|
|
this._bufferMessage(r, type, state);
|
|
return null;
|
|
}
|
|
return r.session._recv(type, state);
|
|
}
|
|
_oncontrolsession(type, state) {
|
|
switch (type) {
|
|
case 0:
|
|
this._onbatch(state);
|
|
break;
|
|
case 1:
|
|
return this._onopensession(state);
|
|
case 2:
|
|
this._onrejectsession(state);
|
|
break;
|
|
case 3:
|
|
this._onclosesession(state);
|
|
break;
|
|
}
|
|
return null;
|
|
}
|
|
_bufferMessage(r, type, { buffer, start, end }) {
|
|
const state = { buffer, start, end };
|
|
r.pending.push({ type, state });
|
|
this._buffered += byteSize(state);
|
|
this._pauseMaybe();
|
|
}
|
|
_pauseMaybe() {
|
|
if (this._paused === true || this._buffered <= MAX_BUFFERED) return;
|
|
this._paused = true;
|
|
this.stream.pause();
|
|
}
|
|
_resumeMaybe() {
|
|
if (this._paused === false || this._buffered > MAX_BUFFERED) return;
|
|
this._paused = false;
|
|
this.stream.resume();
|
|
}
|
|
_onbatch(state) {
|
|
const end = state.end;
|
|
let remoteId = c.uint.decode(state);
|
|
let waiting = null;
|
|
while (state.end > state.start) {
|
|
const len = c.uint.decode(state);
|
|
if (len === 0) {
|
|
remoteId = c.uint.decode(state);
|
|
continue;
|
|
}
|
|
state.end = state.start + len;
|
|
if (end !== state.end && waiting === null) {
|
|
waiting = [];
|
|
this.cork();
|
|
}
|
|
const p = this._decode(remoteId, state);
|
|
if (waiting !== null && p !== null) waiting.push(p);
|
|
state.start = state.end;
|
|
state.end = end;
|
|
}
|
|
if (waiting !== null) {
|
|
Promise.all(waiting).then(this._uncorkBound, this._safeDestroyBound);
|
|
}
|
|
}
|
|
_onopensession(state) {
|
|
const remoteId = c.uint.decode(state);
|
|
const protocol = c.string.decode(state);
|
|
const id = unslab(c.buffer.decode(state));
|
|
if (remoteId === 0) {
|
|
this._rejectSession(0);
|
|
return null;
|
|
}
|
|
const rid = remoteId - 1;
|
|
const info = this._get(protocol, id);
|
|
if (this._remote.length === rid) {
|
|
this._remote.push(null);
|
|
}
|
|
if (rid >= this._remote.length || this._remote[rid] !== null) {
|
|
throw new Error("Invalid open message");
|
|
}
|
|
if (info.outgoing.length > 0) {
|
|
const localId = info.outgoing.shift();
|
|
const session = this._local[localId - 1];
|
|
if (session === null) {
|
|
this._free.push(localId - 1);
|
|
return null;
|
|
}
|
|
this._remote[rid] = { state, pending: null, session: null };
|
|
session._remoteId = remoteId;
|
|
session._fullyOpen();
|
|
return null;
|
|
}
|
|
const copyState = { buffer: state.buffer, start: state.start, end: state.end };
|
|
this._remote[rid] = { state: copyState, pending: [], session: null };
|
|
if (++this._remoteBacklog > MAX_BACKLOG) {
|
|
throw new Error("Remote exceeded backlog");
|
|
}
|
|
info.pairing++;
|
|
info.incoming.push(remoteId);
|
|
return this._requestSession(protocol, id, info).catch(this._safeDestroyBound);
|
|
}
|
|
_onrejectsession(state) {
|
|
const localId = c.uint.decode(state);
|
|
for (const info of this._infos.values()) {
|
|
const i = info.outgoing.indexOf(localId);
|
|
if (i === -1) continue;
|
|
info.outgoing.splice(i, 1);
|
|
const session = this._local[localId - 1];
|
|
this._free.push(localId - 1);
|
|
if (session !== null) session._close(true);
|
|
this._gc(info);
|
|
return;
|
|
}
|
|
throw new Error("Invalid reject message");
|
|
}
|
|
_onclosesession(state) {
|
|
const remoteId = c.uint.decode(state);
|
|
if (remoteId === 0) return;
|
|
const rid = remoteId - 1;
|
|
const r = rid < this._remote.length ? this._remote[rid] : null;
|
|
if (r === null) return;
|
|
if (r.session !== null) r.session._close(true);
|
|
}
|
|
async _requestSession(protocol, id, info) {
|
|
const notify = this._notify.get(toKey(protocol, id)) || this._notify.get(toKey(protocol, null));
|
|
if (notify) await notify(id);
|
|
if (--info.pairing > 0) return;
|
|
while (info.incoming.length > 0) {
|
|
this._rejectSession(info, info.incoming.shift());
|
|
}
|
|
this._gc(info);
|
|
}
|
|
_rejectSession(info, remoteId) {
|
|
if (remoteId > 0) {
|
|
const r = this._remote[remoteId - 1];
|
|
if (r.pending !== null) {
|
|
for (let i = 0; i < r.pending.length; i++) {
|
|
this._buffered -= byteSize(r.pending[i].state);
|
|
}
|
|
}
|
|
this._remote[remoteId - 1] = null;
|
|
this._resumeMaybe();
|
|
}
|
|
const state = { buffer: null, start: 2, end: 2 };
|
|
c.uint.preencode(state, remoteId);
|
|
state.buffer = this._alloc(state.end);
|
|
state.buffer[0] = 0;
|
|
state.buffer[1] = 2;
|
|
c.uint.encode(state, remoteId);
|
|
this._write0(state.buffer);
|
|
}
|
|
_write0(buffer) {
|
|
if (this._batch !== null) {
|
|
this._pushBatch(0, buffer.subarray(1));
|
|
return;
|
|
}
|
|
this.drained = this.stream.write(buffer);
|
|
}
|
|
destroy(err) {
|
|
this.stream.destroy(err);
|
|
}
|
|
_safeDestroy(err) {
|
|
safetyCatch(err);
|
|
this.stream.destroy(err);
|
|
}
|
|
_shutdown() {
|
|
for (const s of this._local) {
|
|
if (s !== null) s._close(true);
|
|
}
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
function toKey(protocol, id) {
|
|
return protocol + "##" + (id ? b4a.toString(id, "hex") : "");
|
|
}
|
|
function byteSize(state) {
|
|
return 512 + (state.end - state.start);
|
|
}
|
|
function isPromise(p) {
|
|
return !!(p && typeof p.then === "function");
|
|
}
|
|
function encodingLength(enc, val) {
|
|
const state = { buffer: null, start: 0, end: 0 };
|
|
enc.preencode(state, val);
|
|
return state.end;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/random-array-iterator/index.js
|
|
var require_random_array_iterator = __commonJS({
|
|
"../../node_modules/random-array-iterator/index.js"(exports, module) {
|
|
module.exports = class RandomArrayIterator {
|
|
constructor(values) {
|
|
this.values = values;
|
|
this.start = 0;
|
|
this.length = this.values.length;
|
|
}
|
|
next() {
|
|
if (this.length === 0) {
|
|
if (this.start === 0) return { done: true, value: void 0 };
|
|
this.length = this.start;
|
|
this.start = 0;
|
|
}
|
|
const i = this.start + (Math.random() * this.length | 0);
|
|
const j = this.start + --this.length;
|
|
const value = this.values[i];
|
|
this.values[i] = this.values[j];
|
|
this.values[j] = value;
|
|
return { done: false, value };
|
|
}
|
|
dequeue() {
|
|
this.values[this.start + this.length] = this.values[this.values.length - 1];
|
|
this.values.pop();
|
|
}
|
|
requeue() {
|
|
const i = this.start + this.length;
|
|
const value = this.values[i];
|
|
this.values[i] = this.values[this.start];
|
|
this.values[this.start++] = value;
|
|
}
|
|
restart() {
|
|
this.start = 0;
|
|
this.length = this.values.length;
|
|
return this;
|
|
}
|
|
[Symbol.iterator]() {
|
|
return this;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/flat-tree/index.js
|
|
var require_flat_tree = __commonJS({
|
|
"../../node_modules/flat-tree/index.js"(exports) {
|
|
exports.fullRoots = function(index, result) {
|
|
if (index & 1) throw new Error("You can only look up roots for depth(0) blocks");
|
|
if (!result) result = [];
|
|
index /= 2;
|
|
let offset = 0;
|
|
let factor = 1;
|
|
while (true) {
|
|
if (!index) return result;
|
|
while (factor * 2 <= index) factor *= 2;
|
|
result.push(offset + factor - 1);
|
|
offset = offset + 2 * factor;
|
|
index -= factor;
|
|
factor = 1;
|
|
}
|
|
};
|
|
exports.futureRoots = function(index, result) {
|
|
if (index & 1) throw new Error("You can only look up future roots for depth(0) blocks");
|
|
if (!result) result = [];
|
|
let factor = 1;
|
|
while (factor * 2 <= index) factor *= 2;
|
|
if (factor * 2 - 2 === index) return result;
|
|
let pos = factor / 2 - 1;
|
|
while (pos + factor / 2 - 1 !== index) {
|
|
pos += factor;
|
|
while (pos + factor / 2 - 1 > index) {
|
|
factor /= 2;
|
|
pos -= factor / 2;
|
|
}
|
|
result.push(pos - factor / 2);
|
|
}
|
|
return result;
|
|
};
|
|
exports.patch = function(from, to) {
|
|
if (from === 0 || from >= to) return [];
|
|
const roots = exports.fullRoots(from);
|
|
const target = exports.fullRoots(to);
|
|
let i = 0;
|
|
for (; i < target.length; i++) {
|
|
if (i >= roots.length || roots[i] !== target[i]) break;
|
|
}
|
|
const patch = [];
|
|
if (i < roots.length) {
|
|
let prev = roots.length - 1;
|
|
const ite = exports.iterator(roots[prev--]);
|
|
while (ite.index !== target[i]) {
|
|
ite.sibling();
|
|
if (prev >= 0 && ite.index === roots[prev]) {
|
|
prev--;
|
|
} else {
|
|
patch.push(ite.index);
|
|
}
|
|
patch.push(ite.parent());
|
|
}
|
|
i++;
|
|
}
|
|
for (; i < target.length; i++) patch.push(target[i]);
|
|
return patch;
|
|
};
|
|
exports.depth = function(index) {
|
|
let depth = 0;
|
|
index += 1;
|
|
while (!(index & 1)) {
|
|
depth++;
|
|
index = rightShift(index);
|
|
}
|
|
return depth;
|
|
};
|
|
exports.sibling = function(index, depth) {
|
|
if (!depth) depth = exports.depth(index);
|
|
const offset = exports.offset(index, depth);
|
|
return exports.index(depth, offset & 1 ? offset - 1 : offset + 1);
|
|
};
|
|
exports.parent = function(index, depth) {
|
|
if (!depth) depth = exports.depth(index);
|
|
const offset = exports.offset(index, depth);
|
|
return exports.index(depth + 1, rightShift(offset));
|
|
};
|
|
exports.leftChild = function(index, depth) {
|
|
if (!(index & 1)) return -1;
|
|
if (!depth) depth = exports.depth(index);
|
|
return exports.index(depth - 1, exports.offset(index, depth) * 2);
|
|
};
|
|
exports.rightChild = function(index, depth) {
|
|
if (!(index & 1)) return -1;
|
|
if (!depth) depth = exports.depth(index);
|
|
return exports.index(depth - 1, 1 + exports.offset(index, depth) * 2);
|
|
};
|
|
exports.children = function(index, depth) {
|
|
if (!(index & 1)) return null;
|
|
if (!depth) depth = exports.depth(index);
|
|
const offset = exports.offset(index, depth) * 2;
|
|
return [
|
|
exports.index(depth - 1, offset),
|
|
exports.index(depth - 1, offset + 1)
|
|
];
|
|
};
|
|
exports.leftSpan = function(index, depth) {
|
|
if (!(index & 1)) return index;
|
|
if (!depth) depth = exports.depth(index);
|
|
return exports.offset(index, depth) * twoPow(depth + 1);
|
|
};
|
|
exports.rightSpan = function(index, depth) {
|
|
if (!(index & 1)) return index;
|
|
if (!depth) depth = exports.depth(index);
|
|
return (exports.offset(index, depth) + 1) * twoPow(depth + 1) - 2;
|
|
};
|
|
exports.nextLeaf = function(index) {
|
|
let factor = 1;
|
|
let r = index;
|
|
while ((r & 1) === 1) {
|
|
r = (r - 1) / 2;
|
|
factor *= 2;
|
|
}
|
|
return index + factor + 1;
|
|
};
|
|
exports.count = function(index, depth) {
|
|
if (!(index & 1)) return 1;
|
|
if (!depth) depth = exports.depth(index);
|
|
return twoPow(depth + 1) - 1;
|
|
};
|
|
exports.countLeaves = function(index) {
|
|
return (exports.count(index) + 1) / 2;
|
|
};
|
|
exports.spans = function(index, depth) {
|
|
if (!(index & 1)) return [index, index];
|
|
if (!depth) depth = exports.depth(index);
|
|
const offset = exports.offset(index, depth);
|
|
const width = twoPow(depth + 1);
|
|
return [offset * width, (offset + 1) * width - 2];
|
|
};
|
|
exports.index = function(depth, offset) {
|
|
return (1 + 2 * offset) * twoPow(depth) - 1;
|
|
};
|
|
exports.offset = function(index, depth) {
|
|
if (!(index & 1)) return index / 2;
|
|
if (!depth) depth = exports.depth(index);
|
|
return ((index + 1) / twoPow(depth) - 1) / 2;
|
|
};
|
|
exports.iterator = function(index) {
|
|
const ite = new Iterator();
|
|
ite.seek(index || 0);
|
|
return ite;
|
|
};
|
|
function twoPow(n) {
|
|
return n < 31 ? 1 << n : (1 << 30) * (1 << n - 30);
|
|
}
|
|
function rightShift(n) {
|
|
return (n - (n & 1)) / 2;
|
|
}
|
|
function Iterator() {
|
|
this.index = 0;
|
|
this.offset = 0;
|
|
this.factor = 0;
|
|
}
|
|
Iterator.prototype.seek = function(index) {
|
|
this.index = index;
|
|
if (this.index & 1) {
|
|
this.offset = exports.offset(index);
|
|
this.factor = twoPow(exports.depth(index) + 1);
|
|
} else {
|
|
this.offset = index / 2;
|
|
this.factor = 2;
|
|
}
|
|
};
|
|
Iterator.prototype.isLeft = function() {
|
|
return (this.offset & 1) === 0;
|
|
};
|
|
Iterator.prototype.isRight = function() {
|
|
return (this.offset & 1) === 1;
|
|
};
|
|
Iterator.prototype.isRoot = function(length) {
|
|
const currentLength = 1 + (this.index + this.factor / 2 - 1) / 2;
|
|
if (length < currentLength) return false;
|
|
const factor = this.factor * 2;
|
|
const index = this.offset & 1 ? this.index - this.factor / 2 : this.index + this.factor / 2;
|
|
const parentLength = 1 + (index + factor / 2 - 1) / 2;
|
|
return parentLength > length;
|
|
};
|
|
Iterator.prototype.contains = function(index) {
|
|
return index > this.index ? index < this.index + this.factor / 2 : index < this.index ? index > this.index - this.factor / 2 : true;
|
|
};
|
|
Iterator.prototype.prev = function() {
|
|
if (!this.offset) return this.index;
|
|
this.offset--;
|
|
this.index -= this.factor;
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.next = function() {
|
|
this.offset++;
|
|
this.index += this.factor;
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.count = function() {
|
|
if (!(this.index & 1)) return 1;
|
|
return this.factor - 1;
|
|
};
|
|
Iterator.prototype.countLeaves = function() {
|
|
return (this.count() + 1) / 2;
|
|
};
|
|
Iterator.prototype.sibling = function() {
|
|
return this.isLeft() ? this.next() : this.prev();
|
|
};
|
|
Iterator.prototype.parent = function() {
|
|
if (this.offset & 1) {
|
|
this.index -= this.factor / 2;
|
|
this.offset = (this.offset - 1) / 2;
|
|
} else {
|
|
this.index += this.factor / 2;
|
|
this.offset /= 2;
|
|
}
|
|
this.factor *= 2;
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.leftSpan = function() {
|
|
this.index = this.index - this.factor / 2 + 1;
|
|
this.offset = this.index / 2;
|
|
this.factor = 2;
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.peekLeftSpan = function() {
|
|
return this.index - this.factor / 2 + 1;
|
|
};
|
|
Iterator.prototype.rightSpan = function() {
|
|
this.index = this.index + this.factor / 2 - 1;
|
|
this.offset = this.index / 2;
|
|
this.factor = 2;
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.peekRightSpan = function() {
|
|
return this.index + this.factor / 2 - 1;
|
|
};
|
|
Iterator.prototype.leftChild = function() {
|
|
if (this.factor === 2) return this.index;
|
|
this.factor /= 2;
|
|
this.index -= this.factor / 2;
|
|
this.offset *= 2;
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.rightChild = function() {
|
|
if (this.factor === 2) return this.index;
|
|
this.factor /= 2;
|
|
this.index += this.factor / 2;
|
|
this.offset = 2 * this.offset + 1;
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.nextTree = function() {
|
|
this.index = this.index + this.factor / 2 + 1;
|
|
this.offset = this.index / 2;
|
|
this.factor = 2;
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.prevTree = function() {
|
|
if (!this.offset) {
|
|
this.index = 0;
|
|
this.factor = 2;
|
|
} else {
|
|
this.index = this.index - this.factor / 2 - 1;
|
|
this.offset = this.index / 2;
|
|
this.factor = 2;
|
|
}
|
|
return this.index;
|
|
};
|
|
Iterator.prototype.fullRoot = function(index) {
|
|
if (index <= this.index || (this.index & 1) > 0) return false;
|
|
while (index > this.index + this.factor + this.factor / 2) {
|
|
this.index += this.factor / 2;
|
|
this.factor *= 2;
|
|
this.offset /= 2;
|
|
}
|
|
return true;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/receiver-queue.js
|
|
var require_receiver_queue = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/receiver-queue.js"(exports, module) {
|
|
var FIFO = require_fast_fifo();
|
|
module.exports = class ReceiverQueue {
|
|
constructor() {
|
|
this.queue = new FIFO();
|
|
this.priority = [];
|
|
this.requests = /* @__PURE__ */ new Map();
|
|
this.length = 0;
|
|
}
|
|
push(req) {
|
|
if (req.priority > 0) this.priority.push(req);
|
|
else this.queue.push(req);
|
|
this.requests.set(req.id, req);
|
|
this.length++;
|
|
}
|
|
shift() {
|
|
while (this.priority.length > 0) {
|
|
const msg = this.priority.pop();
|
|
const req = this._processRequest(msg);
|
|
if (req !== null) return req;
|
|
}
|
|
while (this.queue.length > 0) {
|
|
const msg = this.queue.shift();
|
|
const req = this._processRequest(msg);
|
|
if (req !== null) return req;
|
|
}
|
|
return null;
|
|
}
|
|
_processRequest(req) {
|
|
if (req.block || req.hash || req.seek || req.upgrade || req.manifest) {
|
|
this.requests.delete(req.id);
|
|
this.length--;
|
|
return req;
|
|
}
|
|
return null;
|
|
}
|
|
clear() {
|
|
this.queue.clear();
|
|
this.priority = [];
|
|
this.length = 0;
|
|
this.requests.clear();
|
|
}
|
|
delete(id) {
|
|
const req = this.requests.get(id);
|
|
if (!req) return;
|
|
req.block = null;
|
|
req.hash = null;
|
|
req.seek = null;
|
|
req.upgrade = null;
|
|
req.manifest = false;
|
|
this.requests.delete(id);
|
|
this.length--;
|
|
if (this.length === 0) {
|
|
this.queue.clear();
|
|
this.priority = [];
|
|
}
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/hotswap-queue.js
|
|
var require_hotswap_queue = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/hotswap-queue.js"(exports, module) {
|
|
var TICKS = 16;
|
|
module.exports = class HotswapQueue {
|
|
constructor() {
|
|
this.priorities = [[], [], []];
|
|
}
|
|
*pick(peer) {
|
|
for (let i = 0; i < this.priorities.length; i++) {
|
|
let ticks = (this.priorities.length - i) * TICKS;
|
|
const queue = this.priorities[i];
|
|
for (let j = 0; j < queue.length; j++) {
|
|
const r = j + Math.floor(Math.random() * queue.length - j);
|
|
const a = queue[j];
|
|
const b = queue[r];
|
|
if (r !== j) {
|
|
queue[b.hotswap.index = j] = b;
|
|
queue[a.hotswap.index = r] = a;
|
|
}
|
|
if (hasInflight(b, peer)) continue;
|
|
yield b;
|
|
if (--ticks <= 0) break;
|
|
}
|
|
}
|
|
}
|
|
add(block) {
|
|
if (block.hotswap !== null) this.remove(block);
|
|
if (block.inflight.length === 0 || block.inflight.length >= 3) return;
|
|
const queue = this.priorities[block.inflight.length - 1];
|
|
const index = queue.push(block) - 1;
|
|
block.hotswap = { ref: this, queue, index };
|
|
}
|
|
remove(block) {
|
|
const hotswap = block.hotswap;
|
|
if (hotswap === null) return;
|
|
block.hotswap = null;
|
|
const head = hotswap.queue.pop();
|
|
if (head === block) return;
|
|
hotswap.queue[head.hotswap.index = hotswap.index] = head;
|
|
}
|
|
};
|
|
function hasInflight(block, peer) {
|
|
for (let j = 0; j < block.inflight.length; j++) {
|
|
if (block.inflight[j].peer === peer) return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/big-sparse-array/index.js
|
|
var require_big_sparse_array = __commonJS({
|
|
"../../node_modules/big-sparse-array/index.js"(exports, module) {
|
|
var FACTOR = new Uint16Array(8);
|
|
function factor4096(i, n) {
|
|
while (n > 0) {
|
|
const f = i & 4095;
|
|
FACTOR[--n] = f;
|
|
i = (i - f) / 4096;
|
|
}
|
|
return FACTOR;
|
|
}
|
|
module.exports = class BigSparseArray {
|
|
constructor() {
|
|
this.tiny = new TinyArray();
|
|
this.maxLength = 4096;
|
|
this.factor = 1;
|
|
}
|
|
set(index, val) {
|
|
if (val !== void 0) {
|
|
while (index >= this.maxLength) {
|
|
this.maxLength *= 4096;
|
|
this.factor++;
|
|
if (!this.tiny.isEmptyish()) {
|
|
const t = new TinyArray();
|
|
t.set(0, this.tiny);
|
|
this.tiny = t;
|
|
}
|
|
}
|
|
}
|
|
const f = factor4096(index, this.factor);
|
|
const last = this.factor - 1;
|
|
let tiny = this.tiny;
|
|
for (let i = 0; i < last; i++) {
|
|
const next = tiny.get(f[i]);
|
|
if (next === void 0) {
|
|
if (val === void 0) return;
|
|
tiny = tiny.set(f[i], new TinyArray());
|
|
} else {
|
|
tiny = next;
|
|
}
|
|
}
|
|
return tiny.set(f[last], val);
|
|
}
|
|
get(index) {
|
|
if (index >= this.maxLength) return;
|
|
const f = factor4096(index, this.factor);
|
|
const last = this.factor - 1;
|
|
let tiny = this.tiny;
|
|
for (let i = 0; i < last; i++) {
|
|
tiny = tiny.get(f[i]);
|
|
if (tiny === void 0) return;
|
|
}
|
|
return tiny.get(f[last]);
|
|
}
|
|
};
|
|
var TinyArray = class {
|
|
constructor() {
|
|
this.s = 0;
|
|
this.b = new Array(1);
|
|
this.f = new Uint16Array(1);
|
|
}
|
|
isEmptyish() {
|
|
return this.b.length === 1 && this.b[0] === void 0;
|
|
}
|
|
get(i) {
|
|
if (this.s === 12) return this.b[i];
|
|
const f = i >>> this.s;
|
|
const r = i & this.b.length - 1;
|
|
return this.f[r] === f ? this.b[r] : void 0;
|
|
}
|
|
set(i, v) {
|
|
while (this.s !== 12) {
|
|
const f = i >>> this.s;
|
|
const r = i & this.b.length - 1;
|
|
const o = this.b[r];
|
|
if (o === void 0 || f === this.f[r]) {
|
|
this.b[r] = v;
|
|
this.f[r] = f;
|
|
return v;
|
|
}
|
|
this.grow();
|
|
}
|
|
this.b[i] = v;
|
|
return v;
|
|
}
|
|
grow() {
|
|
const os = this.s;
|
|
const ob = this.b;
|
|
const of = this.f;
|
|
this.s += 4;
|
|
this.b = new Array(this.b.length << 4);
|
|
this.f = this.s === 12 ? null : new Uint8Array(this.b.length);
|
|
const m = this.b.length - 1;
|
|
for (let or = 0; or < ob.length; or++) {
|
|
if (ob[or] === void 0) continue;
|
|
const i = of[or] << os | or;
|
|
const f = i >>> this.s;
|
|
const r = i & m;
|
|
this.b[r] = ob[or];
|
|
if (this.s !== 12) this.f[r] = f;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/simdle-native/binding.js
|
|
var require_binding4 = __commonJS({
|
|
"../../node_modules/simdle-native/binding.js"(exports, module) {
|
|
__require.addon = require_node2();
|
|
module.exports = __require.addon(".", __filename);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/simdle-native/index.js
|
|
var require_simdle_native = __commonJS({
|
|
"../../node_modules/simdle-native/index.js"(exports) {
|
|
var binding = require_binding4();
|
|
var b4a = require_b4a();
|
|
function predicate(u8, u16, u32) {
|
|
return function predicate2(buf) {
|
|
if (buf.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
const n = buf.BYTES_PER_ELEMENT;
|
|
if (n === 1) return u8(buf);
|
|
if (n === 2) return u16(buf);
|
|
return u32(buf);
|
|
};
|
|
}
|
|
function unary(u8, u16, u32) {
|
|
return function unary2(buf, result = b4a.allocUnsafe(buf.byteLength)) {
|
|
if (buf.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
if (buf.byteLength !== result.byteLength) {
|
|
throw new Error("Length of result buffer is insufficient");
|
|
}
|
|
const n = buf.BYTES_PER_ELEMENT;
|
|
if (n === 1) u8(buf, result);
|
|
else if (n === 2) u16(buf, result);
|
|
else u32(buf, result);
|
|
return result;
|
|
};
|
|
}
|
|
function binary(u8, u16, u32) {
|
|
return function binary2(a, b, result = b4a.allocUnsafe(a.byteLength)) {
|
|
if (a.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
if (a.byteLength !== b.byteLength || a.byteLength !== result.byteLength) {
|
|
throw new Error("Buffers must be the same length");
|
|
}
|
|
const n = a.BYTES_PER_ELEMENT;
|
|
if (n === 1) u8(a, b, result);
|
|
else if (n === 2) u16(a, b, result);
|
|
else u32(a, b, result);
|
|
return result;
|
|
};
|
|
}
|
|
function reduce(u8, u16, u32) {
|
|
return function reduce2(buf) {
|
|
if (buf.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
const n = buf.BYTES_PER_ELEMENT;
|
|
if (n === 1) return u8(buf);
|
|
if (n === 2) return u16(buf);
|
|
return u32(buf);
|
|
};
|
|
}
|
|
exports.allo = predicate(
|
|
binding.simdle_native_allo_v128_u8,
|
|
binding.simdle_native_allo_v128_u16,
|
|
binding.simdle_native_allo_v128_u32
|
|
);
|
|
exports.allz = predicate(
|
|
binding.simdle_native_allz_v128_u8,
|
|
binding.simdle_native_allz_v128_u16,
|
|
binding.simdle_native_allz_v128_u32
|
|
);
|
|
exports.and = binary(
|
|
binding.simdle_native_and_v128_u8,
|
|
binding.simdle_native_and_v128_u16,
|
|
binding.simdle_native_and_v128_u32
|
|
);
|
|
exports.clear = binary(
|
|
binding.simdle_native_clear_v128_u8,
|
|
binding.simdle_native_clear_v128_u16,
|
|
binding.simdle_native_clear_v128_u32
|
|
);
|
|
exports.clo = unary(
|
|
binding.simdle_native_clo_v128_u8,
|
|
binding.simdle_native_clo_v128_u16,
|
|
binding.simdle_native_clo_v128_u32
|
|
);
|
|
exports.clz = unary(
|
|
binding.simdle_native_clz_v128_u8,
|
|
binding.simdle_native_clz_v128_u16,
|
|
binding.simdle_native_clz_v128_u32
|
|
);
|
|
exports.cnt = unary(
|
|
binding.simdle_native_cnt_v128_u8,
|
|
binding.simdle_native_cnt_v128_u16,
|
|
binding.simdle_native_cnt_v128_u32
|
|
);
|
|
exports.cto = unary(
|
|
binding.simdle_native_cto_v128_u8,
|
|
binding.simdle_native_cto_v128_u16,
|
|
binding.simdle_native_cto_v128_u32
|
|
);
|
|
exports.ctz = unary(
|
|
binding.simdle_native_ctz_v128_u8,
|
|
binding.simdle_native_ctz_v128_u16,
|
|
binding.simdle_native_ctz_v128_u32
|
|
);
|
|
exports.not = unary(
|
|
binding.simdle_native_not_v128_u8,
|
|
binding.simdle_native_not_v128_u16,
|
|
binding.simdle_native_not_v128_u32
|
|
);
|
|
exports.or = binary(
|
|
binding.simdle_native_or_v128_u8,
|
|
binding.simdle_native_or_v128_u16,
|
|
binding.simdle_native_or_v128_u32
|
|
);
|
|
exports.sum = reduce(
|
|
binding.simdle_native_sum_v128_u8,
|
|
binding.simdle_native_sum_v128_u16,
|
|
binding.simdle_native_sum_v128_u32
|
|
);
|
|
exports.xor = binary(
|
|
binding.simdle_native_xor_v128_u8,
|
|
binding.simdle_native_xor_v128_u16,
|
|
binding.simdle_native_xor_v128_u32
|
|
);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/simdle-universal/scalar.js
|
|
var require_scalar = __commonJS({
|
|
"../../node_modules/simdle-universal/scalar.js"(exports) {
|
|
var clz = exports.clz = function clz2(n) {
|
|
return Math.clz32(n);
|
|
};
|
|
exports.clo = function clo(n) {
|
|
return clz(~n);
|
|
};
|
|
var ctz = exports.ctz = function ctz2(n) {
|
|
return 32 - (n === 0 ? 0 : clz(n & -n) + 1);
|
|
};
|
|
exports.cto = function cto(n) {
|
|
return ctz(~n);
|
|
};
|
|
exports.cnt = function cnt(n) {
|
|
n = n - (n >>> 1 & 1431655765);
|
|
n = (n & 858993459) + (n >>> 2 & 858993459);
|
|
n = n + (n >>> 4) & 252645135;
|
|
n = n * 16843009 >>> 24;
|
|
return n;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/simdle-universal/fallback.js
|
|
var require_fallback = __commonJS({
|
|
"../../node_modules/simdle-universal/fallback.js"(exports) {
|
|
var b4a = require_b4a();
|
|
var scalar = require_scalar();
|
|
function view(buf, n) {
|
|
if (n === buf.BYTES_PER_ELEMENT) return buf;
|
|
let TypedArray;
|
|
if (n === 1) TypedArray = Uint8Array;
|
|
else if (n === 2) TypedArray = Uint16Array;
|
|
else TypedArray = Uint32Array;
|
|
return new TypedArray(buf.buffer, buf.byteOffset, buf.byteLength / n);
|
|
}
|
|
function unary(u8, u16 = u8, u32 = u16) {
|
|
return function unary2(buf, result = b4a.allocUnsafe(buf.byteLength)) {
|
|
if (buf.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
if (buf.byteLength !== result.byteLength) {
|
|
throw new Error("Length of result buffer is insufficient");
|
|
}
|
|
const n = buf.BYTES_PER_ELEMENT;
|
|
if (n === 1) u8(buf, view(result, n));
|
|
else if (n === 2) u16(buf, view(result, n));
|
|
else u32(buf, view(result, n));
|
|
return result;
|
|
};
|
|
}
|
|
function binary(u8, u16 = u8, u32 = u16) {
|
|
return function binary2(a, b, result = b4a.allocUnsafe(a.byteLength)) {
|
|
if (a.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
if (a.byteLength !== b.byteLength || a.byteLength !== result.byteLength) {
|
|
throw new Error("Buffers must be the same length");
|
|
}
|
|
const n = a.BYTES_PER_ELEMENT;
|
|
if (n === 1) u8(a, b, view(result, n));
|
|
else if (n === 2) u16(a, b, view(result, n));
|
|
else u32(a, b, view(result, n));
|
|
return result;
|
|
};
|
|
}
|
|
function reduce(u8, u16 = u8, u32 = u16) {
|
|
return function reduce2(buf) {
|
|
if (buf.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
const n = buf.BYTES_PER_ELEMENT;
|
|
if (n === 1) return u8(buf);
|
|
if (n === 2) return u16(buf);
|
|
return u32(buf);
|
|
};
|
|
}
|
|
exports.allo = function allo(buf) {
|
|
if (buf.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
const m = 2 ** (buf.BYTES_PER_ELEMENT * 8) - 1;
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
if (buf[i] !== m) return false;
|
|
}
|
|
return true;
|
|
};
|
|
exports.allz = function allz(buf) {
|
|
if (buf.byteLength % 16 !== 0) {
|
|
throw new Error("Buffer length must be a multiple of 16");
|
|
}
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
if (buf[i] !== 0) return false;
|
|
}
|
|
return true;
|
|
};
|
|
exports.and = binary(
|
|
(a, b, result) => {
|
|
for (let i = 0, n = result.length; i < n; i++) {
|
|
result[i] = a[i] & b[i];
|
|
}
|
|
}
|
|
);
|
|
exports.clear = binary(
|
|
(a, b, result) => {
|
|
for (let i = 0, n = result.length; i < n; i++) {
|
|
result[i] = a[i] & ~b[i];
|
|
}
|
|
}
|
|
);
|
|
exports.clo = unary(
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = 24 - scalar.clo(buf[i]);
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = 16 - scalar.clo(buf[i]);
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = scalar.clo(buf[i]);
|
|
}
|
|
}
|
|
);
|
|
exports.clz = unary(
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = 24 - scalar.clz(buf[i]);
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = 16 - scalar.clz(buf[i]);
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = scalar.clz(buf[i]);
|
|
}
|
|
}
|
|
);
|
|
exports.cnt = unary(
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = scalar.cnt(buf[i]) & 255;
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = scalar.cnt(buf[i]) & 65535;
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = scalar.cnt(buf[i]);
|
|
}
|
|
}
|
|
);
|
|
exports.cto = unary(
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = Math.min(scalar.cto(buf[i]), 8);
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = Math.min(scalar.cto(buf[i]), 16);
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = scalar.cto(buf[i]);
|
|
}
|
|
}
|
|
);
|
|
exports.ctz = unary(
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = Math.min(scalar.ctz(buf[i]), 8);
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = Math.min(scalar.ctz(buf[i]), 16);
|
|
}
|
|
},
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = scalar.ctz(buf[i]);
|
|
}
|
|
}
|
|
);
|
|
exports.not = unary(
|
|
(buf, result) => {
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result[i] = ~buf[i];
|
|
}
|
|
}
|
|
);
|
|
exports.or = binary(
|
|
(a, b, result) => {
|
|
for (let i = 0, n = result.length; i < n; i++) {
|
|
result[i] = a[i] | b[i];
|
|
}
|
|
}
|
|
);
|
|
exports.sum = reduce(
|
|
(buf) => {
|
|
let result = 0n;
|
|
for (let i = 0, n = buf.length; i < n; i++) {
|
|
result += BigInt(buf[i]);
|
|
}
|
|
return result;
|
|
}
|
|
);
|
|
exports.xor = binary(
|
|
(a, b, result) => {
|
|
for (let i = 0, n = result.length; i < n; i++) {
|
|
result[i] = a[i] ^ b[i];
|
|
}
|
|
}
|
|
);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/simdle-universal/index.js
|
|
var require_simdle_universal = __commonJS({
|
|
"../../node_modules/simdle-universal/index.js"(exports, module) {
|
|
try {
|
|
module.exports = require_simdle_native();
|
|
} catch {
|
|
module.exports = require_fallback();
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/quickbit-universal/fallback.js
|
|
var require_fallback2 = __commonJS({
|
|
"../../node_modules/quickbit-universal/fallback.js"(exports) {
|
|
var simdle = require_simdle_universal();
|
|
var INDEX_LEN = (16 + 128 * 16) * 2;
|
|
var get = exports.get = function get2(field, bit) {
|
|
const n = field.byteLength * 8;
|
|
if (bit < 0) bit += n;
|
|
if (bit < 0 || bit >= n) return false;
|
|
const m = field.BYTES_PER_ELEMENT * 8;
|
|
const offset = bit & m - 1;
|
|
const i = (bit - offset) / m;
|
|
return (field[i] & 1 << offset) !== 0;
|
|
};
|
|
var set = exports.set = function set2(field, bit, value = true) {
|
|
const n = field.byteLength * 8;
|
|
if (bit < 0) bit += n;
|
|
if (bit < 0 || bit >= n) return false;
|
|
const m = field.BYTES_PER_ELEMENT * 8;
|
|
const offset = bit & m - 1;
|
|
const i = (bit - offset) / m;
|
|
const mask = 1 << offset;
|
|
if (value) {
|
|
if ((field[i] & mask) !== 0) return false;
|
|
} else {
|
|
if ((field[i] & mask) === 0) return false;
|
|
}
|
|
field[i] ^= mask;
|
|
return true;
|
|
};
|
|
exports.fill = function fill(field, value, start = 0, end = field.byteLength * 8) {
|
|
const n = field.byteLength * 8;
|
|
if (start < 0) start += n;
|
|
if (end < 0) end += n;
|
|
if (start < 0 || start >= field.byteLength * 8 || start >= end) return field;
|
|
const m = field.BYTES_PER_ELEMENT * 8;
|
|
let i, j;
|
|
{
|
|
const offset = start & m - 1;
|
|
i = (start - offset) / m;
|
|
if (offset !== 0) {
|
|
let shift = m - offset;
|
|
if (end - start < shift) shift = end - start;
|
|
const mask = (1 << shift) - 1 << offset;
|
|
if (value) field[i] |= mask;
|
|
else field[i] &= ~mask;
|
|
i++;
|
|
}
|
|
}
|
|
{
|
|
const offset = end & m - 1;
|
|
j = (end - offset) / m;
|
|
if (offset !== 0 && j >= i) {
|
|
const mask = (1 << offset) - 1;
|
|
if (value) field[j] |= mask;
|
|
else field[j] &= ~mask;
|
|
}
|
|
}
|
|
if (i < j) field.fill(value ? 2 ** m - 1 : 0, i, j);
|
|
return field;
|
|
};
|
|
exports.clear = function clear(field, ...chunks) {
|
|
const n = field.byteLength;
|
|
for (const chunk of chunks) {
|
|
if (chunk.offset >= n) continue;
|
|
const m = chunk.field.byteLength;
|
|
let i = chunk.offset;
|
|
let j = 0;
|
|
while (((i & 15) !== 0 || (j & 15) !== 0) && i < n && j < m) {
|
|
field[i] = field[i] & ~chunk.field[j];
|
|
i++;
|
|
j++;
|
|
}
|
|
if (i + 15 < n && j + 15 < m) {
|
|
const len = Math.min(n - (n & 15) - i, m - (m & 15) - j);
|
|
simdle.clear(field.subarray(i, i + len), chunk.field.subarray(j, j + len), field.subarray(i, i + len));
|
|
}
|
|
while (i < n && j < m) {
|
|
field[i] = field[i] & ~chunk.field[j];
|
|
i++;
|
|
j++;
|
|
}
|
|
}
|
|
};
|
|
function bitOffset(bit, offset) {
|
|
return !bit ? offset : INDEX_LEN * 8 / 2 + offset;
|
|
}
|
|
function byteOffset(bit, offset) {
|
|
return !bit ? offset : INDEX_LEN / 2 + offset;
|
|
}
|
|
exports.findFirst = function findFirst(field, value, position = 0) {
|
|
const n = field.byteLength * 8;
|
|
if (position < 0) position += n;
|
|
if (position < 0) position = 0;
|
|
if (position >= n) return -1;
|
|
value = !!value;
|
|
for (let i = position; i < n; i++) {
|
|
if (get(field, i) === value) return i;
|
|
}
|
|
return -1;
|
|
};
|
|
exports.findLast = function findLast(field, value, position = field.byteLength * 8 - 1) {
|
|
const n = field.byteLength * 8;
|
|
if (position < 0) position += n;
|
|
if (position < 0) return -1;
|
|
if (position >= n) position = n - 1;
|
|
value = !!value;
|
|
for (let i = position; i >= 0; i--) {
|
|
if (get(field, i) === value) return i;
|
|
}
|
|
return -1;
|
|
};
|
|
var Index = exports.Index = class Index {
|
|
static from(fieldOrChunks, byteLength = -1) {
|
|
if (Array.isArray(fieldOrChunks)) {
|
|
return new SparseIndex(fieldOrChunks, byteLength);
|
|
} else {
|
|
return new DenseIndex(fieldOrChunks, byteLength);
|
|
}
|
|
}
|
|
constructor(byteLength) {
|
|
this._byteLength = byteLength;
|
|
this.handle = new Uint32Array(INDEX_LEN / 4);
|
|
}
|
|
get byteLength() {
|
|
return this._byteLength;
|
|
}
|
|
skipFirst(value, position = 0) {
|
|
const n = this.byteLength * 8;
|
|
if (position < 0) position += n;
|
|
if (position < 0) position = 0;
|
|
if (position >= n) return n - 1;
|
|
let i = Math.floor(position / 16384);
|
|
if (i > 127) return position;
|
|
while (i <= 127 && get(this.handle, bitOffset(value, i))) {
|
|
i++;
|
|
}
|
|
if (i === 128) return n - 1;
|
|
let k = i * 16384;
|
|
let j = 0;
|
|
if (position > k) j = Math.floor((position - k) / 128);
|
|
while (j <= 127 && get(this.handle, bitOffset(value, i * 128 + j + 128))) {
|
|
j++;
|
|
k += 128;
|
|
}
|
|
if (j === 128 && i !== 127) return this.skipFirst(value, (i + 1) * 16384);
|
|
if (k > position) position = k;
|
|
return position < n ? position : n - 1;
|
|
}
|
|
skipLast(value, position = this.byteLength * 8 - 1) {
|
|
const n = this.byteLength * 8;
|
|
if (position < 0) position += n;
|
|
if (position < 0) return 0;
|
|
if (position >= n) position = n - 1;
|
|
let i = Math.floor(position / 16384);
|
|
if (i > 127) return position;
|
|
while (i >= 0 && get(this.handle, bitOffset(value, i))) {
|
|
i--;
|
|
}
|
|
if (i === -1) return 0;
|
|
let k = (i + 1) * 16384 - 1;
|
|
let j = 127;
|
|
if (position < k) j = 128 - Math.ceil((k - position) / 128);
|
|
while (j >= 0 && get(this.handle, bitOffset(value, i * 128 + j + 128))) {
|
|
j--;
|
|
k -= 128;
|
|
}
|
|
if (j === -1 && i !== 0) return this.skipLast(value, i * 16384 - 1);
|
|
if (k < position) position = k;
|
|
return position;
|
|
}
|
|
};
|
|
var DenseIndex = class extends Index {
|
|
constructor(field, byteLength) {
|
|
super(byteLength);
|
|
this.field = field;
|
|
const m = field.BYTES_PER_ELEMENT;
|
|
for (let i = 0; i < 128; i++) {
|
|
for (let j = 0; j < 128; j++) {
|
|
const offset = (i * 128 + j) * 16;
|
|
let allz = true;
|
|
let allo = false;
|
|
if (offset + 16 <= this.field.byteLength) {
|
|
const vec = this.field.subarray(offset / m, (offset + 16) / m);
|
|
allz = simdle.allz(vec);
|
|
allo = simdle.allo(vec);
|
|
}
|
|
const k = i * 128 + 128 + j;
|
|
set(this.handle, bitOffset(false, k), allz);
|
|
set(this.handle, bitOffset(true, k), allo);
|
|
}
|
|
{
|
|
const offset = byteOffset(false, i * 16 + 16) / 4;
|
|
const allo = simdle.allo(this.handle.subarray(offset, offset + 4));
|
|
set(this.handle, bitOffset(false, i), allo);
|
|
}
|
|
{
|
|
const offset = byteOffset(true, i * 16 + 16) / 4;
|
|
const allo = simdle.allo(this.handle.subarray(offset, offset + 4));
|
|
set(this.handle, bitOffset(true, i), allo);
|
|
}
|
|
}
|
|
}
|
|
get byteLength() {
|
|
if (this._byteLength !== -1) return this._byteLength;
|
|
return this.field.byteLength;
|
|
}
|
|
update(bit) {
|
|
const n = this.byteLength * 8;
|
|
if (bit < 0) bit += n;
|
|
if (bit < 0 || bit >= n) return false;
|
|
const m = this.field.BYTES_PER_ELEMENT;
|
|
const i = Math.floor(bit / 16384);
|
|
const j = Math.floor(bit / 128);
|
|
const offset = j * 16 / m;
|
|
const vec = this.field.subarray(offset, offset + 16 / m);
|
|
const allz = simdle.allz(vec);
|
|
const allo = simdle.allo(vec);
|
|
let changed = false;
|
|
if (set(this.handle, bitOffset(false, 128 + j), allz)) {
|
|
changed = true;
|
|
const offset2 = byteOffset(false, i * 16 + 16) / 4;
|
|
const allo2 = simdle.allo(this.handle.subarray(offset2, offset2 + 4));
|
|
set(this.handle, bitOffset(false, i), allo2);
|
|
}
|
|
if (set(this.handle, bitOffset(true, 128 + j), allo)) {
|
|
changed = true;
|
|
const offset2 = byteOffset(true, i * 16 + 16) / 4;
|
|
const allo2 = simdle.allo(this.handle.subarray(offset2, offset2 + 4));
|
|
set(this.handle, bitOffset(true, i), allo2);
|
|
}
|
|
return changed;
|
|
}
|
|
};
|
|
function selectChunk(chunks, offset) {
|
|
for (let i = 0; i < chunks.length; i++) {
|
|
const next = chunks[i];
|
|
const start = next.offset;
|
|
const end = next.offset + next.field.byteLength;
|
|
if (offset >= start && offset + 16 <= end) {
|
|
return next;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
var SparseIndex = class extends Index {
|
|
constructor(chunks, byteLength) {
|
|
super(byteLength);
|
|
this.chunks = chunks;
|
|
for (let i = 0; i < 128; i++) {
|
|
for (let j = 0; j < 128; j++) {
|
|
const offset = (i * 128 + j) * 16;
|
|
let allz = true;
|
|
let allo = false;
|
|
const chunk = selectChunk(this.chunks, offset);
|
|
if (chunk !== null) {
|
|
const m = chunk.field.BYTES_PER_ELEMENT;
|
|
const vec = chunk.field.subarray((offset - chunk.offset) / m, (offset - chunk.offset + 16) / m);
|
|
allz = simdle.allz(vec);
|
|
allo = simdle.allo(vec);
|
|
}
|
|
const k = i * 128 + 128 + j;
|
|
set(this.handle, bitOffset(false, k), allz);
|
|
set(this.handle, bitOffset(true, k), allo);
|
|
}
|
|
{
|
|
const offset = byteOffset(false, i * 16 + 16) / 4;
|
|
const allo = simdle.allo(this.handle.subarray(offset, offset + 4));
|
|
set(this.handle, bitOffset(false, i), allo);
|
|
}
|
|
{
|
|
const offset = byteOffset(true, i * 16 + 16) / 4;
|
|
const allo = simdle.allo(this.handle.subarray(offset, offset + 4));
|
|
set(this.handle, bitOffset(true, i), allo);
|
|
}
|
|
}
|
|
}
|
|
get byteLength() {
|
|
if (this._byteLength !== -1) return this._byteLength;
|
|
const last = this.chunks[this.chunks.length - 1];
|
|
return last ? last.offset + last.field.byteLength : 0;
|
|
}
|
|
update(bit) {
|
|
const n = this.byteLength * 8;
|
|
if (bit < 0) bit += n;
|
|
if (bit < 0 || bit >= n) return false;
|
|
const i = Math.floor(bit / 16384);
|
|
const j = Math.floor(bit / 128);
|
|
const offset = j * 16;
|
|
const chunk = selectChunk(this.chunks, offset);
|
|
if (chunk === null) return false;
|
|
const m = chunk.field.BYTES_PER_ELEMENT;
|
|
const vec = chunk.field.subarray((offset - chunk.offset) / m, (offset - chunk.offset + 16) / m);
|
|
const allz = simdle.allz(vec);
|
|
const allo = simdle.allo(vec);
|
|
let changed = false;
|
|
if (set(this.handle, bitOffset(false, 128 + j), allz)) {
|
|
changed = true;
|
|
const offset2 = byteOffset(false, i * 16 + 16) / 4;
|
|
const allo2 = simdle.allo(this.handle.subarray(offset2, offset2 + 4));
|
|
set(this.handle, bitOffset(false, i), allo2);
|
|
}
|
|
if (set(this.handle, bitOffset(true, 128 + j), allo)) {
|
|
changed = true;
|
|
const offset2 = byteOffset(true, i * 16 + 16) / 4;
|
|
const allo2 = simdle.allo(this.handle.subarray(offset2, offset2 + 4));
|
|
set(this.handle, bitOffset(true, i), allo2);
|
|
}
|
|
return changed;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/quickbit-native/binding.js
|
|
var require_binding5 = __commonJS({
|
|
"../../node_modules/quickbit-native/binding.js"(exports, module) {
|
|
__require.addon = require_node2();
|
|
module.exports = __require.addon(".", __filename);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/quickbit-native/index.js
|
|
var require_quickbit_native = __commonJS({
|
|
"../../node_modules/quickbit-native/index.js"(exports) {
|
|
var binding = require_binding5();
|
|
exports.get = function get(field, bit) {
|
|
const n = field.byteLength * 8;
|
|
if (bit < 0) bit += n;
|
|
if (bit < 0 || bit >= n) return false;
|
|
return binding.quickbit_napi_get(toBuffer(field), bit) !== 0;
|
|
};
|
|
exports.set = function set(field, bit, value = true) {
|
|
const n = field.byteLength * 8;
|
|
if (bit < 0) bit += n;
|
|
if (bit < 0 || bit >= n) return false;
|
|
return binding.quickbit_napi_set(toBuffer(field), bit, value ? 1 : 0) !== 0;
|
|
};
|
|
exports.fill = function fill(field, value, start = 0, end = field.byteLength * 8) {
|
|
const n = field.byteLength * 8;
|
|
if (start < 0) start += n;
|
|
if (end < 0) end += n;
|
|
if (start < 0 || start >= field.byteLength * 8 || start >= end) return field;
|
|
binding.quickbit_napi_fill(toBuffer(field), value ? 1 : 0, start, end);
|
|
return field;
|
|
};
|
|
exports.clear = function clear(field, ...chunks) {
|
|
binding.quickbit_napi_clear(toBuffer(field), chunks.map(toBufferChunk));
|
|
};
|
|
exports.findFirst = function findFirst(field, value, position = 0) {
|
|
const n = field.byteLength * 8;
|
|
if (position < 0) position += n;
|
|
if (position < 0) position = 0;
|
|
if (position >= n) return -1;
|
|
return binding.quickbit_napi_find_first(
|
|
toBuffer(field),
|
|
value ? 1 : 0,
|
|
position
|
|
);
|
|
};
|
|
exports.findLast = function findLast(field, value, position = field.byteLength * 8 - 1) {
|
|
const n = field.byteLength * 8;
|
|
if (position < 0) position += n;
|
|
if (position < 0) return -1;
|
|
if (position >= n) position = n - 1;
|
|
return binding.quickbit_napi_find_last(
|
|
toBuffer(field),
|
|
value ? 1 : 0,
|
|
position
|
|
);
|
|
};
|
|
function toBuffer(field) {
|
|
if (field.BYTES_PER_ELEMENT === 1) return field;
|
|
return new Uint8Array(field.buffer, field.byteOffset, field.byteLength);
|
|
}
|
|
function toBufferChunk(chunk) {
|
|
return { field: toBuffer(chunk.field), offset: chunk.offset };
|
|
}
|
|
var Index = class {
|
|
static from(fieldOrChunks, byteLength = -1) {
|
|
if (Array.isArray(fieldOrChunks)) {
|
|
return new SparseIndex(fieldOrChunks, byteLength);
|
|
} else {
|
|
return new DenseIndex(fieldOrChunks, byteLength);
|
|
}
|
|
}
|
|
constructor(byteLength) {
|
|
this._byteLength = byteLength;
|
|
this.handle = Buffer.allocUnsafe(binding.sizeof_quickbit_index_t);
|
|
}
|
|
get byteLength() {
|
|
return this._byteLength;
|
|
}
|
|
skipFirst(value, position = 0) {
|
|
const n = this.byteLength * 8;
|
|
if (position < 0) position += n;
|
|
if (position < 0) position = 0;
|
|
if (position >= n) return n - 1;
|
|
return binding.quickbit_napi_skip_first(
|
|
this.handle,
|
|
this.byteLength,
|
|
value ? 1 : 0,
|
|
position
|
|
);
|
|
}
|
|
skipLast(value, position = this.byteLength * 8 - 1) {
|
|
const n = this.byteLength * 8;
|
|
if (position < 0) position += n;
|
|
if (position < 0) return 0;
|
|
if (position >= n) position = n - 1;
|
|
return binding.quickbit_napi_skip_last(
|
|
this.handle,
|
|
this.byteLength,
|
|
value ? 1 : 0,
|
|
position
|
|
);
|
|
}
|
|
};
|
|
exports.Index = Index;
|
|
var DenseIndex = class extends Index {
|
|
constructor(field, byteLength) {
|
|
super(byteLength);
|
|
this.field = field;
|
|
binding.quickbit_napi_index_init(this.handle, toBuffer(this.field));
|
|
}
|
|
get byteLength() {
|
|
if (this._byteLength !== -1) return this._byteLength;
|
|
return this.field.byteLength;
|
|
}
|
|
update(bit) {
|
|
const n = this.byteLength * 8;
|
|
if (bit < 0) bit += n;
|
|
if (bit < 0 || bit >= n) return false;
|
|
return binding.quickbit_napi_index_update(
|
|
this.handle,
|
|
toBuffer(this.field),
|
|
bit
|
|
) !== 0;
|
|
}
|
|
};
|
|
function selectChunk(chunks, offset) {
|
|
for (let i = 0; i < chunks.length; i++) {
|
|
const next = chunks[i];
|
|
const start = next.offset;
|
|
const end = next.offset + next.field.byteLength;
|
|
if (offset >= start && offset + 16 <= end) {
|
|
return next;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
var SparseIndex = class extends Index {
|
|
constructor(chunks, byteLength) {
|
|
super(byteLength);
|
|
this.chunks = chunks;
|
|
binding.quickbit_napi_index_init_sparse(
|
|
this.handle,
|
|
this.chunks.map(toBufferChunk)
|
|
);
|
|
}
|
|
get byteLength() {
|
|
if (this._byteLength !== -1) return this._byteLength;
|
|
const last = this.chunks[this.chunks.length - 1];
|
|
return last ? last.offset + last.field.byteLength : 0;
|
|
}
|
|
update(bit) {
|
|
const n = this.byteLength * 8;
|
|
if (bit < 0) bit += n;
|
|
if (bit < 0 || bit >= n) return false;
|
|
const j = Math.floor(bit / 128);
|
|
const offset = j * 16;
|
|
const chunk = selectChunk(this.chunks, offset);
|
|
if (chunk === null) return false;
|
|
return binding.quickbit_napi_index_update_sparse(
|
|
this.handle,
|
|
toBuffer(chunk.field),
|
|
chunk.offset,
|
|
bit
|
|
) !== 0;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/quickbit-universal/index.js
|
|
var require_quickbit_universal = __commonJS({
|
|
"../../node_modules/quickbit-universal/index.js"(exports, module) {
|
|
var fallback = require_fallback2();
|
|
try {
|
|
const native = require_quickbit_native();
|
|
exports.get = fallback.get;
|
|
exports.set = fallback.set;
|
|
exports.fill = fallback.fill;
|
|
exports.clear = native.clear;
|
|
exports.findFirst = native.findFirst;
|
|
exports.findLast = native.findLast;
|
|
exports.Index = native.Index;
|
|
} catch {
|
|
module.exports = fallback;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/compat.js
|
|
var require_compat = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/compat.js"(exports) {
|
|
var quickbit = require_quickbit_universal();
|
|
if (typeof quickbit.findFirst !== "function" || typeof quickbit.findLast !== "function" || typeof quickbit.clear !== "function") {
|
|
quickbit = require_fallback2();
|
|
}
|
|
exports.quickbit = quickbit;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/remote-bitfield.js
|
|
var require_remote_bitfield = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/remote-bitfield.js"(exports, module) {
|
|
var BigSparseArray = require_big_sparse_array();
|
|
var quickbit = require_compat().quickbit;
|
|
var BITS_PER_PAGE = 32768;
|
|
var BYTES_PER_PAGE = BITS_PER_PAGE / 8;
|
|
var WORDS_PER_PAGE = BYTES_PER_PAGE / 4;
|
|
var BITS_PER_SEGMENT = 2097152;
|
|
var BYTES_PER_SEGMENT = BITS_PER_SEGMENT / 8;
|
|
var PAGES_PER_SEGMENT = BITS_PER_SEGMENT / BITS_PER_PAGE;
|
|
var RemoteBitfieldPage = class {
|
|
constructor(index, bitfield, segment) {
|
|
this.index = index;
|
|
this.offset = index * BYTES_PER_PAGE - segment.offset;
|
|
this.bitfield = bitfield;
|
|
this.segment = segment;
|
|
segment.add(this);
|
|
}
|
|
get tree() {
|
|
return this.segment.tree;
|
|
}
|
|
get(index) {
|
|
return quickbit.get(this.bitfield, index);
|
|
}
|
|
set(index, val) {
|
|
if (quickbit.set(this.bitfield, index, val)) {
|
|
this.tree.update(this.offset * 8 + index);
|
|
}
|
|
}
|
|
setRange(start, length, val) {
|
|
quickbit.fill(this.bitfield, val, start, start + length);
|
|
let i = Math.floor(start / 128);
|
|
const n = i + Math.ceil(length / 128);
|
|
while (i <= n) this.tree.update(this.offset * 8 + i++ * 128);
|
|
}
|
|
findFirst(val, position) {
|
|
return quickbit.findFirst(this.bitfield, val, position);
|
|
}
|
|
findLast(val, position) {
|
|
return quickbit.findLast(this.bitfield, val, position);
|
|
}
|
|
insert(start, bitfield) {
|
|
this.bitfield.set(bitfield, start / 32);
|
|
this.segment.refresh();
|
|
}
|
|
clear(start, bitfield) {
|
|
quickbit.clear(this.bitfield, { field: bitfield, offset: start });
|
|
}
|
|
};
|
|
var RemoteBitfieldSegment = class {
|
|
constructor(index) {
|
|
this.index = index;
|
|
this.offset = index * BYTES_PER_SEGMENT;
|
|
this.tree = quickbit.Index.from([], BYTES_PER_SEGMENT);
|
|
this.pages = new Array(PAGES_PER_SEGMENT);
|
|
this.pagesLength = 0;
|
|
}
|
|
get chunks() {
|
|
return this.tree.chunks;
|
|
}
|
|
refresh() {
|
|
this.tree = quickbit.Index.from(this.tree.chunks, BYTES_PER_SEGMENT);
|
|
}
|
|
add(page) {
|
|
const pageIndex = page.index - this.index * PAGES_PER_SEGMENT;
|
|
if (pageIndex >= this.pagesLength) this.pagesLength = pageIndex + 1;
|
|
this.pages[pageIndex] = page;
|
|
const chunk = { field: page.bitfield, offset: page.offset };
|
|
this.chunks.push(chunk);
|
|
for (let i = this.chunks.length - 2; i >= 0; i--) {
|
|
const prev = this.chunks[i];
|
|
if (prev.offset <= chunk.offset) break;
|
|
this.chunks[i] = chunk;
|
|
this.chunks[i + 1] = prev;
|
|
}
|
|
}
|
|
findFirst(val, position) {
|
|
position = this.tree.skipFirst(!val, position);
|
|
let j = position & BITS_PER_PAGE - 1;
|
|
let i = (position - j) / BITS_PER_PAGE;
|
|
if (i >= PAGES_PER_SEGMENT) return -1;
|
|
while (i < this.pagesLength) {
|
|
const p = this.pages[i];
|
|
let index = -1;
|
|
if (p) index = p.findFirst(val, j);
|
|
else if (!val) index = j;
|
|
if (index !== -1) return i * BITS_PER_PAGE + index;
|
|
j = 0;
|
|
i++;
|
|
}
|
|
return val || this.pagesLength === PAGES_PER_SEGMENT ? -1 : this.pagesLength * BITS_PER_PAGE;
|
|
}
|
|
findLast(val, position) {
|
|
position = this.tree.skipLast(!val, position);
|
|
let j = position & BITS_PER_PAGE - 1;
|
|
let i = (position - j) / BITS_PER_PAGE;
|
|
if (i >= PAGES_PER_SEGMENT) return -1;
|
|
while (i >= 0) {
|
|
const p = this.pages[i];
|
|
let index = -1;
|
|
if (p) index = p.findLast(val, j);
|
|
else if (!val) index = j;
|
|
if (index !== -1) return i * BITS_PER_PAGE + index;
|
|
j = BITS_PER_PAGE - 1;
|
|
i--;
|
|
}
|
|
return -1;
|
|
}
|
|
};
|
|
module.exports = class RemoteBitfield {
|
|
static BITS_PER_PAGE = BITS_PER_PAGE;
|
|
constructor() {
|
|
this._pages = new BigSparseArray();
|
|
this._segments = new BigSparseArray();
|
|
this._maxSegments = 0;
|
|
}
|
|
getBitfield(index) {
|
|
const j = index & BITS_PER_PAGE - 1;
|
|
const i = (index - j) / BITS_PER_PAGE;
|
|
const p = this._pages.get(i);
|
|
return p || null;
|
|
}
|
|
get(index) {
|
|
const j = index & BITS_PER_PAGE - 1;
|
|
const i = (index - j) / BITS_PER_PAGE;
|
|
const p = this._pages.get(i);
|
|
return p ? p.get(j) : false;
|
|
}
|
|
set(index, val) {
|
|
const j = index & BITS_PER_PAGE - 1;
|
|
const i = (index - j) / BITS_PER_PAGE;
|
|
let p = this._pages.get(i);
|
|
if (!p && val) {
|
|
const k = Math.floor(i / PAGES_PER_SEGMENT);
|
|
const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k));
|
|
if (this._maxSegments <= k) this._maxSegments = k + 1;
|
|
p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s));
|
|
}
|
|
if (p) p.set(j, val);
|
|
}
|
|
setRange(start, length, val) {
|
|
let j = start & BITS_PER_PAGE - 1;
|
|
let i = (start - j) / BITS_PER_PAGE;
|
|
while (length > 0) {
|
|
let p = this._pages.get(i);
|
|
if (!p && val) {
|
|
const k = Math.floor(i / PAGES_PER_SEGMENT);
|
|
const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k));
|
|
if (this._maxSegments <= k) this._maxSegments = k + 1;
|
|
p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s));
|
|
}
|
|
const end = Math.min(j + length, BITS_PER_PAGE);
|
|
const range = end - j;
|
|
if (p) p.setRange(j, range, val);
|
|
j = 0;
|
|
i++;
|
|
length -= range;
|
|
}
|
|
}
|
|
findFirst(val, position) {
|
|
let j = position & BITS_PER_SEGMENT - 1;
|
|
let i = (position - j) / BITS_PER_SEGMENT;
|
|
while (i < this._maxSegments) {
|
|
const s = this._segments.get(i);
|
|
let index = -1;
|
|
if (s) index = s.findFirst(val, j);
|
|
else if (!val) index = j;
|
|
if (index !== -1) return i * BITS_PER_SEGMENT + index;
|
|
j = 0;
|
|
i++;
|
|
}
|
|
return val ? -1 : Math.max(position, this._maxSegments * BITS_PER_SEGMENT);
|
|
}
|
|
firstSet(position) {
|
|
return this.findFirst(true, position);
|
|
}
|
|
firstUnset(position) {
|
|
return this.findFirst(false, position);
|
|
}
|
|
findLast(val, position) {
|
|
let j = position & BITS_PER_SEGMENT - 1;
|
|
let i = (position - j) / BITS_PER_SEGMENT;
|
|
while (i >= 0) {
|
|
const s = this._segments.get(i);
|
|
let index = -1;
|
|
if (s) index = s.findLast(val, j);
|
|
else if (!val) index = j;
|
|
if (index !== -1) return i * BITS_PER_SEGMENT + index;
|
|
j = BITS_PER_SEGMENT - 1;
|
|
i--;
|
|
}
|
|
return -1;
|
|
}
|
|
lastSet(position) {
|
|
return this.findLast(true, position);
|
|
}
|
|
lastUnset(position) {
|
|
return this.findLast(false, position);
|
|
}
|
|
insert(start, bitfield) {
|
|
if (start % 32 !== 0) return false;
|
|
let length = bitfield.byteLength * 8;
|
|
let j = start & BITS_PER_PAGE - 1;
|
|
let i = (start - j) / BITS_PER_PAGE;
|
|
while (length > 0) {
|
|
let p = this._pages.get(i);
|
|
if (!p) {
|
|
const k = Math.floor(i / PAGES_PER_SEGMENT);
|
|
const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k));
|
|
if (this._maxSegments <= k) this._maxSegments = k + 1;
|
|
p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s));
|
|
}
|
|
const end = Math.min(j + length, BITS_PER_PAGE);
|
|
const range = end - j;
|
|
p.insert(j, bitfield.subarray(0, range / 32));
|
|
bitfield = bitfield.subarray(range / 32);
|
|
j = 0;
|
|
i++;
|
|
length -= range;
|
|
}
|
|
return true;
|
|
}
|
|
clear(start, bitfield) {
|
|
if (start % 32 !== 0) return false;
|
|
let length = bitfield.byteLength * 8;
|
|
let j = start & BITS_PER_PAGE - 1;
|
|
let i = (start - j) / BITS_PER_PAGE;
|
|
while (length > 0) {
|
|
let p = this._pages.get(i);
|
|
if (!p) {
|
|
const k = Math.floor(i / PAGES_PER_SEGMENT);
|
|
const s = this._segments.get(k) || this._segments.set(k, new RemoteBitfieldSegment(k));
|
|
if (this._maxSegments <= k) this._maxSegments = k + 1;
|
|
p = this._pages.set(i, new RemoteBitfieldPage(i, new Uint32Array(WORDS_PER_PAGE), s));
|
|
}
|
|
const end = Math.min(j + length, BITS_PER_PAGE);
|
|
const range = end - j;
|
|
p.clear(j, bitfield.subarray(0, range / 32));
|
|
bitfield = bitfield.subarray(range / 32);
|
|
j = 0;
|
|
i++;
|
|
length -= range;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/sodium-native/index.js
|
|
var require_sodium_native2 = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/sodium-native/index.js"(exports, module) {
|
|
__require.addon = require_node2();
|
|
module.exports = __require.addon(".", __filename);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/sodium-universal/index.js
|
|
var require_sodium_universal2 = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/sodium-universal/index.js"(exports, module) {
|
|
module.exports = require_sodium_native2();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/caps.js
|
|
var require_caps = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/caps.js"(exports) {
|
|
var crypto = require_hypercore_crypto();
|
|
var sodium = require_sodium_universal2();
|
|
var b4a = require_b4a();
|
|
var c = require_compact_encoding();
|
|
var [
|
|
TREE,
|
|
REPLICATE_INITIATOR,
|
|
REPLICATE_RESPONDER,
|
|
MANIFEST,
|
|
DEFAULT_NAMESPACE,
|
|
BLOCK_ENCRYPTION
|
|
] = crypto.namespace("hypercore", 6);
|
|
exports.MANIFEST = MANIFEST;
|
|
exports.DEFAULT_NAMESPACE = DEFAULT_NAMESPACE;
|
|
exports.BLOCK_ENCRYPTION = BLOCK_ENCRYPTION;
|
|
exports.replicate = function(isInitiator, key, handshakeHash) {
|
|
const out = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash_batch(out, [isInitiator ? REPLICATE_INITIATOR : REPLICATE_RESPONDER, key], handshakeHash);
|
|
return out;
|
|
};
|
|
exports.treeSignable = function(manifestHash, treeHash, length, fork) {
|
|
const state = { start: 0, end: 112, buffer: b4a.allocUnsafe(112) };
|
|
c.fixed32.encode(state, TREE);
|
|
c.fixed32.encode(state, manifestHash);
|
|
c.fixed32.encode(state, treeHash);
|
|
c.uint64.encode(state, length);
|
|
c.uint64.encode(state, fork);
|
|
return state.buffer;
|
|
};
|
|
exports.treeSignableCompat = function(hash, length, fork, noHeader) {
|
|
const end = noHeader ? 48 : 80;
|
|
const state = { start: 0, end, buffer: b4a.allocUnsafe(end) };
|
|
if (!noHeader) c.fixed32.encode(state, TREE);
|
|
c.fixed32.encode(state, hash);
|
|
c.uint64.encode(state, length);
|
|
c.uint64.encode(state, fork);
|
|
return state.buffer;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/messages.js
|
|
var require_messages2 = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/messages.js"(exports) {
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var { DEFAULT_NAMESPACE } = require_caps();
|
|
var { INVALID_OPLOG_VERSION } = require_hypercore_errors();
|
|
var unslab = require_unslab();
|
|
var EMPTY = b4a.alloc(0);
|
|
var hashes = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
},
|
|
encode(state, m) {
|
|
if (m === "blake2b") {
|
|
c.uint.encode(state, 0);
|
|
return;
|
|
}
|
|
throw new Error("Unknown hash: " + m);
|
|
},
|
|
decode(state) {
|
|
const n = c.uint.decode(state);
|
|
if (n === 0) return "blake2b";
|
|
throw new Error("Unknown hash id: " + n);
|
|
}
|
|
};
|
|
var signatures = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
},
|
|
encode(state, m) {
|
|
if (m === "ed25519") {
|
|
c.uint.encode(state, 0);
|
|
return;
|
|
}
|
|
throw new Error("Unknown signature: " + m);
|
|
},
|
|
decode(state) {
|
|
const n = c.uint.decode(state);
|
|
if (n === 0) return "ed25519";
|
|
throw new Error("Unknown signature id: " + n);
|
|
}
|
|
};
|
|
var signer = {
|
|
preencode(state, m) {
|
|
signatures.preencode(state, m.signature);
|
|
c.fixed32.preencode(state, m.namespace);
|
|
c.fixed32.preencode(state, m.publicKey);
|
|
},
|
|
encode(state, m) {
|
|
signatures.encode(state, m.signature);
|
|
c.fixed32.encode(state, m.namespace);
|
|
c.fixed32.encode(state, m.publicKey);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
signature: signatures.decode(state),
|
|
namespace: c.fixed32.decode(state),
|
|
publicKey: c.fixed32.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var signerArray = c.array(signer);
|
|
var prologue = {
|
|
preencode(state, p) {
|
|
c.fixed32.preencode(state, p.hash);
|
|
c.uint.preencode(state, p.length);
|
|
},
|
|
encode(state, p) {
|
|
c.fixed32.encode(state, p.hash);
|
|
c.uint.encode(state, p.length);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
hash: c.fixed32.decode(state),
|
|
length: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var manifestv0 = {
|
|
preencode(state, m) {
|
|
hashes.preencode(state, m.hash);
|
|
state.end++;
|
|
if (m.prologue && m.signers.length === 0) {
|
|
c.fixed32.preencode(state, m.prologue.hash);
|
|
return;
|
|
}
|
|
if (m.quorum === 1 && m.signers.length === 1 && !m.allowPatch) {
|
|
signer.preencode(state, m.signers[0]);
|
|
} else {
|
|
state.end++;
|
|
c.uint.preencode(state, m.quorum);
|
|
signerArray.preencode(state, m.signers);
|
|
}
|
|
},
|
|
encode(state, m) {
|
|
hashes.encode(state, m.hash);
|
|
if (m.prologue && m.signers.length === 0) {
|
|
c.uint.encode(state, 0);
|
|
c.fixed32.encode(state, m.prologue.hash);
|
|
return;
|
|
}
|
|
if (m.quorum === 1 && m.signers.length === 1 && !m.allowPatch) {
|
|
c.uint.encode(state, 1);
|
|
signer.encode(state, m.signers[0]);
|
|
} else {
|
|
c.uint.encode(state, 2);
|
|
c.uint.encode(state, m.allowPatch ? 1 : 0);
|
|
c.uint.encode(state, m.quorum);
|
|
signerArray.encode(state, m.signers);
|
|
}
|
|
},
|
|
decode(state) {
|
|
const hash = hashes.decode(state);
|
|
const type = c.uint.decode(state);
|
|
if (type > 2) throw new Error("Unknown type: " + type);
|
|
if (type === 0) {
|
|
return {
|
|
version: 0,
|
|
hash,
|
|
allowPatch: false,
|
|
quorum: 0,
|
|
signers: [],
|
|
prologue: {
|
|
hash: c.fixed32.decode(state),
|
|
length: 0
|
|
}
|
|
};
|
|
}
|
|
if (type === 1) {
|
|
return {
|
|
version: 0,
|
|
hash,
|
|
allowPatch: false,
|
|
quorum: 1,
|
|
signers: [signer.decode(state)],
|
|
prologue: null
|
|
};
|
|
}
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
version: 0,
|
|
hash,
|
|
allowPatch: (flags & 1) !== 0,
|
|
quorum: c.uint.decode(state),
|
|
signers: signerArray.decode(state),
|
|
prologue: null
|
|
};
|
|
}
|
|
};
|
|
var manifest = exports.manifest = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
if (m.version === 0) return manifestv0.preencode(state, m);
|
|
state.end++;
|
|
hashes.preencode(state, m.hash);
|
|
c.uint.preencode(state, m.quorum);
|
|
signerArray.preencode(state, m.signers);
|
|
if (m.prologue) prologue.preencode(state, m.prologue);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.version);
|
|
if (m.version === 0) return manifestv0.encode(state, m);
|
|
c.uint.encode(state, (m.allowPatch ? 1 : 0) | (m.prologue ? 2 : 0));
|
|
hashes.encode(state, m.hash);
|
|
c.uint.encode(state, m.quorum);
|
|
signerArray.encode(state, m.signers);
|
|
if (m.prologue) prologue.encode(state, m.prologue);
|
|
},
|
|
decode(state) {
|
|
const v = c.uint.decode(state);
|
|
if (v === 0) return manifestv0.decode(state);
|
|
if (v !== 1) throw new Error("Unknown version: " + v);
|
|
const flags = c.uint.decode(state);
|
|
const hash = hashes.decode(state);
|
|
const quorum = c.uint.decode(state);
|
|
const signers = signerArray.decode(state);
|
|
return {
|
|
version: 1,
|
|
hash,
|
|
allowPatch: (flags & 1) !== 0,
|
|
quorum,
|
|
signers,
|
|
prologue: (flags & 2) === 0 ? null : prologue.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var node = {
|
|
preencode(state, n) {
|
|
c.uint.preencode(state, n.index);
|
|
c.uint.preencode(state, n.size);
|
|
c.fixed32.preencode(state, n.hash);
|
|
},
|
|
encode(state, n) {
|
|
c.uint.encode(state, n.index);
|
|
c.uint.encode(state, n.size);
|
|
c.fixed32.encode(state, n.hash);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
index: c.uint.decode(state),
|
|
size: c.uint.decode(state),
|
|
hash: c.fixed32.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var nodeArray = c.array(node);
|
|
var wire = exports.wire = {};
|
|
wire.handshake = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, 1);
|
|
c.fixed32.preencode(state, m.capability);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.seeks ? 1 : 0);
|
|
c.fixed32.encode(state, m.capability);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
seeks: (flags & 1) !== 0,
|
|
capability: unslab(c.fixed32.decode(state))
|
|
};
|
|
}
|
|
};
|
|
var requestBlock = {
|
|
preencode(state, b) {
|
|
c.uint.preencode(state, b.index);
|
|
c.uint.preencode(state, b.nodes);
|
|
},
|
|
encode(state, b) {
|
|
c.uint.encode(state, b.index);
|
|
c.uint.encode(state, b.nodes);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
index: c.uint.decode(state),
|
|
nodes: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var requestSeek = {
|
|
preencode(state, s) {
|
|
c.uint.preencode(state, s.bytes);
|
|
c.uint.preencode(state, s.padding);
|
|
},
|
|
encode(state, s) {
|
|
c.uint.encode(state, s.bytes);
|
|
c.uint.encode(state, s.padding);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
bytes: c.uint.decode(state),
|
|
padding: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var requestUpgrade = {
|
|
preencode(state, u) {
|
|
c.uint.preencode(state, u.start);
|
|
c.uint.preencode(state, u.length);
|
|
},
|
|
encode(state, u) {
|
|
c.uint.encode(state, u.start);
|
|
c.uint.encode(state, u.length);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
start: c.uint.decode(state),
|
|
length: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
wire.request = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
c.uint.preencode(state, m.id);
|
|
c.uint.preencode(state, m.fork);
|
|
if (m.block) requestBlock.preencode(state, m.block);
|
|
if (m.hash) requestBlock.preencode(state, m.hash);
|
|
if (m.seek) requestSeek.preencode(state, m.seek);
|
|
if (m.upgrade) requestUpgrade.preencode(state, m.upgrade);
|
|
if (m.priority) c.uint.preencode(state, m.priority);
|
|
},
|
|
encode(state, m) {
|
|
const flags = (m.block ? 1 : 0) | (m.hash ? 2 : 0) | (m.seek ? 4 : 0) | (m.upgrade ? 8 : 0) | (m.manifest ? 16 : 0) | (m.priority ? 32 : 0);
|
|
c.uint.encode(state, flags);
|
|
c.uint.encode(state, m.id);
|
|
c.uint.encode(state, m.fork);
|
|
if (m.block) requestBlock.encode(state, m.block);
|
|
if (m.hash) requestBlock.encode(state, m.hash);
|
|
if (m.seek) requestSeek.encode(state, m.seek);
|
|
if (m.upgrade) requestUpgrade.encode(state, m.upgrade);
|
|
if (m.priority) c.uint.encode(state, m.priority);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
id: c.uint.decode(state),
|
|
fork: c.uint.decode(state),
|
|
block: flags & 1 ? requestBlock.decode(state) : null,
|
|
hash: flags & 2 ? requestBlock.decode(state) : null,
|
|
seek: flags & 4 ? requestSeek.decode(state) : null,
|
|
upgrade: flags & 8 ? requestUpgrade.decode(state) : null,
|
|
manifest: (flags & 16) !== 0,
|
|
priority: flags & 32 ? c.uint.decode(state) : 0
|
|
};
|
|
}
|
|
};
|
|
wire.cancel = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.request);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.request);
|
|
},
|
|
decode(state, m) {
|
|
return {
|
|
request: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var dataUpgrade = {
|
|
preencode(state, u) {
|
|
c.uint.preencode(state, u.start);
|
|
c.uint.preencode(state, u.length);
|
|
nodeArray.preencode(state, u.nodes);
|
|
nodeArray.preencode(state, u.additionalNodes);
|
|
c.buffer.preencode(state, u.signature);
|
|
},
|
|
encode(state, u) {
|
|
c.uint.encode(state, u.start);
|
|
c.uint.encode(state, u.length);
|
|
nodeArray.encode(state, u.nodes);
|
|
nodeArray.encode(state, u.additionalNodes);
|
|
c.buffer.encode(state, u.signature);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
start: c.uint.decode(state),
|
|
length: c.uint.decode(state),
|
|
nodes: nodeArray.decode(state),
|
|
additionalNodes: nodeArray.decode(state),
|
|
signature: c.buffer.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var dataSeek = {
|
|
preencode(state, s) {
|
|
c.uint.preencode(state, s.bytes);
|
|
nodeArray.preencode(state, s.nodes);
|
|
},
|
|
encode(state, s) {
|
|
c.uint.encode(state, s.bytes);
|
|
nodeArray.encode(state, s.nodes);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
bytes: c.uint.decode(state),
|
|
nodes: nodeArray.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var dataBlock = {
|
|
preencode(state, b) {
|
|
c.uint.preencode(state, b.index);
|
|
c.buffer.preencode(state, b.value);
|
|
nodeArray.preencode(state, b.nodes);
|
|
},
|
|
encode(state, b) {
|
|
c.uint.encode(state, b.index);
|
|
c.buffer.encode(state, b.value);
|
|
nodeArray.encode(state, b.nodes);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
index: c.uint.decode(state),
|
|
value: c.buffer.decode(state) || EMPTY,
|
|
nodes: nodeArray.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var dataHash = {
|
|
preencode(state, b) {
|
|
c.uint.preencode(state, b.index);
|
|
nodeArray.preencode(state, b.nodes);
|
|
},
|
|
encode(state, b) {
|
|
c.uint.encode(state, b.index);
|
|
nodeArray.encode(state, b.nodes);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
index: c.uint.decode(state),
|
|
nodes: nodeArray.decode(state)
|
|
};
|
|
}
|
|
};
|
|
wire.data = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
c.uint.preencode(state, m.request);
|
|
c.uint.preencode(state, m.fork);
|
|
if (m.block) dataBlock.preencode(state, m.block);
|
|
if (m.hash) dataHash.preencode(state, m.hash);
|
|
if (m.seek) dataSeek.preencode(state, m.seek);
|
|
if (m.upgrade) dataUpgrade.preencode(state, m.upgrade);
|
|
if (m.manifest) manifest.preencode(state, m.manifest);
|
|
},
|
|
encode(state, m) {
|
|
const flags = (m.block ? 1 : 0) | (m.hash ? 2 : 0) | (m.seek ? 4 : 0) | (m.upgrade ? 8 : 0) | (m.manifest ? 16 : 0);
|
|
c.uint.encode(state, flags);
|
|
c.uint.encode(state, m.request);
|
|
c.uint.encode(state, m.fork);
|
|
if (m.block) dataBlock.encode(state, m.block);
|
|
if (m.hash) dataHash.encode(state, m.hash);
|
|
if (m.seek) dataSeek.encode(state, m.seek);
|
|
if (m.upgrade) dataUpgrade.encode(state, m.upgrade);
|
|
if (m.manifest) manifest.encode(state, m.manifest);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
request: c.uint.decode(state),
|
|
fork: c.uint.decode(state),
|
|
block: flags & 1 ? dataBlock.decode(state) : null,
|
|
hash: flags & 2 ? dataHash.decode(state) : null,
|
|
seek: flags & 4 ? dataSeek.decode(state) : null,
|
|
upgrade: flags & 8 ? dataUpgrade.decode(state) : null,
|
|
manifest: flags & 16 ? manifest.decode(state) : null
|
|
};
|
|
}
|
|
};
|
|
wire.noData = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.request);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.request);
|
|
},
|
|
decode(state, m) {
|
|
return {
|
|
request: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
wire.want = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.start);
|
|
c.uint.preencode(state, m.length);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.start);
|
|
c.uint.encode(state, m.length);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
start: c.uint.decode(state),
|
|
length: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
wire.unwant = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.start);
|
|
c.uint.preencode(state, m.length);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.start);
|
|
c.uint.encode(state, m.length);
|
|
},
|
|
decode(state, m) {
|
|
return {
|
|
start: c.uint.decode(state),
|
|
length: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
wire.range = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
c.uint.preencode(state, m.start);
|
|
if (m.length !== 1) c.uint.preencode(state, m.length);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, (m.drop ? 1 : 0) | (m.length === 1 ? 2 : 0));
|
|
c.uint.encode(state, m.start);
|
|
if (m.length !== 1) c.uint.encode(state, m.length);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
drop: (flags & 1) !== 0,
|
|
start: c.uint.decode(state),
|
|
length: (flags & 2) !== 0 ? 1 : c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
wire.bitfield = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.start);
|
|
c.uint32array.preencode(state, m.bitfield);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.start);
|
|
c.uint32array.encode(state, m.bitfield);
|
|
},
|
|
decode(state, m) {
|
|
return {
|
|
start: c.uint.decode(state),
|
|
bitfield: c.uint32array.decode(state)
|
|
};
|
|
}
|
|
};
|
|
wire.sync = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
c.uint.preencode(state, m.fork);
|
|
c.uint.preencode(state, m.length);
|
|
c.uint.preencode(state, m.remoteLength);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, (m.canUpgrade ? 1 : 0) | (m.uploading ? 2 : 0) | (m.downloading ? 4 : 0) | (m.hasManifest ? 8 : 0));
|
|
c.uint.encode(state, m.fork);
|
|
c.uint.encode(state, m.length);
|
|
c.uint.encode(state, m.remoteLength);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
fork: c.uint.decode(state),
|
|
length: c.uint.decode(state),
|
|
remoteLength: c.uint.decode(state),
|
|
canUpgrade: (flags & 1) !== 0,
|
|
uploading: (flags & 2) !== 0,
|
|
downloading: (flags & 4) !== 0,
|
|
hasManifest: (flags & 8) !== 0
|
|
};
|
|
}
|
|
};
|
|
wire.reorgHint = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.from);
|
|
c.uint.preencode(state, m.to);
|
|
c.uint.preencode(state, m.ancestors);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.from);
|
|
c.uint.encode(state, m.to);
|
|
c.uint.encode(state, m.ancestors);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
from: c.uint.encode(state),
|
|
to: c.uint.encode(state),
|
|
ancestors: c.uint.encode(state)
|
|
};
|
|
}
|
|
};
|
|
wire.extension = {
|
|
preencode(state, m) {
|
|
c.string.preencode(state, m.name);
|
|
c.raw.preencode(state, m.message);
|
|
},
|
|
encode(state, m) {
|
|
c.string.encode(state, m.name);
|
|
c.raw.encode(state, m.message);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
name: c.string.decode(state),
|
|
message: c.raw.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var keyValue = {
|
|
preencode(state, p) {
|
|
c.string.preencode(state, p.key);
|
|
c.buffer.preencode(state, p.value);
|
|
},
|
|
encode(state, p) {
|
|
c.string.encode(state, p.key);
|
|
c.buffer.encode(state, p.value);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
key: c.string.decode(state),
|
|
value: c.buffer.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var treeUpgrade = {
|
|
preencode(state, u) {
|
|
c.uint.preencode(state, u.fork);
|
|
c.uint.preencode(state, u.ancestors);
|
|
c.uint.preencode(state, u.length);
|
|
c.buffer.preencode(state, u.signature);
|
|
},
|
|
encode(state, u) {
|
|
c.uint.encode(state, u.fork);
|
|
c.uint.encode(state, u.ancestors);
|
|
c.uint.encode(state, u.length);
|
|
c.buffer.encode(state, u.signature);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
fork: c.uint.decode(state),
|
|
ancestors: c.uint.decode(state),
|
|
length: c.uint.decode(state),
|
|
signature: c.buffer.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var bitfieldUpdate = {
|
|
// NOTE: can maybe be folded into a HAVE later on with the most recent spec
|
|
preencode(state, b) {
|
|
state.end++;
|
|
c.uint.preencode(state, b.start);
|
|
c.uint.preencode(state, b.length);
|
|
},
|
|
encode(state, b) {
|
|
state.buffer[state.start++] = b.drop ? 1 : 0;
|
|
c.uint.encode(state, b.start);
|
|
c.uint.encode(state, b.length);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
drop: (flags & 1) !== 0,
|
|
start: c.uint.decode(state),
|
|
length: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var oplog = exports.oplog = {};
|
|
oplog.entry = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
if (m.userData) keyValue.preencode(state, m.userData);
|
|
if (m.treeNodes) nodeArray.preencode(state, m.treeNodes);
|
|
if (m.treeUpgrade) treeUpgrade.preencode(state, m.treeUpgrade);
|
|
if (m.bitfield) bitfieldUpdate.preencode(state, m.bitfield);
|
|
},
|
|
encode(state, m) {
|
|
const s = state.start++;
|
|
let flags = 0;
|
|
if (m.userData) {
|
|
flags |= 1;
|
|
keyValue.encode(state, m.userData);
|
|
}
|
|
if (m.treeNodes) {
|
|
flags |= 2;
|
|
nodeArray.encode(state, m.treeNodes);
|
|
}
|
|
if (m.treeUpgrade) {
|
|
flags |= 4;
|
|
treeUpgrade.encode(state, m.treeUpgrade);
|
|
}
|
|
if (m.bitfield) {
|
|
flags |= 8;
|
|
bitfieldUpdate.encode(state, m.bitfield);
|
|
}
|
|
state.buffer[s] = flags;
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
userData: (flags & 1) !== 0 ? keyValue.decode(state) : null,
|
|
treeNodes: (flags & 2) !== 0 ? nodeArray.decode(state) : null,
|
|
treeUpgrade: (flags & 4) !== 0 ? treeUpgrade.decode(state) : null,
|
|
bitfield: (flags & 8) !== 0 ? bitfieldUpdate.decode(state) : null
|
|
};
|
|
}
|
|
};
|
|
var keyPair = {
|
|
preencode(state, kp) {
|
|
c.buffer.preencode(state, kp.publicKey);
|
|
c.buffer.preencode(state, kp.secretKey);
|
|
},
|
|
encode(state, kp) {
|
|
c.buffer.encode(state, kp.publicKey);
|
|
c.buffer.encode(state, kp.secretKey);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
publicKey: c.buffer.decode(state),
|
|
secretKey: c.buffer.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var reorgHint = {
|
|
preencode(state, r) {
|
|
c.uint.preencode(state, r.from);
|
|
c.uint.preencode(state, r.to);
|
|
c.uint.preencode(state, r.ancestors);
|
|
},
|
|
encode(state, r) {
|
|
c.uint.encode(state, r.from);
|
|
c.uint.encode(state, r.to);
|
|
c.uint.encode(state, r.ancestors);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
from: c.uint.decode(state),
|
|
to: c.uint.decode(state),
|
|
ancestors: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var reorgHintArray = c.array(reorgHint);
|
|
var hints = {
|
|
preencode(state, h) {
|
|
reorgHintArray.preencode(state, h.reorgs);
|
|
c.uint.preencode(state, h.contiguousLength);
|
|
},
|
|
encode(state, h) {
|
|
reorgHintArray.encode(state, h.reorgs);
|
|
c.uint.encode(state, h.contiguousLength);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
reorgs: reorgHintArray.decode(state),
|
|
contiguousLength: state.start < state.end ? c.uint.decode(state) : 0
|
|
};
|
|
}
|
|
};
|
|
var treeHeader = {
|
|
preencode(state, t) {
|
|
c.uint.preencode(state, t.fork);
|
|
c.uint.preencode(state, t.length);
|
|
c.buffer.preencode(state, t.rootHash);
|
|
c.buffer.preencode(state, t.signature);
|
|
},
|
|
encode(state, t) {
|
|
c.uint.encode(state, t.fork);
|
|
c.uint.encode(state, t.length);
|
|
c.buffer.encode(state, t.rootHash);
|
|
c.buffer.encode(state, t.signature);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
fork: c.uint.decode(state),
|
|
length: c.uint.decode(state),
|
|
rootHash: c.buffer.decode(state),
|
|
signature: c.buffer.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var types = {
|
|
preencode(state, t) {
|
|
c.string.preencode(state, t.tree);
|
|
c.string.preencode(state, t.bitfield);
|
|
c.string.preencode(state, t.signer);
|
|
},
|
|
encode(state, t) {
|
|
c.string.encode(state, t.tree);
|
|
c.string.encode(state, t.bitfield);
|
|
c.string.encode(state, t.signer);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
tree: c.string.decode(state),
|
|
bitfield: c.string.decode(state),
|
|
signer: c.string.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var externalHeader = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.start);
|
|
c.uint.preencode(state, m.length);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.start);
|
|
c.uint.encode(state, m.length);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
start: c.uint.decode(state),
|
|
length: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var keyValueArray = c.array(keyValue);
|
|
oplog.header = {
|
|
preencode(state, h) {
|
|
state.end += 2;
|
|
if (h.external) {
|
|
externalHeader.preencode(state, h.external);
|
|
return;
|
|
}
|
|
c.fixed32.preencode(state, h.key);
|
|
if (h.manifest) manifest.preencode(state, h.manifest);
|
|
if (h.keyPair) keyPair.preencode(state, h.keyPair);
|
|
keyValueArray.preencode(state, h.userData);
|
|
treeHeader.preencode(state, h.tree);
|
|
hints.preencode(state, h.hints);
|
|
},
|
|
encode(state, h) {
|
|
c.uint.encode(state, 1);
|
|
if (h.external) {
|
|
c.uint.encode(state, 1);
|
|
externalHeader.encode(state, h.external);
|
|
return;
|
|
}
|
|
c.uint.encode(state, (h.manifest ? 2 : 0) | (h.keyPair ? 4 : 0));
|
|
c.fixed32.encode(state, h.key);
|
|
if (h.manifest) manifest.encode(state, h.manifest);
|
|
if (h.keyPair) keyPair.encode(state, h.keyPair);
|
|
keyValueArray.encode(state, h.userData);
|
|
treeHeader.encode(state, h.tree);
|
|
hints.encode(state, h.hints);
|
|
},
|
|
decode(state) {
|
|
const version = c.uint.decode(state);
|
|
if (version > 1) {
|
|
throw INVALID_OPLOG_VERSION("Invalid header version. Expected <= 1, got " + version);
|
|
}
|
|
if (version === 0) {
|
|
const old = {
|
|
types: types.decode(state),
|
|
userData: keyValueArray.decode(state),
|
|
tree: treeHeader.decode(state),
|
|
signer: keyPair.decode(state),
|
|
hints: hints.decode(state)
|
|
};
|
|
return {
|
|
external: null,
|
|
key: old.signer.publicKey,
|
|
manifest: {
|
|
version: 0,
|
|
hash: old.types.tree,
|
|
allowPatch: false,
|
|
quorum: 1,
|
|
signers: [{
|
|
signature: old.types.signer,
|
|
namespace: DEFAULT_NAMESPACE,
|
|
publicKey: old.signer.publicKey
|
|
}],
|
|
prologue: null
|
|
},
|
|
keyPair: old.signer.secretKey ? old.signer : null,
|
|
userData: old.userData,
|
|
tree: old.tree,
|
|
hints: old.hints
|
|
};
|
|
}
|
|
const flags = c.uint.decode(state);
|
|
if (flags & 1) {
|
|
return {
|
|
external: externalHeader.decode(state),
|
|
key: null,
|
|
manifest: null,
|
|
keyPair: null,
|
|
userData: null,
|
|
tree: null,
|
|
hints: null
|
|
};
|
|
}
|
|
return {
|
|
external: null,
|
|
key: c.fixed32.decode(state),
|
|
manifest: (flags & 2) !== 0 ? manifest.decode(state) : null,
|
|
keyPair: (flags & 4) !== 0 ? keyPair.decode(state) : null,
|
|
userData: keyValueArray.decode(state),
|
|
tree: treeHeader.decode(state),
|
|
hints: hints.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var uintArray = c.array(c.uint);
|
|
var multisigInput = {
|
|
preencode(state, inp) {
|
|
c.uint.preencode(state, inp.signer);
|
|
c.fixed64.preencode(state, inp.signature);
|
|
c.uint.preencode(state, inp.patch);
|
|
},
|
|
encode(state, inp) {
|
|
c.uint.encode(state, inp.signer);
|
|
c.fixed64.encode(state, inp.signature);
|
|
c.uint.encode(state, inp.patch);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
signer: c.uint.decode(state),
|
|
signature: c.fixed64.decode(state),
|
|
patch: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var patchEncodingv0 = {
|
|
preencode(state, n) {
|
|
c.uint.preencode(state, n.start);
|
|
c.uint.preencode(state, n.length);
|
|
uintArray.preencode(state, n.nodes);
|
|
},
|
|
encode(state, n) {
|
|
c.uint.encode(state, n.start);
|
|
c.uint.encode(state, n.length);
|
|
uintArray.encode(state, n.nodes);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
start: c.uint.decode(state),
|
|
length: c.uint.decode(state),
|
|
nodes: uintArray.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var multisigInputv0 = {
|
|
preencode(state, n) {
|
|
state.end++;
|
|
c.uint.preencode(state, n.signer);
|
|
c.fixed64.preencode(state, n.signature);
|
|
if (n.patch) patchEncodingv0.preencode(state, n.patch);
|
|
},
|
|
encode(state, n) {
|
|
c.uint.encode(state, n.patch ? 1 : 0);
|
|
c.uint.encode(state, n.signer);
|
|
c.fixed64.encode(state, n.signature);
|
|
if (n.patch) patchEncodingv0.encode(state, n.patch);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
signer: c.uint.decode(state),
|
|
signature: c.fixed64.decode(state),
|
|
patch: flags & 1 ? patchEncodingv0.decode(state) : null
|
|
};
|
|
}
|
|
};
|
|
var multisigInputArrayv0 = c.array(multisigInputv0);
|
|
var multisigInputArray = c.array(multisigInput);
|
|
var compactNode = {
|
|
preencode(state, n) {
|
|
c.uint.preencode(state, n.index);
|
|
c.uint.preencode(state, n.size);
|
|
c.fixed32.preencode(state, n.hash);
|
|
},
|
|
encode(state, n) {
|
|
c.uint.encode(state, n.index);
|
|
c.uint.encode(state, n.size);
|
|
c.fixed32.encode(state, n.hash);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
index: c.uint.decode(state),
|
|
size: c.uint.decode(state),
|
|
hash: c.fixed32.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var compactNodeArray = c.array(compactNode);
|
|
exports.multiSignaturev0 = {
|
|
preencode(state, s) {
|
|
multisigInputArrayv0.preencode(state, s.proofs);
|
|
compactNodeArray.preencode(state, s.patch);
|
|
},
|
|
encode(state, s) {
|
|
multisigInputArrayv0.encode(state, s.proofs);
|
|
compactNodeArray.encode(state, s.patch);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
proofs: multisigInputArrayv0.decode(state),
|
|
patch: compactNodeArray.decode(state)
|
|
};
|
|
}
|
|
};
|
|
exports.multiSignature = {
|
|
preencode(state, s) {
|
|
multisigInputArray.preencode(state, s.proofs);
|
|
compactNodeArray.preencode(state, s.patch);
|
|
},
|
|
encode(state, s) {
|
|
multisigInputArray.encode(state, s.proofs);
|
|
compactNodeArray.encode(state, s.patch);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
proofs: multisigInputArray.decode(state),
|
|
patch: compactNodeArray.decode(state)
|
|
};
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/replicator.js
|
|
var require_replicator = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/replicator.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var safetyCatch = require_safety_catch();
|
|
var RandomIterator = require_random_array_iterator();
|
|
var flatTree = require_flat_tree();
|
|
var ReceiverQueue = require_receiver_queue();
|
|
var HotswapQueue = require_hotswap_queue();
|
|
var RemoteBitfield = require_remote_bitfield();
|
|
var { REQUEST_CANCELLED, REQUEST_TIMEOUT, INVALID_CAPABILITY, SNAPSHOT_NOT_AVAILABLE } = require_hypercore_errors();
|
|
var m = require_messages2();
|
|
var caps = require_caps();
|
|
var DEFAULT_MAX_INFLIGHT = [16, 512];
|
|
var SCALE_LATENCY = 50;
|
|
var DEFAULT_SEGMENT_SIZE = 256 * 1024 * 8;
|
|
var NOT_DOWNLOADING_SLACK = 2e4 + Math.random() * 2e4 | 0;
|
|
var MAX_PEERS_UPGRADE = 3;
|
|
var MAX_RANGES = 64;
|
|
var PRIORITY = {
|
|
NORMAL: 0,
|
|
HIGH: 1,
|
|
VERY_HIGH: 2,
|
|
CANCELLED: 255
|
|
// reserved to mark cancellation
|
|
};
|
|
var Attachable = class {
|
|
constructor() {
|
|
this.resolved = false;
|
|
this.refs = [];
|
|
}
|
|
attach(session) {
|
|
const r = {
|
|
context: this,
|
|
session,
|
|
sindex: 0,
|
|
rindex: 0,
|
|
snapshot: true,
|
|
resolve: null,
|
|
reject: null,
|
|
promise: null,
|
|
timeout: null
|
|
};
|
|
r.sindex = session.push(r) - 1;
|
|
r.rindex = this.refs.push(r) - 1;
|
|
r.promise = new Promise((resolve, reject) => {
|
|
r.resolve = resolve;
|
|
r.reject = reject;
|
|
});
|
|
return r;
|
|
}
|
|
detach(r, err = null) {
|
|
if (r.context !== this) return false;
|
|
this._detach(r);
|
|
this._cancel(r, err);
|
|
this.gc();
|
|
return true;
|
|
}
|
|
_detach(r) {
|
|
const rh = this.refs.pop();
|
|
const sh = r.session.pop();
|
|
if (r.rindex < this.refs.length) this.refs[rh.rindex = r.rindex] = rh;
|
|
if (r.sindex < r.session.length) r.session[sh.sindex = r.sindex] = sh;
|
|
destroyRequestTimeout(r);
|
|
r.context = null;
|
|
return r;
|
|
}
|
|
gc() {
|
|
if (this.refs.length === 0) this._unref();
|
|
}
|
|
_cancel(r, err) {
|
|
r.reject(err || REQUEST_CANCELLED());
|
|
}
|
|
_unref() {
|
|
}
|
|
resolve(val) {
|
|
this.resolved = true;
|
|
while (this.refs.length > 0) {
|
|
this._detach(this.refs[this.refs.length - 1]).resolve(val);
|
|
}
|
|
}
|
|
reject(err) {
|
|
this.resolved = true;
|
|
while (this.refs.length > 0) {
|
|
this._detach(this.refs[this.refs.length - 1]).reject(err);
|
|
}
|
|
}
|
|
setTimeout(r, ms) {
|
|
destroyRequestTimeout(r);
|
|
r.timeout = setTimeout(onrequesttimeout, ms, r);
|
|
}
|
|
};
|
|
var BlockRequest = class extends Attachable {
|
|
constructor(tracker, index, priority) {
|
|
super();
|
|
this.index = index;
|
|
this.priority = priority;
|
|
this.inflight = [];
|
|
this.queued = false;
|
|
this.hotswap = null;
|
|
this.tracker = tracker;
|
|
}
|
|
_unref() {
|
|
this.queued = false;
|
|
for (const req of this.inflight) {
|
|
req.peer._cancelRequest(req);
|
|
}
|
|
this.tracker.remove(this.index);
|
|
removeHotswap(this);
|
|
}
|
|
};
|
|
var RangeRequest = class extends Attachable {
|
|
constructor(ranges, start, end, linear, ifAvailable, blocks) {
|
|
super();
|
|
this.start = start;
|
|
this.end = end;
|
|
this.linear = linear;
|
|
this.ifAvailable = ifAvailable;
|
|
this.blocks = blocks;
|
|
this.ranges = ranges;
|
|
this.userStart = start;
|
|
this.userEnd = end;
|
|
}
|
|
_unref() {
|
|
const i = this.ranges.indexOf(this);
|
|
if (i === -1) return;
|
|
const h = this.ranges.pop();
|
|
if (i < this.ranges.length) this.ranges[i] = h;
|
|
}
|
|
_cancel(r) {
|
|
r.resolve(false);
|
|
}
|
|
};
|
|
var UpgradeRequest = class extends Attachable {
|
|
constructor(replicator, fork, length) {
|
|
super();
|
|
this.fork = fork;
|
|
this.length = length;
|
|
this.inflight = [];
|
|
this.replicator = replicator;
|
|
}
|
|
_unref() {
|
|
if (this.replicator.eagerUpgrade === true || this.inflight.length > 0) return;
|
|
this.replicator._upgrade = null;
|
|
}
|
|
_cancel(r) {
|
|
r.resolve(false);
|
|
}
|
|
};
|
|
var SeekRequest = class extends Attachable {
|
|
constructor(seeks, seeker) {
|
|
super();
|
|
this.seeker = seeker;
|
|
this.inflight = [];
|
|
this.seeks = seeks;
|
|
}
|
|
_unref() {
|
|
if (this.inflight.length > 0) return;
|
|
const i = this.seeks.indexOf(this);
|
|
if (i === -1) return;
|
|
const h = this.seeks.pop();
|
|
if (i < this.seeks.length) this.seeks[i] = h;
|
|
}
|
|
};
|
|
var InflightTracker = class {
|
|
constructor() {
|
|
this._requests = [];
|
|
this._free = [];
|
|
}
|
|
get idle() {
|
|
return this._requests.length === this._free.length;
|
|
}
|
|
*[Symbol.iterator]() {
|
|
for (const req of this._requests) {
|
|
if (req !== null) yield req;
|
|
}
|
|
}
|
|
add(req) {
|
|
const id = this._free.length ? this._free.pop() : this._requests.push(null);
|
|
req.id = id;
|
|
this._requests[id - 1] = req;
|
|
return req;
|
|
}
|
|
get(id) {
|
|
return id <= this._requests.length ? this._requests[id - 1] : null;
|
|
}
|
|
remove(id, roundtrip) {
|
|
if (id > this._requests.length) return;
|
|
this._requests[id - 1] = null;
|
|
if (roundtrip === true) this._free.push(id);
|
|
}
|
|
reusable(id) {
|
|
this._free.push(id);
|
|
}
|
|
};
|
|
var BlockTracker = class {
|
|
constructor() {
|
|
this._map = /* @__PURE__ */ new Map();
|
|
}
|
|
[Symbol.iterator]() {
|
|
return this._map.values();
|
|
}
|
|
isEmpty() {
|
|
return this._map.size === 0;
|
|
}
|
|
has(index) {
|
|
return this._map.has(index);
|
|
}
|
|
get(index) {
|
|
return this._map.get(index) || null;
|
|
}
|
|
add(index, priority) {
|
|
let b = this._map.get(index);
|
|
if (b) return b;
|
|
b = new BlockRequest(this, index, priority);
|
|
this._map.set(index, b);
|
|
return b;
|
|
}
|
|
remove(index) {
|
|
const b = this.get(index);
|
|
this._map.delete(index);
|
|
return b;
|
|
}
|
|
};
|
|
var RoundtripQueue = class {
|
|
constructor() {
|
|
this.queue = [];
|
|
this.tick = 0;
|
|
}
|
|
clear() {
|
|
const ids = new Array(this.queue.length);
|
|
for (let i = 0; i < ids.length; i++) {
|
|
ids[i] = this.queue[i][1];
|
|
}
|
|
this.queue = [];
|
|
return ids;
|
|
}
|
|
add(id) {
|
|
this.queue.push([++this.tick, id]);
|
|
}
|
|
flush(tick) {
|
|
let flushed = null;
|
|
for (let i = 0; i < this.queue.length; i++) {
|
|
if (this.queue[i][0] > tick) break;
|
|
if (flushed === null) flushed = [];
|
|
flushed.push(this.queue[i][1]);
|
|
}
|
|
if (flushed !== null) this.queue.splice(0, flushed.length);
|
|
return flushed;
|
|
}
|
|
};
|
|
var Peer = class {
|
|
constructor(replicator, protomux, channel, useSession, inflightRange) {
|
|
this.core = replicator.core;
|
|
this.replicator = replicator;
|
|
this.stream = protomux.stream;
|
|
this.protomux = protomux;
|
|
this.remotePublicKey = this.stream.remotePublicKey;
|
|
this.remoteSupportsSeeks = false;
|
|
this.inflightRange = inflightRange;
|
|
this.paused = false;
|
|
this.removed = false;
|
|
this.useSession = useSession;
|
|
this.channel = channel;
|
|
this.channel.userData = this;
|
|
this.wireSync = this.channel.messages[0];
|
|
this.wireRequest = this.channel.messages[1];
|
|
this.wireCancel = this.channel.messages[2];
|
|
this.wireData = this.channel.messages[3];
|
|
this.wireNoData = this.channel.messages[4];
|
|
this.wireWant = this.channel.messages[5];
|
|
this.wireUnwant = this.channel.messages[6];
|
|
this.wireBitfield = this.channel.messages[7];
|
|
this.wireRange = this.channel.messages[8];
|
|
this.wireExtension = this.channel.messages[9];
|
|
this.stats = {
|
|
wireSync: { tx: 0, rx: 0 },
|
|
wireRequest: { tx: 0, rx: 0 },
|
|
wireCancel: { tx: 0, rx: 0 },
|
|
wireData: { tx: 0, rx: 0 },
|
|
wireWant: { tx: 0, rx: 0 },
|
|
wireBitfield: { tx: 0, rx: 0 },
|
|
wireRange: { tx: 0, rx: 0 },
|
|
wireExtension: { tx: 0, rx: 0 },
|
|
hotswaps: 0
|
|
};
|
|
this.receiverQueue = new ReceiverQueue();
|
|
this.receiverBusy = false;
|
|
this.roundtripQueue = null;
|
|
this.inflight = 0;
|
|
this.dataProcessing = 0;
|
|
this.canUpgrade = true;
|
|
this.needsSync = false;
|
|
this.syncsProcessing = 0;
|
|
this._remoteContiguousLength = 0;
|
|
this.remoteOpened = false;
|
|
this.remoteBitfield = new RemoteBitfield();
|
|
this.missingBlocks = new RemoteBitfield();
|
|
this.remoteFork = 0;
|
|
this.remoteLength = 0;
|
|
this.remoteCanUpgrade = false;
|
|
this.remoteUploading = true;
|
|
this.remoteDownloading = true;
|
|
this.remoteSynced = false;
|
|
this.remoteHasManifest = false;
|
|
this.remoteRequests = /* @__PURE__ */ new Map();
|
|
this.segmentsWanted = /* @__PURE__ */ new Set();
|
|
this.broadcastedNonSparse = false;
|
|
this.lengthAcked = 0;
|
|
this.extensions = /* @__PURE__ */ new Map();
|
|
this.lastExtensionSent = "";
|
|
this.lastExtensionRecv = "";
|
|
replicator._ifAvailable++;
|
|
}
|
|
get remoteContiguousLength() {
|
|
return this.remoteBitfield.findFirst(false, this._remoteContiguousLength);
|
|
}
|
|
getMaxInflight() {
|
|
const stream = this.stream.rawStream;
|
|
if (!stream.udx) return Math.min(this.inflightRange[1], this.inflightRange[0] * 3);
|
|
const scale = stream.rtt <= SCALE_LATENCY ? 1 : stream.rtt / SCALE_LATENCY * Math.min(1, 2 / this.replicator.peers.length);
|
|
return Math.max(this.inflightRange[0], Math.round(Math.min(this.inflightRange[1], this.inflightRange[0] * scale)));
|
|
}
|
|
getMaxHotswapInflight() {
|
|
const inf = this.getMaxInflight();
|
|
return Math.max(16, inf / 2);
|
|
}
|
|
signalUpgrade() {
|
|
if (this._shouldUpdateCanUpgrade() === true) this._updateCanUpgradeAndSync();
|
|
else this.sendSync();
|
|
}
|
|
_markInflight(index) {
|
|
this.missingBlocks.set(index, false);
|
|
}
|
|
broadcastRange(start, length, drop) {
|
|
if (drop) this._unclearLocalRange(start, length);
|
|
else this._clearLocalRange(start, length);
|
|
if (!drop) {
|
|
if (this._remoteContiguousLength >= start + length) return;
|
|
if (length === 1) {
|
|
if (this.remoteBitfield.get(start)) return;
|
|
} else {
|
|
if (this.remoteBitfield.firstUnset(start) >= start + length) return;
|
|
}
|
|
}
|
|
this.wireRange.send({
|
|
drop,
|
|
start,
|
|
length
|
|
});
|
|
incrementTx(this.stats.wireRange, this.replicator.stats.wireRange);
|
|
}
|
|
extension(name, message) {
|
|
this.wireExtension.send({ name: name === this.lastExtensionSent ? "" : name, message });
|
|
incrementTx(this.stats.wireExtension, this.replicator.stats.wireExtension);
|
|
this.lastExtensionSent = name;
|
|
}
|
|
onextension(message) {
|
|
const name = message.name || this.lastExtensionRecv;
|
|
this.lastExtensionRecv = name;
|
|
const ext = this.extensions.get(name);
|
|
if (ext) ext._onmessage({ start: 0, end: message.message.byteLength, buffer: message.message }, this);
|
|
}
|
|
sendSync() {
|
|
if (this.syncsProcessing !== 0) {
|
|
this.needsSync = true;
|
|
return;
|
|
}
|
|
if (this.core.tree.fork !== this.remoteFork) {
|
|
this.canUpgrade = false;
|
|
}
|
|
this.needsSync = false;
|
|
this.wireSync.send({
|
|
fork: this.core.tree.fork,
|
|
length: this.core.tree.length,
|
|
remoteLength: this.core.tree.fork === this.remoteFork ? this.remoteLength : 0,
|
|
canUpgrade: this.canUpgrade,
|
|
uploading: true,
|
|
downloading: this.replicator.isDownloading(),
|
|
hasManifest: !!this.core.header.manifest && this.core.compat === false
|
|
});
|
|
incrementTx(this.stats.wireSync, this.replicator.stats.wireSync);
|
|
}
|
|
onopen({ seeks, capability }) {
|
|
const expected = caps.replicate(this.stream.isInitiator === false, this.replicator.key, this.stream.handshakeHash);
|
|
if (b4a.equals(capability, expected) !== true) {
|
|
throw INVALID_CAPABILITY("Remote sent an invalid replication capability");
|
|
}
|
|
if (this.remoteOpened === true) return;
|
|
this.remoteOpened = true;
|
|
this.remoteSupportsSeeks = seeks;
|
|
this.protomux.cork();
|
|
this.sendSync();
|
|
const contig = Math.min(this.core.tree.length, this.core.header.hints.contiguousLength);
|
|
if (contig > 0) {
|
|
this.broadcastRange(0, contig, false);
|
|
if (contig === this.core.tree.length) {
|
|
this.broadcastedNonSparse = true;
|
|
}
|
|
}
|
|
this.replicator._ifAvailable--;
|
|
this.replicator._addPeer(this);
|
|
this.protomux.uncork();
|
|
}
|
|
onclose(isRemote) {
|
|
const reopen = isRemote === true && this.remoteOpened === true && this.remoteDownloading === false && this.remoteUploading === true && this.replicator.downloading === true;
|
|
if (this.remoteOpened === false) {
|
|
if (this.useSession) {
|
|
this.replicator._peerSessions--;
|
|
this.replicator._closeSessionMaybe();
|
|
}
|
|
this.replicator._ifAvailable--;
|
|
this.replicator.updateAll();
|
|
return;
|
|
}
|
|
this.remoteOpened = false;
|
|
this.removed = true;
|
|
this.remoteRequests.clear();
|
|
this.receiverQueue.clear();
|
|
if (this.roundtripQueue !== null) {
|
|
for (const id of this.roundtripQueue.clear()) this.replicator._inflight.reusable(id);
|
|
}
|
|
this.replicator._removePeer(this);
|
|
if (reopen) {
|
|
this.replicator._makePeer(this.protomux, this.useSession);
|
|
}
|
|
if (this.useSession) {
|
|
this.replicator._peerSessions--;
|
|
this.replicator._closeSessionMaybe();
|
|
}
|
|
}
|
|
closeIfIdle() {
|
|
if (this.remoteDownloading === false && this.replicator.isDownloading() === false) {
|
|
this.channel.close();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
async onsync({ fork, length, remoteLength, canUpgrade, uploading, downloading, hasManifest }) {
|
|
const lengthChanged = length !== this.remoteLength;
|
|
const sameFork = fork === this.core.tree.fork;
|
|
this.remoteSynced = true;
|
|
this.remoteFork = fork;
|
|
this.remoteLength = length;
|
|
this.remoteCanUpgrade = canUpgrade;
|
|
this.remoteUploading = uploading;
|
|
this.remoteDownloading = downloading;
|
|
this.remoteHasManifest = hasManifest;
|
|
if (this.closeIfIdle()) return;
|
|
this.lengthAcked = sameFork ? remoteLength : 0;
|
|
this.syncsProcessing++;
|
|
this.replicator._updateFork(this);
|
|
if (this.remoteLength > this.core.tree.length && this.lengthAcked === this.core.tree.length) {
|
|
if (this.replicator._addUpgradeMaybe() !== null) this._update();
|
|
}
|
|
const upgrade = lengthChanged === false || sameFork === false ? this.canUpgrade && sameFork : await this._canUpgrade(length, fork);
|
|
if (length === this.remoteLength && fork === this.core.tree.fork) {
|
|
this.canUpgrade = upgrade;
|
|
}
|
|
if (--this.syncsProcessing !== 0) return;
|
|
if (this.needsSync === true || this.core.tree.fork === this.remoteFork && this.core.tree.length > this.remoteLength) {
|
|
this.signalUpgrade();
|
|
}
|
|
this._update();
|
|
}
|
|
_shouldUpdateCanUpgrade() {
|
|
return this.core.tree.fork === this.remoteFork && this.core.tree.length > this.remoteLength && this.canUpgrade === false && this.syncsProcessing === 0;
|
|
}
|
|
async _updateCanUpgradeAndSync() {
|
|
const { length, fork } = this.core.tree;
|
|
const canUpgrade = await this._canUpgrade(this.remoteLength, this.remoteFork);
|
|
if (this.syncsProcessing > 0 || length !== this.core.tree.length || fork !== this.core.tree.fork) {
|
|
return;
|
|
}
|
|
if (canUpgrade === this.canUpgrade) {
|
|
return;
|
|
}
|
|
this.canUpgrade = canUpgrade;
|
|
this.sendSync();
|
|
}
|
|
// Safe to call in the background - never fails
|
|
async _canUpgrade(remoteLength, remoteFork) {
|
|
if (remoteFork !== this.core.tree.fork) return false;
|
|
if (remoteLength === 0) return true;
|
|
if (remoteLength >= this.core.tree.length) return false;
|
|
try {
|
|
const canUpgrade = await this.core.tree.upgradeable(remoteLength);
|
|
if (remoteFork !== this.core.tree.fork) return false;
|
|
return canUpgrade;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
async _getProof(msg) {
|
|
const proof = await this.core.tree.proof(msg);
|
|
if (proof.block) {
|
|
const index = msg.block.index;
|
|
if (msg.fork !== this.core.tree.fork || !this.core.bitfield.get(index)) {
|
|
return null;
|
|
}
|
|
proof.block.value = await this.core.blocks.get(index);
|
|
}
|
|
if (msg.manifest && !this.core.compat) {
|
|
proof.manifest = this.core.header.manifest;
|
|
}
|
|
return proof;
|
|
}
|
|
async onrequest(msg) {
|
|
const size = this.remoteRequests.size;
|
|
this.remoteRequests.set(msg.id, msg);
|
|
if (size === this.remoteRequests.size) {
|
|
this._cancel(msg.id);
|
|
this.remoteRequests.set(msg.id, msg);
|
|
}
|
|
if (!this.protomux.drained || this.receiverQueue.length) {
|
|
this.receiverQueue.push(msg);
|
|
return;
|
|
}
|
|
await this._handleRequest(msg);
|
|
}
|
|
oncancel(msg) {
|
|
this._cancel(msg.request);
|
|
}
|
|
_cancel(id) {
|
|
this.remoteRequests.delete(id);
|
|
this.receiverQueue.delete(id);
|
|
}
|
|
ondrain() {
|
|
return this._handleRequests();
|
|
}
|
|
async _handleRequests() {
|
|
if (this.receiverBusy) return;
|
|
this.receiverBusy = true;
|
|
this.protomux.cork();
|
|
while (this.remoteOpened && this.protomux.drained && this.receiverQueue.length > 0 && !this.removed) {
|
|
const msg = this.receiverQueue.shift();
|
|
await this._handleRequest(msg);
|
|
}
|
|
this.protomux.uncork();
|
|
this.receiverBusy = false;
|
|
}
|
|
async _handleRequest(msg) {
|
|
let proof = null;
|
|
if (msg.fork === this.core.tree.fork) {
|
|
try {
|
|
proof = await this._getProof(msg);
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
if (msg.fork === this.core.tree.fork && isCriticalError(err)) throw err;
|
|
}
|
|
}
|
|
if (this.remoteRequests.get(msg.id) !== msg) {
|
|
return;
|
|
}
|
|
this.remoteRequests.delete(msg.id);
|
|
if (proof === null) {
|
|
if (msg.manifest && this.core.header.manifest) {
|
|
const manifest = this.core.header.manifest;
|
|
this.wireData.send({ request: msg.id, fork: this.core.tree.fork, block: null, hash: null, seek: null, upgrade: null, manifest });
|
|
incrementTx(this.stats.wireData, this.replicator.stats.wireData);
|
|
return;
|
|
}
|
|
this.wireNoData.send({ request: msg.id });
|
|
return;
|
|
}
|
|
if (proof.block !== null) {
|
|
this.replicator.onupload(proof.block.index, proof.block.value, this);
|
|
}
|
|
this.wireData.send({
|
|
request: msg.id,
|
|
fork: msg.fork,
|
|
block: proof.block,
|
|
hash: proof.hash,
|
|
seek: proof.seek,
|
|
upgrade: proof.upgrade,
|
|
manifest: proof.manifest
|
|
});
|
|
incrementTx(this.stats.wireData, this.replicator.stats.wireData);
|
|
}
|
|
_cancelRequest(req) {
|
|
if (req.priority === PRIORITY.CANCELLED) return;
|
|
req.priority = PRIORITY.CANCELLED;
|
|
this.inflight--;
|
|
this.replicator._requestDone(req.id, false);
|
|
if (isBlockRequest(req)) this.replicator._unmarkInflight(req.block.index);
|
|
if (isUpgradeRequest(req)) this.replicator._clearInflightUpgrade(req);
|
|
if (this.roundtripQueue === null) this.roundtripQueue = new RoundtripQueue();
|
|
this.roundtripQueue.add(req.id);
|
|
this.wireCancel.send({ request: req.id });
|
|
incrementTx(this.stats.wireCancel, this.replicator.stats.wireCancel);
|
|
}
|
|
_checkIfConflict() {
|
|
this.paused = true;
|
|
const length = Math.min(this.core.tree.length, this.remoteLength);
|
|
if (length === 0) return;
|
|
this.wireRequest.send({
|
|
id: 0,
|
|
// NOTE: use an more explicit id for this eventually...
|
|
fork: this.remoteFork,
|
|
block: null,
|
|
hash: null,
|
|
seek: null,
|
|
upgrade: {
|
|
start: 0,
|
|
length
|
|
}
|
|
});
|
|
incrementTx(this.stats.wireRequest, this.replicator.stats.wireRequest);
|
|
}
|
|
async ondata(data) {
|
|
if (data.request === 0 && data.upgrade && data.upgrade.start === 0) {
|
|
if (await this.core.checkConflict(data, this)) return;
|
|
this.paused = false;
|
|
}
|
|
const req = data.request > 0 ? this.replicator._inflight.get(data.request) : null;
|
|
const reorg = data.fork > this.core.tree.fork;
|
|
if (req === null && reorg === false) return;
|
|
if (req !== null) {
|
|
if (req.peer !== this) return;
|
|
this._onrequestroundtrip(req);
|
|
}
|
|
try {
|
|
if (reorg === true) return await this.replicator._onreorgdata(this, req, data);
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
if (isBlockRequest(req)) this.replicator._unmarkInflight(req.block.index);
|
|
this.paused = true;
|
|
this.replicator.oninvalid(err, req, data, this);
|
|
return;
|
|
}
|
|
this.dataProcessing++;
|
|
try {
|
|
if (!matchingRequest(req, data) || !await this.core.verify(data, this)) {
|
|
this.replicator._onnodata(this, req);
|
|
return;
|
|
}
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
if (isBlockRequest(req)) this.replicator._unmarkInflight(req.block.index);
|
|
if (err.code === "WRITE_FAILED") {
|
|
this.paused = true;
|
|
return;
|
|
}
|
|
if (this.core.closed && !isCriticalError(err)) return;
|
|
if (err.code !== "INVALID_OPERATION") {
|
|
this._checkIfConflict();
|
|
}
|
|
this.replicator._onnodata(this, req);
|
|
this.replicator.oninvalid(err, req, data, this);
|
|
return;
|
|
} finally {
|
|
this.dataProcessing--;
|
|
}
|
|
this.replicator._ondata(this, req, data);
|
|
if (this._shouldUpdateCanUpgrade() === true) {
|
|
this._updateCanUpgradeAndSync();
|
|
}
|
|
}
|
|
onnodata({ request }) {
|
|
const req = request > 0 ? this.replicator._inflight.get(request) : null;
|
|
if (req === null || req.peer !== this) return;
|
|
this._onrequestroundtrip(req);
|
|
this.replicator._onnodata(this, req);
|
|
}
|
|
_onrequestroundtrip(req) {
|
|
if (req.priority === PRIORITY.CANCELLED) return;
|
|
req.priority = PRIORITY.CANCELLED;
|
|
this.inflight--;
|
|
this.replicator._requestDone(req.id, true);
|
|
if (this.roundtripQueue === null) return;
|
|
const flushed = this.roundtripQueue.flush(req.rt);
|
|
if (flushed === null) return;
|
|
for (const id of flushed) this.replicator._inflight.reusable(id);
|
|
}
|
|
onwant({ start, length }) {
|
|
this.replicator._onwant(this, start, length);
|
|
}
|
|
onunwant() {
|
|
}
|
|
onbitfield({ start, bitfield }) {
|
|
if (start < this._remoteContiguousLength) this._remoteContiguousLength = start;
|
|
this.remoteBitfield.insert(start, bitfield);
|
|
this.missingBlocks.insert(start, bitfield);
|
|
this._clearLocalRange(start, bitfield.byteLength * 8);
|
|
this._update();
|
|
}
|
|
_clearLocalRange(start, length) {
|
|
const bitfield = this.core.skipBitfield === null ? this.core.bitfield : this.core.skipBitfield;
|
|
if (length === 1) {
|
|
this.missingBlocks.set(start, this._remoteHasBlock(start) && !bitfield.get(start));
|
|
return;
|
|
}
|
|
const contig = Math.min(this.core.tree.length, this.core.header.hints.contiguousLength);
|
|
if (start + length < contig) {
|
|
const delta = contig - start;
|
|
this.missingBlocks.setRange(start, delta, false);
|
|
return;
|
|
}
|
|
const rem = start & 32767;
|
|
if (rem > 0) {
|
|
start -= rem;
|
|
length += rem;
|
|
}
|
|
const end = start + Math.min(length, this.core.tree.length);
|
|
while (start < end) {
|
|
const local = bitfield.getBitfield(start);
|
|
if (local && local.bitfield) {
|
|
this.missingBlocks.clear(start, local.bitfield);
|
|
}
|
|
start += 32768;
|
|
}
|
|
}
|
|
_resetMissingBlock(index) {
|
|
const bitfield = this.core.skipBitfield === null ? this.core.bitfield : this.core.skipBitfield;
|
|
this.missingBlocks.set(index, this._remoteHasBlock(index) && !bitfield.get(index));
|
|
}
|
|
_unclearLocalRange(start, length) {
|
|
if (length === 1) {
|
|
this._resetMissingBlock(start);
|
|
return;
|
|
}
|
|
const rem = start & 2097151;
|
|
if (rem > 0) {
|
|
start -= rem;
|
|
length += rem;
|
|
}
|
|
const fixedStart = start;
|
|
const end = start + Math.min(length, this.remoteLength);
|
|
while (start < end) {
|
|
const remote = this.remoteBitfield.getBitfield(start);
|
|
if (remote && remote.bitfield) {
|
|
this.missingBlocks.insert(start, remote.bitfield);
|
|
}
|
|
start += 2097152;
|
|
}
|
|
this._clearLocalRange(fixedStart, length);
|
|
}
|
|
onrange({ drop, start, length }) {
|
|
const has = drop === false;
|
|
if (drop === true && start < this._remoteContiguousLength) {
|
|
this._remoteContiguousLength = start;
|
|
}
|
|
if (start === 0 && drop === false) {
|
|
if (length > this._remoteContiguousLength) this._remoteContiguousLength = length;
|
|
} else if (length === 1) {
|
|
const bitfield = this.core.skipBitfield === null ? this.core.bitfield : this.core.skipBitfield;
|
|
this.remoteBitfield.set(start, has);
|
|
this.missingBlocks.set(start, has && !bitfield.get(start));
|
|
} else {
|
|
const rangeStart = this.remoteBitfield.findFirst(!has, start);
|
|
const rangeLength = length - (rangeStart - start);
|
|
if (rangeLength > 0) {
|
|
this.remoteBitfield.setRange(rangeStart, rangeLength, has);
|
|
this.missingBlocks.setRange(rangeStart, rangeLength, has);
|
|
if (has) this._clearLocalRange(rangeStart, rangeLength);
|
|
}
|
|
}
|
|
if (drop === false) this._update();
|
|
}
|
|
onreorghint() {
|
|
}
|
|
_update() {
|
|
this.replicator.updatePeer(this);
|
|
}
|
|
async _onconflict() {
|
|
this.protomux.cork();
|
|
if (this.remoteLength > 0 && this.core.tree.fork === this.remoteFork) {
|
|
await this.onrequest({
|
|
id: 0,
|
|
fork: this.core.tree.fork,
|
|
block: null,
|
|
hash: null,
|
|
seek: null,
|
|
upgrade: {
|
|
start: 0,
|
|
length: Math.min(this.core.tree.length, this.remoteLength)
|
|
}
|
|
});
|
|
}
|
|
this.channel.close();
|
|
this.protomux.uncork();
|
|
}
|
|
_makeRequest(needsUpgrade, priority, minLength) {
|
|
if (needsUpgrade === true && this.replicator._shouldUpgrade(this) === false) {
|
|
return null;
|
|
}
|
|
if (this.remoteLength < minLength) {
|
|
return null;
|
|
}
|
|
if (needsUpgrade === false && this.replicator._autoUpgrade(this) === true) {
|
|
needsUpgrade = true;
|
|
}
|
|
return {
|
|
peer: this,
|
|
rt: this.roundtripQueue === null ? 0 : this.roundtripQueue.tick,
|
|
id: 0,
|
|
fork: this.remoteFork,
|
|
block: null,
|
|
hash: null,
|
|
seek: null,
|
|
upgrade: needsUpgrade === false ? null : { start: this.core.tree.length, length: this.remoteLength - this.core.tree.length },
|
|
// remote manifest check can be removed eventually...
|
|
manifest: this.core.header.manifest === null && this.remoteHasManifest === true,
|
|
priority
|
|
};
|
|
}
|
|
_requestManifest() {
|
|
const req = this._makeRequest(false, 0, 0);
|
|
this._send(req);
|
|
}
|
|
_requestUpgrade(u) {
|
|
const req = this._makeRequest(true, 0, 0);
|
|
if (req === null) return false;
|
|
this._send(req);
|
|
return true;
|
|
}
|
|
_requestSeek(s) {
|
|
if (this.replicator._updatesPending > 0) return false;
|
|
const { length, fork } = this.core.tree;
|
|
if (fork !== this.remoteFork) return false;
|
|
if (s.seeker.start >= length) {
|
|
const req = this._makeRequest(true, 0, 0);
|
|
if (req === null) return false;
|
|
req.seek = this.remoteSupportsSeeks ? { bytes: s.seeker.bytes, padding: s.seeker.padding } : null;
|
|
s.inflight.push(req);
|
|
this._send(req);
|
|
return true;
|
|
}
|
|
const len = s.seeker.end - s.seeker.start;
|
|
const off = s.seeker.start + Math.floor(Math.random() * len);
|
|
for (let i = 0; i < len; i++) {
|
|
let index = off + i;
|
|
if (index > s.seeker.end) index -= len;
|
|
if (this._remoteHasBlock(index) === false) continue;
|
|
if (this.core.bitfield.get(index) === true) continue;
|
|
if (!this._hasTreeParent(index)) continue;
|
|
const b = this.replicator._blocks.get(index);
|
|
if (b !== null && b.inflight.length > 0) continue;
|
|
const h = this.replicator._hashes.add(index, PRIORITY.NORMAL);
|
|
if (h.inflight.length > 0) continue;
|
|
const req = this._makeRequest(false, h.priority, index + 1);
|
|
if (req === null) continue;
|
|
const nodes = flatTree.depth(s.seeker.start + s.seeker.end - 1);
|
|
req.hash = { index: 2 * index, nodes };
|
|
req.seek = this.remoteSupportsSeeks ? { bytes: s.seeker.bytes, padding: s.seeker.padding } : null;
|
|
s.inflight.push(req);
|
|
h.inflight.push(req);
|
|
this._send(req);
|
|
return true;
|
|
}
|
|
this._maybeWant(s.seeker.start, len);
|
|
return false;
|
|
}
|
|
_hasTreeParent(index) {
|
|
if (this.remoteLength >= this.core.tree.length) return true;
|
|
const ite = flatTree.iterator(index * 2);
|
|
let span = 2;
|
|
let length = 0;
|
|
while (true) {
|
|
ite.parent();
|
|
const left = (ite.index - ite.factor / 2 + 1) / 2;
|
|
length = left + span;
|
|
if (length > this.core.tree.length) {
|
|
if (length > this.remoteLength) return true;
|
|
break;
|
|
}
|
|
if (length > this.remoteLength) break;
|
|
span *= 2;
|
|
const first = this.core.bitfield.findFirst(true, left);
|
|
if (first > -1 && first < length) return true;
|
|
}
|
|
return false;
|
|
}
|
|
_remoteHasBlock(index) {
|
|
return index < this._remoteContiguousLength || this.remoteBitfield.get(index) === true;
|
|
}
|
|
_sendBlockRequest(req, b) {
|
|
req.block = { index: b.index, nodes: 0 };
|
|
this.replicator._markInflight(b.index);
|
|
b.inflight.push(req);
|
|
this.replicator.hotswaps.add(b);
|
|
this._send(req);
|
|
}
|
|
_requestBlock(b) {
|
|
const { length, fork } = this.core.tree;
|
|
if (this._remoteHasBlock(b.index) === false || fork !== this.remoteFork) {
|
|
this._maybeWant(b.index);
|
|
return false;
|
|
}
|
|
if (!this._hasTreeParent(b.index)) {
|
|
return false;
|
|
}
|
|
const req = this._makeRequest(b.index >= length, b.priority, b.index + 1);
|
|
if (req === null) return false;
|
|
this._sendBlockRequest(req, b);
|
|
return true;
|
|
}
|
|
_requestRangeBlock(index, length) {
|
|
if (this.core.bitfield.get(index) === true || !this._hasTreeParent(index)) return false;
|
|
const b = this.replicator._blocks.add(index, PRIORITY.NORMAL);
|
|
if (b.inflight.length > 0) {
|
|
this.missingBlocks.set(index, false);
|
|
return false;
|
|
}
|
|
const req = this._makeRequest(index >= length, b.priority, index + 1);
|
|
if (req === null) {
|
|
b.gc();
|
|
return false;
|
|
}
|
|
this._sendBlockRequest(req, b);
|
|
if (b.queued) b.queued = false;
|
|
return true;
|
|
}
|
|
_findNext(i) {
|
|
if (i < this._remoteContiguousLength) {
|
|
if (this.core.skipBitfield === null) this.replicator._openSkipBitfield();
|
|
i = this.core.skipBitfield.findFirst(false, i);
|
|
if (i < this._remoteContiguousLength && i > -1) return i;
|
|
i = this._remoteContiguousLength;
|
|
}
|
|
return this.missingBlocks.findFirst(true, i);
|
|
}
|
|
_requestRange(r) {
|
|
const { length, fork } = this.core.tree;
|
|
if (r.blocks) {
|
|
let min = -1;
|
|
let max = -1;
|
|
for (let i2 = r.start; i2 < r.end; i2++) {
|
|
const index = r.blocks[i2];
|
|
if (min === -1 || index < min) min = index;
|
|
if (max === -1 || index > max) max = index;
|
|
const has = index < this._remoteContiguousLength || this.missingBlocks.get(index) === true;
|
|
if (has === true && this._requestRangeBlock(index, length)) return true;
|
|
}
|
|
if (min > -1) this._maybeWant(min, max - min);
|
|
return false;
|
|
}
|
|
const end = Math.min(this.core.tree.length, Math.min(r.end === -1 ? this.remoteLength : r.end, this.remoteLength));
|
|
if (end <= r.start || fork !== this.remoteFork) return false;
|
|
const len = end - r.start;
|
|
const off = r.start + (r.linear ? 0 : Math.floor(Math.random() * len));
|
|
let i = off;
|
|
while (true) {
|
|
i = this._findNext(i);
|
|
if (i === -1 || i >= end) break;
|
|
if (this._requestRangeBlock(i, length)) return true;
|
|
i++;
|
|
}
|
|
i = r.start;
|
|
while (true) {
|
|
i = this._findNext(i);
|
|
if (i === -1 || i >= off) break;
|
|
if (this._requestRangeBlock(i, length)) return true;
|
|
i++;
|
|
}
|
|
this._maybeWant(r.start, len);
|
|
return false;
|
|
}
|
|
_requestForkProof(f) {
|
|
const req = this._makeRequest(false, 0, 0);
|
|
req.upgrade = { start: 0, length: this.remoteLength };
|
|
req.manifest = !this.core.header.manifest;
|
|
f.inflight.push(req);
|
|
this._send(req);
|
|
}
|
|
_requestForkRange(f) {
|
|
if (f.fork !== this.remoteFork || f.batch.want === null) return false;
|
|
const end = Math.min(f.batch.want.end, this.remoteLength);
|
|
if (end < f.batch.want.start) return false;
|
|
const len = end - f.batch.want.start;
|
|
const off = f.batch.want.start + Math.floor(Math.random() * len);
|
|
for (let i = 0; i < len; i++) {
|
|
let index = off + i;
|
|
if (index >= end) index -= len;
|
|
if (this._remoteHasBlock(index) === false) continue;
|
|
const req = this._makeRequest(false, 0, 0);
|
|
req.hash = { index: 2 * index, nodes: f.batch.want.nodes };
|
|
f.inflight.push(req);
|
|
this._send(req);
|
|
return true;
|
|
}
|
|
this._maybeWant(f.batch.want.start, len);
|
|
return false;
|
|
}
|
|
_maybeWant(start, length = 1) {
|
|
if (start + length <= this.remoteContiguousLength) return;
|
|
let i = Math.floor(start / DEFAULT_SEGMENT_SIZE);
|
|
const n = Math.ceil((start + length) / DEFAULT_SEGMENT_SIZE);
|
|
for (; i < n; i++) {
|
|
if (this.segmentsWanted.has(i)) continue;
|
|
this.segmentsWanted.add(i);
|
|
this.wireWant.send({
|
|
start: i * DEFAULT_SEGMENT_SIZE,
|
|
length: DEFAULT_SEGMENT_SIZE
|
|
});
|
|
incrementTx(this.stats.wireWant, this.replicator.stats.wireWant);
|
|
}
|
|
}
|
|
isActive() {
|
|
if (this.paused || this.removed) return false;
|
|
return true;
|
|
}
|
|
async _send(req) {
|
|
const fork = this.core.tree.fork;
|
|
this.inflight++;
|
|
this.replicator._inflight.add(req);
|
|
if (req.upgrade !== null && req.fork === fork) {
|
|
const u = this.replicator._addUpgrade();
|
|
u.inflight.push(req);
|
|
}
|
|
try {
|
|
if (req.block !== null && req.fork === fork) {
|
|
req.block.nodes = await this.core.tree.missingNodes(2 * req.block.index);
|
|
if (req.priority === PRIORITY.CANCELLED) return;
|
|
}
|
|
if (req.hash !== null && req.fork === fork && req.hash.nodes === 0) {
|
|
req.hash.nodes = await this.core.tree.missingNodes(req.hash.index);
|
|
if (req.priority === PRIORITY.CANCELLED) return;
|
|
if (req.hash.nodes === 0 && (req.hash.index & 1) === 0) {
|
|
this.inflight--;
|
|
this.replicator._resolveHashLocally(this, req);
|
|
return;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
this.stream.destroy(err);
|
|
return;
|
|
}
|
|
this.wireRequest.send(req);
|
|
incrementTx(this.stats.wireRequest, this.replicator.stats.wireRequest);
|
|
}
|
|
};
|
|
module.exports = class Replicator {
|
|
static Peer = Peer;
|
|
// Bridge: access Peer from outside this module
|
|
constructor(core, key, {
|
|
notDownloadingLinger = NOT_DOWNLOADING_SLACK,
|
|
eagerUpgrade = true,
|
|
allowFork = true,
|
|
inflightRange = null,
|
|
onpeerupdate = noop,
|
|
onupload = noop,
|
|
oninvalid = noop
|
|
} = {}) {
|
|
this.key = key;
|
|
this.discoveryKey = core.crypto.discoveryKey(key);
|
|
this.core = core;
|
|
this.eagerUpgrade = eagerUpgrade;
|
|
this.allowFork = allowFork;
|
|
this.onpeerupdate = onpeerupdate;
|
|
this.onupload = onupload;
|
|
this.oninvalid = oninvalid;
|
|
this.ondownloading = null;
|
|
this.peers = [];
|
|
this.findingPeers = 0;
|
|
this.destroyed = false;
|
|
this.downloading = false;
|
|
this.activeSessions = 0;
|
|
this.hotswaps = new HotswapQueue();
|
|
this.inflightRange = inflightRange || DEFAULT_MAX_INFLIGHT;
|
|
this.stats = {
|
|
wireSync: { tx: 0, rx: 0 },
|
|
wireRequest: { tx: 0, rx: 0 },
|
|
wireCancel: { tx: 0, rx: 0 },
|
|
wireData: { tx: 0, rx: 0 },
|
|
wireWant: { tx: 0, rx: 0 },
|
|
wireBitfield: { tx: 0, rx: 0 },
|
|
wireRange: { tx: 0, rx: 0 },
|
|
wireExtension: { tx: 0, rx: 0 },
|
|
hotswaps: 0
|
|
};
|
|
this._attached = /* @__PURE__ */ new Set();
|
|
this._inflight = new InflightTracker();
|
|
this._blocks = new BlockTracker();
|
|
this._hashes = new BlockTracker();
|
|
this._queued = [];
|
|
this._seeks = [];
|
|
this._upgrade = null;
|
|
this._reorgs = [];
|
|
this._ranges = [];
|
|
this._hadPeers = false;
|
|
this._ifAvailable = 0;
|
|
this._updatesPending = 0;
|
|
this._applyingReorg = null;
|
|
this._manifestPeer = null;
|
|
this._hasSession = false;
|
|
this._peerSessions = 0;
|
|
this._notDownloadingLinger = notDownloadingLinger;
|
|
this._downloadingTimer = null;
|
|
const self2 = this;
|
|
this._onstreamclose = onstreamclose;
|
|
function onstreamclose() {
|
|
self2.detachFrom(this.userData);
|
|
}
|
|
}
|
|
updateActivity(inc, session) {
|
|
this.activeSessions += inc;
|
|
this.setDownloading(this.activeSessions !== 0, session);
|
|
}
|
|
isDownloading() {
|
|
return this.downloading || !this._inflight.idle;
|
|
}
|
|
setDownloading(downloading) {
|
|
clearTimeout(this._downloadingTimer);
|
|
if (this.destroyed) return;
|
|
if (downloading || this._notDownloadingLinger === 0) {
|
|
this.setDownloadingNow(downloading);
|
|
return;
|
|
}
|
|
this._downloadingTimer = setTimeout(setDownloadingLater, this._notDownloadingLinger, this, downloading);
|
|
}
|
|
setDownloadingNow(downloading) {
|
|
this._downloadingTimer = null;
|
|
if (this.downloading === downloading) return;
|
|
this.downloading = downloading;
|
|
if (!downloading && this.isDownloading()) return;
|
|
for (const peer of this.peers) peer.signalUpgrade();
|
|
if (downloading) {
|
|
for (const protomux of this._attached) {
|
|
if (!protomux.stream.handshakeHash) continue;
|
|
if (protomux.opened({ protocol: "hypercore/alpha", id: this.discoveryKey })) continue;
|
|
this._makePeer(protomux, true);
|
|
}
|
|
} else {
|
|
for (const peer of this.peers) peer.closeIfIdle();
|
|
}
|
|
if (this.ondownloading !== null && downloading) this.ondownloading();
|
|
}
|
|
cork() {
|
|
for (const peer of this.peers) peer.protomux.cork();
|
|
}
|
|
uncork() {
|
|
for (const peer of this.peers) peer.protomux.uncork();
|
|
}
|
|
// Called externally when a range of new blocks has been processed/removed
|
|
onhave(start, length, drop = false) {
|
|
for (const peer of this.peers) peer.broadcastRange(start, length, drop);
|
|
}
|
|
// Called externally when a truncation upgrade has been processed
|
|
ontruncate(newLength, truncated) {
|
|
const notify = [];
|
|
for (const blk of this._blocks) {
|
|
if (blk.index < newLength) continue;
|
|
notify.push(blk);
|
|
}
|
|
for (const blk of notify) {
|
|
for (const r of blk.refs) {
|
|
if (r.snapshot === false) continue;
|
|
blk.detach(r, SNAPSHOT_NOT_AVAILABLE());
|
|
}
|
|
}
|
|
for (const peer of this.peers) peer._unclearLocalRange(newLength, truncated);
|
|
}
|
|
// Called externally when a upgrade has been processed
|
|
onupgrade() {
|
|
for (const peer of this.peers) peer.signalUpgrade();
|
|
if (this._blocks.isEmpty() === false) this._resolveBlocksLocally();
|
|
if (this._upgrade !== null) this._resolveUpgradeRequest(null);
|
|
if (this._ranges.length !== 0 || this._seeks.length !== 0) this._updateNonPrimary(true);
|
|
}
|
|
// Called externally when a conflict has been detected and verified
|
|
async onconflict(from) {
|
|
const all = [];
|
|
for (const peer of this.peers) {
|
|
all.push(peer._onconflict());
|
|
}
|
|
await Promise.allSettled(all);
|
|
}
|
|
async applyPendingReorg() {
|
|
if (this._applyingReorg !== null) {
|
|
await this._applyingReorg;
|
|
return true;
|
|
}
|
|
for (let i = this._reorgs.length - 1; i >= 0; i--) {
|
|
const f = this._reorgs[i];
|
|
if (f.batch !== null && f.batch.finished) {
|
|
await this._applyReorg(f);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
addUpgrade(session) {
|
|
if (this._upgrade !== null) {
|
|
const ref2 = this._upgrade.attach(session);
|
|
this._checkUpgradeIfAvailable();
|
|
return ref2;
|
|
}
|
|
const ref = this._addUpgrade().attach(session);
|
|
this.updateAll();
|
|
return ref;
|
|
}
|
|
addBlock(session, index) {
|
|
const b = this._blocks.add(index, PRIORITY.HIGH);
|
|
const ref = b.attach(session);
|
|
this._queueBlock(b);
|
|
this.updateAll();
|
|
return ref;
|
|
}
|
|
addSeek(session, seeker) {
|
|
const s = new SeekRequest(this._seeks, seeker);
|
|
const ref = s.attach(session);
|
|
this._seeks.push(s);
|
|
this.updateAll();
|
|
return ref;
|
|
}
|
|
addRange(session, { start = 0, end = -1, length = toLength(start, end), blocks = null, linear = false, ifAvailable = false } = {}) {
|
|
if (blocks !== null) {
|
|
start = 0;
|
|
end = length = blocks.length;
|
|
}
|
|
const r = new RangeRequest(
|
|
this._ranges,
|
|
start,
|
|
length === -1 ? -1 : start + length,
|
|
linear,
|
|
ifAvailable,
|
|
blocks
|
|
);
|
|
const ref = r.attach(session);
|
|
clampRange(this.core, r);
|
|
this._ranges.push(r);
|
|
if (r.end !== -1 && r.start >= r.end) {
|
|
this._resolveRangeRequest(r, this._ranges.length - 1);
|
|
return ref;
|
|
}
|
|
this.updateAll();
|
|
return ref;
|
|
}
|
|
cancel(ref) {
|
|
ref.context.detach(ref, null);
|
|
}
|
|
clearRequests(session, err = null) {
|
|
let cleared = false;
|
|
while (session.length > 0) {
|
|
const ref = session[session.length - 1];
|
|
ref.context.detach(ref, err);
|
|
cleared = true;
|
|
}
|
|
if (cleared) this.updateAll();
|
|
}
|
|
_addUpgradeMaybe() {
|
|
return this.eagerUpgrade === true ? this._addUpgrade() : this._upgrade;
|
|
}
|
|
// NOTE: this function is OVER called atm, at each updatePeer/updateAll
|
|
// instead its more efficient to only call it when the conditions in here change - ie on sync/add/remove peer
|
|
// Do this when we have more tests.
|
|
_checkUpgradeIfAvailable() {
|
|
if (this._ifAvailable > 0 && this.peers.length < MAX_PEERS_UPGRADE) return;
|
|
if (this._upgrade === null || this._upgrade.refs.length === 0) return;
|
|
if (this._hadPeers === false && this.findingPeers > 0) return;
|
|
const maxPeers = Math.min(this.peers.length, MAX_PEERS_UPGRADE);
|
|
for (let i = 0; i < maxPeers; i++) {
|
|
const peer = this.peers[i];
|
|
if (peer.remoteSynced === false) return;
|
|
if (this.core.tree.length === 0 && peer.remoteLength > 0) return;
|
|
if (peer.remoteLength <= this._upgrade.length || peer.remoteFork !== this._upgrade.fork) continue;
|
|
if (peer.syncsProcessing > 0) return;
|
|
if (peer.lengthAcked !== this.core.tree.length && peer.remoteFork === this.core.tree.fork) return;
|
|
if (peer.remoteCanUpgrade === true) return;
|
|
}
|
|
if (this._applyingReorg !== null) return;
|
|
for (let i = 0; i < this._reorgs.length; i++) {
|
|
const r = this._reorgs[i];
|
|
if (r.inflight.length > 0) return;
|
|
}
|
|
if (this._upgrade.inflight.length > 0) return;
|
|
const u = this._upgrade;
|
|
this._upgrade = null;
|
|
u.resolve(false);
|
|
}
|
|
_addUpgrade() {
|
|
if (this._upgrade !== null) return this._upgrade;
|
|
this._upgrade = new UpgradeRequest(this, this.core.tree.fork, this.core.tree.length);
|
|
return this._upgrade;
|
|
}
|
|
_addReorg(fork, peer) {
|
|
if (this.allowFork === false) return null;
|
|
for (const f2 of this._reorgs) {
|
|
if (f2.fork > fork && f2.batch !== null) return null;
|
|
if (f2.fork === fork) return f2;
|
|
}
|
|
const f = {
|
|
fork,
|
|
inflight: [],
|
|
batch: null
|
|
};
|
|
this._reorgs.push(f);
|
|
let i = this._reorgs.length - 1;
|
|
while (i > 0 && this._reorgs[i - 1].fork > fork) {
|
|
this._reorgs[i] = this._reorgs[i - 1];
|
|
this._reorgs[--i] = f;
|
|
}
|
|
return f;
|
|
}
|
|
_shouldUpgrade(peer) {
|
|
if (this._upgrade !== null && this._upgrade.inflight.length > 0) return false;
|
|
return peer.remoteCanUpgrade === true && peer.remoteLength > this.core.tree.length && peer.lengthAcked === this.core.tree.length;
|
|
}
|
|
_autoUpgrade(peer) {
|
|
return this._upgrade !== null && peer.remoteFork === this.core.tree.fork && this._shouldUpgrade(peer);
|
|
}
|
|
_addPeer(peer) {
|
|
this._hadPeers = true;
|
|
this.peers.push(peer);
|
|
this.updatePeer(peer);
|
|
this.onpeerupdate(true, peer);
|
|
}
|
|
_requestDone(id, roundtrip) {
|
|
this._inflight.remove(id, roundtrip);
|
|
if (this.isDownloading() === true) return;
|
|
for (const peer of this.peers) peer.signalUpgrade();
|
|
}
|
|
_removePeer(peer) {
|
|
this.peers.splice(this.peers.indexOf(peer), 1);
|
|
if (this._manifestPeer === peer) this._manifestPeer = null;
|
|
for (const req of this._inflight) {
|
|
if (req.peer !== peer) continue;
|
|
this._inflight.remove(req.id, true);
|
|
this._clearRequest(peer, req);
|
|
}
|
|
if (peer.useSession) this._closeSessionMaybe();
|
|
this.onpeerupdate(false, peer);
|
|
this.updateAll();
|
|
}
|
|
_queueBlock(b) {
|
|
if (b.inflight.length > 0 || b.queued === true) return;
|
|
b.queued = true;
|
|
this._queued.push(b);
|
|
}
|
|
_resolveHashLocally(peer, req) {
|
|
this._requestDone(req.id, false);
|
|
this._resolveBlockRequest(this._hashes, req.hash.index / 2, null, req);
|
|
this.updatePeer(peer);
|
|
}
|
|
// Runs in the background - not allowed to throw
|
|
async _resolveBlocksLocally() {
|
|
let clear = null;
|
|
for (const b of this._blocks) {
|
|
if (this.core.bitfield.get(b.index) === false) continue;
|
|
try {
|
|
b.resolve(await this.core.blocks.get(b.index));
|
|
} catch (err) {
|
|
b.reject(err);
|
|
}
|
|
if (clear === null) clear = [];
|
|
clear.push(b);
|
|
}
|
|
if (clear === null) return;
|
|
for (const b of clear) {
|
|
this._blocks.remove(b.index);
|
|
removeHotswap(b);
|
|
}
|
|
}
|
|
_resolveBlockRequest(tracker, index, value, req) {
|
|
const b = tracker.remove(index);
|
|
if (b === null) return false;
|
|
removeInflight(b.inflight, req);
|
|
removeHotswap(b);
|
|
b.queued = false;
|
|
b.resolve(value);
|
|
if (b.inflight.length > 0) {
|
|
for (let i = b.inflight.length - 1; i >= 0; i--) {
|
|
const req2 = b.inflight[i];
|
|
req2.peer._cancelRequest(req2);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
_resolveUpgradeRequest(req) {
|
|
if (req !== null) removeInflight(this._upgrade.inflight, req);
|
|
if (this.core.tree.length === this._upgrade.length && this.core.tree.fork === this._upgrade.fork) return false;
|
|
const u = this._upgrade;
|
|
this._upgrade = null;
|
|
u.resolve(true);
|
|
return true;
|
|
}
|
|
_resolveRangeRequest(req, index) {
|
|
const head = this._ranges.pop();
|
|
if (index < this._ranges.length) this._ranges[index] = head;
|
|
req.resolve(true);
|
|
}
|
|
_clearInflightBlock(tracker, req) {
|
|
const isBlock = tracker === this._blocks;
|
|
const index = isBlock === true ? req.block.index : req.hash.index / 2;
|
|
const b = tracker.get(index);
|
|
if (b === null || removeInflight(b.inflight, req) === false) return;
|
|
if (removeHotswap(b) === true && b.inflight.length > 0) {
|
|
this.hotswaps.add(b);
|
|
}
|
|
if (b.refs.length > 0 && isBlock === true) {
|
|
this._queueBlock(b);
|
|
return;
|
|
}
|
|
b.gc();
|
|
}
|
|
_clearInflightUpgrade(req) {
|
|
if (removeInflight(this._upgrade.inflight, req) === false) return;
|
|
this._upgrade.gc();
|
|
}
|
|
_clearInflightSeeks(req) {
|
|
for (const s of this._seeks) {
|
|
if (removeInflight(s.inflight, req) === false) continue;
|
|
s.gc();
|
|
}
|
|
}
|
|
_clearInflightReorgs(req) {
|
|
for (const r of this._reorgs) {
|
|
removeInflight(r.inflight, req);
|
|
}
|
|
}
|
|
_clearOldReorgs(fork) {
|
|
for (let i = 0; i < this._reorgs.length; i++) {
|
|
const f = this._reorgs[i];
|
|
if (f.fork >= fork) continue;
|
|
if (i === this._reorgs.length - 1) this._reorgs.pop();
|
|
else this._reorgs[i] = this._reorgs.pop();
|
|
i--;
|
|
}
|
|
}
|
|
// "slow" updates here - async but not allowed to ever throw
|
|
async _updateNonPrimary(updateAll) {
|
|
while (++this._updatesPending === 1) {
|
|
let len = Math.min(MAX_RANGES, this._ranges.length);
|
|
for (let i = 0; i < len; i++) {
|
|
const r = this._ranges[i];
|
|
clampRange(this.core, r);
|
|
if (r.end !== -1 && r.start >= r.end) {
|
|
this._resolveRangeRequest(r, i--);
|
|
if (len > this._ranges.length) len--;
|
|
if (this._ranges.length === MAX_RANGES) updateAll = true;
|
|
}
|
|
}
|
|
for (let i = 0; i < this._seeks.length; i++) {
|
|
const s = this._seeks[i];
|
|
let err = null;
|
|
let res = null;
|
|
try {
|
|
res = await s.seeker.update();
|
|
} catch (error) {
|
|
err = error;
|
|
}
|
|
if (!res && !err) continue;
|
|
if (i < this._seeks.length - 1) this._seeks[i] = this._seeks.pop();
|
|
else this._seeks.pop();
|
|
i--;
|
|
if (err) s.reject(err);
|
|
else s.resolve(res);
|
|
}
|
|
if (--this._updatesPending === 0) break;
|
|
this._updatesPending = 0;
|
|
}
|
|
if (this._inflight.idle || updateAll) this.updateAll();
|
|
}
|
|
_maybeResolveIfAvailableRanges() {
|
|
if (this._ifAvailable > 0 || !this._inflight.idle || !this._ranges.length) return;
|
|
for (let i = 0; i < this.peers.length; i++) {
|
|
if (this.peers[i].dataProcessing > 0) return;
|
|
}
|
|
for (let i = 0; i < this._ranges.length; i++) {
|
|
const r = this._ranges[i];
|
|
if (r.ifAvailable) {
|
|
this._resolveRangeRequest(r, i--);
|
|
}
|
|
}
|
|
}
|
|
_clearRequest(peer, req) {
|
|
if (req.block !== null) {
|
|
this._clearInflightBlock(this._blocks, req);
|
|
this._unmarkInflight(req.block.index);
|
|
}
|
|
if (req.hash !== null) {
|
|
this._clearInflightBlock(this._hashes, req);
|
|
}
|
|
if (req.upgrade !== null && this._upgrade !== null) {
|
|
this._clearInflightUpgrade(req);
|
|
}
|
|
if (this._seeks.length > 0) {
|
|
this._clearInflightSeeks(req);
|
|
}
|
|
if (this._reorgs.length > 0) {
|
|
this._clearInflightReorgs(req);
|
|
}
|
|
}
|
|
_onnodata(peer, req) {
|
|
this._clearRequest(peer, req);
|
|
this.updateAll();
|
|
}
|
|
_openSkipBitfield() {
|
|
const bitfield = this.core.openSkipBitfield();
|
|
for (const req of this._inflight) {
|
|
if (req.block) bitfield.set(req.block.index, true);
|
|
}
|
|
}
|
|
_markInflight(index) {
|
|
if (this.core.skipBitfield !== null) this.core.skipBitfield.set(index, true);
|
|
for (const peer of this.peers) peer._markInflight(index);
|
|
}
|
|
_unmarkInflight(index) {
|
|
if (this.core.skipBitfield !== null) this.core.skipBitfield.set(index, this.core.bitfield.get(index));
|
|
for (const peer of this.peers) peer._resetMissingBlock(index);
|
|
}
|
|
_ondata(peer, req, data) {
|
|
if (data.block !== null) {
|
|
this._resolveBlockRequest(this._blocks, data.block.index, data.block.value, req);
|
|
}
|
|
if (data.hash !== null && (data.hash.index & 1) === 0) {
|
|
this._resolveBlockRequest(this._hashes, data.hash.index / 2, null, req);
|
|
}
|
|
if (this._upgrade !== null) {
|
|
this._resolveUpgradeRequest(req);
|
|
}
|
|
if (this._seeks.length > 0) {
|
|
this._clearInflightSeeks(req);
|
|
}
|
|
if (this._reorgs.length > 0) {
|
|
this._clearInflightReorgs(req);
|
|
}
|
|
if (this._manifestPeer === peer && this.core.header.manifest !== null) {
|
|
this._manifestPeer = null;
|
|
}
|
|
if (this._seeks.length > 0 || this._ranges.length > 0) this._updateNonPrimary(this._seeks.length > 0);
|
|
this.updatePeer(peer);
|
|
}
|
|
_onwant(peer, start, length) {
|
|
const contig = Math.min(this.core.tree.length, this.core.header.hints.contiguousLength);
|
|
if (start + length < contig || this.core.tree.length === contig) {
|
|
peer.wireRange.send({
|
|
drop: false,
|
|
start: 0,
|
|
length: contig
|
|
});
|
|
incrementTx(peer.stats.wireRange, this.stats.wireRange);
|
|
return;
|
|
}
|
|
length = Math.min(length, this.core.tree.length - start);
|
|
peer.protomux.cork();
|
|
for (const msg of this.core.bitfield.want(start, length)) {
|
|
peer.wireBitfield.send(msg);
|
|
incrementTx(peer.stats.wireBitfield, this.stats.wireBitfield);
|
|
}
|
|
peer.protomux.uncork();
|
|
}
|
|
async _onreorgdata(peer, req, data) {
|
|
const newBatch = data.upgrade && await this.core.verifyReorg(data);
|
|
const f = this._addReorg(data.fork, peer);
|
|
if (f === null) {
|
|
this.updateAll();
|
|
return;
|
|
}
|
|
removeInflight(f.inflight, req);
|
|
if (f.batch) {
|
|
await f.batch.update(data);
|
|
} else if (data.upgrade) {
|
|
f.batch = newBatch;
|
|
this._clearOldReorgs(f.fork);
|
|
}
|
|
if (f.batch && f.batch.finished) {
|
|
if (this._addUpgradeMaybe() !== null) {
|
|
await this._applyReorg(f);
|
|
}
|
|
}
|
|
this.updateAll();
|
|
}
|
|
// Never throws, allowed to run in the background
|
|
async _applyReorg(f) {
|
|
const u = this._upgrade;
|
|
this._reorgs = [];
|
|
this._applyingReorg = this.core.reorg(f.batch, null);
|
|
try {
|
|
await this._applyingReorg;
|
|
} catch (err) {
|
|
this._upgrade = null;
|
|
u.reject(err);
|
|
}
|
|
this._applyingReorg = null;
|
|
if (this._upgrade !== null) {
|
|
this._resolveUpgradeRequest(null);
|
|
}
|
|
for (const peer of this.peers) this._updateFork(peer);
|
|
for (const r of this._ranges) {
|
|
r.start = r.userStart;
|
|
r.end = r.userEnd;
|
|
}
|
|
this.updateAll();
|
|
}
|
|
_maybeUpdate() {
|
|
return this._upgrade !== null && this._upgrade.inflight.length === 0;
|
|
}
|
|
_maybeRequestManifest() {
|
|
return this.core.header.manifest === null && this._manifestPeer === null;
|
|
}
|
|
_updateFork(peer) {
|
|
if (this._applyingReorg !== null || this.allowFork === false || peer.remoteFork <= this.core.tree.fork) {
|
|
return false;
|
|
}
|
|
const f = this._addReorg(peer.remoteFork, peer);
|
|
if (f !== null && f.batch === null && f.inflight.length === 0) {
|
|
return peer._requestForkProof(f);
|
|
}
|
|
return false;
|
|
}
|
|
_updateHotswap(peer) {
|
|
const maxHotswaps = peer.getMaxHotswapInflight();
|
|
if (!peer.isActive() || peer.inflight >= maxHotswaps) return;
|
|
for (const b of this.hotswaps.pick(peer)) {
|
|
if (peer._requestBlock(b) === false) continue;
|
|
peer.stats.hotswaps++;
|
|
peer.replicator.stats.hotswaps++;
|
|
if (peer.inflight >= maxHotswaps) break;
|
|
}
|
|
}
|
|
_updatePeer(peer) {
|
|
if (!peer.isActive() || peer.inflight >= peer.getMaxInflight()) {
|
|
return false;
|
|
}
|
|
if (this._maybeRequestManifest() === true && peer.remoteLength === 0 && peer.remoteHasManifest === true) {
|
|
this._manifestPeer = peer;
|
|
peer._requestManifest();
|
|
}
|
|
for (const s of this._seeks) {
|
|
if (s.inflight.length > 0) continue;
|
|
if (peer._requestSeek(s) === true) {
|
|
return true;
|
|
}
|
|
}
|
|
const blks = new RandomIterator(this._queued);
|
|
for (const b of blks) {
|
|
if (b.queued === false || peer._requestBlock(b) === true) {
|
|
b.queued = false;
|
|
blks.dequeue();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
_updatePeerNonPrimary(peer) {
|
|
if (!peer.isActive() || peer.inflight >= peer.getMaxInflight()) {
|
|
return false;
|
|
}
|
|
const ranges = new RandomIterator(this._ranges);
|
|
let tried = 0;
|
|
for (const r of ranges) {
|
|
if (peer._requestRange(r) === true) {
|
|
return true;
|
|
}
|
|
if (++tried >= MAX_RANGES) break;
|
|
}
|
|
for (let i = this._reorgs.length - 1; i >= 0; i--) {
|
|
const f = this._reorgs[i];
|
|
if (f.batch !== null && f.inflight.length === 0 && peer._requestForkRange(f) === true) {
|
|
return true;
|
|
}
|
|
}
|
|
if (this._maybeUpdate() === true && peer._requestUpgrade(this._upgrade) === true) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
updatePeer(peer) {
|
|
if (this._applyingReorg !== null) return;
|
|
while (this._updatePeer(peer) === true) ;
|
|
while (this._updatePeerNonPrimary(peer) === true) ;
|
|
if (this.peers.length > 1 && this._blocks.isEmpty() === false) {
|
|
this._updateHotswap(peer);
|
|
}
|
|
this._checkUpgradeIfAvailable();
|
|
this._maybeResolveIfAvailableRanges();
|
|
}
|
|
updateAll() {
|
|
if (this._applyingReorg !== null) return;
|
|
const peers = new RandomIterator(this.peers);
|
|
for (const peer of peers) {
|
|
if (this._updatePeer(peer) === true) {
|
|
peers.requeue();
|
|
}
|
|
}
|
|
if (this._maybeUpdate() === false && this._ranges.length === 0 && this._reorgs.length === 0) {
|
|
this._checkUpgradeIfAvailable();
|
|
return;
|
|
}
|
|
for (const peer of peers.restart()) {
|
|
if (this._updatePeerNonPrimary(peer) === true) {
|
|
peers.requeue();
|
|
}
|
|
}
|
|
this._checkUpgradeIfAvailable();
|
|
this._maybeResolveIfAvailableRanges();
|
|
}
|
|
_closeSessionMaybe() {
|
|
if (this._hasSession && this._peerSessions === 0) {
|
|
this._hasSession = false;
|
|
this.core.active--;
|
|
}
|
|
if (this.core.active === 0 && this.core.sessions.length === 0) {
|
|
this.destroy();
|
|
this.core.close().catch(safetyCatch);
|
|
return;
|
|
}
|
|
if (this.core.sessions.length === 1 && this.core.active === 1 && this.core.sessions[0].autoClose) {
|
|
this.core.sessions[0].close().catch(safetyCatch);
|
|
}
|
|
}
|
|
attached(protomux) {
|
|
return this._attached.has(protomux);
|
|
}
|
|
ensureSession() {
|
|
if (this._hasSession) return;
|
|
this._hasSession = true;
|
|
this.core.active++;
|
|
}
|
|
attachTo(protomux, useSession) {
|
|
if (this.core.closed) return;
|
|
if (useSession) this.ensureSession();
|
|
const makePeer = this._makePeer.bind(this, protomux, useSession);
|
|
this._attached.add(protomux);
|
|
protomux.pair({ protocol: "hypercore/alpha", id: this.discoveryKey }, makePeer);
|
|
protomux.stream.setMaxListeners(0);
|
|
protomux.stream.on("close", this._onstreamclose);
|
|
if (useSession) this._peerSessions++;
|
|
this._ifAvailable++;
|
|
protomux.stream.opened.then((opened) => {
|
|
if (useSession) this._peerSessions--;
|
|
this._ifAvailable--;
|
|
if (opened && !this.destroyed) makePeer();
|
|
else if (useSession) this._closeSessionMaybe();
|
|
this._checkUpgradeIfAvailable();
|
|
});
|
|
}
|
|
detachFrom(protomux) {
|
|
if (this._attached.delete(protomux)) {
|
|
protomux.stream.removeListener("close", this._onstreamclose);
|
|
protomux.unpair({ protocol: "hypercore/alpha", id: this.discoveryKey });
|
|
}
|
|
}
|
|
destroy() {
|
|
this.destroyed = true;
|
|
if (this._downloadingTimer) {
|
|
clearTimeout(this._downloadingTimer);
|
|
this._downloadingTimer = null;
|
|
}
|
|
const waiting = [];
|
|
while (this.peers.length) {
|
|
const peer = this.peers[this.peers.length - 1];
|
|
this.detachFrom(peer.protomux);
|
|
peer.channel.close();
|
|
waiting.push(peer.channel.fullyClosed());
|
|
}
|
|
for (const protomux of this._attached) {
|
|
this.detachFrom(protomux);
|
|
}
|
|
return Promise.all(waiting);
|
|
}
|
|
_makePeer(protomux, useSession) {
|
|
const replicator = this;
|
|
if (protomux.opened({ protocol: "hypercore/alpha", id: this.discoveryKey })) return onnochannel();
|
|
const channel = protomux.createChannel({
|
|
userData: null,
|
|
protocol: "hypercore/alpha",
|
|
aliases: ["hypercore"],
|
|
id: this.discoveryKey,
|
|
handshake: m.wire.handshake,
|
|
messages: [
|
|
{ encoding: m.wire.sync, onmessage: onwiresync },
|
|
{ encoding: m.wire.request, onmessage: onwirerequest },
|
|
{ encoding: m.wire.cancel, onmessage: onwirecancel },
|
|
{ encoding: m.wire.data, onmessage: onwiredata },
|
|
{ encoding: m.wire.noData, onmessage: onwirenodata },
|
|
{ encoding: m.wire.want, onmessage: onwirewant },
|
|
{ encoding: m.wire.unwant, onmessage: onwireunwant },
|
|
{ encoding: m.wire.bitfield, onmessage: onwirebitfield },
|
|
{ encoding: m.wire.range, onmessage: onwirerange },
|
|
{ encoding: m.wire.extension, onmessage: onwireextension }
|
|
],
|
|
onopen: onwireopen,
|
|
onclose: onwireclose,
|
|
ondrain: onwiredrain
|
|
});
|
|
if (channel === null) return onnochannel();
|
|
const peer = new Peer(replicator, protomux, channel, useSession, this.inflightRange);
|
|
const stream = protomux.stream;
|
|
if (useSession) {
|
|
replicator.ensureSession();
|
|
replicator._peerSessions++;
|
|
}
|
|
peer.channel.open({
|
|
seeks: true,
|
|
capability: caps.replicate(stream.isInitiator, this.key, stream.handshakeHash)
|
|
});
|
|
return true;
|
|
function onnochannel() {
|
|
if (useSession) replicator._closeSessionMaybe();
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
function matchingRequest(req, data) {
|
|
if (data.block !== null && (req.block === null || req.block.index !== data.block.index)) return false;
|
|
if (data.hash !== null && (req.hash === null || req.hash.index !== data.hash.index)) return false;
|
|
if (data.seek !== null && (req.seek === null || req.seek.bytes !== data.seek.bytes)) return false;
|
|
if (data.upgrade !== null && req.upgrade === null) return false;
|
|
return req.fork === data.fork;
|
|
}
|
|
function removeHotswap(block) {
|
|
if (block.hotswap === null) return false;
|
|
block.hotswap.ref.remove(block);
|
|
return true;
|
|
}
|
|
function removeInflight(inf, req) {
|
|
const i = inf.indexOf(req);
|
|
if (i === -1) return false;
|
|
if (i < inf.length - 1) inf[i] = inf.pop();
|
|
else inf.pop();
|
|
return true;
|
|
}
|
|
function noop() {
|
|
}
|
|
function toLength(start, end) {
|
|
return end === -1 ? -1 : end < start ? 0 : end - start;
|
|
}
|
|
function clampRange(core, r) {
|
|
if (r.blocks === null) {
|
|
const start = core.bitfield.firstUnset(r.start);
|
|
if (r.end === -1) r.start = start === -1 ? core.tree.length : start;
|
|
else if (start === -1 || start >= r.end) r.start = r.end;
|
|
else {
|
|
r.start = start;
|
|
const end = core.bitfield.lastUnset(r.end - 1);
|
|
if (end === -1 || start >= end + 1) r.end = r.start;
|
|
else r.end = end + 1;
|
|
}
|
|
} else {
|
|
while (r.start < r.end && core.bitfield.get(r.blocks[r.start])) r.start++;
|
|
while (r.start < r.end && core.bitfield.get(r.blocks[r.end - 1])) r.end--;
|
|
}
|
|
}
|
|
function onrequesttimeout(req) {
|
|
if (req.context) req.context.detach(req, REQUEST_TIMEOUT());
|
|
}
|
|
function destroyRequestTimeout(req) {
|
|
if (req.timeout !== null) {
|
|
clearTimeout(req.timeout);
|
|
req.timeout = null;
|
|
}
|
|
}
|
|
function isCriticalError(err) {
|
|
return err.name === "HypercoreError";
|
|
}
|
|
function onwireopen(m2, c) {
|
|
return c.userData.onopen(m2);
|
|
}
|
|
function onwireclose(isRemote, c) {
|
|
return c.userData.onclose(isRemote);
|
|
}
|
|
function onwiredrain(c) {
|
|
return c.userData.ondrain();
|
|
}
|
|
function onwiresync(m2, c) {
|
|
incrementRx(c.userData.stats.wireSync, c.userData.replicator.stats.wireSync);
|
|
return c.userData.onsync(m2);
|
|
}
|
|
function onwirerequest(m2, c) {
|
|
incrementRx(c.userData.stats.wireRequest, c.userData.replicator.stats.wireRequest);
|
|
return c.userData.onrequest(m2);
|
|
}
|
|
function onwirecancel(m2, c) {
|
|
incrementRx(c.userData.stats.wireCancel, c.userData.replicator.stats.wireCancel);
|
|
return c.userData.oncancel(m2);
|
|
}
|
|
function onwiredata(m2, c) {
|
|
incrementRx(c.userData.stats.wireData, c.userData.replicator.stats.wireData);
|
|
return c.userData.ondata(m2);
|
|
}
|
|
function onwirenodata(m2, c) {
|
|
return c.userData.onnodata(m2);
|
|
}
|
|
function onwirewant(m2, c) {
|
|
incrementRx(c.userData.stats.wireWant, c.userData.replicator.stats.wireWant);
|
|
return c.userData.onwant(m2);
|
|
}
|
|
function onwireunwant(m2, c) {
|
|
return c.userData.onunwant(m2);
|
|
}
|
|
function onwirebitfield(m2, c) {
|
|
incrementRx(c.userData.stats.wireBitfield, c.userData.replicator.stats.wireBitfield);
|
|
return c.userData.onbitfield(m2);
|
|
}
|
|
function onwirerange(m2, c) {
|
|
incrementRx(c.userData.stats.wireRange, c.userData.replicator.stats.wireRange);
|
|
return c.userData.onrange(m2);
|
|
}
|
|
function onwireextension(m2, c) {
|
|
incrementRx(c.userData.stats.wireExtension, c.userData.replicator.stats.wireExtension);
|
|
return c.userData.onextension(m2);
|
|
}
|
|
function setDownloadingLater(repl, downloading, session) {
|
|
repl.setDownloadingNow(downloading, session);
|
|
}
|
|
function isBlockRequest(req) {
|
|
return req !== null && req.block !== null;
|
|
}
|
|
function isUpgradeRequest(req) {
|
|
return req !== null && req.upgrade !== null;
|
|
}
|
|
function incrementTx(stats1, stats2) {
|
|
stats1.tx++;
|
|
stats2.tx++;
|
|
}
|
|
function incrementRx(stats1, stats2) {
|
|
stats1.rx++;
|
|
stats2.rx++;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/crc-universal/lookup.js
|
|
var require_lookup = __commonJS({
|
|
"../../node_modules/crc-universal/lookup.js"(exports, module) {
|
|
var lookup = new Array(16);
|
|
for (let i = 0; i < 16; i++) {
|
|
lookup[i] = new Uint32Array(256);
|
|
}
|
|
for (let i = 0; i <= 255; i++) {
|
|
let crc = i;
|
|
for (let j = 0; j < 8; j++) {
|
|
crc = crc >>> 1 ^ (crc & 1) * 3988292384;
|
|
}
|
|
lookup[0][i] = crc;
|
|
}
|
|
for (let i = 0; i <= 255; i++) {
|
|
for (let j = 1; j < 16; j++) {
|
|
lookup[j][i] = lookup[j - 1][i] >>> 8 ^ lookup[0][lookup[j - 1][i] & 255];
|
|
}
|
|
}
|
|
module.exports = lookup;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/crc-universal/fallback.js
|
|
var require_fallback3 = __commonJS({
|
|
"../../node_modules/crc-universal/fallback.js"(exports) {
|
|
var lookup = require_lookup();
|
|
exports.crc32 = function crc32(buffer) {
|
|
let crc = ~0;
|
|
let i = 0;
|
|
let length = buffer.byteLength;
|
|
while (length >= 16) {
|
|
crc = lookup[15][buffer[i++] ^ crc & 255] ^ lookup[14][buffer[i++] ^ crc >>> 8 & 255] ^ lookup[13][buffer[i++] ^ crc >>> 16 & 255] ^ lookup[12][buffer[i++] ^ crc >>> 24] ^ lookup[11][buffer[i++]] ^ lookup[10][buffer[i++]] ^ lookup[9][buffer[i++]] ^ lookup[8][buffer[i++]] ^ lookup[7][buffer[i++]] ^ lookup[6][buffer[i++]] ^ lookup[5][buffer[i++]] ^ lookup[4][buffer[i++]] ^ lookup[3][buffer[i++]] ^ lookup[2][buffer[i++]] ^ lookup[1][buffer[i++]] ^ lookup[0][buffer[i++]];
|
|
length -= 16;
|
|
}
|
|
while (length-- > 0) {
|
|
crc = crc >>> 8 ^ lookup[0][crc & 255 ^ buffer[i++]];
|
|
}
|
|
return ~crc >>> 0;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/crc-native/binding.js
|
|
var require_binding6 = __commonJS({
|
|
"../../node_modules/crc-native/binding.js"(exports, module) {
|
|
__require.addon = require_node2();
|
|
module.exports = __require.addon(".", __filename);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/crc-native/index.js
|
|
var require_crc_native = __commonJS({
|
|
"../../node_modules/crc-native/index.js"(exports) {
|
|
var binding = require_binding6();
|
|
exports.crc32 = function crc32(buffer) {
|
|
return binding.crc_u32_napi(buffer);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/crc-universal/index.js
|
|
var require_crc_universal = __commonJS({
|
|
"../../node_modules/crc-universal/index.js"(exports, module) {
|
|
var fallback = require_fallback3();
|
|
try {
|
|
const native = require_crc_native();
|
|
exports.crc32 = function crc32(buffer) {
|
|
return buffer.byteLength <= 24 ? fallback.crc32(buffer) : native.crc32(buffer);
|
|
};
|
|
} catch {
|
|
module.exports = fallback;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/oplog.js
|
|
var require_oplog = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/oplog.js"(exports, module) {
|
|
var cenc = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var { crc32 } = require_crc_universal();
|
|
var { OPLOG_CORRUPT, OPLOG_HEADER_OVERFLOW, WRITE_FAILED } = require_hypercore_errors();
|
|
module.exports = class Oplog {
|
|
constructor(storage, { pageSize = 4096, headerEncoding = cenc.raw, entryEncoding = cenc.raw, readonly = false } = {}) {
|
|
this.storage = storage;
|
|
this.headerEncoding = headerEncoding;
|
|
this.entryEncoding = entryEncoding;
|
|
this.readonly = readonly;
|
|
this.flushed = false;
|
|
this.byteLength = 0;
|
|
this.length = 0;
|
|
this._headers = [1, 0];
|
|
this._pageSize = pageSize;
|
|
this._entryOffset = pageSize * 2;
|
|
}
|
|
_addHeader(state, len, headerBit, partialBit) {
|
|
state.start = state.start - len - 4;
|
|
cenc.uint32.encode(state, len << 2 | headerBit | partialBit);
|
|
state.start -= 8;
|
|
cenc.uint32.encode(state, crc32(state.buffer.subarray(state.start + 4, state.start + 8 + len)));
|
|
state.start += len + 4;
|
|
}
|
|
_decodeEntry(state, enc) {
|
|
if (state.end - state.start < 8) return null;
|
|
const cksum = cenc.uint32.decode(state);
|
|
const l = cenc.uint32.decode(state);
|
|
const length = l >>> 2;
|
|
const headerBit = l & 1;
|
|
const partialBit = l & 2;
|
|
if (state.end - state.start < length) return null;
|
|
const end = state.start + length;
|
|
if (crc32(state.buffer.subarray(state.start - 4, end)) !== cksum) {
|
|
return null;
|
|
}
|
|
const result = { header: headerBit, partial: partialBit !== 0, byteLength: length + 8, message: null };
|
|
try {
|
|
result.message = enc.decode({ start: state.start, end, buffer: state.buffer });
|
|
} catch {
|
|
return null;
|
|
}
|
|
state.start = end;
|
|
return result;
|
|
}
|
|
async open() {
|
|
const buffer = await this._readAll();
|
|
const state = { start: 0, end: buffer.byteLength, buffer };
|
|
const result = { header: null, entries: [] };
|
|
this.byteLength = 0;
|
|
this.length = 0;
|
|
const h1 = this._decodeEntry(state, this.headerEncoding);
|
|
state.start = this._pageSize;
|
|
const h2 = this._decodeEntry(state, this.headerEncoding);
|
|
state.start = this._entryOffset;
|
|
if (!h1 && !h2) {
|
|
this.flushed = false;
|
|
this._headers[0] = 1;
|
|
this._headers[1] = 0;
|
|
if (buffer.byteLength >= this._entryOffset) {
|
|
throw OPLOG_CORRUPT();
|
|
}
|
|
return result;
|
|
}
|
|
this.flushed = true;
|
|
if (h1 && !h2) {
|
|
this._headers[0] = h1.header;
|
|
this._headers[1] = h1.header;
|
|
} else if (!h1 && h2) {
|
|
this._headers[0] = h2.header + 1 & 1;
|
|
this._headers[1] = h2.header;
|
|
} else {
|
|
this._headers[0] = h1.header;
|
|
this._headers[1] = h2.header;
|
|
}
|
|
const header = this._headers[0] + this._headers[1] & 1;
|
|
const decoded = [];
|
|
result.header = header ? h2.message : h1.message;
|
|
while (true) {
|
|
const entry = this._decodeEntry(state, this.entryEncoding);
|
|
if (!entry) break;
|
|
if (entry.header !== header) break;
|
|
decoded.push(entry);
|
|
}
|
|
while (decoded.length > 0 && decoded[decoded.length - 1].partial) decoded.pop();
|
|
for (const e of decoded) {
|
|
result.entries.push(e.message);
|
|
this.byteLength += e.byteLength;
|
|
this.length++;
|
|
}
|
|
const size = this.byteLength + this._entryOffset;
|
|
if (size === buffer.byteLength) return result;
|
|
await new Promise((resolve, reject) => {
|
|
if (this.readonly) return resolve();
|
|
this.storage.truncate(size, (err) => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
});
|
|
});
|
|
return result;
|
|
}
|
|
_readAll() {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.open((err) => {
|
|
if (err && err.code !== "ENOENT") return reject(err);
|
|
if (err) return resolve(b4a.alloc(0));
|
|
this.storage.stat((err2, stat) => {
|
|
if (err2 && err2.code !== "ENOENT") return reject(err2);
|
|
this.storage.read(0, stat.size, (err3, buf) => {
|
|
if (err3) return reject(err3);
|
|
resolve(buf);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}
|
|
flush(header) {
|
|
const state = { start: 8, end: 8, buffer: null };
|
|
const i = this._headers[0] === this._headers[1] ? 1 : 0;
|
|
const bit = this._headers[i] + 1 & 1;
|
|
this.headerEncoding.preencode(state, header);
|
|
if (state.end > this._pageSize) throw OPLOG_HEADER_OVERFLOW();
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
this.headerEncoding.encode(state, header);
|
|
this._addHeader(state, state.end - 8, bit, 0);
|
|
return this._writeHeaderAndTruncate(i, bit, state.buffer);
|
|
}
|
|
_writeHeaderAndTruncate(i, bit, buf) {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.write(i === 0 ? 0 : this._pageSize, buf, (err) => {
|
|
if (err) return reject(err);
|
|
this.storage.truncate(this._entryOffset, (err2) => {
|
|
if (err2) return reject(err2);
|
|
this._headers[i] = bit;
|
|
this.byteLength = 0;
|
|
this.length = 0;
|
|
this.flushed = true;
|
|
resolve();
|
|
});
|
|
});
|
|
});
|
|
}
|
|
append(batch, atomic = true) {
|
|
if (!Array.isArray(batch)) batch = [batch];
|
|
const state = { start: 0, end: batch.length * 8, buffer: null };
|
|
const bit = this._headers[0] + this._headers[1] & 1;
|
|
for (let i = 0; i < batch.length; i++) {
|
|
this.entryEncoding.preencode(state, batch[i]);
|
|
}
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
for (let i = 0; i < batch.length; i++) {
|
|
const start = state.start += 8;
|
|
const partial = atomic && i < batch.length - 1 ? 2 : 0;
|
|
this.entryEncoding.encode(state, batch[i]);
|
|
this._addHeader(state, state.start - start, bit, partial);
|
|
}
|
|
return this._append(state.buffer, batch.length);
|
|
}
|
|
close() {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.close((err) => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
_append(buf, count) {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.write(this._entryOffset + this.byteLength, buf, (err) => {
|
|
if (err) return reject(WRITE_FAILED(err.message));
|
|
this.byteLength += buf.byteLength;
|
|
this.length += count;
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/big-header.js
|
|
var require_big_header = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/big-header.js"(exports, module) {
|
|
var c = require_compact_encoding();
|
|
var { oplog } = require_messages2();
|
|
module.exports = class BigHeader {
|
|
constructor(storage) {
|
|
this.storage = storage;
|
|
}
|
|
async load(external) {
|
|
const buf = await new Promise((resolve, reject) => {
|
|
this.storage.read(external.start, external.length, (err, buf2) => {
|
|
if (err) return reject(err);
|
|
resolve(buf2);
|
|
});
|
|
});
|
|
const header = c.decode(oplog.header, buf);
|
|
header.external = external;
|
|
return header;
|
|
}
|
|
async flush(header) {
|
|
const external = header.external || { start: 0, length: 0 };
|
|
header.external = null;
|
|
const buf = c.encode(oplog.header, header);
|
|
let start = 0;
|
|
if (buf.byteLength > external.start) {
|
|
start = external.start + external.length;
|
|
const rem = start & 4095;
|
|
if (rem > 0) start += 4096 - rem;
|
|
}
|
|
header.external = { start, length: buf.byteLength };
|
|
await new Promise((resolve, reject) => {
|
|
this.storage.write(start, buf, (err) => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
});
|
|
});
|
|
return header;
|
|
}
|
|
close() {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.close((err) => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/mutex.js
|
|
var require_mutex = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/mutex.js"(exports, module) {
|
|
module.exports = class Mutex {
|
|
constructor() {
|
|
this.locked = false;
|
|
this.destroyed = false;
|
|
this._destroying = null;
|
|
this._destroyError = null;
|
|
this._queue = [];
|
|
this._enqueue = (resolve, reject) => this._queue.push([resolve, reject]);
|
|
}
|
|
lock() {
|
|
if (this.destroyed) return Promise.reject(this._destroyError || new Error("Mutex has been destroyed"));
|
|
if (this.locked) return new Promise(this._enqueue);
|
|
this.locked = true;
|
|
return Promise.resolve();
|
|
}
|
|
unlock() {
|
|
if (!this._queue.length) {
|
|
this.locked = false;
|
|
return;
|
|
}
|
|
this._queue.shift()[0]();
|
|
}
|
|
destroy(err) {
|
|
if (!this._destroying) this._destroying = this.locked ? this.lock().catch(() => {
|
|
}) : Promise.resolve();
|
|
this.destroyed = true;
|
|
if (err) this._destroyError = err;
|
|
if (err) {
|
|
while (this._queue.length) this._queue.shift()[1](err);
|
|
}
|
|
return this._destroying;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/merkle-tree.js
|
|
var require_merkle_tree = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/merkle-tree.js"(exports, module) {
|
|
var flat = require_flat_tree();
|
|
var crypto = require_hypercore_crypto();
|
|
var c = require_compact_encoding();
|
|
var Xache = require_xache();
|
|
var b4a = require_b4a();
|
|
var unslab = require_unslab();
|
|
var caps = require_caps();
|
|
var { INVALID_PROOF, INVALID_CHECKSUM, INVALID_OPERATION, BAD_ARGUMENT, ASSERTION } = require_hypercore_errors();
|
|
var BLANK_HASH = b4a.alloc(32);
|
|
var OLD_TREE = b4a.from([5, 2, 87, 2, 0, 0, 40, 7, 66, 76, 65, 75, 69, 50, 98]);
|
|
var TREE_CACHE = 128;
|
|
var NodeQueue = class {
|
|
constructor(nodes, extra = null) {
|
|
this.i = 0;
|
|
this.nodes = nodes;
|
|
this.extra = extra;
|
|
this.length = nodes.length + (this.extra === null ? 0 : 1);
|
|
}
|
|
shift(index) {
|
|
if (this.extra !== null && this.extra.index === index) {
|
|
const node2 = this.extra;
|
|
this.extra = null;
|
|
this.length--;
|
|
return node2;
|
|
}
|
|
if (this.i >= this.nodes.length) {
|
|
throw INVALID_OPERATION("Expected node " + index + ", got (nil)");
|
|
}
|
|
const node = this.nodes[this.i++];
|
|
if (node.index !== index) {
|
|
throw INVALID_OPERATION("Expected node " + index + ", got node " + node.index);
|
|
}
|
|
this.length--;
|
|
return node;
|
|
}
|
|
};
|
|
var MerkleTreeBatch = class _MerkleTreeBatch {
|
|
constructor(tree) {
|
|
this.fork = tree.fork;
|
|
this.roots = [...tree.roots];
|
|
this.length = tree.length;
|
|
this.ancestors = tree.length;
|
|
this.byteLength = tree.byteLength;
|
|
this.signature = null;
|
|
this.hashCached = null;
|
|
this.treeLength = tree.length;
|
|
this.treeFork = tree.fork;
|
|
this.tree = tree;
|
|
this.nodes = [];
|
|
this.upgraded = false;
|
|
}
|
|
checkout(length, additionalRoots) {
|
|
const roots = [];
|
|
let r = 0;
|
|
const head = 2 * length - 2;
|
|
const gaps = /* @__PURE__ */ new Set();
|
|
const all = /* @__PURE__ */ new Map();
|
|
if (additionalRoots) {
|
|
for (const node of additionalRoots) all.set(node.index, node);
|
|
}
|
|
for (const node of this.nodes) all.set(node.index, node);
|
|
for (const index of flat.fullRoots(head + 2)) {
|
|
const left = flat.leftSpan(index);
|
|
if (left !== 0) gaps.add(left - 1);
|
|
if (r < this.roots.length && this.roots[r].index === index) {
|
|
roots.push(this.roots[r++]);
|
|
continue;
|
|
}
|
|
const node = all.get(index);
|
|
if (!node) throw new BAD_ARGUMENT("root missing for given length");
|
|
roots.push(node);
|
|
}
|
|
this.roots = roots;
|
|
this.length = length;
|
|
this.byteLength = totalSize(roots);
|
|
this.hashCached = null;
|
|
this.signature = null;
|
|
for (let i = 0; i < this.nodes.length; i++) {
|
|
const index = this.nodes[i].index;
|
|
if (index <= head && !gaps.has(index)) continue;
|
|
const last = this.nodes.pop();
|
|
if (i < this.nodes.length) this.nodes[i--] = last;
|
|
}
|
|
}
|
|
prune(length) {
|
|
if (length === 0) return;
|
|
const head = 2 * length - 2;
|
|
const gaps = /* @__PURE__ */ new Set();
|
|
for (const index of flat.fullRoots(head + 2)) {
|
|
const left = flat.leftSpan(index);
|
|
if (left !== 0) gaps.add(left - 1);
|
|
}
|
|
for (let i = 0; i < this.nodes.length; i++) {
|
|
const index = this.nodes[i].index;
|
|
if (index > head || gaps.has(index)) continue;
|
|
const last = this.nodes.pop();
|
|
if (i < this.nodes.length) this.nodes[i--] = last;
|
|
}
|
|
}
|
|
clone() {
|
|
const b = new _MerkleTreeBatch(this.tree);
|
|
b.fork = this.fork;
|
|
b.roots = [...this.roots];
|
|
b.length = this.length;
|
|
b.byteLength = this.byteLength;
|
|
b.signature = this.signature;
|
|
b.treeLength = this.treeLength;
|
|
b.treeFork = this.treeFork;
|
|
b.tree = this.tree;
|
|
b.nodes = [...this.nodes];
|
|
b.upgraded = this.upgraded;
|
|
return b;
|
|
}
|
|
hash() {
|
|
if (this.hashCached === null) this.hashCached = unslab(this.tree.crypto.tree(this.roots));
|
|
return this.hashCached;
|
|
}
|
|
signable(manifestHash) {
|
|
return caps.treeSignable(manifestHash, this.hash(), this.length, this.fork);
|
|
}
|
|
signableCompat(noHeader) {
|
|
return caps.treeSignableCompat(this.hash(), this.length, this.fork, noHeader);
|
|
}
|
|
get(index, error) {
|
|
if (index >= this.length * 2) {
|
|
return null;
|
|
}
|
|
for (const n of this.nodes) {
|
|
if (n.index === index) return n;
|
|
}
|
|
return this.tree.get(index, error);
|
|
}
|
|
proof({ block, hash, seek, upgrade }) {
|
|
return generateProof(this, block, hash, seek, upgrade);
|
|
}
|
|
verifyUpgrade(proof) {
|
|
const unverified = verifyTree(proof, this.tree.crypto, this.nodes);
|
|
if (!proof.upgrade) throw INVALID_OPERATION("Expected upgrade proof");
|
|
return verifyUpgrade(proof, unverified, this);
|
|
}
|
|
append(buf) {
|
|
const head = this.length * 2;
|
|
const ite = flat.iterator(head);
|
|
const node = blockNode(this.tree.crypto, head, buf);
|
|
this.appendRoot(node, ite);
|
|
}
|
|
appendRoot(node, ite) {
|
|
node = unslabNode(node);
|
|
this.hashCached = null;
|
|
this.upgraded = true;
|
|
this.length += ite.factor / 2;
|
|
this.byteLength += node.size;
|
|
this.roots.push(node);
|
|
this.nodes.push(node);
|
|
while (this.roots.length > 1) {
|
|
const a = this.roots[this.roots.length - 1];
|
|
const b = this.roots[this.roots.length - 2];
|
|
if (ite.sibling() !== b.index) {
|
|
ite.sibling();
|
|
break;
|
|
}
|
|
const node2 = unslabNode(parentNode(this.tree.crypto, ite.parent(), a, b));
|
|
this.nodes.push(node2);
|
|
this.roots.pop();
|
|
this.roots.pop();
|
|
this.roots.push(node2);
|
|
}
|
|
}
|
|
commitable() {
|
|
return this.treeFork === this.tree.fork && (this.upgraded ? this.treeLength === this.tree.length : this.treeLength <= this.tree.length);
|
|
}
|
|
commit() {
|
|
if (!this.commitable()) throw INVALID_OPERATION("Tree was modified during batch, refusing to commit");
|
|
if (this.upgraded) this._commitUpgrade();
|
|
for (let i = 0; i < this.nodes.length; i++) {
|
|
const node = this.nodes[i];
|
|
this.tree.unflushed.set(node.index, node);
|
|
}
|
|
}
|
|
_commitUpgrade() {
|
|
if (this.ancestors < this.treeLength) {
|
|
if (this.ancestors > 0) {
|
|
const head = 2 * this.ancestors;
|
|
const ite = flat.iterator(head - 2);
|
|
while (true) {
|
|
if (ite.contains(head) && ite.index < head) {
|
|
this.tree.unflushed.set(ite.index, blankNode(ite.index));
|
|
}
|
|
if (ite.offset === 0) break;
|
|
ite.parent();
|
|
}
|
|
}
|
|
this.tree.truncateTo = this.tree.truncated ? Math.min(this.tree.truncateTo, this.ancestors) : this.ancestors;
|
|
this.tree.truncated = true;
|
|
this.tree.cache = new Xache({ maxSize: this.tree.cache.maxSize });
|
|
truncateMap(this.tree.unflushed, this.ancestors);
|
|
if (this.tree.flushing !== null) truncateMap(this.tree.flushing, this.ancestors);
|
|
}
|
|
this.tree.roots = this.roots;
|
|
this.tree.length = this.length;
|
|
this.tree.byteLength = this.byteLength;
|
|
this.tree.fork = this.fork;
|
|
this.tree.signature = this.signature;
|
|
}
|
|
seek(bytes, padding) {
|
|
return new ByteSeeker(this, bytes, padding);
|
|
}
|
|
byteRange(index) {
|
|
return getByteRange(this, index);
|
|
}
|
|
byteOffset(index) {
|
|
if (index === 2 * this.tree.length) return this.tree.byteLength;
|
|
return getByteOffset(this, index);
|
|
}
|
|
};
|
|
var ReorgBatch = class extends MerkleTreeBatch {
|
|
constructor(tree) {
|
|
super(tree);
|
|
this.roots = [];
|
|
this.length = 0;
|
|
this.byteLength = 0;
|
|
this.diff = null;
|
|
this.ancestors = 0;
|
|
this.upgraded = true;
|
|
this.want = {
|
|
nodes: 0,
|
|
start: 0,
|
|
end: 0
|
|
};
|
|
}
|
|
get finished() {
|
|
return this.want === null;
|
|
}
|
|
update(proof) {
|
|
if (this.want === null) return true;
|
|
const nodes = [];
|
|
const root = verifyTree(proof, this.tree.crypto, nodes);
|
|
if (root === null || !b4a.equals(root.hash, this.diff.hash)) return false;
|
|
this.nodes.push(...nodes);
|
|
return this._update(nodes);
|
|
}
|
|
async _update(nodes) {
|
|
const n = /* @__PURE__ */ new Map();
|
|
for (const node of nodes) n.set(node.index, node);
|
|
let diff = null;
|
|
const ite = flat.iterator(this.diff.index);
|
|
const startingDiff = this.diff;
|
|
while ((ite.index & 1) !== 0) {
|
|
const left = n.get(ite.leftChild());
|
|
if (!left) break;
|
|
const existing = await this.tree.get(left.index, false);
|
|
if (!existing || !b4a.equals(existing.hash, left.hash)) {
|
|
diff = left;
|
|
} else {
|
|
diff = n.get(ite.sibling());
|
|
}
|
|
}
|
|
if ((this.diff.index & 1) === 0) return true;
|
|
if (diff === null) return false;
|
|
if (startingDiff !== this.diff) return false;
|
|
return this._updateDiffRoot(diff);
|
|
}
|
|
_updateDiffRoot(diff) {
|
|
if (this.want === null) return true;
|
|
const spans = flat.spans(diff.index);
|
|
const start = spans[0] / 2;
|
|
const end = Math.min(this.treeLength, spans[1] / 2 + 1);
|
|
const len = end - start;
|
|
this.ancestors = start;
|
|
this.diff = diff;
|
|
if ((diff.index & 1) === 0 || this.want.start >= this.treeLength || len <= 0) {
|
|
this.want = null;
|
|
return true;
|
|
}
|
|
this.want.start = start;
|
|
this.want.end = end;
|
|
this.want.nodes = log2(spans[1] - spans[0] + 2) - 1;
|
|
return false;
|
|
}
|
|
};
|
|
var ByteSeeker = class {
|
|
constructor(tree, bytes, padding = 0) {
|
|
this.tree = tree;
|
|
this.bytes = bytes;
|
|
this.padding = padding;
|
|
const size = tree.byteLength - tree.length * padding;
|
|
this.start = bytes >= size ? tree.length : 0;
|
|
this.end = bytes < size ? tree.length : 0;
|
|
}
|
|
async _seek(bytes) {
|
|
if (!bytes) return [0, 0];
|
|
for (const node of this.tree.roots) {
|
|
const size = getUnpaddedSize(node, this.padding, null);
|
|
if (bytes === size) return [flat.rightSpan(node.index) + 2, 0];
|
|
if (bytes > size) {
|
|
bytes -= size;
|
|
continue;
|
|
}
|
|
const ite = flat.iterator(node.index);
|
|
while ((ite.index & 1) !== 0) {
|
|
const l = await this.tree.get(ite.leftChild(), false);
|
|
if (l) {
|
|
const size2 = getUnpaddedSize(l, this.padding, ite);
|
|
if (size2 === bytes) return [ite.rightSpan() + 2, 0];
|
|
if (size2 > bytes) continue;
|
|
bytes -= size2;
|
|
ite.sibling();
|
|
} else {
|
|
ite.parent();
|
|
return [ite.index, bytes];
|
|
}
|
|
}
|
|
return [ite.index, bytes];
|
|
}
|
|
return null;
|
|
}
|
|
async update() {
|
|
const res = await this._seek(this.bytes);
|
|
if (!res) return null;
|
|
if ((res[0] & 1) === 0) return [res[0] / 2, res[1]];
|
|
const span = flat.spans(res[0]);
|
|
this.start = span[0] / 2;
|
|
this.end = span[1] / 2 + 1;
|
|
return null;
|
|
}
|
|
};
|
|
module.exports = class MerkleTree {
|
|
constructor(storage, roots, fork, signature, prologue) {
|
|
this.crypto = crypto;
|
|
this.fork = fork;
|
|
this.roots = roots;
|
|
this.length = roots.length ? totalSpan(roots) / 2 : 0;
|
|
this.byteLength = totalSize(roots);
|
|
this.signature = signature;
|
|
this.prologue = prologue;
|
|
this.storage = storage;
|
|
this.unflushed = /* @__PURE__ */ new Map();
|
|
this.cache = new Xache({ maxSize: TREE_CACHE });
|
|
this.flushing = null;
|
|
this.truncated = false;
|
|
this.truncateTo = 0;
|
|
}
|
|
addNode(node) {
|
|
if (node.size === 0 && b4a.equals(node.hash, BLANK_HASH)) node = blankNode(node.index);
|
|
this.unflushed.set(node.index, node);
|
|
}
|
|
batch() {
|
|
return new MerkleTreeBatch(this);
|
|
}
|
|
async restoreBatch(length) {
|
|
const batch = new MerkleTreeBatch(this);
|
|
if (length === this.length) return batch;
|
|
const roots = unslabNodes(await this.getRoots(length));
|
|
batch.roots = roots;
|
|
batch.length = length;
|
|
batch.byteLength = 0;
|
|
batch.ancestors = length;
|
|
for (const node of roots) batch.byteLength += node.size;
|
|
return batch;
|
|
}
|
|
seek(bytes, padding) {
|
|
return new ByteSeeker(this, bytes, padding);
|
|
}
|
|
hash() {
|
|
return unslab(this.crypto.tree(this.roots));
|
|
}
|
|
signable(namespace) {
|
|
return caps.treeSignable(namespace, this.hash(), this.length, this.fork);
|
|
}
|
|
getRoots(length) {
|
|
const indexes = flat.fullRoots(2 * length);
|
|
const roots = new Array(indexes.length);
|
|
for (let i = 0; i < indexes.length; i++) {
|
|
roots[i] = this.get(indexes[i], true);
|
|
}
|
|
return Promise.all(roots);
|
|
}
|
|
setPrologue({ hash, length }) {
|
|
this.prologue = { hash, length };
|
|
}
|
|
addNodes(nodes) {
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
const node = nodes[i];
|
|
this.unflushed.set(node.index, node);
|
|
}
|
|
}
|
|
getNeededNodes(length, start, end) {
|
|
const nodes = /* @__PURE__ */ new Map();
|
|
const head = length * 2;
|
|
for (let i = start; i < end; i++) {
|
|
const ite = flat.iterator(i * 2);
|
|
while (true) {
|
|
if (nodes.has(ite.index)) break;
|
|
nodes.set(ite.index, this.get(ite.index, true));
|
|
const sibling = ite.sibling();
|
|
ite.parent();
|
|
if (ite.contains(head)) break;
|
|
if (nodes.has(sibling)) break;
|
|
nodes.set(sibling, this.get(sibling, true));
|
|
}
|
|
}
|
|
return Promise.all([...nodes.values()]);
|
|
}
|
|
async upgradeable(length) {
|
|
const indexes = flat.fullRoots(2 * length);
|
|
const roots = new Array(indexes.length);
|
|
for (let i = 0; i < indexes.length; i++) {
|
|
roots[i] = this.get(indexes[i], false);
|
|
}
|
|
for (const node of await Promise.all(roots)) {
|
|
if (node === null) return false;
|
|
}
|
|
return true;
|
|
}
|
|
blankNode(index) {
|
|
return blankNode(index);
|
|
}
|
|
get(index, error = true) {
|
|
const c2 = this.cache.get(index);
|
|
if (c2) return c2;
|
|
let node = this.unflushed.get(index);
|
|
if (this.flushing !== null && node === void 0) {
|
|
node = this.flushing.get(index);
|
|
}
|
|
if (this.truncated && node !== void 0 && node.index >= 2 * this.truncateTo) {
|
|
node = blankNode(index);
|
|
}
|
|
if (node !== void 0) {
|
|
if (node.hash === BLANK_HASH) {
|
|
if (error) throw INVALID_OPERATION("Could not load node: " + index);
|
|
return Promise.resolve(null);
|
|
}
|
|
return Promise.resolve(node);
|
|
}
|
|
return getStoredNode(this.storage, index, this.cache, error);
|
|
}
|
|
async flush() {
|
|
this.flushing = this.unflushed;
|
|
this.unflushed = /* @__PURE__ */ new Map();
|
|
try {
|
|
if (this.truncated) await this._flushTruncation();
|
|
await this._flushNodes();
|
|
} catch (err) {
|
|
for (const node of this.flushing.values()) {
|
|
if (!this.unflushed.has(node.index)) this.unflushed.set(node.index, node);
|
|
}
|
|
throw err;
|
|
} finally {
|
|
this.flushing = null;
|
|
}
|
|
}
|
|
_flushTruncation() {
|
|
return new Promise((resolve, reject) => {
|
|
const t = this.truncateTo;
|
|
const offset = t === 0 ? 0 : (t - 1) * 80 + 40;
|
|
this.storage.truncate(offset, (err) => {
|
|
if (err) return reject(err);
|
|
if (this.truncateTo === t) {
|
|
this.truncateTo = 0;
|
|
this.truncated = false;
|
|
}
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
_flushNodes() {
|
|
return new Promise((resolve, reject) => {
|
|
const slab = b4a.allocUnsafe(40 * this.flushing.size);
|
|
let error = null;
|
|
let missing = this.flushing.size + 1;
|
|
let offset = 0;
|
|
for (const node of this.flushing.values()) {
|
|
const state = {
|
|
start: 0,
|
|
end: 40,
|
|
buffer: slab.subarray(offset, offset += 40)
|
|
};
|
|
c.uint64.encode(state, node.size);
|
|
c.raw.encode(state, node.hash);
|
|
this.storage.write(node.index * 40, state.buffer, done);
|
|
}
|
|
done(null);
|
|
function done(err) {
|
|
if (err) error = err;
|
|
if (--missing > 0) return;
|
|
if (error) reject(error);
|
|
else resolve();
|
|
}
|
|
});
|
|
}
|
|
clear() {
|
|
this.cache = new Xache({ maxSize: this.cache.maxSize });
|
|
this.truncated = true;
|
|
this.truncateTo = 0;
|
|
this.roots = [];
|
|
this.length = 0;
|
|
this.byteLength = 0;
|
|
this.fork = 0;
|
|
this.signature = null;
|
|
if (this.flushing !== null) this.flushing.clear();
|
|
this.unflushed.clear();
|
|
return this.flush();
|
|
}
|
|
close() {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.close((err) => {
|
|
if (err) reject(err);
|
|
else resolve();
|
|
});
|
|
});
|
|
}
|
|
async truncate(length, fork = this.fork) {
|
|
const head = length * 2;
|
|
const batch = new MerkleTreeBatch(this);
|
|
const fullRoots = flat.fullRoots(head);
|
|
for (let i = 0; i < fullRoots.length; i++) {
|
|
const root = fullRoots[i];
|
|
if (i < batch.roots.length && batch.roots[i].index === root) continue;
|
|
while (batch.roots.length > i) batch.roots.pop();
|
|
batch.roots.push(unslabNode(await this.get(root)));
|
|
}
|
|
while (batch.roots.length > fullRoots.length) {
|
|
batch.roots.pop();
|
|
}
|
|
batch.fork = fork;
|
|
batch.length = length;
|
|
batch.ancestors = length;
|
|
batch.byteLength = totalSize(batch.roots);
|
|
batch.upgraded = true;
|
|
return batch;
|
|
}
|
|
async reorg(proof) {
|
|
const batch = new ReorgBatch(this);
|
|
let unverified = null;
|
|
if (proof.block || proof.hash || proof.seek) {
|
|
unverified = verifyTree(proof, this.crypto, batch.nodes);
|
|
}
|
|
if (!verifyUpgrade(proof, unverified, batch)) {
|
|
throw INVALID_PROOF("Fork proof not verifiable");
|
|
}
|
|
for (const root of batch.roots) {
|
|
const existing = await this.get(root.index, false);
|
|
if (existing && b4a.equals(existing.hash, root.hash)) continue;
|
|
batch._updateDiffRoot(root);
|
|
break;
|
|
}
|
|
if (batch.diff !== null) {
|
|
await batch._update(batch.nodes);
|
|
} else {
|
|
batch.want = null;
|
|
batch.ancestors = batch.length;
|
|
}
|
|
return batch;
|
|
}
|
|
verifyFullyRemote(proof) {
|
|
const batch = new MerkleTreeBatch(this);
|
|
batch.fork = proof.fork;
|
|
batch.roots = [];
|
|
batch.length = 0;
|
|
batch.ancestors = 0;
|
|
batch.byteLength = 0;
|
|
let unverified = verifyTree(proof, this.crypto, batch.nodes);
|
|
if (proof.upgrade) {
|
|
if (verifyUpgrade(proof, unverified, batch)) {
|
|
unverified = null;
|
|
}
|
|
}
|
|
return batch;
|
|
}
|
|
async verify(proof) {
|
|
const batch = new MerkleTreeBatch(this);
|
|
let unverified = verifyTree(proof, this.crypto, batch.nodes);
|
|
if (proof.upgrade) {
|
|
if (verifyUpgrade(proof, unverified, batch)) {
|
|
unverified = null;
|
|
}
|
|
}
|
|
if (unverified) {
|
|
const verified = await this.get(unverified.index);
|
|
if (!b4a.equals(verified.hash, unverified.hash)) {
|
|
throw INVALID_CHECKSUM("Invalid checksum at node " + unverified.index);
|
|
}
|
|
}
|
|
return batch;
|
|
}
|
|
proof({ block, hash, seek, upgrade }) {
|
|
return generateProof(this, block, hash, seek, upgrade);
|
|
}
|
|
// Successor to .nodes()
|
|
async missingNodes(index) {
|
|
const head = 2 * this.length;
|
|
const ite = flat.iterator(index);
|
|
const iteRightSpan = ite.index + ite.factor / 2 - 1;
|
|
if (iteRightSpan >= head) return 0;
|
|
let cnt = 0;
|
|
while (!ite.contains(head) && await this.get(ite.index, false) === null) {
|
|
cnt++;
|
|
ite.parent();
|
|
}
|
|
return cnt;
|
|
}
|
|
// Deprecated
|
|
async nodes(index) {
|
|
const head = 2 * this.length;
|
|
const ite = flat.iterator(index);
|
|
let cnt = 0;
|
|
while (!ite.contains(head) && await this.get(ite.index, false) === null) {
|
|
cnt++;
|
|
ite.parent();
|
|
}
|
|
return cnt;
|
|
}
|
|
byteRange(index) {
|
|
return getByteRange(this, index);
|
|
}
|
|
byteOffset(index) {
|
|
return getByteOffset(this, index);
|
|
}
|
|
static async open(storage, opts = {}) {
|
|
await new Promise((resolve, reject) => {
|
|
storage.read(0, OLD_TREE.length, (err, buf) => {
|
|
if (err) return resolve();
|
|
if (b4a.equals(buf, OLD_TREE)) return reject(new Error("Storage contains an incompatible merkle tree"));
|
|
resolve();
|
|
});
|
|
});
|
|
const length = typeof opts.length === "number" ? opts.length : await autoLength(storage);
|
|
const roots = [];
|
|
for (const index of flat.fullRoots(2 * length)) {
|
|
roots.push(unslabNode(await getStoredNode(storage, index, null, true)));
|
|
}
|
|
return new MerkleTree(storage, roots, opts.fork || 0, opts.signature || null, opts.prologue || null);
|
|
}
|
|
};
|
|
async function getByteRange(tree, index) {
|
|
const head = 2 * tree.length;
|
|
if (((index & 1) === 0 ? index : flat.rightSpan(index)) >= head) {
|
|
throw BAD_ARGUMENT("Index is out of bounds");
|
|
}
|
|
return [await tree.byteOffset(index), (await tree.get(index)).size];
|
|
}
|
|
async function getByteOffset(tree, index) {
|
|
if (index === 2 * tree.length) return tree.byteLength;
|
|
if ((index & 1) === 1) index = flat.leftSpan(index);
|
|
let head = 0;
|
|
let offset = 0;
|
|
for (const node of tree.roots) {
|
|
head += 2 * (node.index - head + 1);
|
|
if (index >= head) {
|
|
offset += node.size;
|
|
continue;
|
|
}
|
|
const ite = flat.iterator(node.index);
|
|
while (ite.index !== index) {
|
|
if (index < ite.index) {
|
|
ite.leftChild();
|
|
} else {
|
|
offset += (await tree.get(ite.leftChild())).size;
|
|
ite.sibling();
|
|
}
|
|
}
|
|
return offset;
|
|
}
|
|
throw ASSERTION("Failed to find offset");
|
|
}
|
|
function verifyTree({ block, hash, seek }, crypto2, nodes) {
|
|
const untrustedNode = block ? { index: 2 * block.index, value: block.value, nodes: block.nodes } : hash ? { index: hash.index, value: null, nodes: hash.nodes } : null;
|
|
if (untrustedNode === null && (!seek || !seek.nodes.length)) return null;
|
|
let root = null;
|
|
if (seek && seek.nodes.length) {
|
|
const ite2 = flat.iterator(seek.nodes[0].index);
|
|
const q2 = new NodeQueue(seek.nodes);
|
|
root = q2.shift(ite2.index);
|
|
nodes.push(root);
|
|
while (q2.length > 0) {
|
|
const node = q2.shift(ite2.sibling());
|
|
root = parentNode(crypto2, ite2.parent(), root, node);
|
|
nodes.push(node);
|
|
nodes.push(root);
|
|
}
|
|
}
|
|
if (untrustedNode === null) return root;
|
|
const ite = flat.iterator(untrustedNode.index);
|
|
const blockHash = untrustedNode.value && blockNode(crypto2, ite.index, untrustedNode.value);
|
|
const q = new NodeQueue(untrustedNode.nodes, root);
|
|
root = blockHash || q.shift(ite.index);
|
|
nodes.push(root);
|
|
while (q.length > 0) {
|
|
const node = q.shift(ite.sibling());
|
|
root = parentNode(crypto2, ite.parent(), root, node);
|
|
nodes.push(node);
|
|
nodes.push(root);
|
|
}
|
|
return root;
|
|
}
|
|
function verifyUpgrade({ fork, upgrade }, blockRoot, batch) {
|
|
const prologue = batch.tree.prologue;
|
|
if (prologue) {
|
|
const { start, length } = upgrade;
|
|
if (start < prologue.length && (start !== 0 || length < prologue.length)) {
|
|
throw INVALID_PROOF("Upgrade does not satisfy prologue");
|
|
}
|
|
}
|
|
const q = new NodeQueue(upgrade.nodes, blockRoot);
|
|
let grow = batch.roots.length > 0;
|
|
let i = 0;
|
|
const to = 2 * (upgrade.start + upgrade.length);
|
|
const ite = flat.iterator(0);
|
|
for (; ite.fullRoot(to); ite.nextTree()) {
|
|
if (i < batch.roots.length && batch.roots[i].index === ite.index) {
|
|
i++;
|
|
continue;
|
|
}
|
|
if (grow) {
|
|
grow = false;
|
|
const root = ite.index;
|
|
if (i < batch.roots.length) {
|
|
ite.seek(batch.roots[batch.roots.length - 1].index);
|
|
while (ite.index !== root) {
|
|
batch.appendRoot(q.shift(ite.sibling()), ite);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
batch.appendRoot(q.shift(ite.index), ite);
|
|
}
|
|
if (prologue && batch.length === prologue.length) {
|
|
if (!b4a.equals(prologue.hash, batch.hash())) {
|
|
throw INVALID_PROOF("Invalid hash");
|
|
}
|
|
}
|
|
const extra = upgrade.additionalNodes;
|
|
ite.seek(batch.roots[batch.roots.length - 1].index);
|
|
i = 0;
|
|
while (i < extra.length && extra[i].index === ite.sibling()) {
|
|
batch.appendRoot(extra[i++], ite);
|
|
}
|
|
while (i < extra.length) {
|
|
const node = extra[i++];
|
|
while (node.index !== ite.index) {
|
|
if (ite.factor === 2) throw INVALID_OPERATION("Unexpected node: " + node.index);
|
|
ite.leftChild();
|
|
}
|
|
batch.appendRoot(node, ite);
|
|
ite.sibling();
|
|
}
|
|
batch.signature = unslab(upgrade.signature);
|
|
batch.fork = fork;
|
|
return q.extra === null;
|
|
}
|
|
async function seekFromHead(tree, head, bytes, padding) {
|
|
const roots = flat.fullRoots(head);
|
|
for (let i = 0; i < roots.length; i++) {
|
|
const root = roots[i];
|
|
const node = await tree.get(root);
|
|
const size = getUnpaddedSize(node, padding, null);
|
|
if (bytes === size) return root;
|
|
if (bytes > size) {
|
|
bytes -= size;
|
|
continue;
|
|
}
|
|
return seekTrustedTree(tree, root, bytes, padding);
|
|
}
|
|
return head;
|
|
}
|
|
async function seekTrustedTree(tree, root, bytes, padding) {
|
|
if (!bytes) return root;
|
|
const ite = flat.iterator(root);
|
|
while ((ite.index & 1) !== 0) {
|
|
const l = await tree.get(ite.leftChild(), false);
|
|
if (l) {
|
|
const size = getUnpaddedSize(l, padding, ite);
|
|
if (size === bytes) return ite.index;
|
|
if (size > bytes) continue;
|
|
bytes -= size;
|
|
ite.sibling();
|
|
} else {
|
|
ite.parent();
|
|
return ite.index;
|
|
}
|
|
}
|
|
return ite.index;
|
|
}
|
|
async function seekUntrustedTree(tree, root, bytes, padding) {
|
|
const offset = await tree.byteOffset(root) - (padding ? padding * flat.leftSpan(root) / 2 : 0);
|
|
if (offset > bytes) throw INVALID_OPERATION("Invalid seek");
|
|
if (offset === bytes) return root;
|
|
bytes -= offset;
|
|
const node = await tree.get(root);
|
|
if (getUnpaddedSize(node, padding, null) <= bytes) throw INVALID_OPERATION("Invalid seek");
|
|
return seekTrustedTree(tree, root, bytes, padding);
|
|
}
|
|
function seekProof(tree, seekRoot, root, p) {
|
|
const ite = flat.iterator(seekRoot);
|
|
p.seek = [];
|
|
p.seek.push(tree.get(ite.index));
|
|
while (ite.index !== root) {
|
|
ite.sibling();
|
|
p.seek.push(tree.get(ite.index));
|
|
ite.parent();
|
|
}
|
|
}
|
|
function blockAndSeekProof(tree, node, seek, seekRoot, root, p) {
|
|
if (!node) return seekProof(tree, seekRoot, root, p);
|
|
const ite = flat.iterator(node.index);
|
|
p.node = [];
|
|
if (!node.value) p.node.push(tree.get(ite.index));
|
|
while (ite.index !== root) {
|
|
ite.sibling();
|
|
if (seek && ite.contains(seekRoot) && ite.index !== seekRoot) {
|
|
seekProof(tree, seekRoot, ite.index, p);
|
|
} else {
|
|
p.node.push(tree.get(ite.index));
|
|
}
|
|
ite.parent();
|
|
}
|
|
}
|
|
function upgradeProof(tree, node, seek, from, to, subTree, p) {
|
|
if (from === 0) p.upgrade = [];
|
|
for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
|
|
if (ite.index + ite.factor / 2 < from) continue;
|
|
if (p.upgrade === null && ite.contains(from - 2)) {
|
|
p.upgrade = [];
|
|
const root = ite.index;
|
|
const target = from - 2;
|
|
ite.seek(target);
|
|
while (ite.index !== root) {
|
|
ite.sibling();
|
|
if (ite.index > target) {
|
|
if (p.node === null && p.seek === null && ite.contains(subTree)) {
|
|
blockAndSeekProof(tree, node, seek, subTree, ite.index, p);
|
|
} else {
|
|
p.upgrade.push(tree.get(ite.index));
|
|
}
|
|
}
|
|
ite.parent();
|
|
}
|
|
continue;
|
|
}
|
|
if (p.upgrade === null) {
|
|
p.upgrade = [];
|
|
}
|
|
if (p.node === null && p.seek === null && ite.contains(subTree)) {
|
|
blockAndSeekProof(tree, node, seek, subTree, ite.index, p);
|
|
continue;
|
|
}
|
|
p.upgrade.push(tree.get(ite.index));
|
|
}
|
|
}
|
|
function additionalUpgradeProof(tree, from, to, p) {
|
|
if (from === 0) p.additionalUpgrade = [];
|
|
for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
|
|
if (ite.index + ite.factor / 2 < from) continue;
|
|
if (p.additionalUpgrade === null && ite.contains(from - 2)) {
|
|
p.additionalUpgrade = [];
|
|
const root = ite.index;
|
|
const target = from - 2;
|
|
ite.seek(target);
|
|
while (ite.index !== root) {
|
|
ite.sibling();
|
|
if (ite.index > target) {
|
|
p.additionalUpgrade.push(tree.get(ite.index));
|
|
}
|
|
ite.parent();
|
|
}
|
|
continue;
|
|
}
|
|
if (p.additionalUpgrade === null) {
|
|
p.additionalUpgrade = [];
|
|
}
|
|
p.additionalUpgrade.push(tree.get(ite.index));
|
|
}
|
|
}
|
|
function nodesToRoot(index, nodes, head) {
|
|
const ite = flat.iterator(index);
|
|
for (let i = 0; i < nodes; i++) {
|
|
ite.parent();
|
|
if (ite.contains(head)) throw BAD_ARGUMENT("Nodes is out of bounds");
|
|
}
|
|
return ite.index;
|
|
}
|
|
function totalSize(nodes) {
|
|
let s = 0;
|
|
for (const node of nodes) s += node.size;
|
|
return s;
|
|
}
|
|
function totalSpan(nodes) {
|
|
let s = 0;
|
|
for (const node of nodes) s += 2 * (node.index - s + 1);
|
|
return s;
|
|
}
|
|
function blockNode(crypto2, index, value) {
|
|
return { index, size: value.byteLength, hash: crypto2.data(value) };
|
|
}
|
|
function parentNode(crypto2, index, a, b) {
|
|
return { index, size: a.size + b.size, hash: crypto2.parent(a, b) };
|
|
}
|
|
function blankNode(index) {
|
|
return { index, size: 0, hash: BLANK_HASH };
|
|
}
|
|
function getStoredNode(storage, index, cache, error) {
|
|
return new Promise((resolve, reject) => {
|
|
storage.read(40 * index, 40, (err, data) => {
|
|
if (err) {
|
|
if (error) return reject(err);
|
|
else resolve(null);
|
|
return;
|
|
}
|
|
const hash = data.subarray(8);
|
|
const size = c.decode(c.uint64, data);
|
|
if (size === 0 && b4a.compare(hash, BLANK_HASH) === 0) {
|
|
if (error) reject(new Error("Could not load node: " + index));
|
|
else resolve(null);
|
|
return;
|
|
}
|
|
const node = { index, size, hash };
|
|
if (cache !== null) {
|
|
node.hash = unslab(hash);
|
|
cache.set(index, node);
|
|
}
|
|
resolve(node);
|
|
});
|
|
});
|
|
}
|
|
function storedNodes(storage) {
|
|
return new Promise((resolve) => {
|
|
storage.stat((_, st) => {
|
|
if (!st) return resolve(0);
|
|
resolve((st.size - st.size % 40) / 40);
|
|
});
|
|
});
|
|
}
|
|
async function autoLength(storage) {
|
|
const nodes = await storedNodes(storage);
|
|
if (!nodes) return 0;
|
|
const ite = flat.iterator(nodes - 1);
|
|
let index = nodes - 1;
|
|
while (await getStoredNode(storage, ite.parent(), null, false)) index = ite.index;
|
|
return flat.rightSpan(index) / 2 + 1;
|
|
}
|
|
function truncateMap(map, len) {
|
|
for (const node of map.values()) {
|
|
if (node.index >= 2 * len) map.delete(node.index);
|
|
}
|
|
}
|
|
function log2(n) {
|
|
let res = 1;
|
|
while (n > 2) {
|
|
n /= 2;
|
|
res++;
|
|
}
|
|
return res;
|
|
}
|
|
function normalizeIndexed(block, hash) {
|
|
if (block) return { value: true, index: block.index * 2, nodes: block.nodes, lastIndex: block.index };
|
|
if (hash) return { value: false, index: hash.index, nodes: hash.nodes, lastIndex: flat.rightSpan(hash.index) / 2 };
|
|
return null;
|
|
}
|
|
async function settleProof(p) {
|
|
const result = [
|
|
p.node && Promise.all(p.node),
|
|
p.seek && Promise.all(p.seek),
|
|
p.upgrade && Promise.all(p.upgrade),
|
|
p.additionalUpgrade && Promise.all(p.additionalUpgrade)
|
|
];
|
|
try {
|
|
return await Promise.all(result);
|
|
} catch (err) {
|
|
if (p.node) await Promise.allSettled(p.node);
|
|
if (p.seek) await Promise.allSettled(p.seek);
|
|
if (p.upgrade) await Promise.allSettled(p.upgrade);
|
|
if (p.additionalUpgrade) await Promise.allSettled(p.additionalUpgrade);
|
|
throw err;
|
|
}
|
|
}
|
|
async function generateProof(tree, block, hash, seek, upgrade) {
|
|
if (tree.prologue && upgrade) {
|
|
upgrade.start = upgrade.start < tree.prologue.length ? 0 : upgrade.start;
|
|
upgrade.length = upgrade.start < tree.prologue.length ? tree.prologue.length : upgrade.length;
|
|
}
|
|
const fork = tree.fork;
|
|
const signature = tree.signature;
|
|
const head = 2 * tree.length;
|
|
const from = upgrade ? upgrade.start * 2 : 0;
|
|
const to = upgrade ? from + upgrade.length * 2 : head;
|
|
const node = normalizeIndexed(block, hash);
|
|
const result = { fork, block: null, hash: null, seek: null, upgrade: null, manifest: null };
|
|
if (head === 0) return result;
|
|
if (from >= to || to > head) {
|
|
throw INVALID_OPERATION("Invalid upgrade");
|
|
}
|
|
if (seek && upgrade && node !== null && node.index >= from) {
|
|
throw INVALID_OPERATION("Cannot both do a seek and block/hash request when upgrading");
|
|
}
|
|
let subTree = head;
|
|
const p = {
|
|
node: null,
|
|
seek: null,
|
|
upgrade: null,
|
|
additionalUpgrade: null
|
|
};
|
|
if (node !== null && (!upgrade || node.lastIndex < upgrade.start)) {
|
|
subTree = nodesToRoot(node.index, node.nodes, to);
|
|
const seekRoot = seek ? await seekUntrustedTree(tree, subTree, seek.bytes, seek.padding) : head;
|
|
blockAndSeekProof(tree, node, seek, seekRoot, subTree, p);
|
|
} else if ((node || seek) && upgrade) {
|
|
subTree = seek ? await seekFromHead(tree, to, seek.bytes, seek.padding) : node.index;
|
|
}
|
|
if (upgrade) {
|
|
upgradeProof(tree, node, seek, from, to, subTree, p);
|
|
if (head > to) additionalUpgradeProof(tree, to, head, p);
|
|
}
|
|
const [pNode, pSeek, pUpgrade, pAdditional] = await settleProof(p);
|
|
if (block) {
|
|
if (pNode === null) throw INVALID_OPERATION("Invalid block request");
|
|
result.block = {
|
|
index: block.index,
|
|
value: null,
|
|
// populated upstream, alloc it here for simplicity
|
|
nodes: pNode
|
|
};
|
|
} else if (hash) {
|
|
if (pNode === null) throw INVALID_OPERATION("Invalid hash request");
|
|
result.hash = {
|
|
index: hash.index,
|
|
nodes: pNode
|
|
};
|
|
}
|
|
if (seek && pSeek !== null) {
|
|
result.seek = {
|
|
bytes: seek.bytes,
|
|
nodes: pSeek
|
|
};
|
|
}
|
|
if (upgrade) {
|
|
result.upgrade = {
|
|
start: upgrade.start,
|
|
length: upgrade.length,
|
|
nodes: pUpgrade,
|
|
additionalNodes: pAdditional || [],
|
|
signature
|
|
};
|
|
}
|
|
return result;
|
|
}
|
|
function getUnpaddedSize(node, padding, ite) {
|
|
return padding === 0 ? node.size : node.size - padding * (ite ? ite.countLeaves() : flat.countLeaves(node.index));
|
|
}
|
|
function unslabNodes(nodes) {
|
|
for (const node of nodes) unslabNode(node);
|
|
return nodes;
|
|
}
|
|
function unslabNode(node) {
|
|
if (node === null) return node;
|
|
node.hash = unslab(node.hash);
|
|
return node;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/block-store.js
|
|
var require_block_store = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/block-store.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var { WRITE_FAILED } = require_hypercore_errors();
|
|
module.exports = class BlockStore {
|
|
constructor(storage, tree) {
|
|
this.storage = storage;
|
|
this.tree = tree;
|
|
}
|
|
async get(i, tree) {
|
|
if (!tree) tree = this.tree;
|
|
const [offset, size] = await tree.byteRange(2 * i);
|
|
return this._read(offset, size);
|
|
}
|
|
async put(i, data, offset) {
|
|
return this._write(offset, data);
|
|
}
|
|
putBatch(i, batch, offset) {
|
|
if (batch.length === 0) return Promise.resolve();
|
|
return this.put(i, batch.length === 1 ? batch[0] : b4a.concat(batch), offset);
|
|
}
|
|
clear(offset = 0, length = -1) {
|
|
return new Promise((resolve, reject) => {
|
|
if (length === -1) this.storage.truncate(offset, done);
|
|
else this.storage.del(offset, length, done);
|
|
function done(err) {
|
|
if (err) reject(err);
|
|
else resolve();
|
|
}
|
|
});
|
|
}
|
|
close() {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.close((err) => {
|
|
if (err) reject(err);
|
|
else resolve();
|
|
});
|
|
});
|
|
}
|
|
_read(offset, size) {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.read(offset, size, (err, data) => {
|
|
if (err) reject(err);
|
|
else resolve(data);
|
|
});
|
|
});
|
|
}
|
|
_write(offset, data) {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.write(offset, data, (err) => {
|
|
if (err) reject(WRITE_FAILED(err.message));
|
|
else resolve(offset + data.byteLength);
|
|
});
|
|
});
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/bitfield.js
|
|
var require_bitfield = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/bitfield.js"(exports, module) {
|
|
var BigSparseArray = require_big_sparse_array();
|
|
var b4a = require_b4a();
|
|
var quickbit = require_compat().quickbit;
|
|
var BITS_PER_PAGE = 32768;
|
|
var BYTES_PER_PAGE = BITS_PER_PAGE / 8;
|
|
var WORDS_PER_PAGE = BYTES_PER_PAGE / 4;
|
|
var BITS_PER_SEGMENT = 2097152;
|
|
var BYTES_PER_SEGMENT = BITS_PER_SEGMENT / 8;
|
|
var WORDS_PER_SEGMENT = BYTES_PER_SEGMENT / 4;
|
|
var INITIAL_WORDS_PER_SEGMENT = 1024;
|
|
var PAGES_PER_SEGMENT = BITS_PER_SEGMENT / BITS_PER_PAGE;
|
|
var SEGMENT_GROWTH_FACTOR = 4;
|
|
var BitfieldPage = class {
|
|
constructor(index, segment) {
|
|
this.dirty = false;
|
|
this.index = index;
|
|
this.offset = index * BYTES_PER_PAGE - segment.offset;
|
|
this.bitfield = null;
|
|
this.segment = segment;
|
|
segment.add(this);
|
|
}
|
|
get tree() {
|
|
return this.segment.tree;
|
|
}
|
|
get(index) {
|
|
return quickbit.get(this.bitfield, index);
|
|
}
|
|
set(index, val) {
|
|
if (quickbit.set(this.bitfield, index, val)) {
|
|
this.tree.update(this.offset * 8 + index);
|
|
}
|
|
}
|
|
setRange(start, length, val) {
|
|
quickbit.fill(this.bitfield, val, start, start + length);
|
|
let i = Math.floor(start / 128);
|
|
const n = i + Math.ceil(length / 128);
|
|
while (i <= n) this.tree.update(this.offset * 8 + i++ * 128);
|
|
}
|
|
findFirst(val, position) {
|
|
return quickbit.findFirst(this.bitfield, val, position);
|
|
}
|
|
findLast(val, position) {
|
|
return quickbit.findLast(this.bitfield, val, position);
|
|
}
|
|
count(start, length, val) {
|
|
const end = start + length;
|
|
let i = start;
|
|
let c = 0;
|
|
while (length > 0) {
|
|
const l = this.findFirst(val, i);
|
|
if (l === -1 || l >= end) return c;
|
|
const h = this.findFirst(!val, l + 1);
|
|
if (h === -1 || h >= end) return c + end - l;
|
|
c += h - l;
|
|
length -= h - i;
|
|
i = h;
|
|
}
|
|
return c;
|
|
}
|
|
};
|
|
var BitfieldSegment = class {
|
|
constructor(index, bitfield) {
|
|
this.index = index;
|
|
this.offset = index * BYTES_PER_SEGMENT;
|
|
this.tree = quickbit.Index.from(bitfield, BYTES_PER_SEGMENT);
|
|
this.pages = new Array(PAGES_PER_SEGMENT);
|
|
}
|
|
get bitfield() {
|
|
return this.tree.field;
|
|
}
|
|
add(page) {
|
|
const i = page.index - this.index * PAGES_PER_SEGMENT;
|
|
this.pages[i] = page;
|
|
const start = i * WORDS_PER_PAGE;
|
|
const end = start + WORDS_PER_PAGE;
|
|
if (end >= this.bitfield.length) this.reallocate(end);
|
|
page.bitfield = this.bitfield.subarray(start, end);
|
|
}
|
|
reallocate(length) {
|
|
let target = this.bitfield.length;
|
|
while (target < length) target *= SEGMENT_GROWTH_FACTOR;
|
|
const bitfield = new Uint32Array(target);
|
|
bitfield.set(this.bitfield);
|
|
this.tree = quickbit.Index.from(bitfield, BYTES_PER_SEGMENT);
|
|
for (let i = 0; i < this.pages.length; i++) {
|
|
const page = this.pages[i];
|
|
if (!page) continue;
|
|
const start = i * WORDS_PER_PAGE;
|
|
const end = start + WORDS_PER_PAGE;
|
|
page.bitfield = bitfield.subarray(start, end);
|
|
}
|
|
}
|
|
findFirst(val, position) {
|
|
position = this.tree.skipFirst(!val, position);
|
|
let j = position & BITS_PER_PAGE - 1;
|
|
let i = (position - j) / BITS_PER_PAGE;
|
|
if (i >= PAGES_PER_SEGMENT) return -1;
|
|
while (i < this.pages.length) {
|
|
const p = this.pages[i];
|
|
let index = -1;
|
|
if (p) index = p.findFirst(val, j);
|
|
else if (!val) index = j;
|
|
if (index !== -1) return i * BITS_PER_PAGE + index;
|
|
j = 0;
|
|
i++;
|
|
}
|
|
return -1;
|
|
}
|
|
findLast(val, position) {
|
|
position = this.tree.skipLast(!val, position);
|
|
let j = position & BITS_PER_PAGE - 1;
|
|
let i = (position - j) / BITS_PER_PAGE;
|
|
if (i >= PAGES_PER_SEGMENT) return -1;
|
|
while (i >= 0) {
|
|
const p = this.pages[i];
|
|
let index = -1;
|
|
if (p) index = p.findLast(val, j);
|
|
else if (!val) index = j;
|
|
if (index !== -1) return i * BITS_PER_PAGE + index;
|
|
j = BITS_PER_PAGE - 1;
|
|
i--;
|
|
}
|
|
return -1;
|
|
}
|
|
};
|
|
module.exports = class Bitfield {
|
|
constructor(storage, buffer) {
|
|
this.unflushed = [];
|
|
this.storage = storage;
|
|
this.resumed = !!(buffer && buffer.byteLength >= 4);
|
|
this._pages = new BigSparseArray();
|
|
this._segments = new BigSparseArray();
|
|
const view = this.resumed ? new Uint32Array(
|
|
buffer.buffer,
|
|
buffer.byteOffset,
|
|
Math.floor(buffer.byteLength / 4)
|
|
) : new Uint32Array(INITIAL_WORDS_PER_SEGMENT);
|
|
for (let i = 0; i < view.length; i += WORDS_PER_SEGMENT) {
|
|
let bitfield = view.subarray(i, i + WORDS_PER_SEGMENT);
|
|
let length = WORDS_PER_SEGMENT;
|
|
if (i === 0) {
|
|
length = INITIAL_WORDS_PER_SEGMENT;
|
|
while (length < bitfield.length) length *= SEGMENT_GROWTH_FACTOR;
|
|
}
|
|
if (bitfield.length !== length) {
|
|
const copy = new Uint32Array(length);
|
|
copy.set(bitfield, 0);
|
|
bitfield = copy;
|
|
}
|
|
const segment = new BitfieldSegment(i / WORDS_PER_SEGMENT, bitfield);
|
|
this._segments.set(segment.index, segment);
|
|
for (let j = 0; j < bitfield.length; j += WORDS_PER_PAGE) {
|
|
const page = new BitfieldPage((i + j) / WORDS_PER_PAGE, segment);
|
|
this._pages.set(page.index, page);
|
|
}
|
|
}
|
|
}
|
|
toBuffer(length) {
|
|
const pages = Math.ceil(length / BITS_PER_PAGE);
|
|
const buffer = b4a.allocUnsafe(pages * BYTES_PER_PAGE);
|
|
for (let i = 0; i < pages; i++) {
|
|
const page = this._pages.get(i);
|
|
const offset = i * BYTES_PER_PAGE;
|
|
if (page) {
|
|
const buf = b4a.from(
|
|
page.bitfield.buffer,
|
|
page.bitfield.byteOffset,
|
|
page.bitfield.byteLength
|
|
);
|
|
buffer.set(buf, offset);
|
|
} else {
|
|
buffer.fill(0, offset, offset + BYTES_PER_PAGE);
|
|
}
|
|
}
|
|
return buffer;
|
|
}
|
|
getBitfield(index) {
|
|
const j = index & BITS_PER_PAGE - 1;
|
|
const i = (index - j) / BITS_PER_PAGE;
|
|
const p = this._pages.get(i);
|
|
return p || null;
|
|
}
|
|
get(index) {
|
|
const j = index & BITS_PER_PAGE - 1;
|
|
const i = (index - j) / BITS_PER_PAGE;
|
|
const p = this._pages.get(i);
|
|
return p ? p.get(j) : false;
|
|
}
|
|
set(index, val) {
|
|
const j = index & BITS_PER_PAGE - 1;
|
|
const i = (index - j) / BITS_PER_PAGE;
|
|
let p = this._pages.get(i);
|
|
if (!p && val) {
|
|
const k = Math.floor(i / PAGES_PER_SEGMENT);
|
|
const s = this._segments.get(k) || this._segments.set(k, new BitfieldSegment(k, new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)));
|
|
p = this._pages.set(i, new BitfieldPage(i, s));
|
|
}
|
|
if (p) {
|
|
p.set(j, val);
|
|
if (!p.dirty) {
|
|
p.dirty = true;
|
|
this.unflushed.push(p);
|
|
}
|
|
}
|
|
}
|
|
setRange(start, length, val) {
|
|
let j = start & BITS_PER_PAGE - 1;
|
|
let i = (start - j) / BITS_PER_PAGE;
|
|
while (length > 0) {
|
|
let p = this._pages.get(i);
|
|
if (!p && val) {
|
|
const k = Math.floor(i / PAGES_PER_SEGMENT);
|
|
const s = this._segments.get(k) || this._segments.set(k, new BitfieldSegment(k, new Uint32Array(k === 0 ? INITIAL_WORDS_PER_SEGMENT : WORDS_PER_SEGMENT)));
|
|
p = this._pages.set(i, new BitfieldPage(i, s));
|
|
}
|
|
const end = Math.min(j + length, BITS_PER_PAGE);
|
|
const range = end - j;
|
|
if (p) {
|
|
p.setRange(j, range, val);
|
|
if (!p.dirty) {
|
|
p.dirty = true;
|
|
this.unflushed.push(p);
|
|
}
|
|
}
|
|
j = 0;
|
|
i++;
|
|
length -= range;
|
|
}
|
|
}
|
|
findFirst(val, position) {
|
|
let j = position & BITS_PER_SEGMENT - 1;
|
|
let i = (position - j) / BITS_PER_SEGMENT;
|
|
while (i < this._segments.maxLength) {
|
|
const s = this._segments.get(i);
|
|
let index = -1;
|
|
if (s) index = s.findFirst(val, j);
|
|
else if (!val) index = j;
|
|
if (index !== -1) return i * BITS_PER_SEGMENT + index;
|
|
j = 0;
|
|
i++;
|
|
}
|
|
return val ? -1 : this._segments.maxLength * BITS_PER_SEGMENT;
|
|
}
|
|
firstSet(position) {
|
|
return this.findFirst(true, position);
|
|
}
|
|
firstUnset(position) {
|
|
return this.findFirst(false, position);
|
|
}
|
|
findLast(val, position) {
|
|
let j = position & BITS_PER_SEGMENT - 1;
|
|
let i = (position - j) / BITS_PER_SEGMENT;
|
|
while (i >= 0) {
|
|
const s = this._segments.get(i);
|
|
let index = -1;
|
|
if (s) index = s.findLast(val, j);
|
|
else if (!val) index = j;
|
|
if (index !== -1) return i * BITS_PER_SEGMENT + index;
|
|
j = BITS_PER_SEGMENT - 1;
|
|
i--;
|
|
}
|
|
return -1;
|
|
}
|
|
lastSet(position) {
|
|
return this.findLast(true, position);
|
|
}
|
|
lastUnset(position) {
|
|
return this.findLast(false, position);
|
|
}
|
|
count(start, length, val) {
|
|
let j = start & BITS_PER_PAGE - 1;
|
|
let i = (start - j) / BITS_PER_PAGE;
|
|
let c = 0;
|
|
while (length > 0) {
|
|
const p = this._pages.get(i);
|
|
const end = Math.min(j + length, BITS_PER_PAGE);
|
|
const range = end - j;
|
|
if (p) c += p.count(j, range, val);
|
|
else if (!val) c += range;
|
|
j = 0;
|
|
i++;
|
|
length -= range;
|
|
}
|
|
return c;
|
|
}
|
|
countSet(start, length) {
|
|
return this.count(start, length, true);
|
|
}
|
|
countUnset(start, length) {
|
|
return this.count(start, length, false);
|
|
}
|
|
*want(start, length) {
|
|
const j = start & BITS_PER_SEGMENT - 1;
|
|
let i = (start - j) / BITS_PER_SEGMENT;
|
|
while (length > 0) {
|
|
const s = this._segments.get(i);
|
|
if (s) {
|
|
const end = ceilTo(clamp(length / 8, 4096, BYTES_PER_SEGMENT), 4096);
|
|
yield {
|
|
start: i * BITS_PER_SEGMENT,
|
|
bitfield: s.bitfield.subarray(0, end / 4)
|
|
};
|
|
}
|
|
i++;
|
|
length -= BITS_PER_SEGMENT;
|
|
}
|
|
}
|
|
clear() {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.truncate(0, (err) => {
|
|
if (err) return reject(err);
|
|
this._pages = new BigSparseArray();
|
|
this.unflushed = [];
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
close() {
|
|
return new Promise((resolve, reject) => {
|
|
this.storage.close((err) => {
|
|
if (err) reject(err);
|
|
else resolve();
|
|
});
|
|
});
|
|
}
|
|
flush() {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this.unflushed.length) return resolve();
|
|
const self2 = this;
|
|
let missing = this.unflushed.length;
|
|
let error = null;
|
|
for (const page of this.unflushed) {
|
|
const buf = b4a.from(
|
|
page.bitfield.buffer,
|
|
page.bitfield.byteOffset,
|
|
page.bitfield.byteLength
|
|
);
|
|
page.dirty = false;
|
|
this.storage.write(page.index * BYTES_PER_PAGE, buf, done);
|
|
}
|
|
function done(err) {
|
|
if (err) error = err;
|
|
if (--missing) return;
|
|
if (error) return reject(error);
|
|
self2.unflushed = [];
|
|
resolve();
|
|
}
|
|
});
|
|
}
|
|
static open(storage, tree = null) {
|
|
return new Promise((resolve, reject) => {
|
|
storage.stat((err, st) => {
|
|
if (err) return resolve(new Bitfield(storage, null));
|
|
let size = st.size - (st.size & 3);
|
|
if (!size) return resolve(new Bitfield(storage, null));
|
|
if (tree) size = Math.min(size, ceilTo(tree.length / 8, 4096));
|
|
storage.read(0, size, (err2, data) => {
|
|
if (err2) return reject(err2);
|
|
resolve(new Bitfield(storage, data));
|
|
});
|
|
});
|
|
});
|
|
}
|
|
};
|
|
function clamp(n, min, max) {
|
|
return Math.min(Math.max(n, min), max);
|
|
}
|
|
function ceilTo(n, multiple = 1) {
|
|
const remainder = n % multiple;
|
|
if (remainder === 0) return n;
|
|
return n + multiple - remainder;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/info.js
|
|
var require_info = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/info.js"(exports, module) {
|
|
module.exports = class Info {
|
|
constructor(opts = {}) {
|
|
this.key = opts.key;
|
|
this.discoveryKey = opts.discoveryKey;
|
|
this.length = opts.length || 0;
|
|
this.contiguousLength = opts.contiguousLength || 0;
|
|
this.byteLength = opts.byteLength || 0;
|
|
this.fork = opts.fork || 0;
|
|
this.padding = opts.padding || 0;
|
|
this.storage = opts.storage || null;
|
|
}
|
|
static async from(session, opts = {}) {
|
|
return new Info({
|
|
key: session.key,
|
|
discoveryKey: session.discoveryKey,
|
|
length: session.length,
|
|
contiguousLength: session.contiguousLength,
|
|
byteLength: session.byteLength,
|
|
fork: session.fork,
|
|
padding: session.padding,
|
|
storage: opts.storage ? await this.storage(session) : null
|
|
});
|
|
}
|
|
static async storage(session) {
|
|
const { oplog, tree, blocks, bitfield } = session.core;
|
|
try {
|
|
return {
|
|
oplog: await Info.bytesUsed(oplog.storage),
|
|
tree: await Info.bytesUsed(tree.storage),
|
|
blocks: await Info.bytesUsed(blocks.storage),
|
|
bitfield: await Info.bytesUsed(bitfield.storage)
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
static bytesUsed(file) {
|
|
return new Promise((resolve, reject) => {
|
|
file.stat((err, st) => {
|
|
if (err) {
|
|
resolve(0);
|
|
} else if (typeof st.blocks !== "number") {
|
|
reject(new Error("cannot determine bytes used"));
|
|
} else {
|
|
resolve(st.blocks * 512);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/multisig.js
|
|
var require_multisig = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/multisig.js"(exports, module) {
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var flat = require_flat_tree();
|
|
var { multiSignature, multiSignaturev0 } = require_messages2();
|
|
module.exports = {
|
|
assemblev0,
|
|
assemble,
|
|
inflatev0,
|
|
inflate,
|
|
partialSignature,
|
|
signableLength
|
|
};
|
|
function inflatev0(data) {
|
|
return c.decode(multiSignaturev0, data);
|
|
}
|
|
function inflate(data) {
|
|
return c.decode(multiSignature, data);
|
|
}
|
|
async function partialSignature(tree, signer, from, to = tree.length, signature = tree.signature) {
|
|
if (from > tree.length) return null;
|
|
const nodes = to <= from ? null : await upgradeNodes(tree, from, to);
|
|
if (signature.byteLength !== 64) signature = c.decode(multiSignature, signature).proofs[0].signature;
|
|
return {
|
|
signer,
|
|
signature,
|
|
patch: nodes ? to - from : 0,
|
|
nodes
|
|
};
|
|
}
|
|
async function upgradeNodes(tree, from, to) {
|
|
const p = await tree.proof({ upgrade: { start: from, length: to - from } });
|
|
return p.upgrade.nodes;
|
|
}
|
|
function signableLength(lengths, quorum) {
|
|
if (quorum <= 0) quorum = 1;
|
|
if (quorum > lengths.length) return 0;
|
|
return lengths.sort(cmp)[quorum - 1];
|
|
}
|
|
function cmp(a, b) {
|
|
return b - a;
|
|
}
|
|
function assemblev0(inputs) {
|
|
const proofs = [];
|
|
const patch = [];
|
|
for (const u of inputs) {
|
|
proofs.push(compressProof(u, patch));
|
|
}
|
|
return c.encode(multiSignaturev0, { proofs, patch });
|
|
}
|
|
function assemble(inputs) {
|
|
const proofs = [];
|
|
const patch = [];
|
|
const seen = /* @__PURE__ */ new Set();
|
|
for (const u of inputs) {
|
|
if (u.nodes) {
|
|
for (const node of u.nodes) {
|
|
if (seen.has(node.index)) continue;
|
|
seen.add(node.index);
|
|
patch.push(node);
|
|
}
|
|
}
|
|
proofs.push({
|
|
signer: u.signer,
|
|
signature: u.signature,
|
|
patch: u.patch
|
|
});
|
|
}
|
|
return c.encode(multiSignature, { proofs, patch });
|
|
}
|
|
function compareNode(a, b) {
|
|
if (a.index !== b.index) return false;
|
|
if (a.size !== b.size) return false;
|
|
return b4a.equals(a.hash, b.hash);
|
|
}
|
|
function compressProof(proof, nodes) {
|
|
return {
|
|
signer: proof.signer,
|
|
signature: proof.signature,
|
|
patch: proof.patch ? compressUpgrade(proof, nodes) : null
|
|
};
|
|
}
|
|
function compressUpgrade(p, nodes) {
|
|
const u = {
|
|
start: flat.rightSpan(p.nodes[p.nodes.length - 1].index) / 2 + 1,
|
|
length: p.patch,
|
|
nodes: []
|
|
};
|
|
for (const node of p.nodes) {
|
|
let present = false;
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
if (!compareNode(nodes[i], node)) continue;
|
|
u.nodes.push(i);
|
|
present = true;
|
|
break;
|
|
}
|
|
if (present) continue;
|
|
u.nodes.push(nodes.push(node) - 1);
|
|
}
|
|
return u;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/verifier.js
|
|
var require_verifier = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/verifier.js"(exports, module) {
|
|
var defaultCrypto = require_hypercore_crypto();
|
|
var b4a = require_b4a();
|
|
var c = require_compact_encoding();
|
|
var flat = require_flat_tree();
|
|
var { BAD_ARGUMENT } = require_hypercore_errors();
|
|
var unslab = require_unslab();
|
|
var m = require_messages2();
|
|
var multisig = require_multisig();
|
|
var caps = require_caps();
|
|
var Signer = class {
|
|
constructor(crypto, manifestHash2, version, index, { signature = "ed25519", publicKey, namespace = caps.DEFAULT_NAMESPACE } = {}) {
|
|
if (!publicKey) throw BAD_ARGUMENT("public key is required for a signer");
|
|
if (signature !== "ed25519") throw BAD_ARGUMENT("Only Ed25519 signatures are supported");
|
|
this.crypto = crypto;
|
|
this.manifestHash = manifestHash2;
|
|
this.version = version;
|
|
this.signer = index;
|
|
this.signature = signature;
|
|
this.publicKey = publicKey;
|
|
this.namespace = namespace;
|
|
}
|
|
_ctx() {
|
|
return this.version === 0 ? this.namespace : this.manifestHash;
|
|
}
|
|
verify(batch, signature) {
|
|
return this.crypto.verify(batch.signable(this._ctx()), signature, this.publicKey);
|
|
}
|
|
sign(batch, keyPair) {
|
|
return this.crypto.sign(batch.signable(this._ctx()), keyPair.secretKey);
|
|
}
|
|
};
|
|
var CompatSigner = class extends Signer {
|
|
constructor(crypto, index, signer, legacy) {
|
|
super(crypto, null, 0, index, signer);
|
|
this.legacy = legacy;
|
|
}
|
|
verify(batch, signature) {
|
|
return this.crypto.verify(batch.signableCompat(this.legacy), signature, this.publicKey);
|
|
}
|
|
sign(batch, keyPair) {
|
|
return this.crypto.sign(batch.signableCompat(this.legacy), keyPair.secretKey);
|
|
}
|
|
};
|
|
module.exports = class Verifier {
|
|
constructor(manifestHash2, manifest, { compat = isCompat(manifestHash2, manifest), crypto = defaultCrypto, legacy = false } = {}) {
|
|
const self2 = this;
|
|
this.manifestHash = manifestHash2;
|
|
this.compat = compat || manifest === null;
|
|
this.version = this.compat ? 0 : typeof manifest.version === "number" ? manifest.version : 1;
|
|
this.hash = manifest.hash || "blake2b";
|
|
this.allowPatch = !this.compat && !!manifest.allowPatch;
|
|
this.quorum = this.compat ? 1 : defaultQuorum(manifest);
|
|
this.signers = manifest.signers ? manifest.signers.map(createSigner) : [];
|
|
this.prologue = this.compat ? null : manifest.prologue || null;
|
|
function createSigner(signer, index) {
|
|
return self2.compat ? new CompatSigner(crypto, index, signer, legacy) : new Signer(crypto, manifestHash2, self2.version, index, signer);
|
|
}
|
|
}
|
|
_verifyCompat(batch, signature) {
|
|
if (!signature) return false;
|
|
if (this.compat || !this.allowPatch && this.signers.length === 1) {
|
|
return !!signature && this.signers[0].verify(batch, signature);
|
|
}
|
|
return this._verifyMulti(batch, signature);
|
|
}
|
|
_inflate(signature) {
|
|
if (this.version >= 1) return multisig.inflate(signature);
|
|
const { proofs, patch } = multisig.inflatev0(signature);
|
|
return {
|
|
proofs: proofs.map(proofToVersion1),
|
|
patch
|
|
};
|
|
}
|
|
_verifyMulti(batch, signature) {
|
|
if (!signature || this.quorum === 0) return false;
|
|
const { proofs, patch } = this._inflate(signature);
|
|
if (proofs.length < this.quorum) return false;
|
|
const tried = new Uint8Array(this.signers.length);
|
|
const nodes = this.allowPatch && patch.length ? toMap(patch) : null;
|
|
for (let i = 0; i < this.quorum; i++) {
|
|
const inp = proofs[i];
|
|
let tree = batch;
|
|
if (inp.patch && this.allowPatch) {
|
|
tree = batch.clone();
|
|
const upgrade = generateUpgrade(nodes, batch.length, inp.patch);
|
|
const proof = { fork: tree.fork, block: null, hash: null, seek: null, upgrade, manifest: null };
|
|
try {
|
|
if (!tree.verifyUpgrade(proof)) return false;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
if (inp.signer >= this.signers.length || tried[inp.signer]) return false;
|
|
tried[inp.signer] = 1;
|
|
const s = this.signers[inp.signer];
|
|
if (!s.verify(tree, inp.signature)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
verify(batch, signature) {
|
|
if (this.version !== 1) {
|
|
return this._verifyCompat(batch, signature);
|
|
}
|
|
if (this.prologue !== null && batch.length <= this.prologue.length) {
|
|
return batch.length === this.prologue.length && b4a.equals(batch.hash(), this.prologue.hash);
|
|
}
|
|
return this._verifyMulti(batch, signature);
|
|
}
|
|
// NOTE: better api for this that is more ... multisig-ey
|
|
sign(batch, keyPair) {
|
|
if (!keyPair || !keyPair.secretKey) throw BAD_ARGUMENT("No key pair was passed");
|
|
for (const s of this.signers) {
|
|
if (b4a.equals(s.publicKey, keyPair.publicKey)) {
|
|
const signature = s.sign(batch, keyPair);
|
|
if (this.signers.length !== 1 || this.version === 0) return signature;
|
|
return this.assemble([{ signer: 0, signature, patch: 0, nodes: null }]);
|
|
}
|
|
}
|
|
throw BAD_ARGUMENT("Public key is not a declared signer");
|
|
}
|
|
assemble(inputs) {
|
|
return this.version === 0 ? multisig.assemblev0(inputs) : multisig.assemble(inputs);
|
|
}
|
|
static manifestHash(manifest) {
|
|
return manifestHash(manifest);
|
|
}
|
|
static defaultSignerManifest(publicKey) {
|
|
return {
|
|
version: 1,
|
|
hash: "blake2b",
|
|
allowPatch: false,
|
|
quorum: 1,
|
|
signers: [{
|
|
signature: "ed25519",
|
|
namespace: caps.DEFAULT_NAMESPACE,
|
|
publicKey
|
|
}],
|
|
prologue: null
|
|
};
|
|
}
|
|
static fromManifest(manifest, opts) {
|
|
const m2 = this.createManifest(manifest);
|
|
return new this(manifestHash(m2), m2, opts);
|
|
}
|
|
static createManifest(inp) {
|
|
if (!inp) return null;
|
|
const manifest = {
|
|
version: typeof inp.version === "number" ? inp.version : 1,
|
|
hash: "blake2b",
|
|
allowPatch: !!inp.allowPatch,
|
|
quorum: defaultQuorum(inp),
|
|
signers: inp.signers ? inp.signers.map(parseSigner) : [],
|
|
prologue: null
|
|
};
|
|
if (inp.hash && inp.hash !== "blake2b") throw BAD_ARGUMENT("Only Blake2b hashes are supported");
|
|
if (inp.prologue) {
|
|
if (!(b4a.isBuffer(inp.prologue.hash) && inp.prologue.hash.byteLength === 32) || !(inp.prologue.length >= 0)) {
|
|
throw BAD_ARGUMENT("Invalid prologue");
|
|
}
|
|
manifest.prologue = inp.prologue;
|
|
manifest.prologue.hash = unslab(manifest.prologue.hash);
|
|
}
|
|
return manifest;
|
|
}
|
|
static isValidManifest(key, manifest) {
|
|
return b4a.equals(key, manifestHash(manifest));
|
|
}
|
|
static isCompat(key, manifest) {
|
|
return isCompat(key, manifest);
|
|
}
|
|
static sign(manifest, batch, keyPair, opts) {
|
|
return Verifier.fromManifest(manifest, opts).sign(batch, keyPair);
|
|
}
|
|
};
|
|
function toMap(nodes) {
|
|
const m2 = /* @__PURE__ */ new Map();
|
|
for (const node of nodes) m2.set(node.index, node);
|
|
return m2;
|
|
}
|
|
function isCompat(key, manifest) {
|
|
return !!(manifest && manifest.signers.length === 1 && b4a.equals(key, manifest.signers[0].publicKey));
|
|
}
|
|
function defaultQuorum(man) {
|
|
if (typeof man.quorum === "number") return man.quorum;
|
|
if (!man.signers || !man.signers.length) return 0;
|
|
return (man.signers.length >> 1) + 1;
|
|
}
|
|
function generateUpgrade(patch, start, length) {
|
|
const upgrade = { start, length, nodes: null, additionalNodes: [], signature: null };
|
|
const from = start * 2;
|
|
const to = from + length * 2;
|
|
for (const ite = flat.iterator(0); ite.fullRoot(to); ite.nextTree()) {
|
|
if (ite.index + ite.factor / 2 < from) continue;
|
|
if (upgrade.nodes === null && ite.contains(from - 2)) {
|
|
upgrade.nodes = [];
|
|
const root = ite.index;
|
|
const target = from - 2;
|
|
ite.seek(target);
|
|
while (ite.index !== root) {
|
|
ite.sibling();
|
|
if (ite.index > target) upgrade.nodes.push(patch.get(ite.index));
|
|
ite.parent();
|
|
}
|
|
continue;
|
|
}
|
|
if (upgrade.nodes === null) upgrade.nodes = [];
|
|
upgrade.nodes.push(patch.get(ite.index));
|
|
}
|
|
if (upgrade.nodes === null) upgrade.nodes = [];
|
|
return upgrade;
|
|
}
|
|
function parseSigner(signer) {
|
|
validateSigner(signer);
|
|
return {
|
|
signature: "ed25519",
|
|
namespace: unslab(signer.namespace || caps.DEFAULT_NAMESPACE),
|
|
publicKey: unslab(signer.publicKey)
|
|
};
|
|
}
|
|
function validateSigner(signer) {
|
|
if (!signer || !signer.publicKey) throw BAD_ARGUMENT("Signer missing public key");
|
|
if (signer.signature && signer.signature !== "ed25519") throw BAD_ARGUMENT("Only Ed25519 signatures are supported");
|
|
}
|
|
function manifestHash(manifest) {
|
|
const state = { start: 0, end: 32, buffer: null };
|
|
m.manifest.preencode(state, manifest);
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
c.raw.encode(state, caps.MANIFEST);
|
|
m.manifest.encode(state, manifest);
|
|
return defaultCrypto.hash(state.buffer);
|
|
}
|
|
function proofToVersion1(proof) {
|
|
return {
|
|
signer: proof.signer,
|
|
signature: proof.signature,
|
|
patch: proof.patch ? proof.patch.length : 0
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/audit.js
|
|
var require_audit = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/audit.js"(exports, module) {
|
|
var hypercoreCrypto = require_hypercore_crypto();
|
|
var flat = require_flat_tree();
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var empty = b4a.alloc(32);
|
|
module.exports = async function auditCore(core) {
|
|
const corrections = {
|
|
tree: 0,
|
|
blocks: 0
|
|
};
|
|
const length = core.header.tree.length;
|
|
const data = await readFullStorage(core.blocks.storage);
|
|
const tree = await readFullStorage(core.tree.storage);
|
|
const valid = new Uint8Array(Math.ceil(tree.byteLength / 40));
|
|
const stack = [];
|
|
for (const r of core.tree.roots) {
|
|
valid[r.index] = 1;
|
|
stack.push(r);
|
|
}
|
|
while (stack.length > 0) {
|
|
const node = stack.pop();
|
|
if ((node.index & 1) === 0) continue;
|
|
const [left, right] = flat.children(node.index);
|
|
const leftNode = getNode(left);
|
|
const rightNode = getNode(right);
|
|
if (!rightNode && !leftNode) continue;
|
|
stack.push(leftNode, rightNode);
|
|
if (valid[node.index]) {
|
|
const hash = hypercoreCrypto.parent(leftNode, rightNode);
|
|
if (b4a.equals(hash, node.hash) && node.size === leftNode.size + rightNode.size) {
|
|
valid[leftNode.index] = 1;
|
|
valid[rightNode.index] = 1;
|
|
continue;
|
|
}
|
|
}
|
|
if (leftNode.size) clearNode(leftNode);
|
|
if (rightNode.size) clearNode(rightNode);
|
|
}
|
|
if (corrections.tree) {
|
|
core.tree.cache.clear();
|
|
}
|
|
let i = 0;
|
|
let nextOffset = -1;
|
|
while (i < length) {
|
|
const has = core.bitfield.get(i);
|
|
if (!has) {
|
|
if (i + 1 === length) break;
|
|
i = core.bitfield.findFirst(true, i + 1);
|
|
if (i < 0) break;
|
|
nextOffset = -1;
|
|
continue;
|
|
}
|
|
if (nextOffset === -1) {
|
|
try {
|
|
nextOffset = await core.tree.byteOffset(i * 2);
|
|
} catch {
|
|
core._setBitfield(i, false);
|
|
corrections.blocks++;
|
|
i++;
|
|
continue;
|
|
}
|
|
}
|
|
const node = getNode(i * 2);
|
|
const blk = data.subarray(nextOffset, nextOffset + node.size);
|
|
const hash = hypercoreCrypto.data(blk);
|
|
nextOffset += blk.byteLength;
|
|
if (!b4a.equals(hash, node.hash)) {
|
|
core._setBitfield(i, false);
|
|
corrections.blocks++;
|
|
}
|
|
i++;
|
|
}
|
|
return corrections;
|
|
function getNode(index) {
|
|
if (index * 40 + 40 > tree.byteLength) return null;
|
|
const state = { start: index * 40, end: index * 40 + 40, buffer: tree };
|
|
const size = c.uint64.decode(state);
|
|
const hash = c.fixed32.decode(state);
|
|
if (size === 0 && hash.equals(empty)) return null;
|
|
return { index, size, hash };
|
|
}
|
|
function clearNode(node) {
|
|
valid[node.index] = 0;
|
|
if (node.size) {
|
|
b4a.fill(tree, 0, node.index * 40, node.index * 40 + 40);
|
|
core.tree.unflushed.set(node.index, core.tree.blankNode(node.index));
|
|
corrections.tree++;
|
|
}
|
|
}
|
|
};
|
|
function readFullStorage(storage) {
|
|
return new Promise((resolve, reject) => {
|
|
storage.stat((_, st) => {
|
|
if (!st) return resolve(b4a.alloc(0));
|
|
storage.read(0, st.size, (err, data) => {
|
|
if (err) reject(err);
|
|
else resolve(data);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/core.js
|
|
var require_core = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/core.js"(exports, module) {
|
|
var hypercoreCrypto = require_hypercore_crypto();
|
|
var b4a = require_b4a();
|
|
var unslab = require_unslab();
|
|
var Oplog = require_oplog();
|
|
var BigHeader = require_big_header();
|
|
var Mutex = require_mutex();
|
|
var MerkleTree = require_merkle_tree();
|
|
var BlockStore = require_block_store();
|
|
var Bitfield = require_bitfield();
|
|
var RemoteBitfield = require_remote_bitfield();
|
|
var Info = require_info();
|
|
var { BAD_ARGUMENT, STORAGE_EMPTY, STORAGE_CONFLICT, INVALID_OPERATION, INVALID_SIGNATURE, INVALID_CHECKSUM } = require_hypercore_errors();
|
|
var m = require_messages2();
|
|
var Verifier = require_verifier();
|
|
var audit = require_audit();
|
|
module.exports = class Core {
|
|
constructor(header, compat, crypto, oplog, bigHeader, tree, blocks, bitfield, verifier, sessions, legacy, globalCache, onupdate, onconflict) {
|
|
this.onupdate = onupdate;
|
|
this.onconflict = onconflict;
|
|
this.preupdate = null;
|
|
this.header = header;
|
|
this.compat = compat;
|
|
this.crypto = crypto;
|
|
this.oplog = oplog;
|
|
this.bigHeader = bigHeader;
|
|
this.tree = tree;
|
|
this.blocks = blocks;
|
|
this.bitfield = bitfield;
|
|
this.verifier = verifier;
|
|
this.truncating = 0;
|
|
this.updating = false;
|
|
this.closed = false;
|
|
this.skipBitfield = null;
|
|
this.active = sessions.length;
|
|
this.sessions = sessions;
|
|
this.globalCache = globalCache;
|
|
this._manifestFlushed = !!header.manifest;
|
|
this._maxOplogSize = 65536;
|
|
this._autoFlush = 1;
|
|
this._verifies = null;
|
|
this._verifiesFlushed = null;
|
|
this._mutex = new Mutex();
|
|
this._legacy = legacy;
|
|
}
|
|
static async open(storage, opts = {}) {
|
|
const oplogFile = storage("oplog");
|
|
const treeFile = storage("tree");
|
|
const bitfieldFile = storage("bitfield");
|
|
const dataFile = storage("data");
|
|
const headerFile = storage("header");
|
|
try {
|
|
return await this.resume(oplogFile, treeFile, bitfieldFile, dataFile, headerFile, opts);
|
|
} catch (err) {
|
|
await closeAll(oplogFile, treeFile, bitfieldFile, dataFile, headerFile);
|
|
throw err;
|
|
}
|
|
}
|
|
static async resume(oplogFile, treeFile, bitfieldFile, dataFile, headerFile, opts) {
|
|
let overwrite = opts.overwrite === true;
|
|
const force = opts.force === true;
|
|
const createIfMissing = opts.createIfMissing !== false;
|
|
const crypto = opts.crypto || hypercoreCrypto;
|
|
const legacy = !!opts.legacy;
|
|
const oplog = new Oplog(oplogFile, {
|
|
headerEncoding: m.oplog.header,
|
|
entryEncoding: m.oplog.entry,
|
|
readonly: opts.readonly
|
|
});
|
|
let compat = opts.compat === true || opts.compat !== false && !opts.manifest;
|
|
let { header, entries } = await oplog.open();
|
|
if (force && opts.key && header && !b4a.equals(header.key, opts.key)) {
|
|
overwrite = true;
|
|
}
|
|
const bigHeader = new BigHeader(headerFile);
|
|
if (!header || overwrite) {
|
|
if (!createIfMissing) {
|
|
throw STORAGE_EMPTY("No Hypercore is stored here");
|
|
}
|
|
if (compat) {
|
|
if (opts.key && opts.keyPair && !b4a.equals(opts.key, opts.keyPair.publicKey)) {
|
|
throw BAD_ARGUMENT("Key must match publicKey when in compat mode");
|
|
}
|
|
}
|
|
const keyPair = opts.keyPair || (opts.key ? null : crypto.keyPair());
|
|
const defaultManifest = !opts.manifest && (!!opts.compat || !opts.key || !!(keyPair && b4a.equals(opts.key, keyPair.publicKey)));
|
|
const manifest = defaultManifest ? Verifier.defaultSignerManifest(opts.key || keyPair.publicKey) : Verifier.createManifest(opts.manifest);
|
|
header = {
|
|
external: null,
|
|
key: opts.key || (compat ? manifest.signers[0].publicKey : Verifier.manifestHash(manifest)),
|
|
manifest,
|
|
keyPair: keyPair ? { publicKey: keyPair.publicKey, secretKey: keyPair.secretKey || null } : null,
|
|
userData: [],
|
|
tree: {
|
|
fork: 0,
|
|
length: 0,
|
|
rootHash: null,
|
|
signature: null
|
|
},
|
|
hints: {
|
|
reorgs: [],
|
|
contiguousLength: 0
|
|
}
|
|
};
|
|
await flushHeader(oplog, bigHeader, header);
|
|
} else if (header.external) {
|
|
header = await bigHeader.load(header.external);
|
|
}
|
|
header.key = unslab(header.key);
|
|
header.tree.rootHash = unslab(header.tree.rootHash);
|
|
header.tree.signature = unslab(header.tree.signature);
|
|
if (header.keyPair) {
|
|
header.keyPair.publicKey = unslab(header.keyPair.publicKey);
|
|
header.keyPair.secretKey = unslab(header.keyPair.secretKey);
|
|
}
|
|
if (opts.manifest) {
|
|
if (!opts.key && !Verifier.isValidManifest(header.key, Verifier.createManifest(opts.manifest))) {
|
|
throw STORAGE_CONFLICT("Manifest does not hash to provided key");
|
|
}
|
|
if (!header.manifest) header.manifest = opts.manifest;
|
|
}
|
|
if (opts.key && !b4a.equals(header.key, opts.key)) {
|
|
throw STORAGE_CONFLICT("Another Hypercore is stored here");
|
|
}
|
|
if (compat && header.manifest && !Verifier.isCompat(header.key, header.manifest)) {
|
|
compat = false;
|
|
} else if (!compat && header.manifest && Verifier.isCompat(header.key, header.manifest)) {
|
|
compat = true;
|
|
}
|
|
const prologue = header.manifest ? header.manifest.prologue : null;
|
|
const tree = await MerkleTree.open(treeFile, { crypto, prologue, ...header.tree });
|
|
const bitfield = await Bitfield.open(bitfieldFile);
|
|
const blocks = new BlockStore(dataFile, tree);
|
|
if (overwrite) {
|
|
await tree.clear();
|
|
await blocks.clear();
|
|
await bitfield.clear();
|
|
entries = [];
|
|
}
|
|
if (header.hints.contiguousLength === 0) {
|
|
while (bitfield.get(header.hints.contiguousLength)) header.hints.contiguousLength++;
|
|
}
|
|
if (header.manifest) header.manifest = Verifier.createManifest(header.manifest);
|
|
const verifier = header.manifest ? new Verifier(header.key, header.manifest, { crypto, legacy }) : null;
|
|
for (const e of entries) {
|
|
if (e.userData) {
|
|
updateUserData(header.userData, e.userData.key, e.userData.value);
|
|
}
|
|
if (e.treeNodes) {
|
|
for (const node of e.treeNodes) {
|
|
tree.addNode(node);
|
|
}
|
|
}
|
|
if (e.bitfield) {
|
|
bitfield.setRange(e.bitfield.start, e.bitfield.length, !e.bitfield.drop);
|
|
updateContig(header, e.bitfield, bitfield);
|
|
}
|
|
if (e.treeUpgrade) {
|
|
const batch = await tree.truncate(e.treeUpgrade.length, e.treeUpgrade.fork);
|
|
batch.ancestors = e.treeUpgrade.ancestors;
|
|
batch.signature = unslab(e.treeUpgrade.signature);
|
|
addReorgHint(header.hints.reorgs, tree, batch);
|
|
batch.commit();
|
|
header.tree.length = tree.length;
|
|
header.tree.fork = tree.fork;
|
|
header.tree.rootHash = tree.hash();
|
|
header.tree.signature = tree.signature;
|
|
}
|
|
}
|
|
for (const entry of header.userData) {
|
|
entry.value = unslab(entry.value);
|
|
}
|
|
return new this(header, compat, crypto, oplog, bigHeader, tree, blocks, bitfield, verifier, opts.sessions || [], legacy, opts.globalCache || null, opts.onupdate || noop, opts.onconflict || noop);
|
|
}
|
|
async audit() {
|
|
await this._mutex.lock();
|
|
try {
|
|
await this._flushOplog();
|
|
const corrections = await audit(this);
|
|
if (corrections.blocks || corrections.tree) await this._flushOplog();
|
|
return corrections;
|
|
} finally {
|
|
await this._mutex.unlock();
|
|
}
|
|
}
|
|
async setManifest(manifest) {
|
|
await this._mutex.lock();
|
|
try {
|
|
if (manifest && this.header.manifest === null) {
|
|
if (!Verifier.isValidManifest(this.header.key, manifest)) throw INVALID_CHECKSUM("Manifest hash does not match");
|
|
this._setManifest(Verifier.createManifest(manifest), null);
|
|
await this._flushOplog();
|
|
}
|
|
} finally {
|
|
this._mutex.unlock();
|
|
}
|
|
}
|
|
_setManifest(manifest, keyPair) {
|
|
if (!manifest && b4a.equals(keyPair.publicKey, this.header.key)) manifest = Verifier.defaultSignerManifest(this.header.key);
|
|
if (!manifest) return;
|
|
const verifier = new Verifier(this.header.key, manifest, { crypto: this.crypto, legacy: this._legacy });
|
|
if (verifier.prologue) this.tree.setPrologue(verifier.prologue);
|
|
this.header.manifest = manifest;
|
|
this.compat = verifier.compat;
|
|
this.verifier = verifier;
|
|
this._manifestFlushed = false;
|
|
this.onupdate(16, null, null, null);
|
|
}
|
|
_shouldFlush() {
|
|
if (--this._autoFlush <= 0 || this.oplog.byteLength >= this._maxOplogSize) {
|
|
this._autoFlush = 4;
|
|
return true;
|
|
}
|
|
if (!this._manifestFlushed && this.header.manifest) {
|
|
this._manifestFlushed = true;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
async copyPrologue(src, { additional = [] } = {}) {
|
|
await this._mutex.lock();
|
|
try {
|
|
await src._mutex.lock();
|
|
} catch (err) {
|
|
this._mutex.unlock();
|
|
throw err;
|
|
}
|
|
try {
|
|
const prologue = this.header.manifest && this.header.manifest.prologue;
|
|
if (!prologue) throw INVALID_OPERATION("No prologue present");
|
|
const srcLength = prologue.length - additional.length;
|
|
const srcBatch = srcLength !== src.tree.length ? await src.tree.truncate(srcLength) : src.tree.batch();
|
|
const srcRoots = srcBatch.roots.slice(0);
|
|
const srcByteLength = srcBatch.byteLength;
|
|
for (const blk of additional) srcBatch.append(blk);
|
|
if (!b4a.equals(srcBatch.hash(), prologue.hash)) throw INVALID_OPERATION("Source tree is conflicting");
|
|
const entry = {
|
|
userData: null,
|
|
treeNodes: srcRoots,
|
|
treeUpgrade: null,
|
|
bitfield: null
|
|
};
|
|
if (additional.length) {
|
|
await this.blocks.putBatch(srcLength, additional, srcByteLength);
|
|
entry.treeNodes = entry.treeNodes.concat(srcBatch.nodes);
|
|
entry.bitfield = {
|
|
drop: false,
|
|
start: srcLength,
|
|
length: additional.length
|
|
};
|
|
}
|
|
await this.oplog.append([entry], false);
|
|
this.tree.addNodes(entry.treeNodes);
|
|
if (this.header.tree.length < srcBatch.length) {
|
|
this.header.tree.length = srcBatch.length;
|
|
this.header.tree.rootHash = srcBatch.hash();
|
|
this.tree.length = srcBatch.length;
|
|
this.tree.byteLength = srcBatch.byteLength;
|
|
this.tree.roots = srcBatch.roots;
|
|
this.onupdate(1, null, null, null);
|
|
}
|
|
if (entry.bitfield) {
|
|
this._setBitfieldRange(entry.bitfield.start, entry.bitfield.length, true);
|
|
this.onupdate(0, entry.bitfield, null, null);
|
|
}
|
|
await this._flushOplog();
|
|
let segmentEnd = 0;
|
|
while (segmentEnd < srcLength) {
|
|
const segmentStart = maximumSegmentStart(segmentEnd, src.bitfield, this.bitfield);
|
|
if (segmentStart >= srcLength || segmentStart < 0) break;
|
|
segmentEnd = Math.min(segmentStart + 65536, srcLength, minimumSegmentEnd(segmentStart, src.bitfield, this.bitfield));
|
|
const treeNodes = await src.tree.getNeededNodes(srcLength, segmentStart, segmentEnd);
|
|
const bitfield = {
|
|
drop: false,
|
|
start: segmentStart,
|
|
length: segmentEnd - segmentStart
|
|
};
|
|
const segment = [];
|
|
for (let i = segmentStart; i < segmentEnd; i++) {
|
|
const blk = await src.blocks.get(i);
|
|
segment.push(blk);
|
|
}
|
|
const offset = await src.tree.byteOffset(2 * segmentStart);
|
|
await this.blocks.putBatch(segmentStart, segment, offset);
|
|
const entry2 = {
|
|
userData: null,
|
|
treeNodes,
|
|
treeUpgrade: null,
|
|
bitfield
|
|
};
|
|
await this.oplog.append([entry2], false);
|
|
this.tree.addNodes(treeNodes);
|
|
this._setBitfieldRange(bitfield.start, bitfield.length, true);
|
|
this.onupdate(0, bitfield, null, null);
|
|
await this._flushOplog();
|
|
}
|
|
this.header.userData = src.header.userData.slice(0);
|
|
const contig = Math.min(src.header.hints.contiguousLength, srcBatch.length);
|
|
if (this.header.hints.contiguousLength < contig) this.header.hints.contiguousLength = contig;
|
|
await this._flushOplog();
|
|
} finally {
|
|
src._mutex.unlock();
|
|
this._mutex.unlock();
|
|
}
|
|
}
|
|
async flush() {
|
|
await this._mutex.lock();
|
|
try {
|
|
this._manifestFlushed = true;
|
|
this._autoFlush = 4;
|
|
await this._flushOplog();
|
|
} finally {
|
|
this._mutex.unlock();
|
|
}
|
|
}
|
|
async _flushOplog() {
|
|
await this.bitfield.flush();
|
|
await this.tree.flush();
|
|
return flushHeader(this.oplog, this.bigHeader, this.header);
|
|
}
|
|
_appendBlocks(values) {
|
|
return this.blocks.putBatch(this.tree.length, values, this.tree.byteLength);
|
|
}
|
|
async _writeBlock(batch, index, value) {
|
|
const byteOffset = await batch.byteOffset(index * 2);
|
|
await this.blocks.put(index, value, byteOffset);
|
|
}
|
|
async userData(key, value, flush) {
|
|
await this._mutex.lock();
|
|
try {
|
|
let empty = true;
|
|
for (const u of this.header.userData) {
|
|
if (u.key !== key) continue;
|
|
if (value && b4a.equals(u.value, value)) return;
|
|
empty = false;
|
|
break;
|
|
}
|
|
if (empty && !value) return;
|
|
const entry = {
|
|
userData: { key, value },
|
|
treeNodes: null,
|
|
treeUpgrade: null,
|
|
bitfield: null
|
|
};
|
|
await this.oplog.append([entry], false);
|
|
updateUserData(this.header.userData, key, value);
|
|
if (this._shouldFlush() || flush) await this._flushOplog();
|
|
} finally {
|
|
this._mutex.unlock();
|
|
}
|
|
}
|
|
async truncate(length, fork, { signature, keyPair = this.header.keyPair } = {}) {
|
|
if (this.tree.prologue && length < this.tree.prologue.length) {
|
|
throw INVALID_OPERATION("Truncation breaks prologue");
|
|
}
|
|
this.truncating++;
|
|
await this._mutex.lock();
|
|
if (this.verifier === null && keyPair) this._setManifest(null, keyPair);
|
|
try {
|
|
const batch = await this.tree.truncate(length, fork);
|
|
if (length > 0) batch.signature = signature || this.verifier.sign(batch, keyPair);
|
|
await this._truncate(batch, null);
|
|
} finally {
|
|
this.truncating--;
|
|
this._mutex.unlock();
|
|
}
|
|
}
|
|
async clearBatch() {
|
|
await this._mutex.lock();
|
|
try {
|
|
const len = this.bitfield.findFirst(false, this.tree.length);
|
|
if (len <= this.tree.length) return;
|
|
const batch = await this.tree.truncate(this.tree.length, this.tree.fork);
|
|
batch.signature = this.tree.signature;
|
|
const entry = {
|
|
userData: null,
|
|
treeNodes: batch.nodes,
|
|
treeUpgrade: batch,
|
|
bitfield: {
|
|
drop: true,
|
|
start: batch.ancestors,
|
|
length: len - batch.ancestors
|
|
}
|
|
};
|
|
await this.oplog.append([entry], false);
|
|
this._setBitfieldRange(batch.ancestors, len - batch.ancestors, false);
|
|
batch.commit();
|
|
await this._flushOplog();
|
|
} finally {
|
|
this._mutex.unlock();
|
|
}
|
|
}
|
|
async clear(start, end, cleared) {
|
|
await this._mutex.lock();
|
|
try {
|
|
const entry = {
|
|
userData: null,
|
|
treeNodes: null,
|
|
treeUpgrade: null,
|
|
bitfield: {
|
|
start,
|
|
length: end - start,
|
|
drop: true
|
|
}
|
|
};
|
|
await this.oplog.append([entry], false);
|
|
this._setBitfieldRange(start, end - start, false);
|
|
if (start < this.header.hints.contiguousLength) {
|
|
this.header.hints.contiguousLength = start;
|
|
}
|
|
start = this.bitfield.lastSet(start) + 1;
|
|
end = this.bitfield.firstSet(end);
|
|
if (end === -1) end = this.tree.length;
|
|
if (start >= end || start >= this.tree.length) return;
|
|
const offset = await this.tree.byteOffset(start * 2);
|
|
const endOffset = await this.tree.byteOffset(end * 2);
|
|
const length = endOffset - offset;
|
|
const before = cleared ? await Info.bytesUsed(this.blocks.storage) : null;
|
|
await this.blocks.clear(offset, length);
|
|
const after = cleared ? await Info.bytesUsed(this.blocks.storage) : null;
|
|
if (cleared) cleared.blocks = Math.max(before - after, 0);
|
|
this.onupdate(0, entry.bitfield, null, null);
|
|
if (this._shouldFlush()) await this._flushOplog();
|
|
} finally {
|
|
this._mutex.unlock();
|
|
}
|
|
}
|
|
async purge() {
|
|
return new Promise((resolve, reject) => {
|
|
let missing = 4;
|
|
let error = null;
|
|
this.oplog.storage.unlink(done);
|
|
this.tree.storage.unlink(done);
|
|
this.bitfield.storage.unlink(done);
|
|
this.blocks.storage.unlink(done);
|
|
function done(err) {
|
|
if (err) error = err;
|
|
if (--missing) return;
|
|
if (error) reject(error);
|
|
else resolve();
|
|
}
|
|
});
|
|
}
|
|
async insertBatch(batch, values, { signature, keyPair = this.header.keyPair, pending = false, treeLength = batch.treeLength } = {}) {
|
|
await this._mutex.lock();
|
|
try {
|
|
if (this.verifier === null && keyPair) this._setManifest(null, keyPair);
|
|
if (this.tree.fork !== batch.fork) return null;
|
|
if (this.tree.length > batch.treeLength) {
|
|
if (this.tree.length > batch.length) return null;
|
|
for (const root of this.tree.roots) {
|
|
const batchRoot = await batch.get(root.index);
|
|
if (batchRoot.size !== root.size || !b4a.equals(batchRoot.hash, root.hash)) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
const adding = batch.length - treeLength;
|
|
batch.upgraded = !pending && batch.length > this.tree.length;
|
|
batch.treeLength = this.tree.length;
|
|
batch.ancestors = this.tree.length;
|
|
if (batch.upgraded && !pending) batch.signature = signature || this.verifier.sign(batch, keyPair);
|
|
let byteOffset = batch.byteLength;
|
|
for (let i = 0; i < adding; i++) byteOffset -= values[i].byteLength;
|
|
if (pending === true) batch.upgraded = false;
|
|
const entry = {
|
|
userData: null,
|
|
treeNodes: batch.nodes,
|
|
treeUpgrade: batch.upgraded ? batch : null,
|
|
bitfield: {
|
|
drop: false,
|
|
start: treeLength,
|
|
length: adding
|
|
}
|
|
};
|
|
await this.blocks.putBatch(treeLength, adding < values.length ? values.slice(0, adding) : values, byteOffset);
|
|
await this.oplog.append([entry], false);
|
|
this._setBitfieldRange(entry.bitfield.start, entry.bitfield.length, true);
|
|
batch.commit();
|
|
if (batch.upgraded) {
|
|
this.header.tree.length = batch.length;
|
|
this.header.tree.rootHash = batch.hash();
|
|
this.header.tree.signature = batch.signature;
|
|
}
|
|
const status = (batch.upgraded ? 1 : 0) | updateContig(this.header, entry.bitfield, this.bitfield);
|
|
if (!pending) {
|
|
if (entry.treeUpgrade && treeLength > batch.treeLength) {
|
|
entry.bitfield.start = batch.treeLength;
|
|
entry.bitfield.length = treeLength - batch.treeLength;
|
|
}
|
|
this.onupdate(status, entry.bitfield, null, null);
|
|
}
|
|
if (this._shouldFlush()) await this._flushOplog();
|
|
} finally {
|
|
this._mutex.unlock();
|
|
}
|
|
return { length: batch.length, byteLength: batch.byteLength };
|
|
}
|
|
async append(values, { signature, keyPair = this.header.keyPair, preappend } = {}) {
|
|
await this._mutex.lock();
|
|
try {
|
|
if (this.verifier === null && keyPair) this._setManifest(null, keyPair);
|
|
if (preappend) await preappend(values);
|
|
if (!values.length) {
|
|
return { length: this.tree.length, byteLength: this.tree.byteLength };
|
|
}
|
|
const batch = this.tree.batch();
|
|
for (const val of values) batch.append(val);
|
|
if (this.tree.prologue && batch.length < this.tree.prologue.length) {
|
|
throw INVALID_OPERATION("Append is not consistent with prologue");
|
|
}
|
|
batch.signature = signature || this.verifier.sign(batch, keyPair);
|
|
const entry = {
|
|
userData: null,
|
|
treeNodes: batch.nodes,
|
|
treeUpgrade: batch,
|
|
bitfield: {
|
|
drop: false,
|
|
start: batch.ancestors,
|
|
length: values.length
|
|
}
|
|
};
|
|
const byteLength = await this._appendBlocks(values);
|
|
await this.oplog.append([entry], false);
|
|
this._setBitfieldRange(batch.ancestors, batch.length - batch.ancestors, true);
|
|
batch.commit();
|
|
this.header.tree.length = batch.length;
|
|
this.header.tree.rootHash = batch.hash();
|
|
this.header.tree.signature = batch.signature;
|
|
const status = 1 | updateContig(this.header, entry.bitfield, this.bitfield);
|
|
this.onupdate(status, entry.bitfield, null, null);
|
|
if (this._shouldFlush()) await this._flushOplog();
|
|
return { length: batch.length, byteLength };
|
|
} finally {
|
|
this._mutex.unlock();
|
|
}
|
|
}
|
|
_verifyBatchUpgrade(batch, manifest) {
|
|
if (!this.header.manifest) {
|
|
if (!manifest && this.compat) manifest = Verifier.defaultSignerManifest(this.header.key);
|
|
if (!manifest || !(Verifier.isValidManifest(this.header.key, manifest) || this.compat && Verifier.isCompat(this.header.key, manifest))) {
|
|
throw INVALID_SIGNATURE("Proof contains an invalid manifest");
|
|
}
|
|
}
|
|
manifest = Verifier.createManifest(manifest);
|
|
const verifier = this.verifier || new Verifier(this.header.key, manifest, { crypto: this.crypto, legacy: this._legacy });
|
|
if (!verifier.verify(batch, batch.signature)) {
|
|
throw INVALID_SIGNATURE("Proof contains an invalid signature");
|
|
}
|
|
if (!this.header.manifest) {
|
|
this.header.manifest = manifest;
|
|
this.compat = verifier.compat;
|
|
this.verifier = verifier;
|
|
this.onupdate(16, null, null, null);
|
|
}
|
|
}
|
|
async _verifyExclusive({ batch, bitfield, value, manifest, from }) {
|
|
this._verifyBatchUpgrade(batch, manifest);
|
|
await this._mutex.lock();
|
|
try {
|
|
if (!batch.commitable()) return false;
|
|
this.updating = true;
|
|
const entry = {
|
|
userData: null,
|
|
treeNodes: batch.nodes,
|
|
treeUpgrade: batch,
|
|
bitfield
|
|
};
|
|
if (this.preupdate !== null) await this.preupdate(batch, this.header.key);
|
|
if (bitfield) await this._writeBlock(batch, bitfield.start, value);
|
|
await this.oplog.append([entry], false);
|
|
let status = 1;
|
|
if (bitfield) {
|
|
this._setBitfield(bitfield.start, true);
|
|
status |= updateContig(this.header, bitfield, this.bitfield);
|
|
}
|
|
batch.commit();
|
|
this.header.tree.fork = batch.fork;
|
|
this.header.tree.length = batch.length;
|
|
this.header.tree.rootHash = batch.hash();
|
|
this.header.tree.signature = batch.signature;
|
|
this.onupdate(status, bitfield, value, from);
|
|
if (this._shouldFlush()) await this._flushOplog();
|
|
} finally {
|
|
this.updating = false;
|
|
this._mutex.unlock();
|
|
}
|
|
return true;
|
|
}
|
|
async _verifyShared() {
|
|
if (!this._verifies.length) return false;
|
|
await this._mutex.lock();
|
|
const verifies = this._verifies;
|
|
this._verifies = null;
|
|
this._verified = null;
|
|
try {
|
|
const entries = [];
|
|
for (const { batch, bitfield, value } of verifies) {
|
|
if (!batch.commitable()) continue;
|
|
if (bitfield) {
|
|
await this._writeBlock(batch, bitfield.start, value);
|
|
}
|
|
entries.push({
|
|
userData: null,
|
|
treeNodes: batch.nodes,
|
|
treeUpgrade: null,
|
|
bitfield
|
|
});
|
|
}
|
|
await this.oplog.append(entries, false);
|
|
for (let i = 0; i < verifies.length; i++) {
|
|
const { batch, bitfield, value, manifest, from } = verifies[i];
|
|
if (!batch.commitable()) {
|
|
verifies[i] = null;
|
|
continue;
|
|
}
|
|
let status = 0;
|
|
if (bitfield) {
|
|
this._setBitfield(bitfield.start, true);
|
|
status = updateContig(this.header, bitfield, this.bitfield);
|
|
}
|
|
if (manifest && this.header.manifest === null) {
|
|
if (!Verifier.isValidManifest(this.header.key, manifest)) throw INVALID_CHECKSUM("Manifest hash does not match");
|
|
this._setManifest(manifest, null);
|
|
}
|
|
batch.commit();
|
|
this.onupdate(status, bitfield, value, from);
|
|
}
|
|
if (this._shouldFlush()) await this._flushOplog();
|
|
} finally {
|
|
this._mutex.unlock();
|
|
}
|
|
return verifies[0] !== null;
|
|
}
|
|
async checkConflict(proof, from) {
|
|
if (this.tree.length < proof.upgrade.length || proof.fork !== this.tree.fork) {
|
|
return false;
|
|
}
|
|
const batch = this.tree.verifyFullyRemote(proof);
|
|
try {
|
|
this._verifyBatchUpgrade(batch, proof.manifest);
|
|
} catch {
|
|
return true;
|
|
}
|
|
const remoteTreeHash = this.crypto.tree(proof.upgrade.nodes);
|
|
const localTreeHash = this.crypto.tree(await this.tree.getRoots(proof.upgrade.length));
|
|
if (b4a.equals(localTreeHash, remoteTreeHash)) return false;
|
|
await this.onconflict(proof);
|
|
return true;
|
|
}
|
|
async verifyReorg(proof) {
|
|
const batch = await this.tree.reorg(proof);
|
|
this._verifyBatchUpgrade(batch, proof.manifest);
|
|
return batch;
|
|
}
|
|
async verify(proof, from) {
|
|
if (proof.fork !== this.tree.fork) return false;
|
|
const batch = await this.tree.verify(proof);
|
|
if (!batch.commitable()) return false;
|
|
const value = proof.block && proof.block.value || null;
|
|
const op = {
|
|
batch,
|
|
bitfield: value && { drop: false, start: proof.block.index, length: 1 },
|
|
value,
|
|
manifest: proof.manifest,
|
|
from
|
|
};
|
|
if (batch.upgraded) return this._verifyExclusive(op);
|
|
if (this._verifies !== null) {
|
|
const verifies = this._verifies;
|
|
const i = verifies.push(op);
|
|
await this._verified;
|
|
return verifies[i] !== null;
|
|
}
|
|
this._verifies = [op];
|
|
this._verified = this._verifyShared();
|
|
return this._verified;
|
|
}
|
|
async reorg(batch, from) {
|
|
if (!batch.commitable()) return false;
|
|
this.truncating++;
|
|
await this._mutex.lock();
|
|
try {
|
|
if (!batch.commitable()) return false;
|
|
await this._truncate(batch, from);
|
|
} finally {
|
|
this.truncating--;
|
|
this._mutex.unlock();
|
|
}
|
|
return true;
|
|
}
|
|
async _truncate(batch, from) {
|
|
const entry = {
|
|
userData: null,
|
|
treeNodes: batch.nodes,
|
|
treeUpgrade: batch,
|
|
bitfield: {
|
|
drop: true,
|
|
start: batch.ancestors,
|
|
length: this.tree.length - batch.ancestors
|
|
}
|
|
};
|
|
await this.oplog.append([entry], false);
|
|
this._setBitfieldRange(batch.ancestors, this.tree.length - batch.ancestors, false);
|
|
addReorgHint(this.header.hints.reorgs, this.tree, batch);
|
|
batch.commit();
|
|
const contigStatus = updateContig(this.header, entry.bitfield, this.bitfield);
|
|
const status = (batch.length > batch.ancestors ? 3 : 2) | contigStatus;
|
|
this.header.tree.fork = batch.fork;
|
|
this.header.tree.length = batch.length;
|
|
this.header.tree.rootHash = batch.hash();
|
|
this.header.tree.signature = batch.signature;
|
|
this.onupdate(status, entry.bitfield, null, from);
|
|
await this._flushOplog();
|
|
}
|
|
openSkipBitfield() {
|
|
if (this.skipBitfield !== null) return this.skipBitfield;
|
|
this.skipBitfield = new RemoteBitfield();
|
|
const buf = this.bitfield.toBuffer(this.tree.length);
|
|
const bitfield = new Uint32Array(buf.buffer, buf.byteOffset, buf.byteLength / 4);
|
|
this.skipBitfield.insert(0, bitfield);
|
|
return this.skipBitfield;
|
|
}
|
|
_setBitfield(index, value) {
|
|
this.bitfield.set(index, value);
|
|
if (this.skipBitfield !== null) this.skipBitfield.set(index, value);
|
|
}
|
|
_setBitfieldRange(start, length, value) {
|
|
this.bitfield.setRange(start, length, value);
|
|
if (this.skipBitfield !== null) this.skipBitfield.setRange(start, length, value);
|
|
}
|
|
async close() {
|
|
this.closed = true;
|
|
await this._mutex.destroy();
|
|
await Promise.allSettled([
|
|
this.oplog.close(),
|
|
this.bitfield.close(),
|
|
this.tree.close(),
|
|
this.blocks.close(),
|
|
this.bigHeader.close()
|
|
]);
|
|
}
|
|
};
|
|
function updateContig(header, upd, bitfield) {
|
|
const end = upd.start + upd.length;
|
|
let c = header.hints.contiguousLength;
|
|
if (upd.drop) {
|
|
if (c <= end && c > upd.start) {
|
|
c = upd.start;
|
|
}
|
|
} else {
|
|
if (c <= end && c >= upd.start) {
|
|
c = end;
|
|
while (bitfield.get(c)) c++;
|
|
}
|
|
}
|
|
if (c === header.hints.contiguousLength) {
|
|
return 0;
|
|
}
|
|
if (c > header.hints.contiguousLength) {
|
|
header.hints.contiguousLength = c;
|
|
return 4;
|
|
}
|
|
header.hints.contiguousLength = c;
|
|
return 8;
|
|
}
|
|
function addReorgHint(list, tree, batch) {
|
|
if (tree.length === 0 || tree.fork === batch.fork) return;
|
|
while (list.length >= 4) list.shift();
|
|
while (list.length > 0) {
|
|
if (list[list.length - 1].ancestors > batch.ancestors) list.pop();
|
|
else break;
|
|
}
|
|
list.push({ from: tree.fork, to: batch.fork, ancestors: batch.ancestors });
|
|
}
|
|
function updateUserData(list, key, value) {
|
|
value = unslab(value);
|
|
for (let i = 0; i < list.length; i++) {
|
|
if (list[i].key === key) {
|
|
if (value) list[i].value = value;
|
|
else list.splice(i, 1);
|
|
return;
|
|
}
|
|
}
|
|
if (value) list.push({ key, value });
|
|
}
|
|
function closeAll(...storages) {
|
|
let missing = 1;
|
|
let error = null;
|
|
return new Promise((resolve, reject) => {
|
|
for (const s of storages) {
|
|
missing++;
|
|
s.close(done);
|
|
}
|
|
done(null);
|
|
function done(err) {
|
|
if (err) error = err;
|
|
if (--missing) return;
|
|
if (error) reject(error);
|
|
else resolve();
|
|
}
|
|
});
|
|
}
|
|
async function flushHeader(oplog, bigHeader, header) {
|
|
if (header.external) {
|
|
await bigHeader.flush(header);
|
|
}
|
|
try {
|
|
await oplog.flush(header);
|
|
} catch (err) {
|
|
if (err.code !== "OPLOG_HEADER_OVERFLOW") throw err;
|
|
await bigHeader.flush(header);
|
|
await oplog.flush(header);
|
|
}
|
|
}
|
|
function noop() {
|
|
}
|
|
function maximumSegmentStart(start, src, dst) {
|
|
while (true) {
|
|
const a = src.firstSet(start);
|
|
const b = dst.firstUnset(start);
|
|
if (a === -1) return -1;
|
|
if (b === -1) return a;
|
|
if (a < b) {
|
|
start = b;
|
|
continue;
|
|
}
|
|
return a;
|
|
}
|
|
}
|
|
function minimumSegmentEnd(start, src, dst) {
|
|
const a = src.firstUnset(start);
|
|
const b = dst.firstSet(start);
|
|
if (a === -1) return -1;
|
|
if (b === -1) return a;
|
|
return a < b ? a : b;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/block-encryption.js
|
|
var require_block_encryption = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/block-encryption.js"(exports, module) {
|
|
var sodium = require_sodium_universal2();
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var { BLOCK_ENCRYPTION } = require_caps();
|
|
var nonce = b4a.alloc(sodium.crypto_stream_NONCEBYTES);
|
|
module.exports = class BlockEncryption {
|
|
constructor(encryptionKey, hypercoreKey, { isBlockKey = false, compat = true } = {}) {
|
|
const subKeys = b4a.alloc(2 * sodium.crypto_stream_KEYBYTES);
|
|
this.key = encryptionKey;
|
|
this.blockKey = isBlockKey ? encryptionKey : subKeys.subarray(0, sodium.crypto_stream_KEYBYTES);
|
|
this.blindingKey = subKeys.subarray(sodium.crypto_stream_KEYBYTES);
|
|
this.padding = 8;
|
|
this.compat = compat;
|
|
this.isBlockKey = isBlockKey;
|
|
if (!isBlockKey) {
|
|
if (compat) sodium.crypto_generichash_batch(this.blockKey, [encryptionKey], hypercoreKey);
|
|
else sodium.crypto_generichash_batch(this.blockKey, [BLOCK_ENCRYPTION, hypercoreKey, encryptionKey]);
|
|
}
|
|
sodium.crypto_generichash(this.blindingKey, this.blockKey);
|
|
}
|
|
encrypt(index, block, fork) {
|
|
const padding = block.subarray(0, this.padding);
|
|
block = block.subarray(this.padding);
|
|
c.uint64.encode({ start: 0, end: 8, buffer: padding }, fork);
|
|
c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index);
|
|
nonce.fill(0, 8, 8 + padding.byteLength);
|
|
sodium.crypto_stream_xor(
|
|
padding,
|
|
padding,
|
|
nonce,
|
|
this.blindingKey
|
|
);
|
|
nonce.set(padding, 8);
|
|
sodium.crypto_stream_xor(
|
|
block,
|
|
block,
|
|
nonce,
|
|
this.blockKey
|
|
);
|
|
}
|
|
decrypt(index, block) {
|
|
const padding = block.subarray(0, this.padding);
|
|
block = block.subarray(this.padding);
|
|
c.uint64.encode({ start: 0, end: 8, buffer: nonce }, index);
|
|
nonce.set(padding, 8);
|
|
sodium.crypto_stream_xor(
|
|
block,
|
|
block,
|
|
nonce,
|
|
this.blockKey
|
|
);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/download.js
|
|
var require_download = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/download.js"(exports, module) {
|
|
module.exports = class Download {
|
|
constructor(req) {
|
|
this.req = req;
|
|
}
|
|
async done() {
|
|
return (await this.req).promise;
|
|
}
|
|
/**
|
|
* Deprecated. Use `range.done()`.
|
|
*/
|
|
downloaded() {
|
|
return this.done();
|
|
}
|
|
destroy() {
|
|
this.req.then((req) => req.context && req.context.detach(req), noop);
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/batch.js
|
|
var require_batch = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/batch.js"(exports, module) {
|
|
var { BLOCK_NOT_AVAILABLE, SESSION_CLOSED } = require_hypercore_errors();
|
|
var EventEmitter = __require("events");
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var safetyCatch = require_safety_catch();
|
|
module.exports = class HypercoreBatch extends EventEmitter {
|
|
constructor(session, checkoutLength, autoClose, restore, clear) {
|
|
super();
|
|
this.session = session;
|
|
this.opened = false;
|
|
this.closed = false;
|
|
this.opening = null;
|
|
this.closing = null;
|
|
this.writable = true;
|
|
this.autoClose = autoClose;
|
|
this.restore = restore;
|
|
this.fork = 0;
|
|
this._appends = [];
|
|
this._appendsActual = null;
|
|
this._checkoutLength = checkoutLength;
|
|
this._byteLength = 0;
|
|
this._sessionLength = 0;
|
|
this._sessionByteLength = 0;
|
|
this._sessionBatch = null;
|
|
this._cachedBatch = null;
|
|
this._flushing = null;
|
|
this._clear = clear;
|
|
this.opening = this._open();
|
|
this.opening.catch(safetyCatch);
|
|
}
|
|
get id() {
|
|
return this.session.id;
|
|
}
|
|
get key() {
|
|
return this.session.key;
|
|
}
|
|
get discoveryKey() {
|
|
return this.session.discoveryKey;
|
|
}
|
|
get indexedLength() {
|
|
return Math.min(this._sessionLength, this.session.core === null ? 0 : this.session.core.tree.length);
|
|
}
|
|
get flushedLength() {
|
|
return this._sessionLength;
|
|
}
|
|
get indexedByteLength() {
|
|
return this._sessionByteLength;
|
|
}
|
|
get length() {
|
|
return this._sessionLength + this._appends.length;
|
|
}
|
|
get byteLength() {
|
|
return this._sessionByteLength + this._byteLength;
|
|
}
|
|
get core() {
|
|
return this.session.core;
|
|
}
|
|
get manifest() {
|
|
return this.session.manifest;
|
|
}
|
|
ready() {
|
|
return this.opening;
|
|
}
|
|
async _open() {
|
|
await this.session.ready();
|
|
if (this._clear) this._checkoutLength = this.core.tree.length;
|
|
if (this._checkoutLength !== -1) {
|
|
const batch = await this.session.core.tree.restoreBatch(this._checkoutLength);
|
|
batch.treeLength = this._checkoutLength;
|
|
this._sessionLength = batch.length;
|
|
this._sessionByteLength = batch.byteLength;
|
|
this._sessionBatch = batch;
|
|
if (this._clear) await this.core.clearBatch();
|
|
} else {
|
|
const last = this.restore ? this.session.core.bitfield.findFirst(false, this.session.length) : 0;
|
|
if (last > this.session.length) {
|
|
const batch = await this.session.core.tree.restoreBatch(last);
|
|
this._sessionLength = batch.length;
|
|
this._sessionByteLength = batch.byteLength - this.session.padding * batch.length;
|
|
this._sessionBatch = batch;
|
|
} else {
|
|
this._sessionLength = this.session.length;
|
|
this._sessionByteLength = this.session.byteLength;
|
|
this._sessionBatch = this.session.createTreeBatch();
|
|
}
|
|
}
|
|
this._appendsActual = this.session.encryption ? [] : this._appends;
|
|
this.fork = this.session.fork;
|
|
this.opened = true;
|
|
this.emit("ready");
|
|
}
|
|
async has(index) {
|
|
if (this.opened === false) await this.ready();
|
|
if (index >= this._sessionLength) return index < this.length;
|
|
return this.session.has(index);
|
|
}
|
|
async update(opts) {
|
|
if (this.opened === false) await this.ready();
|
|
await this.session.update(opts);
|
|
}
|
|
treeHash() {
|
|
return this._sessionBatch.hash();
|
|
}
|
|
setUserData(key, value, opts) {
|
|
return this.session.setUserData(key, value, opts);
|
|
}
|
|
getUserData(key, opts) {
|
|
return this.session.getUserData(key, opts);
|
|
}
|
|
async info(opts) {
|
|
const session = this.session;
|
|
const info = await session.info(opts);
|
|
info.length = this._sessionLength;
|
|
if (info.contiguousLength >= info.length) {
|
|
info.contiguousLength = info.length += this._appends.length;
|
|
} else {
|
|
info.length += this._appends.length;
|
|
}
|
|
info.byteLength = this._sessionByteLength + this._byteLength;
|
|
return info;
|
|
}
|
|
async seek(bytes, opts = {}) {
|
|
if (this.opened === false) await this.opening;
|
|
if (this.closing) throw SESSION_CLOSED();
|
|
if (bytes < this._sessionByteLength) return await this.session.seek(bytes, { ...opts, tree: this._sessionBatch });
|
|
bytes -= this._sessionByteLength;
|
|
let i = 0;
|
|
for (const blk of this._appends) {
|
|
if (bytes < blk.byteLength) return [this._sessionLength + i, bytes];
|
|
i++;
|
|
bytes -= blk.byteLength;
|
|
}
|
|
if (bytes === 0) return [this._sessionLength + i, 0];
|
|
throw BLOCK_NOT_AVAILABLE();
|
|
}
|
|
async get(index, opts = {}) {
|
|
if (this.opened === false) await this.opening;
|
|
if (this.closing) throw SESSION_CLOSED();
|
|
const length = this._sessionLength;
|
|
if (index < length) {
|
|
return this.session.get(index, { ...opts, tree: this._sessionBatch });
|
|
}
|
|
if (opts && opts.raw) {
|
|
return this._appendsActual[index - length] || null;
|
|
}
|
|
const buffer = this._appends[index - length] || null;
|
|
if (!buffer) throw BLOCK_NOT_AVAILABLE();
|
|
const encoding = opts && opts.valueEncoding && c.from(opts.valueEncoding) || this.session.valueEncoding;
|
|
if (!encoding) return buffer;
|
|
return c.decode(encoding, buffer);
|
|
}
|
|
async _waitForFlush() {
|
|
while (this._flushing) {
|
|
await this._flushing;
|
|
await Promise.resolve();
|
|
}
|
|
}
|
|
async restoreBatch(length, blocks) {
|
|
if (this.opened === false) await this.opening;
|
|
if (length >= this._sessionLength) return this.createTreeBatch(length, blocks);
|
|
return this.session.core.tree.restoreBatch(length);
|
|
}
|
|
_catchupBatch(clone) {
|
|
if (this._cachedBatch === null) this._cachedBatch = this._sessionBatch.clone();
|
|
if (this.length > this._cachedBatch.length) {
|
|
const offset = this._cachedBatch.length - this._sessionBatch.length;
|
|
for (let i = offset; i < this._appendsActual.length; i++) {
|
|
this._cachedBatch.append(this._appendsActual[i]);
|
|
}
|
|
}
|
|
return clone ? this._cachedBatch.clone() : this._cachedBatch;
|
|
}
|
|
createTreeBatch(length, opts = {}) {
|
|
if (Array.isArray(opts)) opts = { blocks: opts };
|
|
const { blocks = [], clone = true } = opts;
|
|
if (!length && length !== 0) length = this.length + blocks.length;
|
|
const maxLength = this.length + blocks.length;
|
|
const b = this._catchupBatch(clone || (blocks.length > 0 || length !== this.length));
|
|
const len = Math.min(length, this.length);
|
|
if (len < this._sessionLength || length > maxLength) return null;
|
|
if (len < b.length) b.checkout(len, this._sessionBatch.roots);
|
|
for (let i = 0; i < length - len; i++) {
|
|
b.append(this._appendsActual === this._appends ? blocks[i] : this._encrypt(b.length, blocks[i]));
|
|
}
|
|
return b;
|
|
}
|
|
async truncate(newLength = 0, opts = {}) {
|
|
if (this.opened === false) await this.opening;
|
|
if (this.closing) throw SESSION_CLOSED();
|
|
await this._waitForFlush();
|
|
if (typeof opts === "number") opts = { fork: opts };
|
|
const { fork = this.fork + 1, force = false } = opts;
|
|
this._cachedBatch = null;
|
|
const length = this._sessionLength;
|
|
if (newLength < length) {
|
|
if (!force) throw new Error("Cannot truncate committed blocks");
|
|
this._appends.length = 0;
|
|
this._byteLength = 0;
|
|
await this.session.truncate(newLength, { fork, force: true, ...opts });
|
|
this._sessionLength = this.session.length;
|
|
this._sessionByteLength = this.session.byteLength;
|
|
this._sessionBatch = this.session.createTreeBatch();
|
|
} else {
|
|
for (let i = newLength - length; i < this._appends.length; i++) this._byteLength -= this._appends[i].byteLength;
|
|
this._appends.length = newLength - length;
|
|
}
|
|
this.fork = fork;
|
|
this.emit("truncate", newLength, this.fork);
|
|
}
|
|
async append(blocks) {
|
|
const session = this.session;
|
|
if (this.opened === false) await this.opening;
|
|
if (this.closing) throw SESSION_CLOSED();
|
|
await this._waitForFlush();
|
|
blocks = Array.isArray(blocks) ? blocks : [blocks];
|
|
const buffers = session.encodeBatch !== null ? session.encodeBatch(blocks) : new Array(blocks.length);
|
|
if (session.encodeBatch === null) {
|
|
for (let i = 0; i < blocks.length; i++) {
|
|
const buffer = this._encode(session.valueEncoding, blocks[i]);
|
|
buffers[i] = buffer;
|
|
this._byteLength += buffer.byteLength;
|
|
}
|
|
}
|
|
if (this._appends !== this._appendsActual) {
|
|
for (let i = 0; i < buffers.length; i++) {
|
|
this._appendsActual.push(this._encrypt(this._sessionLength + this._appendsActual.length, buffers[i]));
|
|
}
|
|
}
|
|
for (const b of buffers) this._appends.push(b);
|
|
const info = { length: this.length, byteLength: this.byteLength };
|
|
this.emit("append");
|
|
return info;
|
|
}
|
|
_encode(enc, val) {
|
|
const state = { start: 0, end: 0, buffer: null };
|
|
if (b4a.isBuffer(val)) {
|
|
if (state.start === 0) return val;
|
|
state.end += val.byteLength;
|
|
} else if (enc) {
|
|
enc.preencode(state, val);
|
|
} else {
|
|
val = b4a.from(val);
|
|
if (state.start === 0) return val;
|
|
state.end += val.byteLength;
|
|
}
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
if (enc) enc.encode(state, val);
|
|
else state.buffer.set(val, state.start);
|
|
return state.buffer;
|
|
}
|
|
_encrypt(index, buffer) {
|
|
const block = b4a.allocUnsafe(buffer.byteLength + 8);
|
|
block.set(buffer, 8);
|
|
this.session.encryption.encrypt(index, block, this.fork);
|
|
return block;
|
|
}
|
|
async flush(opts = {}) {
|
|
if (this.opened === false) await this.opening;
|
|
if (this.closing) throw SESSION_CLOSED();
|
|
const { length = this.length, keyPair = this.session.keyPair, signature = null, pending = !signature && !keyPair } = opts;
|
|
while (this._flushing) await this._flushing;
|
|
this._flushing = this._flush(length, keyPair, signature, pending);
|
|
let flushed = false;
|
|
try {
|
|
flushed = await this._flushing;
|
|
} finally {
|
|
this._flushing = null;
|
|
}
|
|
if (this.autoClose) await this.close();
|
|
return flushed;
|
|
}
|
|
async _flush(length, keyPair, signature, pending) {
|
|
if (this._sessionBatch.fork !== this.session.fork) return false;
|
|
if (this.session.replicator._upgrade) {
|
|
for (const req of this.session.replicator._upgrade.inflight) {
|
|
if (req.upgrade && req.upgrade.start + req.upgrade.length > length) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
const flushingLength = Math.min(length - this._sessionLength, this._appends.length);
|
|
if (flushingLength <= 0) {
|
|
if (this._sessionLength > this.core.tree.length && length > this.core.tree.length && !pending) {
|
|
const batch2 = await this.restoreBatch(length);
|
|
const info2 = await this.core.insertBatch(batch2, [], { keyPair, signature, pending, treeLength: length });
|
|
return info2 !== null;
|
|
}
|
|
return true;
|
|
}
|
|
const batch = this.createTreeBatch(this._sessionLength + flushingLength);
|
|
if (batch === null) return false;
|
|
const info = await this.core.insertBatch(batch, this._appendsActual, { keyPair, signature, pending, treeLength: this._sessionLength });
|
|
if (info === null) return false;
|
|
const delta = info.byteLength - this._sessionByteLength;
|
|
const newBatch = info.length !== this.session.length ? await this.session.core.tree.restoreBatch(info.length) : this.session.createTreeBatch();
|
|
this._sessionLength = info.length;
|
|
this._sessionByteLength = info.byteLength;
|
|
this._sessionBatch = newBatch;
|
|
if (this._cachedBatch !== null) this._cachedBatch.prune(info.length);
|
|
const same = this._appends === this._appendsActual;
|
|
this._appends = this._appends.slice(flushingLength);
|
|
this._appendsActual = same ? this._appends : this._appendsActual.slice(flushingLength);
|
|
this._byteLength -= delta;
|
|
this.emit("flush");
|
|
return true;
|
|
}
|
|
close() {
|
|
if (!this.closing) this.closing = this._close();
|
|
return this.closing;
|
|
}
|
|
async _close() {
|
|
this._clearAppends();
|
|
await this.session.close();
|
|
this.closed = true;
|
|
this.emit("close");
|
|
}
|
|
_clearAppends() {
|
|
this._appends = [];
|
|
this._appendsActual = [];
|
|
this._byteLength = 0;
|
|
this.fork = 0;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/lib/streams.js
|
|
var require_streams3 = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/lib/streams.js"(exports) {
|
|
var { Writable, Readable } = require_streamx();
|
|
var ReadStream = class extends Readable {
|
|
constructor(core, opts = {}) {
|
|
super();
|
|
this.core = core;
|
|
this.start = opts.start || 0;
|
|
this.end = typeof opts.end === "number" ? opts.end : -1;
|
|
this.snapshot = !opts.live && opts.snapshot !== false;
|
|
this.live = !!opts.live;
|
|
}
|
|
_open(cb) {
|
|
this._openP().then(cb, cb);
|
|
}
|
|
_read(cb) {
|
|
this._readP().then(cb, cb);
|
|
}
|
|
async _openP() {
|
|
if (this.end === -1) await this.core.update();
|
|
else await this.core.ready();
|
|
if (this.snapshot && this.end === -1) this.end = this.core.length;
|
|
}
|
|
async _readP() {
|
|
const end = this.live ? -1 : this.end === -1 ? this.core.length : this.end;
|
|
if (end >= 0 && this.start >= end) {
|
|
this.push(null);
|
|
return;
|
|
}
|
|
this.push(await this.core.get(this.start++));
|
|
}
|
|
};
|
|
exports.ReadStream = ReadStream;
|
|
var WriteStream = class extends Writable {
|
|
constructor(core) {
|
|
super();
|
|
this.core = core;
|
|
}
|
|
_writev(batch, cb) {
|
|
this._writevP(batch).then(cb, cb);
|
|
}
|
|
async _writevP(batch) {
|
|
await this.core.append(batch);
|
|
}
|
|
};
|
|
exports.WriteStream = WriteStream;
|
|
var ByteStream = class extends Readable {
|
|
constructor(core, opts = {}) {
|
|
super();
|
|
this._core = core;
|
|
this._index = 0;
|
|
this._range = null;
|
|
this._byteOffset = opts.byteOffset || 0;
|
|
this._byteLength = typeof opts.byteLength === "number" ? opts.byteLength : -1;
|
|
this._prefetch = typeof opts.prefetch === "number" ? opts.prefetch : 32;
|
|
this._applyOffset = this._byteOffset > 0;
|
|
}
|
|
_open(cb) {
|
|
this._openp().then(cb, cb);
|
|
}
|
|
_read(cb) {
|
|
this._readp().then(cb, cb);
|
|
}
|
|
async _openp() {
|
|
if (this._byteLength === -1) {
|
|
await this._core.update();
|
|
this._byteLength = Math.max(this._core.byteLength - this._byteOffset, 0);
|
|
}
|
|
}
|
|
async _readp() {
|
|
let data = null;
|
|
if (this._byteLength === 0) {
|
|
this.push(null);
|
|
return;
|
|
}
|
|
let relativeOffset = 0;
|
|
if (this._applyOffset) {
|
|
this._applyOffset = false;
|
|
const [block, byteOffset] = await this._core.seek(this._byteOffset);
|
|
this._index = block;
|
|
relativeOffset = byteOffset;
|
|
}
|
|
this._predownload(this._index + 1);
|
|
data = await this._core.get(this._index++, { valueEncoding: "binary" });
|
|
if (relativeOffset > 0) data = data.subarray(relativeOffset);
|
|
if (data.byteLength > this._byteLength) data = data.subarray(0, this._byteLength);
|
|
this._byteLength -= data.byteLength;
|
|
this.push(data);
|
|
if (this._byteLength === 0) this.push(null);
|
|
}
|
|
_predownload(index) {
|
|
if (this._range) this._range.destroy();
|
|
this._range = this._core.download({ start: index, end: index + this._prefetch, linear: true });
|
|
}
|
|
_destroy(cb) {
|
|
if (this._range) this._range.destroy();
|
|
cb(null);
|
|
}
|
|
};
|
|
exports.ByteStream = ByteStream;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hypercore/index.js
|
|
var require_hypercore = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hypercore/index.js"(exports, module) {
|
|
var { EventEmitter } = __require("events");
|
|
var RAF = require_random_access_file();
|
|
var isOptions = require_is_options();
|
|
var hypercoreCrypto = require_hypercore_crypto();
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var Xache = require_xache();
|
|
var NoiseSecretStream = require_secret_stream();
|
|
var Protomux = require_protomux();
|
|
var z32 = require_z32();
|
|
var id = require_hypercore_id_encoding();
|
|
var safetyCatch = require_safety_catch();
|
|
var unslab = require_unslab();
|
|
var Replicator = require_replicator();
|
|
var Core = require_core();
|
|
var BlockEncryption = require_block_encryption();
|
|
var Info = require_info();
|
|
var Download = require_download();
|
|
var Batch = require_batch();
|
|
var { manifestHash, createManifest } = require_verifier();
|
|
var { ReadStream, WriteStream, ByteStream } = require_streams3();
|
|
var {
|
|
ASSERTION,
|
|
BAD_ARGUMENT,
|
|
SESSION_CLOSED,
|
|
SESSION_NOT_WRITABLE,
|
|
SNAPSHOT_NOT_AVAILABLE,
|
|
DECODING_ERROR
|
|
} = require_hypercore_errors();
|
|
var promises = Symbol.for("hypercore.promises");
|
|
var inspect = Symbol.for("nodejs.util.inspect.custom");
|
|
var MAX_SUGGESTED_BLOCK_SIZE = 15 * 1024 * 1024;
|
|
module.exports = class Hypercore extends EventEmitter {
|
|
constructor(storage, key, opts) {
|
|
super();
|
|
if (isOptions(storage)) {
|
|
opts = storage;
|
|
storage = null;
|
|
key = opts.key || null;
|
|
} else if (isOptions(key)) {
|
|
opts = key;
|
|
key = opts.key || null;
|
|
}
|
|
if (key && typeof key === "string") key = id.decode(key);
|
|
if (!opts) opts = {};
|
|
if (!storage) storage = opts.storage;
|
|
this[promises] = true;
|
|
this.storage = null;
|
|
this.crypto = opts.crypto || hypercoreCrypto;
|
|
this.core = null;
|
|
this.replicator = null;
|
|
this.encryption = null;
|
|
this.extensions = /* @__PURE__ */ new Map();
|
|
this.cache = createCache(opts.cache);
|
|
this.valueEncoding = null;
|
|
this.encodeBatch = null;
|
|
this.activeRequests = [];
|
|
this.id = null;
|
|
this.key = key || null;
|
|
this.keyPair = opts.keyPair || null;
|
|
this.readable = true;
|
|
this.writable = false;
|
|
this.opened = false;
|
|
this.closed = false;
|
|
this.snapshotted = !!opts.snapshot;
|
|
this.sparse = opts.sparse !== false;
|
|
this.sessions = opts._sessions || [this];
|
|
this.autoClose = !!opts.autoClose;
|
|
this.onwait = opts.onwait || null;
|
|
this.wait = opts.wait !== false;
|
|
this.timeout = opts.timeout || 0;
|
|
this.closing = null;
|
|
this.opening = null;
|
|
this._readonly = opts.writable === false;
|
|
this._preappend = preappend.bind(this);
|
|
this._snapshot = null;
|
|
this._findingPeers = 0;
|
|
this._active = opts.active !== false;
|
|
this.opening = this._openSession(key, storage, opts);
|
|
this.opening.catch(safetyCatch);
|
|
}
|
|
[inspect](depth, opts) {
|
|
let indent = "";
|
|
if (typeof opts.indentationLvl === "number") {
|
|
while (indent.length < opts.indentationLvl) indent += " ";
|
|
}
|
|
let peers = "";
|
|
const min = Math.min(this.peers.length, 5);
|
|
for (let i = 0; i < min; i++) {
|
|
const peer = this.peers[i];
|
|
peers += indent + " Peer(\n";
|
|
peers += indent + " remotePublicKey: " + opts.stylize(toHex(peer.remotePublicKey), "string") + "\n";
|
|
peers += indent + " remoteLength: " + opts.stylize(peer.remoteLength, "number") + "\n";
|
|
peers += indent + " remoteFork: " + opts.stylize(peer.remoteFork, "number") + "\n";
|
|
peers += indent + " remoteCanUpgrade: " + opts.stylize(peer.remoteCanUpgrade, "boolean") + "\n";
|
|
peers += indent + " )\n";
|
|
}
|
|
if (this.peers.length > 5) {
|
|
peers += indent + " ... and " + (this.peers.length - 5) + " more\n";
|
|
}
|
|
if (peers) peers = "[\n" + peers + indent + " ]";
|
|
else peers = "[ " + opts.stylize(0, "number") + " ]";
|
|
return this.constructor.name + "(\n" + indent + " id: " + opts.stylize(this.id, "string") + "\n" + indent + " key: " + opts.stylize(toHex(this.key), "string") + "\n" + indent + " discoveryKey: " + opts.stylize(toHex(this.discoveryKey), "string") + "\n" + indent + " opened: " + opts.stylize(this.opened, "boolean") + "\n" + indent + " closed: " + opts.stylize(this.closed, "boolean") + "\n" + indent + " snapshotted: " + opts.stylize(this.snapshotted, "boolean") + "\n" + indent + " sparse: " + opts.stylize(this.sparse, "boolean") + "\n" + indent + " writable: " + opts.stylize(this.writable, "boolean") + "\n" + indent + " length: " + opts.stylize(this.length, "number") + "\n" + indent + " fork: " + opts.stylize(this.fork, "number") + "\n" + indent + " sessions: [ " + opts.stylize(this.sessions.length, "number") + " ]\n" + indent + " activeRequests: [ " + opts.stylize(this.activeRequests.length, "number") + " ]\n" + indent + " peers: " + peers + "\n" + indent + ")";
|
|
}
|
|
static MAX_SUGGESTED_BLOCK_SIZE = MAX_SUGGESTED_BLOCK_SIZE;
|
|
static key(manifest, { compat, version, namespace } = {}) {
|
|
if (b4a.isBuffer(manifest)) manifest = { version, signers: [{ publicKey: manifest, namespace }] };
|
|
return compat ? manifest.signers[0].publicKey : manifestHash(createManifest(manifest));
|
|
}
|
|
static discoveryKey(key) {
|
|
return hypercoreCrypto.discoveryKey(key);
|
|
}
|
|
static getProtocolMuxer(stream) {
|
|
return stream.noiseStream.userData;
|
|
}
|
|
static createProtocolStream(isInitiator, opts = {}) {
|
|
let outerStream = Protomux.isProtomux(isInitiator) ? isInitiator.stream : isStream(isInitiator) ? isInitiator : opts.stream;
|
|
let noiseStream = null;
|
|
if (outerStream) {
|
|
noiseStream = outerStream.noiseStream;
|
|
} else {
|
|
noiseStream = new NoiseSecretStream(isInitiator, null, opts);
|
|
outerStream = noiseStream.rawStream;
|
|
}
|
|
if (!noiseStream) throw BAD_ARGUMENT("Invalid stream");
|
|
if (!noiseStream.userData) {
|
|
const protocol = Protomux.from(noiseStream);
|
|
if (opts.keepAlive !== false) {
|
|
noiseStream.setKeepAlive(5e3);
|
|
}
|
|
noiseStream.userData = protocol;
|
|
}
|
|
if (opts.ondiscoverykey) {
|
|
noiseStream.userData.pair({ protocol: "hypercore/alpha" }, opts.ondiscoverykey);
|
|
}
|
|
return outerStream;
|
|
}
|
|
static defaultStorage(storage, opts = {}) {
|
|
if (typeof storage !== "string") {
|
|
if (!isRandomAccessClass(storage)) return storage;
|
|
const Cls = storage;
|
|
return (name) => new Cls(name);
|
|
}
|
|
const directory = storage;
|
|
const toLock = opts.unlocked ? null : opts.lock || "oplog";
|
|
const pool = opts.pool || (opts.poolSize ? RAF.createPool(opts.poolSize) : null);
|
|
const rmdir = !!opts.rmdir;
|
|
const writable = opts.writable !== false;
|
|
return createFile;
|
|
function createFile(name) {
|
|
const lock = toLock === null ? false : isFile(name, toLock);
|
|
const sparse = isFile(name, "data") || isFile(name, "bitfield") || isFile(name, "tree");
|
|
return new RAF(name, { directory, lock, sparse, pool: lock ? null : pool, rmdir, writable });
|
|
}
|
|
function isFile(name, n) {
|
|
return name === n || name.endsWith("/" + n);
|
|
}
|
|
}
|
|
snapshot(opts) {
|
|
return this.session({ ...opts, snapshot: true });
|
|
}
|
|
session(opts = {}) {
|
|
if (this.closing) {
|
|
throw SESSION_CLOSED("Cannot make sessions on a closing core");
|
|
}
|
|
const sparse = opts.sparse === false ? false : this.sparse;
|
|
const wait = opts.wait === false ? false : this.wait;
|
|
const writable = opts.writable === false ? false : !this._readonly;
|
|
const onwait = opts.onwait === void 0 ? this.onwait : opts.onwait;
|
|
const timeout = opts.timeout === void 0 ? this.timeout : opts.timeout;
|
|
const Clz = opts.class || Hypercore;
|
|
const s = new Clz(this.storage, this.key, {
|
|
...opts,
|
|
sparse,
|
|
wait,
|
|
onwait,
|
|
timeout,
|
|
writable,
|
|
_opening: this.opening,
|
|
_sessions: this.sessions
|
|
});
|
|
s._passCapabilities(this);
|
|
if (opts.cache !== false) {
|
|
s.cache = opts.cache === true || !opts.cache ? this.cache : opts.cache;
|
|
}
|
|
if (this.opened) ensureEncryption(s, opts);
|
|
this._addSession(s);
|
|
return s;
|
|
}
|
|
_addSession(s) {
|
|
this.sessions.push(s);
|
|
if (this.core) this.core.active++;
|
|
}
|
|
async setEncryptionKey(encryptionKey, opts) {
|
|
if (!this.opened) await this.opening;
|
|
this.encryption = encryptionKey ? new BlockEncryption(encryptionKey, this.key, { compat: this.core.compat, ...opts }) : null;
|
|
}
|
|
setKeyPair(keyPair) {
|
|
this.keyPair = keyPair;
|
|
this.writable = this._isWritable();
|
|
}
|
|
setActive(bool) {
|
|
const active = !!bool;
|
|
if (active === this._active || this.closing) return;
|
|
this._active = active;
|
|
if (!this.opened) return;
|
|
this.replicator.updateActivity(this._active ? 1 : -1);
|
|
}
|
|
_passCapabilities(o) {
|
|
if (!this.keyPair) this.keyPair = o.keyPair;
|
|
this.crypto = o.crypto;
|
|
this.id = o.id;
|
|
this.key = o.key;
|
|
this.core = o.core;
|
|
this.replicator = o.replicator;
|
|
this.encryption = o.encryption;
|
|
this.writable = this._isWritable();
|
|
this.autoClose = o.autoClose;
|
|
if (this.snapshotted && this.core && !this._snapshot) this._updateSnapshot();
|
|
}
|
|
async _openFromExisting(from, opts) {
|
|
if (!from.opened) await from.opening;
|
|
const sessions = this.sessions;
|
|
for (const s of sessions) {
|
|
s.sessions = from.sessions;
|
|
s._passCapabilities(from);
|
|
s._addSession(s);
|
|
}
|
|
this.storage = from.storage;
|
|
this.replicator.findingPeers += this._findingPeers;
|
|
ensureEncryption(this, opts);
|
|
if (this.encryption && !from.encryption) {
|
|
for (const s of sessions) s.encryption = this.encryption;
|
|
}
|
|
}
|
|
async _openSession(key, storage, opts) {
|
|
const isFirst = !opts._opening;
|
|
if (!isFirst) {
|
|
await opts._opening;
|
|
}
|
|
if (opts.preload) opts = { ...opts, ...await this._retryPreload(opts.preload) };
|
|
if (this.cache === null && opts.cache) this.cache = createCache(opts.cache);
|
|
if (isFirst) {
|
|
await this._openCapabilities(key, storage, opts);
|
|
if (!opts.from) {
|
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
const s = this.sessions[i];
|
|
if (s !== this) s._passCapabilities(this);
|
|
}
|
|
}
|
|
} else {
|
|
ensureEncryption(this, opts);
|
|
}
|
|
if (opts.manifest && !this.core.header.manifest) {
|
|
await this.core.setManifest(opts.manifest);
|
|
}
|
|
this.writable = this._isWritable();
|
|
if (opts.valueEncoding) {
|
|
this.valueEncoding = c.from(opts.valueEncoding);
|
|
}
|
|
if (opts.encodeBatch) {
|
|
this.encodeBatch = opts.encodeBatch;
|
|
}
|
|
if (!this.sparse) this.download({ start: 0, end: -1 });
|
|
if (opts._preready) await opts._preready(this);
|
|
this.replicator.updateActivity(this._active ? 1 : 0);
|
|
this.opened = true;
|
|
this.emit("ready");
|
|
}
|
|
async _retryPreload(preload) {
|
|
while (true) {
|
|
const result = await preload();
|
|
const from = result && result.from;
|
|
if (from) {
|
|
if (!from.opened) await from.ready();
|
|
if (from.closing) continue;
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
async _openCapabilities(key, storage, opts) {
|
|
if (opts.from) return this._openFromExisting(opts.from, opts);
|
|
const unlocked = !!opts.unlocked;
|
|
this.storage = Hypercore.defaultStorage(opts.storage || storage, { unlocked, writable: !unlocked });
|
|
this.core = await Core.open(this.storage, {
|
|
compat: opts.compat,
|
|
force: opts.force,
|
|
sessions: this.sessions,
|
|
createIfMissing: opts.createIfMissing,
|
|
readonly: unlocked,
|
|
overwrite: opts.overwrite,
|
|
key,
|
|
keyPair: opts.keyPair,
|
|
crypto: this.crypto,
|
|
legacy: opts.legacy,
|
|
manifest: opts.manifest,
|
|
globalCache: opts.globalCache || null,
|
|
// This is a temp option, not to be relied on unless you know what you are doing (no semver guarantees)
|
|
onupdate: this._oncoreupdate.bind(this),
|
|
onconflict: this._oncoreconflict.bind(this)
|
|
});
|
|
if (opts.userData) {
|
|
for (const [key2, value] of Object.entries(opts.userData)) {
|
|
await this.core.userData(key2, value);
|
|
}
|
|
}
|
|
this.key = this.core.header.key;
|
|
this.keyPair = this.core.header.keyPair;
|
|
this.id = z32.encode(this.key);
|
|
this.replicator = new Replicator(this.core, this.key, {
|
|
eagerUpgrade: true,
|
|
notDownloadingLinger: opts.notDownloadingLinger,
|
|
allowFork: opts.allowFork !== false,
|
|
inflightRange: opts.inflightRange,
|
|
onpeerupdate: this._onpeerupdate.bind(this),
|
|
onupload: this._onupload.bind(this),
|
|
oninvalid: this._oninvalid.bind(this)
|
|
});
|
|
this.replicator.findingPeers += this._findingPeers;
|
|
if (!this.encryption && opts.encryptionKey) {
|
|
this.encryption = new BlockEncryption(opts.encryptionKey, this.key, { compat: this.core.compat, isBlockKey: opts.isBlockKey });
|
|
}
|
|
}
|
|
_getSnapshot() {
|
|
if (this.sparse) {
|
|
return {
|
|
length: this.core.tree.length,
|
|
byteLength: this.core.tree.byteLength,
|
|
fork: this.core.tree.fork,
|
|
compatLength: this.core.tree.length
|
|
};
|
|
}
|
|
return {
|
|
length: this.core.header.hints.contiguousLength,
|
|
byteLength: 0,
|
|
fork: this.core.tree.fork,
|
|
compatLength: this.core.header.hints.contiguousLength
|
|
};
|
|
}
|
|
_updateSnapshot() {
|
|
const prev = this._snapshot;
|
|
const next = this._snapshot = this._getSnapshot();
|
|
if (!prev) return true;
|
|
return prev.length !== next.length || prev.fork !== next.fork;
|
|
}
|
|
_isWritable() {
|
|
return !this._readonly && !!(this.keyPair && this.keyPair.secretKey);
|
|
}
|
|
close(err) {
|
|
if (this.closing) return this.closing;
|
|
this.closing = this._close(err || null);
|
|
return this.closing;
|
|
}
|
|
async _close(err) {
|
|
if (this.opened === false) await this.opening;
|
|
const i = this.sessions.indexOf(this);
|
|
if (i === -1) return;
|
|
this.sessions.splice(i, 1);
|
|
this.core.active--;
|
|
this.readable = false;
|
|
this.writable = false;
|
|
this.closed = true;
|
|
this.opened = false;
|
|
const gc = [];
|
|
for (const ext of this.extensions.values()) {
|
|
if (ext.session === this) gc.push(ext);
|
|
}
|
|
for (const ext of gc) ext.destroy();
|
|
if (this.replicator !== null) {
|
|
this.replicator.findingPeers -= this._findingPeers;
|
|
this.replicator.clearRequests(this.activeRequests, err);
|
|
this.replicator.updateActivity(this._active ? -1 : 0);
|
|
}
|
|
this._findingPeers = 0;
|
|
if (this.sessions.length || this.core.active > 0) {
|
|
if (this.sessions.length === 1 && this.core.active === 1 && this.autoClose) await this.sessions[0].close(err);
|
|
this.emit("close", false);
|
|
return;
|
|
}
|
|
if (this.replicator !== null) {
|
|
await this.replicator.destroy();
|
|
}
|
|
await this.core.close();
|
|
this.emit("close", true);
|
|
}
|
|
replicate(isInitiator, opts = {}) {
|
|
if (Protomux.isProtomux(isInitiator)) return this._attachToMuxer(isInitiator, opts);
|
|
if (isStream(isInitiator) && this._isAttached(isInitiator)) return isInitiator;
|
|
const protocolStream = Hypercore.createProtocolStream(isInitiator, opts);
|
|
const noiseStream = protocolStream.noiseStream;
|
|
const protocol = noiseStream.userData;
|
|
const useSession = !!opts.session;
|
|
this._attachToMuxer(protocol, useSession);
|
|
return protocolStream;
|
|
}
|
|
_isAttached(stream) {
|
|
return stream.userData && this.replicator && this.replicator.attached(stream.userData);
|
|
}
|
|
_attachToMuxer(mux, useSession) {
|
|
if (this.opened) {
|
|
this._attachToMuxerOpened(mux, useSession);
|
|
} else {
|
|
this.opening.then(this._attachToMuxerOpened.bind(this, mux, useSession), mux.destroy.bind(mux));
|
|
}
|
|
return mux;
|
|
}
|
|
_attachToMuxerOpened(mux, useSession) {
|
|
this.replicator.attachTo(mux, useSession);
|
|
}
|
|
get discoveryKey() {
|
|
return this.replicator === null ? null : this.replicator.discoveryKey;
|
|
}
|
|
get manifest() {
|
|
return this.core === null ? null : this.core.header.manifest;
|
|
}
|
|
get length() {
|
|
if (this._snapshot) return this._snapshot.length;
|
|
if (this.core === null) return 0;
|
|
if (!this.sparse) return this.contiguousLength;
|
|
return this.core.tree.length;
|
|
}
|
|
get signedLength() {
|
|
return this.length;
|
|
}
|
|
get indexedLength() {
|
|
return this.length;
|
|
}
|
|
/**
|
|
* Deprecated. Use `const { byteLength } = await core.info()`.
|
|
*/
|
|
get byteLength() {
|
|
if (this._snapshot) return this._snapshot.byteLength;
|
|
if (this.core === null) return 0;
|
|
if (!this.sparse) return this.contiguousByteLength;
|
|
return this.core.tree.byteLength - this.core.tree.length * this.padding;
|
|
}
|
|
get contiguousLength() {
|
|
return this.core === null ? 0 : Math.min(this.core.tree.length, this.core.header.hints.contiguousLength);
|
|
}
|
|
get contiguousByteLength() {
|
|
return 0;
|
|
}
|
|
get fork() {
|
|
return this.core === null ? 0 : this.core.tree.fork;
|
|
}
|
|
get peers() {
|
|
return this.replicator === null ? [] : this.replicator.peers;
|
|
}
|
|
get encryptionKey() {
|
|
return this.encryption && this.encryption.key;
|
|
}
|
|
get padding() {
|
|
return this.encryption === null ? 0 : this.encryption.padding;
|
|
}
|
|
get globalCache() {
|
|
return this.core && this.core.globalCache;
|
|
}
|
|
ready() {
|
|
return this.opening;
|
|
}
|
|
_onupload(index, value, from) {
|
|
const byteLength = value.byteLength - this.padding;
|
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
this.sessions[i].emit("upload", index, byteLength, from);
|
|
}
|
|
}
|
|
_oninvalid(err, req, res, from) {
|
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
this.sessions[i].emit("verification-error", err, req, res, from);
|
|
}
|
|
}
|
|
async _oncoreconflict(proof, from) {
|
|
await this.replicator.onconflict(from);
|
|
for (const s of this.sessions) s.emit("conflict", proof.upgrade.length, proof.fork, proof);
|
|
const err = new Error("Two conflicting signatures exist for length " + proof.upgrade.length);
|
|
await this._closeAllSessions(err);
|
|
}
|
|
async _closeAllSessions(err) {
|
|
const sessions = [...this.sessions];
|
|
const all = [];
|
|
for (const s of sessions) all.push(s.close(err));
|
|
await Promise.allSettled(all);
|
|
}
|
|
_oncoreupdate(status, bitfield, value, from) {
|
|
if (status !== 0) {
|
|
const truncatedNonSparse = (status & 8) !== 0;
|
|
const appendedNonSparse = (status & 4) !== 0;
|
|
const truncated = (status & 2) !== 0;
|
|
const appended = (status & 1) !== 0;
|
|
if (truncated) {
|
|
this.replicator.ontruncate(bitfield.start, bitfield.length);
|
|
}
|
|
if ((status & 19) !== 0) {
|
|
this.replicator.onupgrade();
|
|
}
|
|
if (status & 16) {
|
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
const s = this.sessions[i];
|
|
if (s.encryption && s.encryption.compat !== this.core.compat) {
|
|
s.encryption = new BlockEncryption(s.encryption.key, this.key, { compat: this.core.compat, isBlockKey: s.encryption.isBlockKey });
|
|
}
|
|
}
|
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
this.sessions[i].emit("manifest");
|
|
}
|
|
}
|
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
const s = this.sessions[i];
|
|
if (truncated) {
|
|
if (s.cache) s.cache.clear();
|
|
if (s._snapshot && bitfield.start < s._snapshot.compatLength) s._snapshot.compatLength = bitfield.start;
|
|
}
|
|
if (s.sparse ? truncated : truncatedNonSparse) {
|
|
s.emit("truncate", bitfield.start, this.core.tree.fork);
|
|
}
|
|
if (s.sparse ? appended : appendedNonSparse) {
|
|
s.emit("append");
|
|
}
|
|
}
|
|
const contig = this.core.header.hints.contiguousLength;
|
|
if (appendedNonSparse && contig === this.core.tree.length) {
|
|
for (const peer of this.peers) {
|
|
if (peer.broadcastedNonSparse) continue;
|
|
peer.broadcastRange(0, contig);
|
|
peer.broadcastedNonSparse = true;
|
|
}
|
|
}
|
|
}
|
|
if (bitfield) {
|
|
this.replicator.onhave(bitfield.start, bitfield.length, bitfield.drop);
|
|
}
|
|
if (value) {
|
|
const byteLength = value.byteLength - this.padding;
|
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
this.sessions[i].emit("download", bitfield.start, byteLength, from);
|
|
}
|
|
}
|
|
}
|
|
_onpeerupdate(added, peer) {
|
|
const name = added ? "peer-add" : "peer-remove";
|
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
this.sessions[i].emit(name, peer);
|
|
if (added) {
|
|
for (const ext of this.sessions[i].extensions.values()) {
|
|
peer.extensions.set(ext.name, ext);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
async setUserData(key, value, { flush = false } = {}) {
|
|
if (this.opened === false) await this.opening;
|
|
return this.core.userData(key, value, flush);
|
|
}
|
|
async getUserData(key) {
|
|
if (this.opened === false) await this.opening;
|
|
for (const { key: savedKey, value } of this.core.header.userData) {
|
|
if (key === savedKey) return value;
|
|
}
|
|
return null;
|
|
}
|
|
createTreeBatch() {
|
|
return this.core.tree.batch();
|
|
}
|
|
findingPeers() {
|
|
this._findingPeers++;
|
|
if (this.replicator !== null && !this.closing) this.replicator.findingPeers++;
|
|
let once = true;
|
|
return () => {
|
|
if (this.closing || !once) return;
|
|
once = false;
|
|
this._findingPeers--;
|
|
if (this.replicator !== null && --this.replicator.findingPeers === 0) {
|
|
this.replicator.updateAll();
|
|
}
|
|
};
|
|
}
|
|
async info(opts) {
|
|
if (this.opened === false) await this.opening;
|
|
return Info.from(this, opts);
|
|
}
|
|
async update(opts) {
|
|
if (this.opened === false) await this.opening;
|
|
if (this.closing !== null) return false;
|
|
if (this.writable && (!opts || opts.force !== true)) {
|
|
if (!this.snapshotted) return false;
|
|
return this._updateSnapshot();
|
|
}
|
|
const remoteWait = this._shouldWait(opts, this.replicator.findingPeers > 0);
|
|
let upgraded = false;
|
|
if (await this.replicator.applyPendingReorg()) {
|
|
upgraded = true;
|
|
}
|
|
if (!upgraded && remoteWait) {
|
|
const activeRequests = opts && opts.activeRequests || this.activeRequests;
|
|
const req = this.replicator.addUpgrade(activeRequests);
|
|
upgraded = await req.promise;
|
|
}
|
|
if (!upgraded) return false;
|
|
if (this.snapshotted) return this._updateSnapshot();
|
|
return true;
|
|
}
|
|
batch({ checkout = -1, autoClose = true, session = true, restore = false, clear = false } = {}) {
|
|
return new Batch(session ? this.session() : this, checkout, autoClose, restore, clear);
|
|
}
|
|
async seek(bytes, opts) {
|
|
if (this.opened === false) await this.opening;
|
|
if (!isValidIndex(bytes)) throw ASSERTION("seek is invalid");
|
|
const tree = opts && opts.tree || this.core.tree;
|
|
const s = tree.seek(bytes, this.padding);
|
|
const offset = await s.update();
|
|
if (offset) return offset;
|
|
if (this.closing !== null) throw SESSION_CLOSED();
|
|
if (!this._shouldWait(opts, this.wait)) return null;
|
|
const activeRequests = opts && opts.activeRequests || this.activeRequests;
|
|
const req = this.replicator.addSeek(activeRequests, s);
|
|
const timeout = opts && opts.timeout !== void 0 ? opts.timeout : this.timeout;
|
|
if (timeout) req.context.setTimeout(req, timeout);
|
|
return req.promise;
|
|
}
|
|
async has(start, end = start + 1) {
|
|
if (this.opened === false) await this.opening;
|
|
if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION("has range is invalid");
|
|
if (end === start + 1) return this.core.bitfield.get(start);
|
|
const i = this.core.bitfield.firstUnset(start);
|
|
return i === -1 || i >= end;
|
|
}
|
|
async get(index, opts) {
|
|
if (this.opened === false) await this.opening;
|
|
if (!isValidIndex(index)) throw ASSERTION("block index is invalid");
|
|
if (this.closing !== null) throw SESSION_CLOSED();
|
|
if (this._snapshot !== null && index >= this._snapshot.compatLength) throw SNAPSHOT_NOT_AVAILABLE();
|
|
const encoding = opts && opts.valueEncoding && c.from(opts.valueEncoding) || this.valueEncoding;
|
|
let req = this.cache && this.cache.get(index);
|
|
if (!req) req = this._get(index, opts);
|
|
let block = await req;
|
|
if (!block) return null;
|
|
if (opts && opts.raw) return block;
|
|
if (this.encryption && (!opts || opts.decrypt !== false)) {
|
|
block = b4a.from(block);
|
|
this.encryption.decrypt(index, block);
|
|
}
|
|
return this._decode(encoding, block);
|
|
}
|
|
async clear(start, end = start + 1, opts) {
|
|
if (this.opened === false) await this.opening;
|
|
if (this.closing !== null) throw SESSION_CLOSED();
|
|
if (typeof end === "object") {
|
|
opts = end;
|
|
end = start + 1;
|
|
}
|
|
if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION("clear range is invalid");
|
|
const cleared = opts && opts.diff ? { blocks: 0 } : null;
|
|
if (start >= end) return cleared;
|
|
if (start >= this.length) return cleared;
|
|
await this.core.clear(start, end, cleared);
|
|
return cleared;
|
|
}
|
|
async purge() {
|
|
await this._closeAllSessions(null);
|
|
await this.core.purge();
|
|
}
|
|
async _get(index, opts) {
|
|
let block;
|
|
if (this.core.bitfield.get(index)) {
|
|
const tree = opts && opts.tree || this.core.tree;
|
|
block = this.core.blocks.get(index, tree);
|
|
if (this.cache) this.cache.set(index, block);
|
|
} else {
|
|
if (!this._shouldWait(opts, this.wait)) return null;
|
|
if (opts && opts.onwait) opts.onwait(index, this);
|
|
if (this.onwait) this.onwait(index, this);
|
|
const activeRequests = opts && opts.activeRequests || this.activeRequests;
|
|
const req = this.replicator.addBlock(activeRequests, index);
|
|
req.snapshot = index < this.length;
|
|
const timeout = opts && opts.timeout !== void 0 ? opts.timeout : this.timeout;
|
|
if (timeout) req.context.setTimeout(req, timeout);
|
|
block = this._cacheOnResolve(index, req.promise, this.core.tree.fork);
|
|
}
|
|
return block;
|
|
}
|
|
async _cacheOnResolve(index, req, fork) {
|
|
const resolved = await req;
|
|
const block = resolved !== null && 2 * resolved.byteLength < resolved.buffer.byteLength ? unslab(resolved) : resolved;
|
|
if (this.cache && fork === this.core.tree.fork) {
|
|
this.cache.set(index, Promise.resolve(block));
|
|
}
|
|
return block;
|
|
}
|
|
_shouldWait(opts, defaultValue) {
|
|
if (opts) {
|
|
if (opts.wait === false) return false;
|
|
if (opts.wait === true) return true;
|
|
}
|
|
return defaultValue;
|
|
}
|
|
createReadStream(opts) {
|
|
return new ReadStream(this, opts);
|
|
}
|
|
createWriteStream(opts) {
|
|
return new WriteStream(this, opts);
|
|
}
|
|
createByteStream(opts) {
|
|
return new ByteStream(this, opts);
|
|
}
|
|
download(range) {
|
|
const req = this._download(range);
|
|
req.catch(safetyCatch);
|
|
return new Download(req);
|
|
}
|
|
async _download(range) {
|
|
if (this.opened === false) await this.opening;
|
|
const activeRequests = range && range.activeRequests || this.activeRequests;
|
|
return this.replicator.addRange(activeRequests, range);
|
|
}
|
|
// NOTE: get rid of this / deprecate it?
|
|
undownload(range) {
|
|
range.destroy(null);
|
|
}
|
|
// NOTE: get rid of this / deprecate it?
|
|
cancel(request) {
|
|
}
|
|
async truncate(newLength = 0, opts = {}) {
|
|
if (this.opened === false) await this.opening;
|
|
const {
|
|
fork = this.core.tree.fork + 1,
|
|
keyPair = this.keyPair,
|
|
signature = null
|
|
} = typeof opts === "number" ? { fork: opts } : opts;
|
|
const writable = !this._readonly && !!(signature || keyPair && keyPair.secretKey);
|
|
if (writable === false && (newLength > 0 || fork !== this.core.tree.fork)) throw SESSION_NOT_WRITABLE();
|
|
await this.core.truncate(newLength, fork, { keyPair, signature });
|
|
this.replicator.updateAll();
|
|
}
|
|
async append(blocks, opts = {}) {
|
|
if (this.opened === false) await this.opening;
|
|
const { keyPair = this.keyPair, signature = null } = opts;
|
|
const writable = !this._readonly && !!(signature || keyPair && keyPair.secretKey);
|
|
if (writable === false) throw SESSION_NOT_WRITABLE();
|
|
blocks = Array.isArray(blocks) ? blocks : [blocks];
|
|
const preappend2 = this.encryption && this._preappend;
|
|
const buffers = this.encodeBatch !== null ? this.encodeBatch(blocks) : new Array(blocks.length);
|
|
if (this.encodeBatch === null) {
|
|
for (let i = 0; i < blocks.length; i++) {
|
|
buffers[i] = this._encode(this.valueEncoding, blocks[i]);
|
|
}
|
|
}
|
|
for (const b of buffers) {
|
|
if (b.byteLength > MAX_SUGGESTED_BLOCK_SIZE) {
|
|
throw BAD_ARGUMENT("Appended block exceeds the maximum suggested block size");
|
|
}
|
|
}
|
|
return this.core.append(buffers, { keyPair, signature, preappend: preappend2 });
|
|
}
|
|
async treeHash(length) {
|
|
if (length === void 0) {
|
|
await this.ready();
|
|
length = this.core.tree.length;
|
|
}
|
|
const roots = await this.core.tree.getRoots(length);
|
|
return this.crypto.tree(roots);
|
|
}
|
|
registerExtension(name, handlers = {}) {
|
|
if (this.extensions.has(name)) {
|
|
const ext2 = this.extensions.get(name);
|
|
ext2.handlers = handlers;
|
|
ext2.encoding = c.from(handlers.encoding || c.buffer);
|
|
ext2.session = this;
|
|
return ext2;
|
|
}
|
|
const ext = {
|
|
name,
|
|
handlers,
|
|
encoding: c.from(handlers.encoding || c.buffer),
|
|
session: this,
|
|
send(message, peer) {
|
|
const buffer = c.encode(this.encoding, message);
|
|
peer.extension(name, buffer);
|
|
},
|
|
broadcast(message) {
|
|
const buffer = c.encode(this.encoding, message);
|
|
for (const peer of this.session.peers) {
|
|
peer.extension(name, buffer);
|
|
}
|
|
},
|
|
destroy() {
|
|
for (const peer of this.session.peers) {
|
|
if (peer.extensions.get(name) === ext) peer.extensions.delete(name);
|
|
}
|
|
this.session.extensions.delete(name);
|
|
},
|
|
_onmessage(state, peer) {
|
|
const m = this.encoding.decode(state);
|
|
if (this.handlers.onmessage) this.handlers.onmessage(m, peer);
|
|
}
|
|
};
|
|
this.extensions.set(name, ext);
|
|
for (const peer of this.peers) {
|
|
peer.extensions.set(name, ext);
|
|
}
|
|
return ext;
|
|
}
|
|
_encode(enc, val) {
|
|
const state = { start: this.padding, end: this.padding, buffer: null };
|
|
if (b4a.isBuffer(val)) {
|
|
if (state.start === 0) return val;
|
|
state.end += val.byteLength;
|
|
} else if (enc) {
|
|
enc.preencode(state, val);
|
|
} else {
|
|
val = b4a.from(val);
|
|
if (state.start === 0) return val;
|
|
state.end += val.byteLength;
|
|
}
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
if (enc) enc.encode(state, val);
|
|
else state.buffer.set(val, state.start);
|
|
return state.buffer;
|
|
}
|
|
_decode(enc, block) {
|
|
if (this.padding) block = block.subarray(this.padding);
|
|
try {
|
|
if (enc) return c.decode(enc, block);
|
|
} catch {
|
|
throw DECODING_ERROR();
|
|
}
|
|
return block;
|
|
}
|
|
};
|
|
function isStream(s) {
|
|
return typeof s === "object" && s && typeof s.pipe === "function";
|
|
}
|
|
function isRandomAccessClass(fn) {
|
|
return !!(typeof fn === "function" && fn.prototype && typeof fn.prototype.open === "function");
|
|
}
|
|
function toHex(buf) {
|
|
return buf && b4a.toString(buf, "hex");
|
|
}
|
|
function preappend(blocks) {
|
|
const offset = this.core.tree.length;
|
|
const fork = this.core.tree.fork;
|
|
for (let i = 0; i < blocks.length; i++) {
|
|
this.encryption.encrypt(offset + i, blocks[i], fork);
|
|
}
|
|
}
|
|
function ensureEncryption(core, opts) {
|
|
if (!opts.encryptionKey) return;
|
|
if (core.encryption && b4a.equals(core.encryption.key, opts.encryptionKey) && core.encryption.compat === core.core.compat) return;
|
|
core.encryption = new BlockEncryption(opts.encryptionKey, core.key, { compat: core.core ? core.core.compat : true, isBlockKey: opts.isBlockKey });
|
|
}
|
|
function createCache(cache) {
|
|
return cache === true ? new Xache({ maxSize: 65536, maxAge: 0 }) : cache || null;
|
|
}
|
|
function isValidIndex(index) {
|
|
return index === 0 || index > 0;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hyperdrive/lib/monitor.js
|
|
var require_monitor2 = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hyperdrive/lib/monitor.js"(exports, module) {
|
|
var ReadyResource = require_ready_resource();
|
|
var safetyCatch = require_safety_catch();
|
|
var speedometer = require_speedometer();
|
|
module.exports = class Monitor extends ReadyResource {
|
|
constructor(drive, opts = {}) {
|
|
super();
|
|
this.drive = drive;
|
|
this.blobs = null;
|
|
this.name = opts.name || null;
|
|
this.entry = opts.entry || null;
|
|
this.peers = 0;
|
|
this._boundOnUpload = this._onUpload.bind(this);
|
|
this._boundOnDownload = this._onDownload.bind(this);
|
|
this._boundPeerUpdate = this._updatePeers.bind(this);
|
|
const stats = {
|
|
startTime: 0,
|
|
percentage: 0,
|
|
peers: 0,
|
|
speed: 0,
|
|
blocks: 0,
|
|
totalBytes: 0,
|
|
// local + bytes loaded during monitoring
|
|
monitoringBytes: 0,
|
|
// bytes loaded during monitoring
|
|
targetBytes: 0,
|
|
targetBlocks: 0
|
|
};
|
|
this.uploadStats = { ...stats };
|
|
this.downloadStats = { ...stats };
|
|
this.uploadSpeedometer = null;
|
|
this.downloadSpeedometer = null;
|
|
this.ready().catch(safetyCatch);
|
|
}
|
|
async _open() {
|
|
await this.drive.ready();
|
|
this.blobs = await this.drive.getBlobs();
|
|
if (!this.entry && this.name) this.entry = await this.drive.entry(this.name);
|
|
if (this.entry) this._setEntryInfo();
|
|
this.uploadSpeedometer = speedometer();
|
|
this.downloadSpeedometer = speedometer();
|
|
this._updatePeers();
|
|
this.blobs.core.on("peer-add", this._boundPeerUpdate);
|
|
this.blobs.core.on("peer-remove", this._boundPeerUpdate);
|
|
this.blobs.core.on("upload", this._boundOnUpload);
|
|
this.blobs.core.on("download", this._boundOnDownload);
|
|
}
|
|
async _close() {
|
|
this.blobs.core.off("peer-add", this._boundPeerUpdate);
|
|
this.blobs.core.off("peer-remove", this._boundPeerUpdate);
|
|
this.blobs.core.off("upload", this._boundOnUpload);
|
|
this.blobs.core.off("download", this._boundOnDownload);
|
|
this.drive.monitors.delete(this);
|
|
}
|
|
_setEntryInfo() {
|
|
if (!this.downloadStats.targetBytes || !this.downloadStats.targetBlocks) {
|
|
this.downloadStats.targetBytes = this.entry.value.blob.byteLength;
|
|
this.downloadStats.targetBlocks = this.entry.value.blob.blockLength;
|
|
}
|
|
if (!this.uploadStats.targetBytes || !this.uploadStats.targetBlocks) {
|
|
this.uploadStats.targetBytes = this.entry.value.blob.byteLength;
|
|
this.uploadStats.targetBlocks = this.entry.value.blob.blockLength;
|
|
}
|
|
}
|
|
_onUpload(index, bytes, from) {
|
|
this._updateStats(this.uploadSpeedometer, this.uploadStats, index, bytes, from);
|
|
}
|
|
_onDownload(index, bytes, from) {
|
|
this._updateStats(this.downloadSpeedometer, this.downloadStats, index, bytes, from);
|
|
}
|
|
_updatePeers() {
|
|
this.uploadStats.peers = this.downloadStats.peers = this.peers = this.blobs.core.peers.length;
|
|
}
|
|
_updateStats(speed, stats, index, bytes, from) {
|
|
if (!this.entry || this.closing) return;
|
|
if (!isWithinRange(index, this.entry)) return;
|
|
if (!stats.startTime) stats.startTime = Date.now();
|
|
stats.speed = speed(bytes);
|
|
stats.blocks++;
|
|
stats.monitoringBytes += bytes;
|
|
stats.totalBytes += bytes;
|
|
stats.percentage = toFixed(stats.blocks / stats.targetBlocks * 100);
|
|
this.emit("update");
|
|
}
|
|
downloadSpeed() {
|
|
return this.downloadSpeedometer ? this.downloadSpeedometer() : 0;
|
|
}
|
|
uploadSpeed() {
|
|
return this.uploadSpeedometer ? this.uploadSpeedometer() : 0;
|
|
}
|
|
};
|
|
function isWithinRange(index, entry) {
|
|
if (!entry || !entry.value) return;
|
|
const { blockOffset, blockLength } = entry.value.blob;
|
|
return index >= blockOffset && index < blockOffset + blockLength;
|
|
}
|
|
function toFixed(n) {
|
|
return Math.round(n * 100) / 100;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/hyperdrive/index.js
|
|
var require_hyperdrive = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/hyperdrive/index.js"(exports, module) {
|
|
var Hyperbee = require_hyperbee();
|
|
var Hyperblobs = require_hyperblobs();
|
|
var isOptions = require_is_options();
|
|
var { Writable, Readable } = require_streamx();
|
|
var unixPathResolve = require_unix_path_resolve();
|
|
var MirrorDrive = require_mirror_drive();
|
|
var SubEncoder = require_sub_encoder();
|
|
var ReadyResource = require_ready_resource();
|
|
var safetyCatch = require_safety_catch();
|
|
var crypto = require_hypercore_crypto();
|
|
var Hypercore = require_hypercore();
|
|
var { BLOCK_NOT_AVAILABLE, BAD_ARGUMENT } = require_hypercore_errors();
|
|
var Monitor = require_monitor2();
|
|
var keyEncoding = new SubEncoder("files", "utf-8");
|
|
var [BLOBS] = crypto.namespace("hyperdrive", 1);
|
|
module.exports = class Hyperdrive extends ReadyResource {
|
|
constructor(corestore, key, opts = {}) {
|
|
super();
|
|
if (isOptions(key)) {
|
|
opts = key;
|
|
key = null;
|
|
}
|
|
this.corestore = corestore;
|
|
this.db = opts._db || makeBee(key, corestore, opts);
|
|
this.core = this.db.core;
|
|
this.blobs = null;
|
|
this.supportsMetadata = true;
|
|
this.encryptionKey = opts.encryptionKey || null;
|
|
this.monitors = /* @__PURE__ */ new Set();
|
|
this._active = opts.active !== false;
|
|
this._openingBlobs = null;
|
|
this._onwait = opts.onwait || null;
|
|
this._batching = !!(opts._checkout === null && opts._db);
|
|
this._checkout = opts._checkout || null;
|
|
this.ready().catch(safetyCatch);
|
|
}
|
|
[Symbol.asyncIterator]() {
|
|
return this.entries()[Symbol.asyncIterator]();
|
|
}
|
|
static async getDriveKey(corestore) {
|
|
const core = makeBee(void 0, corestore);
|
|
await core.ready();
|
|
const key = core.key;
|
|
await core.close();
|
|
return key;
|
|
}
|
|
static getContentKey(m, key) {
|
|
if (m instanceof Hypercore) {
|
|
if (m.core.compat) return null;
|
|
return Hyperdrive.getContentKey(m.manifest, m.key);
|
|
}
|
|
const manifest = generateContentManifest(m, key);
|
|
if (!manifest) return null;
|
|
return Hypercore.key(manifest);
|
|
}
|
|
_generateBlobsManifest() {
|
|
const m = this.db.core.manifest;
|
|
if (this.db.core.core.compat) return null;
|
|
return generateContentManifest(m, this.core.key);
|
|
}
|
|
get id() {
|
|
return this.core.id;
|
|
}
|
|
get key() {
|
|
return this.core.key;
|
|
}
|
|
get discoveryKey() {
|
|
return this.core.discoveryKey;
|
|
}
|
|
get contentKey() {
|
|
return this.blobs?.core.key;
|
|
}
|
|
get version() {
|
|
return this.db.version;
|
|
}
|
|
get writable() {
|
|
return this.core.writable;
|
|
}
|
|
get readable() {
|
|
return this.core.readable;
|
|
}
|
|
findingPeers() {
|
|
return this.corestore.findingPeers();
|
|
}
|
|
async truncate(version, { blobs = -1 } = {}) {
|
|
if (!this.opened) await this.ready();
|
|
if (version > this.core.length) {
|
|
throw BAD_ARGUMENT("Bad truncation length");
|
|
}
|
|
const blobsVersion = blobs === -1 ? await this.getBlobsLength(version) : blobs;
|
|
const bl = await this.getBlobs();
|
|
if (blobsVersion > bl.core.length) {
|
|
throw BAD_ARGUMENT("Bad truncation length");
|
|
}
|
|
await this.core.truncate(version);
|
|
await bl.core.truncate(blobsVersion);
|
|
}
|
|
async getBlobsLength(checkout) {
|
|
if (!this.opened) await this.ready();
|
|
if (!checkout) checkout = this.version;
|
|
const c = this.db.checkout(checkout);
|
|
try {
|
|
return await getBlobsLength(c);
|
|
} finally {
|
|
await c.close();
|
|
}
|
|
}
|
|
replicate(isInitiator, opts) {
|
|
return this.corestore.replicate(isInitiator, opts);
|
|
}
|
|
update(opts) {
|
|
return this.db.update(opts);
|
|
}
|
|
_makeCheckout(snapshot) {
|
|
return new Hyperdrive(this.corestore, this.key, {
|
|
onwait: this._onwait,
|
|
encryptionKey: this.encryptionKey,
|
|
_checkout: this._checkout || this,
|
|
_db: snapshot
|
|
});
|
|
}
|
|
checkout(version) {
|
|
return this._makeCheckout(this.db.checkout(version));
|
|
}
|
|
batch() {
|
|
return new Hyperdrive(this.corestore, this.key, {
|
|
onwait: this._onwait,
|
|
encryptionKey: this.encryptionKey,
|
|
_checkout: null,
|
|
_db: this.db.batch()
|
|
});
|
|
}
|
|
setActive(bool) {
|
|
const active = !!bool;
|
|
if (active === this._active) return;
|
|
this._active = active;
|
|
this.core.setActive(active);
|
|
if (this.blobs) this.blobs.core.setActive(active);
|
|
}
|
|
async flush() {
|
|
await this.db.flush();
|
|
return this.close();
|
|
}
|
|
async _close() {
|
|
if (this.blobs && (!this._checkout || this.blobs !== this._checkout.blobs)) {
|
|
await this.blobs.core.close();
|
|
}
|
|
await this.db.close();
|
|
if (!this._checkout && !this._batching) {
|
|
await this.corestore.close();
|
|
}
|
|
await this.closeMonitors();
|
|
}
|
|
async _openBlobsFromHeader(opts) {
|
|
if (this.blobs) return true;
|
|
const header = await getBee(this.db).getHeader(opts);
|
|
if (!header) return false;
|
|
if (this.blobs) return true;
|
|
const contentKey = header.metadata && header.metadata.contentFeed && header.metadata.contentFeed.subarray(0, 32);
|
|
const blobsKey = contentKey || Hypercore.key(this._generateBlobsManifest());
|
|
if (!blobsKey || blobsKey.length < 32) throw new Error("Invalid or no Blob store key set");
|
|
const blobsCore = this.corestore.get({
|
|
key: blobsKey,
|
|
cache: false,
|
|
onwait: this._onwait,
|
|
encryptionKey: this.encryptionKey,
|
|
keyPair: !contentKey && this.db.core.writable ? this.db.core.keyPair : null,
|
|
active: this._active
|
|
});
|
|
await blobsCore.ready();
|
|
if (this.closing) {
|
|
await blobsCore.close();
|
|
return false;
|
|
}
|
|
this.blobs = new Hyperblobs(blobsCore);
|
|
this.emit("blobs", this.blobs);
|
|
this.emit("content-key", blobsCore.key);
|
|
return true;
|
|
}
|
|
async _open() {
|
|
if (this._checkout) {
|
|
await this._checkout.ready();
|
|
this.blobs = this._checkout.blobs;
|
|
return;
|
|
}
|
|
await this._openBlobsFromHeader({ wait: false });
|
|
if (this.db.core.writable && !this.blobs) {
|
|
const m = this._generateBlobsManifest();
|
|
const blobsCore = this.corestore.get({
|
|
manifest: m,
|
|
name: m ? null : this.db.core.id + "/blobs",
|
|
// simple trick to avoid blobs clashing if no namespace is provided...
|
|
cache: false,
|
|
onwait: this._onwait,
|
|
encryptionKey: this.encryptionKey,
|
|
compat: this.db.core.core.compat,
|
|
active: this._active,
|
|
keyPair: m && this.db.core.writable ? this.db.core.keyPair : null
|
|
});
|
|
await blobsCore.ready();
|
|
this.blobs = new Hyperblobs(blobsCore);
|
|
if (!m) getBee(this.db).metadata.contentFeed = this.blobs.core.key;
|
|
this.emit("blobs", this.blobs);
|
|
this.emit("content-key", blobsCore.key);
|
|
}
|
|
await this.db.ready();
|
|
if (!this.blobs) {
|
|
this._openingBlobs = this._openBlobsFromHeader();
|
|
this._openingBlobs.catch(safetyCatch);
|
|
}
|
|
}
|
|
async getBlobs() {
|
|
if (this.blobs) return this.blobs;
|
|
if (this._checkout) {
|
|
this.blobs = await this._checkout.getBlobs();
|
|
} else {
|
|
await this.ready();
|
|
await this._openingBlobs;
|
|
}
|
|
return this.blobs;
|
|
}
|
|
monitor(name, opts = {}) {
|
|
const monitor = new Monitor(this, { name, ...opts });
|
|
this.monitors.add(monitor);
|
|
return monitor;
|
|
}
|
|
async closeMonitors() {
|
|
const closing = [];
|
|
for (const monitor of this.monitors) closing.push(monitor.close());
|
|
await Promise.allSettled(closing);
|
|
}
|
|
async get(name, opts) {
|
|
const node = await this.entry(name, opts);
|
|
if (!node?.value.blob) return null;
|
|
await this.getBlobs();
|
|
const res = await this.blobs.get(node.value.blob, opts);
|
|
if (res === null) throw BLOCK_NOT_AVAILABLE();
|
|
return res;
|
|
}
|
|
async put(name, buf, { executable = false, metadata = null } = {}) {
|
|
await this.getBlobs();
|
|
const blob = await this.blobs.put(buf);
|
|
return this.db.put(std(name, false), { executable, linkname: null, blob, metadata }, { keyEncoding });
|
|
}
|
|
async del(name) {
|
|
return this.db.del(std(name, false), { keyEncoding });
|
|
}
|
|
compare(a, b) {
|
|
const diff = a.seq - b.seq;
|
|
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
|
|
}
|
|
async clear(name, opts) {
|
|
if (!this.opened) await this.ready();
|
|
let node = null;
|
|
try {
|
|
node = await this.entry(name, { wait: false });
|
|
} catch {
|
|
}
|
|
if (node === null || this.blobs === null) {
|
|
return opts && opts.diff ? { blocks: 0 } : null;
|
|
}
|
|
return this.blobs.clear(node.value.blob, opts);
|
|
}
|
|
async clearAll(opts) {
|
|
if (!this.opened) await this.ready();
|
|
if (this.blobs === null) {
|
|
return opts && opts.diff ? { blocks: 0 } : null;
|
|
}
|
|
return this.blobs.core.clear(0, this.blobs.core.length, opts);
|
|
}
|
|
async purge() {
|
|
if (this._checkout || this._batch) throw new Error("Can only purge the main session");
|
|
await this.ready();
|
|
await this.close();
|
|
const proms = [this.core.purge()];
|
|
if (this.blobs) proms.push(this.blobs.core.purge());
|
|
await Promise.all(proms);
|
|
}
|
|
async symlink(name, dst, { metadata = null } = {}) {
|
|
return this.db.put(std(name, false), { executable: false, linkname: dst, blob: null, metadata }, { keyEncoding });
|
|
}
|
|
async entry(name, opts) {
|
|
if (!opts || !opts.follow) return this._entry(name, opts);
|
|
for (let i = 0; i < 16; i++) {
|
|
const node = await this._entry(name, opts);
|
|
if (!node || !node.value.linkname) return node;
|
|
name = unixPathResolve(node.key, node.value.linkname);
|
|
}
|
|
throw new Error("Recursive symlink");
|
|
}
|
|
async _entry(name, opts) {
|
|
if (typeof name !== "string") return name;
|
|
return this.db.get(std(name, false), { ...opts, keyEncoding });
|
|
}
|
|
async exists(name) {
|
|
return await this.entry(name) !== null;
|
|
}
|
|
watch(folder) {
|
|
folder = std(folder || "/", true);
|
|
return this.db.watch(prefixRange(folder), { keyEncoding, map: (snap) => this._makeCheckout(snap) });
|
|
}
|
|
diff(length, folder, opts) {
|
|
if (typeof folder === "object" && folder && !opts) return this.diff(length, null, folder);
|
|
folder = std(folder || "/", true);
|
|
return this.db.createDiffStream(length, prefixRange(folder), { ...opts, keyEncoding });
|
|
}
|
|
async downloadDiff(length, folder, opts) {
|
|
const dls = [];
|
|
for await (const entry of this.diff(length, folder, opts)) {
|
|
if (!entry.left) continue;
|
|
const b = entry.left.value.blob;
|
|
if (!b) continue;
|
|
const blobs = await this.getBlobs();
|
|
dls.push(blobs.core.download({ start: b.blockOffset, length: b.blockLength }));
|
|
}
|
|
const proms = [];
|
|
for (const r of dls) proms.push(r.downloaded());
|
|
await Promise.allSettled(proms);
|
|
}
|
|
async downloadRange(dbRanges, blobRanges) {
|
|
const dls = [];
|
|
await this.ready();
|
|
for (const range of dbRanges) {
|
|
dls.push(this.db.core.download(range));
|
|
}
|
|
const blobs = await this.getBlobs();
|
|
for (const range of blobRanges) {
|
|
dls.push(blobs.core.download(range));
|
|
}
|
|
const proms = [];
|
|
for (const r of dls) proms.push(r.downloaded());
|
|
await Promise.allSettled(proms);
|
|
}
|
|
entries(range, opts) {
|
|
const stream = this.db.createReadStream(range, { ...opts, keyEncoding });
|
|
if (opts && opts.ignore) stream._readableState.map = createStreamMapIgnore(opts.ignore);
|
|
return stream;
|
|
}
|
|
async download(folder = "/", opts) {
|
|
if (typeof folder === "object") return this.download(void 0, folder);
|
|
const dls = [];
|
|
const entry = !folder || folder.endsWith("/") ? null : await this.entry(folder);
|
|
if (entry) {
|
|
const b = entry.value.blob;
|
|
if (!b) return;
|
|
const blobs = await this.getBlobs();
|
|
await blobs.core.download({ start: b.blockOffset, length: b.blockLength }).downloaded();
|
|
return;
|
|
}
|
|
for await (const _ of this.list(folder, opts)) {
|
|
}
|
|
for await (const entry2 of this.list(folder, opts)) {
|
|
const b = entry2.value.blob;
|
|
if (!b) continue;
|
|
const blobs = await this.getBlobs();
|
|
dls.push(blobs.core.download({ start: b.blockOffset, length: b.blockLength }));
|
|
}
|
|
const proms = [];
|
|
for (const r of dls) proms.push(r.downloaded());
|
|
await Promise.allSettled(proms);
|
|
}
|
|
// atm always recursive, but we should add some depth thing to it
|
|
list(folder, opts = {}) {
|
|
if (typeof folder === "object") return this.list(void 0, folder);
|
|
folder = std(folder || "/", true);
|
|
const ignore = opts.ignore ? normalizeIgnore(opts.ignore) : null;
|
|
const stream = opts && opts.recursive === false ? shallowReadStream(this.db, folder, false, ignore, opts) : this.entries(prefixRange(folder), { ...opts, ignore });
|
|
return stream;
|
|
}
|
|
readdir(folder, opts) {
|
|
folder = std(folder || "/", true);
|
|
return shallowReadStream(this.db, folder, true, null, opts);
|
|
}
|
|
mirror(out, opts) {
|
|
return new MirrorDrive(this, out, opts);
|
|
}
|
|
createReadStream(name, opts) {
|
|
const self2 = this;
|
|
let destroyed = false;
|
|
let rs = null;
|
|
const stream = new Readable({
|
|
open(cb) {
|
|
self2.getBlobs().then(onblobs, cb);
|
|
function onblobs() {
|
|
self2.entry(name).then(onnode, cb);
|
|
}
|
|
function onnode(node) {
|
|
if (destroyed) return cb(null);
|
|
if (!node) return cb(new Error("Blob does not exist"));
|
|
if (self2.closing) return cb(new Error("Closed"));
|
|
if (!node.value.blob) {
|
|
stream.push(null);
|
|
return cb(null);
|
|
}
|
|
rs = self2.blobs.createReadStream(node.value.blob, opts);
|
|
rs.on("data", function(data) {
|
|
if (!stream.push(data)) rs.pause();
|
|
});
|
|
rs.on("end", function() {
|
|
stream.push(null);
|
|
});
|
|
rs.on("error", function(err) {
|
|
stream.destroy(err);
|
|
});
|
|
cb(null);
|
|
}
|
|
},
|
|
read(cb) {
|
|
rs.resume();
|
|
cb(null);
|
|
},
|
|
predestroy() {
|
|
destroyed = true;
|
|
if (rs) rs.destroy();
|
|
}
|
|
});
|
|
return stream;
|
|
}
|
|
createWriteStream(name, { executable = false, metadata = null } = {}) {
|
|
const self2 = this;
|
|
let destroyed = false;
|
|
let ws = null;
|
|
let ondrain = null;
|
|
let onfinish = null;
|
|
const stream = new Writable({
|
|
open(cb) {
|
|
self2.getBlobs().then(onblobs, cb);
|
|
function onblobs() {
|
|
if (destroyed) return cb(null);
|
|
ws = self2.blobs.createWriteStream();
|
|
ws.on("error", function(err) {
|
|
stream.destroy(err);
|
|
});
|
|
ws.on("close", function() {
|
|
const err = new Error("Closed");
|
|
callOndrain(err);
|
|
callOnfinish(err);
|
|
});
|
|
ws.on("finish", function() {
|
|
callOnfinish(null);
|
|
});
|
|
ws.on("drain", function() {
|
|
callOndrain(null);
|
|
});
|
|
cb(null);
|
|
}
|
|
},
|
|
write(data, cb) {
|
|
if (ws.write(data) === true) return cb(null);
|
|
ondrain = cb;
|
|
},
|
|
final(cb) {
|
|
onfinish = cb;
|
|
ws.end();
|
|
},
|
|
predestroy() {
|
|
destroyed = true;
|
|
if (ws) ws.destroy();
|
|
}
|
|
});
|
|
return stream;
|
|
function callOnfinish(err) {
|
|
if (!onfinish) return;
|
|
const cb = onfinish;
|
|
onfinish = null;
|
|
if (err) return cb(err);
|
|
self2.db.put(std(name, false), { executable, linkname: null, blob: ws.id, metadata }, { keyEncoding }).then(() => cb(null), cb);
|
|
}
|
|
function callOndrain(err) {
|
|
if (ondrain) {
|
|
const cb = ondrain;
|
|
ondrain = null;
|
|
cb(err);
|
|
}
|
|
}
|
|
}
|
|
static normalizePath(name) {
|
|
return std(name, false);
|
|
}
|
|
};
|
|
function shallowReadStream(files, folder, keys, ignore, opts) {
|
|
let prev = "/";
|
|
let prevName = "";
|
|
return new Readable({
|
|
async read(cb) {
|
|
let node = null;
|
|
try {
|
|
node = await files.peek(prefixRange(folder, prev), { ...opts, keyEncoding });
|
|
} catch (err) {
|
|
return cb(err);
|
|
}
|
|
if (!node) {
|
|
this.push(null);
|
|
return cb(null);
|
|
}
|
|
const suffix = node.key.slice(folder.length + 1);
|
|
const i = suffix.indexOf("/");
|
|
const name = i === -1 ? suffix : suffix.slice(0, i);
|
|
prev = "/" + name + (i === -1 ? "" : "0");
|
|
if (name === prevName) {
|
|
this._read(cb);
|
|
return;
|
|
}
|
|
prevName = name;
|
|
if (ignore && isIgnored(node.key, ignore)) {
|
|
this._read(cb);
|
|
return;
|
|
}
|
|
this.push(keys ? name : node);
|
|
cb(null);
|
|
}
|
|
});
|
|
}
|
|
function makeBee(key, corestore, opts = {}) {
|
|
const name = key ? void 0 : "db";
|
|
const core = corestore.get({ key, name, exclusive: true, onwait: opts.onwait, encryptionKey: opts.encryptionKey, compat: opts.compat, active: opts.active });
|
|
return new Hyperbee(core, {
|
|
keyEncoding: "utf-8",
|
|
valueEncoding: "json",
|
|
metadata: { contentFeed: null }
|
|
});
|
|
}
|
|
function getBee(bee) {
|
|
return bee.tree || bee;
|
|
}
|
|
function std(name, removeSlash) {
|
|
name = unixPathResolve("/", name);
|
|
if (removeSlash && name.endsWith("/")) name = name.slice(0, -1);
|
|
validateFilename(name);
|
|
return name;
|
|
}
|
|
function validateFilename(name) {
|
|
if (name === "/") throw new Error("Invalid filename: " + name);
|
|
}
|
|
function prefixRange(name, prev = "/") {
|
|
return { gt: name + prev, lt: name + "0" };
|
|
}
|
|
function generateContentManifest(m, key) {
|
|
if (m.version < 1) return null;
|
|
const signers = [];
|
|
if (!key) key = Hypercore.key(m);
|
|
for (const s of m.signers) {
|
|
const namespace = crypto.hash([BLOBS, key, s.namespace]);
|
|
signers.push({ ...s, namespace });
|
|
}
|
|
return {
|
|
version: m.version,
|
|
hash: "blake2b",
|
|
allowPatch: m.allowPatch,
|
|
quorum: m.quorum,
|
|
signers,
|
|
prologue: null
|
|
// NOTE: could be configurable through the header still...
|
|
};
|
|
}
|
|
async function getBlobsLength(db) {
|
|
let length = 0;
|
|
for await (const { value } of db.createReadStream()) {
|
|
const b = value && value.blob;
|
|
if (!b) continue;
|
|
const len = b.blockOffset + b.blockLength;
|
|
if (len > length) length = len;
|
|
}
|
|
return length;
|
|
}
|
|
function normalizeIgnore(ignore) {
|
|
return [].concat(ignore).map((e) => unixPathResolve("/", e));
|
|
}
|
|
function isIgnored(key, ignore) {
|
|
return ignore.some((e) => e === key || key.startsWith(e + "/"));
|
|
}
|
|
function createStreamMapIgnore(ignore) {
|
|
return (node) => {
|
|
return isIgnored(node.key, ignore) ? null : node;
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/drive/shared/open.js
|
|
var require_open = __commonJS({
|
|
"../../node_modules/bare-dev/lib/drive/shared/open.js"(exports, module) {
|
|
var path = __require("path");
|
|
var Hyperdrive = require_hyperdrive();
|
|
var Localdrive = require_localdrive();
|
|
var id = require_hypercore_id_encoding();
|
|
module.exports = async function open(key, opts = {}) {
|
|
const {
|
|
store,
|
|
swarm = null,
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
if (!isKey(key)) return new Localdrive(path.resolve(cwd, key));
|
|
const drive = new Hyperdrive(store, id.decode(key));
|
|
await drive.ready();
|
|
if (swarm) {
|
|
swarm.join(drive.discoveryKey);
|
|
const done = store.findingPeers();
|
|
swarm.flush().then(done);
|
|
await drive.core.update();
|
|
}
|
|
return drive;
|
|
};
|
|
function isKey(key) {
|
|
return (key.length === 52 || key.length === 64) && key.indexOf("/") === -1 && key.indexOf("\\") === -1 && key.indexOf(".") === -1;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/read-write-mutexify/index.js
|
|
var require_read_write_mutexify = __commonJS({
|
|
"../../node_modules/read-write-mutexify/index.js"(exports, module) {
|
|
var WriteLock = class {
|
|
constructor(parent) {
|
|
this.writing = false;
|
|
this._waiting = [];
|
|
this._parent = parent;
|
|
this._wait = pushToQueue.bind(this, this._waiting);
|
|
}
|
|
get locked() {
|
|
return this.writing || this._parent.read.readers > 0;
|
|
}
|
|
get waiting() {
|
|
return this._waiting.length;
|
|
}
|
|
lock() {
|
|
if (this._parent._destroying) {
|
|
return Promise.reject(this._parent._destroyError);
|
|
}
|
|
if (this.writing === false && this._parent.read.readers === 0) {
|
|
this.writing = true;
|
|
return Promise.resolve();
|
|
}
|
|
return new Promise(this._wait);
|
|
}
|
|
unlock() {
|
|
this.writing = false;
|
|
this._parent._bump();
|
|
}
|
|
async flush() {
|
|
if (this.writing === false) return;
|
|
try {
|
|
await this.lock();
|
|
} catch {
|
|
return;
|
|
}
|
|
this.unlock();
|
|
}
|
|
};
|
|
var ReadLock = class {
|
|
constructor(parent) {
|
|
this.readers = 0;
|
|
this._waiting = [];
|
|
this._parent = parent;
|
|
this._wait = pushToQueue.bind(this, this._waiting);
|
|
}
|
|
get locked() {
|
|
return this._parent.writing;
|
|
}
|
|
get waiting() {
|
|
return this._waiting.length;
|
|
}
|
|
lock() {
|
|
if (this._parent._destroying) {
|
|
return Promise.reject(this._parent._destroyError);
|
|
}
|
|
if (this._parent.write.writing === false) {
|
|
this.readers++;
|
|
return Promise.resolve();
|
|
}
|
|
return new Promise(this._wait);
|
|
}
|
|
unlock() {
|
|
this.readers--;
|
|
this._parent._bump();
|
|
}
|
|
async flush() {
|
|
if (this.writing === false) return;
|
|
try {
|
|
await this.lock();
|
|
} catch {
|
|
return;
|
|
}
|
|
this.unlock();
|
|
}
|
|
};
|
|
module.exports = class ReadWriteLock {
|
|
constructor() {
|
|
this.read = new ReadLock(this);
|
|
this.write = new WriteLock(this);
|
|
this._destroyError = null;
|
|
this._destroying = null;
|
|
}
|
|
get destroyed() {
|
|
return !!this._destroying;
|
|
}
|
|
destroy(err) {
|
|
if (this._destroying) return this._destroying;
|
|
this._destroying = Promise.all([this.read.flush(), this.write.flush()]);
|
|
this._destroyError = err || new Error("Mutex has been destroyed");
|
|
if (err) {
|
|
while (this.read._waiting) this._waiting.shift()[1](err);
|
|
while (this.write._waiting) this._waiting.shift()[1](err);
|
|
}
|
|
return this._destroying;
|
|
}
|
|
_bump() {
|
|
if (this.write.writing === false && this.read.readers === 0 && this.write._waiting.length > 0) {
|
|
this.write.writing = true;
|
|
this.write._waiting.shift()[0]();
|
|
}
|
|
while (this.write.writing === false && this.read._waiting.length > 0) {
|
|
this.read.readers++;
|
|
this.read._waiting.shift()[0]();
|
|
}
|
|
}
|
|
};
|
|
function pushToQueue(queue, resolve, reject) {
|
|
queue.push([resolve, reject]);
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/node_modules/corestore/index.js
|
|
var require_corestore = __commonJS({
|
|
"../../node_modules/bare-dev/node_modules/corestore/index.js"(exports, module) {
|
|
var safetyCatch = require_safety_catch();
|
|
var crypto = require_hypercore_crypto();
|
|
var sodium = require_sodium_universal2();
|
|
var Hypercore = require_hypercore();
|
|
var hypercoreId = require_hypercore_id_encoding();
|
|
var Xache = require_xache();
|
|
var b4a = require_b4a();
|
|
var ReadyResource = require_ready_resource();
|
|
var RW = require_read_write_mutexify();
|
|
var [NS] = crypto.namespace("corestore", 1);
|
|
var DEFAULT_NAMESPACE = b4a.alloc(32);
|
|
var CORES_DIR = "cores";
|
|
var PRIMARY_KEY_FILE_NAME = "primary-key";
|
|
var USERDATA_NAME_KEY = "corestore/name";
|
|
var USERDATA_NAMESPACE_KEY = "corestore/namespace";
|
|
var POOL_SIZE = 512;
|
|
var DEFAULT_MANIFEST = 0;
|
|
var DEFAULT_COMPAT = true;
|
|
module.exports = class Corestore extends ReadyResource {
|
|
constructor(storage, opts = {}) {
|
|
super();
|
|
const root = opts._root;
|
|
this.storage = Hypercore.defaultStorage(storage, { lock: PRIMARY_KEY_FILE_NAME, poolSize: opts.poolSize || POOL_SIZE, rmdir: true });
|
|
this.cores = root ? root.cores : /* @__PURE__ */ new Map();
|
|
this.cache = !!opts.cache;
|
|
this.primaryKey = opts.primaryKey || null;
|
|
this.passive = !!opts.passive;
|
|
this.manifestVersion = typeof opts.manifestVersion === "number" ? opts.manifestVersion : root ? root.manifestVersion : DEFAULT_MANIFEST;
|
|
this.compat = typeof opts.compat === "boolean" ? opts.compat : root ? root.compat : DEFAULT_COMPAT;
|
|
this.inflightRange = opts.inflightRange || null;
|
|
this.globalCache = opts.globalCache || null;
|
|
this._keyStorage = null;
|
|
this._bootstrap = opts._bootstrap || null;
|
|
this._namespace = opts.namespace || DEFAULT_NAMESPACE;
|
|
this._noCoreCache = root ? root._noCoreCache : new Xache({ maxSize: 65536 });
|
|
this._root = root || this;
|
|
this._replicationStreams = root ? root._replicationStreams : [];
|
|
this._overwrite = opts.overwrite === true;
|
|
this._readonly = opts.writable === false;
|
|
this._attached = opts._attached || null;
|
|
this._notDownloadingLinger = opts.notDownloadingLinger;
|
|
this._sessions = /* @__PURE__ */ new Set();
|
|
this._rootStoreSessions = /* @__PURE__ */ new Set();
|
|
this._locks = root ? root._locks : /* @__PURE__ */ new Map();
|
|
this._findingPeersCount = 0;
|
|
this._findingPeers = [];
|
|
this._isCorestore = true;
|
|
if (this._namespace.byteLength !== 32) throw new Error("Namespace must be a 32-byte Buffer or Uint8Array");
|
|
this.ready().catch(safetyCatch);
|
|
}
|
|
static isCorestore(obj) {
|
|
return !!(typeof obj === "object" && obj && obj._isCorestore);
|
|
}
|
|
static from(storage, opts) {
|
|
return this.isCorestore(storage) ? storage : new this(storage, opts);
|
|
}
|
|
// for now just release the lock...
|
|
async suspend() {
|
|
if (this._root !== this) return this._root.suspend();
|
|
await this.ready();
|
|
if (this._keyStorage !== null) {
|
|
await new Promise((resolve, reject) => {
|
|
this._keyStorage.suspend((err) => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
async resume() {
|
|
if (this._root !== this) return this._root.resume();
|
|
await this.ready();
|
|
if (this._keyStorage !== null) {
|
|
await new Promise((resolve, reject) => {
|
|
this._keyStorage.open((err) => {
|
|
if (err) return reject(err);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
findingPeers() {
|
|
let done = false;
|
|
this._incFindingPeers();
|
|
return () => {
|
|
if (done) return;
|
|
done = true;
|
|
this._decFindingPeers();
|
|
};
|
|
}
|
|
_emitCore(name, core) {
|
|
this.emit(name, core);
|
|
for (const session of this._root._rootStoreSessions) {
|
|
if (session !== this) {
|
|
session.emit(name, core);
|
|
}
|
|
}
|
|
if (this !== this._root) this._root.emit(name, core);
|
|
}
|
|
_incFindingPeers() {
|
|
if (++this._findingPeersCount !== 1) return;
|
|
for (const core of this._sessions) {
|
|
this._findingPeers.push(core.findingPeers());
|
|
}
|
|
}
|
|
_decFindingPeers() {
|
|
if (--this._findingPeersCount !== 0) return;
|
|
while (this._findingPeers.length > 0) {
|
|
this._findingPeers.pop()();
|
|
}
|
|
}
|
|
async _openNamespaceFromBootstrap() {
|
|
const ns = await this._bootstrap.getUserData(USERDATA_NAMESPACE_KEY);
|
|
if (ns) {
|
|
this._namespace = ns;
|
|
}
|
|
}
|
|
async _open() {
|
|
if (this._root !== this) {
|
|
await this._root.ready();
|
|
if (!this.primaryKey) this.primaryKey = this._root.primaryKey;
|
|
if (this._bootstrap) await this._openNamespaceFromBootstrap();
|
|
return;
|
|
}
|
|
this._keyStorage = this.storage(PRIMARY_KEY_FILE_NAME);
|
|
this.primaryKey = await new Promise((resolve, reject) => {
|
|
this._keyStorage.stat((err, st) => {
|
|
if (err && err.code !== "ENOENT") return reject(err);
|
|
if (err || st.size < 32 || this._overwrite) {
|
|
const key = this.primaryKey || crypto.randomBytes(32);
|
|
return this._keyStorage.write(0, key, (err2) => {
|
|
if (err2) return reject(err2);
|
|
return resolve(key);
|
|
});
|
|
}
|
|
this._keyStorage.read(0, 32, (err2, key) => {
|
|
if (err2) return reject(err2);
|
|
if (this.primaryKey) return resolve(this.primaryKey);
|
|
return resolve(key);
|
|
});
|
|
});
|
|
});
|
|
if (this._bootstrap) await this._openNamespaceFromBootstrap();
|
|
}
|
|
async _exists(discoveryKey) {
|
|
const id = b4a.toString(discoveryKey, "hex");
|
|
const storageRoot = getStorageRoot(id);
|
|
const st = this.storage(storageRoot + "/oplog");
|
|
const exists = await new Promise((resolve) => st.stat((err, st2) => resolve(!err && st2.size > 0)));
|
|
await new Promise((resolve) => st.close(resolve));
|
|
return exists;
|
|
}
|
|
async _generateKeys(opts) {
|
|
if (opts._discoveryKey) {
|
|
return {
|
|
manifest: null,
|
|
keyPair: null,
|
|
key: null,
|
|
discoveryKey: opts._discoveryKey
|
|
};
|
|
}
|
|
const keyPair = opts.name ? await this.createKeyPair(opts.name) : opts.secretKey ? { secretKey: opts.secretKey, publicKey: opts.publicKey } : null;
|
|
if (opts.manifest) {
|
|
const key = Hypercore.key(opts.manifest);
|
|
return {
|
|
manifest: opts.manifest,
|
|
keyPair,
|
|
key,
|
|
discoveryKey: crypto.discoveryKey(key)
|
|
};
|
|
}
|
|
if (opts.key) {
|
|
return {
|
|
manifest: null,
|
|
keyPair,
|
|
key: opts.key,
|
|
discoveryKey: crypto.discoveryKey(opts.key)
|
|
};
|
|
}
|
|
const publicKey = opts.publicKey || keyPair.publicKey;
|
|
if (opts.compat === false || opts.compat !== true && !this.compat) {
|
|
let manifest = { version: this.manifestVersion, signers: [{ publicKey }] };
|
|
let key = Hypercore.key(manifest);
|
|
let discoveryKey = crypto.discoveryKey(key);
|
|
if (!await this._exists(discoveryKey) && manifest.version !== 0) {
|
|
const manifestV0 = { version: 0, signers: [{ publicKey }] };
|
|
const keyV0 = Hypercore.key(manifestV0);
|
|
const discoveryKeyV0 = crypto.discoveryKey(keyV0);
|
|
if (await this._exists(discoveryKeyV0)) {
|
|
manifest = manifestV0;
|
|
key = keyV0;
|
|
discoveryKey = discoveryKeyV0;
|
|
}
|
|
}
|
|
return {
|
|
manifest,
|
|
keyPair,
|
|
key,
|
|
discoveryKey
|
|
};
|
|
}
|
|
return {
|
|
manifest: null,
|
|
keyPair,
|
|
key: publicKey,
|
|
discoveryKey: crypto.discoveryKey(publicKey)
|
|
};
|
|
}
|
|
_getPrereadyUserData(core, key) {
|
|
for (const { key: savedKey, value } of core.core.header.userData) {
|
|
if (key === savedKey) return value;
|
|
}
|
|
return null;
|
|
}
|
|
async _preready(core) {
|
|
const name = this._getPrereadyUserData(core, USERDATA_NAME_KEY);
|
|
if (!name) return;
|
|
const namespace = this._getPrereadyUserData(core, USERDATA_NAMESPACE_KEY);
|
|
const keyPair = await this.createKeyPair(b4a.toString(name), namespace);
|
|
core.setKeyPair(keyPair);
|
|
}
|
|
_getLock(id) {
|
|
let rw = this._locks.get(id);
|
|
if (!rw) {
|
|
rw = new RW();
|
|
this._locks.set(id, rw);
|
|
}
|
|
return rw;
|
|
}
|
|
async _preload(id, keys, opts) {
|
|
const { manifest, keyPair, key } = keys;
|
|
while (this.cores.has(id)) {
|
|
const existing = this.cores.get(id);
|
|
if (existing.opened && !existing.closing) return { from: existing, keyPair, manifest, cache: !!opts.cache };
|
|
if (existing.closing) {
|
|
await existing.close();
|
|
} else {
|
|
await existing.ready().catch(safetyCatch);
|
|
}
|
|
}
|
|
const hasKeyPair = !!(keyPair && keyPair.secretKey);
|
|
const userData = {};
|
|
if (opts.name) {
|
|
userData[USERDATA_NAME_KEY] = b4a.from(opts.name);
|
|
userData[USERDATA_NAMESPACE_KEY] = this._namespace;
|
|
}
|
|
const storageRoot = getStorageRoot(id);
|
|
const core = new Hypercore((p) => this.storage(storageRoot + "/" + p), {
|
|
_preready: this._preready.bind(this),
|
|
notDownloadingLinger: this._notDownloadingLinger,
|
|
inflightRange: this.inflightRange,
|
|
autoClose: true,
|
|
active: false,
|
|
encryptionKey: opts.encryptionKey || null,
|
|
isBlockKey: !!opts.isBlockKey,
|
|
userData,
|
|
manifest,
|
|
key,
|
|
compat: opts.compat,
|
|
cache: opts.cache,
|
|
globalCache: this.globalCache,
|
|
createIfMissing: opts.createIfMissing === false ? false : !opts._discoveryKey,
|
|
keyPair: hasKeyPair ? keyPair : null
|
|
});
|
|
if (this._root.closing) {
|
|
try {
|
|
await core.close();
|
|
} catch {
|
|
}
|
|
throw new Error("The corestore is closed");
|
|
}
|
|
this.cores.set(id, core);
|
|
this._noCoreCache.delete(id);
|
|
core.ready().then(() => {
|
|
if (core.closing) return;
|
|
if (hasKeyPair) core.setKeyPair(keyPair);
|
|
this._emitCore("core-open", core);
|
|
if (this.passive) return;
|
|
const ondownloading = () => {
|
|
for (const { stream } of this._replicationStreams) {
|
|
core.replicate(stream, { session: true });
|
|
}
|
|
};
|
|
core.replicator.ondownloading = ondownloading;
|
|
if (core.replicator.downloading) ondownloading();
|
|
}, () => {
|
|
this._noCoreCache.set(id, true);
|
|
this.cores.delete(id);
|
|
});
|
|
core.once("close", () => {
|
|
this._emitCore("core-close", core);
|
|
this.cores.delete(id);
|
|
});
|
|
core.on("conflict", (len, fork, proof) => {
|
|
this.emit("conflict", core, len, fork, proof);
|
|
});
|
|
return { from: core, keyPair, manifest, cache: !!opts.cache };
|
|
}
|
|
async createKeyPair(name, namespace = this._namespace) {
|
|
if (!this.opened) await this.ready();
|
|
const keyPair = {
|
|
publicKey: b4a.allocUnsafeSlow(sodium.crypto_sign_PUBLICKEYBYTES),
|
|
secretKey: b4a.alloc(sodium.crypto_sign_SECRETKEYBYTES)
|
|
};
|
|
const seed = deriveSeed(this.primaryKey, namespace, name);
|
|
sodium.crypto_sign_seed_keypair(keyPair.publicKey, keyPair.secretKey, seed);
|
|
return keyPair;
|
|
}
|
|
get(opts = {}) {
|
|
if (this.closing || this._root.closing) throw new Error("The corestore is closed");
|
|
opts = validateGetOptions(opts);
|
|
if (opts.cache !== false) {
|
|
opts.cache = opts.cache === true || this.cache && !opts.cache ? defaultCache() : opts.cache;
|
|
}
|
|
if (this._readonly && opts.writable !== false) {
|
|
opts.writable = false;
|
|
}
|
|
let rw = null;
|
|
let id = null;
|
|
const core = new Hypercore(null, {
|
|
...opts,
|
|
globalCache: this.globalCache,
|
|
name: null,
|
|
preload: async () => {
|
|
if (opts.preload) opts = { ...opts, ...await opts.preload() };
|
|
if (!this.opened) await this.ready();
|
|
const keys = await this._generateKeys(opts);
|
|
id = b4a.toString(keys.discoveryKey, "hex");
|
|
rw = opts.exclusive && opts.writable !== false ? this._getLock(id) : null;
|
|
if (rw) await rw.write.lock();
|
|
return await this._preload(id, keys, opts);
|
|
}
|
|
});
|
|
this._sessions.add(core);
|
|
if (this._findingPeersCount > 0) {
|
|
this._findingPeers.push(core.findingPeers());
|
|
}
|
|
const gc = () => {
|
|
this._sessions.delete(core);
|
|
if (!rw) return;
|
|
rw.write.unlock();
|
|
if (!rw.write.locked) this._locks.delete(id);
|
|
};
|
|
core.ready().catch(gc);
|
|
core.once("close", gc);
|
|
return core;
|
|
}
|
|
replicate(isInitiator, opts) {
|
|
const isExternal = isStream(isInitiator) || !!(opts && opts.stream);
|
|
const stream = Hypercore.createProtocolStream(isInitiator, {
|
|
...opts,
|
|
ondiscoverykey: async (discoveryKey) => {
|
|
if (this.closing) return;
|
|
const id = b4a.toString(discoveryKey, "hex");
|
|
if (this._noCoreCache.get(id)) return;
|
|
const core = this.get({ _discoveryKey: discoveryKey, active: false });
|
|
try {
|
|
await core.ready();
|
|
} catch {
|
|
return;
|
|
}
|
|
if (!core.closing) core.replicate(stream, { session: true });
|
|
await core.close();
|
|
}
|
|
});
|
|
if (!this.passive) {
|
|
const muxer = stream.noiseStream.userData;
|
|
muxer.cork();
|
|
for (const core of this.cores.values()) {
|
|
if (!core.opened || core.closing || !core.replicator.downloading) continue;
|
|
core.replicate(stream, { session: true });
|
|
}
|
|
stream.noiseStream.opened.then(() => muxer.uncork());
|
|
}
|
|
const streamRecord = { stream, isExternal };
|
|
this._replicationStreams.push(streamRecord);
|
|
stream.once("close", () => {
|
|
this._replicationStreams.splice(this._replicationStreams.indexOf(streamRecord), 1);
|
|
});
|
|
return stream;
|
|
}
|
|
namespace(name, opts) {
|
|
if (name instanceof Hypercore) {
|
|
return this.session({ ...opts, _bootstrap: name });
|
|
}
|
|
return this.session({ ...opts, namespace: generateNamespace(this._namespace, name) });
|
|
}
|
|
session(opts) {
|
|
const session = new Corestore(this.storage, {
|
|
namespace: this._namespace,
|
|
cache: this.cache,
|
|
writable: !this._readonly,
|
|
_attached: opts && opts.detach === false ? this : null,
|
|
_root: this._root,
|
|
inflightRange: this.inflightRange,
|
|
globalCache: this.globalCache,
|
|
...opts
|
|
});
|
|
if (this === this._root) this._rootStoreSessions.add(session);
|
|
return session;
|
|
}
|
|
_closeNamespace() {
|
|
const closePromises = [];
|
|
for (const session of this._sessions) {
|
|
closePromises.push(session.close());
|
|
}
|
|
return Promise.allSettled(closePromises);
|
|
}
|
|
async _closePrimaryNamespace() {
|
|
const closePromises = [];
|
|
for (const { stream, isExternal } of this._replicationStreams) {
|
|
if (!isExternal) stream.destroy();
|
|
}
|
|
for (const core of this.cores.values()) {
|
|
closePromises.push(forceClose(core));
|
|
}
|
|
await Promise.allSettled(closePromises);
|
|
await new Promise((resolve, reject) => {
|
|
this._keyStorage.close((err) => {
|
|
if (err) return reject(err);
|
|
return resolve(null);
|
|
});
|
|
});
|
|
}
|
|
async _close() {
|
|
this._root._rootStoreSessions.delete(this);
|
|
await this._closeNamespace();
|
|
if (this._root === this) {
|
|
await this._closePrimaryNamespace();
|
|
} else if (this._attached) {
|
|
await this._attached.close();
|
|
}
|
|
}
|
|
};
|
|
function validateGetOptions(opts) {
|
|
const key = b4a.isBuffer(opts) || typeof opts === "string" ? hypercoreId.decode(opts) : null;
|
|
if (key) return { key };
|
|
if (opts.key) {
|
|
opts.key = hypercoreId.decode(opts.key);
|
|
}
|
|
if (opts.keyPair) {
|
|
opts.publicKey = opts.keyPair.publicKey;
|
|
opts.secretKey = opts.keyPair.secretKey;
|
|
}
|
|
if (opts.name && typeof opts.name !== "string") throw new Error("name option must be a String");
|
|
if (opts.name && opts.secretKey) throw new Error("Cannot provide both a name and a secret key");
|
|
if (opts.publicKey && !b4a.isBuffer(opts.publicKey)) throw new Error("publicKey option must be a Buffer or Uint8Array");
|
|
if (opts.secretKey && !b4a.isBuffer(opts.secretKey)) throw new Error("secretKey option must be a Buffer or Uint8Array");
|
|
if (!opts._discoveryKey && (!opts.name && !opts.publicKey && !opts.manifest && !opts.key && !opts.preload)) throw new Error("Must provide either a name or a publicKey");
|
|
return opts;
|
|
}
|
|
function generateNamespace(namespace, name) {
|
|
if (!b4a.isBuffer(name)) name = b4a.from(name);
|
|
const out = b4a.allocUnsafeSlow(32);
|
|
sodium.crypto_generichash_batch(out, [namespace, name]);
|
|
return out;
|
|
}
|
|
function deriveSeed(primaryKey, namespace, name) {
|
|
if (!b4a.isBuffer(name)) name = b4a.from(name);
|
|
const out = b4a.alloc(32);
|
|
sodium.crypto_generichash_batch(out, [NS, namespace, name], primaryKey);
|
|
return out;
|
|
}
|
|
function defaultCache() {
|
|
return new Xache({ maxSize: 65536, maxAge: 0 });
|
|
}
|
|
function isStream(s) {
|
|
return typeof s === "object" && s && typeof s.pipe === "function";
|
|
}
|
|
async function forceClose(core) {
|
|
await core.ready();
|
|
return Promise.all(core.sessions.map((s) => s.close()));
|
|
}
|
|
function getStorageRoot(id) {
|
|
return CORES_DIR + "/" + id.slice(0, 2) + "/" + id.slice(2, 4) + "/" + id;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/drive/shared/corestore.js
|
|
var require_corestore2 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/drive/shared/corestore.js"(exports, module) {
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var Corestore = require_corestore();
|
|
module.exports = function corestore(opts = {}) {
|
|
const {
|
|
corestore: corestore2 = process2.env.BARE_DEV_CORESTORE || "corestore",
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
return new Corestore(path.resolve(cwd, corestore2));
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/kademlia-routing-table/index.js
|
|
var require_kademlia_routing_table = __commonJS({
|
|
"../../node_modules/kademlia-routing-table/index.js"(exports, module) {
|
|
var { EventEmitter } = __require("events");
|
|
module.exports = class RoutingTable extends EventEmitter {
|
|
constructor(id, opts) {
|
|
if (!opts) opts = {};
|
|
super();
|
|
this.id = id;
|
|
this.k = opts.k || 20;
|
|
this.size = 0;
|
|
this.rows = new Array(id.length * 8);
|
|
}
|
|
add(node) {
|
|
const i = this._diff(node.id);
|
|
let row = this.rows[i];
|
|
if (!row) {
|
|
row = this.rows[i] = new Row(this, i);
|
|
this.emit("row", row);
|
|
}
|
|
const len = row.nodes.length;
|
|
if (!row.add(node, this.k)) return false;
|
|
this.size += row.nodes.length - len;
|
|
return true;
|
|
}
|
|
remove(id) {
|
|
const i = this._diff(id);
|
|
const row = this.rows[i];
|
|
if (!row) return false;
|
|
if (!row.remove(id)) return false;
|
|
this.size--;
|
|
return true;
|
|
}
|
|
get(id) {
|
|
const i = this._diff(id);
|
|
const row = this.rows[i];
|
|
if (!row) return null;
|
|
return row.get(id);
|
|
}
|
|
has(id) {
|
|
return this.get(id) !== null;
|
|
}
|
|
random() {
|
|
let n = Math.random() * this.size | 0;
|
|
for (let i = 0; i < this.rows.length; i++) {
|
|
const r = this.rows[i];
|
|
if (!r) continue;
|
|
if (n < r.nodes.length) return r.nodes[n];
|
|
n -= r.nodes.length;
|
|
}
|
|
return null;
|
|
}
|
|
closest(id, k) {
|
|
if (!k) k = this.k;
|
|
const result = [];
|
|
const d = this._diff(id);
|
|
for (let i = d; i >= 0 && result.length < k; i--) this._pushNodes(i, k, result);
|
|
for (let i = d + 1; i < this.rows.length && result.length < k; i++) this._pushNodes(i, k, result);
|
|
return result;
|
|
}
|
|
_pushNodes(i, k, result) {
|
|
const row = this.rows[i];
|
|
if (!row) return;
|
|
const missing = Math.min(k - result.length, row.nodes.length);
|
|
for (let j = 0; j < missing; j++) result.push(row.nodes[j]);
|
|
}
|
|
toArray() {
|
|
return this.closest(this.id, Infinity);
|
|
}
|
|
_diff(id) {
|
|
for (let i = 0; i < id.length; i++) {
|
|
const a = id[i];
|
|
const b = this.id[i];
|
|
if (a !== b) return i * 8 + Math.clz32(a ^ b) - 24;
|
|
}
|
|
return this.rows.length - 1;
|
|
}
|
|
};
|
|
var Row = class extends EventEmitter {
|
|
constructor(table, index) {
|
|
super();
|
|
this.data = null;
|
|
this.byteOffset = index >> 3;
|
|
this.index = index;
|
|
this.table = table;
|
|
this.nodes = [];
|
|
}
|
|
add(node) {
|
|
const id = node.id;
|
|
let l = 0;
|
|
let r = this.nodes.length - 1;
|
|
while (l <= r) {
|
|
const m = l + r >> 1;
|
|
const c = this.compare(id, this.nodes[m].id);
|
|
if (c === 0) {
|
|
this.nodes[m] = node;
|
|
return true;
|
|
}
|
|
if (c < 0) r = m - 1;
|
|
else l = m + 1;
|
|
}
|
|
if (this.nodes.length >= this.table.k) {
|
|
this.emit("full", node);
|
|
return false;
|
|
}
|
|
this.insert(l, node);
|
|
return true;
|
|
}
|
|
remove(id) {
|
|
let l = 0;
|
|
let r = this.nodes.length - 1;
|
|
while (l <= r) {
|
|
const m = l + r >> 1;
|
|
const c = this.compare(id, this.nodes[m].id);
|
|
if (c === 0) {
|
|
this.splice(m);
|
|
return true;
|
|
}
|
|
if (c < 0) r = m - 1;
|
|
else l = m + 1;
|
|
}
|
|
return false;
|
|
}
|
|
get(id) {
|
|
let l = 0;
|
|
let r = this.nodes.length - 1;
|
|
while (l <= r) {
|
|
const m = l + r >> 1;
|
|
const node = this.nodes[m];
|
|
const c = this.compare(id, node.id);
|
|
if (c === 0) return node;
|
|
if (c < 0) r = m - 1;
|
|
else l = m + 1;
|
|
}
|
|
return null;
|
|
}
|
|
insert(i, node) {
|
|
this.nodes.push(node);
|
|
for (let j = this.nodes.length - 1; j > i; j--) this.nodes[j] = this.nodes[j - 1];
|
|
this.nodes[i] = node;
|
|
this.emit("add", node);
|
|
}
|
|
splice(i) {
|
|
for (; i < this.nodes.length - 1; i++) this.nodes[i] = this.nodes[i + 1];
|
|
this.emit("remove", this.nodes.pop());
|
|
}
|
|
// very likely they diverge after a couple of bytes so a simple impl, like this is prop fastest vs Buffer.compare
|
|
compare(a, b) {
|
|
for (let i = this.byteOffset; i < a.length; i++) {
|
|
const ai = a[i];
|
|
const bi = b[i];
|
|
if (ai === bi) continue;
|
|
return ai < bi ? -1 : 1;
|
|
}
|
|
return 0;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/time-ordered-set/index.js
|
|
var require_time_ordered_set = __commonJS({
|
|
"../../node_modules/time-ordered-set/index.js"(exports, module) {
|
|
module.exports = class TimeOrderedSet {
|
|
constructor() {
|
|
this.oldest = null;
|
|
this.latest = null;
|
|
this.length = 0;
|
|
}
|
|
has(node) {
|
|
return !!(node.next || node.prev) || node === this.oldest;
|
|
}
|
|
add(node) {
|
|
if (this.has(node)) this.remove(node);
|
|
if (!this.latest && !this.oldest) {
|
|
this.latest = this.oldest = node;
|
|
node.prev = node.next = null;
|
|
} else {
|
|
this.latest.next = node;
|
|
node.prev = this.latest;
|
|
node.next = null;
|
|
this.latest = node;
|
|
}
|
|
this.length++;
|
|
return node;
|
|
}
|
|
remove(node) {
|
|
if (!this.has(node)) return node;
|
|
if (this.oldest !== node && this.latest !== node) {
|
|
node.prev.next = node.next;
|
|
node.next.prev = node.prev;
|
|
} else {
|
|
if (this.oldest === node) {
|
|
this.oldest = node.next;
|
|
if (this.oldest) this.oldest.prev = null;
|
|
}
|
|
if (this.latest === node) {
|
|
this.latest = node.prev;
|
|
if (this.latest) this.latest.next = null;
|
|
}
|
|
}
|
|
node.next = node.prev = null;
|
|
this.length--;
|
|
return node;
|
|
}
|
|
toArray({ limit = Infinity, reverse = false } = {}) {
|
|
const list = [];
|
|
if (reverse) {
|
|
let node = this.latest;
|
|
while (node && limit--) {
|
|
list.push(node);
|
|
node = node.prev;
|
|
}
|
|
} else {
|
|
let node = this.oldest;
|
|
while (node && limit--) {
|
|
list.push(node);
|
|
node = node.next;
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/udx-native/binding.js
|
|
var require_binding7 = __commonJS({
|
|
"../../node_modules/udx-native/binding.js"(exports, module) {
|
|
__require.addon = require_node2();
|
|
module.exports = __require.addon(".", __filename);
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/udx-native/lib/ip.js
|
|
var require_ip = __commonJS({
|
|
"../../node_modules/udx-native/lib/ip.js"(exports) {
|
|
var v4Seg = "(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])";
|
|
var v4Str = `(${v4Seg}[.]){3}${v4Seg}`;
|
|
var IPv4Pattern = new RegExp(`^${v4Str}$`);
|
|
var v6Seg = "(?:[0-9a-fA-F]{1,4})";
|
|
var IPv6Pattern = new RegExp(
|
|
`^((?:${v6Seg}:){7}(?:${v6Seg}|:)|(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:)))(%[0-9a-zA-Z-.:]{1,})?$`
|
|
);
|
|
var isIPv4 = exports.isIPv4 = function isIPv42(host) {
|
|
return IPv4Pattern.test(host);
|
|
};
|
|
var isIPv6 = exports.isIPv6 = function isIPv62(host) {
|
|
return IPv6Pattern.test(host);
|
|
};
|
|
exports.isIP = function isIP(host) {
|
|
if (isIPv4(host)) return 4;
|
|
if (isIPv6(host)) return 6;
|
|
return 0;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/udx-native/lib/socket.js
|
|
var require_socket = __commonJS({
|
|
"../../node_modules/udx-native/lib/socket.js"(exports, module) {
|
|
var events = __require("events");
|
|
var b4a = require_b4a();
|
|
var binding = require_binding7();
|
|
var ip = require_ip();
|
|
module.exports = class UDXSocket extends events.EventEmitter {
|
|
constructor(udx, opts = {}) {
|
|
super();
|
|
this.udx = udx;
|
|
this._handle = b4a.alloc(binding.sizeof_udx_napi_socket_t);
|
|
this._inited = false;
|
|
this._host = null;
|
|
this._family = 0;
|
|
this._ipv6Only = opts.ipv6Only === true;
|
|
this._reuseAddress = opts.reuseAddress === true;
|
|
this._port = 0;
|
|
this._reqs = [];
|
|
this._free = [];
|
|
this._closing = null;
|
|
this._closed = false;
|
|
this._view64 = new BigUint64Array(
|
|
this._handle.buffer,
|
|
this._handle.byteOffset,
|
|
this._handle.byteLength >> 3
|
|
);
|
|
this.streams = /* @__PURE__ */ new Set();
|
|
this.userData = null;
|
|
}
|
|
get bound() {
|
|
return this._port !== 0;
|
|
}
|
|
get closing() {
|
|
return this._closing !== null;
|
|
}
|
|
get idle() {
|
|
return this.streams.size === 0;
|
|
}
|
|
get busy() {
|
|
return this.streams.size > 0;
|
|
}
|
|
get bytesTransmitted() {
|
|
if (this._inited !== true) return 0;
|
|
return Number(this._view64[binding.offsetof_udx_socket_t_bytes_tx >> 3]);
|
|
}
|
|
get packetsTransmitted() {
|
|
if (this._inited !== true) return 0;
|
|
return Number(this._view64[binding.offsetof_udx_socket_t_packets_tx >> 3]);
|
|
}
|
|
get bytesReceived() {
|
|
if (this._inited !== true) return 0;
|
|
return Number(this._view64[binding.offsetof_udx_socket_t_bytes_rx >> 3]);
|
|
}
|
|
get packetsReceived() {
|
|
if (this._inited !== true) return 0;
|
|
return Number(this._view64[binding.offsetof_udx_socket_t_packets_rx >> 3]);
|
|
}
|
|
get packetsDroppedByKernel() {
|
|
if (this._inited !== true) return 0;
|
|
return Number(this._view64[binding.offsetof_udx_socket_t_packets_dropped_by_kernel >> 3]);
|
|
}
|
|
toJSON() {
|
|
return {
|
|
bound: this.bound,
|
|
closing: this.closing,
|
|
streams: this.streams.size,
|
|
address: this.address(),
|
|
ipv6Only: this._ipv6Only,
|
|
reuseAddress: this._reuseAddress,
|
|
idle: this.idle,
|
|
busy: this.busy
|
|
};
|
|
}
|
|
_init() {
|
|
if (this._inited) return;
|
|
binding.udx_napi_socket_init(
|
|
this.udx._handle,
|
|
this._handle,
|
|
this,
|
|
this._onsend,
|
|
this._onmessage,
|
|
this._onclose,
|
|
this._reallocMessage
|
|
);
|
|
this._inited = true;
|
|
}
|
|
_onsend(id, err) {
|
|
const req = this._reqs[id];
|
|
const onflush = req.onflush;
|
|
req.buffer = null;
|
|
req.onflush = null;
|
|
this._free.push(id);
|
|
onflush(err >= 0);
|
|
if (this._free.length >= 16 && this._free.length === this._reqs.length) {
|
|
this._free = [];
|
|
this._reqs = [];
|
|
}
|
|
}
|
|
_onmessage(len, port, host, family) {
|
|
this.emit("message", this.udx._consumeMessage(len), { host, family, port });
|
|
return this.udx._buffer;
|
|
}
|
|
_onclose() {
|
|
this.emit("close");
|
|
}
|
|
_reallocMessage() {
|
|
return this.udx._reallocMessage();
|
|
}
|
|
_onidle() {
|
|
this.emit("idle");
|
|
}
|
|
_onbusy() {
|
|
this.emit("busy");
|
|
}
|
|
_addStream(stream) {
|
|
if (this.streams.has(stream)) return false;
|
|
this.streams.add(stream);
|
|
if (this.streams.size === 1) this._onbusy();
|
|
return true;
|
|
}
|
|
_removeStream(stream) {
|
|
if (!this.streams.has(stream)) return false;
|
|
this.streams.delete(stream);
|
|
const closed = this._closeMaybe();
|
|
if (this.idle && !closed) this._onidle();
|
|
return true;
|
|
}
|
|
address() {
|
|
if (!this.bound) return null;
|
|
return { host: this._host, family: this._family, port: this._port };
|
|
}
|
|
bind(port, host) {
|
|
if (this.bound) throw new Error("Already bound");
|
|
if (this.closing) throw new Error("Socket is closed");
|
|
if (!port) port = 0;
|
|
let flags = 0;
|
|
if (this._ipv6Only) flags |= binding.UV_UDP_IPV6ONLY;
|
|
if (this._reuseAddress) flags |= binding.UV_UDP_REUSEADDR;
|
|
let family;
|
|
if (host) {
|
|
family = ip.isIP(host);
|
|
if (!family) throw new Error(`${host} is not a valid IP address`);
|
|
if (!this._inited) this._init();
|
|
this._port = binding.udx_napi_socket_bind(this._handle, port, host, family, flags);
|
|
} else {
|
|
if (!this._inited) this._init();
|
|
try {
|
|
host = "::";
|
|
family = 6;
|
|
this._port = binding.udx_napi_socket_bind(this._handle, port, host, family, flags);
|
|
} catch {
|
|
host = "0.0.0.0";
|
|
family = 4;
|
|
this._port = binding.udx_napi_socket_bind(this._handle, port, host, family, flags);
|
|
}
|
|
}
|
|
this._host = host;
|
|
this._family = family;
|
|
this.emit("listening");
|
|
}
|
|
async close() {
|
|
if (this._closing) return this._closing;
|
|
this._closing = new Promise((resolve) => this.once("close", resolve));
|
|
this._closeMaybe();
|
|
return this._closing;
|
|
}
|
|
_closeMaybe() {
|
|
if (this._closed || this._closing === null) return this._closed;
|
|
if (!this._inited) {
|
|
this._closed = true;
|
|
this.emit("close");
|
|
return true;
|
|
}
|
|
if (this.idle) {
|
|
binding.udx_napi_socket_close(this._handle);
|
|
this._closed = true;
|
|
}
|
|
return this._closed;
|
|
}
|
|
setTTL(ttl) {
|
|
if (!this._inited) throw new Error("Socket not active");
|
|
binding.udx_napi_socket_set_ttl(this._handle, ttl);
|
|
}
|
|
getRecvBufferSize() {
|
|
if (!this._inited) throw new Error("Socket not active");
|
|
return binding.udx_napi_socket_get_recv_buffer_size(this._handle);
|
|
}
|
|
setRecvBufferSize(size) {
|
|
if (!this._inited) throw new Error("Socket not active");
|
|
return binding.udx_napi_socket_set_recv_buffer_size(this._handle, size);
|
|
}
|
|
getSendBufferSize() {
|
|
if (!this._inited) throw new Error("Socket not active");
|
|
return binding.udx_napi_socket_get_send_buffer_size(this._handle);
|
|
}
|
|
setSendBufferSize(size) {
|
|
if (!this._inited) throw new Error("Socket not active");
|
|
return binding.udx_napi_socket_set_send_buffer_size(this._handle, size);
|
|
}
|
|
addMembership(group, ifaceAddress) {
|
|
if (!this._inited) throw new Error("Socket not active");
|
|
return binding.udx_napi_socket_set_membership(this._handle, group, ifaceAddress || "", true);
|
|
}
|
|
dropMembership(group, ifaceAddress) {
|
|
if (!this._inited) throw new Error("Socket not active");
|
|
return binding.udx_napi_socket_set_membership(this._handle, group, ifaceAddress || "", false);
|
|
}
|
|
async send(buffer, port, host, ttl) {
|
|
if (this.closing) return false;
|
|
if (!host) host = "127.0.0.1";
|
|
const family = ip.isIP(host);
|
|
if (!family) throw new Error(`${host} is not a valid IP address`);
|
|
if (!this.bound) this.bind(0);
|
|
const id = this._allocSend();
|
|
const req = this._reqs[id];
|
|
req.buffer = buffer;
|
|
const promise = new Promise((resolve) => {
|
|
req.onflush = resolve;
|
|
});
|
|
binding.udx_napi_socket_send_ttl(
|
|
this._handle,
|
|
req.handle,
|
|
id,
|
|
buffer,
|
|
port,
|
|
host,
|
|
family,
|
|
ttl || 0
|
|
);
|
|
return promise;
|
|
}
|
|
trySend(buffer, port, host, ttl) {
|
|
if (this.closing) return;
|
|
if (!host) host = "127.0.0.1";
|
|
const family = ip.isIP(host);
|
|
if (!family) throw new Error(`${host} is not a valid IP address`);
|
|
if (!this.bound) this.bind(0);
|
|
const id = this._allocSend();
|
|
const req = this._reqs[id];
|
|
req.buffer = buffer;
|
|
req.onflush = noop;
|
|
binding.udx_napi_socket_send_ttl(
|
|
this._handle,
|
|
req.handle,
|
|
id,
|
|
buffer,
|
|
port,
|
|
host,
|
|
family,
|
|
ttl || 0
|
|
);
|
|
}
|
|
_allocSend() {
|
|
if (this._free.length > 0) return this._free.pop();
|
|
const handle = b4a.allocUnsafe(binding.sizeof_udx_socket_send_t);
|
|
return this._reqs.push({ handle, buffer: null, onflush: null }) - 1;
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/udx-native/lib/stream.js
|
|
var require_stream4 = __commonJS({
|
|
"../../node_modules/udx-native/lib/stream.js"(exports, module) {
|
|
var streamx = require_streamx();
|
|
var b4a = require_b4a();
|
|
var binding = require_binding7();
|
|
var ip = require_ip();
|
|
var MAX_PACKET = 2048;
|
|
var BUFFER_SIZE = 65536 + MAX_PACKET;
|
|
module.exports = class UDXStream extends streamx.Duplex {
|
|
constructor(udx, id, opts = {}) {
|
|
super({ mapWritable: toBuffer, eagerOpen: true });
|
|
this.udx = udx;
|
|
this.socket = null;
|
|
this._handle = b4a.alloc(binding.sizeof_udx_napi_stream_t);
|
|
this._view = new Uint32Array(
|
|
this._handle.buffer,
|
|
this._handle.byteOffset,
|
|
this._handle.byteLength >> 2
|
|
);
|
|
this._view16 = new Uint16Array(
|
|
this._handle.buffer,
|
|
this._handle.byteOffset,
|
|
this._handle.byteLength >> 1
|
|
);
|
|
this._view64 = new BigUint64Array(
|
|
this._handle.buffer,
|
|
this._handle.byteOffset,
|
|
this._handle.byteLength >> 3
|
|
);
|
|
this._wreqs = [];
|
|
this._wfree = [];
|
|
this._sreqs = [];
|
|
this._sfree = [];
|
|
this._closed = false;
|
|
this._flushing = 0;
|
|
this._flushes = [];
|
|
this._buffer = null;
|
|
this._reallocData();
|
|
this._onwrite = null;
|
|
this._ondestroy = null;
|
|
this._firewall = opts.firewall || firewallAll;
|
|
this._remoteChanging = null;
|
|
this._previousSocket = null;
|
|
this.id = id;
|
|
this.remoteId = 0;
|
|
this.remoteHost = null;
|
|
this.remoteFamily = 0;
|
|
this.remotePort = 0;
|
|
this.userData = null;
|
|
binding.udx_napi_stream_init(
|
|
this.udx._handle,
|
|
this._handle,
|
|
id,
|
|
opts.framed ? 1 : 0,
|
|
this,
|
|
this._ondata,
|
|
this._onend,
|
|
this._ondrain,
|
|
this._onack,
|
|
this._onsend,
|
|
this._onmessage,
|
|
this._onclose,
|
|
this._onfirewall,
|
|
this._onremotechanged,
|
|
this._reallocData,
|
|
this._reallocMessage
|
|
);
|
|
if (opts.seq) binding.udx_napi_stream_set_seq(this._handle, opts.seq);
|
|
binding.udx_napi_stream_recv_start(this._handle, this._buffer);
|
|
}
|
|
get connected() {
|
|
return this.socket !== null;
|
|
}
|
|
get mtu() {
|
|
return this._view16[binding.offsetof_udx_stream_t_mtu >> 1];
|
|
}
|
|
get rtt() {
|
|
return this._view[binding.offsetof_udx_stream_t_srtt >> 2];
|
|
}
|
|
get cwnd() {
|
|
return this._view[binding.offsetof_udx_stream_t_cwnd >> 2];
|
|
}
|
|
get rtoCount() {
|
|
return this._view16[binding.offsetof_udx_stream_t_rto_count >> 1];
|
|
}
|
|
get retransmits() {
|
|
return this._view16[binding.offsetof_udx_stream_t_retransmit_count >> 1];
|
|
}
|
|
get fastRecoveries() {
|
|
return this._view16[binding.offsetof_udx_stream_t_fast_recovery_count >> 1];
|
|
}
|
|
get inflight() {
|
|
return this._view[binding.offsetof_udx_stream_t_inflight >> 2];
|
|
}
|
|
get bytesTransmitted() {
|
|
return Number(this._view64[binding.offsetof_udx_stream_t_bytes_tx >> 3]);
|
|
}
|
|
get packetsTransmitted() {
|
|
return Number(this._view64[binding.offsetof_udx_stream_t_packets_tx >> 3]);
|
|
}
|
|
get bytesReceived() {
|
|
return Number(this._view64[binding.offsetof_udx_stream_t_bytes_rx >> 3]);
|
|
}
|
|
get packetsReceived() {
|
|
return Number(this._view64[binding.offsetof_udx_stream_t_packets_rx >> 3]);
|
|
}
|
|
get localHost() {
|
|
return this.socket ? this.socket.address().host : null;
|
|
}
|
|
get localFamily() {
|
|
return this.socket ? this.socket.address().family : 0;
|
|
}
|
|
get localPort() {
|
|
return this.socket ? this.socket.address().port : 0;
|
|
}
|
|
setInteractive(bool) {
|
|
if (!this._closed) return;
|
|
binding.udx_napi_stream_set_mode(this._handle, bool ? 0 : 1);
|
|
}
|
|
connect(socket, remoteId, port, host, opts = {}) {
|
|
if (this._closed) return;
|
|
if (this.connected) throw new Error("Already connected");
|
|
if (socket.closing) throw new Error("Socket is closed");
|
|
if (typeof host === "object") {
|
|
opts = host;
|
|
host = null;
|
|
}
|
|
if (!host) host = "127.0.0.1";
|
|
const family = ip.isIP(host);
|
|
if (!family) throw new Error(`${host} is not a valid IP address`);
|
|
if (!(port > 0 && port < 65536)) throw new Error(`${port} is not a valid port`);
|
|
if (!socket.bound) socket.bind(0);
|
|
this.remoteId = remoteId;
|
|
this.remotePort = port;
|
|
this.remoteHost = host;
|
|
this.remoteFamily = family;
|
|
this.socket = socket;
|
|
if (opts.ack) binding.udx_napi_stream_set_ack(this._handle, opts.ack);
|
|
binding.udx_napi_stream_connect(this._handle, socket._handle, remoteId, port, host, family);
|
|
this.socket._addStream(this);
|
|
this.emit("connect");
|
|
}
|
|
changeRemote(socket, remoteId, port, host) {
|
|
if (this._remoteChanging) throw new Error("Remote already changing");
|
|
if (!this.connected) throw new Error("Not yet connected");
|
|
if (socket.closing) throw new Error("Socket is closed");
|
|
if (this.socket.udx !== socket.udx) {
|
|
throw new Error("Cannot change to a socket on another UDX instance");
|
|
}
|
|
if (!host) host = "127.0.0.1";
|
|
const family = ip.isIP(host);
|
|
if (!family) throw new Error(`${host} is not a valid IP address`);
|
|
if (!(port > 0 && port < 65536)) throw new Error(`${port} is not a valid port`);
|
|
if (this.socket !== socket) this._previousSocket = this.socket;
|
|
this.remoteId = remoteId;
|
|
this.remotePort = port;
|
|
this.remoteHost = host;
|
|
this.remoteFamily = family;
|
|
this.socket = socket;
|
|
this._remoteChanging = new Promise((resolve, reject) => {
|
|
const onchanged = () => {
|
|
this.off("close", onclose);
|
|
resolve();
|
|
};
|
|
const onclose = () => {
|
|
this.off("remote-changed", onchanged);
|
|
reject(new Error("Stream is closed"));
|
|
};
|
|
this.once("remote-changed", onchanged).once("close", onclose);
|
|
});
|
|
binding.udx_napi_stream_change_remote(
|
|
this._handle,
|
|
socket._handle,
|
|
remoteId,
|
|
port,
|
|
host,
|
|
family
|
|
);
|
|
this.socket._addStream(this);
|
|
return this._remoteChanging;
|
|
}
|
|
relayTo(destination) {
|
|
if (this._closed) return;
|
|
binding.udx_napi_stream_relay_to(this._handle, destination._handle);
|
|
}
|
|
async send(buffer) {
|
|
if (!this.connected || this._closed) return false;
|
|
const id = this._allocSend();
|
|
const req = this._sreqs[id];
|
|
req.buffer = buffer;
|
|
const promise = new Promise((resolve) => {
|
|
req.onflush = resolve;
|
|
});
|
|
binding.udx_napi_stream_send(this._handle, req.handle, id, buffer);
|
|
return promise;
|
|
}
|
|
trySend(buffer) {
|
|
if (!this.connected || this._closed) return;
|
|
const id = this._allocSend();
|
|
const req = this._sreqs[id];
|
|
req.buffer = buffer;
|
|
req.onflush = noop;
|
|
binding.udx_napi_stream_send(this._handle, req.handle, id, buffer);
|
|
}
|
|
async flush() {
|
|
if (await streamx.Writable.drained(this) === false) return false;
|
|
if (this.destroying) return false;
|
|
const missing = this._wreqs.length - this._wfree.length;
|
|
if (missing === 0) return true;
|
|
return new Promise((resolve) => {
|
|
this._flushes.push({ flush: this._flushing++, missing, resolve });
|
|
});
|
|
}
|
|
toJSON() {
|
|
return {
|
|
id: this.id,
|
|
connected: this.connected,
|
|
destroying: this.destroying,
|
|
destroyed: this.destroyed,
|
|
remoteId: this.remoteId,
|
|
remoteHost: this.remoteHost,
|
|
remoteFamily: this.remoteFamily,
|
|
remotePort: this.remotePort,
|
|
mtu: this.mtu,
|
|
rtt: this.rtt,
|
|
cwnd: this.cwnd,
|
|
inflight: this.inflight,
|
|
socket: this.socket ? this.socket.toJSON() : null
|
|
};
|
|
}
|
|
_read(cb) {
|
|
cb(null);
|
|
}
|
|
_writeContinue(err) {
|
|
if (this._onwrite === null) return;
|
|
const cb = this._onwrite;
|
|
this._onwrite = null;
|
|
cb(err);
|
|
}
|
|
_destroyContinue(err) {
|
|
if (this._ondestroy === null) return;
|
|
const cb = this._ondestroy;
|
|
this._ondestroy = null;
|
|
cb(err);
|
|
}
|
|
_writev(buffers, cb) {
|
|
if (!this.connected)
|
|
throw customError("Writing while not connected not currently supported", "ERR_ASSERTION");
|
|
let drained = true;
|
|
if (buffers.length === 1) {
|
|
const id = this._allocWrite(1);
|
|
const req = this._wreqs[id];
|
|
req.flush = this._flushing;
|
|
req.buffer = buffers[0];
|
|
drained = binding.udx_napi_stream_write(this._handle, req.handle, id, req.buffer) !== 0;
|
|
} else {
|
|
const id = this._allocWrite(nextBatchSize(buffers.length));
|
|
const req = this._wreqs[id];
|
|
req.flush = this._flushing;
|
|
req.buffers = buffers;
|
|
drained = binding.udx_napi_stream_writev(this._handle, req.handle, id, req.buffers) !== 0;
|
|
}
|
|
if (drained) cb(null);
|
|
else this._onwrite = cb;
|
|
}
|
|
_final(cb) {
|
|
const id = this._allocWrite(1);
|
|
const req = this._wreqs[id];
|
|
req.flush = this._flushes;
|
|
req.buffer = b4a.allocUnsafe(0);
|
|
const drained = binding.udx_napi_stream_write_end(this._handle, req.handle, id, req.buffer) !== 0;
|
|
if (drained) cb(null);
|
|
else this._onwrite = cb;
|
|
}
|
|
_predestroy() {
|
|
if (!this._closed) binding.udx_napi_stream_destroy(this._handle);
|
|
this._closed = true;
|
|
this._writeContinue(null);
|
|
}
|
|
_destroy(cb) {
|
|
if (this.connected) this._ondestroy = cb;
|
|
else cb(null);
|
|
}
|
|
_ondata(read) {
|
|
this.push(this._consumeData(read));
|
|
return this._buffer;
|
|
}
|
|
_onend(read) {
|
|
if (read > 0) this.push(this._consumeData(read));
|
|
this.push(null);
|
|
}
|
|
_ondrain() {
|
|
this._writeContinue(null);
|
|
}
|
|
_flushAck(flush) {
|
|
for (let i = this._flushes.length - 1; i >= 0; i--) {
|
|
const f = this._flushes[i];
|
|
if (f.flush < flush) break;
|
|
f.missing--;
|
|
}
|
|
while (this._flushes.length > 0 && this._flushes[0].missing === 0) {
|
|
this._flushes.shift().resolve(true);
|
|
}
|
|
}
|
|
_onack(id) {
|
|
const req = this._wreqs[id];
|
|
req.buffers = req.buffer = null;
|
|
this._wfree.push(id);
|
|
if (this._flushes.length > 0) this._flushAck(req.flush);
|
|
if (this._wfree.length >= 64 && this._wfree.length === this._wreqs.length) {
|
|
this._wfree = [];
|
|
this._wreqs = [];
|
|
}
|
|
}
|
|
_onsend(id, err) {
|
|
const req = this._sreqs[id];
|
|
const onflush = req.onflush;
|
|
req.buffer = null;
|
|
req.onflush = null;
|
|
this._sfree.push(id);
|
|
onflush(err >= 0);
|
|
if (this._sfree.length >= 16 && this._sfree.length === this._sreqs.length) {
|
|
this._sfree = [];
|
|
this._sreqs = [];
|
|
}
|
|
}
|
|
_onmessage(len) {
|
|
this.emit("message", this.udx._consumeMessage(len));
|
|
return this.udx._buffer;
|
|
}
|
|
_onclose(err) {
|
|
this._closed = true;
|
|
if (this.socket) {
|
|
this.socket._removeStream(this);
|
|
this.socket = null;
|
|
}
|
|
if (this._previousSocket) {
|
|
this._previousSocket._removeStream(this);
|
|
this._previousSocket = null;
|
|
}
|
|
if (!err) return this._destroyContinue(null);
|
|
if (this._ondestroy === null) this.destroy(err);
|
|
else this._destroyContinue(err);
|
|
}
|
|
_onfirewall(socket, port, host, family) {
|
|
return this._firewall(socket, port, host, family) ? 1 : 0;
|
|
}
|
|
_onremotechanged() {
|
|
if (this._previousSocket) {
|
|
this._previousSocket._removeStream(this);
|
|
this._previousSocket = null;
|
|
}
|
|
this._remoteChanging = null;
|
|
this.emit("remote-changed");
|
|
}
|
|
_consumeData(len) {
|
|
const next = this._buffer.subarray(0, len);
|
|
this._buffer = this._buffer.subarray(len);
|
|
if (this._buffer.byteLength < MAX_PACKET) this._reallocData();
|
|
return next;
|
|
}
|
|
_reallocData() {
|
|
this._buffer = b4a.allocUnsafe(BUFFER_SIZE);
|
|
return this._buffer;
|
|
}
|
|
_reallocMessage() {
|
|
return this.udx._reallocMessage();
|
|
}
|
|
_allocWrite(size) {
|
|
if (this._wfree.length === 0) {
|
|
const handle = b4a.allocUnsafe(binding.udx_napi_stream_write_sizeof(size));
|
|
return this._wreqs.push({
|
|
handle,
|
|
size,
|
|
buffers: null,
|
|
buffer: null,
|
|
flush: 0
|
|
}) - 1;
|
|
}
|
|
const free = this._wfree.pop();
|
|
if (size === 1) return free;
|
|
const next = this._wreqs[free];
|
|
if (next.size < size) {
|
|
next.handle = b4a.allocUnsafe(binding.udx_napi_stream_write_sizeof(size));
|
|
next.size = size;
|
|
}
|
|
return free;
|
|
}
|
|
_allocSend() {
|
|
if (this._sfree.length > 0) return this._sfree.pop();
|
|
const handle = b4a.allocUnsafe(binding.sizeof_udx_stream_send_t);
|
|
return this._sreqs.push({ handle, buffer: null, resolve: null, reject: null }) - 1;
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
function toBuffer(data) {
|
|
return typeof data === "string" ? b4a.from(data) : data;
|
|
}
|
|
function firewallAll(socket, port, host) {
|
|
return true;
|
|
}
|
|
function customError(message, code) {
|
|
const error = new Error(message);
|
|
error.code = code;
|
|
return error;
|
|
}
|
|
function nextBatchSize(n) {
|
|
if (n === 1) return 1;
|
|
if (n < 8) return 8;
|
|
if (n < 16) return 16;
|
|
if (n < 32) return 32;
|
|
if (n < 64) return 64;
|
|
return n;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/udx-native/lib/network-interfaces.js
|
|
var require_network_interfaces = __commonJS({
|
|
"../../node_modules/udx-native/lib/network-interfaces.js"(exports, module) {
|
|
var events = __require("events");
|
|
var b4a = require_b4a();
|
|
var binding = require_binding7();
|
|
module.exports = class NetworkInterfaces extends events.EventEmitter {
|
|
constructor(udx) {
|
|
super();
|
|
this._handle = b4a.alloc(binding.sizeof_udx_napi_interface_event_t);
|
|
this._watching = false;
|
|
this._destroying = null;
|
|
binding.udx_napi_interface_event_init(
|
|
udx._handle,
|
|
this._handle,
|
|
this,
|
|
this._onevent,
|
|
this._onclose
|
|
);
|
|
this.interfaces = binding.udx_napi_interface_event_get_addrs(this._handle);
|
|
}
|
|
_onclose() {
|
|
this.emit("close");
|
|
}
|
|
_onevent() {
|
|
this.interfaces = binding.udx_napi_interface_event_get_addrs(this._handle);
|
|
this.emit("change", this.interfaces);
|
|
}
|
|
watch() {
|
|
if (this._watching) return this;
|
|
this._watching = true;
|
|
binding.udx_napi_interface_event_start(this._handle);
|
|
return this;
|
|
}
|
|
unwatch() {
|
|
if (!this._watching) return this;
|
|
this._watching = false;
|
|
binding.udx_napi_interface_event_stop(this._handle);
|
|
return this;
|
|
}
|
|
async destroy() {
|
|
if (this._destroying) return this._destroying;
|
|
this._destroying = events.once(this, "close");
|
|
binding.udx_napi_interface_event_close(this._handle);
|
|
return this._destroying;
|
|
}
|
|
[Symbol.iterator]() {
|
|
return this.interfaces[Symbol.iterator]();
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/udx-native/lib/udx.js
|
|
var require_udx = __commonJS({
|
|
"../../node_modules/udx-native/lib/udx.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var binding = require_binding7();
|
|
var ip = require_ip();
|
|
var Socket = require_socket();
|
|
var Stream = require_stream4();
|
|
var NetworkInterfaces = require_network_interfaces();
|
|
var MAX_MESSAGE = 4096;
|
|
var BUFFER_SIZE = 65536 + MAX_MESSAGE;
|
|
module.exports = class UDX {
|
|
constructor() {
|
|
this._handle = b4a.alloc(binding.sizeof_udx_napi_t);
|
|
this._watchers = /* @__PURE__ */ new Set();
|
|
this._view64 = new BigUint64Array(
|
|
this._handle.buffer,
|
|
this._handle.byteOffset,
|
|
this._handle.byteLength >> 3
|
|
);
|
|
this._buffer = null;
|
|
this._reallocMessage();
|
|
binding.udx_napi_init(this._handle, this._buffer);
|
|
}
|
|
static isIPv4(host) {
|
|
return ip.isIPv4(host);
|
|
}
|
|
static isIPv6(host) {
|
|
return ip.isIPv6(host);
|
|
}
|
|
static isIP(host) {
|
|
return ip.isIP(host);
|
|
}
|
|
get bytesTransmitted() {
|
|
return Number(this._view64[binding.offsetof_udx_t_bytes_tx >> 3]);
|
|
}
|
|
get packetsTransmitted() {
|
|
return Number(this._view64[binding.offsetof_udx_t_packets_tx >> 3]);
|
|
}
|
|
get bytesReceived() {
|
|
return Number(this._view64[binding.offsetof_udx_t_bytes_rx >> 3]);
|
|
}
|
|
get packetsReceived() {
|
|
return Number(this._view64[binding.offsetof_udx_t_packets_rx >> 3]);
|
|
}
|
|
get packetsDroppedByKernel() {
|
|
return Number(this._view64[binding.offsetof_udx_t_packets_dropped_by_kernel >> 3]);
|
|
}
|
|
_consumeMessage(len) {
|
|
const next = this._buffer.subarray(0, len);
|
|
this._buffer = this._buffer.subarray(len);
|
|
if (this._buffer.byteLength < MAX_MESSAGE) this._reallocMessage();
|
|
return next;
|
|
}
|
|
_reallocMessage() {
|
|
this._buffer = b4a.allocUnsafe(BUFFER_SIZE);
|
|
return this._buffer;
|
|
}
|
|
createSocket(opts) {
|
|
return new Socket(this, opts);
|
|
}
|
|
createStream(id, opts) {
|
|
return new Stream(this, id, opts);
|
|
}
|
|
networkInterfaces() {
|
|
let [watcher = null] = this._watchers;
|
|
if (watcher) return watcher.interfaces;
|
|
watcher = new NetworkInterfaces(this);
|
|
watcher.destroy();
|
|
return watcher.interfaces;
|
|
}
|
|
watchNetworkInterfaces(onchange) {
|
|
const watcher = new NetworkInterfaces(this);
|
|
this._watchers.add(watcher);
|
|
watcher.on("close", () => {
|
|
this._watchers.delete(watcher);
|
|
});
|
|
if (onchange) watcher.on("change", onchange);
|
|
return watcher.watch();
|
|
}
|
|
async lookup(host, opts = {}) {
|
|
const { family = 0 } = opts;
|
|
const req = b4a.alloc(binding.sizeof_udx_napi_lookup_t);
|
|
const ctx = {
|
|
req,
|
|
resolve: null,
|
|
reject: null
|
|
};
|
|
const promise = new Promise((resolve, reject) => {
|
|
ctx.resolve = resolve;
|
|
ctx.reject = reject;
|
|
});
|
|
binding.udx_napi_lookup(this._handle, req, host, family, ctx, onlookup);
|
|
return promise;
|
|
}
|
|
};
|
|
function onlookup(err, host, family) {
|
|
if (err) this.reject(err);
|
|
else this.resolve({ host, family });
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/nat-sampler/index.js
|
|
var require_nat_sampler = __commonJS({
|
|
"../../node_modules/nat-sampler/index.js"(exports, module) {
|
|
module.exports = class NatSampler {
|
|
constructor() {
|
|
this.host = null;
|
|
this.port = 0;
|
|
this.size = 0;
|
|
this._a = null;
|
|
this._b = null;
|
|
this._threshold = 0;
|
|
this._top = 0;
|
|
this._samples = [];
|
|
}
|
|
add(host, port) {
|
|
const a = this._bump(host, port, 2);
|
|
const b = this._bump(host, 0, 1);
|
|
if (this._samples.length < 32) {
|
|
this.size++;
|
|
this._threshold = this.size - (this.size < 4 ? 0 : this.size < 8 ? 1 : this.size < 12 ? 2 : 3);
|
|
this._samples.push(a, b);
|
|
this._top += 2;
|
|
} else {
|
|
if (this._top === 32) this._top = 0;
|
|
const oa = this._samples[this._top];
|
|
this._samples[this._top++] = a;
|
|
oa.hits--;
|
|
const ob = this._samples[this._top];
|
|
this._samples[this._top++] = b;
|
|
ob.hits--;
|
|
}
|
|
if (this._a === null || this._a.hits < a.hits) this._a = a;
|
|
if (this._b === null || this._b.hits < b.hits) this._b = b;
|
|
if (this._a.hits >= this._threshold) {
|
|
this.host = this._a.host;
|
|
this.port = this._a.port;
|
|
} else if (this._b.hits >= this._threshold) {
|
|
this.host = this._b.host;
|
|
this.port = 0;
|
|
} else {
|
|
this.host = null;
|
|
this.port = 0;
|
|
}
|
|
return a.hits;
|
|
}
|
|
_bump(host, port, inc) {
|
|
for (let i = 0; i < 4; i++) {
|
|
const j = this._top - inc - 2 * i & 31;
|
|
if (j >= this._samples.length) return { host, port, hits: 1 };
|
|
const s = this._samples[j];
|
|
if (s.port === port && s.host === host) {
|
|
s.hits++;
|
|
return s;
|
|
}
|
|
}
|
|
return { host, port, hits: 1 };
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dht-rpc/lib/health.js
|
|
var require_health = __commonJS({
|
|
"../../node_modules/dht-rpc/lib/health.js"(exports, module) {
|
|
var MAX_HEALTH_WINDOW = 4;
|
|
var IDLE_THRESHOLD = 4;
|
|
var DEGRADED_TIMEOUT_RATE_THRESHOLD = 0.5;
|
|
module.exports = class NetworkHealth {
|
|
constructor(dht) {
|
|
this._dht = dht;
|
|
this._window = [];
|
|
this._head = -1;
|
|
this._degradedTicks = 0;
|
|
this._healthyTicks = 0;
|
|
this.online = true;
|
|
this.degraded = false;
|
|
}
|
|
get oldest() {
|
|
return this._window[this._tail];
|
|
}
|
|
get previous() {
|
|
return this._window[(this._head - 1 + MAX_HEALTH_WINDOW) % MAX_HEALTH_WINDOW];
|
|
}
|
|
get newest() {
|
|
return this._window[this._head];
|
|
}
|
|
get responses() {
|
|
if (!this.newest || !this.previous) return 0;
|
|
return this.newest.responses - this.previous.responses;
|
|
}
|
|
get timeouts() {
|
|
if (!this.newest || !this.previous) return 0;
|
|
return this.newest.timeouts - this.previous.timeouts;
|
|
}
|
|
get timeoutsRate() {
|
|
if (this.timeouts === 0) return 0;
|
|
return this.timeouts / (this.responses + this.timeouts);
|
|
}
|
|
get cold() {
|
|
return this._window.length < MAX_HEALTH_WINDOW;
|
|
}
|
|
get idle() {
|
|
return this.responses + this.timeouts < IDLE_THRESHOLD;
|
|
}
|
|
get allDegraded() {
|
|
return this._degradedTicks === MAX_HEALTH_WINDOW;
|
|
}
|
|
get allHealthy() {
|
|
return this._healthyTicks === MAX_HEALTH_WINDOW;
|
|
}
|
|
get stats() {
|
|
return {
|
|
online: this.online,
|
|
degraded: this.degraded,
|
|
cold: this.cold,
|
|
idle: this.idle,
|
|
responses: this.responses,
|
|
timeouts: this.timeouts,
|
|
timeoutsRate: this.timeoutsRate
|
|
};
|
|
}
|
|
get _tail() {
|
|
return (this._head + 1) % MAX_HEALTH_WINDOW;
|
|
}
|
|
reset() {
|
|
this._window = [];
|
|
this._head = -1;
|
|
this._degradedTicks = 0;
|
|
this._healthyTicks = 0;
|
|
this.online = true;
|
|
this.degraded = false;
|
|
this._dht._online();
|
|
}
|
|
update() {
|
|
if (this.oldest?.degraded) this._degradedTicks--;
|
|
else if (this.oldest?.degraded === false) this._healthyTicks--;
|
|
this._head = this._tail;
|
|
this._window[this._head] = {
|
|
responses: this._dht.stats.requests.responses,
|
|
timeouts: this._dht.stats.requests.timeouts
|
|
};
|
|
if (this.cold || this.idle) return;
|
|
this.newest.degraded = this.timeoutsRate > DEGRADED_TIMEOUT_RATE_THRESHOLD;
|
|
if (this.newest.degraded) this._degradedTicks++;
|
|
else this._healthyTicks++;
|
|
this.online = this.responses > 0;
|
|
if (this.online && this.allDegraded) this.degraded = true;
|
|
if (!this.online || this.allHealthy) this.degraded = false;
|
|
if (this.online && !this.degraded) this._dht._online();
|
|
else if (this.degraded) this._dht._degraded();
|
|
else this._dht._offline();
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/adaptive-timeout/index.js
|
|
var require_adaptive_timeout = __commonJS({
|
|
"../../node_modules/adaptive-timeout/index.js"(exports, module) {
|
|
var Cache = require_xache();
|
|
module.exports = class AdaptiveTimeout {
|
|
constructor(opts = {}) {
|
|
this._cache = new Cache({
|
|
maxSize: opts.maxSize || 65536,
|
|
maxAge: opts.maxAge || 10 * 60 * 1e3
|
|
// 10 minutes
|
|
});
|
|
this._fallback = opts.fallback || AdaptiveTimeout.TimeoutExponential;
|
|
this._min = opts.min ?? 300;
|
|
this._max = opts.max || 4e3;
|
|
this._jitter = opts.jitter ?? 256;
|
|
}
|
|
// Default - aggressive ramp
|
|
static TimeoutAggressive = [500, 750, 1e3, 1500, 2e3];
|
|
// Linear - steady increase
|
|
static TimeoutLinear = [500, 1e3, 1500, 2e3, 2500];
|
|
// Exponential - slow start, rapid backoff
|
|
static TimeoutExponential = [250, 500, 1e3, 2e3, 4e3];
|
|
// Gentle - conservative, patient
|
|
static TimeoutGentle = [1e3, 1250, 1500, 1750, 2e3];
|
|
// Fast - rapid fire retries
|
|
static TimeoutFast = [200, 400, 600, 800, 1e3];
|
|
// U-shape - long, short, long
|
|
static TimeoutUShape = [1500, 750, 500, 750, 1500];
|
|
// Inverse U - short, long, short
|
|
static TimeoutInverseU = [500, 1e3, 1500, 1e3, 500];
|
|
// Sawtooth - alternating fast/slow
|
|
static TimeoutSawtooth = [500, 1500, 500, 1500, 500];
|
|
// Plateau - quick ramp then steady
|
|
static TimeoutPlateau = [500, 1e3, 2e3, 2e3, 2e3];
|
|
// Logarithmic - diminishing increases
|
|
static TimeoutLogarithmic = [500, 1e3, 1300, 1500, 1600];
|
|
getValue(key) {
|
|
return this._cache.get(key);
|
|
}
|
|
put(key, value) {
|
|
let p = this._cache.get(key);
|
|
if (!p) {
|
|
p = { avg: value, variance: value >> 1 };
|
|
} else {
|
|
p.variance += Math.abs(p.avg - value) - p.variance >> 2;
|
|
p.avg += value - p.avg >> 3;
|
|
}
|
|
this._cache.set(key, p);
|
|
return p;
|
|
}
|
|
get(key, attempt = 1) {
|
|
const p = this._cache.get(key);
|
|
const jitter = Math.random() * this._jitter | 0;
|
|
if (p) {
|
|
const base = p.avg + (p.variance << 1);
|
|
const backoff = base * attempt;
|
|
return Math.min(Math.max(backoff + jitter, this._min), this._max);
|
|
} else {
|
|
const base = this._fallback[Math.min(attempt - 1, this._fallback.length - 1)];
|
|
return base + jitter;
|
|
}
|
|
}
|
|
has(key) {
|
|
return this._cache.has(key);
|
|
}
|
|
delete(key) {
|
|
return this._cache.delete(key);
|
|
}
|
|
clear() {
|
|
this._cache.clear();
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/compact-encoding-net/index.js
|
|
var require_compact_encoding_net = __commonJS({
|
|
"../../node_modules/compact-encoding-net/index.js"(exports, module) {
|
|
var c = require_compact_encoding();
|
|
var port = c.uint16;
|
|
var address = (host, family) => {
|
|
return {
|
|
preencode(state, m) {
|
|
host.preencode(state, m.host);
|
|
port.preencode(state, m.port);
|
|
},
|
|
encode(state, m) {
|
|
host.encode(state, m.host);
|
|
port.encode(state, m.port);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
host: host.decode(state),
|
|
family,
|
|
port: port.decode(state)
|
|
};
|
|
}
|
|
};
|
|
};
|
|
var ipv4 = {
|
|
preencode(state) {
|
|
state.end += 4;
|
|
},
|
|
encode(state, string) {
|
|
const start = state.start;
|
|
const end = start + 4;
|
|
let i = 0;
|
|
while (i < string.length) {
|
|
let n = 0;
|
|
let c2;
|
|
while (i < string.length && (c2 = string.charCodeAt(i++)) !== /* . */
|
|
46) {
|
|
n = n * 10 + (c2 - /* 0 */
|
|
48);
|
|
}
|
|
state.buffer[state.start++] = n;
|
|
}
|
|
state.start = end;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 4) throw new Error("Out of bounds");
|
|
return state.buffer[state.start++] + "." + state.buffer[state.start++] + "." + state.buffer[state.start++] + "." + state.buffer[state.start++];
|
|
}
|
|
};
|
|
var ipv4Address = address(ipv4, 4);
|
|
var ipv6 = {
|
|
preencode(state) {
|
|
state.end += 16;
|
|
},
|
|
encode(state, string) {
|
|
const start = state.start;
|
|
const end = start + 16;
|
|
let i = 0;
|
|
let split = null;
|
|
while (i < string.length) {
|
|
let n = 0;
|
|
let c2;
|
|
while (i < string.length && (c2 = string.charCodeAt(i++)) !== /* : */
|
|
58) {
|
|
if (c2 >= 48 && c2 <= 57) n = n * 16 + (c2 - /* 0 */
|
|
48);
|
|
else if (c2 >= 65 && c2 <= 70) n = n * 16 + (c2 - /* A */
|
|
65 + 10);
|
|
else if (c2 >= 97 && c2 <= 102) n = n * 16 + (c2 - /* a */
|
|
97 + 10);
|
|
}
|
|
state.buffer[state.start++] = n >>> 8;
|
|
state.buffer[state.start++] = n;
|
|
if (i < string.length && string.charCodeAt(i) === /* : */
|
|
58) {
|
|
i++;
|
|
split = state.start;
|
|
}
|
|
}
|
|
if (split !== null) {
|
|
const offset = end - state.start;
|
|
state.buffer.copyWithin(split + offset, split).fill(0, split, split + offset);
|
|
}
|
|
state.start = end;
|
|
},
|
|
decode(state) {
|
|
if (state.end - state.start < 16) throw new Error("Out of bounds");
|
|
return (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16) + ":" + (state.buffer[state.start++] * 256 + state.buffer[state.start++]).toString(16);
|
|
}
|
|
};
|
|
var ipv6Address = address(ipv6, 6);
|
|
var ip = {
|
|
preencode(state, string) {
|
|
const family = string.includes(":") ? 6 : 4;
|
|
c.uint8.preencode(state, family);
|
|
if (family === 4) ipv4.preencode(state);
|
|
else ipv6.preencode(state);
|
|
},
|
|
encode(state, string) {
|
|
const family = string.includes(":") ? 6 : 4;
|
|
c.uint8.encode(state, family);
|
|
if (family === 4) ipv4.encode(state, string);
|
|
else ipv6.encode(state, string);
|
|
},
|
|
decode(state) {
|
|
const family = c.uint8.decode(state);
|
|
if (family === 4) return ipv4.decode(state);
|
|
else return ipv6.decode(state);
|
|
}
|
|
};
|
|
var ipAddress = {
|
|
preencode(state, m) {
|
|
ip.preencode(state, m.host);
|
|
port.preencode(state, m.port);
|
|
},
|
|
encode(state, m) {
|
|
ip.encode(state, m.host);
|
|
port.encode(state, m.port);
|
|
},
|
|
decode(state) {
|
|
const family = c.uint8.decode(state);
|
|
return {
|
|
host: family === 4 ? ipv4.decode(state) : ipv6.decode(state),
|
|
family,
|
|
port: port.decode(state)
|
|
};
|
|
}
|
|
};
|
|
module.exports = {
|
|
port,
|
|
ipv4,
|
|
ipv4Address,
|
|
ipv6,
|
|
ipv6Address,
|
|
ip,
|
|
ipAddress
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dht-rpc/lib/peer.js
|
|
var require_peer = __commonJS({
|
|
"../../node_modules/dht-rpc/lib/peer.js"(exports, module) {
|
|
var sodium = require_sodium_universal();
|
|
var c = require_compact_encoding();
|
|
var net = require_compact_encoding_net();
|
|
var b4a = require_b4a();
|
|
var ipv4 = {
|
|
...net.ipv4Address,
|
|
decode(state) {
|
|
const ip = net.ipv4Address.decode(state);
|
|
return {
|
|
id: null,
|
|
// populated by the callee
|
|
host: ip.host,
|
|
port: ip.port
|
|
};
|
|
}
|
|
};
|
|
module.exports = { id, ipv4, ipv4Array: c.array(ipv4) };
|
|
function id(host, port, out = b4a.allocUnsafeSlow(32)) {
|
|
const addr = out.subarray(0, 6);
|
|
ipv4.encode({ start: 0, end: 6, buffer: addr }, { host, port });
|
|
sodium.crypto_generichash(out, addr);
|
|
return out;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dht-rpc/lib/errors.js
|
|
var require_errors5 = __commonJS({
|
|
"../../node_modules/dht-rpc/lib/errors.js"(exports, module) {
|
|
module.exports = class DHTError extends Error {
|
|
constructor(msg, code, fn = DHTError) {
|
|
super(`${code}: ${msg}`);
|
|
this.code = code;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, fn);
|
|
}
|
|
}
|
|
get name() {
|
|
return "DHTError";
|
|
}
|
|
static UNKNOWN_COMMAND = 1;
|
|
static INVALID_TOKEN = 2;
|
|
static REQUEST_TIMEOUT(msg = "Request timed out") {
|
|
return new DHTError(msg, "REQUEST_TIMEOUT", DHTError.REQUEST_TIMEOUT);
|
|
}
|
|
static REQUEST_DESTROYED(msg = "Request destroyed") {
|
|
return new DHTError(msg, "REQUEST_DESTROYED", DHTError.REQUEST_DESTROYED);
|
|
}
|
|
static IO_SUSPENDED(msg = "I/O suspended") {
|
|
return new DHTError(msg, "IO_SUSPENDED", DHTError.IO_SUSPENDED);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dht-rpc/lib/io.js
|
|
var require_io = __commonJS({
|
|
"../../node_modules/dht-rpc/lib/io.js"(exports, module) {
|
|
var FIFO = require_fast_fifo();
|
|
var sodium = require_sodium_universal();
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var AdaptiveTimeout = require_adaptive_timeout();
|
|
var peer = require_peer();
|
|
var { INVALID_TOKEN, REQUEST_TIMEOUT, REQUEST_DESTROYED, IO_SUSPENDED } = require_errors5();
|
|
var VERSION = 3;
|
|
var RESPONSE_ID = 1 << 4 | VERSION;
|
|
var REQUEST_ID = 0 << 4 | VERSION;
|
|
var EMPTY_ARRAY = [];
|
|
var MAX_WINDOW = 80;
|
|
module.exports = class IO {
|
|
constructor(table, udx, {
|
|
maxWindow = MAX_WINDOW,
|
|
port = 0,
|
|
host = "0.0.0.0",
|
|
anyPort = true,
|
|
firewalled = true,
|
|
onrequest,
|
|
onresponse = noop,
|
|
ontimeout = noop,
|
|
adaptiveTimeout
|
|
} = {}) {
|
|
this.table = table;
|
|
this.udx = udx;
|
|
this.inflight = [];
|
|
this.clientSocket = null;
|
|
this.serverSocket = null;
|
|
this.firewalled = firewalled !== false;
|
|
this.ephemeral = true;
|
|
this.congestion = new CongestionWindow(maxWindow);
|
|
this.networkInterfaces = udx.watchNetworkInterfaces();
|
|
this.suspended = false;
|
|
this.stats = {
|
|
requests: {
|
|
active: 0,
|
|
total: 0,
|
|
responses: 0,
|
|
timeouts: 0,
|
|
retries: 0
|
|
},
|
|
commands: [
|
|
{ tx: 0, rx: 0 },
|
|
// tx = transmitted, rx = received
|
|
{ tx: 0, rx: 0 },
|
|
{ tx: 0, rx: 0 },
|
|
{ tx: 0, rx: 0 }
|
|
]
|
|
};
|
|
this.onrequest = onrequest;
|
|
this.onresponse = onresponse;
|
|
this.ontimeout = ontimeout;
|
|
this._pending = new FIFO();
|
|
this._rotateSecrets = 10;
|
|
this._tid = Math.random() * 65536 | 0;
|
|
this._secrets = null;
|
|
this._drainInterval = null;
|
|
this._destroying = null;
|
|
this._binding = null;
|
|
this.portRange = port.length ? port : port === 0 ? [0, 0] : [port, port + 5];
|
|
this._host = host;
|
|
this._anyPort = anyPort !== false;
|
|
this._boundServerPort = 0;
|
|
this._boundClientPort = 0;
|
|
this._adt = adaptiveTimeout ? new AdaptiveTimeout(adaptiveTimeout) : null;
|
|
}
|
|
static DEFAULT_MAX_WINDOW = MAX_WINDOW;
|
|
onmessage(socket, buffer, { host, port }) {
|
|
if (buffer.byteLength < 2 || !(port > 0 && port < 65536) || this.suspended === true) return;
|
|
const from = { id: null, host, port };
|
|
const state = { start: 1, end: buffer.byteLength, buffer };
|
|
const expectedSocket = this.firewalled ? this.clientSocket : this.serverSocket;
|
|
const external = socket !== expectedSocket;
|
|
if (buffer[0] === REQUEST_ID) {
|
|
const req = Request.decode(this, socket, from, state);
|
|
if (req === null) return;
|
|
if (req.token !== null && !b4a.equals(req.token, this.token(req.from, 1)) && !b4a.equals(req.token, this.token(req.from, 0))) {
|
|
req.error(INVALID_TOKEN, { token: true });
|
|
return;
|
|
}
|
|
this.onrequest(req, external);
|
|
return;
|
|
}
|
|
if (buffer[0] === RESPONSE_ID) {
|
|
const res = decodeReply(from, state);
|
|
if (res === null) return;
|
|
for (let i = 0; i < this.inflight.length; i++) {
|
|
const req = this.inflight[i];
|
|
if (req.tid !== res.tid) continue;
|
|
res.rtt = Date.now() - req._timestamp;
|
|
if (this._adt && req.sent <= 2) {
|
|
this._adt.put(`${req.to.host}:${req.to.port}`, res.rtt);
|
|
}
|
|
if (i === this.inflight.length - 1) this.inflight.pop();
|
|
else this.inflight[i] = this.inflight.pop();
|
|
if (req.session) req.session._detach(req);
|
|
if (req._timeout) {
|
|
clearTimeout(req._timeout);
|
|
req._timeout = null;
|
|
}
|
|
this.congestion.recv();
|
|
if (req.internal && req.command < this.stats.commands.length) {
|
|
this.stats.commands[req.command].rx++;
|
|
}
|
|
this.stats.requests.active--;
|
|
this.stats.requests.responses++;
|
|
this.onresponse(res, external);
|
|
req.onresponse(res, req);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
token(addr, i) {
|
|
if (this._secrets === null) {
|
|
const buf = b4a.alloc(64);
|
|
this._secrets = [buf.subarray(0, 32), buf.subarray(32, 64)];
|
|
sodium.randombytes_buf(this._secrets[0]);
|
|
sodium.randombytes_buf(this._secrets[1]);
|
|
}
|
|
const token = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(token, b4a.from(addr.host), this._secrets[i]);
|
|
return token;
|
|
}
|
|
async destroy() {
|
|
if (this._destroying) return this._destroying;
|
|
this._destroying = this._destroy();
|
|
return this._destroying;
|
|
}
|
|
async _destroy() {
|
|
await this.bind();
|
|
await this._clear(false);
|
|
}
|
|
async _clear(suspended) {
|
|
if (this._drainInterval) {
|
|
clearInterval(this._drainInterval);
|
|
this._drainInterval = null;
|
|
}
|
|
while (this.inflight.length) {
|
|
const req = this.inflight.pop();
|
|
if (req._timeout) clearTimeout(req._timeout);
|
|
req._timeout = null;
|
|
req.destroyed = true;
|
|
if (req.session) req.session._detach(req);
|
|
this.congestion.recv();
|
|
this.stats.requests.active--;
|
|
req.onerror(suspended ? IO_SUSPENDED() : REQUEST_DESTROYED(), req);
|
|
}
|
|
await Promise.allSettled([this.serverSocket.close(), this.clientSocket.close()]);
|
|
this.networkInterfaces.destroy();
|
|
}
|
|
async suspend() {
|
|
this.suspended = true;
|
|
await this._clear(true);
|
|
this.congestion.clear();
|
|
if (this._drainInterval) {
|
|
clearInterval(this._drainInterval);
|
|
this._drainInterval = null;
|
|
}
|
|
}
|
|
async _rebind(binding) {
|
|
if (binding) await binding;
|
|
if (this._destroying) return this._destroying;
|
|
await this._bindSockets();
|
|
this.networkInterfaces = this.udx.watchNetworkInterfaces();
|
|
}
|
|
resume() {
|
|
this.suspended = false;
|
|
const binding = this._binding;
|
|
this._binding = this._rebind(binding);
|
|
return this._binding;
|
|
}
|
|
bind() {
|
|
if (this._binding) return this._binding;
|
|
this._binding = this._bindSockets();
|
|
return this._binding;
|
|
}
|
|
async _bindSockets() {
|
|
const serverSocket = this.udx.createSocket();
|
|
const candidatePorts = [];
|
|
if (this._boundServerPort) candidatePorts.push(this._boundServerPort);
|
|
for (let i = this.portRange[0]; i < this.portRange[1]; i++) candidatePorts.push(i);
|
|
for (const port of candidatePorts) {
|
|
if (serverSocket.bound) break;
|
|
try {
|
|
serverSocket.bind(port, this._host);
|
|
} catch (err) {
|
|
if (!this._anyPort) {
|
|
await serverSocket.close();
|
|
throw err;
|
|
}
|
|
}
|
|
}
|
|
if (!serverSocket.bound) {
|
|
try {
|
|
serverSocket.bind(0, this._host);
|
|
} catch (err) {
|
|
await serverSocket.close();
|
|
throw err;
|
|
}
|
|
}
|
|
const clientSocket = this.udx.createSocket();
|
|
try {
|
|
clientSocket.bind(this._boundClientPort || 0, this._host);
|
|
} catch {
|
|
try {
|
|
clientSocket.bind(0, this._host);
|
|
} catch (err) {
|
|
await serverSocket.close();
|
|
await clientSocket.close();
|
|
throw err;
|
|
}
|
|
}
|
|
this._boundServerPort = serverSocket.address().port;
|
|
this._boundClientPort = clientSocket.address().port;
|
|
this.clientSocket = clientSocket;
|
|
this.serverSocket = serverSocket;
|
|
this.serverSocket.on("message", this.onmessage.bind(this, this.serverSocket));
|
|
this.clientSocket.on("message", this.onmessage.bind(this, this.clientSocket));
|
|
if (this._drainInterval === null) {
|
|
this._drainInterval = setInterval(this._drain.bind(this), 750);
|
|
if (this._drainInterval.unref) this._drainInterval.unref();
|
|
}
|
|
for (const req of this.inflight) {
|
|
if (!req.socket) req.socket = this.firewalled ? this.clientSocket : this.serverSocket;
|
|
req.sent = 0;
|
|
req.send(false);
|
|
}
|
|
}
|
|
_drain() {
|
|
if (this._secrets !== null && --this._rotateSecrets === 0) {
|
|
this._rotateSecrets = 10;
|
|
const tmp = this._secrets[0];
|
|
this._secrets[0] = this._secrets[1];
|
|
this._secrets[1] = tmp;
|
|
sodium.crypto_generichash(tmp, tmp);
|
|
}
|
|
this.congestion.drain();
|
|
while (!this.congestion.isFull()) {
|
|
const p = this._pending.shift();
|
|
if (p === void 0) return;
|
|
p._sendNow();
|
|
}
|
|
}
|
|
createRequest(to, token, internal, command, target, value, session, ttl) {
|
|
if (this._destroying !== null) return null;
|
|
if (this._tid === 65536) this._tid = 0;
|
|
const tid = this._tid++;
|
|
const socket = this.firewalled ? this.clientSocket : this.serverSocket;
|
|
const req = new Request(
|
|
this,
|
|
socket,
|
|
tid,
|
|
null,
|
|
to,
|
|
token,
|
|
internal,
|
|
command,
|
|
target,
|
|
value,
|
|
session,
|
|
ttl || 0
|
|
);
|
|
this.inflight.push(req);
|
|
if (session) session._attach(req);
|
|
if (internal && command < this.stats.commands.length) {
|
|
this.stats.commands[command].tx++;
|
|
}
|
|
this.stats.requests.active++;
|
|
this.stats.requests.total++;
|
|
return req;
|
|
}
|
|
};
|
|
var Request = class _Request {
|
|
constructor(io, socket, tid, from, to, token, internal, command, target, value, session, ttl) {
|
|
this.socket = socket;
|
|
this.tid = tid;
|
|
this.from = from;
|
|
this.to = to;
|
|
this.token = token;
|
|
this.command = command;
|
|
this.target = target;
|
|
this.value = value;
|
|
this.internal = internal;
|
|
this.session = session;
|
|
this.ttl = ttl;
|
|
this.index = -1;
|
|
this.sent = 0;
|
|
this.retries = 3;
|
|
this.destroyed = false;
|
|
this.timeout = 0;
|
|
this.oncycle = noop;
|
|
this.onerror = noop;
|
|
this.onresponse = noop;
|
|
this._buffer = null;
|
|
this._io = io;
|
|
this._timeout = null;
|
|
this._timestamp = Date.now();
|
|
}
|
|
static decode(io, socket, from, state) {
|
|
try {
|
|
const flags = c.uint.decode(state);
|
|
const tid = c.uint16.decode(state);
|
|
const to = peer.ipv4.decode(state);
|
|
const id = flags & 1 ? c.fixed32.decode(state) : null;
|
|
const token = flags & 2 ? c.fixed32.decode(state) : null;
|
|
const internal = (flags & 4) !== 0;
|
|
const command = c.uint.decode(state);
|
|
const target = flags & 8 ? c.fixed32.decode(state) : null;
|
|
const value = flags & 16 ? c.buffer.decode(state) : null;
|
|
if (id !== null) from.id = validateId(id, from);
|
|
return new _Request(
|
|
io,
|
|
socket,
|
|
tid,
|
|
from,
|
|
to,
|
|
token,
|
|
internal,
|
|
command,
|
|
target,
|
|
value,
|
|
null,
|
|
0
|
|
);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
reply(value, opts = {}) {
|
|
const socket = opts.socket || this.socket;
|
|
const to = opts.to || this.from;
|
|
this._sendReply(0, value || null, opts.token !== false, opts.closerNodes !== false, to, socket);
|
|
}
|
|
error(code, opts = {}) {
|
|
const socket = opts.socket || this.socket;
|
|
const to = opts.to || this.from;
|
|
this._sendReply(code, null, opts.token === true, opts.closerNodes !== false, to, socket);
|
|
}
|
|
relay(value, to, opts) {
|
|
const socket = opts && opts.socket || this.socket;
|
|
const buffer = this._encodeRequest(null, value, to, socket);
|
|
socket.trySend(buffer, to.port, to.host, this.ttl);
|
|
}
|
|
send(force = false) {
|
|
if (this.destroyed) return;
|
|
if (this.socket === null) return;
|
|
if (this._buffer === null) {
|
|
this._buffer = this._encodeRequest(this.token, this.value, this.to, this.socket);
|
|
}
|
|
if (!force && this._io.congestion.isFull()) {
|
|
this._io._pending.push(this);
|
|
return;
|
|
}
|
|
this._sendNow();
|
|
}
|
|
sendReply(error, value, token, hasCloserNodes) {
|
|
this._sendReply(error, value, token, hasCloserNodes, this.from, this.socket, null);
|
|
}
|
|
_sendNow() {
|
|
if (this.destroyed) return;
|
|
this.sent++;
|
|
this._io.congestion.send();
|
|
this.socket.trySend(this._buffer, this.to.port, this.to.host, this.ttl);
|
|
if (this._timeout) clearTimeout(this._timeout);
|
|
const value = this.timeout || this._io._adt?.get(`${this.to.host}:${this.to.port}`, this.sent) || 1e3;
|
|
this._timeout = setTimeout(oncycle, value, this);
|
|
}
|
|
destroy(err) {
|
|
if (this.destroyed) return;
|
|
this.destroyed = true;
|
|
if (this._timeout) {
|
|
clearTimeout(this._timeout);
|
|
this._timeout = null;
|
|
}
|
|
const i = this._io.inflight.indexOf(this);
|
|
if (i === -1) return;
|
|
if (i === this._io.inflight.length - 1) this._io.inflight.pop();
|
|
else this._io.inflight[i] = this._io.inflight.pop();
|
|
if (this.session) this.session._detach(this);
|
|
this._io.stats.requests.active--;
|
|
this._io.congestion.recv();
|
|
this.onerror(err || REQUEST_DESTROYED(), this);
|
|
}
|
|
_sendReply(error, value, token, hasCloserNodes, from, socket) {
|
|
if (socket === null || this.destroyed) return;
|
|
const id = this._io.ephemeral === false && socket === this._io.serverSocket;
|
|
const closerNodes = this.target !== null && hasCloserNodes ? this._io.table.closest(this.target) : EMPTY_ARRAY;
|
|
const state = { start: 0, end: 1 + 1 + 6 + 2, buffer: null };
|
|
if (id) state.end += 32;
|
|
if (token) state.end += 32;
|
|
if (closerNodes.length > 0) peer.ipv4Array.preencode(state, closerNodes);
|
|
if (error > 0) c.uint.preencode(state, error);
|
|
if (value) c.buffer.preencode(state, value);
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
state.buffer[state.start++] = RESPONSE_ID;
|
|
state.buffer[state.start++] = (id ? 1 : 0) | (token ? 2 : 0) | (closerNodes.length > 0 ? 4 : 0) | (error > 0 ? 8 : 0) | (value ? 16 : 0);
|
|
c.uint16.encode(state, this.tid);
|
|
peer.ipv4.encode(state, from);
|
|
if (id) c.fixed32.encode(state, this._io.table.id);
|
|
if (token) c.fixed32.encode(state, this._io.token(from, 1));
|
|
if (closerNodes.length > 0) peer.ipv4Array.encode(state, closerNodes);
|
|
if (error > 0) c.uint.encode(state, error);
|
|
if (value) c.buffer.encode(state, value);
|
|
socket.trySend(state.buffer, from.port, from.host, this.ttl);
|
|
}
|
|
_encodeRequest(token, value, to, socket) {
|
|
const id = this._io.ephemeral === false && socket === this._io.serverSocket;
|
|
const state = { start: 0, end: 1 + 1 + 6 + 2, buffer: null };
|
|
if (id) state.end += 32;
|
|
if (token) state.end += 32;
|
|
c.uint.preencode(state, this.command);
|
|
if (this.target) state.end += 32;
|
|
if (value) c.buffer.preencode(state, value);
|
|
state.buffer = b4a.allocUnsafe(state.end);
|
|
state.buffer[state.start++] = REQUEST_ID;
|
|
state.buffer[state.start++] = (id ? 1 : 0) | (token ? 2 : 0) | (this.internal ? 4 : 0) | (this.target ? 8 : 0) | (value ? 16 : 0);
|
|
c.uint16.encode(state, this.tid);
|
|
peer.ipv4.encode(state, to);
|
|
if (id) c.fixed32.encode(state, this._io.table.id);
|
|
if (token) c.fixed32.encode(state, token);
|
|
c.uint.encode(state, this.command);
|
|
if (this.target) c.fixed32.encode(state, this.target);
|
|
if (value) c.buffer.encode(state, value);
|
|
return state.buffer;
|
|
}
|
|
};
|
|
var CongestionWindow = class {
|
|
constructor(maxWindow) {
|
|
this._i = 0;
|
|
this._total = 0;
|
|
this._window = [0, 0, 0, 0];
|
|
this._maxWindow = maxWindow;
|
|
}
|
|
clear() {
|
|
this._i = 0;
|
|
this._total = 0;
|
|
this._window = [0, 0, 0, 0];
|
|
}
|
|
isFull() {
|
|
return this._total >= 2 * this._maxWindow || this._window[this._i] >= this._maxWindow;
|
|
}
|
|
recv() {
|
|
if (this._window[this._i] > 0) {
|
|
this._window[this._i]--;
|
|
this._total--;
|
|
}
|
|
}
|
|
send() {
|
|
this._total++;
|
|
this._window[this._i]++;
|
|
}
|
|
drain() {
|
|
this._i = this._i + 1 & 3;
|
|
this._total -= this._window[this._i];
|
|
this._window[this._i] = 0;
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
function oncycle(req) {
|
|
req._timeout = null;
|
|
req.oncycle(req);
|
|
if (req.sent > req.retries) {
|
|
req._io.stats.requests.timeouts++;
|
|
req.destroy(REQUEST_TIMEOUT());
|
|
req._io.ontimeout(req);
|
|
} else {
|
|
req._io.stats.requests.retries++;
|
|
req.send();
|
|
}
|
|
}
|
|
function decodeReply(from, state) {
|
|
try {
|
|
const flags = c.uint.decode(state);
|
|
const tid = c.uint16.decode(state);
|
|
const to = peer.ipv4.decode(state);
|
|
const id = flags & 1 ? c.fixed32.decode(state) : null;
|
|
const token = flags & 2 ? c.fixed32.decode(state) : null;
|
|
const closerNodes = flags & 4 ? peer.ipv4Array.decode(state) : null;
|
|
const error = flags & 8 ? c.uint.decode(state) : 0;
|
|
const value = flags & 16 ? c.buffer.decode(state) : null;
|
|
if (id !== null) from.id = validateId(id, from);
|
|
return { tid, rtt: 0, from, to, token, closerNodes, error, value };
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
function validateId(id, from) {
|
|
const expected = peer.id(from.host, from.port);
|
|
return b4a.equals(expected, id) ? expected : null;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dht-rpc/lib/commands.js
|
|
var require_commands = __commonJS({
|
|
"../../node_modules/dht-rpc/lib/commands.js"(exports) {
|
|
exports.PING = 0;
|
|
exports.PING_NAT = 1;
|
|
exports.FIND_NODE = 2;
|
|
exports.DOWN_HINT = 3;
|
|
exports.DELAYED_PING = 4;
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dht-rpc/lib/query.js
|
|
var require_query = __commonJS({
|
|
"../../node_modules/dht-rpc/lib/query.js"(exports, module) {
|
|
var { Readable, getStreamError } = require_streamx();
|
|
var b4a = require_b4a();
|
|
var peer = require_peer();
|
|
var { DOWN_HINT } = require_commands();
|
|
var DONE = [];
|
|
var DOWN = [];
|
|
module.exports = class Query extends Readable {
|
|
constructor(dht, target, internal, command, value, opts = {}) {
|
|
super();
|
|
dht.stats.queries.total++;
|
|
dht.stats.queries.active++;
|
|
this.force = !!opts.force;
|
|
this.dht = dht;
|
|
this.k = this.dht.table.k;
|
|
this.target = target;
|
|
this.internal = internal;
|
|
this.command = command;
|
|
this.value = value;
|
|
this.errors = 0;
|
|
this.successes = 0;
|
|
this.concurrency = opts.concurrency || this.dht.concurrency;
|
|
this.inflight = 0;
|
|
this.map = opts.map || defaultMap;
|
|
this.retries = opts.retries === 0 ? 0 : opts.retries || (this.internal && command === DOWN_HINT ? 3 : 5);
|
|
this.closestReplies = [];
|
|
this._slow = 0;
|
|
this._slowdown = false;
|
|
this._seen = /* @__PURE__ */ new Map();
|
|
this._pending = [];
|
|
this._fromTable = false;
|
|
this._commit = opts.commit === true ? autoCommit : opts.commit || null;
|
|
this._commiting = false;
|
|
this._session = opts.session || dht.session();
|
|
this._autoDestroySession = !opts.session;
|
|
this._onlyClosestNodes = false;
|
|
this._onvisitbound = this._onvisit.bind(this);
|
|
this._onerrorbound = this._onerror.bind(this);
|
|
this._oncyclebound = this._oncycle.bind(this);
|
|
const nodes = opts.nodes || opts.closestNodes;
|
|
const replies = opts.replies || opts.closestReplies;
|
|
if (nodes) {
|
|
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
const node = nodes[i];
|
|
this._addPending(
|
|
{
|
|
id: node.id || peer.id(node.host, node.port),
|
|
host: node.host,
|
|
port: node.port
|
|
},
|
|
null
|
|
);
|
|
}
|
|
} else if (replies) {
|
|
for (let i = replies.length - 1; i >= 0; i--) {
|
|
this._addPending(replies[i].from, null);
|
|
}
|
|
}
|
|
if (opts.onlyClosestNodes) this._onlyClosestNodes = true;
|
|
}
|
|
get closestNodes() {
|
|
const nodes = new Array(this.closestReplies.length);
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
nodes[i] = this.closestReplies[i].from;
|
|
}
|
|
return nodes;
|
|
}
|
|
finished() {
|
|
return new Promise((resolve, reject) => {
|
|
if (this.destroyed) {
|
|
const error2 = getStreamError(this);
|
|
if (error2) reject(error2);
|
|
else resolve();
|
|
return;
|
|
}
|
|
const self2 = this;
|
|
let error = null;
|
|
this.resume();
|
|
this.on("error", onerror);
|
|
this.on("close", onclose);
|
|
function onclose() {
|
|
self2.removeListener("error", onerror);
|
|
self2.removeListener("close", onclose);
|
|
if (error) reject(error);
|
|
else resolve();
|
|
}
|
|
function onerror(err) {
|
|
error = err;
|
|
}
|
|
});
|
|
}
|
|
_addFromTable() {
|
|
if (this._pending.length >= this.k) return;
|
|
this._fromTable = true;
|
|
const closest = this.dht.table.closest(this.target, this.k - this._pending.length);
|
|
for (const node of closest) {
|
|
this._addPending({ id: node.id, host: node.host, port: node.port }, null);
|
|
}
|
|
}
|
|
async _open(cb) {
|
|
this._addFromTable();
|
|
if (this._pending.length >= this.k) return cb(null);
|
|
for await (const node of this.dht._resolveBootstrapNodes()) {
|
|
this._addPending(node, null);
|
|
}
|
|
cb(null);
|
|
}
|
|
_isCloser(id) {
|
|
return this.closestReplies.length < this.k || this._compare(id, this.closestReplies[this.closestReplies.length - 1].from.id) < 0;
|
|
}
|
|
_addPending(node, ref) {
|
|
if (this._onlyClosestNodes) return false;
|
|
const addr = node.host + ":" + node.port;
|
|
const refs = this._seen.get(addr);
|
|
const isCloser = this._isCloser(node.id);
|
|
if (refs === DONE) {
|
|
return isCloser;
|
|
}
|
|
if (refs === DOWN) {
|
|
if (ref) this._downHint(ref, node);
|
|
return isCloser;
|
|
}
|
|
if (refs) {
|
|
if (ref !== null) refs.push(ref);
|
|
return isCloser;
|
|
}
|
|
if (!isCloser) {
|
|
return false;
|
|
}
|
|
this._seen.set(addr, ref === null ? [] : [ref]);
|
|
this._pending.push(node);
|
|
return true;
|
|
}
|
|
_read(cb) {
|
|
this._readMore();
|
|
cb(null);
|
|
}
|
|
_readMore() {
|
|
if (this.destroying || this._commiting) return;
|
|
const concurrency = (this._slowdown ? 3 : this.concurrency) + this._slow;
|
|
while (this.inflight < concurrency && this._pending.length > 0) {
|
|
const next = this._pending.pop();
|
|
if (next && next.id && !this._isCloser(next.id)) continue;
|
|
this._visit(next);
|
|
}
|
|
if (!this._fromTable && this.successes === 0 && this.errors === 0) {
|
|
this._slowdown = true;
|
|
}
|
|
if (this._pending.length > 0) return;
|
|
if (this.inflight === 0 || this._slow === this.inflight && this.closestReplies.length >= this.k) {
|
|
if (!this._fromTable && this.successes < this.k / 4) {
|
|
this._addFromTable();
|
|
this._readMore();
|
|
return;
|
|
}
|
|
this._flush();
|
|
}
|
|
}
|
|
_flush() {
|
|
if (this._commiting) return;
|
|
this._commiting = true;
|
|
if (this._commit === null) {
|
|
this.push(null);
|
|
return;
|
|
}
|
|
const p = [];
|
|
for (const m of this.closestReplies) p.push(this._commit(m, this.dht, this));
|
|
this._endAfterCommit(p);
|
|
}
|
|
_endAfterCommit(ps) {
|
|
if (!ps.length) {
|
|
this.destroy(new Error("Too few nodes responded"));
|
|
return;
|
|
}
|
|
const self2 = this;
|
|
let pending = ps.length;
|
|
let success = 0;
|
|
for (const p of ps) p.then(ondone, onerror);
|
|
function ondone() {
|
|
success++;
|
|
if (--pending === 0) self2.push(null);
|
|
}
|
|
function onerror(err) {
|
|
if (--pending > 0) return;
|
|
if (success) self2.push(null);
|
|
else self2.destroy(err);
|
|
}
|
|
}
|
|
_dec(req) {
|
|
if (req.oncycle === noop) {
|
|
this._slow--;
|
|
} else {
|
|
req.oncycle = noop;
|
|
}
|
|
this.inflight--;
|
|
}
|
|
_onvisit(m, req) {
|
|
this._dec(req);
|
|
const addr = req.to.host + ":" + req.to.port;
|
|
this._seen.set(addr, DONE);
|
|
if (this._commiting) return;
|
|
if (m.error === 0) this.successes++;
|
|
else this.errors++;
|
|
if (m.error === 0 && m.from.id !== null && this._isCloser(m.from.id)) this._pushClosest(m);
|
|
if (m.closerNodes !== null) {
|
|
for (const node of m.closerNodes) {
|
|
node.id = peer.id(node.host, node.port);
|
|
if (this.dht._filterNode !== null && !this.dht._filterNode(node)) continue;
|
|
if (b4a.equals(node.id, this.dht.table.id)) continue;
|
|
if (!this._addPending(node, m.from)) break;
|
|
}
|
|
}
|
|
if (!this._fromTable && this.successes + this.errors >= this.concurrency) {
|
|
this._slowdown = false;
|
|
}
|
|
if (m.error !== 0) {
|
|
this._readMore();
|
|
return;
|
|
}
|
|
const data = this.map(m);
|
|
if (!data || this.push(data) !== false) {
|
|
this._readMore();
|
|
}
|
|
}
|
|
_onerror(err, req) {
|
|
const addr = req.to.host + ":" + req.to.port;
|
|
const refs = this._seen.get(addr);
|
|
if (err.code === "REQUEST_TIMEOUT") {
|
|
this._seen.set(addr, DOWN);
|
|
for (const node of refs) this._downHint(node, req.to);
|
|
}
|
|
this._dec(req);
|
|
this.errors++;
|
|
this._readMore();
|
|
}
|
|
_oncycle(req) {
|
|
req.oncycle = noop;
|
|
this._slow++;
|
|
this._readMore();
|
|
}
|
|
_downHint(node, down) {
|
|
if (this.dht._downHintsRateLimit !== -1 && this.dht._downHintsSentPerTick >= this.dht._downHintsRateLimit) {
|
|
return null;
|
|
}
|
|
this.dht._downHintsSentPerTick++;
|
|
const state = { start: 0, end: 6, buffer: b4a.allocUnsafe(6) };
|
|
peer.ipv4.encode(state, down);
|
|
this.dht._request(node, false, true, DOWN_HINT, null, state.buffer, this._session, noop, noop);
|
|
}
|
|
_pushClosest(m) {
|
|
this.closestReplies.push(m);
|
|
for (let i = this.closestReplies.length - 2; i >= 0; i--) {
|
|
const prev = this.closestReplies[i];
|
|
const cmp = this._compare(prev.from.id, m.from.id);
|
|
if (cmp < 0) break;
|
|
if (cmp === 0) {
|
|
this.closestReplies.splice(i + 1, 1);
|
|
break;
|
|
}
|
|
this.closestReplies[i + 1] = prev;
|
|
this.closestReplies[i] = m;
|
|
}
|
|
if (this.closestReplies.length > this.k) this.closestReplies.pop();
|
|
}
|
|
_compare(a, b) {
|
|
for (let i = 0; i < a.length; i++) {
|
|
if (a[i] === b[i]) continue;
|
|
const t = this.target[i];
|
|
return (t ^ a[i]) - (t ^ b[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
_visit(to) {
|
|
this.inflight++;
|
|
const req = this.dht._request(
|
|
to,
|
|
this.force,
|
|
this.internal,
|
|
this.command,
|
|
this.target,
|
|
this.value,
|
|
this._session,
|
|
this._onvisitbound,
|
|
this._onerrorbound
|
|
);
|
|
if (req === null) {
|
|
this.destroy(new Error("Node was destroyed"));
|
|
return;
|
|
}
|
|
req.retries = this.retries;
|
|
req.oncycle = this._oncyclebound;
|
|
if (this.force) req.retries = 0;
|
|
}
|
|
_destroy(cb) {
|
|
this.dht.stats.queries.active--;
|
|
if (this._autoDestroySession) this._session.destroy();
|
|
cb(null);
|
|
}
|
|
};
|
|
function autoCommit(reply, dht, query) {
|
|
if (!reply.token) return Promise.reject(new Error("No token received for closest node"));
|
|
return dht.request(
|
|
{
|
|
token: reply.token,
|
|
target: query.target,
|
|
command: query.command,
|
|
value: query.value
|
|
},
|
|
reply.from
|
|
);
|
|
}
|
|
function defaultMap(m) {
|
|
return m;
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dht-rpc/lib/session.js
|
|
var require_session = __commonJS({
|
|
"../../node_modules/dht-rpc/lib/session.js"(exports, module) {
|
|
module.exports = class Session {
|
|
constructor(dht) {
|
|
this.dht = dht;
|
|
this.inflight = [];
|
|
}
|
|
_attach(req) {
|
|
req.index = this.inflight.push(req) - 1;
|
|
}
|
|
_detach(req) {
|
|
const i = req.index;
|
|
if (i === -1) return;
|
|
req.index = -1;
|
|
if (i === this.inflight.length - 1) this.inflight.pop();
|
|
else {
|
|
const req2 = this.inflight[i] = this.inflight.pop();
|
|
req2.index = i;
|
|
}
|
|
}
|
|
query({ target, command, value }, opts = {}) {
|
|
return this.dht.query({ target, command, value }, { ...opts, session: this });
|
|
}
|
|
request({ token, command, target, value }, { host, port }, opts = {}) {
|
|
return this.dht.request(
|
|
{ token, command, target, value },
|
|
{ host, port },
|
|
{ ...opts, session: this }
|
|
);
|
|
}
|
|
ping({ host, port }, opts = {}) {
|
|
return this.dht.ping({ host, port }, { ...opts, session: this });
|
|
}
|
|
destroy(err) {
|
|
while (this.inflight.length) {
|
|
const req = this.inflight[0];
|
|
this.dht.io.congestion.recv();
|
|
req.destroy(err);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/dht-rpc/index.js
|
|
var require_dht_rpc = __commonJS({
|
|
"../../node_modules/dht-rpc/index.js"(exports, module) {
|
|
var { EventEmitter } = __require("events");
|
|
var Table = require_kademlia_routing_table();
|
|
var TOS = require_time_ordered_set();
|
|
var UDX = require_udx();
|
|
var sodium = require_sodium_universal();
|
|
var c = require_compact_encoding();
|
|
var NatSampler = require_nat_sampler();
|
|
var b4a = require_b4a();
|
|
var NetworkHealth = require_health();
|
|
var IO = require_io();
|
|
var Query = require_query();
|
|
var Session = require_session();
|
|
var peer = require_peer();
|
|
var { UNKNOWN_COMMAND, INVALID_TOKEN } = require_errors5();
|
|
var { PING, PING_NAT, FIND_NODE, DOWN_HINT, DELAYED_PING } = require_commands();
|
|
var TMP = b4a.allocUnsafe(32);
|
|
var TICK_INTERVAL = 5e3;
|
|
var SLEEPING_INTERVAL = 3 * TICK_INTERVAL;
|
|
var STABLE_TICKS = 240;
|
|
var MORE_STABLE_TICKS = 3 * STABLE_TICKS;
|
|
var REFRESH_TICKS = 60;
|
|
var RECENT_NODE = 12;
|
|
var OLD_NODE = 360;
|
|
var DEFAULTS = {
|
|
concurrency: 10,
|
|
maxWindow: IO.DEFAULT_MAX_WINDOW,
|
|
maxPingDelay: 1e4
|
|
};
|
|
var DHT = class extends EventEmitter {
|
|
constructor(opts = {}) {
|
|
super();
|
|
this.bootstrapNodes = opts.bootstrap === false ? [] : (opts.bootstrap || []).map(parseNode);
|
|
this.table = new Table(randomBytes(32));
|
|
this.nodes = new TOS();
|
|
this.udx = opts.udx || new UDX();
|
|
this.io = new IO(this.table, this.udx, {
|
|
...opts,
|
|
onrequest: this._onrequest.bind(this),
|
|
onresponse: this._onresponse.bind(this),
|
|
ontimeout: this._ontimeout.bind(this)
|
|
});
|
|
this.health = new NetworkHealth(this);
|
|
this.concurrency = opts.concurrency || DEFAULTS.concurrency;
|
|
this.maxPingDelay = opts.maxPingDelay || DEFAULTS.maxPingDelay;
|
|
this.bootstrapped = false;
|
|
this.ephemeral = true;
|
|
this.firewalled = this.io.firewalled;
|
|
this.adaptive = typeof opts.ephemeral !== "boolean" && opts.adaptive !== false;
|
|
this.destroyed = false;
|
|
this.suspended = false;
|
|
this.online = true;
|
|
this.degraded = false;
|
|
this.stats = {
|
|
queries: { active: 0, total: 0 },
|
|
requests: this.io.stats.requests,
|
|
commands: {
|
|
ping: this.io.stats.commands[PING],
|
|
pingNat: this.io.stats.commands[PING_NAT],
|
|
findNode: this.io.stats.commands[FIND_NODE],
|
|
downHint: this.io.stats.commands[DOWN_HINT]
|
|
}
|
|
};
|
|
this._nat = new NatSampler();
|
|
this._quickFirewall = opts.quickFirewall !== false;
|
|
this._forcePersistent = opts.ephemeral === false;
|
|
this._repinging = 0;
|
|
this._checks = 0;
|
|
this._tick = randomOffset(100);
|
|
this._refreshTicks = randomOffset(REFRESH_TICKS);
|
|
this._stableTicks = this.adaptive ? STABLE_TICKS : 0;
|
|
this._tickInterval = setInterval(this._ontick.bind(this), TICK_INTERVAL);
|
|
this._lastTick = Date.now();
|
|
this._lastHost = null;
|
|
this._filterNode = opts.filterNode || opts.addNode || null;
|
|
this._onrow = (row) => row.on("full", (node) => this._onfullrow(node, row));
|
|
this._nonePersistentSamples = [];
|
|
this._bootstrapping = this._bootstrap();
|
|
this._bootstrapping.catch(noop);
|
|
this._sendDownHints = opts.sendDownHints !== false;
|
|
this._downHintsRateLimit = opts.downHintsRateLimit !== void 0 ? opts.downHintsRateLimit : 10 * 5;
|
|
this._downHintsSentPerTick = 0;
|
|
this._pendingTimers = /* @__PURE__ */ new Set();
|
|
this.table.on("row", this._onrow);
|
|
this.io.networkInterfaces.on("change", (interfaces) => this._onnetworkchange(interfaces));
|
|
if (opts.nodes) {
|
|
for (let i = opts.nodes.length - 1; i >= 0; i--) {
|
|
this.addNode(opts.nodes[i]);
|
|
}
|
|
}
|
|
}
|
|
static DEFAULTS = DEFAULTS;
|
|
static bootstrapper(port, host, opts) {
|
|
if (!port) throw new Error("Port is required");
|
|
if (!host) throw new Error("Host is required");
|
|
if (host === "0.0.0.0" || host === "::") throw new Error("Invalid host");
|
|
if (!UDX.isIPv4(host)) throw new Error("Host must be a IPv4 address");
|
|
const dht = new this({
|
|
port,
|
|
ephemeral: false,
|
|
firewalled: false,
|
|
anyPort: false,
|
|
bootstrap: [],
|
|
...opts
|
|
});
|
|
dht._nat.add(host, port);
|
|
return dht;
|
|
}
|
|
get id() {
|
|
return this.ephemeral ? null : this.table.id;
|
|
}
|
|
get host() {
|
|
return this._nat.host;
|
|
}
|
|
get port() {
|
|
return this._nat.port;
|
|
}
|
|
get randomized() {
|
|
return this._nat.host !== null && this._nat.port === 0;
|
|
}
|
|
get socket() {
|
|
return this.firewalled ? this.io.clientSocket : this.io.serverSocket;
|
|
}
|
|
get config() {
|
|
return {
|
|
concurrency: this.concurrency,
|
|
maxWindow: this.io.congestion._maxWindow,
|
|
randomPunchInterval: this._randomPunchInterval,
|
|
connectionKeepAlive: this.connectionKeepAlive,
|
|
sendDownHints: this._sendDownHints,
|
|
downHintsRateLimit: this._downHintsRateLimit
|
|
};
|
|
}
|
|
onmessage(socket, buf, rinfo) {
|
|
if (buf.byteLength > 1) this.io.onmessage(socket, buf, rinfo);
|
|
}
|
|
bind() {
|
|
return this.io.bind();
|
|
}
|
|
async suspend({ log = noop } = {}) {
|
|
log("Suspending waiting for io bind...");
|
|
await this.io.bind();
|
|
log("Done, continuing");
|
|
if (this.suspended || this.destroyed) return;
|
|
this.suspended = true;
|
|
clearInterval(this._tickInterval);
|
|
log("Done, suspending io");
|
|
await this.io.suspend({ log });
|
|
log("Done, dht suspended");
|
|
this.emit("suspend");
|
|
}
|
|
async resume({ log = noop } = {}) {
|
|
if (!this.suspended || this.destroyed) return;
|
|
this.suspended = false;
|
|
this._tickInterval = setInterval(this._ontick.bind(this), TICK_INTERVAL);
|
|
this._onwakeup();
|
|
log("Resuming io");
|
|
await this.io.resume();
|
|
log("Done, dht resumed");
|
|
this.io.networkInterfaces.on("change", (interfaces) => this._onnetworkchange(interfaces));
|
|
this.refresh();
|
|
this.emit("resume");
|
|
}
|
|
address() {
|
|
const socket = this.socket;
|
|
return socket ? socket.address() : null;
|
|
}
|
|
localAddress() {
|
|
if (!this.io.serverSocket) return null;
|
|
return {
|
|
host: localIP(this.udx),
|
|
port: this.io.serverSocket.address().port
|
|
};
|
|
}
|
|
remoteAddress() {
|
|
if (!this.host) return null;
|
|
if (!this.port) return null;
|
|
if (this.firewalled) return null;
|
|
if (!this.io.serverSocket) return null;
|
|
const port = this.io.serverSocket.address().port;
|
|
if (port !== this.port) return null;
|
|
return {
|
|
host: this.host,
|
|
port
|
|
};
|
|
}
|
|
addNode({ host, port }) {
|
|
this._addNode({
|
|
id: peer.id(host, port),
|
|
port,
|
|
host,
|
|
token: null,
|
|
to: null,
|
|
sampled: 0,
|
|
added: this._tick,
|
|
pinged: 0,
|
|
seen: 0,
|
|
downHints: 0,
|
|
prev: null,
|
|
next: null
|
|
});
|
|
}
|
|
toArray(opts) {
|
|
const limit = opts && opts.limit;
|
|
if (limit === 0) return [];
|
|
return this.nodes.toArray({ limit, reverse: true }).map(({ host, port }) => ({ host, port }));
|
|
}
|
|
async fullyBootstrapped() {
|
|
return this._bootstrapping;
|
|
}
|
|
ready() {
|
|
return this.fullyBootstrapped();
|
|
}
|
|
findNode(target, opts) {
|
|
if (this.destroyed) throw new Error("Node destroyed");
|
|
this._refreshTicks = REFRESH_TICKS;
|
|
return new Query(this, target, true, FIND_NODE, null, opts);
|
|
}
|
|
query({ target, command, value }, opts) {
|
|
if (this.destroyed) throw new Error("Node destroyed");
|
|
this._refreshTicks = REFRESH_TICKS;
|
|
return new Query(this, target, false, command, value || null, opts);
|
|
}
|
|
ping({ host, port }, opts) {
|
|
let value = null;
|
|
if (opts && opts.size && opts.size > 0) value = b4a.alloc(opts.size);
|
|
const req = this.io.createRequest(
|
|
{ id: null, host, port },
|
|
null,
|
|
true,
|
|
PING,
|
|
null,
|
|
value,
|
|
opts && opts.session || null,
|
|
opts && opts.ttl
|
|
);
|
|
return this._requestToPromise(req, opts);
|
|
}
|
|
delayedPing({ host, port }, delayMs, opts) {
|
|
if (delayMs > this.maxPingDelay) {
|
|
throw new Error(`Delay exceeds max delay: ${this.maxPingDelay}ms`);
|
|
}
|
|
const value = b4a.allocUnsafe(4);
|
|
c.uint32.encode({ start: 0, end: 4, buffer: value }, delayMs);
|
|
const req = this.io.createRequest(
|
|
{ id: null, host, port },
|
|
null,
|
|
true,
|
|
DELAYED_PING,
|
|
null,
|
|
value,
|
|
opts && opts.session || null,
|
|
opts && opts.ttl
|
|
);
|
|
req.timeout = delayMs + 1e3;
|
|
return this._requestToPromise(req, opts);
|
|
}
|
|
async rttStats() {
|
|
const stats = {
|
|
successes: 0,
|
|
errors: 0,
|
|
responses: {
|
|
avgRtt: 0,
|
|
errors: 0,
|
|
avgCloserNodes: 0
|
|
},
|
|
closestReplies: {
|
|
avgRtt: 0,
|
|
errors: 0,
|
|
avgCloserNodes: 0
|
|
}
|
|
};
|
|
if (this.nodes.latest) {
|
|
const q = this.findNode(this.nodes.latest.id);
|
|
let responseCount = 0;
|
|
let closestCount = 0;
|
|
for await (const msg of q) {
|
|
stats.responses.avgRtt += msg.rtt;
|
|
stats.responses.errors += msg.error;
|
|
stats.responses.avgCloserNodes += msg.closerNodes?.length || 0;
|
|
responseCount++;
|
|
}
|
|
stats.responses.avgRtt /= responseCount;
|
|
stats.responses.avgCloserNodes /= responseCount;
|
|
for await (const msg of q.closestReplies) {
|
|
stats.closestReplies.avgRtt += msg.rtt;
|
|
stats.closestReplies.errors += msg.error;
|
|
stats.closestReplies.avgCloserNodes += msg.closerNodes?.length || 0;
|
|
closestCount++;
|
|
}
|
|
stats.closestReplies.avgRtt /= closestCount;
|
|
stats.closestReplies.avgCloserNodes /= closestCount;
|
|
stats.successes = q.successes;
|
|
stats.errors = q.errors;
|
|
}
|
|
return stats;
|
|
}
|
|
request({ token = null, command, target = null, value = null }, { host, port }, opts) {
|
|
const req = this.io.createRequest(
|
|
{ id: null, host, port },
|
|
token,
|
|
false,
|
|
command,
|
|
target,
|
|
value,
|
|
opts && opts.session || null,
|
|
opts && opts.ttl
|
|
);
|
|
return this._requestToPromise(req, opts);
|
|
}
|
|
session() {
|
|
return new Session(this);
|
|
}
|
|
_requestToPromise(req, opts) {
|
|
if (req === null) return Promise.reject(new Error("Node destroyed"));
|
|
if (opts && opts.socket) req.socket = opts.socket;
|
|
if (opts && opts.retry === false) req.retries = 0;
|
|
return new Promise((resolve, reject) => {
|
|
req.onresponse = resolve;
|
|
req.onerror = reject;
|
|
req.send();
|
|
});
|
|
}
|
|
async _bootstrap() {
|
|
const self2 = this;
|
|
await Promise.resolve();
|
|
await this.io.bind();
|
|
this.emit("listening");
|
|
let first = this.firewalled && this._quickFirewall && !this._forcePersistent;
|
|
let testNat = false;
|
|
const onlyFirewall = !this._forcePersistent;
|
|
for (let i = 0; i < 2; i++) {
|
|
await this._backgroundQuery(this.table.id).on("data", ondata).finished();
|
|
if (this.bootstrapped || !testNat && !this._forcePersistent) break;
|
|
if (!await this._updateNetworkState(onlyFirewall)) break;
|
|
}
|
|
if (this.bootstrapped) return;
|
|
this.bootstrapped = true;
|
|
this.emit("ready");
|
|
function ondata(data) {
|
|
if (!first) return;
|
|
first = false;
|
|
const value = b4a.allocUnsafe(2);
|
|
c.uint16.encode({ start: 0, end: 2, buffer: value }, self2.io.serverSocket.address().port);
|
|
self2._request(
|
|
data.from,
|
|
false,
|
|
true,
|
|
PING_NAT,
|
|
null,
|
|
value,
|
|
null,
|
|
() => {
|
|
testNat = true;
|
|
},
|
|
noop
|
|
);
|
|
}
|
|
}
|
|
refresh() {
|
|
const node = this.table.random();
|
|
this._backgroundQuery(node ? node.id : this.table.id).on("error", noop);
|
|
}
|
|
async destroy() {
|
|
const emitClose = !this.destroyed;
|
|
this.destroyed = true;
|
|
clearInterval(this._tickInterval);
|
|
for (const timer of this._pendingTimers) {
|
|
clearTimeout(timer);
|
|
}
|
|
await this.io.destroy();
|
|
if (emitClose) this.emit("close");
|
|
}
|
|
_request(to, force, internal, command, target, value, session, onresponse, onerror) {
|
|
if (internal && !this._sendDownHints && command === DOWN_HINT) return null;
|
|
const req = this.io.createRequest(to, null, internal, command, target, value, session);
|
|
if (req === null) return null;
|
|
req.onresponse = onresponse;
|
|
req.onerror = onerror;
|
|
req.send(force);
|
|
return req;
|
|
}
|
|
_natAdd(host, port) {
|
|
const prevHost = this._nat.host;
|
|
const prevPort = this._nat.port;
|
|
this._nat.add(host, port);
|
|
if (prevHost === this._nat.host && prevPort === this._nat.port) return;
|
|
this.emit("nat-update", this._nat.host, this._nat.port);
|
|
}
|
|
// we don't check that this is a bootstrap node but we limit the sample size to very few nodes, so fine
|
|
_sampleBootstrapMaybe(from, to) {
|
|
if (this._nonePersistentSamples.length >= Math.max(1, this.bootstrapNodes.length)) return;
|
|
const id = from.host + ":" + from.port;
|
|
if (this._nonePersistentSamples.indexOf(id) > -1) return;
|
|
this._nonePersistentSamples.push(id);
|
|
this._natAdd(to.host, to.port);
|
|
}
|
|
_addNodeFromNetwork(sample, from, to) {
|
|
if (this._filterNode !== null && !this._filterNode(from)) {
|
|
return;
|
|
}
|
|
if (from.id === null) {
|
|
this._sampleBootstrapMaybe(from, to);
|
|
return;
|
|
}
|
|
const oldNode = this.table.get(from.id);
|
|
if (oldNode) {
|
|
if (sample && (oldNode.sampled === 0 || this._tick - oldNode.sampled >= OLD_NODE)) {
|
|
oldNode.to = to;
|
|
oldNode.sampled = this._tick;
|
|
this._natAdd(to.host, to.port);
|
|
}
|
|
oldNode.pinged = oldNode.seen = this._tick;
|
|
this.nodes.add(oldNode);
|
|
return;
|
|
}
|
|
this._addNode({
|
|
id: from.id,
|
|
port: from.port,
|
|
host: from.host,
|
|
to,
|
|
sampled: 0,
|
|
added: this._tick,
|
|
pinged: this._tick,
|
|
// last time we interacted with them
|
|
seen: this._tick,
|
|
// last time we heard from them
|
|
downHints: 0,
|
|
prev: null,
|
|
next: null
|
|
});
|
|
}
|
|
_addNode(node) {
|
|
if (this.nodes.has(node) || b4a.equals(node.id, this.table.id)) return;
|
|
node.added = node.pinged = node.seen = this._tick;
|
|
if (!this.table.add(node)) return;
|
|
this.nodes.add(node);
|
|
if (node.to && node.sampled === 0) {
|
|
node.sampled = this._tick;
|
|
this._natAdd(node.to.host, node.to.port);
|
|
}
|
|
this.emit("add-node", node);
|
|
}
|
|
_removeStaleNode(node, lastSeen) {
|
|
if (node.seen <= lastSeen) this._removeNode(node);
|
|
}
|
|
_removeNode(node) {
|
|
if (!this.nodes.has(node)) return;
|
|
this.table.remove(node.id);
|
|
this.nodes.remove(node);
|
|
this.emit("remove-node", node);
|
|
}
|
|
_onwakeup() {
|
|
this._tick += 2 * OLD_NODE;
|
|
this._tick += 8 - (this._tick & 7) - 2;
|
|
this._stableTicks = MORE_STABLE_TICKS;
|
|
this._refreshTicks = 1;
|
|
this._lastHost = null;
|
|
this.health.reset();
|
|
if (this.adaptive) {
|
|
if (!this.ephemeral) {
|
|
this.ephemeral = true;
|
|
this.io.ephemeral = true;
|
|
this.emit("ephemeral");
|
|
}
|
|
}
|
|
this.emit("wakeup");
|
|
}
|
|
_onfullrow(newNode, row) {
|
|
if (!this.bootstrapped || this._repinging >= 3) return;
|
|
let oldest = null;
|
|
for (const node of row.nodes) {
|
|
if (node.pinged === this._tick) continue;
|
|
if (oldest === null || oldest.pinged > node.pinged || oldest.pinged === node.pinged && oldest.added > node.added) {
|
|
oldest = node;
|
|
}
|
|
}
|
|
if (oldest === null) return;
|
|
if (this._tick - oldest.pinged < RECENT_NODE && this._tick - oldest.added > OLD_NODE) return;
|
|
this._repingAndSwap(newNode, oldest);
|
|
}
|
|
_onnetworkchange(interfaces) {
|
|
this.emit("network-change", interfaces);
|
|
this.emit("network-update");
|
|
}
|
|
_repingAndSwap(newNode, oldNode) {
|
|
const self2 = this;
|
|
const lastSeen = oldNode.seen;
|
|
oldNode.pinged = this._tick;
|
|
this._repinging++;
|
|
this._request(
|
|
{ id: null, host: oldNode.host, port: oldNode.port },
|
|
false,
|
|
true,
|
|
PING,
|
|
null,
|
|
null,
|
|
null,
|
|
onsuccess,
|
|
onswap
|
|
);
|
|
function onsuccess(m) {
|
|
if (oldNode.seen <= lastSeen) return onswap();
|
|
self2._repinging--;
|
|
}
|
|
function onswap(e) {
|
|
self2._repinging--;
|
|
self2._removeNode(oldNode);
|
|
self2._addNode(newNode);
|
|
}
|
|
}
|
|
_onrequest(req, external) {
|
|
if (req.from.id !== null) {
|
|
this._addNodeFromNetwork(!external, req.from, req.to);
|
|
}
|
|
if (req.internal) {
|
|
switch (req.command) {
|
|
// standard keep alive call
|
|
case PING: {
|
|
req.sendReply(0, null, false, false);
|
|
return;
|
|
}
|
|
case DELAYED_PING: {
|
|
this._ondelayedping(req);
|
|
return;
|
|
}
|
|
// check if the other side can receive a message to their other socket
|
|
case PING_NAT: {
|
|
if (req.value === null || req.value.byteLength < 2) return;
|
|
const port = c.uint16.decode({ start: 0, end: 2, buffer: req.value });
|
|
if (port === 0) return;
|
|
req.from.port = port;
|
|
req.sendReply(0, null, false, false);
|
|
return;
|
|
}
|
|
// empty dht reply back
|
|
case FIND_NODE: {
|
|
if (!req.target) return;
|
|
req.sendReply(0, null, false, true);
|
|
return;
|
|
}
|
|
// "this is node you sent me is down" - let's try to ping it
|
|
case DOWN_HINT: {
|
|
if (req.value === null || req.value.byteLength < 6) return;
|
|
if (this._checks < 10) {
|
|
sodium.crypto_generichash(TMP, req.value.subarray(0, 6));
|
|
const node = this.table.get(TMP);
|
|
if (node && (node.pinged < this._tick || node.downHints === 0)) {
|
|
node.downHints++;
|
|
this._check(node);
|
|
}
|
|
}
|
|
req.sendReply(0, null, false, false);
|
|
return;
|
|
}
|
|
}
|
|
req.sendReply(UNKNOWN_COMMAND, null, false, req.target !== null);
|
|
return;
|
|
}
|
|
if (this.onrequest(req) === false) {
|
|
req.sendReply(UNKNOWN_COMMAND, null, false, req.target !== null);
|
|
}
|
|
}
|
|
onrequest(req) {
|
|
return this.emit("request", req);
|
|
}
|
|
_ondelayedping(req) {
|
|
if (req.value === null || req.value.byteLength < 4) return;
|
|
const delayMs = c.uint32.decode({ start: 0, end: 4, buffer: req.value });
|
|
if (delayMs > this.maxPingDelay) return;
|
|
const timer = setTimeout(() => {
|
|
if (this.destroyed) return;
|
|
this._pendingTimers.delete(timer);
|
|
req.sendReply(0, null, false, false);
|
|
}, delayMs);
|
|
this._pendingTimers.add(timer);
|
|
}
|
|
_onresponse(res, external) {
|
|
this._addNodeFromNetwork(!external, res.from, res.to);
|
|
}
|
|
_ontimeout(req) {
|
|
if (!req.to.id) return;
|
|
const node = this.table.get(req.to.id);
|
|
if (node) this._removeNode(node);
|
|
}
|
|
_pingSome() {
|
|
let cnt = this.io.inflight.length > 2 ? 3 : 5;
|
|
let oldest = this.nodes.oldest;
|
|
if (!oldest) {
|
|
this.refresh();
|
|
return;
|
|
}
|
|
if (this._tick - oldest.pinged < RECENT_NODE) {
|
|
cnt = 2;
|
|
}
|
|
while (cnt--) {
|
|
if (!oldest || this._tick === oldest.pinged) continue;
|
|
this._check(oldest);
|
|
oldest = oldest.next;
|
|
}
|
|
}
|
|
_check(node) {
|
|
node.pinged = this._tick;
|
|
const lastSeen = node.seen;
|
|
const onresponse = () => {
|
|
this._checks--;
|
|
this._removeStaleNode(node, lastSeen);
|
|
};
|
|
const onerror = () => {
|
|
this._checks--;
|
|
this._removeNode(node);
|
|
};
|
|
this._checks++;
|
|
this._request(
|
|
{ id: null, host: node.host, port: node.port },
|
|
false,
|
|
true,
|
|
PING,
|
|
null,
|
|
null,
|
|
null,
|
|
onresponse,
|
|
onerror
|
|
);
|
|
}
|
|
_ontick() {
|
|
const time = Date.now();
|
|
if (time - this._lastTick > SLEEPING_INTERVAL && this.suspended === false) {
|
|
this._onwakeup();
|
|
} else {
|
|
this._tick++;
|
|
}
|
|
this._lastTick = time;
|
|
if (!this.bootstrapped || this.suspended) return;
|
|
if (this.adaptive && this.ephemeral && --this._stableTicks <= 0) {
|
|
if (this._lastHost === this._nat.host) {
|
|
this._stableTicks = MORE_STABLE_TICKS;
|
|
} else {
|
|
this._updateNetworkState();
|
|
}
|
|
}
|
|
if ((this._tick & 7) === 0) {
|
|
this._pingSome();
|
|
}
|
|
if ((this._tick & 63) === 0 && this.nodes.length < this.table.k || --this._refreshTicks <= 0) {
|
|
this.refresh();
|
|
}
|
|
this._downHintsSentPerTick = 0;
|
|
this.health.update();
|
|
}
|
|
async _updateNetworkState(onlyFirewall = false) {
|
|
if (!this.ephemeral) return false;
|
|
if (onlyFirewall && !this.firewalled) return false;
|
|
const { host, port } = this._nat;
|
|
if (!onlyFirewall) {
|
|
this._stableTicks = MORE_STABLE_TICKS;
|
|
this._lastHost = host;
|
|
}
|
|
if (host === null || port === 0) {
|
|
return false;
|
|
}
|
|
const natSampler = this.firewalled ? new NatSampler() : this._nat;
|
|
const firewalled = this.firewalled && await this._checkIfFirewalled(natSampler);
|
|
if (firewalled) return false;
|
|
this.firewalled = this.io.firewalled = false;
|
|
if (!this.ephemeral || host !== this._nat.host || port !== this._nat.port) return false;
|
|
if (natSampler.host !== host || natSampler.port === 0) return false;
|
|
const id = peer.id(natSampler.host, natSampler.port);
|
|
if (!onlyFirewall) {
|
|
this.ephemeral = this.io.ephemeral = false;
|
|
}
|
|
if (natSampler !== this._nat) {
|
|
const prevHost = this._nat.host;
|
|
const prevPort = this._nat.port;
|
|
this._nonePersistentSamples = [];
|
|
this._nat = natSampler;
|
|
if (prevHost !== this._nat.host || prevPort !== this._nat.port) {
|
|
this.emit("nat-update", this._nat.host, this._nat.port);
|
|
}
|
|
}
|
|
if (!b4a.equals(this.table.id, id)) {
|
|
const nodes = this.table.toArray();
|
|
this.table = this.io.table = new Table(id);
|
|
for (const node of nodes) {
|
|
if (b4a.equals(node.id, id)) continue;
|
|
if (!this.table.add(node)) this.nodes.remove(node);
|
|
}
|
|
this.table.on("row", this._onrow);
|
|
if (this.bootstrapped) this.refresh();
|
|
}
|
|
if (!this.ephemeral) {
|
|
this.emit("persistent");
|
|
}
|
|
return true;
|
|
}
|
|
async *_resolveBootstrapNodes() {
|
|
for (let { host, port } of this.bootstrapNodes) {
|
|
let doLookup = false;
|
|
if (host.indexOf("@") === -1) {
|
|
doLookup = true;
|
|
} else {
|
|
const [suggestedIP, fallbackHost] = host.split("@");
|
|
try {
|
|
await this.ping({ host: suggestedIP, port });
|
|
host = suggestedIP;
|
|
} catch {
|
|
host = fallbackHost;
|
|
doLookup = true;
|
|
}
|
|
}
|
|
if (doLookup) {
|
|
try {
|
|
host = UDX.isIPv4(host) ? host : (await this.udx.lookup(host, { family: 4 })).host;
|
|
} catch {
|
|
continue;
|
|
}
|
|
}
|
|
yield {
|
|
id: peer.id(host, port),
|
|
host,
|
|
port
|
|
};
|
|
}
|
|
}
|
|
async _addBootstrapNodes(nodes) {
|
|
for await (const node of this._resolveBootstrapNodes()) {
|
|
nodes.push(node);
|
|
}
|
|
}
|
|
async _checkIfFirewalled(natSampler = new NatSampler()) {
|
|
const nodes = [];
|
|
for (let node = this.nodes.latest; node && nodes.length < 5; node = node.prev) {
|
|
nodes.push(node);
|
|
}
|
|
if (nodes.length < 5) await this._addBootstrapNodes(nodes);
|
|
if (nodes.length === 0) return true;
|
|
const hosts = /* @__PURE__ */ new Set();
|
|
const value = b4a.allocUnsafe(2);
|
|
c.uint16.encode({ start: 0, end: 2, buffer: value }, this.io.serverSocket.address().port);
|
|
this.io.serverSocket.on("message", onmessage);
|
|
const pongs = await requestAll(this, true, PING_NAT, value, nodes);
|
|
let count = 0;
|
|
for (const res of pongs) {
|
|
if (hosts.has(res.from.host)) {
|
|
count++;
|
|
natSampler.add(res.to.host, res.to.port);
|
|
}
|
|
}
|
|
this.io.serverSocket.removeListener("message", onmessage);
|
|
if (count < (nodes.length >= 5 ? 3 : 1)) return true;
|
|
if (natSampler.host === null || this._nat.host !== natSampler.host) return true;
|
|
if (natSampler.port === 0 || natSampler.port !== this.io.serverSocket.address().port) {
|
|
return true;
|
|
}
|
|
return false;
|
|
function onmessage(_, { host }) {
|
|
hosts.add(host);
|
|
}
|
|
}
|
|
_backgroundQuery(target) {
|
|
this._refreshTicks = REFRESH_TICKS;
|
|
const backgroundCon = Math.min(this.concurrency, Math.max(2, this.concurrency / 8 | 0));
|
|
const q = new Query(this, target, true, FIND_NODE, null, {
|
|
concurrency: backgroundCon
|
|
});
|
|
q.on("data", () => {
|
|
q.concurrency = this.io.inflight.length < 3 ? this.concurrency : backgroundCon;
|
|
});
|
|
return q;
|
|
}
|
|
// called by health
|
|
_online() {
|
|
if (this.online && !this.degraded) return;
|
|
this.online = true;
|
|
this.degraded = false;
|
|
this.emit("network-update");
|
|
}
|
|
// called by health
|
|
_degraded() {
|
|
if (this.degraded) return;
|
|
this.online = true;
|
|
this.degraded = true;
|
|
this.emit("network-update");
|
|
}
|
|
// called by health
|
|
_offline() {
|
|
if (!this.online) return;
|
|
this.online = false;
|
|
this.degraded = false;
|
|
this.emit("network-update");
|
|
}
|
|
};
|
|
DHT.OK = 0;
|
|
DHT.ERROR_UNKNOWN_COMMAND = UNKNOWN_COMMAND;
|
|
DHT.ERROR_INVALID_TOKEN = INVALID_TOKEN;
|
|
module.exports = DHT;
|
|
function localIP(udx, family = 4) {
|
|
let host = null;
|
|
for (const n of udx.networkInterfaces()) {
|
|
if (n.family !== family || n.internal) continue;
|
|
if (n.name === "en0") return n.host;
|
|
if (host === null) host = n.host;
|
|
}
|
|
return host || (family === 4 ? "127.0.0.1" : "::1");
|
|
}
|
|
function parseNode(s) {
|
|
if (typeof s === "object") return s;
|
|
if (typeof s === "number") return { host: "127.0.0.1", port: s };
|
|
const [host, port] = s.split(":");
|
|
if (!port) throw new Error("Bootstrap node format is host:port");
|
|
return {
|
|
host,
|
|
port: Number(port)
|
|
};
|
|
}
|
|
function randomBytes(n) {
|
|
const b = b4a.alloc(n);
|
|
sodium.randombytes_buf(b);
|
|
return b;
|
|
}
|
|
function randomOffset(n) {
|
|
return n - (Math.random() * 0.5 * n | 0);
|
|
}
|
|
function requestAll(dht, internal, command, value, nodes) {
|
|
let missing = nodes.length;
|
|
const replies = [];
|
|
return new Promise((resolve) => {
|
|
for (const node of nodes) {
|
|
const req = dht._request(
|
|
node,
|
|
false,
|
|
internal,
|
|
command,
|
|
null,
|
|
value,
|
|
null,
|
|
onsuccess,
|
|
onerror
|
|
);
|
|
if (!req) return resolve(replies);
|
|
}
|
|
function onsuccess(res) {
|
|
replies.push(res);
|
|
if (--missing === 0) resolve(replies);
|
|
}
|
|
function onerror() {
|
|
if (--missing === 0) resolve(replies);
|
|
}
|
|
});
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/messages.js
|
|
var require_messages3 = __commonJS({
|
|
"../../node_modules/hyperdht/lib/messages.js"(exports) {
|
|
var c = require_compact_encoding();
|
|
var ipv4 = {
|
|
...c.ipv4Address,
|
|
decode(state) {
|
|
const ip = c.ipv4Address.decode(state);
|
|
return {
|
|
host: ip.host,
|
|
port: ip.port
|
|
};
|
|
}
|
|
};
|
|
var ipv4Array = c.array(ipv4);
|
|
var ipv6 = {
|
|
...c.ipv6Address,
|
|
decode(state) {
|
|
const ip = c.ipv6Address.decode(state);
|
|
return {
|
|
host: ip.host,
|
|
port: ip.port
|
|
};
|
|
}
|
|
};
|
|
var ipv6Array = c.array(ipv6);
|
|
exports.handshake = {
|
|
preencode(state, m) {
|
|
state.end += 1 + 1 + (m.peerAddress ? 6 : 0) + (m.relayAddress ? 6 : 0);
|
|
c.buffer.preencode(state, m.noise);
|
|
},
|
|
encode(state, m) {
|
|
const flags = (m.peerAddress ? 1 : 0) | (m.relayAddress ? 2 : 0);
|
|
c.uint.encode(state, flags);
|
|
c.uint.encode(state, m.mode);
|
|
c.buffer.encode(state, m.noise);
|
|
if (m.peerAddress) ipv4.encode(state, m.peerAddress);
|
|
if (m.relayAddress) ipv4.encode(state, m.relayAddress);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
mode: c.uint.decode(state),
|
|
noise: c.buffer.decode(state),
|
|
peerAddress: flags & 1 ? ipv4.decode(state) : null,
|
|
relayAddress: flags & 2 ? ipv4.decode(state) : null
|
|
};
|
|
}
|
|
};
|
|
var relayInfo = {
|
|
preencode(state, m) {
|
|
state.end += 12;
|
|
},
|
|
encode(state, m) {
|
|
ipv4.encode(state, m.relayAddress);
|
|
ipv4.encode(state, m.peerAddress);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
relayAddress: ipv4.decode(state),
|
|
peerAddress: ipv4.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var relayInfoArray = c.array(relayInfo);
|
|
var holepunchInfo = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.id);
|
|
relayInfoArray.preencode(state, m.relays);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.id);
|
|
relayInfoArray.encode(state, m.relays);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
id: c.uint.decode(state),
|
|
relays: relayInfoArray.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var udxInfo = {
|
|
preencode(state, m) {
|
|
state.end += 2;
|
|
c.uint.preencode(state, m.id);
|
|
c.uint.preencode(state, m.seq);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, 1);
|
|
c.uint.encode(state, m.reusableSocket ? 1 : 0);
|
|
c.uint.encode(state, m.id);
|
|
c.uint.encode(state, m.seq);
|
|
},
|
|
decode(state) {
|
|
const version = c.uint.decode(state);
|
|
const features = c.uint.decode(state);
|
|
return {
|
|
version,
|
|
reusableSocket: (features & 1) !== 0,
|
|
id: c.uint.decode(state),
|
|
seq: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var secretStreamInfo = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, 1);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, 1);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
version: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var relayThroughInfo = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, 1);
|
|
c.uint.preencode(state, 0);
|
|
c.fixed32.preencode(state, m.publicKey);
|
|
c.fixed32.preencode(state, m.token);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, 1);
|
|
c.uint.encode(state, 0);
|
|
c.fixed32.encode(state, m.publicKey);
|
|
c.fixed32.encode(state, m.token);
|
|
},
|
|
decode(state) {
|
|
const version = c.uint.decode(state);
|
|
c.uint.decode(state);
|
|
return {
|
|
version,
|
|
publicKey: c.fixed32.decode(state),
|
|
token: c.fixed32.decode(state)
|
|
};
|
|
}
|
|
};
|
|
exports.noisePayload = {
|
|
preencode(state, m) {
|
|
state.end += 4;
|
|
if (m.holepunch) holepunchInfo.preencode(state, m.holepunch);
|
|
if (m.addresses4 && m.addresses4.length) ipv4Array.preencode(state, m.addresses4);
|
|
if (m.addresses6 && m.addresses6.length) ipv6Array.preencode(state, m.addresses6);
|
|
if (m.udx) udxInfo.preencode(state, m.udx);
|
|
if (m.secretStream) secretStreamInfo.preencode(state, m.secretStream);
|
|
if (m.relayThrough) relayThroughInfo.preencode(state, m.relayThrough);
|
|
if (m.relayAddresses) ipv4Array.preencode(state, m.relayAddresses);
|
|
},
|
|
encode(state, m) {
|
|
let flags = 0;
|
|
if (m.holepunch) flags |= 1;
|
|
if (m.addresses4 && m.addresses4.length) flags |= 2;
|
|
if (m.addresses6 && m.addresses6.length) flags |= 4;
|
|
if (m.udx) flags |= 8;
|
|
if (m.secretStream) flags |= 16;
|
|
if (m.relayThrough) flags |= 32;
|
|
if (m.relayAddresses) flags |= 64;
|
|
c.uint.encode(state, 1);
|
|
c.uint.encode(state, flags);
|
|
c.uint.encode(state, m.error);
|
|
c.uint.encode(state, m.firewall);
|
|
if (m.holepunch) holepunchInfo.encode(state, m.holepunch);
|
|
if (m.addresses4 && m.addresses4.length) ipv4Array.encode(state, m.addresses4);
|
|
if (m.addresses6 && m.addresses6.length) ipv6Array.encode(state, m.addresses6);
|
|
if (m.udx) udxInfo.encode(state, m.udx);
|
|
if (m.secretStream) secretStreamInfo.encode(state, m.secretStream);
|
|
if (m.relayThrough) relayThroughInfo.encode(state, m.relayThrough);
|
|
if (m.relayAddresses) ipv4Array.encode(state, m.relayAddresses);
|
|
},
|
|
decode(state) {
|
|
const version = c.uint.decode(state);
|
|
if (version !== 1) {
|
|
return {
|
|
version,
|
|
error: 0,
|
|
firewall: 0,
|
|
holepunch: null,
|
|
addresses4: [],
|
|
addresses6: [],
|
|
udx: null,
|
|
secretStream: null,
|
|
relayThrough: null,
|
|
relayAddresses: null
|
|
};
|
|
}
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
version,
|
|
error: c.uint.decode(state),
|
|
firewall: c.uint.decode(state),
|
|
holepunch: (flags & 1) !== 0 ? holepunchInfo.decode(state) : null,
|
|
addresses4: (flags & 2) !== 0 ? ipv4Array.decode(state) : [],
|
|
addresses6: (flags & 4) !== 0 ? ipv6Array.decode(state) : [],
|
|
udx: (flags & 8) !== 0 ? udxInfo.decode(state) : null,
|
|
secretStream: (flags & 16) !== 0 ? secretStreamInfo.decode(state) : null,
|
|
relayThrough: (flags & 32) !== 0 ? relayThroughInfo.decode(state) : null,
|
|
relayAddresses: (flags & 64) !== 0 ? ipv4Array.decode(state) : null
|
|
};
|
|
}
|
|
};
|
|
exports.holepunch = {
|
|
preencode(state, m) {
|
|
state.end += 2;
|
|
c.uint.preencode(state, m.id);
|
|
c.buffer.preencode(state, m.payload);
|
|
if (m.peerAddress) ipv4.preencode(state, m.peerAddress);
|
|
},
|
|
encode(state, m) {
|
|
const flags = m.peerAddress ? 1 : 0;
|
|
c.uint.encode(state, flags);
|
|
c.uint.encode(state, m.mode);
|
|
c.uint.encode(state, m.id);
|
|
c.buffer.encode(state, m.payload);
|
|
if (m.peerAddress) ipv4.encode(state, m.peerAddress);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
mode: c.uint.decode(state),
|
|
id: c.uint.decode(state),
|
|
payload: c.buffer.decode(state),
|
|
peerAddress: flags & 1 ? ipv4.decode(state) : null
|
|
};
|
|
}
|
|
};
|
|
exports.holepunchPayload = {
|
|
preencode(state, m) {
|
|
state.end += 4;
|
|
if (m.addresses) ipv4Array.preencode(state, m.addresses);
|
|
if (m.remoteAddress) state.end += 6;
|
|
if (m.token) state.end += 32;
|
|
if (m.remoteToken) state.end += 32;
|
|
},
|
|
encode(state, m) {
|
|
const flags = (m.connected ? 1 : 0) | (m.punching ? 2 : 0) | (m.addresses ? 4 : 0) | (m.remoteAddress ? 8 : 0) | (m.token ? 16 : 0) | (m.remoteToken ? 32 : 0);
|
|
c.uint.encode(state, flags);
|
|
c.uint.encode(state, m.error);
|
|
c.uint.encode(state, m.firewall);
|
|
c.uint.encode(state, m.round);
|
|
if (m.addresses) ipv4Array.encode(state, m.addresses);
|
|
if (m.remoteAddress) ipv4.encode(state, m.remoteAddress);
|
|
if (m.token) c.fixed32.encode(state, m.token);
|
|
if (m.remoteToken) c.fixed32.encode(state, m.remoteToken);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
error: c.uint.decode(state),
|
|
firewall: c.uint.decode(state),
|
|
round: c.uint.decode(state),
|
|
connected: (flags & 1) !== 0,
|
|
punching: (flags & 2) !== 0,
|
|
addresses: (flags & 4) !== 0 ? ipv4Array.decode(state) : null,
|
|
remoteAddress: (flags & 8) !== 0 ? ipv4.decode(state) : null,
|
|
token: (flags & 16) !== 0 ? c.fixed32.decode(state) : null,
|
|
remoteToken: (flags & 32) !== 0 ? c.fixed32.decode(state) : null
|
|
};
|
|
}
|
|
};
|
|
var peer = exports.peer = {
|
|
preencode(state, m) {
|
|
state.end += 32;
|
|
ipv4Array.preencode(state, m.relayAddresses);
|
|
},
|
|
encode(state, m) {
|
|
c.fixed32.encode(state, m.publicKey);
|
|
ipv4Array.encode(state, m.relayAddresses);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
publicKey: c.fixed32.decode(state),
|
|
relayAddresses: ipv4Array.decode(state)
|
|
};
|
|
}
|
|
};
|
|
var peers = exports.peers = c.array(peer);
|
|
var rawPeers = c.array(c.raw);
|
|
exports.lookupRawReply = {
|
|
preencode(state, m) {
|
|
rawPeers.preencode(state, m.peers);
|
|
c.uint.preencode(state, m.bump);
|
|
},
|
|
encode(state, m) {
|
|
rawPeers.encode(state, m.peers);
|
|
c.uint.encode(state, m.bump);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
peers: peers.decode(state),
|
|
bump: state.start < state.end ? c.uint.decode(state) : 0
|
|
};
|
|
}
|
|
};
|
|
exports.announce = {
|
|
preencode(state, m) {
|
|
state.end++;
|
|
if (m.peer) peer.preencode(state, m.peer);
|
|
if (m.refresh) state.end += 32;
|
|
if (m.signature) state.end += 64;
|
|
if (m.bump) c.uint.preencode(state, m.bump);
|
|
},
|
|
encode(state, m) {
|
|
const flags = (m.peer ? 1 : 0) | (m.refresh ? 2 : 0) | (m.signature ? 4 : 0) | (m.bump ? 8 : 0);
|
|
c.uint.encode(state, flags);
|
|
if (m.peer) peer.encode(state, m.peer);
|
|
if (m.refresh) c.fixed32.encode(state, m.refresh);
|
|
if (m.signature) c.fixed64.encode(state, m.signature);
|
|
if (m.bump) c.uint.encode(state, m.bump);
|
|
},
|
|
decode(state) {
|
|
const flags = c.uint.decode(state);
|
|
return {
|
|
peer: (flags & 1) !== 0 ? peer.decode(state) : null,
|
|
refresh: (flags & 2) !== 0 ? c.fixed32.decode(state) : null,
|
|
signature: (flags & 4) !== 0 ? c.fixed64.decode(state) : null,
|
|
bump: (flags & 8) !== 0 ? c.uint.decode(state) : 0
|
|
};
|
|
}
|
|
};
|
|
exports.mutableSignable = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.seq);
|
|
c.buffer.preencode(state, m.value);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.seq);
|
|
c.buffer.encode(state, m.value);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
seq: c.uint.decode(state),
|
|
value: c.buffer.decode(state)
|
|
};
|
|
}
|
|
};
|
|
exports.mutablePutRequest = {
|
|
preencode(state, m) {
|
|
c.fixed32.preencode(state, m.publicKey);
|
|
c.uint.preencode(state, m.seq);
|
|
c.buffer.preencode(state, m.value);
|
|
c.fixed64.preencode(state, m.signature);
|
|
},
|
|
encode(state, m) {
|
|
c.fixed32.encode(state, m.publicKey);
|
|
c.uint.encode(state, m.seq);
|
|
c.buffer.encode(state, m.value);
|
|
c.fixed64.encode(state, m.signature);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
publicKey: c.fixed32.decode(state),
|
|
seq: c.uint.decode(state),
|
|
value: c.buffer.decode(state),
|
|
signature: c.fixed64.decode(state)
|
|
};
|
|
}
|
|
};
|
|
exports.mutableGetResponse = {
|
|
preencode(state, m) {
|
|
c.uint.preencode(state, m.seq);
|
|
c.buffer.preencode(state, m.value);
|
|
c.fixed64.preencode(state, m.signature);
|
|
},
|
|
encode(state, m) {
|
|
c.uint.encode(state, m.seq);
|
|
c.buffer.encode(state, m.value);
|
|
c.fixed64.encode(state, m.signature);
|
|
},
|
|
decode(state) {
|
|
return {
|
|
seq: c.uint.decode(state),
|
|
value: c.buffer.decode(state),
|
|
signature: c.fixed64.decode(state)
|
|
};
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/socket-pool.js
|
|
var require_socket_pool = __commonJS({
|
|
"../../node_modules/hyperdht/lib/socket-pool.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var LINGER_TIME = 3e3;
|
|
module.exports = class SocketPool {
|
|
constructor(dht, host) {
|
|
this._dht = dht;
|
|
this._sockets = /* @__PURE__ */ new Map();
|
|
this._lingering = /* @__PURE__ */ new Set();
|
|
this._host = host;
|
|
this.routes = new SocketRoutes(this);
|
|
}
|
|
_onmessage(ref, data, address) {
|
|
this._dht.onmessage(ref.socket, data, address);
|
|
}
|
|
_add(ref) {
|
|
this._sockets.set(ref.socket, ref);
|
|
}
|
|
_remove(ref) {
|
|
this._sockets.delete(ref.socket);
|
|
this._lingering.delete(ref);
|
|
}
|
|
lookup(socket) {
|
|
return this._sockets.get(socket) || null;
|
|
}
|
|
setReusable(socket, bool) {
|
|
const ref = this.lookup(socket);
|
|
if (ref) ref.reusable = bool;
|
|
}
|
|
acquire() {
|
|
return new SocketRef(this);
|
|
}
|
|
async destroy() {
|
|
const closing = [];
|
|
for (const ref of this._sockets.values()) {
|
|
ref._unlinger();
|
|
closing.push(ref.socket.close());
|
|
}
|
|
await Promise.allSettled(closing);
|
|
}
|
|
};
|
|
var SocketRoutes = class {
|
|
constructor(pool) {
|
|
this._pool = pool;
|
|
this._routes = /* @__PURE__ */ new Map();
|
|
}
|
|
add(publicKey, rawStream) {
|
|
if (rawStream.socket) this._onconnect(publicKey, rawStream);
|
|
else rawStream.on("connect", this._onconnect.bind(this, publicKey, rawStream));
|
|
}
|
|
get(publicKey) {
|
|
const id = b4a.toString(publicKey, "hex");
|
|
const route = this._routes.get(id);
|
|
if (!route) return null;
|
|
return route;
|
|
}
|
|
_onconnect(publicKey, rawStream) {
|
|
const id = b4a.toString(publicKey, "hex");
|
|
const socket = rawStream.socket;
|
|
let route = this._routes.get(id);
|
|
if (!route) {
|
|
const gc = () => {
|
|
if (this._routes.get(id) === route) this._routes.delete(id);
|
|
socket.removeListener("close", gc);
|
|
};
|
|
route = {
|
|
socket,
|
|
address: { host: rawStream.remoteHost, port: rawStream.remotePort },
|
|
gc
|
|
};
|
|
this._routes.set(id, route);
|
|
socket.on("close", gc);
|
|
}
|
|
this._pool.setReusable(socket, true);
|
|
rawStream.on("error", () => {
|
|
this._pool.setReusable(socket, false);
|
|
if (!route) route = this._routes.get(id);
|
|
if (route && route.socket === socket) route.gc();
|
|
});
|
|
}
|
|
};
|
|
var SocketRef = class {
|
|
constructor(pool) {
|
|
this._pool = pool;
|
|
this.onholepunchmessage = noop;
|
|
this.reusable = false;
|
|
this.socket = pool._dht.udx.createSocket();
|
|
this.socket.on("close", this._onclose.bind(this)).on("message", this._onmessage.bind(this)).on("idle", this._onidle.bind(this)).on("busy", this._onbusy.bind(this)).bind(0, this._pool._host);
|
|
this._refs = 1;
|
|
this._released = false;
|
|
this._closed = false;
|
|
this._timeout = null;
|
|
this._wasBusy = false;
|
|
this._pool._add(this);
|
|
}
|
|
_onclose() {
|
|
this._pool._remove(this);
|
|
}
|
|
_onmessage(data, address) {
|
|
if (data.byteLength > 1) {
|
|
this._pool._onmessage(this, data, address);
|
|
} else {
|
|
this.onholepunchmessage(data, address, this);
|
|
}
|
|
}
|
|
_onidle() {
|
|
this._closeMaybe();
|
|
}
|
|
_onbusy() {
|
|
this._wasBusy = true;
|
|
this._unlinger();
|
|
}
|
|
_reset() {
|
|
this.onholepunchmessage = noop;
|
|
}
|
|
_closeMaybe() {
|
|
if (this._refs === 0 && this.socket.idle && !this._timeout) this._close();
|
|
}
|
|
_lingeringClose() {
|
|
this._pool._lingering.delete(this);
|
|
this._timeout = null;
|
|
this._closeMaybe();
|
|
}
|
|
_close() {
|
|
this._unlinger();
|
|
if (this.reusable && this._wasBusy) {
|
|
this._wasBusy = false;
|
|
this._pool._lingering.add(this);
|
|
this._timeout = setTimeout(this._lingeringClose.bind(this), LINGER_TIME);
|
|
return;
|
|
}
|
|
this._closed = true;
|
|
this.socket.close();
|
|
}
|
|
_unlinger() {
|
|
if (this._timeout !== null) {
|
|
clearTimeout(this._timeout);
|
|
this._pool._lingering.delete(this);
|
|
this._timeout = null;
|
|
}
|
|
}
|
|
get free() {
|
|
return this._refs === 0;
|
|
}
|
|
active() {
|
|
this._refs++;
|
|
this._unlinger();
|
|
}
|
|
inactive() {
|
|
this._refs--;
|
|
this._closeMaybe();
|
|
}
|
|
address() {
|
|
return this.socket.address();
|
|
}
|
|
release() {
|
|
if (this._released) return;
|
|
this._released = true;
|
|
this._reset();
|
|
this._refs--;
|
|
this._closeMaybe();
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/record-cache/index.js
|
|
var require_record_cache = __commonJS({
|
|
"../../node_modules/record-cache/index.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var EMPTY = [];
|
|
module.exports = RecordCache;
|
|
function RecordSet() {
|
|
this.list = [];
|
|
this.map = /* @__PURE__ */ new Map();
|
|
}
|
|
RecordSet.prototype.add = function(record, value) {
|
|
var k = toString(record);
|
|
var r = this.map.get(k);
|
|
if (r) return false;
|
|
r = { index: this.list.length, record: value || record };
|
|
this.list.push(r);
|
|
this.map.set(k, r);
|
|
return true;
|
|
};
|
|
RecordSet.prototype.remove = function(record) {
|
|
var k = toString(record);
|
|
var r = this.map.get(k);
|
|
if (!r) return false;
|
|
swap(this.list, r.index, this.list.length - 1);
|
|
this.list.pop();
|
|
this.map.delete(k);
|
|
return true;
|
|
};
|
|
function RecordStore() {
|
|
this.records = /* @__PURE__ */ new Map();
|
|
this.size = 0;
|
|
}
|
|
RecordStore.prototype.add = function(name, record, value) {
|
|
var r = this.records.get(name);
|
|
if (!r) {
|
|
r = new RecordSet();
|
|
this.records.set(name, r);
|
|
}
|
|
if (r.add(record, value)) {
|
|
this.size++;
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
RecordStore.prototype.remove = function(name, record, value) {
|
|
var r = this.records.get(name);
|
|
if (!r) return false;
|
|
if (r.remove(record, value)) {
|
|
this.size--;
|
|
if (!r.map.size) this.records.delete(name);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
RecordStore.prototype.get = function(name) {
|
|
var r = this.records.get(name);
|
|
return r ? r.list : EMPTY;
|
|
};
|
|
function RecordCache(opts) {
|
|
if (!(this instanceof RecordCache)) return new RecordCache(opts);
|
|
if (!opts) opts = {};
|
|
this.maxSize = opts.maxSize || Infinity;
|
|
this.maxAge = opts.maxAge || 0;
|
|
this._onstale = opts.onStale || opts.onstale || null;
|
|
this._fresh = new RecordStore();
|
|
this._stale = new RecordStore();
|
|
this._interval = null;
|
|
this._gced = false;
|
|
if (this.maxAge && this.maxAge < Infinity) {
|
|
var tick = Math.ceil(2 / 3 * this.maxAge);
|
|
this._interval = setInterval(this._gcAuto.bind(this), tick);
|
|
if (this._interval.unref) this._interval.unref();
|
|
}
|
|
}
|
|
Object.defineProperty(RecordCache.prototype, "size", {
|
|
get: function() {
|
|
return this._fresh.size + this._stale.size;
|
|
}
|
|
});
|
|
RecordCache.prototype.add = function(name, record, value) {
|
|
this._stale.remove(name, record, value);
|
|
if (this._fresh.add(name, record, value) && this._fresh.size > this.maxSize) {
|
|
this._gc();
|
|
}
|
|
};
|
|
RecordCache.prototype.remove = function(name, record, value) {
|
|
this._fresh.remove(name, record, value);
|
|
this._stale.remove(name, record, value);
|
|
};
|
|
RecordCache.prototype.get = function(name, n) {
|
|
var a = this._fresh.get(name);
|
|
var b = this._stale.get(name);
|
|
var aLen = a.length;
|
|
var bLen = b.length;
|
|
var len = aLen + bLen;
|
|
if (n > len || !n) n = len;
|
|
var result = new Array(n);
|
|
for (var i = 0; i < n; i++) {
|
|
var j = Math.floor(Math.random() * (aLen + bLen));
|
|
if (j < aLen) {
|
|
result[i] = a[j].record;
|
|
swap(a, j, --aLen);
|
|
} else {
|
|
j -= aLen;
|
|
result[i] = b[j].record;
|
|
swap(b, j, --bLen);
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
RecordCache.prototype._gcAuto = function() {
|
|
if (!this._gced) this._gc();
|
|
this._gced = false;
|
|
};
|
|
RecordCache.prototype._gc = function() {
|
|
if (this._onstale && this._stale.size > 0) this._onstale(this._stale);
|
|
this._stale = this._fresh;
|
|
this._fresh = new RecordStore();
|
|
this._gced = true;
|
|
};
|
|
RecordCache.prototype.clear = function() {
|
|
this._gc();
|
|
this._gc();
|
|
};
|
|
RecordCache.prototype.destroy = function() {
|
|
this.clear();
|
|
clearInterval(this._interval);
|
|
this._interval = null;
|
|
};
|
|
function toString(record) {
|
|
return b4a.isBuffer(record) ? b4a.toString(record, "hex") : record;
|
|
}
|
|
function swap(list, a, b) {
|
|
var tmp = list[a];
|
|
tmp.index = b;
|
|
list[b].index = a;
|
|
list[a] = list[b];
|
|
list[b] = tmp;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/encode.js
|
|
var require_encode2 = __commonJS({
|
|
"../../node_modules/hyperdht/lib/encode.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var cenc = require_compact_encoding();
|
|
function encodeUnslab(enc, m) {
|
|
const state = cenc.state();
|
|
enc.preencode(state, m);
|
|
state.buffer = b4a.allocUnsafeSlow(state.end);
|
|
enc.encode(state, m);
|
|
return state.buffer;
|
|
}
|
|
module.exports = {
|
|
encodeUnslab
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/constants.js
|
|
var require_constants2 = __commonJS({
|
|
"../../node_modules/hyperdht/lib/constants.js"(exports) {
|
|
var crypto = require_hypercore_crypto();
|
|
var COMMANDS = exports.COMMANDS = {
|
|
PEER_HANDSHAKE: 0,
|
|
PEER_HOLEPUNCH: 1,
|
|
FIND_PEER: 2,
|
|
LOOKUP: 3,
|
|
ANNOUNCE: 4,
|
|
UNANNOUNCE: 5,
|
|
MUTABLE_PUT: 6,
|
|
MUTABLE_GET: 7,
|
|
IMMUTABLE_PUT: 8,
|
|
IMMUTABLE_GET: 9
|
|
};
|
|
exports.BOOTSTRAP_NODES = global.Pear?.config.dht?.bootstrap || [
|
|
"[email protected]:49737",
|
|
"[email protected]:49737",
|
|
"[email protected]:49737"
|
|
];
|
|
exports.KNOWN_NODES = global.Pear?.config.dht?.nodes || [];
|
|
exports.FIREWALL = {
|
|
UNKNOWN: 0,
|
|
OPEN: 1,
|
|
CONSISTENT: 2,
|
|
RANDOM: 3
|
|
};
|
|
exports.ERROR = {
|
|
// noise / connection related
|
|
NONE: 0,
|
|
ABORTED: 1,
|
|
VERSION_MISMATCH: 2,
|
|
TRY_LATER: 3,
|
|
// dht related
|
|
SEQ_REUSED: 16,
|
|
SEQ_TOO_LOW: 17
|
|
};
|
|
var [NS_ANNOUNCE, NS_UNANNOUNCE, NS_MUTABLE_PUT, NS_PEER_HANDSHAKE, NS_PEER_HOLEPUNCH] = crypto.namespace("hyperswarm/dht", [
|
|
COMMANDS.ANNOUNCE,
|
|
COMMANDS.UNANNOUNCE,
|
|
COMMANDS.MUTABLE_PUT,
|
|
COMMANDS.PEER_HANDSHAKE,
|
|
COMMANDS.PEER_HOLEPUNCH
|
|
]);
|
|
exports.NS = {
|
|
ANNOUNCE: NS_ANNOUNCE,
|
|
UNANNOUNCE: NS_UNANNOUNCE,
|
|
MUTABLE_PUT: NS_MUTABLE_PUT,
|
|
PEER_HANDSHAKE: NS_PEER_HANDSHAKE,
|
|
PEER_HOLEPUNCH: NS_PEER_HOLEPUNCH
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/persistent.js
|
|
var require_persistent = __commonJS({
|
|
"../../node_modules/hyperdht/lib/persistent.js"(exports, module) {
|
|
var c = require_compact_encoding();
|
|
var sodium = require_sodium_universal();
|
|
var RecordCache = require_record_cache();
|
|
var Cache = require_xache();
|
|
var b4a = require_b4a();
|
|
var unslab = require_unslab();
|
|
var { encodeUnslab } = require_encode2();
|
|
var m = require_messages3();
|
|
var { NS, ERROR } = require_constants2();
|
|
var EMPTY = b4a.alloc(0);
|
|
var TMP = b4a.allocUnsafe(32);
|
|
var MAX_BUMP_DRIFT = 6e4;
|
|
module.exports = class Persistent {
|
|
constructor(dht, opts) {
|
|
this.dht = dht;
|
|
this.records = new RecordCache(opts.records);
|
|
this.bumps = new Cache(opts.bumps);
|
|
this.refreshes = new Cache(opts.refreshes);
|
|
this.mutables = new Cache(opts.mutables);
|
|
this.immutables = new Cache(opts.immutables);
|
|
}
|
|
onlookup(req) {
|
|
if (!req.target) return;
|
|
const k = b4a.toString(req.target, "hex");
|
|
const records = this.records.get(k, 20);
|
|
const bump = this.bumps.get(k) || 0;
|
|
const fwd = this.dht._router.get(k);
|
|
if (fwd && records.length < 20) records.push(fwd.record);
|
|
req.reply(records.length ? c.encode(m.lookupRawReply, { peers: records, bump }) : null);
|
|
}
|
|
onfindpeer(req) {
|
|
if (!req.target) return;
|
|
const fwd = this.dht._router.get(req.target);
|
|
req.reply(fwd ? fwd.record : null);
|
|
}
|
|
unannounce(target, publicKey) {
|
|
const k = b4a.toString(target, "hex");
|
|
sodium.crypto_generichash(TMP, publicKey);
|
|
if (b4a.equals(TMP, target)) this.dht._router.delete(k);
|
|
this.records.remove(k, publicKey);
|
|
}
|
|
onunannounce(req) {
|
|
if (!req.target || !req.token) return;
|
|
const unann = decode(m.announce, req.value);
|
|
if (unann === null) return;
|
|
const { peer, signature } = unann;
|
|
if (!peer || !signature) return;
|
|
const signable = annSignable(req.target, req.token, this.dht.id, unann, NS.UNANNOUNCE);
|
|
if (!sodium.crypto_sign_verify_detached(signature, signable, peer.publicKey)) {
|
|
return;
|
|
}
|
|
this.unannounce(req.target, peer.publicKey);
|
|
req.reply(null, { token: false, closerNodes: false });
|
|
}
|
|
_onrefresh(token, req) {
|
|
sodium.crypto_generichash(TMP, token);
|
|
const activeRefresh = b4a.toString(TMP, "hex");
|
|
const r = this.refreshes.get(activeRefresh);
|
|
if (!r) return;
|
|
const { announceSelf, k, record } = r;
|
|
const publicKey = record.subarray(0, 32);
|
|
if (announceSelf) {
|
|
this.dht._router.set(k, {
|
|
relay: req.from,
|
|
record,
|
|
onconnect: null,
|
|
onholepunch: null
|
|
});
|
|
this.records.remove(k, publicKey);
|
|
} else {
|
|
this.records.add(k, publicKey, record);
|
|
}
|
|
this.refreshes.delete(activeRefresh);
|
|
this.refreshes.set(b4a.toString(token, "hex"), r);
|
|
req.reply(null, { token: false, closerNodes: false });
|
|
}
|
|
onannounce(req) {
|
|
if (!req.target || !req.token || !this.dht.id) return;
|
|
const ann = decode(m.announce, req.value);
|
|
if (ann === null) return;
|
|
const { peer, refresh, signature, bump } = ann;
|
|
if (!peer) {
|
|
if (!refresh) return;
|
|
this._onrefresh(refresh, req);
|
|
return;
|
|
}
|
|
const signable = annSignable(req.target, req.token, this.dht.id, ann, NS.ANNOUNCE);
|
|
if (!signature || !sodium.crypto_sign_verify_detached(signature, signable, peer.publicKey)) {
|
|
return;
|
|
}
|
|
if (peer.relayAddresses.length > 3) {
|
|
peer.relayAddresses = peer.relayAddresses.slice(0, 3);
|
|
}
|
|
sodium.crypto_generichash(TMP, peer.publicKey);
|
|
const k = b4a.toString(req.target, "hex");
|
|
const announceSelf = b4a.equals(TMP, req.target);
|
|
const record = encodeUnslab(m.peer, peer);
|
|
if (announceSelf) {
|
|
this.dht._router.set(k, {
|
|
relay: req.from,
|
|
record,
|
|
onconnect: null,
|
|
onholepunch: null
|
|
});
|
|
this.records.remove(k, peer.publicKey);
|
|
} else {
|
|
const currentBump = this.bumps.get(k) || 0;
|
|
if (bump > currentBump && bump <= Date.now() + MAX_BUMP_DRIFT) this.bumps.set(k, bump);
|
|
this.records.add(k, peer.publicKey, record);
|
|
}
|
|
if (refresh) {
|
|
this.refreshes.set(b4a.toString(refresh, "hex"), { k, record, announceSelf });
|
|
}
|
|
req.reply(null, { token: false, closerNodes: false });
|
|
}
|
|
onmutableget(req) {
|
|
if (!req.target || !req.value) return;
|
|
let seq = 0;
|
|
try {
|
|
seq = c.decode(c.uint, req.value);
|
|
} catch {
|
|
return;
|
|
}
|
|
const k = b4a.toString(req.target, "hex");
|
|
const value = this.mutables.get(k);
|
|
if (!value) {
|
|
req.reply(null);
|
|
return;
|
|
}
|
|
const localSeq = c.decode(c.uint, value);
|
|
req.reply(localSeq < seq ? null : value);
|
|
}
|
|
onmutableput(req) {
|
|
if (!req.target || !req.token || !req.value) return;
|
|
const p = decode(m.mutablePutRequest, req.value);
|
|
if (!p) return;
|
|
const { publicKey, seq, value, signature } = p;
|
|
const hash = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(hash, publicKey);
|
|
if (!b4a.equals(hash, req.target)) return;
|
|
if (!value || !verifyMutable(signature, seq, value, publicKey)) return;
|
|
const k = b4a.toString(hash, "hex");
|
|
const local = this.mutables.get(k);
|
|
if (local) {
|
|
const existing = c.decode(m.mutableGetResponse, local);
|
|
if (existing.value && existing.seq === seq && b4a.compare(value, existing.value) !== 0) {
|
|
req.error(ERROR.SEQ_REUSED);
|
|
return;
|
|
}
|
|
if (seq < existing.seq) {
|
|
req.error(ERROR.SEQ_TOO_LOW);
|
|
return;
|
|
}
|
|
}
|
|
this.mutables.set(k, encodeUnslab(m.mutableGetResponse, { seq, value, signature }));
|
|
req.reply(null);
|
|
}
|
|
onimmutableget(req) {
|
|
if (!req.target) return;
|
|
const k = b4a.toString(req.target, "hex");
|
|
const value = this.immutables.get(k);
|
|
req.reply(value || null);
|
|
}
|
|
onimmutableput(req) {
|
|
if (!req.target || !req.token || !req.value) return;
|
|
const hash = b4a.alloc(32);
|
|
sodium.crypto_generichash(hash, req.value);
|
|
if (!b4a.equals(hash, req.target)) return;
|
|
const k = b4a.toString(hash, "hex");
|
|
this.immutables.set(k, unslab(req.value));
|
|
req.reply(null);
|
|
}
|
|
destroy() {
|
|
this.records.destroy();
|
|
this.refreshes.destroy();
|
|
this.mutables.destroy();
|
|
this.immutables.destroy();
|
|
}
|
|
static signMutable(seq, value, keyPair) {
|
|
const signable = b4a.allocUnsafe(32 + 32);
|
|
const hash = signable.subarray(32);
|
|
signable.set(NS.MUTABLE_PUT, 0);
|
|
sodium.crypto_generichash(hash, c.encode(m.mutableSignable, { seq, value }));
|
|
return sign(signable, keyPair);
|
|
}
|
|
static verifyMutable(signature, seq, value, publicKey) {
|
|
return verifyMutable(signature, seq, value, publicKey);
|
|
}
|
|
static signAnnounce(target, token, id, ann, keyPair) {
|
|
return sign(annSignable(target, token, id, ann, NS.ANNOUNCE), keyPair);
|
|
}
|
|
static signUnannounce(target, token, id, ann, keyPair) {
|
|
return sign(annSignable(target, token, id, ann, NS.UNANNOUNCE), keyPair);
|
|
}
|
|
};
|
|
function verifyMutable(signature, seq, value, publicKey) {
|
|
const signable = b4a.allocUnsafe(32 + 32);
|
|
const hash = signable.subarray(32);
|
|
signable.set(NS.MUTABLE_PUT, 0);
|
|
sodium.crypto_generichash(hash, c.encode(m.mutableSignable, { seq, value }));
|
|
return sodium.crypto_sign_verify_detached(signature, signable, publicKey);
|
|
}
|
|
function annSignable(target, token, id, ann, ns) {
|
|
const signable = b4a.allocUnsafe(32 + 32);
|
|
const hash = signable.subarray(32);
|
|
signable.set(ns, 0);
|
|
sodium.crypto_generichash_batch(hash, [
|
|
target,
|
|
id,
|
|
token,
|
|
c.encode(m.peer, ann.peer),
|
|
// note that this is the partial encoding of the announce message so we could just use that for perf
|
|
ann.refresh || EMPTY
|
|
]);
|
|
return signable;
|
|
}
|
|
function sign(signable, keyPair) {
|
|
if (keyPair.sign) {
|
|
return keyPair.sign(signable);
|
|
}
|
|
const secretKey = keyPair.secretKey ? keyPair.secretKey : keyPair;
|
|
const signature = b4a.allocUnsafe(64);
|
|
sodium.crypto_sign_detached(signature, signable, secretKey);
|
|
return signature;
|
|
}
|
|
function decode(enc, val) {
|
|
try {
|
|
return val && c.decode(enc, val);
|
|
} catch (err) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/errors.js
|
|
var require_errors6 = __commonJS({
|
|
"../../node_modules/hyperdht/lib/errors.js"(exports, module) {
|
|
module.exports = class DHTError extends Error {
|
|
constructor(msg, code, fn = DHTError) {
|
|
super(`${code}: ${msg}`);
|
|
this.code = code;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, fn);
|
|
}
|
|
}
|
|
get name() {
|
|
return "DHTError";
|
|
}
|
|
static BAD_HANDSHAKE_REPLY(msg = "Bad handshake reply") {
|
|
return new DHTError(msg, "BAD_HANDSHAKE_REPLY", DHTError.BAD_HANDSHAKE_REPLY);
|
|
}
|
|
static BAD_HOLEPUNCH_REPLY(msg = "Bad holepunch reply") {
|
|
return new DHTError(msg, "BAD_HOLEPUNCH_REPLY", DHTError.BAD_HOLEPUNCH_REPLY);
|
|
}
|
|
static HOLEPUNCH_ABORTED(msg = "Holepunch aborted") {
|
|
return new DHTError(msg, "HOLEPUNCH_ABORTED", DHTError.HOLEPUNCH_ABORTED);
|
|
}
|
|
static HOLEPUNCH_INVALID(msg = "Invalid holepunch payload") {
|
|
return new DHTError(msg, "HOLEPUNCH_INVALID", DHTError.HOLEPUNCH_INVALID);
|
|
}
|
|
static HOLEPUNCH_PROBE_TIMEOUT(msg = "Holepunching probe did not finish in time") {
|
|
return new DHTError(msg, "HOLEPUNCH_PROBE_TIMEOUT", DHTError.HOLEPUNCH_PROBE_TIMEOUT);
|
|
}
|
|
static HOLEPUNCH_DOUBLE_RANDOMIZED_NATS(msg = "Both remote and local NATs are randomized") {
|
|
return new DHTError(
|
|
msg,
|
|
"HOLEPUNCH_DOUBLE_RANDOMIZED_NATS",
|
|
DHTError.HOLEPUNCH_DOUBLE_RANDOMIZED_NATS
|
|
);
|
|
}
|
|
static CANNOT_HOLEPUNCH(msg = "Cannot holepunch to remote") {
|
|
return new DHTError(msg, "CANNOT_HOLEPUNCH", DHTError.CANNOT_HOLEPUNCH);
|
|
}
|
|
static REMOTE_NOT_HOLEPUNCHING(msg = "Remote is not holepunching") {
|
|
return new DHTError(msg, "REMOTE_NOT_HOLEPUNCHING", DHTError.REMOTE_NOT_HOLEPUNCHING);
|
|
}
|
|
static REMOTE_NOT_HOLEPUNCHABLE(msg = "Remote is not holepunchable") {
|
|
return new DHTError(msg, "REMOTE_NOT_HOLEPUNCHABLE", DHTError.REMOTE_NOT_HOLEPUNCHABLE);
|
|
}
|
|
static REMOTE_ABORTED(msg = "Remote aborted") {
|
|
return new DHTError(msg, "REMOTE_ABORTED", DHTError.REMOTE_ABORTED);
|
|
}
|
|
static HANDSHAKE_UNFINISHED(msg = "Handshake did not finish") {
|
|
return new DHTError(msg, "HANDSHAKE_UNFINISHED", DHTError.HANDSHAKE_UNFINISHED);
|
|
}
|
|
static HANDSHAKE_INVALID(msg = "Received invalid handshake") {
|
|
return new DHTError(msg, "HANDSHAKE_INVALID", DHTError.HANDSHAKE_INVALID);
|
|
}
|
|
static ALREADY_LISTENING(msg = "Already listening") {
|
|
return new DHTError(msg, "ALREADY_LISTENING", DHTError.ALREADY_LISTENING);
|
|
}
|
|
static KEYPAIR_ALREADY_USED(msg = "Keypair already used") {
|
|
return new DHTError(msg, "KEYPAIR_ALREADY_USED", DHTError.KEYPAIR_ALREADY_USED);
|
|
}
|
|
static NODE_DESTROYED(msg = "Node destroyed") {
|
|
return new DHTError(msg, "NODE_DESTROYED", DHTError.NODE_DESTROYED);
|
|
}
|
|
static PEER_CONNECTION_FAILED(msg = "Could not connect to peer") {
|
|
return new DHTError(msg, "PEER_CONNECTION_FAILED", DHTError.PEER_CONNECTION_FAILED);
|
|
}
|
|
static PEER_NOT_FOUND(msg = "Peer not found") {
|
|
return new DHTError(msg, "PEER_NOT_FOUND", DHTError.PEER_NOT_FOUND);
|
|
}
|
|
static STREAM_NOT_CONNECTED(msg = "Stream is not connected") {
|
|
return new DHTError(msg, "STREAM_NOT_CONNECTED", DHTError.STREAM_DISCONNECTED);
|
|
}
|
|
static SERVER_INCOMPATIBLE(msg = "Server is using an incompatible version") {
|
|
return new DHTError(msg, "SERVER_INCOMPATIBLE", DHTError.SERVER_INCOMPATIBLE);
|
|
}
|
|
static SERVER_ERROR(msg = "Server returned an error") {
|
|
return new DHTError(msg, "SERVER_ERROR", DHTError.SERVER_ERROR);
|
|
}
|
|
static DUPLICATE_CONNECTION(msg = "Duplicate connection") {
|
|
return new DHTError(msg, "DUPLICATE_CONNECTION", DHTError.DUPLICATE_CONNECTION);
|
|
}
|
|
static RELAY_ABORTED(msg = "Relay aborted") {
|
|
return new DHTError(msg, "RELAY_ABORTED", DHTError.RELAY_ABORTED);
|
|
}
|
|
static SUSPENDED(msg = "Suspended") {
|
|
return new DHTError(msg, "SUSPENDED", DHTError.SUSPENDED);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/router.js
|
|
var require_router = __commonJS({
|
|
"../../node_modules/hyperdht/lib/router.js"(exports, module) {
|
|
var c = require_compact_encoding();
|
|
var Cache = require_xache();
|
|
var safetyCatch = require_safety_catch();
|
|
var b4a = require_b4a();
|
|
var { handshake, holepunch } = require_messages3();
|
|
var { COMMANDS } = require_constants2();
|
|
var { BAD_HANDSHAKE_REPLY, BAD_HOLEPUNCH_REPLY } = require_errors6();
|
|
var FROM_CLIENT = 0;
|
|
var FROM_SERVER = 1;
|
|
var FROM_RELAY = 2;
|
|
var FROM_SECOND_RELAY = 3;
|
|
var REPLY = 4;
|
|
module.exports = class Router {
|
|
constructor(dht, opts) {
|
|
this.dht = dht;
|
|
this.forwards = new Cache(opts.forwards);
|
|
}
|
|
set(target, state) {
|
|
if (state.onpeerhandshake) {
|
|
this.forwards.retain(toString(target), state);
|
|
} else {
|
|
this.forwards.set(toString(target), state);
|
|
}
|
|
}
|
|
get(target) {
|
|
return this.forwards.get(toString(target));
|
|
}
|
|
delete(target) {
|
|
this.forwards.delete(toString(target));
|
|
}
|
|
destroy() {
|
|
this.forwards.destroy();
|
|
}
|
|
async peerHandshake(target, { noise, peerAddress, relayAddress, socket, session }, to) {
|
|
const dht = this.dht;
|
|
const requestValue = c.encode(handshake, {
|
|
mode: FROM_CLIENT,
|
|
noise,
|
|
peerAddress,
|
|
relayAddress
|
|
});
|
|
const res = await dht.request(
|
|
{ command: COMMANDS.PEER_HANDSHAKE, target, value: requestValue },
|
|
to,
|
|
{ socket, session }
|
|
);
|
|
const hs = decode(handshake, res.value);
|
|
if (!hs || hs.mode !== REPLY || to.host !== res.from.host || to.port !== res.from.port || !hs.noise) {
|
|
throw BAD_HANDSHAKE_REPLY();
|
|
}
|
|
return {
|
|
noise: hs.noise,
|
|
relayed: !!hs.peerAddress,
|
|
serverAddress: hs.peerAddress || to,
|
|
clientAddress: res.to
|
|
};
|
|
}
|
|
async onpeerhandshake(req) {
|
|
const hs = req.value && decode(handshake, req.value);
|
|
if (!hs) return;
|
|
const { mode, noise, peerAddress, relayAddress } = hs;
|
|
const state = req.target && this.get(req.target);
|
|
const isServer = !!(state && state.onpeerhandshake);
|
|
const relay = state && state.relay;
|
|
if (isServer) {
|
|
let reply = null;
|
|
try {
|
|
reply = noise && await state.onpeerhandshake({ noise, peerAddress }, req);
|
|
} catch (e) {
|
|
safetyCatch(e);
|
|
return;
|
|
}
|
|
if (!reply || !reply.noise) return;
|
|
const opts = { socket: reply.socket, closerNodes: false, token: false };
|
|
switch (mode) {
|
|
case FROM_CLIENT: {
|
|
req.reply(
|
|
c.encode(handshake, { mode: REPLY, noise: reply.noise, peerAddress: null }),
|
|
opts
|
|
);
|
|
return;
|
|
}
|
|
case FROM_RELAY: {
|
|
req.relay(
|
|
c.encode(handshake, { mode: FROM_SERVER, noise: reply.noise, peerAddress }),
|
|
req.from,
|
|
opts
|
|
);
|
|
return;
|
|
}
|
|
case FROM_SECOND_RELAY: {
|
|
if (!relayAddress) return;
|
|
req.relay(
|
|
c.encode(handshake, { mode: FROM_SERVER, noise: reply.noise, peerAddress }),
|
|
relayAddress,
|
|
opts
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
switch (mode) {
|
|
case FROM_CLIENT: {
|
|
if (!noise) return;
|
|
if (!relay && !relayAddress) {
|
|
req.reply(null, { token: false, closerNodes: true });
|
|
return;
|
|
}
|
|
req.relay(
|
|
c.encode(handshake, {
|
|
mode: FROM_RELAY,
|
|
noise,
|
|
peerAddress: req.from,
|
|
relayAddress: null
|
|
}),
|
|
relayAddress || relay
|
|
);
|
|
return;
|
|
}
|
|
case FROM_RELAY: {
|
|
if (!relay || !noise) return;
|
|
req.relay(
|
|
c.encode(handshake, {
|
|
mode: FROM_SECOND_RELAY,
|
|
noise,
|
|
peerAddress,
|
|
relayAddress: req.from
|
|
}),
|
|
relay
|
|
);
|
|
return;
|
|
}
|
|
case FROM_SERVER: {
|
|
if (!peerAddress || !noise) return;
|
|
req.reply(
|
|
c.encode(handshake, { mode: REPLY, noise, peerAddress: req.from, relayAddress: null }),
|
|
{ to: peerAddress, closerNodes: false, token: false }
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
async peerHolepunch(target, { id, payload, peerAddress, socket, session }, to) {
|
|
const dht = this.dht;
|
|
const requestValue = c.encode(holepunch, {
|
|
mode: FROM_CLIENT,
|
|
id,
|
|
payload,
|
|
peerAddress
|
|
});
|
|
const res = await dht.request(
|
|
{ command: COMMANDS.PEER_HOLEPUNCH, target, value: requestValue },
|
|
to,
|
|
{ socket, session }
|
|
);
|
|
const hp = decode(holepunch, res.value);
|
|
if (!hp || hp.mode !== REPLY || to.host !== res.from.host || to.port !== res.from.port) {
|
|
throw BAD_HOLEPUNCH_REPLY();
|
|
}
|
|
return {
|
|
from: res.from,
|
|
to: res.to,
|
|
payload: hp.payload,
|
|
peerAddress: hp.peerAddress || to
|
|
};
|
|
}
|
|
async onpeerholepunch(req) {
|
|
const hp = req.value && decode(holepunch, req.value);
|
|
if (!hp) return;
|
|
const { mode, id, payload, peerAddress } = hp;
|
|
const state = req.target && this.get(req.target);
|
|
const isServer = !!(state && state.onpeerholepunch);
|
|
const relay = state && state.relay;
|
|
switch (mode) {
|
|
case FROM_CLIENT: {
|
|
if (!peerAddress && !relay) return;
|
|
req.relay(
|
|
c.encode(holepunch, { mode: FROM_RELAY, id, payload, peerAddress: req.from }),
|
|
peerAddress || relay
|
|
);
|
|
return;
|
|
}
|
|
case FROM_RELAY: {
|
|
if (!isServer || !peerAddress) return;
|
|
let reply = null;
|
|
try {
|
|
reply = await state.onpeerholepunch({ id, payload, peerAddress }, req);
|
|
} catch (e) {
|
|
safetyCatch(e);
|
|
return;
|
|
}
|
|
if (!reply) return;
|
|
const opts = { socket: reply.socket, closerNodes: false, token: false };
|
|
req.relay(
|
|
c.encode(holepunch, { mode: FROM_SERVER, id: 0, payload: reply.payload, peerAddress }),
|
|
req.from,
|
|
opts
|
|
);
|
|
return;
|
|
}
|
|
case FROM_SERVER: {
|
|
req.reply(c.encode(holepunch, { mode: REPLY, id, payload, peerAddress: req.from }), {
|
|
to: peerAddress,
|
|
closerNodes: false,
|
|
token: false
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
function decode(enc, val) {
|
|
try {
|
|
return c.decode(enc, val);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
function toString(t) {
|
|
return typeof t === "string" ? t : b4a.toString(t, "hex");
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/compact-encoding-bitfield/index.js
|
|
var require_compact_encoding_bitfield = __commonJS({
|
|
"../../node_modules/compact-encoding-bitfield/index.js"(exports, module) {
|
|
var c = require_compact_encoding();
|
|
module.exports = function bitfield(length) {
|
|
if (length > 64) throw new RangeError("Bitfield cannot be larger than 64 bits");
|
|
let byteLength;
|
|
if (length < 8) byteLength = 1;
|
|
else if (length <= 16) byteLength = 2;
|
|
else if (length <= 32) byteLength = 4;
|
|
else byteLength = 8;
|
|
return {
|
|
preencode(state) {
|
|
state.end++;
|
|
if (byteLength === 1) ;
|
|
else if (byteLength === 2) c.uint16.preencode(state);
|
|
else if (byteLength === 4) c.uint32.preencode(state);
|
|
else c.uint64.preencode(state);
|
|
},
|
|
encode(state, b) {
|
|
if (byteLength === 1) ;
|
|
else if (byteLength === 2) c.uint8.encode(state, 253);
|
|
else if (byteLength === 4) c.uint8.encode(state, 254);
|
|
else c.uint8.encode(state, 255);
|
|
if (typeof b === "number") {
|
|
if (byteLength === 1) c.uint8.encode(state, b);
|
|
else if (byteLength === 2) c.uint16.encode(state, b);
|
|
else if (byteLength === 4) c.uint32.encode(state, b);
|
|
else c.uint64.encode(state, b);
|
|
} else {
|
|
state.buffer.set(b, state.start);
|
|
if (b.byteLength < byteLength) {
|
|
state.buffer.fill(
|
|
0,
|
|
state.start + b.byteLength,
|
|
state.start + byteLength
|
|
);
|
|
}
|
|
state.start += byteLength;
|
|
}
|
|
},
|
|
decode(state) {
|
|
const byte = state.buffer[state.start];
|
|
let byteLength2;
|
|
if (byte <= 252) byteLength2 = 1;
|
|
else if (byte === 253) byteLength2 = 2;
|
|
else if (byte === 254) byteLength2 = 4;
|
|
else byteLength2 = 8;
|
|
if (byteLength2 > 1) state.start++;
|
|
if (state.end - state.start < byteLength2) throw new Error("Out of bounds");
|
|
const b = state.buffer.subarray(state.start, state.start += byteLength2);
|
|
return length <= 8 ? b.subarray(0, 1) : b;
|
|
}
|
|
};
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bits-to-bytes/index.js
|
|
var require_bits_to_bytes = __commonJS({
|
|
"../../node_modules/bits-to-bytes/index.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
function byteLength(size) {
|
|
return Math.ceil(size / 8);
|
|
}
|
|
function get(buffer, bit) {
|
|
const n = buffer.BYTES_PER_ELEMENT * 8;
|
|
const offset = bit & n - 1;
|
|
const i = (bit - offset) / n;
|
|
return (buffer[i] & 1 << offset) !== 0;
|
|
}
|
|
function set(buffer, bit, value = true) {
|
|
const n = buffer.BYTES_PER_ELEMENT * 8;
|
|
const offset = bit & n - 1;
|
|
const i = (bit - offset) / n;
|
|
const mask = 1 << offset;
|
|
if (value) {
|
|
if ((buffer[i] & mask) !== 0) return false;
|
|
} else {
|
|
if ((buffer[i] & mask) === 0) return false;
|
|
}
|
|
buffer[i] ^= mask;
|
|
return true;
|
|
}
|
|
function setRange(buffer, start, end, value = true) {
|
|
const n = buffer.BYTES_PER_ELEMENT * 8;
|
|
let remaining = end - start;
|
|
let offset = start & n - 1;
|
|
let i = (start - offset) / n;
|
|
let changed = false;
|
|
while (remaining > 0) {
|
|
const mask = 2 ** Math.min(remaining, n - offset) - 1 << offset;
|
|
if (value) {
|
|
if ((buffer[i] & mask) !== mask) {
|
|
buffer[i] |= mask;
|
|
changed = true;
|
|
}
|
|
} else {
|
|
if ((buffer[i] & mask) !== 0) {
|
|
buffer[i] &= ~mask;
|
|
changed = true;
|
|
}
|
|
}
|
|
remaining -= n - offset;
|
|
offset = 0;
|
|
i++;
|
|
}
|
|
return changed;
|
|
}
|
|
function fill(buffer, value, start = 0, end = buffer.byteLength * 8) {
|
|
const n = buffer.BYTES_PER_ELEMENT * 8;
|
|
let i, j;
|
|
{
|
|
const offset = start & n - 1;
|
|
i = (start - offset) / n;
|
|
if (offset !== 0) {
|
|
const mask = 2 ** Math.min(n - offset, end - start) - 1 << offset;
|
|
if (value) buffer[i] |= mask;
|
|
else buffer[i] &= ~mask;
|
|
i++;
|
|
}
|
|
}
|
|
{
|
|
const offset = end & n - 1;
|
|
j = (end - offset) / n;
|
|
if (offset !== 0 && j >= i) {
|
|
const mask = 2 ** offset - 1;
|
|
if (value) buffer[j] |= mask;
|
|
else buffer[j] &= ~mask;
|
|
}
|
|
}
|
|
return buffer.fill(value ? 2 ** n - 1 : 0, i, j);
|
|
}
|
|
function toggle(buffer, bit) {
|
|
const n = buffer.BYTES_PER_ELEMENT * 8;
|
|
const offset = bit & n - 1;
|
|
const i = (bit - offset) / n;
|
|
const mask = 1 << offset;
|
|
buffer[i] ^= mask;
|
|
return (buffer[i] & mask) !== 0;
|
|
}
|
|
function remove(buffer, bit) {
|
|
return set(buffer, bit, false);
|
|
}
|
|
function removeRange(buffer, start, end) {
|
|
return setRange(buffer, start, end, false);
|
|
}
|
|
function indexOf(buffer, value, position = 0) {
|
|
for (let i = position, n = buffer.byteLength * 8; i < n; i++) {
|
|
if (get(buffer, i) === value) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
function lastIndexOf(buffer, value, position = buffer.byteLength * 8 - 1) {
|
|
for (let i = position; i >= 0; i--) {
|
|
if (get(buffer, i) === value) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
function of(...bits) {
|
|
return from(bits);
|
|
}
|
|
function from(bits) {
|
|
const buffer = b4a.alloc(byteLength(bits.length));
|
|
for (let i = 0; i < bits.length; i++) set(buffer, i, bits[i]);
|
|
return buffer;
|
|
}
|
|
function* iterator(buffer) {
|
|
for (let i = 0, n = buffer.byteLength * 8; i < n; i++) yield get(buffer, i);
|
|
}
|
|
module.exports = {
|
|
byteLength,
|
|
get,
|
|
set,
|
|
setRange,
|
|
fill,
|
|
toggle,
|
|
remove,
|
|
removeRange,
|
|
indexOf,
|
|
lastIndexOf,
|
|
of,
|
|
from,
|
|
iterator
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/blind-relay/lib/errors.js
|
|
var require_errors7 = __commonJS({
|
|
"../../node_modules/blind-relay/lib/errors.js"(exports, module) {
|
|
module.exports = class BlindRelayError extends Error {
|
|
constructor(msg, code, fn = BlindRelayError) {
|
|
super(`${code}: ${msg}`);
|
|
this.code = code;
|
|
if (Error.captureStackTrace) {
|
|
Error.captureStackTrace(this, fn);
|
|
}
|
|
}
|
|
get name() {
|
|
return "BlindRelayError";
|
|
}
|
|
static DUPLICATE_CHANNEL(msg = "Duplicate channel") {
|
|
return new BlindRelayError(msg, "DUPLICATE_CHANNEL", BlindRelayError.DUPLICATE_CHANNEL);
|
|
}
|
|
static CHANNEL_CLOSED(msg = "Channel closed") {
|
|
return new BlindRelayError(msg, "CHANNEL_CLOSED", BlindRelayError.CHANNEL_CLOSED);
|
|
}
|
|
static CHANNEL_DESTROYED(msg = "Channel destroyed") {
|
|
return new BlindRelayError(msg, "CHANNEL_DESTROYED", BlindRelayError.CHANNEL_DESTROYED);
|
|
}
|
|
static ALREADY_PAIRING(msg = "Already pairing") {
|
|
return new BlindRelayError(msg, "ALREADY_PAIRING", BlindRelayError.ALREADY_PAIRING);
|
|
}
|
|
static PAIRING_CANCELLED(msg = "Pairing cancelled") {
|
|
return new BlindRelayError(msg, "PAIRING_CANCELLED", BlindRelayError.PAIRING_CANCELLED);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/blind-relay/index.js
|
|
var require_blind_relay = __commonJS({
|
|
"../../node_modules/blind-relay/index.js"(exports) {
|
|
var EventEmitter = __require("events");
|
|
var Protomux = require_protomux();
|
|
var { Readable } = require_streamx();
|
|
var sodium = require_sodium_universal();
|
|
var b4a = require_b4a();
|
|
var c = require_compact_encoding();
|
|
var bitfield = require_compact_encoding_bitfield();
|
|
var bits = require_bits_to_bytes();
|
|
var errors = require_errors7();
|
|
exports.Server = class BlindRelayServer extends EventEmitter {
|
|
constructor(opts = {}) {
|
|
super();
|
|
const {
|
|
createStream
|
|
} = opts;
|
|
this._createStream = createStream;
|
|
this._pairing = /* @__PURE__ */ new Map();
|
|
this._sessions = /* @__PURE__ */ new Set();
|
|
}
|
|
get sessions() {
|
|
return this._sessions[Symbol.iterator]();
|
|
}
|
|
accept(stream, opts) {
|
|
const session = new BlindRelaySession(this, stream, opts);
|
|
this._sessions.add(session);
|
|
return session;
|
|
}
|
|
async close() {
|
|
const ending = [];
|
|
for (const session of this._sessions) {
|
|
ending.push(session.end());
|
|
}
|
|
await Promise.all(ending);
|
|
this._pairing.clear();
|
|
}
|
|
};
|
|
var BlindRelaySession = class extends EventEmitter {
|
|
constructor(server, stream, opts = {}) {
|
|
super();
|
|
const {
|
|
id,
|
|
handshake,
|
|
handshakeEncoding
|
|
} = opts;
|
|
this._server = server;
|
|
this._mux = Protomux.from(stream);
|
|
this._channel = this._mux.createChannel({
|
|
protocol: "blind-relay",
|
|
id,
|
|
handshake: handshake ? handshakeEncoding || c.raw : null,
|
|
onopen: this._onopen.bind(this),
|
|
onclose: this._onclose.bind(this),
|
|
ondestroy: this._ondestroy.bind(this)
|
|
});
|
|
this._pair = this._channel.addMessage({
|
|
encoding: m.pair,
|
|
onmessage: this._onpair.bind(this)
|
|
});
|
|
this._unpair = this._channel.addMessage({
|
|
encoding: m.unpair,
|
|
onmessage: this._onunpair.bind(this)
|
|
});
|
|
this._ending = null;
|
|
this._destroyed = false;
|
|
this._error = null;
|
|
this._pairing = /* @__PURE__ */ new Set();
|
|
this._streams = /* @__PURE__ */ new Map();
|
|
this._onerror = (err) => this.emit("error", err);
|
|
this._channel.open(handshake);
|
|
}
|
|
get closed() {
|
|
return this._channel.closed;
|
|
}
|
|
get mux() {
|
|
return this._mux;
|
|
}
|
|
get stream() {
|
|
return this._mux.stream;
|
|
}
|
|
_onopen() {
|
|
this.emit("open");
|
|
}
|
|
_onclose() {
|
|
this._ending = Promise.resolve();
|
|
const err = this._error || errors.CHANNEL_CLOSED();
|
|
for (const token of this._pairing) {
|
|
this._server._pairing.delete(token.toString("hex"));
|
|
}
|
|
for (const stream of this._streams.values()) {
|
|
stream.off("error", this._onerror).on("error", noop).destroy(err);
|
|
}
|
|
this._pairing.clear();
|
|
this._streams.clear();
|
|
this._server._sessions.delete(this);
|
|
this.emit("close");
|
|
}
|
|
_ondestroy() {
|
|
this._destroyed = true;
|
|
this.emit("destroy");
|
|
}
|
|
_onpair({ isInitiator, token, id: remoteId }) {
|
|
const keyString = token.toString("hex");
|
|
let pair = this._server._pairing.get(keyString);
|
|
if (pair === void 0) {
|
|
pair = new BlindRelayPair(token);
|
|
this._server._pairing.set(keyString, pair);
|
|
} else if (pair.links[+isInitiator]) return;
|
|
this._pairing.add(keyString);
|
|
pair.links[+isInitiator] = new BlindRelayLink(this, isInitiator, remoteId);
|
|
if (!pair.paired) return;
|
|
this._server._pairing.delete(keyString);
|
|
for (const link of pair.links) {
|
|
link.createStream();
|
|
}
|
|
for (const { isInitiator: isInitiator2, session, stream } of pair.links) {
|
|
const remote = pair.remote(isInitiator2);
|
|
stream.on("error", session._onerror).on("close", () => session._streams.delete(keyString)).relayTo(remote.stream);
|
|
session._pairing.delete(keyString);
|
|
session._streams.set(keyString, stream);
|
|
}
|
|
for (const { isInitiator: isInitiator2, session, remoteId: remoteId2, stream } of pair.links) {
|
|
session._pair.send({
|
|
isInitiator: isInitiator2,
|
|
token,
|
|
id: stream.id,
|
|
seq: 0
|
|
});
|
|
session._endMaybe();
|
|
session.emit("pair", isInitiator2, token, stream, remoteId2);
|
|
}
|
|
}
|
|
_onunpair({ token }) {
|
|
const keyString = token.toString("hex");
|
|
const pair = this._server._pairing.get(keyString);
|
|
if (pair) {
|
|
for (const link of pair.links) {
|
|
if (link) link.session._pairing.delete(keyString);
|
|
}
|
|
return this._server._pairing.delete(keyString);
|
|
}
|
|
const stream = this._streams.get(keyString);
|
|
if (stream) {
|
|
stream.off("error", this._onerror).on("error", noop).destroy(errors.PAIRING_CANCELLED());
|
|
this._streams.delete(keyString);
|
|
}
|
|
}
|
|
cork() {
|
|
this._channel.cork();
|
|
}
|
|
uncork() {
|
|
this._channel.uncork();
|
|
}
|
|
async end() {
|
|
if (this._ending) return this._ending;
|
|
this._ending = EventEmitter.once(this, "close");
|
|
this._endMaybe();
|
|
return this._ending;
|
|
}
|
|
_endMaybe() {
|
|
if (this._ending && this._pairing.size === 0) {
|
|
this._channel.close();
|
|
}
|
|
}
|
|
destroy(err) {
|
|
if (this._destroyed) return;
|
|
this._destroyed = true;
|
|
this._error = err || errors.CHANNEL_DESTROYED();
|
|
this._channel.close();
|
|
}
|
|
};
|
|
var BlindRelayPair = class {
|
|
constructor(token) {
|
|
this.token = token;
|
|
this.links = [null, null];
|
|
}
|
|
get paired() {
|
|
return this.links[0] !== null && this.links[1] !== null;
|
|
}
|
|
remote(isInitiator) {
|
|
return this.links[isInitiator ? 0 : 1];
|
|
}
|
|
};
|
|
var BlindRelayLink = class {
|
|
constructor(session, isInitiator, remoteId) {
|
|
this.session = session;
|
|
this.isInitiator = isInitiator;
|
|
this.remoteId = remoteId;
|
|
this.stream = null;
|
|
}
|
|
createStream() {
|
|
if (this.stream) return;
|
|
this.stream = this.session._server._createStream({
|
|
firewall: this._onfirewall.bind(this)
|
|
});
|
|
}
|
|
_onfirewall(socket, port, host) {
|
|
this.stream.connect(socket, this.remoteId, port, host);
|
|
return false;
|
|
}
|
|
};
|
|
exports.Client = class BlindRelayClient extends EventEmitter {
|
|
static _clients = /* @__PURE__ */ new WeakMap();
|
|
static from(stream, opts) {
|
|
let client = this._clients.get(stream);
|
|
if (client) return client;
|
|
client = new this(stream, opts);
|
|
this._clients.set(stream, client);
|
|
return client;
|
|
}
|
|
constructor(stream, opts = {}) {
|
|
super();
|
|
const {
|
|
id,
|
|
handshake,
|
|
handshakeEncoding
|
|
} = opts;
|
|
this._mux = Protomux.from(stream);
|
|
this._channel = this._mux.createChannel({
|
|
protocol: "blind-relay",
|
|
id,
|
|
handshake: handshake ? handshakeEncoding || c.raw : null,
|
|
onopen: this._onopen.bind(this),
|
|
onclose: this._onclose.bind(this),
|
|
ondestroy: this._ondestroy.bind(this)
|
|
});
|
|
this._pair = this._channel.addMessage({
|
|
encoding: m.pair,
|
|
onmessage: this._onpair.bind(this)
|
|
});
|
|
this._unpair = this._channel.addMessage({
|
|
encoding: m.unpair
|
|
});
|
|
this._ending = false;
|
|
this._destroyed = false;
|
|
this._error = null;
|
|
this._requests = /* @__PURE__ */ new Map();
|
|
this._channel.open(handshake);
|
|
}
|
|
get closed() {
|
|
return this._channel.closed;
|
|
}
|
|
get mux() {
|
|
return this._mux;
|
|
}
|
|
get stream() {
|
|
return this._mux.stream;
|
|
}
|
|
get requests() {
|
|
return this._requests.values();
|
|
}
|
|
_onopen() {
|
|
this.emit("open");
|
|
}
|
|
_onclose() {
|
|
this._ending = Promise.resolve();
|
|
const err = this._error || errors.CHANNEL_CLOSED();
|
|
for (const request of this._requests.values()) {
|
|
request.destroy(err);
|
|
}
|
|
this._requests.clear();
|
|
this.constructor._clients.delete(this.stream);
|
|
this.emit("close");
|
|
}
|
|
_ondestroy() {
|
|
this._destroyed = true;
|
|
this.emit("destroy");
|
|
}
|
|
_onpair({ isInitiator, token, id: remoteId }) {
|
|
const request = this._requests.get(token.toString("hex"));
|
|
if (request === void 0 || request.isInitiator !== isInitiator) return;
|
|
request.push(remoteId);
|
|
request.push(null);
|
|
this.emit("pair", request.isInitiator, request.token, request.stream, remoteId);
|
|
}
|
|
pair(isInitiator, token, stream) {
|
|
if (this._destroyed) throw errors.CHANNEL_DESTROYED();
|
|
const keyString = token.toString("hex");
|
|
if (this._requests.has(keyString)) throw errors.ALREADY_PAIRING();
|
|
const request = new BlindRelayRequest(this, isInitiator, token, stream);
|
|
this._requests.set(keyString, request);
|
|
return request;
|
|
}
|
|
unpair(token) {
|
|
if (this._destroyed) throw errors.CHANNEL_DESTROYED();
|
|
const request = this._requests.get(token.toString("hex"));
|
|
if (request) request.destroy(errors.PAIRING_CANCELLED());
|
|
this._unpair.send({ token });
|
|
}
|
|
cork() {
|
|
this._channel.cork();
|
|
}
|
|
uncork() {
|
|
this._channel.uncork();
|
|
}
|
|
async end() {
|
|
if (this._ending) return this._ending;
|
|
this._ending = EventEmitter.once(this, "close");
|
|
this._endMaybe();
|
|
return this._ending;
|
|
}
|
|
_endMaybe() {
|
|
if (this._ending && this._requests.size === 0) {
|
|
this._channel.close();
|
|
}
|
|
}
|
|
destroy(err) {
|
|
if (this._destroyed) return;
|
|
this._destroyed = true;
|
|
this._error = err || errors.CHANNEL_DESTROYED();
|
|
this._channel.close();
|
|
}
|
|
};
|
|
var BlindRelayRequest = class extends Readable {
|
|
constructor(client, isInitiator, token, stream) {
|
|
super();
|
|
this.client = client;
|
|
this.isInitiator = isInitiator;
|
|
this.token = token;
|
|
this.stream = stream;
|
|
}
|
|
_open(cb) {
|
|
if (this.client._destroyed) return cb(errors.CHANNEL_DESTROYED());
|
|
this.client._pair.send({
|
|
isInitiator: this.isInitiator,
|
|
token: this.token,
|
|
id: this.stream.id,
|
|
seq: 0
|
|
});
|
|
cb(null);
|
|
}
|
|
_destroy(cb) {
|
|
this.client._requests.delete(this.token.toString("hex"));
|
|
cb(null);
|
|
this.client._endMaybe();
|
|
}
|
|
};
|
|
exports.token = function token(buf = b4a.allocUnsafe(32)) {
|
|
sodium.randombytes_buf(buf);
|
|
return buf;
|
|
};
|
|
function noop() {
|
|
}
|
|
var m = exports.messages = {};
|
|
var flags = bitfield(7);
|
|
m.pair = {
|
|
preencode(state, m2) {
|
|
flags.preencode(state);
|
|
c.fixed32.preencode(state, m2.token);
|
|
c.uint.preencode(state, m2.id);
|
|
c.uint.preencode(state, m2.seq);
|
|
},
|
|
encode(state, m2) {
|
|
flags.encode(state, bits.of(m2.isInitiator));
|
|
c.fixed32.encode(state, m2.token);
|
|
c.uint.encode(state, m2.id);
|
|
c.uint.encode(state, m2.seq);
|
|
},
|
|
decode(state) {
|
|
const [isInitiator] = bits.iterator(flags.decode(state));
|
|
return {
|
|
isInitiator,
|
|
token: c.fixed32.decode(state),
|
|
id: c.uint.decode(state),
|
|
seq: c.uint.decode(state)
|
|
};
|
|
}
|
|
};
|
|
m.unpair = {
|
|
preencode(state, m2) {
|
|
flags.preencode(state);
|
|
c.fixed32.preencode(state, m2.token);
|
|
},
|
|
encode(state, m2) {
|
|
flags.encode(state, bits.of());
|
|
c.fixed32.encode(state, m2.token);
|
|
},
|
|
decode(state) {
|
|
flags.decode(state);
|
|
return {
|
|
token: c.fixed32.decode(state)
|
|
};
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/noise-wrap.js
|
|
var require_noise_wrap = __commonJS({
|
|
"../../node_modules/hyperdht/lib/noise-wrap.js"(exports, module) {
|
|
var NoiseSecretStream = require_secret_stream();
|
|
var NoiseHandshake = require_noise();
|
|
var curve = require_noise_curve_ed();
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var sodium = require_sodium_universal();
|
|
var m = require_messages3();
|
|
var { NS } = require_constants2();
|
|
var { HANDSHAKE_UNFINISHED } = require_errors6();
|
|
var NOISE_PROLOUGE = NS.PEER_HANDSHAKE;
|
|
module.exports = class NoiseWrap {
|
|
constructor(keyPair, remotePublicKey) {
|
|
this.isInitiator = !!remotePublicKey;
|
|
this.remotePublicKey = remotePublicKey;
|
|
this.keyPair = keyPair;
|
|
this.handshake = new NoiseHandshake("IK", this.isInitiator, keyPair, { curve });
|
|
this.handshake.initialise(NOISE_PROLOUGE, remotePublicKey);
|
|
}
|
|
send(payload) {
|
|
const buf = c.encode(m.noisePayload, payload);
|
|
return this.handshake.send(buf);
|
|
}
|
|
recv(buf) {
|
|
const payload = c.decode(m.noisePayload, this.handshake.recv(buf));
|
|
this.remotePublicKey = b4a.toBuffer(this.handshake.rs);
|
|
return payload;
|
|
}
|
|
final() {
|
|
if (!this.handshake.complete) throw HANDSHAKE_UNFINISHED();
|
|
const holepunchSecret = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(holepunchSecret, NS.PEER_HOLEPUNCH, this.handshake.hash);
|
|
return {
|
|
isInitiator: this.isInitiator,
|
|
publicKey: this.keyPair.publicKey,
|
|
streamId: this.streamId,
|
|
remotePublicKey: this.remotePublicKey,
|
|
remoteId: NoiseSecretStream.id(this.handshake.hash, !this.isInitiator),
|
|
holepunchSecret,
|
|
hash: b4a.toBuffer(this.handshake.hash),
|
|
rx: b4a.toBuffer(this.handshake.rx),
|
|
tx: b4a.toBuffer(this.handshake.tx)
|
|
};
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/signal-promise/index.js
|
|
var require_signal_promise = __commonJS({
|
|
"../../node_modules/signal-promise/index.js"(exports, module) {
|
|
module.exports = class Signal {
|
|
constructor() {
|
|
this._resolve = null;
|
|
this._reject = null;
|
|
this._promise = null;
|
|
this._bind = bind.bind(this);
|
|
this._onerror = clear.bind(this);
|
|
this._onsuccess = clear.bind(this, null);
|
|
this._timers = /* @__PURE__ */ new Set();
|
|
}
|
|
wait(max) {
|
|
if (!this._promise) {
|
|
this._promise = new Promise(this._bind);
|
|
this._promise.then(this._onsuccess).catch(this._onerror);
|
|
}
|
|
if (max) return this._sleep(max);
|
|
return this._promise;
|
|
}
|
|
_sleep(max) {
|
|
const s = new Promise((resolve, reject) => {
|
|
const done = () => {
|
|
this._timers.delete(state);
|
|
resolve(true);
|
|
};
|
|
const id = setTimeout(done, max);
|
|
const state = { id, resolve, reject };
|
|
this._timers.add(state);
|
|
});
|
|
return s;
|
|
}
|
|
notify(err) {
|
|
if (!this._promise) return;
|
|
const resolve = this._resolve;
|
|
const reject = this._reject;
|
|
this._promise = null;
|
|
if (err) reject(err);
|
|
else resolve(true);
|
|
}
|
|
};
|
|
function clear(err) {
|
|
for (const { id, resolve, reject } of this._timers) {
|
|
clearTimeout(id);
|
|
if (err) reject(err);
|
|
else resolve(true);
|
|
}
|
|
this._timers.clear();
|
|
}
|
|
function bind(resolve, reject) {
|
|
this._resolve = resolve;
|
|
this._reject = reject;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/sleeper.js
|
|
var require_sleeper = __commonJS({
|
|
"../../node_modules/hyperdht/lib/sleeper.js"(exports, module) {
|
|
module.exports = class Sleeper {
|
|
constructor() {
|
|
this._timeout = null;
|
|
this._resolve = null;
|
|
this._start = (resolve) => {
|
|
this._resolve = resolve;
|
|
};
|
|
this._trigger = () => {
|
|
if (this._resolve === null) return;
|
|
const resolve = this._resolve;
|
|
this._timeout = null;
|
|
this._resolve = null;
|
|
resolve();
|
|
};
|
|
}
|
|
pause(ms) {
|
|
const p = new Promise(this._start);
|
|
if (this._timeout !== null) {
|
|
clearTimeout(this._timeout);
|
|
this._trigger();
|
|
}
|
|
this._timeout = setTimeout(this._trigger, ms);
|
|
return p;
|
|
}
|
|
resume() {
|
|
if (this._timeout !== null) {
|
|
clearTimeout(this._timeout);
|
|
this._trigger();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/announcer.js
|
|
var require_announcer = __commonJS({
|
|
"../../node_modules/hyperdht/lib/announcer.js"(exports, module) {
|
|
var safetyCatch = require_safety_catch();
|
|
var c = require_compact_encoding();
|
|
var Signal = require_signal_promise();
|
|
var { encodeUnslab } = require_encode2();
|
|
var Sleeper = require_sleeper();
|
|
var m = require_messages3();
|
|
var Persistent = require_persistent();
|
|
var { COMMANDS } = require_constants2();
|
|
var MIN_ACTIVE = 3;
|
|
module.exports = class Announcer {
|
|
constructor(dht, keyPair, target, opts = {}) {
|
|
this.dht = dht;
|
|
this.keyPair = keyPair;
|
|
this.target = target;
|
|
this.relays = [];
|
|
this.relayAddresses = [];
|
|
this.stopped = false;
|
|
this.suspended = false;
|
|
this.record = encodeUnslab(m.peer, { publicKey: keyPair.publicKey, relayAddresses: [] });
|
|
this.online = new Signal();
|
|
this._refreshing = false;
|
|
this._closestNodes = null;
|
|
this._active = null;
|
|
this._sleeper = new Sleeper();
|
|
this._resumed = new Signal();
|
|
this._signAnnounce = opts.signAnnounce || Persistent.signAnnounce;
|
|
this._signUnannounce = opts.signUnannounce || Persistent.signUnannounce;
|
|
this._updating = null;
|
|
this._activeQuery = null;
|
|
this._unannouncing = null;
|
|
this._serverRelays = [/* @__PURE__ */ new Map(), /* @__PURE__ */ new Map(), /* @__PURE__ */ new Map()];
|
|
}
|
|
isRelay(addr) {
|
|
const id = addr.host + ":" + addr.port;
|
|
const [a, b, c2] = this._serverRelays;
|
|
return a.has(id) || b.has(id) || c2.has(id);
|
|
}
|
|
async suspend({ log = noop } = {}) {
|
|
if (this.suspended) return;
|
|
this.suspended = true;
|
|
log("Suspending announcer");
|
|
this.online.notify();
|
|
if (this._activeQuery) this._activeQuery.destroy();
|
|
this._sleeper.resume();
|
|
if (this._updating) await this._updating;
|
|
log("Suspending announcer (post update)");
|
|
if (this.suspended === false || this.stopped) return;
|
|
log("Suspending announcer (pre unannounce)");
|
|
await this._unannounceCurrent();
|
|
log("Suspending announcer (post unannounce)");
|
|
}
|
|
resume() {
|
|
if (!this.suspended) return;
|
|
this.suspended = false;
|
|
this.refresh();
|
|
this._sleeper.resume();
|
|
this._resumed.notify();
|
|
}
|
|
refresh() {
|
|
if (this.stopped) return;
|
|
this._refreshing = true;
|
|
}
|
|
async start() {
|
|
if (this.stopped) return;
|
|
this._active = this._runUpdate();
|
|
await this._active;
|
|
if (this.stopped) return;
|
|
this._active = this._background();
|
|
}
|
|
async stop() {
|
|
this.stopped = true;
|
|
this.online.notify();
|
|
this._sleeper.resume();
|
|
this._resumed.notify();
|
|
await this._active;
|
|
await this._unannounceCurrent();
|
|
}
|
|
async _unannounceCurrent() {
|
|
while (this._unannouncing !== null) await this._unannouncing;
|
|
const un = this._unannouncing = this._unannounceAll(this._serverRelays[2].values());
|
|
await this._unannouncing;
|
|
if (un === this._unannouncing) this._unannouncing = null;
|
|
}
|
|
async _background() {
|
|
while (!this.dht.destroyed && !this.stopped) {
|
|
try {
|
|
this._refreshing = false;
|
|
for (let i = 0; i < 100 && !this.stopped && !this._refreshing && !this.suspended; i++) {
|
|
const pings = [];
|
|
for (const node of this._serverRelays[2].values()) {
|
|
pings.push(this.dht.ping(node));
|
|
}
|
|
const active = await resolved(pings);
|
|
if (active < Math.min(pings.length, MIN_ACTIVE)) {
|
|
this.refresh();
|
|
}
|
|
if (this.stopped) return;
|
|
if (!this.suspended && !this._refreshing) await this._sleeper.pause(3e3);
|
|
}
|
|
while (!this.stopped && this.suspended) await this._resumed.wait();
|
|
if (!this.stopped) await this._runUpdate();
|
|
while (!this.dht.online && !this.stopped && !this.suspended) {
|
|
await this.online.wait();
|
|
}
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
}
|
|
}
|
|
}
|
|
async _runUpdate() {
|
|
this._updating = this._update();
|
|
await this._updating;
|
|
this._updating = null;
|
|
}
|
|
async _update() {
|
|
while (this._unannouncing) await this._unannouncing;
|
|
this._cycle();
|
|
const q = this._activeQuery = this.dht.findPeer(this.target, {
|
|
hash: false,
|
|
nodes: this._closestNodes
|
|
});
|
|
try {
|
|
await q.finished();
|
|
} catch {
|
|
}
|
|
this._activeQuery = null;
|
|
if (this.stopped || this.suspended) return;
|
|
const ann = [];
|
|
const replies = pickBest(q.closestReplies);
|
|
const relays = [];
|
|
const relayAddresses = [];
|
|
if (!this.dht.firewalled) {
|
|
const addr = this.dht.remoteAddress();
|
|
if (addr) relayAddresses.push(addr);
|
|
}
|
|
for (const msg of replies) {
|
|
ann.push(this._commit(msg, relays, relayAddresses));
|
|
}
|
|
await Promise.allSettled(ann);
|
|
if (this.stopped || this.suspended) return;
|
|
this._closestNodes = q.closestNodes;
|
|
this.relays = relays;
|
|
this.relayAddresses = relayAddresses;
|
|
const removed = [];
|
|
for (const [key, value] of this._serverRelays[1]) {
|
|
if (!this._serverRelays[2].has(key)) removed.push(value);
|
|
}
|
|
await this._unannounceAll(removed);
|
|
}
|
|
_unannounceAll(relays) {
|
|
const unann = [];
|
|
for (const r of relays) unann.push(this._unannounce(r));
|
|
return Promise.allSettled(unann);
|
|
}
|
|
async _unannounce(to) {
|
|
const unann = {
|
|
peer: {
|
|
publicKey: this.keyPair.publicKey,
|
|
relayAddresses: []
|
|
},
|
|
refresh: null,
|
|
signature: null
|
|
};
|
|
const { from, token, value } = await this.dht.request(
|
|
{
|
|
token: null,
|
|
command: COMMANDS.FIND_PEER,
|
|
target: this.target,
|
|
value: null
|
|
},
|
|
to
|
|
);
|
|
if (!token || !from.id || !value) return;
|
|
unann.signature = await this._signUnannounce(this.target, token, from.id, unann, this.keyPair);
|
|
await this.dht.request(
|
|
{
|
|
token,
|
|
command: COMMANDS.UNANNOUNCE,
|
|
target: this.target,
|
|
value: c.encode(m.announce, unann)
|
|
},
|
|
to
|
|
);
|
|
}
|
|
async _commit(msg, relays, relayAddresses) {
|
|
const ann = {
|
|
peer: {
|
|
publicKey: this.keyPair.publicKey,
|
|
relayAddresses: []
|
|
},
|
|
refresh: null,
|
|
signature: null
|
|
};
|
|
ann.signature = await this._signAnnounce(this.target, msg.token, msg.from.id, ann, this.keyPair);
|
|
const res = await this.dht.request(
|
|
{
|
|
token: msg.token,
|
|
command: COMMANDS.ANNOUNCE,
|
|
target: this.target,
|
|
value: c.encode(m.announce, ann)
|
|
},
|
|
msg.from
|
|
);
|
|
if (res.error !== 0) return;
|
|
if (relayAddresses.length < 3) relayAddresses.push({ host: msg.from.host, port: msg.from.port });
|
|
relays.push({ relayAddress: msg.from, peerAddress: msg.to });
|
|
this._serverRelays[2].set(msg.from.host + ":" + msg.from.port, msg.from);
|
|
}
|
|
_cycle() {
|
|
const tmp = this._serverRelays[0];
|
|
this._serverRelays[0] = this._serverRelays[1];
|
|
this._serverRelays[1] = this._serverRelays[2];
|
|
this._serverRelays[2] = tmp;
|
|
tmp.clear();
|
|
}
|
|
};
|
|
function resolved(ps) {
|
|
let replied = 0;
|
|
let ticks = ps.length + 1;
|
|
return new Promise((resolve) => {
|
|
for (const p of ps) p.then(push, tick);
|
|
tick();
|
|
function push(v) {
|
|
replied++;
|
|
tick();
|
|
}
|
|
function tick() {
|
|
if (--ticks === 0) resolve(replied);
|
|
}
|
|
});
|
|
}
|
|
function pickBest(replies) {
|
|
return replies.slice(0, 3);
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/crypto.js
|
|
var require_crypto = __commonJS({
|
|
"../../node_modules/hyperdht/lib/crypto.js"(exports, module) {
|
|
var sodium = require_sodium_universal();
|
|
var b4a = require_b4a();
|
|
function hash(data) {
|
|
const out = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(out, data);
|
|
return out;
|
|
}
|
|
function unslabbedHash(data) {
|
|
const out = b4a.allocUnsafeSlow(32);
|
|
sodium.crypto_generichash(out, data);
|
|
return out;
|
|
}
|
|
function createKeyPair(seed) {
|
|
const publicKey = b4a.alloc(32);
|
|
const secretKey = b4a.alloc(64);
|
|
if (seed) sodium.crypto_sign_seed_keypair(publicKey, secretKey, seed);
|
|
else sodium.crypto_sign_keypair(publicKey, secretKey);
|
|
return { publicKey, secretKey };
|
|
}
|
|
module.exports = {
|
|
hash,
|
|
unslabbedHash,
|
|
createKeyPair
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/secure-payload.js
|
|
var require_secure_payload = __commonJS({
|
|
"../../node_modules/hyperdht/lib/secure-payload.js"(exports, module) {
|
|
var sodium = require_sodium_universal();
|
|
var b4a = require_b4a();
|
|
var { holepunchPayload } = require_messages3();
|
|
module.exports = class HolepunchPayload {
|
|
constructor(holepunchSecret) {
|
|
this._sharedSecret = holepunchSecret;
|
|
this._localSecret = b4a.allocUnsafe(32);
|
|
sodium.randombytes_buf(this._localSecret);
|
|
}
|
|
decrypt(buffer) {
|
|
const state = { start: 24, end: buffer.byteLength - 16, buffer };
|
|
if (state.end <= state.start) return null;
|
|
const nonce = buffer.subarray(0, 24);
|
|
const msg = state.buffer.subarray(state.start, state.end);
|
|
const cipher = state.buffer.subarray(state.start);
|
|
if (!sodium.crypto_secretbox_open_easy(msg, cipher, nonce, this._sharedSecret)) return null;
|
|
try {
|
|
return holepunchPayload.decode(state);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
encrypt(payload) {
|
|
const state = { start: 24, end: 24, buffer: null };
|
|
holepunchPayload.preencode(state, payload);
|
|
state.buffer = b4a.allocUnsafe(state.end + 16);
|
|
const nonce = state.buffer.subarray(0, 24);
|
|
const msg = state.buffer.subarray(state.start, state.end);
|
|
const cipher = state.buffer.subarray(state.start);
|
|
holepunchPayload.encode(state, payload);
|
|
sodium.randombytes_buf(nonce);
|
|
sodium.crypto_secretbox_easy(cipher, msg, nonce, this._sharedSecret);
|
|
return state.buffer;
|
|
}
|
|
token(addr) {
|
|
const out = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(out, b4a.from(addr.host), this._localSecret);
|
|
return out;
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/nat.js
|
|
var require_nat = __commonJS({
|
|
"../../node_modules/hyperdht/lib/nat.js"(exports, module) {
|
|
var { FIREWALL } = require_constants2();
|
|
module.exports = class Nat {
|
|
constructor(dht, session, socket) {
|
|
this._samplesHost = [];
|
|
this._samplesFull = [];
|
|
this._visited = /* @__PURE__ */ new Map();
|
|
this._resolve = null;
|
|
this._minSamples = 4;
|
|
this._autoSampling = false;
|
|
this.dht = dht;
|
|
this.session = session;
|
|
this.socket = socket;
|
|
this.sampled = 0;
|
|
this.firewall = dht.firewalled ? FIREWALL.UNKNOWN : FIREWALL.OPEN;
|
|
this.addresses = null;
|
|
this.analyzing = new Promise((resolve) => {
|
|
this._resolve = resolve;
|
|
});
|
|
}
|
|
autoSample(retry = true) {
|
|
if (this._autoSampling) return;
|
|
this._autoSampling = true;
|
|
const self2 = this;
|
|
const socket = this.socket;
|
|
const maxPings = this._minSamples;
|
|
let skip = this.dht.nodes.length >= 8 ? 5 : 0;
|
|
let pending = 0;
|
|
for (let node = this.dht.nodes.latest; node && this.sampled + pending < maxPings; node = node.prev) {
|
|
if (skip > 0) {
|
|
skip--;
|
|
continue;
|
|
}
|
|
const ref = node.host + ":" + node.port;
|
|
if (this._visited.has(ref)) continue;
|
|
this._visited.set(ref, 1);
|
|
pending++;
|
|
this.session.ping(node, { socket, retry: false }).then(onpong, onskip);
|
|
}
|
|
pending++;
|
|
onskip();
|
|
function onpong(res) {
|
|
self2.add(res.to, res.from);
|
|
onskip();
|
|
}
|
|
function onskip() {
|
|
if (--pending === 0 && self2.sampled < self2._minSamples) {
|
|
if (retry) {
|
|
self2._autoSampling = false;
|
|
self2.autoSample(false);
|
|
return;
|
|
}
|
|
self2._resolve();
|
|
}
|
|
}
|
|
}
|
|
destroy() {
|
|
this._autoSampling = true;
|
|
this._minSamples = 0;
|
|
this._resolve();
|
|
}
|
|
unfreeze() {
|
|
this.frozen = false;
|
|
this._updateFirewall();
|
|
this._updateAddresses();
|
|
}
|
|
freeze() {
|
|
this.frozen = true;
|
|
}
|
|
_updateFirewall() {
|
|
if (!this.dht.firewalled) {
|
|
this.firewall = FIREWALL.OPEN;
|
|
return;
|
|
}
|
|
if (this.sampled < 3) return;
|
|
const max = this._samplesFull[0].hits;
|
|
if (max >= 3) {
|
|
this.firewall = FIREWALL.CONSISTENT;
|
|
return;
|
|
}
|
|
if (max === 1) {
|
|
this.firewall = FIREWALL.RANDOM;
|
|
return;
|
|
}
|
|
if (this._samplesHost.length === 1 && this.sampled > 3) {
|
|
this.firewall = FIREWALL.RANDOM;
|
|
return;
|
|
}
|
|
if (this._samplesHost.length > 1 && this._samplesFull[1].hits > 1) {
|
|
this.firewall = FIREWALL.CONSISTENT;
|
|
return;
|
|
}
|
|
if (this.sampled > 4) {
|
|
this.firewall = FIREWALL.RANDOM;
|
|
}
|
|
}
|
|
_updateAddresses() {
|
|
if (this.firewall === FIREWALL.UNKNOWN) {
|
|
this.addresses = null;
|
|
return;
|
|
}
|
|
if (this.firewall === FIREWALL.RANDOM) {
|
|
this.addresses = [this._samplesHost[0]];
|
|
return;
|
|
}
|
|
if (this.firewall === FIREWALL.CONSISTENT) {
|
|
this.addresses = [];
|
|
for (const addr of this._samplesFull) {
|
|
if (addr.hits >= 2 || this.addresses.length < 2) this.addresses.push(addr);
|
|
}
|
|
}
|
|
}
|
|
update() {
|
|
if (this.dht.firewalled && this.firewall === FIREWALL.OPEN) {
|
|
this.firewall = FIREWALL.UNKNOWN;
|
|
}
|
|
this._updateFirewall();
|
|
this._updateAddresses();
|
|
}
|
|
add(addr, from) {
|
|
const ref = from.host + ":" + from.port;
|
|
if (this._visited.get(ref) === 2) return;
|
|
this._visited.set(ref, 2);
|
|
addSample(this._samplesHost, addr.host, 0);
|
|
addSample(this._samplesFull, addr.host, addr.port);
|
|
if ((++this.sampled >= 3 || !this.dht.firewalled) && !this.frozen) {
|
|
this.update();
|
|
}
|
|
if (this.firewall === FIREWALL.CONSISTENT || this.firewall === FIREWALL.OPEN) {
|
|
this._resolve();
|
|
} else if (this.sampled >= this._minSamples) {
|
|
this._resolve();
|
|
}
|
|
}
|
|
};
|
|
function addSample(samples, host, port) {
|
|
for (let i = 0; i < samples.length; i++) {
|
|
const s = samples[i];
|
|
if (s.port !== port || s.host !== host) continue;
|
|
s.hits++;
|
|
for (; i > 0; i--) {
|
|
const prev = samples[i - 1];
|
|
if (prev.hits >= s.hits) return;
|
|
samples[i - 1] = s;
|
|
samples[i] = prev;
|
|
}
|
|
return;
|
|
}
|
|
samples.push({
|
|
host,
|
|
port,
|
|
hits: 1
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/holepuncher.js
|
|
var require_holepuncher = __commonJS({
|
|
"../../node_modules/hyperdht/lib/holepuncher.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var Nat = require_nat();
|
|
var Sleeper = require_sleeper();
|
|
var { FIREWALL } = require_constants2();
|
|
var BIRTHDAY_SOCKETS = 256;
|
|
var HOLEPUNCH = b4a.from([0]);
|
|
var HOLEPUNCH_TTL = 5;
|
|
var DEFAULT_TTL = 64;
|
|
var MAX_REOPENS = 3;
|
|
module.exports = class Holepuncher {
|
|
constructor(dht, session, isInitiator, remoteFirewall = FIREWALL.UNKNOWN) {
|
|
const holder = dht._socketPool.acquire();
|
|
this.dht = dht;
|
|
this.session = session;
|
|
this.nat = new Nat(dht, session, holder.socket);
|
|
this.nat.autoSample();
|
|
this.isInitiator = isInitiator;
|
|
this.onconnect = noop;
|
|
this.onabort = noop;
|
|
this.punching = false;
|
|
this.connected = false;
|
|
this.destroyed = false;
|
|
this.randomized = false;
|
|
this.remoteFirewall = remoteFirewall;
|
|
this.remoteAddresses = [];
|
|
this.remoteHolepunching = false;
|
|
this._sleeper = new Sleeper();
|
|
this._reopening = null;
|
|
this._timeout = null;
|
|
this._punching = null;
|
|
this._allHolders = [];
|
|
this._holder = this._addRef(holder);
|
|
}
|
|
get socket() {
|
|
return this._holder.socket;
|
|
}
|
|
updateRemote({ punching, firewall, addresses, verified }) {
|
|
const remoteAddresses = [];
|
|
if (addresses) {
|
|
for (const addr of addresses) {
|
|
remoteAddresses.push({
|
|
host: addr.host,
|
|
port: addr.port,
|
|
verified: verified === addr.host || this._isVerified(addr.host)
|
|
});
|
|
}
|
|
}
|
|
this.remoteFirewall = firewall;
|
|
this.remoteAddresses = remoteAddresses;
|
|
this.remoteHolepunching = punching;
|
|
}
|
|
_isVerified(host) {
|
|
for (const addr of this.remoteAddresses) {
|
|
if (addr.verified && addr.host === host) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
ping(addr, socket = this._holder.socket) {
|
|
return holepunch(socket, addr, false);
|
|
}
|
|
openSession(addr, socket = this._holder.socket) {
|
|
return holepunch(socket, addr, true);
|
|
}
|
|
async analyze(allowReopen) {
|
|
await this.nat.analyzing;
|
|
if (this._unstable()) {
|
|
if (!allowReopen) return false;
|
|
if (!this._reopening) this._reopening = this._reopen();
|
|
return this._reopening;
|
|
}
|
|
return true;
|
|
}
|
|
_unstable() {
|
|
const firewall = this.nat.firewall;
|
|
return this.remoteFirewall >= FIREWALL.RANDOM && firewall >= FIREWALL.RANDOM || firewall === FIREWALL.UNKNOWN;
|
|
}
|
|
_reset() {
|
|
const prev = this._holder;
|
|
this._allHolders.pop();
|
|
this._holder = this._addRef(this.dht._socketPool.acquire());
|
|
prev.release();
|
|
this.nat.destroy();
|
|
this.nat = new Nat(this.dht, this.session, this._holder.socket);
|
|
this.nat.autoSample();
|
|
}
|
|
_addRef(ref) {
|
|
this._allHolders.push(ref);
|
|
ref.onholepunchmessage = (msg, rinfo) => this._onholepunchmessage(msg, rinfo, ref);
|
|
return ref;
|
|
}
|
|
_onholepunchmessage(_, addr, ref) {
|
|
if (!this.isInitiator) {
|
|
holepunch(ref.socket, addr, false);
|
|
return;
|
|
}
|
|
if (this.connected) return;
|
|
this.connected = true;
|
|
this.punching = false;
|
|
for (const r of this._allHolders) {
|
|
if (r === ref) continue;
|
|
r.release();
|
|
}
|
|
this._allHolders[0] = ref;
|
|
while (this._allHolders.length > 1) this._allHolders.pop();
|
|
this._decrementRandomized();
|
|
this.onconnect(ref.socket, addr.port, addr.host);
|
|
}
|
|
_done() {
|
|
return this.destroyed || this.connected;
|
|
}
|
|
async _reopen() {
|
|
for (let i = 0; this._unstable() && i < MAX_REOPENS && !this._done() && !this.punching; i++) {
|
|
this._reset();
|
|
await this.nat.analyzing;
|
|
}
|
|
return coerceFirewall(this.nat.firewall) === FIREWALL.CONSISTENT;
|
|
}
|
|
punch() {
|
|
if (!this._punching) this._punching = this._punch();
|
|
return this._punching;
|
|
}
|
|
async _punch() {
|
|
if (this._done() || !this.remoteAddresses.length) return false;
|
|
this.punching = true;
|
|
const local = coerceFirewall(this.nat.firewall);
|
|
const remote = coerceFirewall(this.remoteFirewall);
|
|
let remoteVerifiedAddress = null;
|
|
for (const addr of this.remoteAddresses) {
|
|
if (addr.verified) {
|
|
remoteVerifiedAddress = addr;
|
|
break;
|
|
}
|
|
}
|
|
if (local === FIREWALL.CONSISTENT && remote === FIREWALL.CONSISTENT) {
|
|
this.dht.stats.punches.consistent++;
|
|
this._consistentProbe();
|
|
return true;
|
|
}
|
|
if (!remoteVerifiedAddress) return false;
|
|
if (local === FIREWALL.CONSISTENT && remote >= FIREWALL.RANDOM) {
|
|
this.dht.stats.punches.random++;
|
|
this._incrementRandomized();
|
|
this._randomProbes(remoteVerifiedAddress);
|
|
return true;
|
|
}
|
|
if (local >= FIREWALL.RANDOM && remote === FIREWALL.CONSISTENT) {
|
|
this.dht.stats.punches.random++;
|
|
this._incrementRandomized();
|
|
await this._openBirthdaySockets(remoteVerifiedAddress);
|
|
if (this.punching) this._keepAliveRandomNat(remoteVerifiedAddress);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
// Note that this never throws so it is safe to run in the background
|
|
async _consistentProbe() {
|
|
if (!this.isInitiator) await this._sleeper.pause(1e3);
|
|
let tries = 0;
|
|
while (this.punching && tries++ < 10) {
|
|
for (const addr of this.remoteAddresses) {
|
|
if (!addr.verified && (tries & 3) !== 0) continue;
|
|
await holepunch(this._holder.socket, addr, false);
|
|
}
|
|
if (this.punching) await this._sleeper.pause(1e3);
|
|
}
|
|
this._autoDestroy();
|
|
}
|
|
// Note that this never throws so it is safe to run in the background
|
|
async _randomProbes(remoteAddr) {
|
|
let tries = 1750;
|
|
while (this.punching && tries-- > 0) {
|
|
const addr = { host: remoteAddr.host, port: randomPort() };
|
|
await holepunch(this._holder.socket, addr, false);
|
|
if (this.punching) await this._sleeper.pause(20);
|
|
}
|
|
this._autoDestroy();
|
|
}
|
|
// Note that this never throws so it is safe to run in the background
|
|
async _keepAliveRandomNat(remoteAddr) {
|
|
let i = 0;
|
|
let lowTTLRounds = 1;
|
|
await this._sleeper.pause(100);
|
|
let tries = 1750;
|
|
while (this.punching && tries-- > 0) {
|
|
if (i === this._allHolders.length) {
|
|
i = 0;
|
|
if (lowTTLRounds > 0) lowTTLRounds--;
|
|
}
|
|
await holepunch(this._allHolders[i++].socket, remoteAddr, lowTTLRounds > 0);
|
|
if (this.punching) await this._sleeper.pause(20);
|
|
}
|
|
this._autoDestroy();
|
|
}
|
|
async _openBirthdaySockets(remoteAddr) {
|
|
while (this.punching && this._allHolders.length < BIRTHDAY_SOCKETS) {
|
|
const ref = this._addRef(this.dht._socketPool.acquire());
|
|
await holepunch(ref.socket, remoteAddr, HOLEPUNCH_TTL);
|
|
}
|
|
}
|
|
_autoDestroy() {
|
|
if (!this.connected) this.destroy();
|
|
}
|
|
_incrementRandomized() {
|
|
if (!this.randomized) {
|
|
this.randomized = true;
|
|
this.dht._randomPunches++;
|
|
}
|
|
}
|
|
_decrementRandomized() {
|
|
if (this.randomized) {
|
|
this.dht._lastRandomPunch = Date.now();
|
|
this.randomized = false;
|
|
this.dht._randomPunches--;
|
|
}
|
|
}
|
|
destroy() {
|
|
if (this.destroyed) return;
|
|
this.destroyed = true;
|
|
this.punching = false;
|
|
for (const ref of this._allHolders) ref.release();
|
|
this._allHolders = [];
|
|
this.nat.destroy();
|
|
if (!this.connected) {
|
|
this._decrementRandomized();
|
|
this.onabort();
|
|
}
|
|
}
|
|
static ping(socket, addr) {
|
|
return holepunch(socket, addr, false);
|
|
}
|
|
static localAddresses(socket) {
|
|
return localAddresses(socket);
|
|
}
|
|
static matchAddress(myAddresses, externalAddresses) {
|
|
return matchAddress(myAddresses, externalAddresses);
|
|
}
|
|
};
|
|
function holepunch(socket, addr, lowTTL) {
|
|
return socket.send(HOLEPUNCH, addr.port, addr.host, lowTTL ? HOLEPUNCH_TTL : DEFAULT_TTL);
|
|
}
|
|
function randomPort() {
|
|
return 1e3 + Math.random() * 64536 | 0;
|
|
}
|
|
function coerceFirewall(fw) {
|
|
return fw === FIREWALL.OPEN ? FIREWALL.CONSISTENT : fw;
|
|
}
|
|
function localAddresses(socket) {
|
|
const addrs = [];
|
|
const { host, port } = socket.address();
|
|
if (host === "127.0.0.1") return [{ host, port }];
|
|
for (const n of socket.udx.networkInterfaces()) {
|
|
if (n.family !== 4 || n.internal) continue;
|
|
addrs.push({ host: n.host, port });
|
|
}
|
|
if (addrs.length === 0) {
|
|
addrs.push({ host: "127.0.0.1", port });
|
|
}
|
|
return addrs;
|
|
}
|
|
function matchAddress(localAddresses2, remoteLocalAddresses) {
|
|
if (remoteLocalAddresses.length === 0) return null;
|
|
let best = { segment: 1, addr: null };
|
|
for (const localAddress of localAddresses2) {
|
|
const a = localAddress.host.split(".");
|
|
for (const remoteAddress of remoteLocalAddresses) {
|
|
const b = remoteAddress.host.split(".");
|
|
if (a[0] === b[0]) {
|
|
if (best.segment === 1) best = { segment: 2, addr: remoteAddress };
|
|
if (a[1] === b[1]) {
|
|
if (best.segment === 2) best = { segment: 3, addr: remoteAddress };
|
|
if (a[2] === b[2]) return remoteAddress;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return best.addr;
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bogon/index.js
|
|
var require_bogon = __commonJS({
|
|
"../../node_modules/bogon/index.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
var c = require_compact_encoding();
|
|
var net = require_compact_encoding_net();
|
|
module.exports = exports = function isBogon(ip) {
|
|
return isBogonIP(ensureBuffer(ip));
|
|
};
|
|
exports.isBogon = exports;
|
|
exports.isPrivate = function isPrivate(ip) {
|
|
return isPrivateIP(ensureBuffer(ip));
|
|
};
|
|
exports.isReserved = function isReserved(ip) {
|
|
return isReservedIP(ensureBuffer(ip));
|
|
};
|
|
function isBogonIP(ip) {
|
|
return isPrivateIP(ip) || isReservedIP(ip);
|
|
}
|
|
function isPrivateIP(ip) {
|
|
return ip.byteLength === 4 ? isPrivateIPv4(ip) : false;
|
|
}
|
|
function isPrivateIPv4(ip) {
|
|
return (
|
|
// 10.0.0.0/8 Private-use networks
|
|
ip[0] === 10 || // 100.64.0.0/10 Carrier-grade NAT
|
|
ip[0] === 100 && ip[1] >= 64 && ip[1] <= 127 || // 127.0.0.0/8 Loopback + Name collision occurrence (127.0.53.53)
|
|
ip[0] === 127 || // 169.254.0.0/16 Link local
|
|
ip[0] === 169 && ip[1] === 254 || // 172.16.0.0/12 Private-use networks
|
|
ip[0] === 172 && ip[1] >= 16 && ip[1] <= 31 || // 192.168.0.0/16 Private-use networks
|
|
ip[0] === 192 && ip[1] === 168
|
|
);
|
|
}
|
|
function isReservedIP(ip) {
|
|
return ip.byteLength === 4 ? isReservedIPv4(ip) : isReservedIPv6(ip);
|
|
}
|
|
function isReservedIPv4(ip) {
|
|
return (
|
|
// 0.0.0.0/8 "This" network
|
|
ip[0] === 0 || // 192.0.0.0/24 IETF protocol assignments
|
|
ip[0] === 192 && ip[1] === 0 && ip[2] === 0 || // 192.0.2.0/24 TEST-NET-1
|
|
ip[0] === 192 && ip[1] === 0 && ip[2] === 2 || // 198.18.0.0/15 Network interconnect device benchmark testing
|
|
ip[0] === 198 && ip[1] >= 18 && ip[1] <= 19 || // 198.51.100.0/24 TEST-NET-2
|
|
ip[0] === 198 && ip[1] === 51 && ip[2] === 100 || // 203.0.113.0/24 TEST-NET-3
|
|
ip[0] === 203 && ip[1] === 0 && ip[2] === 113 || // 224.0.0.0/4 Multicast
|
|
ip[0] >= 224 && ip[0] <= 239 || // 240.0.0.0/4 Reserved for future use
|
|
ip[0] >= 240 || // 255.255.255.255/32
|
|
ip[0] === 255 && ip[1] === 255 && ip[2] === 255 && ip[3] === 255
|
|
);
|
|
}
|
|
function isReservedIPv6(ip) {
|
|
return (
|
|
// ::/128 Node-scope unicast unspecified address
|
|
// ::1/128 Node-scope unicast loopback address
|
|
ip[0] === 0 && ip[1] === 0 && ip[2] === 0 && ip[3] === 0 && ip[4] === 0 && ip[5] === 0 && ip[6] === 0 && ip[7] === 0 && ip[8] === 0 && ip[9] === 0 && ip[10] === 0 && ip[11] === 0 && ip[12] === 0 && ip[13] === 0 && ip[14] === 0 && ip[15] <= 1 || // ::ffff:0:0/96 IPv4-mapped addresses
|
|
// ::/96 IPv4-compatible addresses
|
|
ip[0] === 0 && ip[1] === 0 && ip[2] === 0 && ip[3] === 0 && ip[4] === 0 && ip[5] === 0 && ip[6] === 0 && ip[7] === 0 && ip[8] === 0 && ip[9] === 0 && (ip[10] === 0 || ip[10] === 255) && (ip[11] === 0 || ip[11] === 255) || // 100::/64 Remotely triggered black hole addresses
|
|
ip[0] === 1 && ip[1] === 0 && ip[2] === 0 && ip[3] === 0 && ip[4] === 0 && ip[5] === 0 && ip[6] === 0 && ip[7] === 0 || // 2001:10::/28 Overlay routable cryptographic hash identifiers (ORCHID)
|
|
ip[0] === 32 && ip[1] === 1 && ip[2] === 0 && ip[3] >= 16 && ip[3] <= 31 || // 2001:20::/28 Overlay routable cryptographic hash identifiers version 2 (ORCHIDv2)
|
|
ip[0] === 32 && ip[1] === 1 && ip[2] === 0 && ip[3] >= 32 && ip[3] <= 47 || // 2001:db8::/32 Documentation prefix
|
|
ip[0] === 32 && ip[1] === 1 && ip[2] === 13 && ip[3] === 184 || // fc00::/7 Unique local addresses (ULA)
|
|
ip[0] >= 252 && ip[0] <= 253 || // fe80::/10 Link-local unicast
|
|
ip[0] === 254 && ip[1] >= 128 && ip[1] <= 191 || // ff00::/8 Multicast
|
|
ip[0] === 255
|
|
);
|
|
}
|
|
var state = c.state(0, 0, b4a.allocUnsafe(1 + 16));
|
|
function ensureBuffer(ip) {
|
|
if (b4a.isBuffer(ip)) return ip;
|
|
net.ip.preencode(state, ip);
|
|
net.ip.encode(state, ip);
|
|
const buffer = state.buffer.subarray(1, state.end);
|
|
state.start = 0;
|
|
state.end = 0;
|
|
return buffer;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/server.js
|
|
var require_server = __commonJS({
|
|
"../../node_modules/hyperdht/lib/server.js"(exports, module) {
|
|
var { EventEmitter } = __require("events");
|
|
var safetyCatch = require_safety_catch();
|
|
var NoiseSecretStream = require_secret_stream();
|
|
var b4a = require_b4a();
|
|
var relay = require_blind_relay();
|
|
var NoiseWrap = require_noise_wrap();
|
|
var Announcer = require_announcer();
|
|
var { FIREWALL, ERROR } = require_constants2();
|
|
var { unslabbedHash } = require_crypto();
|
|
var SecurePayload = require_secure_payload();
|
|
var Holepuncher = require_holepuncher();
|
|
var { isPrivate } = require_bogon();
|
|
var { ALREADY_LISTENING, NODE_DESTROYED, KEYPAIR_ALREADY_USED } = require_errors6();
|
|
var HANDSHAKE_CLEAR_WAIT = 1e4;
|
|
var HANDSHAKE_INITIAL_TIMEOUT = 1e4;
|
|
module.exports = class Server extends EventEmitter {
|
|
constructor(dht, opts = {}) {
|
|
super();
|
|
this.dht = dht;
|
|
this.target = null;
|
|
this.closed = false;
|
|
this.firewall = opts.firewall || (() => false);
|
|
this.holepunch = opts.holepunch || (() => true);
|
|
this.relayThrough = opts.relayThrough || null;
|
|
this.relayKeepAlive = opts.relayKeepAlive || 5e3;
|
|
this.pool = opts.pool || null;
|
|
this.createHandshake = opts.createHandshake || defaultCreateHandshake;
|
|
this.createSecretStream = opts.createSecretStream || defaultCreateSecretStream;
|
|
this.suspended = false;
|
|
this.handshakeClearWait = opts.handshakeClearWait || HANDSHAKE_CLEAR_WAIT;
|
|
this._shareLocalAddress = opts.shareLocalAddress !== false;
|
|
this._reusableSocket = !!opts.reusableSocket;
|
|
this._neverPunch = opts.holepunch === false;
|
|
this._keyPair = null;
|
|
this._announcer = null;
|
|
this._connects = /* @__PURE__ */ new Map();
|
|
this._holepunches = [];
|
|
this._listening = null;
|
|
this._closing = null;
|
|
}
|
|
get listening() {
|
|
return this._listening !== null;
|
|
}
|
|
get publicKey() {
|
|
return this._keyPair && this._keyPair.publicKey;
|
|
}
|
|
get relayAddresses() {
|
|
return this._announcer ? this._announcer.relayAddresses : [];
|
|
}
|
|
onconnection(encryptedSocket) {
|
|
this.emit("connection", encryptedSocket);
|
|
}
|
|
async suspend({ log = noop } = {}) {
|
|
log("Suspending hyperdht server");
|
|
if (this._listening !== null) await this._listening;
|
|
log("Suspending hyperdht server (post listening)");
|
|
this.suspended = true;
|
|
this._clearAll();
|
|
return this._announcer ? this._announcer.suspend({ log }) : Promise.resolve();
|
|
}
|
|
async resume() {
|
|
if (this._listening !== null) await this._listening;
|
|
this.suspended = false;
|
|
return this._announcer ? this._announcer.resume() : Promise.resolve();
|
|
}
|
|
address() {
|
|
if (!this._keyPair) return null;
|
|
return {
|
|
publicKey: this._keyPair.publicKey,
|
|
host: this.dht.host,
|
|
port: this.dht.port
|
|
};
|
|
}
|
|
close() {
|
|
if (this._closing) return this._closing;
|
|
this._closing = this._close();
|
|
return this._closing;
|
|
}
|
|
_gc() {
|
|
this.dht.listening.delete(this);
|
|
if (this.target) this.dht._router.delete(this.target);
|
|
}
|
|
async _stopListening() {
|
|
try {
|
|
if (this._announcer) await this._announcer.stop();
|
|
} catch {
|
|
}
|
|
this._announcer = null;
|
|
this._listening = null;
|
|
this._keyPair = null;
|
|
}
|
|
async _close() {
|
|
if (this._listening === null) {
|
|
this.closed = true;
|
|
this.emit("close");
|
|
return;
|
|
}
|
|
try {
|
|
await this._listening;
|
|
} catch {
|
|
}
|
|
this._gc();
|
|
this._clearAll();
|
|
await this._stopListening();
|
|
this.closed = true;
|
|
this.emit("close");
|
|
}
|
|
_clearAll() {
|
|
while (this._holepunches.length > 0) {
|
|
const h = this._holepunches.pop();
|
|
if (h && h.puncher) h.puncher.destroy();
|
|
if (h && h.clearing) clearTimeout(h.clearing);
|
|
if (h && h.prepunching) clearTimeout(h.prepunching);
|
|
if (h && h.rawStream) h.rawStream.destroy();
|
|
}
|
|
this._connects.clear();
|
|
}
|
|
async listen(keyPair = this.dht.defaultKeyPair, opts = {}) {
|
|
if (this._listening !== null) throw ALREADY_LISTENING();
|
|
if (this.dht.destroyed) throw NODE_DESTROYED();
|
|
this._listening = this._listen(keyPair, opts);
|
|
await this._listening;
|
|
return this;
|
|
}
|
|
async _listen(keyPair, opts) {
|
|
this.dht.listening.add(this);
|
|
try {
|
|
await this.dht.bind();
|
|
if (this._closing) return;
|
|
for (const s of this.dht.listening) {
|
|
if (s._keyPair && b4a.equals(s._keyPair.publicKey, keyPair.publicKey)) {
|
|
throw KEYPAIR_ALREADY_USED();
|
|
}
|
|
}
|
|
this.target = unslabbedHash(keyPair.publicKey);
|
|
this._keyPair = keyPair;
|
|
this._announcer = new Announcer(this.dht, keyPair, this.target, opts);
|
|
this.dht._router.set(this.target, {
|
|
relay: null,
|
|
record: this._announcer.record,
|
|
onpeerhandshake: this._onpeerhandshake.bind(this),
|
|
onpeerholepunch: this._onpeerholepunch.bind(this)
|
|
});
|
|
this._localAddresses().catch(safetyCatch);
|
|
await this._announcer.start();
|
|
} catch (err) {
|
|
await this._stopListening();
|
|
this._gc();
|
|
throw err;
|
|
}
|
|
if (this._closing) return;
|
|
if (this.suspended) await this._announcer.suspend();
|
|
if (this._closing) return;
|
|
if (this.dht.destroyed) throw NODE_DESTROYED();
|
|
if (this.pool) this.pool._attachServer(this);
|
|
this.emit("listening");
|
|
}
|
|
refresh() {
|
|
if (this._announcer && !this.suspended) this._announcer.refresh();
|
|
}
|
|
notifyOnline() {
|
|
if (this._announcer) this._announcer.online.notify();
|
|
}
|
|
_localAddresses() {
|
|
return this.dht.validateLocalAddresses(Holepuncher.localAddresses(this.dht.io.serverSocket));
|
|
}
|
|
async _addHandshake(k, noise, clientAddress, { from, to: serverAddress, socket }, direct) {
|
|
let id = this._holepunches.indexOf(null);
|
|
if (id === -1) id = this._holepunches.push(null) - 1;
|
|
const hs = {
|
|
round: 0,
|
|
reply: null,
|
|
puncher: null,
|
|
payload: null,
|
|
rawStream: null,
|
|
encryptedSocket: null,
|
|
prepunching: null,
|
|
firewalled: true,
|
|
clearing: null,
|
|
onsocket: null,
|
|
aborted: false,
|
|
// Relay state
|
|
relayTimeout: null,
|
|
relayToken: null,
|
|
relaySocket: null,
|
|
relayClient: null,
|
|
relayPaired: false
|
|
};
|
|
this._holepunches[id] = hs;
|
|
const handshake = this.createHandshake(this._keyPair, null);
|
|
let remotePayload;
|
|
try {
|
|
remotePayload = await handshake.recv(noise);
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
this._clearLater(hs, id, k);
|
|
return null;
|
|
}
|
|
if (this._closing || this.suspended) return null;
|
|
try {
|
|
hs.firewalled = await this.firewall(handshake.remotePublicKey, remotePayload, clientAddress);
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
}
|
|
if (this._closing || this.suspended) return null;
|
|
if (hs.firewalled) {
|
|
this._clearLater(hs, id, k);
|
|
return null;
|
|
}
|
|
const error = remotePayload.version === 1 ? remotePayload.udx ? ERROR.NONE : ERROR.ABORTED : ERROR.VERSION_MISMATCH;
|
|
const addresses = [];
|
|
const ourRemoteAddr = this.dht.remoteAddress();
|
|
const ourLocalAddrs = this._shareLocalAddress ? await this._localAddresses() : null;
|
|
if (this._closing || this.suspended) return null;
|
|
if (ourRemoteAddr) addresses.push(ourRemoteAddr);
|
|
if (ourLocalAddrs) addresses.push(...ourLocalAddrs);
|
|
if (error === ERROR.NONE) {
|
|
let autoDestroy2 = function() {
|
|
if (hs.puncher) hs.puncher.destroy();
|
|
};
|
|
var autoDestroy = autoDestroy2;
|
|
hs.rawStream = this.dht.createRawStream({
|
|
framed: true,
|
|
firewall(socket2, port, host) {
|
|
if (!(port > 0 && port < 65536)) return true;
|
|
if (hs.relaySocket && isRelay(hs.relaySocket, socket2, port, host)) {
|
|
return false;
|
|
}
|
|
hs.onsocket(socket2, port, host);
|
|
return false;
|
|
}
|
|
});
|
|
hs.rawStream.on("error", autoDestroy2);
|
|
const onrawstreamclose = () => {
|
|
if (this._closing) return;
|
|
this._clearLater(hs, id, k);
|
|
};
|
|
hs.rawStream.on("close", onrawstreamclose);
|
|
hs.onsocket = (socket2, port, host) => {
|
|
if (hs.rawStream === null) return;
|
|
this._clearLater(hs, id, k);
|
|
if (hs.prepunching) {
|
|
clearTimeout(hs.prepunching);
|
|
hs.prepunching = null;
|
|
}
|
|
if (this._reusableSocket && remotePayload.udx.reusableSocket) {
|
|
this.dht._socketPool.routes.add(handshake.remotePublicKey, hs.rawStream);
|
|
}
|
|
hs.rawStream.removeListener("error", autoDestroy2);
|
|
hs.rawStream.removeListener("close", onrawstreamclose);
|
|
if (hs.rawStream.connected) {
|
|
const remoteChanging = hs.rawStream.changeRemote(socket2, remotePayload.udx.id, port, host);
|
|
if (remoteChanging) remoteChanging.catch(safetyCatch);
|
|
} else {
|
|
hs.rawStream.connect(socket2, remotePayload.udx.id, port, host);
|
|
hs.encryptedSocket = this.createSecretStream(false, hs.rawStream, {
|
|
handshake: h,
|
|
keepAlive: this.dht.connectionKeepAlive
|
|
});
|
|
this.onconnection(hs.encryptedSocket);
|
|
}
|
|
if (hs.puncher) {
|
|
hs.puncher.onabort = noop;
|
|
hs.puncher.destroy();
|
|
}
|
|
hs.rawStream = null;
|
|
};
|
|
}
|
|
const relayAddresses = this.relayAddresses;
|
|
const relayThrough = selectRelay(this.relayThrough);
|
|
if (relayThrough) hs.relayToken = relay.token();
|
|
try {
|
|
hs.reply = await handshake.send({
|
|
error,
|
|
firewall: ourRemoteAddr ? FIREWALL.OPEN : FIREWALL.UNKNOWN,
|
|
holepunch: ourRemoteAddr ? null : { id, relays: this._announcer.relays },
|
|
addresses4: addresses,
|
|
addresses6: null,
|
|
udx: {
|
|
reusableSocket: this._reusableSocket,
|
|
id: hs.rawStream ? hs.rawStream.id : 0,
|
|
seq: 0
|
|
},
|
|
secretStream: {},
|
|
relayThrough: relayThrough ? { publicKey: relayThrough, token: hs.relayToken } : null,
|
|
relayAddresses: relayAddresses.length ? relayAddresses : null
|
|
});
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
if (hs.rawStream) hs.rawStream.destroy();
|
|
this._clearLater(hs, id, k);
|
|
return null;
|
|
}
|
|
if (this._closing || this.suspended) {
|
|
if (hs.rawStream) hs.rawStream.destroy();
|
|
return null;
|
|
}
|
|
const h = handshake.final();
|
|
if (error !== ERROR.NONE) {
|
|
if (hs.rawStream) hs.rawStream.destroy();
|
|
this._clearLater(hs, id, k);
|
|
return hs;
|
|
}
|
|
if (remotePayload.firewall === FIREWALL.OPEN || direct) {
|
|
const sock = direct ? socket : this.dht.socket;
|
|
this.dht.stats.punches.open++;
|
|
hs.onsocket(sock, clientAddress.port, clientAddress.host);
|
|
return hs;
|
|
}
|
|
if (relayThrough || remotePayload.relayThrough) {
|
|
this._relayConnection(hs, relayThrough, remotePayload, h);
|
|
}
|
|
const onabort = () => {
|
|
hs.aborted = true;
|
|
if (hs.prepunching) clearTimeout(hs.prepunching);
|
|
hs.prepunching = null;
|
|
if (hs.rawStream.destroyed) {
|
|
this._clearLater(hs, id, k);
|
|
return;
|
|
}
|
|
hs.rawStream.on("close", () => this._clearLater(hs, id, k));
|
|
if (hs.relayToken === null) hs.rawStream.destroy();
|
|
};
|
|
if (!direct && clientAddress.host === serverAddress.host) {
|
|
const clientAddresses = remotePayload.addresses4.filter(onlyPrivateHosts);
|
|
if (clientAddresses.length > 0 && this._shareLocalAddress) {
|
|
const myAddresses = await this._localAddresses();
|
|
const addr = Holepuncher.matchAddress(myAddresses, clientAddresses);
|
|
if (addr) {
|
|
hs.prepunching = setTimeout(onabort, HANDSHAKE_INITIAL_TIMEOUT);
|
|
return hs;
|
|
}
|
|
}
|
|
}
|
|
if (this._closing || this.suspended) return null;
|
|
if (ourRemoteAddr || this._neverPunch) {
|
|
hs.prepunching = setTimeout(onabort, HANDSHAKE_INITIAL_TIMEOUT);
|
|
return hs;
|
|
}
|
|
hs.payload = new SecurePayload(h.holepunchSecret);
|
|
hs.puncher = new Holepuncher(this.dht, this.dht.session(), false, remotePayload.firewall);
|
|
hs.puncher.onconnect = hs.onsocket;
|
|
hs.puncher.onabort = onabort;
|
|
hs.prepunching = setTimeout(hs.puncher.destroy.bind(hs.puncher), HANDSHAKE_INITIAL_TIMEOUT);
|
|
return hs;
|
|
}
|
|
_clearLater(hs, id, k) {
|
|
if (hs.clearing) return;
|
|
hs.clearing = setTimeout(() => this._clear(hs, id, k), this.handshakeClearWait);
|
|
}
|
|
_clear(hs, id, k) {
|
|
if (id >= this._holepunches.length || this._holepunches[id] !== hs) return;
|
|
if (hs.clearing) clearTimeout(hs.clearing);
|
|
this._holepunches[id] = null;
|
|
while (this._holepunches.length > 0 && this._holepunches[this._holepunches.length - 1] === null) {
|
|
this._holepunches.pop();
|
|
}
|
|
this._connects.delete(k);
|
|
}
|
|
async _onpeerhandshake({ noise, peerAddress }, req) {
|
|
const k = b4a.toString(noise, "hex");
|
|
let p = this._connects.get(k);
|
|
if (!p) {
|
|
p = this._addHandshake(k, noise, peerAddress || req.from, req, !peerAddress);
|
|
this._connects.set(k, p);
|
|
}
|
|
const h = await p;
|
|
if (!h) return null;
|
|
if (this._closing !== null || this.suspended) return null;
|
|
return { socket: h.puncher && h.puncher.socket, noise: h.reply };
|
|
}
|
|
async _onpeerholepunch({ id, peerAddress, payload }, req) {
|
|
const h = id < this._holepunches.length ? this._holepunches[id] : null;
|
|
if (!h) return null;
|
|
if (!peerAddress || this._closing !== null || this.suspended) return null;
|
|
const p = h.puncher;
|
|
if (!p || !p.socket) return this._abort(h);
|
|
const remotePayload = h.payload.decrypt(payload);
|
|
if (!remotePayload) return null;
|
|
const isServerRelay = this._announcer.isRelay(req.from);
|
|
const { error, firewall, round, punching, addresses, remoteAddress, remoteToken } = remotePayload;
|
|
if (error !== ERROR.NONE) {
|
|
if (round >= h.round) h.round = round;
|
|
return this._abort(h);
|
|
}
|
|
const token = h.payload.token(peerAddress);
|
|
const echoed = isServerRelay && !!remoteToken && b4a.equals(token, remoteToken);
|
|
if (req.socket === p.socket) {
|
|
p.nat.add(req.to, req.from);
|
|
}
|
|
if (round >= h.round) {
|
|
h.round = round;
|
|
p.updateRemote({ punching, firewall, addresses, verified: echoed ? peerAddress.host : null });
|
|
}
|
|
let stable = await p.analyze(false);
|
|
if (p.destroyed) return null;
|
|
if (!p.remoteHolepunching && !stable) {
|
|
stable = await p.analyze(true);
|
|
if (p.destroyed) return null;
|
|
if (!stable) return this._abort(h);
|
|
}
|
|
if (isConsistent(p.nat.firewall) && remoteAddress && hasSameAddr(p.nat.addresses, remoteAddress)) {
|
|
await p.ping(peerAddress);
|
|
if (p.destroyed) return null;
|
|
}
|
|
if (p.remoteHolepunching) {
|
|
if (!this.holepunch(p.remoteFirewall, p.nat.firewall, p.remoteAddresses, p.nat.addresses)) {
|
|
return p.destroyed ? null : this._abort(h);
|
|
}
|
|
if (h.prepunching) {
|
|
clearTimeout(h.prepunching);
|
|
h.prepunching = null;
|
|
}
|
|
if (p.remoteFirewall >= FIREWALL.RANDOM || p.nat.firewall >= FIREWALL.RANDOM) {
|
|
if (this.dht._randomPunches >= this.dht._randomPunchLimit || Date.now() - this.dht._lastRandomPunch < this.dht._randomPunchInterval) {
|
|
if (!h.relayToken) return this._abort(h, ERROR.TRY_LATER);
|
|
return {
|
|
socket: p.socket,
|
|
payload: h.payload.encrypt({
|
|
error: ERROR.TRY_LATER,
|
|
firewall: p.nat.firewall,
|
|
round: h.round,
|
|
connected: p.connected,
|
|
punching: p.punching,
|
|
addresses: p.nat.addresses,
|
|
remoteAddress: null,
|
|
token: isServerRelay ? token : null,
|
|
remoteToken: remotePayload.token
|
|
})
|
|
};
|
|
}
|
|
}
|
|
const punching2 = await p.punch();
|
|
if (p.destroyed) return null;
|
|
if (!punching2) return this._abort(h);
|
|
}
|
|
if (p.nat.firewall !== FIREWALL.UNKNOWN) {
|
|
p.nat.freeze();
|
|
}
|
|
return {
|
|
socket: p.socket,
|
|
payload: h.payload.encrypt({
|
|
error: ERROR.NONE,
|
|
firewall: p.nat.firewall,
|
|
round: h.round,
|
|
connected: p.connected,
|
|
punching: p.punching,
|
|
addresses: p.nat.addresses,
|
|
remoteAddress: null,
|
|
token: isServerRelay ? token : null,
|
|
remoteToken: remotePayload.token
|
|
})
|
|
};
|
|
}
|
|
_abort(h, error = ERROR.ABORTED) {
|
|
if (!h.payload) {
|
|
if (h.puncher) h.puncher.destroy();
|
|
return null;
|
|
}
|
|
const payload = h.payload.encrypt({
|
|
error,
|
|
firewall: FIREWALL.UNKNOWN,
|
|
round: h.round,
|
|
connected: false,
|
|
punching: false,
|
|
addresses: null,
|
|
remoteAddress: null,
|
|
token: null,
|
|
remoteToken: null
|
|
});
|
|
h.puncher.destroy();
|
|
return { socket: this.dht.socket, payload };
|
|
}
|
|
_relayConnection(hs, relayThrough, remotePayload, h) {
|
|
this.dht.stats.relaying.attempts++;
|
|
let isInitiator;
|
|
let publicKey;
|
|
let token;
|
|
if (relayThrough) {
|
|
isInitiator = true;
|
|
publicKey = relayThrough;
|
|
token = hs.relayToken;
|
|
} else {
|
|
isInitiator = false;
|
|
publicKey = remotePayload.relayThrough.publicKey;
|
|
token = remotePayload.relayThrough.token;
|
|
}
|
|
hs.relayToken = token;
|
|
hs.relaySocket = this.dht.connect(publicKey);
|
|
hs.relaySocket.setKeepAlive(this.relayKeepAlive);
|
|
hs.relayClient = relay.Client.from(hs.relaySocket, { id: hs.relaySocket.publicKey });
|
|
hs.relayTimeout = setTimeout(onabort, 15e3);
|
|
hs.relayClient.pair(isInitiator, token, hs.rawStream).on("error", onabort).on("data", (remoteId) => {
|
|
if (hs.relayTimeout) clearRelayTimeout(hs);
|
|
if (hs.rawStream === null) {
|
|
onabort(null);
|
|
return;
|
|
}
|
|
hs.relayPaired = true;
|
|
this.dht.stats.relaying.successes++;
|
|
if (hs.prepunching) clearTimeout(hs.prepunching);
|
|
hs.prepunching = null;
|
|
const { remotePort, remoteHost, socket } = hs.relaySocket.rawStream;
|
|
hs.rawStream.on("close", () => hs.relaySocket.destroy()).connect(socket, remoteId, remotePort, remoteHost);
|
|
hs.encryptedSocket = this.createSecretStream(false, hs.rawStream, { handshake: h });
|
|
this.onconnection(hs.encryptedSocket);
|
|
});
|
|
const dht = this.dht;
|
|
function onabort() {
|
|
if (!hs.relayPaired) dht.stats.relaying.aborts++;
|
|
if (hs.relayTimeout) clearRelayTimeout(hs);
|
|
const socket = hs.relaySocket;
|
|
hs.relayToken = null;
|
|
hs.relaySocket = null;
|
|
if (socket) socket.destroy();
|
|
if (hs.aborted && hs.rawStream) hs.rawStream.destroy();
|
|
}
|
|
}
|
|
};
|
|
function clearRelayTimeout(hs) {
|
|
clearTimeout(hs.relayTimeout);
|
|
hs.relayTimeout = null;
|
|
}
|
|
function isConsistent(fw) {
|
|
return fw === FIREWALL.OPEN || fw === FIREWALL.CONSISTENT;
|
|
}
|
|
function hasSameAddr(addrs, other) {
|
|
if (addrs === null) return false;
|
|
for (const addr of addrs) {
|
|
if (addr.port === other.port && addr.host === other.host) return true;
|
|
}
|
|
return false;
|
|
}
|
|
function defaultCreateHandshake(keyPair, remotePublicKey) {
|
|
return new NoiseWrap(keyPair, remotePublicKey);
|
|
}
|
|
function defaultCreateSecretStream(isInitiator, rawStream, opts) {
|
|
return new NoiseSecretStream(isInitiator, rawStream, opts);
|
|
}
|
|
function onlyPrivateHosts(addr) {
|
|
return isPrivate(addr.host);
|
|
}
|
|
function isRelay(relaySocket, socket, port, host) {
|
|
const stream = relaySocket.rawStream;
|
|
if (!stream) return false;
|
|
if (stream.socket !== socket) return false;
|
|
return port === stream.remotePort && host === stream.remoteHost;
|
|
}
|
|
function selectRelay(relayThrough) {
|
|
if (typeof relayThrough === "function") relayThrough = relayThrough();
|
|
if (relayThrough === null) return null;
|
|
if (Array.isArray(relayThrough)) {
|
|
return relayThrough[Math.floor(Math.random() * relayThrough.length)];
|
|
}
|
|
return relayThrough;
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/semaphore.js
|
|
var require_semaphore = __commonJS({
|
|
"../../node_modules/hyperdht/lib/semaphore.js"(exports, module) {
|
|
var DONE = Promise.resolve(true);
|
|
var DESTROYED = Promise.resolve(false);
|
|
module.exports = class Semaphore {
|
|
constructor(limit = 1) {
|
|
this.limit = limit;
|
|
this.active = 0;
|
|
this.waiting = [];
|
|
this.flushedPromise = null;
|
|
this.flushedResolve = null;
|
|
this.destroyed = false;
|
|
this._onwait = this._queueWaiting.bind(this);
|
|
this._onflush = this._queueFlushed.bind(this);
|
|
}
|
|
_queueWaiting(resolve) {
|
|
this.waiting.push(resolve);
|
|
}
|
|
_queueFlushed(resolve) {
|
|
this.flushedResolve = resolve;
|
|
}
|
|
wait() {
|
|
if (this.destroyed === true) return DESTROYED;
|
|
if (this.active < this.limit && this.waiting.length === 0) {
|
|
this.active++;
|
|
return DONE;
|
|
}
|
|
return new Promise(this._onwait);
|
|
}
|
|
signal() {
|
|
if (this.destroyed === true) return;
|
|
this.active--;
|
|
while (this.active < this.limit && this.waiting.length > 0 && this.destroyed === false) {
|
|
this.active++;
|
|
this.waiting.shift()(true);
|
|
}
|
|
if (this.active === 0 && this.flushedResolve) {
|
|
const resolve = this.flushedResolve;
|
|
this.flushedResolve = null;
|
|
this.flushedPromise = null;
|
|
resolve(true);
|
|
}
|
|
}
|
|
async flush() {
|
|
if (this.destroyed === true) return;
|
|
if (this.active === 0) return;
|
|
if (this.flushedPromise) return this.flushedPromise;
|
|
this.flushedPromise = new Promise(this._onflush);
|
|
return this.flushedPromise;
|
|
}
|
|
destroy() {
|
|
this.destroyed = true;
|
|
this.active = 0;
|
|
while (this.waiting.length) this.waiting.pop()(false);
|
|
if (this.flushedResolve) this.flushedResolve(false);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/connect.js
|
|
var require_connect = __commonJS({
|
|
"../../node_modules/hyperdht/lib/connect.js"(exports, module) {
|
|
var NoiseSecretStream = require_secret_stream();
|
|
var b4a = require_b4a();
|
|
var relay = require_blind_relay();
|
|
var { isReserved, isBogon } = require_bogon();
|
|
var safetyCatch = require_safety_catch();
|
|
var unslab = require_unslab();
|
|
var Semaphore = require_semaphore();
|
|
var NoiseWrap = require_noise_wrap();
|
|
var SecurePayload = require_secure_payload();
|
|
var Holepuncher = require_holepuncher();
|
|
var Sleeper = require_sleeper();
|
|
var { FIREWALL, ERROR } = require_constants2();
|
|
var { unslabbedHash } = require_crypto();
|
|
var {
|
|
CANNOT_HOLEPUNCH,
|
|
HANDSHAKE_INVALID,
|
|
HOLEPUNCH_ABORTED,
|
|
HOLEPUNCH_INVALID,
|
|
HOLEPUNCH_PROBE_TIMEOUT,
|
|
HOLEPUNCH_DOUBLE_RANDOMIZED_NATS,
|
|
PEER_CONNECTION_FAILED,
|
|
PEER_NOT_FOUND,
|
|
REMOTE_ABORTED,
|
|
REMOTE_NOT_HOLEPUNCHABLE,
|
|
REMOTE_NOT_HOLEPUNCHING,
|
|
SERVER_ERROR,
|
|
SERVER_INCOMPATIBLE,
|
|
RELAY_ABORTED,
|
|
SUSPENDED
|
|
} = require_errors6();
|
|
module.exports = function connect(dht, publicKey, opts = {}) {
|
|
const pool = opts.pool || null;
|
|
if (pool && pool.has(publicKey)) return pool.get(publicKey);
|
|
publicKey = unslab(publicKey);
|
|
const keyPair = opts.keyPair || dht.defaultKeyPair;
|
|
const relayThrough = selectRelay(opts.relayThrough || null);
|
|
const encryptedSocket = (opts.createSecretStream || defaultCreateSecretStream)(true, null, {
|
|
publicKey: keyPair.publicKey,
|
|
remotePublicKey: publicKey,
|
|
autoStart: false,
|
|
keepAlive: dht.connectionKeepAlive
|
|
});
|
|
if (dht.suspended || !dht._connectable) {
|
|
encryptedSocket.destroy(SUSPENDED());
|
|
return encryptedSocket;
|
|
}
|
|
if (pool) pool._attachStream(encryptedSocket, false);
|
|
const id = b4a.toString(publicKey, "hex");
|
|
const c = {
|
|
id,
|
|
dht,
|
|
session: dht.session(),
|
|
relayAddresses: opts.relayAddresses || [],
|
|
remoteRelayAddresses: [],
|
|
pool,
|
|
round: 0,
|
|
target: unslabbedHash(publicKey),
|
|
remotePublicKey: publicKey,
|
|
reusableSocket: !!opts.reusableSocket,
|
|
handshake: (opts.createHandshake || defaultCreateHandshake)(keyPair, publicKey),
|
|
request: null,
|
|
requesting: false,
|
|
lan: opts.localConnection !== false,
|
|
firewall: FIREWALL.UNKNOWN,
|
|
rawStream: dht.createRawStream({ framed: true, firewall }),
|
|
connect: null,
|
|
query: null,
|
|
puncher: null,
|
|
payload: null,
|
|
passiveConnectTimeout: null,
|
|
serverSocket: null,
|
|
serverAddress: null,
|
|
onsocket: null,
|
|
sleeper: new Sleeper(),
|
|
encryptedSocket,
|
|
// Relay state
|
|
relayTimeout: null,
|
|
relayThrough,
|
|
relayToken: relayThrough ? relay.token() : null,
|
|
relaySocket: null,
|
|
relayClient: null,
|
|
relayPaired: false,
|
|
relayKeepAlive: opts.relayKeepAlive || 5e3
|
|
};
|
|
c.rawStream.on("error", autoDestroy);
|
|
c.rawStream.once("connect", () => {
|
|
c.rawStream.removeListener("error", autoDestroy);
|
|
});
|
|
encryptedSocket.on("close", function() {
|
|
if (c.passiveConnectTimeout) clearPassiveConnectTimeout(c);
|
|
if (c.query) c.query.destroy();
|
|
if (c.puncher) c.puncher.destroy();
|
|
if (c.rawStream) c.rawStream.destroy();
|
|
c.session.destroy();
|
|
c.sleeper.resume();
|
|
});
|
|
if (dht.suspended) encryptedSocket.destroy(SUSPENDED());
|
|
else connectAndHolepunch(c, opts);
|
|
return encryptedSocket;
|
|
function autoDestroy(err) {
|
|
maybeDestroyEncryptedSocket(c, err);
|
|
}
|
|
function firewall(socket, port, host) {
|
|
if (c.relaySocket && isRelay(c.relaySocket, socket, port, host)) {
|
|
return false;
|
|
}
|
|
if (c.onsocket) {
|
|
c.onsocket(socket, port, host);
|
|
} else {
|
|
c.serverSocket = socket;
|
|
c.serverAddress = { port, host };
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
function isDone(c) {
|
|
if (c.encryptedSocket.destroying || !!(c.puncher && c.puncher.connected)) {
|
|
return true;
|
|
}
|
|
if (c.encryptedSocket.rawStream === null) {
|
|
return false;
|
|
}
|
|
if (c.relaySocket && !!(c.puncher && !c.puncher.connected && !c.puncher.destroyed)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
async function retryRoute(c, route) {
|
|
const ref = c.dht._socketPool.lookup(route.socket);
|
|
if (!ref) {
|
|
if (route.socket === c.dht.socket) {
|
|
await connectThroughNode(c, route.address, c.dht.socket);
|
|
}
|
|
return;
|
|
}
|
|
ref.active();
|
|
try {
|
|
await connectThroughNode(c, route.address, route.socket);
|
|
} catch {
|
|
}
|
|
ref.inactive();
|
|
}
|
|
async function connectAndHolepunch(c, opts) {
|
|
const route = c.reusableSocket ? c.dht._socketPool.routes.get(c.remotePublicKey) : null;
|
|
if (route) {
|
|
await retryRoute(c, route);
|
|
if (isDone(c)) return;
|
|
}
|
|
await findAndConnect(c, opts);
|
|
if (isDone(c)) return;
|
|
if (!c.connect) {
|
|
maybeDestroyEncryptedSocket(c, HANDSHAKE_INVALID());
|
|
return;
|
|
}
|
|
await holepunch(c, opts);
|
|
}
|
|
function getFirstRemoteAddress(addrs, serverAddress) {
|
|
for (const addr of addrs) {
|
|
if (isBogon(addr.host)) continue;
|
|
return addr;
|
|
}
|
|
return serverAddress;
|
|
}
|
|
async function holepunch(c, opts) {
|
|
let { relayAddress, serverAddress, clientAddress, payload } = c.connect;
|
|
const remoteHolepunchable = !!(payload.holepunch && payload.holepunch.relays.length);
|
|
const relayed = diffAddress(serverAddress, relayAddress);
|
|
if (payload.firewall === FIREWALL.OPEN || relayed && !remoteHolepunchable) {
|
|
const addr = getFirstRemoteAddress(payload.addresses4, serverAddress);
|
|
if (addr) {
|
|
const socket = c.dht.socket;
|
|
c.dht.stats.punches.open++;
|
|
c.onsocket(socket, addr.port, addr.host);
|
|
return;
|
|
}
|
|
}
|
|
const onabort = () => {
|
|
c.session.destroy();
|
|
maybeDestroyEncryptedSocket(c, HOLEPUNCH_ABORTED());
|
|
};
|
|
if (c.firewall === FIREWALL.OPEN) {
|
|
c.passiveConnectTimeout = setTimeout(onabort, 1e4);
|
|
return;
|
|
}
|
|
if (c.lan && relayed && clientAddress.host === serverAddress.host) {
|
|
const serverAddresses = payload.addresses4.filter(onlyNonReserved);
|
|
if (serverAddresses.length > 0) {
|
|
const myAddresses = Holepuncher.localAddresses(c.dht.io.serverSocket);
|
|
const addr = Holepuncher.matchAddress(myAddresses, serverAddresses) || serverAddresses[0];
|
|
const socket = c.dht.io.serverSocket;
|
|
try {
|
|
await c.dht.ping(addr);
|
|
} catch {
|
|
maybeDestroyEncryptedSocket(c, HOLEPUNCH_ABORTED());
|
|
return;
|
|
}
|
|
c.onsocket(socket, addr.port, addr.host);
|
|
return;
|
|
}
|
|
}
|
|
if (!remoteHolepunchable) {
|
|
maybeDestroyEncryptedSocket(c, CANNOT_HOLEPUNCH());
|
|
return;
|
|
}
|
|
c.puncher = new Holepuncher(c.dht, c.session, true, payload.firewall);
|
|
c.puncher.onconnect = c.onsocket;
|
|
c.puncher.onabort = onabort;
|
|
const serverRelay = pickServerRelay(payload.holepunch.relays, relayAddress);
|
|
let probe;
|
|
try {
|
|
probe = await probeRound(c, opts.fastOpen === false ? null : serverAddress, serverRelay, true);
|
|
} catch (err) {
|
|
destroyPuncher(c);
|
|
maybeDestroyEncryptedSocket(c, err);
|
|
return;
|
|
}
|
|
if (isDone(c) || !probe) return;
|
|
const { token, peerAddress } = probe;
|
|
if (!diffAddress(serverRelay.relayAddress, relayAddress) && diffAddress(serverAddress, peerAddress)) {
|
|
serverAddress = peerAddress;
|
|
await c.puncher.openSession(serverAddress);
|
|
if (isDone(c)) return;
|
|
}
|
|
if (opts.holepunch && !opts.holepunch(
|
|
c.puncher.remoteFirewall,
|
|
c.puncher.nat.firewall,
|
|
c.puncher.remoteAddresses,
|
|
c.puncher.nat.addresses
|
|
)) {
|
|
await abort(c, serverRelay, HOLEPUNCH_ABORTED("Client aborted holepunch"));
|
|
return;
|
|
}
|
|
try {
|
|
await roundPunch(c, serverAddress, token, relayAddress, serverRelay, false);
|
|
} catch (err) {
|
|
destroyPuncher(c);
|
|
maybeDestroyEncryptedSocket(c, err);
|
|
}
|
|
}
|
|
async function findAndConnect(c, opts) {
|
|
let attempts = 0;
|
|
let closestNodes = opts.relayAddresses && opts.relayAddresses.length ? opts.relayAddresses : null;
|
|
if (!closestNodes) {
|
|
const cachedRelayAddresses = c.dht._relayAddressesCache.get(c.id);
|
|
if (cachedRelayAddresses) closestNodes = cachedRelayAddresses;
|
|
}
|
|
if (c.dht._persistent) {
|
|
const route = c.dht._router.get(c.target);
|
|
if (route && route.relay !== null) {
|
|
closestNodes = [{ host: route.relay.host, port: route.relay.port }];
|
|
}
|
|
}
|
|
const sem = new Semaphore(2);
|
|
const signal = sem.signal.bind(sem);
|
|
const tries = closestNodes !== null ? 2 : 1;
|
|
try {
|
|
for (let i = 0; i < tries && !isDone(c) && !c.connect; i++) {
|
|
c.query = c.dht.findPeer(c.target, {
|
|
hash: false,
|
|
session: c.session,
|
|
closestNodes,
|
|
onlyClosestNodes: closestNodes !== null,
|
|
retries: closestNodes ? 1 : 3
|
|
});
|
|
for await (const data of c.query) {
|
|
await sem.wait();
|
|
if (isDone(c)) return;
|
|
if (c.connect) {
|
|
sem.signal();
|
|
break;
|
|
}
|
|
c.remoteRelayAddresses.push(data.from);
|
|
attempts++;
|
|
connectThroughNode(c, data.from, null).then(signal, signal);
|
|
}
|
|
closestNodes = null;
|
|
if (attempts > 0) await sem.flush();
|
|
}
|
|
c.query = null;
|
|
if (isDone(c)) return;
|
|
await sem.flush();
|
|
if (isDone(c)) return;
|
|
} catch (err) {
|
|
c.query = null;
|
|
maybeDestroyEncryptedSocket(c, err);
|
|
return;
|
|
}
|
|
if (!c.connect) {
|
|
maybeDestroyEncryptedSocket(c, attempts ? PEER_CONNECTION_FAILED() : PEER_NOT_FOUND());
|
|
}
|
|
}
|
|
async function connectThroughNode(c, address, socket) {
|
|
if (!c.requesting) {
|
|
const addr = c.dht.remoteAddress();
|
|
const localAddrs = c.lan ? Holepuncher.localAddresses(c.dht.io.serverSocket) : null;
|
|
const addresses4 = [];
|
|
if (addr) addresses4.push(addr);
|
|
if (localAddrs) addresses4.push(...localAddrs);
|
|
c.firewall = addr ? FIREWALL.OPEN : FIREWALL.UNKNOWN;
|
|
c.requesting = true;
|
|
c.request = await c.handshake.send({
|
|
error: ERROR.NONE,
|
|
firewall: c.firewall,
|
|
holepunch: null,
|
|
addresses4,
|
|
addresses6: [],
|
|
udx: {
|
|
reusableSocket: c.reusableSocket,
|
|
id: c.rawStream.id,
|
|
seq: 0
|
|
},
|
|
secretStream: {},
|
|
relayThrough: c.relayThrough ? { publicKey: c.relayThrough, token: c.relayToken } : null
|
|
});
|
|
if (isDone(c)) return;
|
|
}
|
|
const { serverAddress, clientAddress, relayed, noise } = await c.dht._router.peerHandshake(
|
|
c.target,
|
|
{ noise: c.request, socket, session: c.session },
|
|
address
|
|
);
|
|
if (isDone(c) || c.connect) return;
|
|
const payload = await c.handshake.recv(noise);
|
|
if (isDone(c) || !payload) return;
|
|
if (payload.version !== 1) {
|
|
maybeDestroyEncryptedSocket(c, SERVER_INCOMPATIBLE());
|
|
return;
|
|
}
|
|
if (payload.error !== ERROR.NONE) {
|
|
maybeDestroyEncryptedSocket(c, SERVER_ERROR());
|
|
return;
|
|
}
|
|
if (!payload.udx) {
|
|
maybeDestroyEncryptedSocket(c, SERVER_ERROR("Server did not send UDX data"));
|
|
return;
|
|
}
|
|
const hs = c.handshake.final();
|
|
c.handshake = null;
|
|
c.request = null;
|
|
c.requesting = false;
|
|
c.connect = {
|
|
relayed,
|
|
relayAddress: address,
|
|
clientAddress,
|
|
serverAddress,
|
|
payload
|
|
};
|
|
c.payload = new SecurePayload(hs.holepunchSecret);
|
|
c.onsocket = function(socket2, port, host) {
|
|
if (c.rawStream === null) return;
|
|
if (c.rawStream.connected) {
|
|
const remoteChanging = c.rawStream.changeRemote(socket2, c.connect.payload.udx.id, port, host);
|
|
if (remoteChanging) remoteChanging.catch(safetyCatch);
|
|
} else {
|
|
if (payload.relayAddresses && payload.relayAddresses.length) {
|
|
c.dht._relayAddressesCache.set(c.id, payload.relayAddresses);
|
|
} else if (c.remoteRelayAddresses.length) {
|
|
c.dht._relayAddressesCache.set(c.id, c.remoteRelayAddresses);
|
|
}
|
|
c.rawStream.connect(socket2, c.connect.payload.udx.id, port, host);
|
|
c.encryptedSocket.start(c.rawStream, { handshake: hs });
|
|
}
|
|
if (c.reusableSocket && payload.udx.reusableSocket) {
|
|
c.dht._socketPool.routes.add(c.remotePublicKey, c.rawStream);
|
|
}
|
|
if (c.puncher) {
|
|
c.puncher.onabort = noop;
|
|
c.puncher.destroy();
|
|
}
|
|
if (c.passiveConnectTimeout) {
|
|
clearPassiveConnectTimeout(c);
|
|
}
|
|
c.rawStream = null;
|
|
};
|
|
if (payload.relayThrough || c.relayThrough) {
|
|
relayConnection(c, c.relayThrough, payload, hs);
|
|
}
|
|
if (c.serverSocket) {
|
|
c.onsocket(c.serverSocket, c.serverAddress.port, c.serverAddress.host);
|
|
return;
|
|
}
|
|
if (!relayed) {
|
|
c.onsocket(socket || c.dht.socket, address.port, address.host);
|
|
}
|
|
c.session.destroy();
|
|
}
|
|
async function updateHolepunch(c, peerAddress, relayAddr, payload) {
|
|
const holepunch2 = await c.dht._router.peerHolepunch(
|
|
c.target,
|
|
{
|
|
id: c.connect.payload.holepunch.id,
|
|
payload: c.payload.encrypt(payload),
|
|
peerAddress,
|
|
socket: c.puncher.socket,
|
|
session: c.session
|
|
},
|
|
relayAddr
|
|
);
|
|
if (isDone(c)) return null;
|
|
const remotePayload = c.payload.decrypt(holepunch2.payload);
|
|
if (!remotePayload) {
|
|
throw HOLEPUNCH_INVALID();
|
|
}
|
|
const { error, firewall, punching, addresses, remoteToken } = remotePayload;
|
|
if (error === ERROR.TRY_LATER && c.relayToken && payload.punching) {
|
|
return {
|
|
tryLater: true,
|
|
...holepunch2,
|
|
payload: remotePayload
|
|
};
|
|
}
|
|
if (error !== ERROR.NONE) {
|
|
throw REMOTE_ABORTED("Remote aborted with error code " + error);
|
|
}
|
|
const echoed = !!(remoteToken && payload.token && b4a.equals(remoteToken, payload.token));
|
|
c.puncher.updateRemote({
|
|
punching,
|
|
firewall,
|
|
addresses,
|
|
verified: echoed ? peerAddress.host : null
|
|
});
|
|
return {
|
|
tryLater: false,
|
|
...holepunch2,
|
|
payload: remotePayload
|
|
};
|
|
}
|
|
async function probeRound(c, serverAddress, serverRelay, retry) {
|
|
if (serverAddress) await c.puncher.openSession(serverAddress);
|
|
if (isDone(c)) return null;
|
|
const reply = await updateHolepunch(c, serverRelay.peerAddress, serverRelay.relayAddress, {
|
|
error: ERROR.NONE,
|
|
firewall: c.puncher.nat.firewall,
|
|
round: c.round++,
|
|
connected: false,
|
|
punching: false,
|
|
addresses: c.puncher.nat.addresses,
|
|
remoteAddress: serverAddress,
|
|
token: null,
|
|
remoteToken: null
|
|
});
|
|
if (isDone(c) || !reply) return null;
|
|
const { peerAddress } = reply;
|
|
const { address, token } = reply.payload;
|
|
c.puncher.nat.add(reply.to, reply.from);
|
|
if (c.puncher.remoteFirewall < FIREWALL.RANDOM && address && address.host && address.port && diffAddress(address, serverAddress)) {
|
|
await c.puncher.openSession(address);
|
|
if (isDone(c)) return null;
|
|
}
|
|
if (c.puncher.remoteFirewall === FIREWALL.UNKNOWN) {
|
|
await c.sleeper.pause(1e3);
|
|
if (isDone(c)) return null;
|
|
}
|
|
let stable = await c.puncher.analyze(false);
|
|
if (isDone(c)) return null;
|
|
if (!stable) {
|
|
stable = await c.puncher.analyze(true);
|
|
if (isDone(c)) return null;
|
|
if (stable) return probeRound(c, serverAddress, serverRelay, false);
|
|
}
|
|
if ((c.puncher.remoteFirewall === FIREWALL.UNKNOWN || !token) && retry) {
|
|
return probeRound(c, serverAddress, serverRelay, false);
|
|
}
|
|
if (c.puncher.remoteFirewall === FIREWALL.UNKNOWN || c.puncher.nat.firewall === FIREWALL.UNKNOWN) {
|
|
await abort(c, serverRelay, HOLEPUNCH_PROBE_TIMEOUT());
|
|
return null;
|
|
}
|
|
if (c.puncher.remoteFirewall >= FIREWALL.RANDOM && c.puncher.nat.firewall >= FIREWALL.RANDOM) {
|
|
await abort(c, serverRelay, HOLEPUNCH_DOUBLE_RANDOMIZED_NATS());
|
|
return null;
|
|
}
|
|
return { token, peerAddress };
|
|
}
|
|
async function roundPunch(c, serverAddress, remoteToken, clientRelay, serverRelay, delayed) {
|
|
c.puncher.nat.freeze();
|
|
const isRandom = c.puncher.remoteFirewall >= FIREWALL.RANDOM || c.puncher.nat.firewall >= FIREWALL.RANDOM;
|
|
if (isRandom) {
|
|
while (c.dht._randomPunches >= c.dht._randomPunchLimit || Date.now() - c.dht._lastRandomPunch < c.dht._randomPunchInterval) {
|
|
if (!c.relayToken) throw HOLEPUNCH_ABORTED();
|
|
if (!delayed) {
|
|
delayed = true;
|
|
await updateHolepunch(c, serverAddress, clientRelay, {
|
|
error: ERROR.NONE,
|
|
firewall: c.puncher.nat.firewall,
|
|
round: c.round++,
|
|
connected: false,
|
|
punching: false,
|
|
addresses: c.puncher.nat.addresses,
|
|
remoteAddress: null,
|
|
token: c.payload.token(serverAddress),
|
|
remoteToken
|
|
});
|
|
if (isDone(c)) return;
|
|
}
|
|
await tryLater(c);
|
|
if (isDone(c)) return;
|
|
}
|
|
}
|
|
if (isRandom) c.dht._randomPunches++;
|
|
let reply;
|
|
try {
|
|
reply = await updateHolepunch(
|
|
c,
|
|
delayed ? serverRelay.peerAddress : serverAddress,
|
|
delayed ? serverRelay.relayAddress : clientRelay,
|
|
{
|
|
error: ERROR.NONE,
|
|
firewall: c.puncher.nat.firewall,
|
|
round: c.round++,
|
|
connected: false,
|
|
punching: true,
|
|
addresses: c.puncher.nat.addresses,
|
|
remoteAddress: null,
|
|
token: delayed ? null : c.payload.token(serverAddress),
|
|
remoteToken
|
|
}
|
|
);
|
|
} finally {
|
|
if (isRandom) c.dht._randomPunches--;
|
|
}
|
|
if (isDone(c)) return;
|
|
if (!reply) return;
|
|
if (reply.tryLater) {
|
|
await tryLater(c);
|
|
if (isDone(c)) return;
|
|
return roundPunch(c, serverAddress, remoteToken, clientRelay, serverRelay, true);
|
|
}
|
|
if (!c.puncher.remoteHolepunching) {
|
|
throw REMOTE_NOT_HOLEPUNCHING();
|
|
}
|
|
if (!await c.puncher.punch()) {
|
|
throw REMOTE_NOT_HOLEPUNCHABLE();
|
|
}
|
|
}
|
|
async function tryLater(c) {
|
|
if (!c.relayToken) throw HOLEPUNCH_ABORTED();
|
|
await c.sleeper.pause(1e4 + Math.round(Math.random() * 1e4));
|
|
}
|
|
function maybeDestroyEncryptedSocket(c, err) {
|
|
if (isDone(c)) return;
|
|
if (c.encryptedSocket.rawStream) return;
|
|
if (c.relaySocket) return;
|
|
if (c.puncher && !c.puncher.destroyed) return;
|
|
c.session.destroy();
|
|
c.encryptedSocket.destroy(err);
|
|
}
|
|
async function abort(c, { peerAddress, relayAddress }, err) {
|
|
try {
|
|
await updateHolepunch(peerAddress, relayAddress, {
|
|
error: ERROR.ABORTED,
|
|
firewall: FIREWALL.UNKNOWN,
|
|
round: c.round++,
|
|
connected: false,
|
|
punching: false,
|
|
addresses: null,
|
|
remoteAddress: null,
|
|
token: null,
|
|
remoteToken: null
|
|
});
|
|
} catch {
|
|
}
|
|
destroyPuncher(c);
|
|
maybeDestroyEncryptedSocket(c, err);
|
|
}
|
|
function relayConnection(c, relayThrough, payload, hs) {
|
|
let isInitiator;
|
|
let publicKey;
|
|
let token;
|
|
if (payload.relayThrough) {
|
|
isInitiator = false;
|
|
publicKey = payload.relayThrough.publicKey;
|
|
token = payload.relayThrough.token;
|
|
} else {
|
|
isInitiator = true;
|
|
publicKey = relayThrough;
|
|
token = c.relayToken;
|
|
}
|
|
c.relayToken = token;
|
|
c.relaySocket = c.dht.connect(publicKey);
|
|
c.relaySocket.setKeepAlive(c.relayKeepAlive);
|
|
c.relayClient = relay.Client.from(c.relaySocket, { id: c.relaySocket.publicKey });
|
|
c.relayTimeout = setTimeout(onabort, 15e3, null);
|
|
c.relayClient.pair(isInitiator, token, c.rawStream).on("error", onabort).on("data", ondata);
|
|
function ondata(remoteId) {
|
|
if (c.relayTimeout) clearRelayTimeout(c);
|
|
if (c.rawStream === null) {
|
|
onabort(null);
|
|
return;
|
|
}
|
|
c.relayPaired = true;
|
|
const { remotePort, remoteHost, socket } = c.relaySocket.rawStream;
|
|
c.rawStream.on("close", () => c.relaySocket.destroy()).connect(socket, remoteId, remotePort, remoteHost);
|
|
c.encryptedSocket.start(c.rawStream, { handshake: hs });
|
|
}
|
|
function onabort(err) {
|
|
if (c.relayTimeout) clearRelayTimeout(c);
|
|
const socket = c.relaySocket;
|
|
c.relayToken = null;
|
|
c.relaySocket = null;
|
|
if (socket) socket.destroy();
|
|
maybeDestroyEncryptedSocket(c, err || RELAY_ABORTED());
|
|
}
|
|
}
|
|
function clearPassiveConnectTimeout(c) {
|
|
clearTimeout(c.passiveConnectTimeout);
|
|
c.passiveConnectTimeout = null;
|
|
}
|
|
function clearRelayTimeout(c) {
|
|
clearTimeout(c.relayTimeout);
|
|
c.relayTimeout = null;
|
|
}
|
|
function destroyPuncher(c) {
|
|
if (c.puncher) c.puncher.destroy();
|
|
c.session.destroy();
|
|
}
|
|
function pickServerRelay(relays, clientRelay) {
|
|
for (const r of relays) {
|
|
if (!diffAddress(r.relayAddress, clientRelay)) return r;
|
|
}
|
|
return relays[0];
|
|
}
|
|
function diffAddress(a, b) {
|
|
return a.host !== b.host || a.port !== b.port;
|
|
}
|
|
function defaultCreateHandshake(keyPair, remotePublicKey) {
|
|
return new NoiseWrap(keyPair, remotePublicKey);
|
|
}
|
|
function defaultCreateSecretStream(isInitiator, rawStream, opts) {
|
|
return new NoiseSecretStream(isInitiator, rawStream, opts);
|
|
}
|
|
function onlyNonReserved(addr) {
|
|
return !isReserved(addr.host);
|
|
}
|
|
function isRelay(relaySocket, socket, port, host) {
|
|
const stream = relaySocket.rawStream;
|
|
if (!stream) return false;
|
|
if (stream.socket !== socket) return false;
|
|
return port === stream.remotePort && host === stream.remoteHost;
|
|
}
|
|
function selectRelay(relayThrough) {
|
|
if (typeof relayThrough === "function") relayThrough = relayThrough();
|
|
if (relayThrough === null) return null;
|
|
if (Array.isArray(relayThrough))
|
|
return relayThrough[Math.floor(Math.random() * relayThrough.length)];
|
|
return relayThrough;
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/raw-stream-set.js
|
|
var require_raw_stream_set = __commonJS({
|
|
"../../node_modules/hyperdht/lib/raw-stream-set.js"(exports, module) {
|
|
module.exports = class RawStreamSet {
|
|
constructor(dht) {
|
|
this._dht = dht;
|
|
this._prefix = 16 - 1;
|
|
this._streams = /* @__PURE__ */ new Map();
|
|
}
|
|
get size() {
|
|
return this._streams.size;
|
|
}
|
|
[Symbol.iterator]() {
|
|
return this._streams.values();
|
|
}
|
|
add(opts) {
|
|
const self2 = this;
|
|
let id = 0;
|
|
while (true) {
|
|
id = Math.random() * 4294967296 >>> 0;
|
|
if (this._streams.has(id & this._prefix)) continue;
|
|
break;
|
|
}
|
|
if (2 * this._streams.size >= this._prefix) {
|
|
this._prefix = 2 * this._prefix + 1;
|
|
const next = /* @__PURE__ */ new Map();
|
|
for (const stream2 of this._streams.values()) {
|
|
next.set(stream2.id & this._prefix, stream2);
|
|
}
|
|
this._streams = next;
|
|
}
|
|
const stream = this._dht.udx.createStream(id, opts);
|
|
this._streams.set(id & this._prefix, stream);
|
|
stream.on("close", onclose);
|
|
return stream;
|
|
function onclose() {
|
|
self2._streams.delete(id & self2._prefix);
|
|
}
|
|
}
|
|
async clear() {
|
|
const destroying = [];
|
|
for (const stream of this._streams.values()) {
|
|
destroying.push(new Promise((resolve) => stream.once("close", resolve).destroy()));
|
|
}
|
|
await Promise.allSettled(destroying);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/lib/connection-pool.js
|
|
var require_connection_pool = __commonJS({
|
|
"../../node_modules/hyperdht/lib/connection-pool.js"(exports, module) {
|
|
var EventEmitter = __require("events");
|
|
var b4a = require_b4a();
|
|
var errors = require_errors6();
|
|
module.exports = class ConnectionPool extends EventEmitter {
|
|
constructor(dht) {
|
|
super();
|
|
this._dht = dht;
|
|
this._servers = /* @__PURE__ */ new Map();
|
|
this._connecting = /* @__PURE__ */ new Map();
|
|
this._connections = /* @__PURE__ */ new Map();
|
|
}
|
|
_attachServer(server) {
|
|
const keyString = b4a.toString(server.publicKey, "hex");
|
|
this._servers.set(keyString, server);
|
|
server.on("close", () => {
|
|
this._servers.delete(keyString);
|
|
}).on("connection", (socket) => {
|
|
this._attachStream(socket, true);
|
|
});
|
|
}
|
|
_attachStream(stream, opened) {
|
|
const existing = this.get(stream.remotePublicKey);
|
|
if (existing) {
|
|
const keepNew = stream.isInitiator === existing.isInitiator || b4a.compare(stream.publicKey, stream.remotePublicKey) > 0;
|
|
if (keepNew) {
|
|
let closed = false;
|
|
const onclose = () => {
|
|
closed = true;
|
|
};
|
|
existing.on("error", noop).on("close", () => {
|
|
if (closed) return;
|
|
stream.off("error", noop).off("close", onclose);
|
|
this._attachStream(stream, opened);
|
|
}).destroy(errors.DUPLICATE_CONNECTION());
|
|
stream.on("error", noop).on("close", onclose);
|
|
} else {
|
|
stream.on("error", noop).destroy(errors.DUPLICATE_CONNECTION());
|
|
}
|
|
return;
|
|
}
|
|
const session = new ConnectionRef(this, stream);
|
|
const keyString = b4a.toString(stream.remotePublicKey, "hex");
|
|
if (opened) {
|
|
this._connections.set(keyString, session);
|
|
stream.on("close", () => {
|
|
this._connections.delete(keyString);
|
|
});
|
|
this.emit("connection", stream, session);
|
|
} else {
|
|
this._connecting.set(keyString, session);
|
|
stream.on("error", noop).on("close", () => {
|
|
if (opened) this._connections.delete(keyString);
|
|
else this._connecting.delete(keyString);
|
|
}).on("open", () => {
|
|
opened = true;
|
|
this._connecting.delete(keyString);
|
|
this._connections.set(keyString, session);
|
|
stream.off("error", noop);
|
|
this.emit("connection", stream, session);
|
|
});
|
|
}
|
|
return session;
|
|
}
|
|
get connecting() {
|
|
return this._connecting.size;
|
|
}
|
|
get connections() {
|
|
return this._connections.values();
|
|
}
|
|
has(publicKey) {
|
|
const keyString = b4a.toString(publicKey, "hex");
|
|
return this._connections.has(keyString) || this._connecting.has(keyString);
|
|
}
|
|
get(publicKey) {
|
|
const keyString = b4a.toString(publicKey, "hex");
|
|
const existing = this._connections.get(keyString) || this._connecting.get(keyString);
|
|
return existing?._stream || null;
|
|
}
|
|
};
|
|
var ConnectionRef = class {
|
|
constructor(pool, stream) {
|
|
this._pool = pool;
|
|
this._stream = stream;
|
|
this._refs = 0;
|
|
}
|
|
active() {
|
|
this._refs++;
|
|
}
|
|
inactive() {
|
|
this._refs--;
|
|
}
|
|
release() {
|
|
this._stream.destroy();
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperdht/index.js
|
|
var require_hyperdht = __commonJS({
|
|
"../../node_modules/hyperdht/index.js"(exports, module) {
|
|
var DHT = require_dht_rpc();
|
|
var sodium = require_sodium_universal();
|
|
var c = require_compact_encoding();
|
|
var b4a = require_b4a();
|
|
var safetyCatch = require_safety_catch();
|
|
var m = require_messages3();
|
|
var SocketPool = require_socket_pool();
|
|
var Persistent = require_persistent();
|
|
var Router = require_router();
|
|
var Cache = require_xache();
|
|
var Server = require_server();
|
|
var connect = require_connect();
|
|
var { FIREWALL, BOOTSTRAP_NODES, KNOWN_NODES, COMMANDS } = require_constants2();
|
|
var { hash, createKeyPair } = require_crypto();
|
|
var { decode } = require_hypercore_id_encoding();
|
|
var RawStreamSet = require_raw_stream_set();
|
|
var ConnectionPool = require_connection_pool();
|
|
var { STREAM_NOT_CONNECTED } = require_errors6();
|
|
var DEFAULTS = {
|
|
...DHT.DEFAULTS,
|
|
connectionKeepAlive: 5e3,
|
|
randomPunchInterval: 2e4
|
|
};
|
|
var HyperDHT = class extends DHT {
|
|
constructor(opts = {}) {
|
|
const port = opts.port || 49737;
|
|
const bootstrap = opts.bootstrap || BOOTSTRAP_NODES;
|
|
const nodes = opts.nodes || KNOWN_NODES;
|
|
super({ ...opts, port, bootstrap, nodes, filterNode });
|
|
const { router, relayAddresses, persistent } = defaultCacheOpts(opts);
|
|
this.defaultKeyPair = opts.keyPair || createKeyPair(opts.seed);
|
|
this.listening = /* @__PURE__ */ new Set();
|
|
this.connectionKeepAlive = opts.connectionKeepAlive === false ? 0 : opts.connectionKeepAlive || DEFAULTS.connectionKeepAlive;
|
|
this.stats = {
|
|
punches: { consistent: 0, random: 0, open: 0 },
|
|
relaying: { attempts: 0, successes: 0, aborts: 0 },
|
|
...this.stats
|
|
};
|
|
this.rawStreams = new RawStreamSet(this);
|
|
this._router = new Router(this, router);
|
|
this._socketPool = new SocketPool(this, opts.host || "0.0.0.0");
|
|
this._persistent = null;
|
|
this._validatedLocalAddresses = /* @__PURE__ */ new Map();
|
|
this._relayAddressesCache = new Cache(relayAddresses);
|
|
this._deferRandomPunch = !!opts.deferRandomPunch;
|
|
this._lastRandomPunch = this._deferRandomPunch ? Date.now() : 0;
|
|
this._connectable = true;
|
|
this._randomPunchInterval = opts.randomPunchInterval || DEFAULTS.randomPunchInterval;
|
|
this._randomPunches = 0;
|
|
this._randomPunchLimit = 1;
|
|
this.once("persistent", () => {
|
|
this._persistent = new Persistent(this, persistent);
|
|
});
|
|
this.on("network-change", () => {
|
|
for (const server of this.listening) server.refresh();
|
|
});
|
|
this.on("network-update", () => {
|
|
if (!this.online) return;
|
|
for (const server of this.listening) server.notifyOnline();
|
|
});
|
|
}
|
|
static DEFAULTS = DEFAULTS;
|
|
connect(remotePublicKey, opts) {
|
|
return connect(this, decode(remotePublicKey), opts);
|
|
}
|
|
createServer(opts, onconnection) {
|
|
if (typeof opts === "function") return this.createServer({}, opts);
|
|
if (opts && opts.onconnection) onconnection = opts.onconnection;
|
|
const s = new Server(this, opts);
|
|
if (onconnection) s.on("connection", onconnection);
|
|
return s;
|
|
}
|
|
pool() {
|
|
return new ConnectionPool(this);
|
|
}
|
|
async resume({ log = noop } = {}) {
|
|
if (this._deferRandomPunch) this._lastRandomPunch = Date.now();
|
|
await super.resume({ log });
|
|
const resuming = [];
|
|
for (const server of this.listening) resuming.push(server.resume());
|
|
log("Resuming hyperdht servers");
|
|
await Promise.allSettled(resuming);
|
|
log("Done, hyperdht fully resumed");
|
|
}
|
|
async suspend({ log = noop } = {}) {
|
|
this._connectable = false;
|
|
const suspending = [];
|
|
for (const server of this.listening) suspending.push(server.suspend());
|
|
log("Suspending all hyperdht servers");
|
|
await Promise.allSettled(suspending);
|
|
log("Done, clearing all raw streams");
|
|
await this.rawStreams.clear();
|
|
log("Done, suspending dht-rpc");
|
|
await super.suspend({ log });
|
|
log("Done, clearing raw streams again");
|
|
await this.rawStreams.clear();
|
|
log("Done, hyperdht fully suspended");
|
|
this._connectable = true;
|
|
}
|
|
async destroy({ force = false } = {}) {
|
|
if (!force) {
|
|
const closing = [];
|
|
for (const server of this.listening) closing.push(server.close());
|
|
await Promise.allSettled(closing);
|
|
}
|
|
this._router.destroy();
|
|
if (this._persistent) this._persistent.destroy();
|
|
await this.rawStreams.clear();
|
|
await this._socketPool.destroy();
|
|
await super.destroy();
|
|
}
|
|
async validateLocalAddresses(addresses) {
|
|
const list = [];
|
|
const socks = [];
|
|
const waiting = [];
|
|
for (const addr of addresses) {
|
|
const { host } = addr;
|
|
if (this._validatedLocalAddresses.has(host)) {
|
|
if (await this._validatedLocalAddresses.get(host)) {
|
|
list.push(addr);
|
|
}
|
|
continue;
|
|
}
|
|
const sock = this.udx.createSocket();
|
|
try {
|
|
sock.bind(0, host);
|
|
} catch {
|
|
this._validatedLocalAddresses.set(host, Promise.resolve(false));
|
|
continue;
|
|
}
|
|
socks.push(sock);
|
|
const promise = new Promise((resolve) => {
|
|
sock.on("message", () => resolve(true));
|
|
setTimeout(() => resolve(false), 500);
|
|
sock.trySend(b4a.alloc(1), sock.address().port, addr.host);
|
|
});
|
|
this._validatedLocalAddresses.set(host, promise);
|
|
waiting.push(addr);
|
|
}
|
|
for (const addr of waiting) {
|
|
const { host } = addr;
|
|
if (this._validatedLocalAddresses.has(host)) {
|
|
if (await this._validatedLocalAddresses.get(host)) {
|
|
list.push(addr);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
for (const sock of socks) await sock.close();
|
|
return list;
|
|
}
|
|
findPeer(publicKey, opts = {}) {
|
|
const target = opts.hash === false ? publicKey : hash(publicKey);
|
|
opts = { ...opts, map: mapFindPeer };
|
|
return this.query({ target, command: COMMANDS.FIND_PEER, value: null }, opts);
|
|
}
|
|
lookup(target, opts = {}) {
|
|
opts = { ...opts, map: mapLookup };
|
|
return this.query({ target, command: COMMANDS.LOOKUP, value: null }, opts);
|
|
}
|
|
lookupAndUnannounce(target, keyPair, opts = {}) {
|
|
const unannounces = [];
|
|
const dht = this;
|
|
const userCommit = opts.commit || noop;
|
|
const signUnannounce = opts.signUnannounce || Persistent.signUnannounce;
|
|
if (this._persistent !== null) {
|
|
this._persistent.unannounce(target, keyPair.publicKey);
|
|
}
|
|
opts = { ...opts, map, commit };
|
|
return this.query({ target, command: COMMANDS.LOOKUP, value: null }, opts);
|
|
async function commit(reply, dht2, query) {
|
|
await Promise.all(unannounces);
|
|
return userCommit(reply, dht2, query);
|
|
}
|
|
function map(reply) {
|
|
const data = mapLookup(reply);
|
|
if (!data || !data.token) return data;
|
|
let found = data.peers.length >= 20;
|
|
for (let i = 0; !found && i < data.peers.length; i++) {
|
|
found = b4a.equals(data.peers[i].publicKey, keyPair.publicKey);
|
|
}
|
|
if (!found) return data;
|
|
if (!data.from.id) return data;
|
|
unannounces.push(
|
|
dht._requestUnannounce(keyPair, dht, target, data.token, data.from, signUnannounce).catch(safetyCatch)
|
|
);
|
|
return data;
|
|
}
|
|
}
|
|
unannounce(target, keyPair, opts = {}) {
|
|
return this.lookupAndUnannounce(target, keyPair, opts).finished();
|
|
}
|
|
announce(target, keyPair, relayAddresses, opts = {}) {
|
|
const signAnnounce = opts.signAnnounce || Persistent.signAnnounce;
|
|
const bump = opts.bump || 0;
|
|
opts = { ...opts, commit };
|
|
return opts.clear ? this.lookupAndUnannounce(target, keyPair, opts) : this.lookup(target, opts);
|
|
function commit(reply, dht) {
|
|
return dht._requestAnnounce(
|
|
keyPair,
|
|
dht,
|
|
target,
|
|
reply.token,
|
|
reply.from,
|
|
relayAddresses,
|
|
signAnnounce,
|
|
bump
|
|
);
|
|
}
|
|
}
|
|
async immutableGet(target, opts = {}) {
|
|
opts = { ...opts, map: mapImmutable };
|
|
const query = this.query({ target, command: COMMANDS.IMMUTABLE_GET, value: null }, opts);
|
|
const check = b4a.allocUnsafe(32);
|
|
for await (const node of query) {
|
|
const { value } = node;
|
|
sodium.crypto_generichash(check, value);
|
|
if (b4a.equals(check, target)) return node;
|
|
}
|
|
return null;
|
|
}
|
|
async immutablePut(value, opts = {}) {
|
|
const target = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(target, value);
|
|
opts = {
|
|
...opts,
|
|
map: mapImmutable,
|
|
commit(reply, dht) {
|
|
return dht.request(
|
|
{ token: reply.token, target, command: COMMANDS.IMMUTABLE_PUT, value },
|
|
reply.from
|
|
);
|
|
}
|
|
};
|
|
const query = this.query({ target, command: COMMANDS.IMMUTABLE_GET, value: null }, opts);
|
|
await query.finished();
|
|
return { hash: target, closestNodes: query.closestNodes };
|
|
}
|
|
async mutableGet(publicKey, opts = {}) {
|
|
let refresh = opts.refresh || null;
|
|
let signed = null;
|
|
let result = null;
|
|
opts = { ...opts, map: mapMutable, commit: refresh ? commit : null };
|
|
const target = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(target, publicKey);
|
|
const userSeq = opts.seq || 0;
|
|
const query = this.query(
|
|
{ target, command: COMMANDS.MUTABLE_GET, value: c.encode(c.uint, userSeq) },
|
|
opts
|
|
);
|
|
const latest = opts.latest !== false;
|
|
for await (const node of query) {
|
|
if (result && node.seq <= result.seq) continue;
|
|
if (node.seq < userSeq || !Persistent.verifyMutable(node.signature, node.seq, node.value, publicKey))
|
|
continue;
|
|
if (!latest) return node;
|
|
if (!result || node.seq > result.seq) result = node;
|
|
}
|
|
return result;
|
|
function commit(reply, dht) {
|
|
if (!signed && result && refresh) {
|
|
if (refresh(result)) {
|
|
signed = c.encode(m.mutablePutRequest, {
|
|
publicKey,
|
|
seq: result.seq,
|
|
value: result.value,
|
|
signature: result.signature
|
|
});
|
|
} else {
|
|
refresh = null;
|
|
}
|
|
}
|
|
return signed ? dht.request(
|
|
{ token: reply.token, target, command: COMMANDS.MUTABLE_PUT, value: signed },
|
|
reply.from
|
|
) : Promise.resolve(null);
|
|
}
|
|
}
|
|
async mutablePut(keyPair, value, opts = {}) {
|
|
const signMutable = opts.signMutable || Persistent.signMutable;
|
|
const target = b4a.allocUnsafe(32);
|
|
sodium.crypto_generichash(target, keyPair.publicKey);
|
|
const seq = opts.seq || 0;
|
|
const signature = await signMutable(seq, value, keyPair);
|
|
const signed = c.encode(m.mutablePutRequest, {
|
|
publicKey: keyPair.publicKey,
|
|
seq,
|
|
value,
|
|
signature
|
|
});
|
|
opts = {
|
|
...opts,
|
|
map: mapMutable,
|
|
commit(reply, dht) {
|
|
return dht.request(
|
|
{ token: reply.token, target, command: COMMANDS.MUTABLE_PUT, value: signed },
|
|
reply.from
|
|
);
|
|
}
|
|
};
|
|
const query = this.query(
|
|
{ target, command: COMMANDS.MUTABLE_GET, value: c.encode(c.uint, 0) },
|
|
opts
|
|
);
|
|
await query.finished();
|
|
return { publicKey: keyPair.publicKey, closestNodes: query.closestNodes, seq, signature };
|
|
}
|
|
onrequest(req) {
|
|
switch (req.command) {
|
|
case COMMANDS.PEER_HANDSHAKE: {
|
|
this._router.onpeerhandshake(req);
|
|
return true;
|
|
}
|
|
case COMMANDS.PEER_HOLEPUNCH: {
|
|
this._router.onpeerholepunch(req);
|
|
return true;
|
|
}
|
|
}
|
|
if (this._persistent === null || this.id === null) return false;
|
|
switch (req.command) {
|
|
case COMMANDS.FIND_PEER: {
|
|
this._persistent.onfindpeer(req);
|
|
return true;
|
|
}
|
|
case COMMANDS.LOOKUP: {
|
|
this._persistent.onlookup(req);
|
|
return true;
|
|
}
|
|
case COMMANDS.ANNOUNCE: {
|
|
this._persistent.onannounce(req);
|
|
return true;
|
|
}
|
|
case COMMANDS.UNANNOUNCE: {
|
|
this._persistent.onunannounce(req);
|
|
return true;
|
|
}
|
|
case COMMANDS.MUTABLE_PUT: {
|
|
this._persistent.onmutableput(req);
|
|
return true;
|
|
}
|
|
case COMMANDS.MUTABLE_GET: {
|
|
this._persistent.onmutableget(req);
|
|
return true;
|
|
}
|
|
case COMMANDS.IMMUTABLE_PUT: {
|
|
this._persistent.onimmutableput(req);
|
|
return true;
|
|
}
|
|
case COMMANDS.IMMUTABLE_GET: {
|
|
this._persistent.onimmutableget(req);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
static keyPair(seed) {
|
|
return createKeyPair(seed);
|
|
}
|
|
static hash(data) {
|
|
return hash(data);
|
|
}
|
|
static connectRawStream(encryptedStream, rawStream, remoteId) {
|
|
const stream = encryptedStream.rawStream;
|
|
if (!stream.connected) throw STREAM_NOT_CONNECTED();
|
|
rawStream.connect(stream.socket, remoteId, stream.remotePort, stream.remoteHost);
|
|
}
|
|
createRawStream(opts) {
|
|
return this.rawStreams.add(opts);
|
|
}
|
|
async _requestAnnounce(keyPair, dht, target, token, from, relayAddresses, sign, bump) {
|
|
const ann = {
|
|
peer: {
|
|
publicKey: keyPair.publicKey,
|
|
relayAddresses: relayAddresses || []
|
|
},
|
|
refresh: null,
|
|
signature: null,
|
|
bump
|
|
};
|
|
ann.signature = await sign(target, token, from.id, ann, keyPair);
|
|
const value = c.encode(m.announce, ann);
|
|
return dht.request(
|
|
{
|
|
token,
|
|
target,
|
|
command: COMMANDS.ANNOUNCE,
|
|
value
|
|
},
|
|
from
|
|
);
|
|
}
|
|
async _requestUnannounce(keyPair, dht, target, token, from, sign) {
|
|
const unann = {
|
|
peer: {
|
|
publicKey: keyPair.publicKey,
|
|
relayAddresses: []
|
|
},
|
|
signature: null
|
|
};
|
|
unann.signature = await sign(target, token, from.id, unann, keyPair);
|
|
const value = c.encode(m.announce, unann);
|
|
return dht.request(
|
|
{
|
|
token,
|
|
target,
|
|
command: COMMANDS.UNANNOUNCE,
|
|
value
|
|
},
|
|
from
|
|
);
|
|
}
|
|
};
|
|
HyperDHT.BOOTSTRAP = BOOTSTRAP_NODES;
|
|
HyperDHT.FIREWALL = FIREWALL;
|
|
module.exports = HyperDHT;
|
|
function mapLookup(node) {
|
|
if (!node.value) return null;
|
|
try {
|
|
const l = c.decode(m.lookupRawReply, node.value);
|
|
return {
|
|
token: node.token,
|
|
from: node.from,
|
|
to: node.to,
|
|
peers: l.peers,
|
|
bump: l.bump
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
function mapFindPeer(node) {
|
|
if (!node.value) return null;
|
|
try {
|
|
return {
|
|
token: node.token,
|
|
from: node.from,
|
|
to: node.to,
|
|
peer: c.decode(m.peer, node.value)
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
function mapImmutable(node) {
|
|
if (!node.value) return null;
|
|
return {
|
|
token: node.token,
|
|
from: node.from,
|
|
to: node.to,
|
|
value: node.value
|
|
};
|
|
}
|
|
function mapMutable(node) {
|
|
if (!node.value) return null;
|
|
try {
|
|
const { seq, value, signature } = c.decode(m.mutableGetResponse, node.value);
|
|
return {
|
|
token: node.token,
|
|
from: node.from,
|
|
to: node.to,
|
|
seq,
|
|
value,
|
|
signature
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
function noop() {
|
|
}
|
|
function filterNode(node) {
|
|
return !(node.port === 49738 && (node.host === "134.209.28.98" || node.host === "167.99.142.185")) && !(node.port === 9400 && node.host === "35.233.47.252") && !(node.host === "150.136.142.116");
|
|
}
|
|
var defaultMaxSize = 65536;
|
|
var defaultMaxAge = 20 * 60 * 1e3;
|
|
function defaultCacheOpts(opts) {
|
|
const maxSize = opts.maxSize || defaultMaxSize;
|
|
const maxAge = opts.maxAge || defaultMaxAge;
|
|
return {
|
|
router: {
|
|
forwards: { maxSize, maxAge }
|
|
},
|
|
relayAddresses: { maxSize: Math.min(maxSize, 512), maxAge: 0 },
|
|
persistent: {
|
|
records: { maxSize, maxAge },
|
|
refreshes: { maxSize, maxAge },
|
|
mutables: {
|
|
maxSize: maxSize / 2 | 0,
|
|
maxAge: opts.maxAge || 48 * 60 * 60 * 1e3
|
|
// 48 hours
|
|
},
|
|
immutables: {
|
|
maxSize: maxSize / 2 | 0,
|
|
maxAge: opts.maxAge || 48 * 60 * 60 * 1e3
|
|
// 48 hours
|
|
},
|
|
bumps: { maxSize, maxAge }
|
|
}
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/unordered-set/index.js
|
|
var require_unordered_set = __commonJS({
|
|
"../../node_modules/unordered-set/index.js"(exports) {
|
|
exports.add = add;
|
|
exports.has = has;
|
|
exports.remove = remove;
|
|
exports.swap = swap;
|
|
function add(list, item) {
|
|
if (has(list, item)) return item;
|
|
item._index = list.length;
|
|
list.push(item);
|
|
return item;
|
|
}
|
|
function has(list, item) {
|
|
return item._index < list.length && list[item._index] === item;
|
|
}
|
|
function remove(list, item) {
|
|
if (!has(list, item)) return null;
|
|
var last = list.pop();
|
|
if (last !== item) {
|
|
list[item._index] = last;
|
|
last._index = item._index;
|
|
}
|
|
return item;
|
|
}
|
|
function swap(list, a, b) {
|
|
if (!has(list, a) || !has(list, b)) return;
|
|
var tmp = a._index;
|
|
a._index = b._index;
|
|
list[a._index] = a;
|
|
b._index = tmp;
|
|
list[b._index] = b;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/shuffled-priority-queue/index.js
|
|
var require_shuffled_priority_queue = __commonJS({
|
|
"../../node_modules/shuffled-priority-queue/index.js"(exports, module) {
|
|
var set = require_unordered_set();
|
|
module.exports = (opts) => new ShuffledPriorityQueue(opts);
|
|
var ShuffledPriorityQueue = class {
|
|
constructor(opts) {
|
|
this.priorities = [];
|
|
this.equals = opts && opts.equals || null;
|
|
}
|
|
get length() {
|
|
return this.priorities.reduce(add, 0);
|
|
}
|
|
[Symbol.iterator]() {
|
|
return new Iterator(this);
|
|
}
|
|
head() {
|
|
for (let i = this.priorities.length - 1; i >= 0; i--) {
|
|
const q = this.priorities[i];
|
|
if (q.length) return shuffle(q, 0);
|
|
}
|
|
return null;
|
|
}
|
|
tail() {
|
|
for (let i = 0; i < this.priorities.length; i++) {
|
|
const q = this.priorities[i];
|
|
if (q.length) return shuffle(q, 0);
|
|
}
|
|
return null;
|
|
}
|
|
prev(prev) {
|
|
if (!prev) return this.tail();
|
|
return next(this.priorities, prev, 1);
|
|
}
|
|
next(prev) {
|
|
if (!prev) return this.head();
|
|
return next(this.priorities, prev, -1);
|
|
}
|
|
shift() {
|
|
return this.remove(this.head());
|
|
}
|
|
pop() {
|
|
return this.remove(this.tail());
|
|
}
|
|
add(val) {
|
|
const prio = val.priority || 0;
|
|
while (prio >= this.priorities.length) this.priorities.push([]);
|
|
set.add(this.priorities[prio], val);
|
|
return val;
|
|
}
|
|
remove(val) {
|
|
if (!val) return null;
|
|
if (val._index === void 0) {
|
|
val = this.find(val);
|
|
if (!val) return null;
|
|
}
|
|
return set.remove(this.priorities[val.priority || 0], val);
|
|
}
|
|
has(val) {
|
|
if (val._index === void 0) return this.find(val);
|
|
const priority = val.priority || 0;
|
|
if (priority >= this.priorities.length) return false;
|
|
return set.has(this.priorities[priority], val);
|
|
}
|
|
find(val) {
|
|
if (val._index !== void 0) return val;
|
|
const prio = val.priority || 0;
|
|
const qs = this.priorities;
|
|
if (prio >= qs.length) return null;
|
|
const q = qs[prio];
|
|
for (let i = 0; i < q.length; i++) {
|
|
if (this.equals(q[i], val)) return q[i];
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
var Iterator = class {
|
|
constructor(queue) {
|
|
this.prev = null;
|
|
this.queue = queue;
|
|
}
|
|
next() {
|
|
const next2 = this.queue.next(this.prev);
|
|
this.prev = next2;
|
|
return { done: !next2, value: next2 };
|
|
}
|
|
};
|
|
function shuffle(q, i) {
|
|
const ran = i + Math.floor(Math.random() * (q.length - i));
|
|
set.swap(q, q[ran], q[i]);
|
|
return q[i];
|
|
}
|
|
function next(queues, prev, inc) {
|
|
let i = prev.priority || 0;
|
|
let j = (prev._index || 0) + 1;
|
|
while (true) {
|
|
if (i < 0 || i >= queues.length) return null;
|
|
const q = queues[i];
|
|
if (j >= q.length) {
|
|
i += inc;
|
|
j = 0;
|
|
continue;
|
|
}
|
|
return shuffle(q, j);
|
|
}
|
|
}
|
|
function add(len, b) {
|
|
return len + b.length;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperswarm/lib/peer-info.js
|
|
var require_peer_info = __commonJS({
|
|
"../../node_modules/hyperswarm/lib/peer-info.js"(exports, module) {
|
|
var { EventEmitter } = __require("events");
|
|
var b4a = require_b4a();
|
|
var unslab = require_unslab();
|
|
var MIN_CONNECTION_TIME = 15e3;
|
|
var VERY_LOW_PRIORITY = 0;
|
|
var LOW_PRIORITY = 1;
|
|
var NORMAL_PRIORITY = 2;
|
|
var HIGH_PRIORITY = 3;
|
|
var VERY_HIGH_PRIORITY = 4;
|
|
module.exports = class PeerInfo extends EventEmitter {
|
|
constructor({ publicKey, relayAddresses }) {
|
|
super();
|
|
this.publicKey = unslab(publicKey);
|
|
this.relayAddresses = relayAddresses;
|
|
this.reconnecting = true;
|
|
this.proven = false;
|
|
this.connectedTime = -1;
|
|
this.disconnectedTime = 0;
|
|
this.banned = false;
|
|
this.tried = false;
|
|
this.explicit = false;
|
|
this.waiting = false;
|
|
this.forceRelaying = false;
|
|
this.queued = false;
|
|
this.client = false;
|
|
this.topics = [];
|
|
this.attempts = 0;
|
|
this.priority = NORMAL_PRIORITY;
|
|
this._index = 0;
|
|
this._flushTick = 0;
|
|
this._seenTopics = /* @__PURE__ */ new Set();
|
|
}
|
|
get server() {
|
|
return !this.client;
|
|
}
|
|
get prioritized() {
|
|
return this.priority >= NORMAL_PRIORITY;
|
|
}
|
|
_getPriority() {
|
|
const peerIsStale = this.tried && !this.proven;
|
|
if (peerIsStale || this.attempts > 3) return VERY_LOW_PRIORITY;
|
|
if (this.attempts === 3) return LOW_PRIORITY;
|
|
if (this.attempts === 2) return HIGH_PRIORITY;
|
|
if (this.attempts === 1) return VERY_HIGH_PRIORITY;
|
|
return NORMAL_PRIORITY;
|
|
}
|
|
_connected() {
|
|
this.proven = true;
|
|
this.connectedTime = Date.now();
|
|
}
|
|
_disconnected() {
|
|
this.disconnectedTime = Date.now();
|
|
if (this.connectedTime > -1) {
|
|
if (this.disconnectedTime - this.connectedTime >= MIN_CONNECTION_TIME) this.attempts = 0;
|
|
this.connectedTime = -1;
|
|
}
|
|
this.attempts++;
|
|
}
|
|
_deprioritize() {
|
|
this.attempts = 3;
|
|
}
|
|
_reset() {
|
|
this.client = false;
|
|
this.proven = false;
|
|
this.tried = false;
|
|
this.attempts = 0;
|
|
}
|
|
_updatePriority() {
|
|
if (this.explicit && this.attempts > 3) this._deprioritize();
|
|
if (this.banned || this.queued || this.attempts > 3) return false;
|
|
this.priority = this._getPriority();
|
|
return true;
|
|
}
|
|
_topic(topic) {
|
|
const topicString = b4a.toString(topic, "hex");
|
|
if (this._seenTopics.has(topicString)) return;
|
|
this._seenTopics.add(topicString);
|
|
this.topics.push(topic);
|
|
this.emit("topic", topic);
|
|
}
|
|
reconnect(val) {
|
|
this.reconnecting = !!val;
|
|
}
|
|
ban(val) {
|
|
this.banned = !!val;
|
|
}
|
|
shouldGC() {
|
|
return !(this.banned || this.queued || this.explicit || this.waiting);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperswarm/lib/bulk-timer.js
|
|
var require_bulk_timer = __commonJS({
|
|
"../../node_modules/hyperswarm/lib/bulk-timer.js"(exports, module) {
|
|
module.exports = class BulkTimer {
|
|
constructor(time, fn) {
|
|
this._time = time;
|
|
this._fn = fn;
|
|
this._interval = null;
|
|
this._next = [];
|
|
this._pending = [];
|
|
this._destroyed = false;
|
|
}
|
|
destroy() {
|
|
if (this._destroyed) return;
|
|
this._destroyed = true;
|
|
clearInterval(this._interval);
|
|
this._interval = null;
|
|
}
|
|
_ontick() {
|
|
if (!this._next.length && !this._pending.length) return;
|
|
if (this._next.length) this._fn(this._next);
|
|
this._next = this._pending;
|
|
this._pending = [];
|
|
}
|
|
add(info) {
|
|
if (this._destroyed) return;
|
|
if (!this._interval) {
|
|
this._interval = setInterval(this._ontick.bind(this), Math.floor(this._time * 0.66));
|
|
}
|
|
this._pending.push(info);
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperswarm/lib/retry-timer.js
|
|
var require_retry_timer = __commonJS({
|
|
"../../node_modules/hyperswarm/lib/retry-timer.js"(exports, module) {
|
|
var BulkTimer = require_bulk_timer();
|
|
var BACKOFF_JITTER = 500;
|
|
var BACKOFF_S = 1e3 + Math.round(BACKOFF_JITTER * Math.random());
|
|
var BACKOFF_M = 5e3 + Math.round(2 * BACKOFF_JITTER * Math.random());
|
|
var BACKOFF_L = 15e3 + Math.round(4 * BACKOFF_JITTER * Math.random());
|
|
var BACKOFF_X = 1e3 * 60 * 10 + Math.round(240 * BACKOFF_JITTER * Math.random());
|
|
module.exports = class RetryTimer {
|
|
constructor(push, { backoffs = [BACKOFF_S, BACKOFF_M, BACKOFF_L, BACKOFF_X], jitter = BACKOFF_JITTER } = {}) {
|
|
this.jitter = jitter;
|
|
this.backoffs = backoffs;
|
|
this._sTimer = new BulkTimer(backoffs[0] + Math.round(jitter * Math.random()), push);
|
|
this._mTimer = new BulkTimer(backoffs[1] + Math.round(jitter * Math.random()), push);
|
|
this._lTimer = new BulkTimer(backoffs[2] + Math.round(jitter * Math.random()), push);
|
|
this._xTimer = new BulkTimer(backoffs[3] + Math.round(jitter * Math.random()), push);
|
|
}
|
|
_selectRetryTimer(peerInfo) {
|
|
if (peerInfo.banned || !peerInfo.reconnecting) return null;
|
|
if (peerInfo.attempts > 3) {
|
|
return peerInfo.explicit ? this._xTimer : null;
|
|
}
|
|
if (peerInfo.attempts === 0) return this._sTimer;
|
|
if (peerInfo.proven) {
|
|
switch (peerInfo.attempts) {
|
|
case 1:
|
|
return this._sTimer;
|
|
case 2:
|
|
return this._mTimer;
|
|
case 3:
|
|
return this._lTimer;
|
|
}
|
|
} else {
|
|
switch (peerInfo.attempts) {
|
|
case 1:
|
|
return this._mTimer;
|
|
case 2:
|
|
return this._lTimer;
|
|
case 3:
|
|
return this._lTimer;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
add(peerInfo) {
|
|
const timer = this._selectRetryTimer(peerInfo);
|
|
if (!timer) return false;
|
|
timer.add(peerInfo);
|
|
return true;
|
|
}
|
|
destroy() {
|
|
this._sTimer.destroy();
|
|
this._mTimer.destroy();
|
|
this._lTimer.destroy();
|
|
this._xTimer.destroy();
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperswarm/lib/connection-set.js
|
|
var require_connection_set = __commonJS({
|
|
"../../node_modules/hyperswarm/lib/connection-set.js"(exports, module) {
|
|
var b4a = require_b4a();
|
|
module.exports = class ConnectionSet {
|
|
constructor() {
|
|
this._byPublicKey = /* @__PURE__ */ new Map();
|
|
}
|
|
[Symbol.iterator]() {
|
|
return this._byPublicKey.values();
|
|
}
|
|
get size() {
|
|
return this._byPublicKey.size;
|
|
}
|
|
has(publicKey) {
|
|
return this._byPublicKey.has(toHex(publicKey));
|
|
}
|
|
get(publicKey) {
|
|
return this._byPublicKey.get(toHex(publicKey));
|
|
}
|
|
add(connection) {
|
|
this._byPublicKey.set(b4a.toString(connection.remotePublicKey, "hex"), connection);
|
|
}
|
|
delete(connection) {
|
|
const keyString = b4a.toString(connection.remotePublicKey, "hex");
|
|
const existing = this._byPublicKey.get(keyString);
|
|
if (existing !== connection) return;
|
|
this._byPublicKey.delete(keyString);
|
|
}
|
|
};
|
|
function toHex(b) {
|
|
return typeof b === "string" ? b : b4a.toString(b, "hex");
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperswarm/lib/peer-discovery.js
|
|
var require_peer_discovery = __commonJS({
|
|
"../../node_modules/hyperswarm/lib/peer-discovery.js"(exports, module) {
|
|
var safetyCatch = require_safety_catch();
|
|
var b4a = require_b4a();
|
|
var REFRESH_INTERVAL = 1e3 * 60 * 10;
|
|
var RANDOM_JITTER = 1e3 * 60 * 2;
|
|
var DELAY_GRACE_PERIOD = 1e3 * 30;
|
|
var MAX_DISCOVERY_CACHE = 64;
|
|
module.exports = class PeerDiscovery {
|
|
constructor(swarm, topic, { limit = Infinity, wait = null, suspended = false, onpeer = noop, onerror = safetyCatch }) {
|
|
this.limit = limit;
|
|
this.swarm = swarm;
|
|
this.topic = topic;
|
|
this.isClient = false;
|
|
this.isServer = false;
|
|
this.destroyed = false;
|
|
this.destroying = null;
|
|
this.suspended = suspended;
|
|
this._sessions = [];
|
|
this._clientSessions = 0;
|
|
this._serverSessions = 0;
|
|
this._onpeer = onpeer;
|
|
this._onerror = onerror;
|
|
this._discovered = /* @__PURE__ */ new Set();
|
|
this._activeQuery = null;
|
|
this._timer = null;
|
|
this._currentRefresh = null;
|
|
this._closestNodes = null;
|
|
this._firstAnnounce = true;
|
|
this._needsUnannounce = false;
|
|
this._refreshes = 0;
|
|
this._wait = wait;
|
|
}
|
|
session({ server = true, client = true, limit = Infinity, onerror = safetyCatch }) {
|
|
if (this.destroyed) throw new Error("PeerDiscovery is destroyed");
|
|
const session = new PeerDiscoverySession(this);
|
|
session.refresh({ server, client, limit }).catch(onerror);
|
|
this._sessions.push(session);
|
|
return session;
|
|
}
|
|
_refreshLater(eager) {
|
|
const jitter = Math.round(Math.random() * RANDOM_JITTER);
|
|
const delay = !eager ? REFRESH_INTERVAL + jitter : jitter;
|
|
if (this._timer) clearTimeout(this._timer);
|
|
const startTime = Date.now();
|
|
this._timer = setTimeout(() => {
|
|
const overdue = Date.now() - startTime > delay + DELAY_GRACE_PERIOD;
|
|
if (overdue) this._refreshLater(true);
|
|
else this.refresh().catch(this._onerror);
|
|
}, delay);
|
|
}
|
|
_isActive() {
|
|
return !this.destroyed && !this.suspended;
|
|
}
|
|
// NOTE: Allow announce to be an argument to this
|
|
// NOTE: Maybe announce should be a setter?
|
|
async _refresh() {
|
|
if (this.suspended) return;
|
|
const clock = ++this._refreshes;
|
|
if (this._wait) {
|
|
await this._wait;
|
|
this._wait = null;
|
|
if (clock !== this._refreshes || !this._isActive()) return;
|
|
}
|
|
const clear = this.isServer && this._firstAnnounce;
|
|
if (clear) this._firstAnnounce = false;
|
|
const opts = {
|
|
clear,
|
|
closestNodes: this._closestNodes
|
|
};
|
|
if (this.isServer) {
|
|
await this.swarm.listen();
|
|
if (clock !== this._refreshes || !this._isActive()) return;
|
|
this._needsUnannounce = true;
|
|
}
|
|
let limit = this.limit;
|
|
if (limit < Infinity && limit > 0) {
|
|
for (const id of this._discovered) {
|
|
if (!this.swarm.connections.has(id)) continue;
|
|
if (--limit === 0) break;
|
|
}
|
|
}
|
|
this._discovered.clear();
|
|
const announcing = this.isServer;
|
|
const query = this._activeQuery = announcing ? this.swarm.dht.announce(
|
|
this.topic,
|
|
this.swarm.keyPair,
|
|
this.swarm.server.relayAddresses,
|
|
opts
|
|
) : this._needsUnannounce ? this.swarm.dht.lookupAndUnannounce(this.topic, this.swarm.keyPair, opts) : this.swarm.dht.lookup(this.topic, opts);
|
|
try {
|
|
for await (const data of this._activeQuery) {
|
|
if (!this.isClient || !this._isActive()) continue;
|
|
for (const peer of data.peers) {
|
|
if (limit < Infinity) {
|
|
const id = b4a.toString(peer.publicKey, "hex");
|
|
if (this._discovered.size < MAX_DISCOVERY_CACHE) {
|
|
this._discovered.add(id);
|
|
}
|
|
if (limit === 0) continue;
|
|
if (!this.swarm.connections.has(id)) limit--;
|
|
}
|
|
this._onpeer(peer, data);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
if (this._isActive()) throw err;
|
|
} finally {
|
|
if (this._activeQuery === query) {
|
|
this._activeQuery = null;
|
|
if (!this.destroyed && !this.suspended) this._refreshLater(false);
|
|
}
|
|
}
|
|
this._closestNodes = query.closestNodes;
|
|
if (clock !== this._refreshes) return;
|
|
if (!announcing) this._needsUnannounce = false;
|
|
}
|
|
async refresh() {
|
|
if (this.destroyed) throw new Error("PeerDiscovery is destroyed");
|
|
const server = this._serverSessions > 0;
|
|
const client = this._clientSessions > 0;
|
|
if (this.suspended) return;
|
|
if (server === this.isServer && client === this.isClient) {
|
|
if (this._currentRefresh) return this._currentRefresh;
|
|
this._currentRefresh = this._refresh();
|
|
} else {
|
|
if (this._activeQuery) this._activeQuery.destroy();
|
|
this.isServer = server;
|
|
this.isClient = client;
|
|
this._currentRefresh = this._refresh();
|
|
}
|
|
const refresh = this._currentRefresh;
|
|
try {
|
|
await refresh;
|
|
} catch {
|
|
return false;
|
|
} finally {
|
|
if (refresh === this._currentRefresh) {
|
|
this._currentRefresh = null;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
async flushed() {
|
|
if (this.swarm.listening) await this.swarm.listening;
|
|
try {
|
|
await this._currentRefresh;
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
async _destroyMaybe() {
|
|
if (this.destroyed) return;
|
|
try {
|
|
if (this._sessions.length === 0) await this.swarm.leave(this.topic);
|
|
else if (this._serverSessions === 0 && this._needsUnannounce) await this.refresh();
|
|
} catch (err) {
|
|
safetyCatch(err);
|
|
}
|
|
}
|
|
destroy() {
|
|
if (this.destroying) return this.destroying;
|
|
this.destroying = this._destroy();
|
|
return this.destroying;
|
|
}
|
|
async _abort(log) {
|
|
const id = log === noop ? "" : b4a.toString(this.topic, "hex");
|
|
log("Aborting discovery", id);
|
|
if (this._wait) await this._wait;
|
|
log("Aborting discovery (post wait)", id);
|
|
if (this._activeQuery) {
|
|
this._activeQuery.destroy();
|
|
this._activeQuery = null;
|
|
}
|
|
if (this._timer) {
|
|
clearTimeout(this._timer);
|
|
this._timer = null;
|
|
}
|
|
let nodes = this._closestNodes;
|
|
if (this._currentRefresh) {
|
|
try {
|
|
await this._currentRefresh;
|
|
} catch {
|
|
}
|
|
}
|
|
log("Aborting discovery (post refresh)", id);
|
|
if (this._isActive()) return;
|
|
if (!nodes) nodes = this._closestNodes;
|
|
else if (this._closestNodes !== nodes) {
|
|
const len = nodes.length;
|
|
for (const newer of this._closestNodes) {
|
|
if (newer.id && !hasNode(nodes, len, newer)) nodes.push(newer);
|
|
}
|
|
}
|
|
if (this._needsUnannounce) {
|
|
log("Unannouncing discovery", id);
|
|
if (nodes && nodes.length) {
|
|
await this.swarm.dht.unannounce(this.topic, this.swarm.keyPair, {
|
|
closestNodes: nodes,
|
|
onlyClosestNodes: true,
|
|
force: true
|
|
});
|
|
}
|
|
this._needsUnannounce = false;
|
|
log("Unannouncing discovery (done)", id);
|
|
}
|
|
}
|
|
_destroy() {
|
|
if (this.destroyed) return;
|
|
this.destroyed = true;
|
|
return this._abort(noop);
|
|
}
|
|
async suspend({ log = noop } = {}) {
|
|
if (this.suspended) return;
|
|
this.suspended = true;
|
|
try {
|
|
await this._abort(log);
|
|
} catch {
|
|
}
|
|
}
|
|
resume() {
|
|
if (!this.suspended) return;
|
|
this.suspended = false;
|
|
this.refresh().catch(noop);
|
|
}
|
|
};
|
|
var PeerDiscoverySession = class {
|
|
constructor(discovery) {
|
|
this.discovery = discovery;
|
|
this.isClient = false;
|
|
this.isServer = false;
|
|
this.destroyed = false;
|
|
}
|
|
get swarm() {
|
|
return this.discovery.swarm;
|
|
}
|
|
get topic() {
|
|
return this.discovery.topic;
|
|
}
|
|
async refresh({ client = this.isClient, server = this.isServer, limit = Infinity } = {}) {
|
|
if (this.destroyed) throw new Error("PeerDiscovery is destroyed");
|
|
if (!client && !server) throw new Error("Cannot refresh with neither client nor server option");
|
|
if (client !== this.isClient) {
|
|
this.isClient = client;
|
|
this.discovery._clientSessions += client ? 1 : -1;
|
|
}
|
|
if (server !== this.isServer) {
|
|
this.isServer = server;
|
|
this.discovery._serverSessions += server ? 1 : -1;
|
|
}
|
|
this.discovery.limit = limit;
|
|
return this.discovery.refresh();
|
|
}
|
|
async flushed() {
|
|
return this.discovery.flushed();
|
|
}
|
|
async destroy() {
|
|
if (this.destroyed) return;
|
|
this.destroyed = true;
|
|
if (this.isClient) this.discovery._clientSessions--;
|
|
if (this.isServer) this.discovery._serverSessions--;
|
|
const index = this.discovery._sessions.indexOf(this);
|
|
const head = this.discovery._sessions.pop();
|
|
if (head !== this) this.discovery._sessions[index] = head;
|
|
return this.discovery._destroyMaybe();
|
|
}
|
|
};
|
|
function hasNode(nodes, len, node) {
|
|
for (let i = 0; i < len; i++) {
|
|
const existing = nodes[i];
|
|
if (existing.id && b4a.equals(existing.id, node.id)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
function noop() {
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/hyperswarm/index.js
|
|
var require_hyperswarm = __commonJS({
|
|
"../../node_modules/hyperswarm/index.js"(exports, module) {
|
|
var { EventEmitter } = __require("events");
|
|
var { getStreamError } = require_streamx();
|
|
var DHT = require_hyperdht();
|
|
var spq = require_shuffled_priority_queue();
|
|
var b4a = require_b4a();
|
|
var unslab = require_unslab();
|
|
var PeerInfo = require_peer_info();
|
|
var RetryTimer = require_retry_timer();
|
|
var ConnectionSet = require_connection_set();
|
|
var PeerDiscovery = require_peer_discovery();
|
|
var MAX_PEERS = 64;
|
|
var MAX_PARALLEL = 3;
|
|
var MAX_CLIENT_CONNECTIONS = Infinity;
|
|
var MAX_SERVER_CONNECTIONS = Infinity;
|
|
var ERR_MISSING_TOPIC = "Topic is required and must be a 32-byte buffer";
|
|
var ERR_DESTROYED = "Swarm has been destroyed";
|
|
var ERR_DUPLICATE = "Duplicate connection";
|
|
var ERR_FIREWALL = "Peer is firewalled";
|
|
module.exports = class Hyperswarm extends EventEmitter {
|
|
constructor(opts = {}) {
|
|
super();
|
|
const {
|
|
seed,
|
|
relayThrough,
|
|
keyPair = DHT.keyPair(seed),
|
|
maxPeers = MAX_PEERS,
|
|
maxClientConnections = MAX_CLIENT_CONNECTIONS,
|
|
maxServerConnections = MAX_SERVER_CONNECTIONS,
|
|
maxParallel = MAX_PARALLEL,
|
|
firewall = allowAll
|
|
} = opts;
|
|
this.keyPair = keyPair;
|
|
this.dht = opts.dht || new DHT({
|
|
bootstrap: opts.bootstrap,
|
|
nodes: opts.nodes,
|
|
port: opts.port,
|
|
deferRandomPunch: opts.deferRandomPunch,
|
|
randomPunchInterval: opts.randomPunchInterval
|
|
});
|
|
this.server = this.dht.createServer(
|
|
{
|
|
firewall: this._handleFirewall.bind(this),
|
|
relayThrough: this._maybeRelayConnection.bind(this),
|
|
handshakeClearWait: opts.handshakeClearWait
|
|
},
|
|
this._handleServerConnection.bind(this)
|
|
);
|
|
this.destroyed = false;
|
|
this.suspended = false;
|
|
this.maxPeers = maxPeers;
|
|
this.maxClientConnections = maxClientConnections;
|
|
this.maxServerConnections = maxServerConnections;
|
|
this.maxParallel = maxParallel;
|
|
this.relayThrough = relayThrough ? toRelayFunction(relayThrough) : null;
|
|
this.connecting = 0;
|
|
this.connections = /* @__PURE__ */ new Set();
|
|
this.peers = /* @__PURE__ */ new Map();
|
|
this.explicitPeers = /* @__PURE__ */ new Set();
|
|
this.listening = null;
|
|
this.stats = {
|
|
updates: 0,
|
|
connects: {
|
|
client: {
|
|
opened: 0,
|
|
closed: 0,
|
|
attempted: 0
|
|
},
|
|
server: {
|
|
// Note: there is no notion of 'attempts' for server connections
|
|
opened: 0,
|
|
closed: 0
|
|
}
|
|
},
|
|
bannedPeers: 0
|
|
};
|
|
this._discovery = /* @__PURE__ */ new Map();
|
|
this._timer = new RetryTimer(this._requeue.bind(this), {
|
|
backoffs: opts.backoffs,
|
|
jitter: opts.jitter
|
|
});
|
|
this._queue = spq();
|
|
this._allConnections = new ConnectionSet();
|
|
this._pendingFlushes = [];
|
|
this._flushTick = 0;
|
|
this._drainingQueue = false;
|
|
this._clientConnections = 0;
|
|
this._serverConnections = 0;
|
|
this._firewall = firewall;
|
|
this.dht.on("network-change", this._handleNetworkChange.bind(this));
|
|
this.dht.on("network-update", this._handleNetworkUpdate.bind(this));
|
|
this.on("update", this._handleUpdate);
|
|
}
|
|
_maybeRelayConnection(force) {
|
|
if (!this.relayThrough) return null;
|
|
return this.relayThrough(force, this);
|
|
}
|
|
_enqueue(peerInfo) {
|
|
if (peerInfo.queued) return;
|
|
peerInfo.queued = true;
|
|
peerInfo._flushTick = this._flushTick;
|
|
this._queue.add(peerInfo);
|
|
this._attemptClientConnections();
|
|
}
|
|
_requeue(batch) {
|
|
if (this.suspended) return;
|
|
for (const peerInfo of batch) {
|
|
peerInfo.waiting = false;
|
|
if (peerInfo._updatePriority() === false || this._allConnections.has(peerInfo.publicKey) || peerInfo.queued) {
|
|
continue;
|
|
}
|
|
peerInfo.queued = true;
|
|
peerInfo._flushTick = this._flushTick;
|
|
this._queue.add(peerInfo);
|
|
}
|
|
this._attemptClientConnections();
|
|
}
|
|
_flushMaybe(peerInfo) {
|
|
for (let i = 0; i < this._pendingFlushes.length; i++) {
|
|
const flush = this._pendingFlushes[i];
|
|
if (peerInfo._flushTick > flush.tick) continue;
|
|
if (--flush.missing > 0) continue;
|
|
flush.onflush(true);
|
|
this._pendingFlushes.splice(i--, 1);
|
|
}
|
|
}
|
|
_withinMaxPeers() {
|
|
const e = this.explicitPeers.size;
|
|
const factor = e === 0 ? 1 : e < 2 ? 2 : e < 4 ? 3 : 4;
|
|
return factor * this._allConnections.size < this.maxPeers;
|
|
}
|
|
_flushAllMaybe() {
|
|
if (this.connecting > 0 || this._withinMaxPeers() && this._clientConnections < this.maxClientConnections) {
|
|
return false;
|
|
}
|
|
while (this._pendingFlushes.length) {
|
|
const flush = this._pendingFlushes.pop();
|
|
flush.onflush(true);
|
|
}
|
|
return true;
|
|
}
|
|
_shouldConnectExplicit() {
|
|
return !this.destroyed && !this.suspended && this.connecting < this.maxParallel;
|
|
}
|
|
_shouldConnect() {
|
|
return !this.destroyed && !this.suspended && this.connecting < this.maxParallel && this._withinMaxPeers() && this._clientConnections < this.maxClientConnections;
|
|
}
|
|
_shouldRequeue(peerInfo) {
|
|
if (this.suspended) return false;
|
|
if (peerInfo.explicit) return true;
|
|
for (const topic of peerInfo.topics) {
|
|
if (this._discovery.has(b4a.toString(topic, "hex")) && !this.destroyed) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
_connect(peerInfo, queued) {
|
|
if (peerInfo.banned || this._allConnections.has(peerInfo.publicKey)) {
|
|
if (queued) this._flushMaybe(peerInfo);
|
|
return;
|
|
}
|
|
if (this._handleFirewall(peerInfo.publicKey, null)) {
|
|
if (queued) this._flushMaybe(peerInfo);
|
|
return;
|
|
}
|
|
const relayThrough = this._maybeRelayConnection(peerInfo.forceRelaying);
|
|
const conn = this.dht.connect(peerInfo.publicKey, {
|
|
relayAddresses: peerInfo.relayAddresses,
|
|
keyPair: this.keyPair,
|
|
relayThrough
|
|
});
|
|
this._allConnections.add(conn);
|
|
this.stats.connects.client.attempted++;
|
|
this.connecting++;
|
|
this._clientConnections++;
|
|
let opened = false;
|
|
const onerror = (err) => {
|
|
if (this.relayThrough && shouldForceRelaying(err.code)) {
|
|
peerInfo.forceRelaying = true;
|
|
peerInfo.attempts = 0;
|
|
}
|
|
};
|
|
conn.on("error", onerror);
|
|
conn.on("open", () => {
|
|
opened = true;
|
|
this.stats.connects.client.opened++;
|
|
this._connectDone();
|
|
this.connections.add(conn);
|
|
conn.removeListener("error", onerror);
|
|
peerInfo._connected();
|
|
peerInfo.client = true;
|
|
this.emit("connection", conn, peerInfo);
|
|
if (queued) this._flushMaybe(peerInfo);
|
|
this.emit("update");
|
|
});
|
|
conn.on("close", () => {
|
|
if (!opened) this._connectDone();
|
|
this.stats.connects.client.closed++;
|
|
const err = getStreamError(conn);
|
|
if (shouldBan(err)) {
|
|
this._banPeer(peerInfo, true, err);
|
|
}
|
|
this.connections.delete(conn);
|
|
this._allConnections.delete(conn);
|
|
this._clientConnections--;
|
|
peerInfo._disconnected();
|
|
peerInfo.waiting = this._shouldRequeue(peerInfo) && this._timer.add(peerInfo);
|
|
this._maybeDeletePeer(peerInfo);
|
|
if (!opened && queued) this._flushMaybe(peerInfo);
|
|
this._attemptClientConnections();
|
|
this.emit("update");
|
|
});
|
|
this.emit("update");
|
|
}
|
|
_connectDone() {
|
|
this.connecting--;
|
|
if (this.connecting < this.maxParallel) this._attemptClientConnections();
|
|
if (this.connecting === 0) this._flushAllMaybe();
|
|
}
|
|
// Called when the PeerQueue indicates a connection should be attempted.
|
|
_attemptClientConnections() {
|
|
if (this._drainingQueue || this.suspended) return;
|
|
this._drainingQueue = true;
|
|
for (const peerInfo of this.explicitPeers) {
|
|
if (!this._shouldConnectExplicit()) break;
|
|
if (peerInfo.attempts >= 5 || Date.now() - peerInfo.disconnectedTime < peerInfo.attempts * 1e3) {
|
|
continue;
|
|
}
|
|
this._connect(peerInfo, false);
|
|
}
|
|
while (this._queue.length && this._shouldConnect()) {
|
|
const peerInfo = this._queue.shift();
|
|
peerInfo.queued = false;
|
|
this._connect(peerInfo, true);
|
|
}
|
|
this._drainingQueue = false;
|
|
if (this.connecting === 0) this._flushAllMaybe();
|
|
}
|
|
_handleFirewall(remotePublicKey, payload) {
|
|
if (b4a.equals(remotePublicKey, this.keyPair.publicKey)) return true;
|
|
let peerInfo = this.peers.get(b4a.toString(remotePublicKey, "hex"));
|
|
if (peerInfo && peerInfo.banned) return true;
|
|
const firewalled = this._firewall(remotePublicKey, payload);
|
|
if (firewalled) {
|
|
if (!peerInfo) peerInfo = this._upsertPeer(remotePublicKey);
|
|
this._banPeer(peerInfo, true, new Error(ERR_FIREWALL));
|
|
}
|
|
return firewalled;
|
|
}
|
|
_handleServerConnectionSwap(existing, conn) {
|
|
let closed = false;
|
|
existing.on("close", () => {
|
|
if (closed) return;
|
|
conn.removeListener("error", noop);
|
|
conn.removeListener("close", onclose);
|
|
this._handleServerConnection(conn);
|
|
});
|
|
conn.on("error", noop);
|
|
conn.on("close", onclose);
|
|
function onclose() {
|
|
closed = true;
|
|
}
|
|
}
|
|
// Called when the DHT receives a new server connection.
|
|
_handleServerConnection(conn) {
|
|
if (this.destroyed || this.suspended) {
|
|
conn.on("error", noop);
|
|
return conn.destroy(ERR_DESTROYED);
|
|
}
|
|
const existing = this._allConnections.get(conn.remotePublicKey);
|
|
if (existing) {
|
|
const existingIsOutdated = existing.rawBytesRead > 0 && existing.rawBytesWritten > 0;
|
|
const expectedInitiator = b4a.compare(conn.publicKey, conn.remotePublicKey) > 0;
|
|
const keepNew = existingIsOutdated || expectedInitiator === conn.isInitiator;
|
|
if (keepNew === false) {
|
|
existing.sendKeepAlive();
|
|
conn.on("error", noop);
|
|
conn.destroy(new Error(ERR_DUPLICATE));
|
|
return;
|
|
}
|
|
existing.on("error", noop);
|
|
existing.destroy(new Error(ERR_DUPLICATE));
|
|
this._handleServerConnectionSwap(existing, conn);
|
|
return;
|
|
}
|
|
this.stats.connects.server.opened++;
|
|
const peerInfo = this._upsertPeer(conn.remotePublicKey, null);
|
|
this.connections.add(conn);
|
|
this._allConnections.add(conn);
|
|
this._serverConnections++;
|
|
conn.on("close", () => {
|
|
const err = getStreamError(conn);
|
|
if (shouldBan(err)) {
|
|
this._banPeer(peerInfo, true, err);
|
|
}
|
|
this.connections.delete(conn);
|
|
this._allConnections.delete(conn);
|
|
this._serverConnections--;
|
|
this.stats.connects.server.closed++;
|
|
this._maybeDeletePeer(peerInfo);
|
|
this._attemptClientConnections();
|
|
this.emit("update");
|
|
});
|
|
peerInfo.client = false;
|
|
this.emit("connection", conn, peerInfo);
|
|
this.emit("update");
|
|
}
|
|
_upsertPeer(publicKey, relayAddresses) {
|
|
if (b4a.equals(publicKey, this.keyPair.publicKey)) return null;
|
|
const keyString = b4a.toString(publicKey, "hex");
|
|
let peerInfo = this.peers.get(keyString);
|
|
if (peerInfo) {
|
|
peerInfo.relayAddresses = relayAddresses;
|
|
return peerInfo;
|
|
}
|
|
peerInfo = new PeerInfo({
|
|
publicKey,
|
|
relayAddresses
|
|
});
|
|
this.peers.set(keyString, peerInfo);
|
|
return peerInfo;
|
|
}
|
|
_handleUpdate() {
|
|
this.stats.updates++;
|
|
}
|
|
_maybeDeletePeer(peerInfo) {
|
|
if (!peerInfo.shouldGC()) return;
|
|
const hasActiveConn = this._allConnections.has(peerInfo.publicKey);
|
|
if (hasActiveConn) return;
|
|
const keyString = b4a.toString(peerInfo.publicKey, "hex");
|
|
this.peers.delete(keyString);
|
|
}
|
|
/*
|
|
* Called when a peer is actively discovered during a lookup.
|
|
*
|
|
* Three conditions:
|
|
* 1. Not a known peer -- insert into queue
|
|
* 2. A known peer with normal priority -- do nothing
|
|
* 3. A known peer with low priority -- bump priority, because it's been rediscovered
|
|
*/
|
|
_handlePeer(peer, topic) {
|
|
const peerInfo = this._upsertPeer(peer.publicKey, peer.relayAddresses);
|
|
if (peerInfo) peerInfo._topic(topic);
|
|
if (!peerInfo || this._allConnections.has(peer.publicKey)) return;
|
|
if (!peerInfo.prioritized || peerInfo.server) peerInfo._reset();
|
|
if (peerInfo._updatePriority()) {
|
|
this._enqueue(peerInfo);
|
|
}
|
|
}
|
|
async _handleNetworkUpdate() {
|
|
if (!this.online) return;
|
|
this._handleNetworkChange();
|
|
}
|
|
async _handleNetworkChange() {
|
|
if (this.suspended) return;
|
|
for (const conn of this._allConnections) {
|
|
conn.sendKeepAlive();
|
|
}
|
|
const refreshes = [];
|
|
for (const discovery of this._discovery.values()) {
|
|
refreshes.push(discovery.refresh());
|
|
}
|
|
await Promise.allSettled(refreshes);
|
|
}
|
|
_banPeer(peerInfo, banned, err) {
|
|
peerInfo.ban(banned);
|
|
this.stats.bannedPeers++;
|
|
this.emit("ban", peerInfo, err);
|
|
}
|
|
status(key) {
|
|
return this._discovery.get(b4a.toString(key, "hex")) || null;
|
|
}
|
|
listen() {
|
|
if (!this.listening) {
|
|
if (this.destroyed) throw new Error("Swarm destroyed");
|
|
this.listening = this.server.listen(this.keyPair);
|
|
}
|
|
return this.listening;
|
|
}
|
|
// Object that exposes a cancellation method (destroy)
|
|
// NOTE: When you rejoin, it should reannounce + bump lookup priority
|
|
join(topic, opts = {}) {
|
|
if (this.destroyed) throw new Error("Swarm destroyed");
|
|
if (!topic) throw new Error(ERR_MISSING_TOPIC);
|
|
topic = unslab(topic);
|
|
const topicString = b4a.toString(topic, "hex");
|
|
let discovery = this._discovery.get(topicString);
|
|
if (discovery && !discovery.destroyed) {
|
|
return discovery.session(opts);
|
|
}
|
|
discovery = new PeerDiscovery(this, topic, {
|
|
limit: opts.limit,
|
|
wait: discovery ? discovery.destroy() : null,
|
|
suspended: this.suspended,
|
|
onpeer: (peer) => this._handlePeer(peer, topic)
|
|
});
|
|
this._discovery.set(topicString, discovery);
|
|
return discovery.session(opts);
|
|
}
|
|
// Returns a promise
|
|
async leave(topic) {
|
|
if (!topic) throw new Error(ERR_MISSING_TOPIC);
|
|
const topicString = b4a.toString(topic, "hex");
|
|
if (!this._discovery.has(topicString)) return Promise.resolve();
|
|
const discovery = this._discovery.get(topicString);
|
|
try {
|
|
await discovery.destroy();
|
|
} catch {
|
|
}
|
|
if (this._discovery.get(topicString) === discovery) {
|
|
this._discovery.delete(topicString);
|
|
}
|
|
}
|
|
joinPeer(publicKey) {
|
|
const peerInfo = this._upsertPeer(publicKey, null);
|
|
if (!peerInfo) return;
|
|
if (!this.explicitPeers.has(peerInfo)) {
|
|
peerInfo.explicit = true;
|
|
this.explicitPeers.add(peerInfo);
|
|
}
|
|
if (this._allConnections.has(publicKey)) return;
|
|
if (peerInfo._updatePriority()) {
|
|
this._enqueue(peerInfo);
|
|
}
|
|
}
|
|
leavePeer(publicKey) {
|
|
const keyString = b4a.toString(publicKey, "hex");
|
|
if (!this.peers.has(keyString)) return;
|
|
const peerInfo = this.peers.get(keyString);
|
|
peerInfo.explicit = false;
|
|
this.explicitPeers.delete(peerInfo);
|
|
this._maybeDeletePeer(peerInfo);
|
|
}
|
|
// Returns a promise
|
|
async flush() {
|
|
const allFlushed = [...this._discovery.values()].map((v) => v.flushed());
|
|
await Promise.all(allFlushed);
|
|
if (this._flushAllMaybe()) return true;
|
|
const pendingSize = this._allConnections.size - this.connections.size;
|
|
if (!this._queue.length && !pendingSize) return true;
|
|
return new Promise((resolve) => {
|
|
this._pendingFlushes.push({
|
|
onflush: resolve,
|
|
missing: this._queue.length + pendingSize,
|
|
tick: this._flushTick++
|
|
});
|
|
});
|
|
}
|
|
async clear() {
|
|
const cleared = Promise.allSettled([...this._discovery.values()].map((d) => d.destroy()));
|
|
this._discovery.clear();
|
|
return cleared;
|
|
}
|
|
async destroy({ force } = {}) {
|
|
if (this.destroyed && !force) return;
|
|
this.destroyed = true;
|
|
this._timer.destroy();
|
|
if (!force) await this.clear();
|
|
await this.server.close();
|
|
while (this._pendingFlushes.length) {
|
|
const flush = this._pendingFlushes.pop();
|
|
flush.onflush(false);
|
|
}
|
|
await this.dht.destroy({ force });
|
|
}
|
|
async suspend({ log = noop } = {}) {
|
|
if (this.suspended) return;
|
|
const promises = [];
|
|
promises.push(this.server.suspend({ log }));
|
|
for (const discovery of this._discovery.values()) {
|
|
promises.push(discovery.suspend({ log }));
|
|
}
|
|
const pending = [];
|
|
for (const connection of this._allConnections) {
|
|
connection.destroy();
|
|
pending.push(new Promise((resolve) => connection.on("close", resolve)));
|
|
}
|
|
this.suspended = true;
|
|
log("Suspending server and discovery... (" + promises.length + ")");
|
|
await Promise.allSettled(promises);
|
|
log("Done, suspending the dht...");
|
|
await this.dht.suspend({ log });
|
|
log("Done, swarm fully suspended");
|
|
await Promise.all(pending);
|
|
this._timer.destroy();
|
|
this._timer = new RetryTimer(this._requeue.bind(this), {
|
|
backoffs: this._timer.backoffs,
|
|
jitter: this._timer.jitter
|
|
});
|
|
this._queue = spq();
|
|
}
|
|
async resume({ log = noop } = {}) {
|
|
if (!this.suspended) return;
|
|
log("Resuming the dht");
|
|
await this.dht.resume();
|
|
log("Done, resuming the server");
|
|
await this.server.resume();
|
|
log("Done, all discovery");
|
|
for (const discovery of this._discovery.values()) {
|
|
discovery.resume();
|
|
}
|
|
this.suspended = false;
|
|
this._attemptClientConnections();
|
|
}
|
|
topics() {
|
|
return this._discovery.values();
|
|
}
|
|
};
|
|
function noop() {
|
|
}
|
|
function allowAll() {
|
|
return false;
|
|
}
|
|
function shouldForceRelaying(code) {
|
|
return code === "HOLEPUNCH_ABORTED" || code === "HOLEPUNCH_DOUBLE_RANDOMIZED_NATS" || code === "REMOTE_NOT_HOLEPUNCHABLE";
|
|
}
|
|
function shouldBan() {
|
|
return false;
|
|
}
|
|
function toRelayFunction(relayThrough) {
|
|
return typeof relayThrough === "function" ? relayThrough : (force, swarm) => force || swarm.dht.randomized ? relayThrough : null;
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/drive/shared/swarm.js
|
|
var require_swarm = __commonJS({
|
|
"../../node_modules/bare-dev/lib/drive/shared/swarm.js"(exports, module) {
|
|
var Hyperswarm = require_hyperswarm();
|
|
module.exports = function swarm(store) {
|
|
return new Hyperswarm().on("connection", (socket) => store.replicate(socket));
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/drive/list.js
|
|
var require_list2 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/drive/list.js"(exports, module) {
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var open = require_open();
|
|
module.exports = async function list(drive, opts = {}) {
|
|
const {
|
|
prefix = "/",
|
|
mount = "/",
|
|
checkout,
|
|
separator = "\n",
|
|
cwd = path.resolve("."),
|
|
quiet = true
|
|
} = opts;
|
|
const store = require_corestore2()(opts);
|
|
const swarm = require_swarm()(store);
|
|
drive = await open(drive, { store, swarm, cwd });
|
|
if (checkout) drive = drive.checkout(checkout);
|
|
const result = [];
|
|
let first = true;
|
|
for await (const entry of drive.list(prefix)) {
|
|
result.push(entry);
|
|
if (quiet) continue;
|
|
let out = path.join(path.resolve(cwd, mount), entry.key);
|
|
if (/^\s+$/.test(separator)) {
|
|
out += separator;
|
|
} else {
|
|
first ? first = false : out = separator + out;
|
|
}
|
|
process2.stdout.write(out);
|
|
}
|
|
await swarm.destroy();
|
|
return result;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/drive/mirror.js
|
|
var require_mirror = __commonJS({
|
|
"../../node_modules/bare-dev/lib/drive/mirror.js"(exports, module) {
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var open = require_open();
|
|
var symbols = {
|
|
add: "+",
|
|
remove: "-",
|
|
change: "~"
|
|
};
|
|
module.exports = async function mirror(source, destination, opts = {}) {
|
|
const {
|
|
prefix = "/",
|
|
checkout,
|
|
prune = false,
|
|
separator = "\n",
|
|
cwd = path.resolve("."),
|
|
quiet = true
|
|
} = opts;
|
|
const store = require_corestore2()(opts);
|
|
const swarm = require_swarm()(store);
|
|
source = await open(source, { store, swarm, cwd });
|
|
destination = await open(destination, { store, swarm, cwd });
|
|
if (checkout) source = source.checkout(checkout);
|
|
const result = [];
|
|
let first = false;
|
|
for await (const entry of source.mirror(destination, { prefix, prune })) {
|
|
result.push(entry);
|
|
if (quiet) continue;
|
|
let out = `${symbols[entry.op]} ${entry.key}`;
|
|
if (/^\s+$/.test(separator)) {
|
|
out += separator;
|
|
} else {
|
|
first ? first = false : out = separator + out;
|
|
}
|
|
process2.stdout.write(out);
|
|
}
|
|
await swarm.destroy();
|
|
return result;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/drive/version.js
|
|
var require_version2 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/drive/version.js"(exports, module) {
|
|
var process2 = __require("process");
|
|
var path = __require("path");
|
|
var open = require_open();
|
|
module.exports = async function version(drive, opts = {}) {
|
|
const {
|
|
separator = "\n",
|
|
cwd = path.resolve("."),
|
|
quiet = true
|
|
} = opts;
|
|
const store = require_corestore2()(opts);
|
|
const swarm = require_swarm()(store);
|
|
drive = await open(drive, { store, swarm, cwd });
|
|
if (!quiet) {
|
|
let out = drive.version;
|
|
if (/^\s+$/.test(separator)) {
|
|
out += separator;
|
|
}
|
|
process2.stdout.write(out);
|
|
}
|
|
await swarm.destroy();
|
|
return drive.version;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/drive.js
|
|
var require_drive = __commonJS({
|
|
"../../node_modules/bare-dev/lib/drive.js"(exports) {
|
|
exports.list = require_list2();
|
|
exports.mirror = require_mirror();
|
|
exports.version = require_version2();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/init/addon.js
|
|
var require_addon = __commonJS({
|
|
"../../node_modules/bare-dev/lib/init/addon.js"(exports, module) {
|
|
var fs = __require("fs/promises");
|
|
var path = __require("path");
|
|
module.exports = async function addon(opts = {}) {
|
|
const {
|
|
force = false,
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
let {
|
|
name = null
|
|
} = opts;
|
|
if (name === null) {
|
|
const pkg = __require(path.join(cwd, "package.json"));
|
|
name = pkg.name.replace(/[^a-z]/ig, "_").replace(/_+/, "_").replace(/^_|_$/, "");
|
|
}
|
|
const definition = path.join(cwd, "CMakeLists.txt");
|
|
let exists = false;
|
|
try {
|
|
await fs.access(definition);
|
|
exists = true;
|
|
} catch {
|
|
}
|
|
if (exists && !force) throw new Error(`refusing to overwrite ${definition}`);
|
|
await fs.writeFile(
|
|
definition,
|
|
`cmake_minimum_required(VERSION 3.25)
|
|
|
|
project(${name} C)
|
|
|
|
include(bare)
|
|
|
|
add_bare_module(${name})
|
|
|
|
target_sources(
|
|
\${${name}}
|
|
PRIVATE
|
|
binding.c
|
|
)
|
|
`
|
|
);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/init/appling.js
|
|
var require_appling = __commonJS({
|
|
"../../node_modules/bare-dev/lib/init/appling.js"(exports, module) {
|
|
var fs = __require("fs/promises");
|
|
var path = __require("path");
|
|
module.exports = async function appling(opts = {}) {
|
|
const {
|
|
force = false,
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
let {
|
|
name = null,
|
|
key,
|
|
version,
|
|
author,
|
|
description,
|
|
macos,
|
|
windows,
|
|
linux
|
|
} = opts;
|
|
if (name === null) {
|
|
const pkg = __require(path.join(cwd, "package.json"));
|
|
name = pkg.name.replace(/[^a-z]/ig, "_").replace(/_+/, "_").replace(/^_|_$/, "");
|
|
}
|
|
const definition = path.join(cwd, "CMakeLists.txt");
|
|
let exists = false;
|
|
try {
|
|
await fs.access(definition);
|
|
exists = true;
|
|
} catch {
|
|
}
|
|
if (exists && !force) throw new Error(`refusing to overwrite ${definition}`);
|
|
await fs.writeFile(
|
|
definition,
|
|
`cmake_minimum_required(VERSION 3.25)
|
|
|
|
project(${name} C)
|
|
|
|
include(pear)
|
|
|
|
add_pear_appling(
|
|
pear_appling
|
|
NAME "${name}"
|
|
KEY ${key}
|
|
VERSION "${version}"
|
|
AUTHOR "${author}"
|
|
DESCRIPTION "${description}"
|
|
|
|
MACOS_IDENTIFIER ${macos.identifier}
|
|
MACOS_CATEGORY ${macos.category}
|
|
MACOS_ENTITLEMENTS ${macos.entitlements.join(" ")}
|
|
MACOS_SIGNING_IDENTITY "${macos.signing.identity}"
|
|
|
|
WINDOWS_SIGNING_SUBJECT "${windows.signing.subject}"
|
|
WINDOWS_SIGNING_THUMBPRINT ${windows.signing.thumbprint}
|
|
|
|
LINUX_CATEGORY ${linux.category}
|
|
)
|
|
`
|
|
);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/init.js
|
|
var require_init = __commonJS({
|
|
"../../node_modules/bare-dev/lib/init.js"(exports) {
|
|
exports.addon = require_addon();
|
|
exports.appling = require_appling();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/vendor/sync.js
|
|
var require_sync = __commonJS({
|
|
"../../node_modules/bare-dev/lib/vendor/sync.js"(exports, module) {
|
|
var path = __require("path");
|
|
var which = require_bare_which();
|
|
var spawn = require_spawn();
|
|
var git = which.sync("git");
|
|
module.exports = function sync(root = ".", opts = {}) {
|
|
const {
|
|
submodules = true,
|
|
cwd = path.resolve("."),
|
|
quiet = true,
|
|
verbose = false
|
|
} = opts;
|
|
if (submodules) {
|
|
spawn(git, ["submodule", "update", "--init", "--recursive", root], { quiet, verbose, cwd });
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/install.js
|
|
var require_install = __commonJS({
|
|
"../../node_modules/bare-dev/lib/install.js"(exports, module) {
|
|
var fs = __require("fs");
|
|
var os = __require("os");
|
|
var path = __require("path");
|
|
var { globSync } = require_commonjs5();
|
|
module.exports = function install(opts = {}) {
|
|
const {
|
|
build = "build",
|
|
prebuilds = "prebuilds",
|
|
platform = os.platform(),
|
|
arch = os.arch(),
|
|
simulator = false,
|
|
bare = true,
|
|
node = false,
|
|
link = false,
|
|
force = false,
|
|
sync = false,
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
const info = __require(path.join(cwd, "package.json"));
|
|
const name = info.name.replace(/\//g, "+");
|
|
const extensions = [];
|
|
if (bare) extensions.push(".bare");
|
|
if (node) extensions.push(".node");
|
|
const dir = path.resolve(cwd, prebuilds, `${platform}-${arch}${simulator ? "-simulator" : ""}`);
|
|
const targets = extensions.map((ext) => path.join(dir, name + ext));
|
|
if (force || !targets.every((target) => isFile(target))) {
|
|
if (sync) require_sync()(opts);
|
|
if (isFile(path.join(cwd, "CMakeLists.txt"))) {
|
|
require_configure()(opts);
|
|
require_build()(opts);
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
for (const target of targets) {
|
|
const [addon] = globSync(path.join(cwd, build, `**/${name}${path.extname(target)}`), {
|
|
windowsPathsNoEscape: true
|
|
});
|
|
if (addon) {
|
|
try {
|
|
fs.unlinkSync(target);
|
|
} catch {
|
|
}
|
|
if (link) {
|
|
fs.symlinkSync(addon, target);
|
|
} else {
|
|
fs.copyFileSync(addon, target);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
function isFile(file) {
|
|
try {
|
|
return fs.statSync(file).isFile();
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/ios/shared/xcrun.js
|
|
var require_xcrun = __commonJS({
|
|
"../../node_modules/bare-dev/lib/ios/shared/xcrun.js"(exports, module) {
|
|
var which = require_bare_which();
|
|
var exec = require_exec();
|
|
var xcrun = module.exports = exports = function xcrun2() {
|
|
return which.sync("xcrun");
|
|
};
|
|
exports.find = function find(tool, opts = {}) {
|
|
return exec(xcrun(), ["--find", tool], opts).trim();
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/ios/shared/simctl.js
|
|
var require_simctl = __commonJS({
|
|
"../../node_modules/bare-dev/lib/ios/shared/simctl.js"(exports, module) {
|
|
var path = __require("path");
|
|
var which = require_bare_which();
|
|
var exec = require_exec();
|
|
var spawn = require_spawn();
|
|
var xcrun = require_xcrun();
|
|
var simctl = module.exports = exports = function simctl2() {
|
|
return xcrun.find("simctl");
|
|
};
|
|
exports.list = function list(opts) {
|
|
const json = JSON.parse(
|
|
exec(simctl(), ["list", "--json", "--no-escape-slashes", "devices", "available"], opts)
|
|
);
|
|
return Object.values(json.devices).flatMap((devices) => devices.map((device) => {
|
|
return {
|
|
id: device.udid,
|
|
name: device.name,
|
|
state: device.state.toLowerCase()
|
|
};
|
|
}));
|
|
};
|
|
exports.launch = function launch(device, opts = {}) {
|
|
const {
|
|
open = false
|
|
} = opts;
|
|
spawn(simctl(), ["boot", device], opts);
|
|
if (open) {
|
|
spawn(which.sync("open"), ["-a", "Simulator.app"], opts);
|
|
}
|
|
};
|
|
exports.install = function install(device, app, opts = {}) {
|
|
const {
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
app = path.resolve(cwd, app);
|
|
spawn(simctl(), ["install", device, app], opts);
|
|
};
|
|
exports.start = function start(device, app, opts = {}) {
|
|
const {
|
|
attach = false,
|
|
waitForDebugger = false,
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
app = path.resolve(cwd, app);
|
|
const id = exec(which.sync("defaults"), ["read", path.join(app, "Info"), "CFBundleIdentifier"], opts).trim();
|
|
const args = ["launch", "--terminate-running-process"];
|
|
if (attach) args.push("--console-pty");
|
|
if (waitForDebugger) args.push("--wait-for-debugger");
|
|
spawn(simctl(), [...args, device, id], opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/ios/device/list.js
|
|
var require_list3 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/ios/device/list.js"(exports, module) {
|
|
var process2 = __require("process");
|
|
var simctl = require_simctl();
|
|
module.exports = function list(opts = {}) {
|
|
const {
|
|
separator = "\n",
|
|
quiet = true
|
|
} = opts;
|
|
const devices = simctl.list(opts);
|
|
if (!quiet) {
|
|
let first = true;
|
|
for (const device of devices) {
|
|
let out = device.name;
|
|
if (/^\s+$/.test(separator)) {
|
|
out += separator;
|
|
} else {
|
|
first ? first = false : out = separator + out;
|
|
}
|
|
process2.stdout.write(out);
|
|
}
|
|
}
|
|
return devices;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/ios/device/launch.js
|
|
var require_launch2 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/ios/device/launch.js"(exports, module) {
|
|
var simctl = require_simctl();
|
|
var list = require_list3();
|
|
module.exports = function launch(name = null, opts) {
|
|
if (typeof name === "object" && name !== null) {
|
|
opts = name;
|
|
name = null;
|
|
}
|
|
const [device = null] = list().filter((candidate) => name ? candidate.name === name : true);
|
|
if (device === null) {
|
|
throw new Error(`launch() could not find device "${device}"`);
|
|
}
|
|
if (device.state !== "booted") simctl.launch(device.id, opts);
|
|
return device.id;
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/ios/device.js
|
|
var require_device2 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/ios/device.js"(exports) {
|
|
exports.launch = require_launch2();
|
|
exports.list = require_list3();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/ios/run.js
|
|
var require_run2 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/ios/run.js"(exports, module) {
|
|
var path = __require("path");
|
|
var { globSync } = require_commonjs5();
|
|
var launch = require_launch2();
|
|
var simctl = require_simctl();
|
|
module.exports = function run(app = null, opts = {}) {
|
|
const {
|
|
device = null,
|
|
cwd = path.resolve(".")
|
|
} = opts;
|
|
if (app === null) {
|
|
[app = null] = globSync(path.join(cwd, "**/*.app"), {
|
|
ignore: [
|
|
"**/vendor/**"
|
|
]
|
|
});
|
|
if (app === null) {
|
|
throw new Error("no .app found");
|
|
}
|
|
}
|
|
const id = launch(device, opts);
|
|
app = path.resolve(cwd, app);
|
|
simctl.install(id, app, opts);
|
|
simctl.start(id, app, opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/ios.js
|
|
var require_ios = __commonJS({
|
|
"../../node_modules/bare-dev/lib/ios.js"(exports) {
|
|
exports.device = require_device2();
|
|
exports.run = require_run2();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/test.js
|
|
var require_test = __commonJS({
|
|
"../../node_modules/bare-dev/lib/test.js"(exports, module) {
|
|
var path = __require("path");
|
|
var spawn = require_spawn();
|
|
var cmake = require_cmake();
|
|
module.exports = function test(opts = {}) {
|
|
exports.ctest(opts);
|
|
};
|
|
exports.ctest = function(opts = {}) {
|
|
const {
|
|
build = "build",
|
|
timeout = 30,
|
|
debug = false,
|
|
cwd = path.resolve("."),
|
|
verbose = false
|
|
} = opts;
|
|
const args = [
|
|
"--test-dir",
|
|
path.resolve(cwd, build),
|
|
"--build-config",
|
|
debug ? "Debug" : "Release",
|
|
"--timeout",
|
|
timeout,
|
|
"--output-on-failure"
|
|
];
|
|
if (verbose) args.push("--verbose");
|
|
else args.push("--progress");
|
|
spawn(cmake.ctest(), args, opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/vendor/checkout.js
|
|
var require_checkout = __commonJS({
|
|
"../../node_modules/bare-dev/lib/vendor/checkout.js"(exports, module) {
|
|
var path = __require("path");
|
|
var which = require_bare_which();
|
|
var spawn = require_spawn();
|
|
var sync = require_sync();
|
|
var git = which.sync("git");
|
|
module.exports = function checkout(root, version, opts = {}) {
|
|
const {
|
|
submodules = true,
|
|
cwd = path.resolve("."),
|
|
quiet = true,
|
|
verbose = false
|
|
} = opts;
|
|
if (submodules) {
|
|
spawn(git, ["-C", root, "fetch"], { quiet, verbose, cwd });
|
|
spawn(git, ["-C", root, "checkout", "--force", version], { quiet, verbose, cwd });
|
|
spawn(git, ["stage", root], { quiet, verbose, cwd });
|
|
}
|
|
sync(root, opts);
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/vendor/clean.js
|
|
var require_clean2 = __commonJS({
|
|
"../../node_modules/bare-dev/lib/vendor/clean.js"(exports, module) {
|
|
var path = __require("path");
|
|
var which = require_bare_which();
|
|
var spawn = require_spawn();
|
|
var git = which.sync("git");
|
|
module.exports = function clean(root = ".", opts = {}) {
|
|
const {
|
|
submodules = true,
|
|
cwd = path.resolve("."),
|
|
quiet = true,
|
|
verbose = false
|
|
} = opts;
|
|
if (submodules) {
|
|
spawn(git, ["submodule", "deinit", "--force", root], { quiet, verbose, cwd });
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/lib/vendor.js
|
|
var require_vendor = __commonJS({
|
|
"../../node_modules/bare-dev/lib/vendor.js"(exports) {
|
|
exports.checkout = require_checkout();
|
|
exports.clean = require_clean2();
|
|
exports.sync = require_sync();
|
|
}
|
|
});
|
|
|
|
// ../../node_modules/bare-dev/index.js
|
|
var require_bare_dev = __commonJS({
|
|
"../../node_modules/bare-dev/index.js"(exports) {
|
|
exports.android = require_android();
|
|
exports.build = require_build();
|
|
exports.bundle = require_bundle();
|
|
exports.clean = require_clean();
|
|
exports.configure = require_configure();
|
|
exports.dependencies = require_dependencies();
|
|
exports.drive = require_drive();
|
|
exports.init = require_init();
|
|
exports.install = require_install();
|
|
exports.ios = require_ios();
|
|
exports.paths = require_paths();
|
|
exports.test = require_test();
|
|
exports.vendor = require_vendor();
|
|
}
|
|
});
|
|
|
|
// ../../bare-lib-entry-bareDev.js
|
|
var bare_lib_entry_bareDev_exports = {};
|
|
__export(bare_lib_entry_bareDev_exports, {
|
|
default: () => bare_lib_entry_bareDev_default
|
|
});
|
|
var import_bare_dev = __toESM(require_bare_dev());
|
|
var bare_lib_entry_bareDev_default = import_bare_dev.default;
|
|
return __toCommonJS(bare_lib_entry_bareDev_exports);
|
|
})();
|
|
/*! Bundled license information:
|
|
|
|
safe-buffer/index.js:
|
|
(*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
|
|
|
|
object-assign/index.js:
|
|
(*
|
|
object-assign
|
|
(c) Sindre Sorhus
|
|
@license MIT
|
|
*)
|
|
|
|
is-natural-number/index.js:
|
|
(*!
|
|
* is-natural-number.js | MIT (c) Shinnosuke Watanabe
|
|
* https://github.com/shinnn/is-natural-number.js
|
|
*)
|
|
|
|
strip-dirs/index.js:
|
|
(*!
|
|
* strip-dirs | MIT (c) Shinnosuke Watanabe
|
|
* https://github.com/shinnn/node-strip-dirs
|
|
*)
|
|
*/
|
|
;(function(){var g=globalThis;var s="__bare_os_stdlib__";g[s]=g[s]||{};var e=typeof __bare_os_bundle_exports__!=="undefined"?__bare_os_bundle_exports__:void 0;var v=e!=null&&typeof e==="object"&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e;g[s]["bareDev"]=v;})();
|