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)
|
|
// TODO: 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 todo 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("node:events");
|
|
var node_stream_1 = __importDefault(__require("node:stream"));
|
|
var node_string_decoder_1 = __require("node: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("node:path");
|
|
var node_url_1 = __require("node:url");
|
|
var fs_1 = __require("fs");
|
|
var actualFS = __importStar(__require("node:fs"));
|
|
var realpathSync = fs_1.realpathSync.native;
|
|
var promises_1 = __require("node: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:', ...]
|
|
// XXX: would be nice to 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("node: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 TODO FIXME
|
|
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("not implemented");
|
|
};
|
|
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 = {
|
|
// TODO: 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,
|
|
// TODO: 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;
|
|
// hack to be able to 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;
|
|
}
|
|
// TODO: 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);
|
|
}
|
|
// TODO: 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);
|
|
}
|
|
// TODO: get rid of this / deprecate it?
|
|
undownload(range) {
|
|
range.destroy(null);
|
|
}
|
|
// TODO: 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
|
|
// TODO: 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;
|
|
}
|
|
// TODO: Allow announce to be an argument to this
|
|
// TODO: 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)
|
|
// TODO: 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]||{};g[s]["bareDev"]=typeof __bare_os_bundle_exports__!=="undefined"?__bare_os_bundle_exports__:void 0;})();
|