@vmg-anysphere/napi-rs-cli
Version:
Cli tools for napi-rs
1,253 lines (1,220 loc) • 532 kB
JavaScript
//#region rolldown:runtime
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 __commonJS = (cb, mod) => function() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let node_path = require("node:path");
node_path = __toESM(node_path);
let colorette = require("colorette");
colorette = __toESM(colorette);
let clipanion = require("clipanion");
clipanion = __toESM(clipanion);
let debug = require("debug");
debug = __toESM(debug);
let node_fs_promises = require("node:fs/promises");
node_fs_promises = __toESM(node_fs_promises);
let node_child_process = require("node:child_process");
node_child_process = __toESM(node_child_process);
let node_fs = require("node:fs");
node_fs = __toESM(node_fs);
let es_toolkit = require("es-toolkit");
es_toolkit = __toESM(es_toolkit);
let node_crypto = require("node:crypto");
node_crypto = __toESM(node_crypto);
let node_module = require("node:module");
node_module = __toESM(node_module);
let node_os = require("node:os");
node_os = __toESM(node_os);
let semver = require("semver");
semver = __toESM(semver);
let js_yaml = require("js-yaml");
js_yaml = __toESM(js_yaml);
let typanion = require("typanion");
typanion = __toESM(typanion);
let empathic_find = require("empathic/find");
empathic_find = __toESM(empathic_find);
let __octokit_rest = require("@octokit/rest");
__octokit_rest = __toESM(__octokit_rest);
//#region ../node_modules/@oxc-project/runtime/src/helpers/typeof.js
var require_typeof = /* @__PURE__ */ __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/typeof.js": ((exports, module) => {
function _typeof$2(o) {
"@babel/helpers - typeof";
return module.exports = _typeof$2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
return typeof o$1;
} : function(o$1) {
return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
}, module.exports.__esModule = true, module.exports["default"] = module.exports, _typeof$2(o);
}
module.exports = _typeof$2, module.exports.__esModule = true, module.exports["default"] = module.exports;
}) });
//#endregion
//#region ../node_modules/@oxc-project/runtime/src/helpers/toPrimitive.js
var require_toPrimitive = /* @__PURE__ */ __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/toPrimitive.js": ((exports, module) => {
var _typeof$1 = require_typeof()["default"];
function toPrimitive$1(t, r) {
if ("object" != _typeof$1(t) || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof$1(i)) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
module.exports = toPrimitive$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
}) });
//#endregion
//#region ../node_modules/@oxc-project/runtime/src/helpers/toPropertyKey.js
var require_toPropertyKey = /* @__PURE__ */ __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/toPropertyKey.js": ((exports, module) => {
var _typeof = require_typeof()["default"];
var toPrimitive = require_toPrimitive();
function toPropertyKey$1(t) {
var i = toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : i + "";
}
module.exports = toPropertyKey$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
}) });
//#endregion
//#region ../node_modules/@oxc-project/runtime/src/helpers/defineProperty.js
var require_defineProperty = /* @__PURE__ */ __commonJS({ "../node_modules/@oxc-project/runtime/src/helpers/defineProperty.js": ((exports, module) => {
var toPropertyKey = require_toPropertyKey();
function _defineProperty$11(e, r, t) {
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
module.exports = _defineProperty$11, module.exports.__esModule = true, module.exports["default"] = module.exports;
}) });
//#endregion
//#region src/def/artifacts.ts
var import_defineProperty$10 = /* @__PURE__ */ __toESM(require_defineProperty(), 1);
var BaseArtifactsCommand = class extends clipanion.Command {
constructor(..._args) {
super(..._args);
(0, import_defineProperty$10.default)(this, "cwd", clipanion.Option.String("--cwd", process.cwd(), { description: "The working directory of where napi command will be executed in, all other paths options are relative to this path" }));
(0, import_defineProperty$10.default)(this, "configPath", clipanion.Option.String("--config-path,-c", { description: "Path to `napi` config json file" }));
(0, import_defineProperty$10.default)(this, "packageJsonPath", clipanion.Option.String("--package-json-path", "package.json", { description: "Path to `package.json`" }));
(0, import_defineProperty$10.default)(this, "outputDir", clipanion.Option.String("--output-dir,-o,-d", "./artifacts", { description: "Path to the folder where all built `.node` files put, same as `--output-dir` of build command" }));
(0, import_defineProperty$10.default)(this, "npmDir", clipanion.Option.String("--npm-dir", "npm", { description: "Path to the folder where the npm packages put" }));
(0, import_defineProperty$10.default)(this, "buildOutputDir", clipanion.Option.String("--build-output-dir", { description: "Path to the build output dir, only needed when targets contains `wasm32-wasi-*`" }));
}
getOptions() {
return {
cwd: this.cwd,
configPath: this.configPath,
packageJsonPath: this.packageJsonPath,
outputDir: this.outputDir,
npmDir: this.npmDir,
buildOutputDir: this.buildOutputDir
};
}
};
(0, import_defineProperty$10.default)(BaseArtifactsCommand, "paths", [["artifacts"]]);
(0, import_defineProperty$10.default)(BaseArtifactsCommand, "usage", clipanion.Command.Usage({ description: "Copy artifacts from Github Actions into npm packages and ready to publish" }));
function applyDefaultArtifactsOptions(options) {
return {
cwd: process.cwd(),
packageJsonPath: "package.json",
outputDir: "./artifacts",
npmDir: "npm",
...options
};
}
//#endregion
//#region src/utils/log.ts
debug.default.formatters.i = (v) => {
return colorette.green(v);
};
const debugFactory = (namespace) => {
const debug$9 = (0, debug.default)(`napi:${namespace}`);
debug$9.info = (...args) => console.error(colorette.black(colorette.bgGreen(" INFO ")), ...args);
debug$9.warn = (...args) => console.error(colorette.black(colorette.bgYellow(" WARNING ")), ...args);
debug$9.error = (...args) => console.error(colorette.white(colorette.bgRed(" ERROR ")), ...args.map((arg) => arg instanceof Error ? arg.stack ?? arg.message : arg));
return debug$9;
};
const debug$8 = debugFactory("utils");
//#endregion
//#region package.json
var name = "@vmg-anysphere/napi-rs-cli";
var version$1 = "3.2.0-modules.3";
var description = "Cli tools for napi-rs";
var author = "LongYinan <lynweklm@gmail.com>";
var homepage = "https://github.com/napi-rs/napi-rs";
var license = "MIT";
var type = "module";
var engines = { "node": ">= 16" };
var bin = {
"napi": "./dist/cli.js",
"napi-raw": "./cli.mjs"
};
var main = "./dist/index.cjs";
var module$1 = "./dist/index.js";
var types = "./dist/index.d.ts";
var exports$1 = {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./package.json": "./package.json"
};
var files = [
"dist",
"src",
"!__tests__"
];
var keywords = [
"cli",
"rust",
"napi",
"n-api",
"node-api",
"node-addon",
"neon"
];
var maintainers = [{
"name": "LongYinan",
"email": "lynweklm@gmail.com",
"homepage": "https://github.com/Brooooooklyn"
}, {
"name": "forehalo",
"homepage": "https://github.com/forehalo"
}];
var repository = {
"type": "git",
"url": "git+https://github.com/napi-rs/napi-rs.git"
};
var publishConfig = {
"registry": "https://registry.npmjs.org/",
"access": "public"
};
var bugs = { "url": "https://github.com/napi-rs/napi-rs/issues" };
var dependencies = {
"@inquirer/prompts": "^7.8.4",
"@napi-rs/cross-toolchain": "^1.0.3",
"@napi-rs/wasm-tools": "^1.0.1",
"@octokit/rest": "^22.0.0",
"clipanion": "^4.0.0-rc.4",
"colorette": "^2.0.20",
"debug": "^4.4.1",
"emnapi": "^1.5.0",
"empathic": "^2.0.0",
"es-toolkit": "^1.39.10",
"js-yaml": "^4.1.0",
"semver": "^7.7.2",
"typanion": "^3.14.0"
};
var devDependencies = {
"@emnapi/core": "^1.5.0",
"@emnapi/runtime": "^1.5.0",
"@oxc-node/core": "^0.0.32",
"@std/toml": "npm:@jsr/std__toml@^1.0.10",
"@types/debug": "^4.1.12",
"@types/inquirer": "^9.0.9",
"@types/js-yaml": "^4.0.9",
"@types/node": "^24.3.1",
"@types/semver": "^7.7.1",
"ava": "^6.4.1",
"env-paths": "^3.0.0",
"prettier": "^3.6.2",
"tsdown": "^0.15.0",
"tslib": "^2.8.1",
"typescript": "^5.9.2"
};
var peerDependencies = {
"@emnapi/runtime": "^1.1.0",
"emnapi": "^1.1.0"
};
var peerDependenciesMeta = {
"@emnapi/runtime": { "optional": true },
"emnapi": { "optional": true }
};
var funding = {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
};
var scripts = {
"codegen": "node --import @oxc-node/core/register ./codegen/index.ts",
"build": "tsdown",
"test": "node --import @oxc-node/core/register ../node_modules/ava/entrypoints/cli.mjs"
};
var ava = {
"extensions": { "ts": "module" },
"timeout": "1m",
"files": ["**/__tests__/**/*.spec.ts", "e2e/**/*.spec.ts"]
};
var package_default = {
name,
version: version$1,
description,
author,
homepage,
license,
type,
engines,
bin,
main,
module: module$1,
types,
exports: exports$1,
files,
keywords,
maintainers,
repository,
publishConfig,
bugs,
dependencies,
devDependencies,
peerDependencies,
peerDependenciesMeta,
funding,
scripts,
ava
};
//#endregion
//#region src/utils/misc.ts
const readFileAsync = node_fs_promises.readFile;
const writeFileAsync = node_fs_promises.writeFile;
const unlinkAsync = node_fs_promises.unlink;
const copyFileAsync = node_fs_promises.copyFile;
const mkdirAsync = node_fs_promises.mkdir;
const statAsync = node_fs_promises.stat;
const readdirAsync = node_fs_promises.readdir;
function fileExists(path$1) {
return (0, node_fs_promises.access)(path$1).then(() => true, () => false);
}
async function dirExistsAsync(path$1) {
try {
return (await statAsync(path$1)).isDirectory();
} catch {
return false;
}
}
function pick$1(o, ...keys) {
return keys.reduce((acc, key) => {
acc[key] = o[key];
return acc;
}, {});
}
async function updatePackageJson(path$1, partial) {
if (!await fileExists(path$1)) {
debug$8(`File not exists ${path$1}`);
return;
}
const old = JSON.parse(await readFileAsync(path$1, "utf8"));
await writeFileAsync(path$1, JSON.stringify({
...old,
...partial
}, null, 2));
}
const CLI_VERSION = package_default.version;
//#endregion
//#region src/utils/target.ts
const SUB_SYSTEMS = new Set(["android", "ohos"]);
const AVAILABLE_TARGETS = [
"aarch64-apple-darwin",
"aarch64-linux-android",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"aarch64-unknown-linux-ohos",
"aarch64-pc-windows-msvc",
"x86_64-apple-darwin",
"x86_64-pc-windows-msvc",
"x86_64-pc-windows-gnu",
"x86_64-unknown-linux-gnu",
"x86_64-unknown-linux-musl",
"x86_64-unknown-linux-ohos",
"x86_64-unknown-freebsd",
"i686-pc-windows-msvc",
"armv7-unknown-linux-gnueabihf",
"armv7-unknown-linux-musleabihf",
"armv7-linux-androideabi",
"universal-apple-darwin",
"loongarch64-unknown-linux-gnu",
"riscv64gc-unknown-linux-gnu",
"powerpc64le-unknown-linux-gnu",
"s390x-unknown-linux-gnu",
"wasm32-wasi-preview1-threads",
"wasm32-wasip1-threads"
];
const DEFAULT_TARGETS = [
"x86_64-apple-darwin",
"aarch64-apple-darwin",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu"
];
const TARGET_LINKER = {
"aarch64-unknown-linux-musl": "aarch64-linux-musl-gcc",
"loongarch64-unknown-linux-gnu": "loongarch64-linux-gnu-gcc-13",
"riscv64gc-unknown-linux-gnu": "riscv64-linux-gnu-gcc",
"powerpc64le-unknown-linux-gnu": "powerpc64le-linux-gnu-gcc",
"s390x-unknown-linux-gnu": "s390x-linux-gnu-gcc"
};
const CpuToNodeArch = {
x86_64: "x64",
aarch64: "arm64",
i686: "ia32",
armv7: "arm",
loongarch64: "loong64",
riscv64gc: "riscv64",
powerpc64le: "ppc64"
};
const SysToNodePlatform = {
linux: "linux",
freebsd: "freebsd",
darwin: "darwin",
windows: "win32",
ohos: "openharmony"
};
const UniArchsByPlatform = { darwin: ["x64", "arm64"] };
/**
* A triple is a specific format for specifying a target architecture.
* Triples may be referred to as a target triple which is the architecture for the artifact produced, and the host triple which is the architecture that the compiler is running on.
* The general format of the triple is `<arch><sub>-<vendor>-<sys>-<abi>` where:
* - `arch` = The base CPU architecture, for example `x86_64`, `i686`, `arm`, `thumb`, `mips`, etc.
* - `sub` = The CPU sub-architecture, for example `arm` has `v7`, `v7s`, `v5te`, etc.
* - `vendor` = The vendor, for example `unknown`, `apple`, `pc`, `nvidia`, etc.
* - `sys` = The system name, for example `linux`, `windows`, `darwin`, etc. none is typically used for bare-metal without an OS.
* - `abi` = The ABI, for example `gnu`, `android`, `eabi`, etc.
*/
function parseTriple(rawTriple) {
if (rawTriple === "wasm32-wasi" || rawTriple === "wasm32-wasi-preview1-threads" || rawTriple.startsWith("wasm32-wasip")) return {
triple: rawTriple,
platformArchABI: "wasm32-wasi",
platform: "wasi",
arch: "wasm32",
abi: "wasi"
};
const triples = (rawTriple.endsWith("eabi") ? `${rawTriple.slice(0, -4)}-eabi` : rawTriple).split("-");
let cpu;
let sys;
let abi = null;
if (triples.length === 2) [cpu, sys] = triples;
else [cpu, , sys, abi = null] = triples;
if (abi && SUB_SYSTEMS.has(abi)) {
sys = abi;
abi = null;
}
const platform = SysToNodePlatform[sys] ?? sys;
const arch = CpuToNodeArch[cpu] ?? cpu;
return {
triple: rawTriple,
platformArchABI: abi ? `${platform}-${arch}-${abi}` : `${platform}-${arch}`,
platform,
arch,
abi
};
}
function getSystemDefaultTarget() {
const triple = (0, node_child_process.execSync)(`rustc -vV`, { env: process.env }).toString("utf8").split("\n").find((line) => line.startsWith("host: "))?.slice(6);
if (!triple) throw new TypeError(`Can not parse target triple from host`);
return parseTriple(triple);
}
function getTargetLinker(target) {
return TARGET_LINKER[target];
}
function targetToEnvVar(target) {
return target.replace(/-/g, "_").toUpperCase();
}
//#endregion
//#region src/utils/version.ts
let NapiVersion = /* @__PURE__ */ function(NapiVersion$1) {
NapiVersion$1[NapiVersion$1["Napi1"] = 1] = "Napi1";
NapiVersion$1[NapiVersion$1["Napi2"] = 2] = "Napi2";
NapiVersion$1[NapiVersion$1["Napi3"] = 3] = "Napi3";
NapiVersion$1[NapiVersion$1["Napi4"] = 4] = "Napi4";
NapiVersion$1[NapiVersion$1["Napi5"] = 5] = "Napi5";
NapiVersion$1[NapiVersion$1["Napi6"] = 6] = "Napi6";
NapiVersion$1[NapiVersion$1["Napi7"] = 7] = "Napi7";
NapiVersion$1[NapiVersion$1["Napi8"] = 8] = "Napi8";
NapiVersion$1[NapiVersion$1["Napi9"] = 9] = "Napi9";
return NapiVersion$1;
}({});
const NAPI_VERSION_MATRIX = new Map([
[NapiVersion.Napi1, "8.6.0 | 9.0.0 | 10.0.0"],
[NapiVersion.Napi2, "8.10.0 | 9.3.0 | 10.0.0"],
[NapiVersion.Napi3, "6.14.2 | 8.11.2 | 9.11.0 | 10.0.0"],
[NapiVersion.Napi4, "10.16.0 | 11.8.0 | 12.0.0"],
[NapiVersion.Napi5, "10.17.0 | 12.11.0 | 13.0.0"],
[NapiVersion.Napi6, "10.20.0 | 12.17.0 | 14.0.0"],
[NapiVersion.Napi7, "10.23.0 | 12.19.0 | 14.12.0 | 15.0.0"],
[NapiVersion.Napi8, "12.22.0 | 14.17.0 | 15.12.0 | 16.0.0"],
[NapiVersion.Napi9, "18.17.0 | 20.3.0 | 21.1.0"]
]);
function parseNodeVersion(v) {
const matches = v.match(/v?([0-9]+)\.([0-9]+)\.([0-9]+)/i);
if (!matches) throw new Error("Unknown node version number: " + v);
const [, major, minor, patch] = matches;
return {
major: parseInt(major),
minor: parseInt(minor),
patch: parseInt(patch)
};
}
function requiredNodeVersions(napiVersion) {
const requirement = NAPI_VERSION_MATRIX.get(napiVersion);
if (!requirement) return [parseNodeVersion("10.0.0")];
return requirement.split("|").map(parseNodeVersion);
}
function toEngineRequirement(versions) {
const requirements = [];
versions.forEach((v, i) => {
let req = "";
if (i !== 0) {
const lastVersion = versions[i - 1];
req += `< ${lastVersion.major + 1}`;
}
req += `${i === 0 ? "" : " || "}>= ${v.major}.${v.minor}.${v.patch}`;
requirements.push(req);
});
return requirements.join(" ");
}
function napiEngineRequirement(napiVersion) {
return toEngineRequirement(requiredNodeVersions(napiVersion));
}
//#endregion
//#region src/utils/metadata.ts
async function parseMetadata(manifestPath) {
if (!node_fs.default.existsSync(manifestPath)) throw new Error(`No crate found in manifest: ${manifestPath}`);
const childProcess = (0, node_child_process.spawn)("cargo", [
"metadata",
"--manifest-path",
manifestPath,
"--format-version",
"1"
], { stdio: "pipe" });
let stdout = "";
let stderr = "";
let status = 0;
childProcess.stdout.on("data", (data) => {
stdout += data;
});
childProcess.stderr.on("data", (data) => {
stderr += data;
});
await new Promise((resolve$8) => {
childProcess.on("close", (code) => {
status = code ?? 0;
resolve$8();
});
});
if (status !== 0) {
const simpleMessage = `cargo metadata exited with code ${status}`;
throw new Error(`${simpleMessage} and error message:\n\n${stderr}`, { cause: new Error(simpleMessage) });
}
try {
return JSON.parse(stdout);
} catch (e) {
throw new Error("Failed to parse cargo metadata JSON", { cause: e });
}
}
//#endregion
//#region src/utils/config.ts
async function readNapiConfig(path$1, configPath) {
if (configPath && !await fileExists(configPath)) throw new Error(`NAPI-RS config not found at ${configPath}`);
if (!await fileExists(path$1)) throw new Error(`package.json not found at ${path$1}`);
const content = await readFileAsync(path$1, "utf8");
let pkgJson;
try {
pkgJson = JSON.parse(content);
} catch (e) {
throw new Error(`Failed to parse package.json at ${path$1}`, { cause: e });
}
let separatedConfig;
if (configPath) {
const configContent = await readFileAsync(configPath, "utf8");
try {
separatedConfig = JSON.parse(configContent);
} catch (e) {
throw new Error(`Failed to parse NAPI-RS config at ${configPath}`, { cause: e });
}
}
const userNapiConfig = pkgJson.napi ?? {};
if (pkgJson.napi && separatedConfig) {
const pkgJsonPath = (0, colorette.underline)(path$1);
const configPathUnderline = (0, colorette.underline)(configPath);
console.warn((0, colorette.yellow)(`Both napi field in ${pkgJsonPath} and [NAPI-RS config](${configPathUnderline}) file are found, the NAPI-RS config file will be used.`));
Object.assign(userNapiConfig, separatedConfig);
}
const napiConfig = (0, es_toolkit.merge)({
binaryName: "index",
packageName: pkgJson.name,
targets: [],
packageJson: pkgJson,
npmClient: "npm"
}, (0, es_toolkit.omit)(userNapiConfig, ["targets"]));
let targets = userNapiConfig.targets ?? [];
if (userNapiConfig?.name) {
console.warn((0, colorette.yellow)(`[DEPRECATED] napi.name is deprecated, use napi.binaryName instead.`));
napiConfig.binaryName = userNapiConfig.name;
}
if (!targets.length) {
let deprecatedWarned = false;
const warning = (0, colorette.yellow)(`[DEPRECATED] napi.triples is deprecated, use napi.targets instead.`);
if (userNapiConfig.triples?.defaults) {
deprecatedWarned = true;
console.warn(warning);
targets = targets.concat(DEFAULT_TARGETS);
}
if (userNapiConfig.triples?.additional?.length) {
targets = targets.concat(userNapiConfig.triples.additional);
if (!deprecatedWarned) console.warn(warning);
}
}
if (new Set(targets).size !== targets.length) {
const duplicateTarget = targets.find((target, index) => targets.indexOf(target) !== index);
throw new Error(`Duplicate targets are not allowed: ${duplicateTarget}`);
}
napiConfig.targets = targets.map(parseTriple);
return napiConfig;
}
//#endregion
//#region src/utils/cargo.ts
function tryInstallCargoBinary(name$1, bin$1) {
if (detectCargoBinary(bin$1)) {
debug$8("Cargo binary already installed: %s", name$1);
return;
}
try {
debug$8("Installing cargo binary: %s", name$1);
(0, node_child_process.execSync)(`cargo install ${name$1}`, { stdio: "inherit" });
} catch (e) {
throw new Error(`Failed to install cargo binary: ${name$1}`, { cause: e });
}
}
function detectCargoBinary(bin$1) {
debug$8("Detecting cargo binary: %s", bin$1);
try {
(0, node_child_process.execSync)(`cargo help ${bin$1}`, { stdio: "ignore" });
debug$8("Cargo binary detected: %s", bin$1);
return true;
} catch {
debug$8("Cargo binary not detected: %s", bin$1);
return false;
}
}
//#endregion
//#region src/utils/typegen.ts
const TOP_LEVEL_NAMESPACE = "__TOP_LEVEL_MODULE__";
const DEFAULT_TYPE_DEF_HEADER = `/* auto-generated by NAPI-RS (CURSOR FORK 1.0) */
/* eslint-disable */
`;
var TypeDefKind = /* @__PURE__ */ function(TypeDefKind$1) {
TypeDefKind$1["Const"] = "const";
TypeDefKind$1["Enum"] = "enum";
TypeDefKind$1["StringEnum"] = "string_enum";
TypeDefKind$1["Interface"] = "interface";
TypeDefKind$1["Type"] = "type";
TypeDefKind$1["Fn"] = "fn";
TypeDefKind$1["Struct"] = "struct";
TypeDefKind$1["Extends"] = "extends";
TypeDefKind$1["Impl"] = "impl";
return TypeDefKind$1;
}(TypeDefKind || {});
function prettyPrint(line, constEnum, ident, ambient = false) {
let s = line.js_doc ?? "";
switch (line.kind) {
case TypeDefKind.Interface:
s += `export interface ${line.name} {\n${line.def}\n}`;
break;
case TypeDefKind.Type:
s += `export type ${line.name} = \n${line.def}`;
break;
case TypeDefKind.Enum:
const enumName = constEnum ? "const enum" : "enum";
s += `${exportDeclare(ambient)} ${enumName} ${line.name} {\n${line.def}\n}`;
break;
case TypeDefKind.StringEnum:
if (constEnum) s += `${exportDeclare(ambient)} const enum ${line.name} {\n${line.def}\n}`;
else s += `export type ${line.name} = ${line.def.replaceAll(/.*=/g, "").replaceAll(",", "|")};`;
break;
case TypeDefKind.Struct:
const extendsDef = line.extends ? ` extends ${line.extends}` : "";
if (line.extends) {
const genericMatch = line.extends.match(/Iterator<(.+)>$/);
if (genericMatch) {
const [T, TResult, TNext] = genericMatch[1].split(",").map((p) => p.trim());
line.def = line.def + `\nnext(value?: ${TNext}): IteratorResult<${T}, ${TResult}>`;
}
}
s += `${exportDeclare(ambient)} class ${line.name}${extendsDef} {\n${line.def}\n}`;
if (line.original_name && line.original_name !== line.name) s += `\nexport type ${line.original_name} = ${line.name}`;
break;
case TypeDefKind.Fn:
s += `${exportDeclare(ambient)} ${line.def}`;
break;
default: s += line.def;
}
return correctStringIdent(s, ident);
}
function exportDeclare(ambient) {
if (ambient) return "export";
return "export declare";
}
function processOneTypedef(defs, constEnum) {
const exports$2 = [];
return {
declaration: defs.map((def) => {
switch (def.kind) {
case TypeDefKind.Const:
case TypeDefKind.Enum:
case TypeDefKind.StringEnum:
case TypeDefKind.Fn:
case TypeDefKind.Struct:
exports$2.push(def.name);
if (def.original_name && def.original_name !== def.name) exports$2.push(def.original_name);
break;
default: break;
}
return prettyPrint(def, constEnum, 0);
}).join("\n\n"),
exports: exports$2
};
}
async function processTypeDefModules(intermediateTypeFile, constEnum) {
const defs = await readIntermediateTypeFile(intermediateTypeFile);
const groupedDefs = preprocessTypeDef(defs);
const sortedNamespaces = (0, es_toolkit.sortBy)(Array.from(groupedDefs), [([namespace]) => namespace]);
const declarations = /* @__PURE__ */ new Map();
for (const [namespace, defs$1] of sortedNamespaces) {
if (declarations.has(namespace)) throw new Error(`Duplicate namespace: ${namespace}`);
const { declaration, exports: exports$2 } = processOneTypedef(defs$1, constEnum);
declarations.set(namespace, {
declaration,
exports: exports$2
});
}
return declarations;
}
async function processTypeDef(intermediateTypeFile, constEnum) {
const exports$2 = [];
const defs = await readIntermediateTypeFile(intermediateTypeFile);
const groupedDefs = preprocessTypeDef(defs);
return {
dts: (0, es_toolkit.sortBy)(Array.from(groupedDefs), [([namespace]) => namespace]).map(([namespace, defs$1]) => {
if (namespace === TOP_LEVEL_NAMESPACE) {
const { declaration, exports: addExports } = processOneTypedef(defs$1, constEnum);
exports$2.push(...addExports);
return declaration;
} else {
exports$2.push(namespace);
let declaration = "";
declaration += `export declare namespace ${namespace} {\n`;
for (const def of defs$1) declaration += prettyPrint(def, constEnum, 2, true) + "\n";
declaration += "}";
return declaration;
}
}).join("\n\n") + "\n",
exports: exports$2
};
}
async function readIntermediateTypeFile(file) {
return (await readFileAsync(file, "utf8")).split("\n").filter(Boolean).map((line) => {
line = line.trim();
const parsed = JSON.parse(line);
if (parsed.js_doc) parsed.js_doc = parsed.js_doc.replace(/\\n/g, "\n");
if (parsed.def) parsed.def = parsed.def.replace(/\\n/g, "\n");
return parsed;
}).sort((a, b) => {
if (a.kind === TypeDefKind.Struct) {
if (b.kind === TypeDefKind.Struct) return a.name.localeCompare(b.name);
return -1;
} else if (b.kind === TypeDefKind.Struct) return 1;
else return a.name.localeCompare(b.name);
});
}
function preprocessTypeDef(defs) {
const namespaceGrouped = /* @__PURE__ */ new Map();
const classDefs = /* @__PURE__ */ new Map();
for (const def of defs) {
const namespace = def.js_mod ?? TOP_LEVEL_NAMESPACE;
if (!namespaceGrouped.has(namespace)) namespaceGrouped.set(namespace, []);
const group = namespaceGrouped.get(namespace);
if (def.kind === TypeDefKind.Struct) {
group.push(def);
classDefs.set(def.name, def);
} else if (def.kind === TypeDefKind.Extends) {
const classDef = classDefs.get(def.name);
if (classDef) classDef.extends = def.def;
} else if (def.kind === TypeDefKind.Impl) {
const classDef = classDefs.get(def.name);
if (classDef) {
if (classDef.def) classDef.def += "\n";
classDef.def += def.def;
if (classDef.def) classDef.def = classDef.def.replace(/\\n/g, "\n");
}
} else group.push(def);
}
return namespaceGrouped;
}
function correctStringIdent(src, ident) {
let bracketDepth = 0;
return src.split("\n").map((line) => {
line = line.trim();
if (line === "") return "";
const isInMultilineComment = line.startsWith("*");
const isClosingBracket = line.endsWith("}");
const isOpeningBracket = line.endsWith("{");
const isTypeDeclaration = line.endsWith("=");
const isTypeVariant = line.startsWith("|");
let rightIndent = ident;
if ((isOpeningBracket || isTypeDeclaration) && !isInMultilineComment) {
bracketDepth += 1;
rightIndent += (bracketDepth - 1) * 2;
} else {
if (isClosingBracket && bracketDepth > 0 && !isInMultilineComment && !isTypeVariant) bracketDepth -= 1;
rightIndent += bracketDepth * 2;
}
if (isInMultilineComment) rightIndent += 1;
return `${" ".repeat(rightIndent)}${line}`;
}).join("\n");
}
//#endregion
//#region src/utils/read-config.ts
async function readConfig(options) {
const resolvePath = (...paths) => (0, node_path.resolve)(options.cwd, ...paths);
return await readNapiConfig(resolvePath(options.packageJsonPath ?? "package.json"), options.configPath ? resolvePath(options.configPath) : void 0);
}
//#endregion
//#region src/api/artifacts.ts
const debug$7 = debugFactory("artifacts");
async function collectArtifacts(userOptions) {
const options = applyDefaultArtifactsOptions(userOptions);
const resolvePath = (...paths) => (0, node_path.resolve)(options.cwd, ...paths);
const packageJsonPath = resolvePath(options.packageJsonPath);
const { targets, binaryName, packageName } = await readNapiConfig(packageJsonPath, options.configPath ? resolvePath(options.configPath) : void 0);
const distDirs = targets.map((platform) => (0, node_path.join)(options.cwd, options.npmDir, platform.platformArchABI));
const universalSourceBins = new Set(targets.filter((platform) => platform.arch === "universal").flatMap((p) => UniArchsByPlatform[p.platform]?.map((a) => `${p.platform}-${a}`)).filter(Boolean));
await collectNodeBinaries((0, node_path.join)(options.cwd, options.outputDir)).then((output) => Promise.all(output.map(async (filePath) => {
debug$7.info(`Read [${colorette.yellowBright(filePath)}]`);
const sourceContent = await readFileAsync(filePath);
const parsedName = (0, node_path.parse)(filePath);
const terms = parsedName.name.split(".");
const platformArchABI = terms.pop();
const _binaryName = terms.join(".");
if (_binaryName !== binaryName) {
debug$7.warn(`[${_binaryName}] is not matched with [${binaryName}], skip`);
return;
}
const dir = distDirs.find((dir$1) => dir$1.includes(platformArchABI));
if (!dir && universalSourceBins.has(platformArchABI)) {
debug$7.warn(`[${platformArchABI}] has no dist dir but it is source bin for universal arch, skip`);
return;
}
if (!dir) throw new Error(`No dist dir found for ${filePath}`);
const distFilePath = (0, node_path.join)(dir, parsedName.base);
debug$7.info(`Write file content to [${colorette.yellowBright(distFilePath)}]`);
await writeFileAsync(distFilePath, sourceContent);
const distFilePathLocal = (0, node_path.join)((0, node_path.parse)(packageJsonPath).dir, parsedName.base);
debug$7.info(`Write file content to [${colorette.yellowBright(distFilePathLocal)}]`);
await writeFileAsync(distFilePathLocal, sourceContent);
})));
const wasiTarget = targets.find((t) => t.platform === "wasi");
if (wasiTarget) {
const wasiDir = (0, node_path.join)(options.cwd, options.npmDir, wasiTarget.platformArchABI);
const cjsFile = (0, node_path.join)(options.buildOutputDir ?? options.cwd, `${binaryName}.wasi.cjs`);
const workerFile = (0, node_path.join)(options.buildOutputDir ?? options.cwd, `wasi-worker.mjs`);
const browserEntry = (0, node_path.join)(options.buildOutputDir ?? options.cwd, `${binaryName}.wasi-browser.js`);
const browserWorkerFile = (0, node_path.join)(options.buildOutputDir ?? options.cwd, `wasi-worker-browser.mjs`);
debug$7.info(`Move wasi binding file [${colorette.yellowBright(cjsFile)}] to [${colorette.yellowBright(wasiDir)}]`);
await writeFileAsync((0, node_path.join)(wasiDir, `${binaryName}.wasi.cjs`), await readFileAsync(cjsFile));
debug$7.info(`Move wasi worker file [${colorette.yellowBright(workerFile)}] to [${colorette.yellowBright(wasiDir)}]`);
await writeFileAsync((0, node_path.join)(wasiDir, `wasi-worker.mjs`), await readFileAsync(workerFile));
debug$7.info(`Move wasi browser entry file [${colorette.yellowBright(browserEntry)}] to [${colorette.yellowBright(wasiDir)}]`);
await writeFileAsync((0, node_path.join)(wasiDir, `${binaryName}.wasi-browser.js`), (await readFileAsync(browserEntry, "utf8")).replace(`new URL('./wasi-worker-browser.mjs', import.meta.url)`, `new URL('${packageName}-wasm32-wasi/wasi-worker-browser.mjs', import.meta.url)`));
debug$7.info(`Move wasi browser worker file [${colorette.yellowBright(browserWorkerFile)}] to [${colorette.yellowBright(wasiDir)}]`);
await writeFileAsync((0, node_path.join)(wasiDir, `wasi-worker-browser.mjs`), await readFileAsync(browserWorkerFile));
}
}
async function collectNodeBinaries(root) {
const files$1 = await readdirAsync(root, { withFileTypes: true });
const nodeBinaries = files$1.filter((file) => file.isFile() && (file.name.endsWith(".node") || file.name.endsWith(".wasm"))).map((file) => (0, node_path.join)(root, file.name));
const dirs = files$1.filter((file) => file.isDirectory());
for (const dir of dirs) if (dir.name !== "node_modules") nodeBinaries.push(...await collectNodeBinaries((0, node_path.join)(root, dir.name)));
return nodeBinaries;
}
//#endregion
//#region src/def/build.ts
var import_defineProperty$9 = /* @__PURE__ */ __toESM(require_defineProperty(), 1);
var BaseBuildCommand = class extends clipanion.Command {
constructor(..._args) {
super(..._args);
(0, import_defineProperty$9.default)(this, "target", clipanion.Option.String("--target,-t", { description: "Build for the target triple, bypassed to `cargo build --target`" }));
(0, import_defineProperty$9.default)(this, "cwd", clipanion.Option.String("--cwd", { description: "The working directory of where napi command will be executed in, all other paths options are relative to this path" }));
(0, import_defineProperty$9.default)(this, "manifestPath", clipanion.Option.String("--manifest-path", { description: "Path to `Cargo.toml`" }));
(0, import_defineProperty$9.default)(this, "configPath", clipanion.Option.String("--config-path,-c", { description: "Path to `napi` config json file" }));
(0, import_defineProperty$9.default)(this, "packageJsonPath", clipanion.Option.String("--package-json-path", { description: "Path to `package.json`" }));
(0, import_defineProperty$9.default)(this, "targetDir", clipanion.Option.String("--target-dir", { description: "Directory for all crate generated artifacts, see `cargo build --target-dir`" }));
(0, import_defineProperty$9.default)(this, "outputDir", clipanion.Option.String("--output-dir,-o", { description: "Path to where all the built files would be put. Default to the crate folder" }));
(0, import_defineProperty$9.default)(this, "platform", clipanion.Option.Boolean("--platform", { description: "Add platform triple to the generated nodejs binding file, eg: `[name].linux-x64-gnu.node`" }));
(0, import_defineProperty$9.default)(this, "jsPackageName", clipanion.Option.String("--js-package-name", { description: "Package name in generated js binding file. Only works with `--platform` flag" }));
(0, import_defineProperty$9.default)(this, "constEnum", clipanion.Option.Boolean("--const-enum", { description: "Whether generate const enum for typescript bindings" }));
(0, import_defineProperty$9.default)(this, "jsBinding", clipanion.Option.String("--js", { description: "Path and filename of generated JS binding file. Only works with `--platform` flag. Relative to `--output-dir`." }));
(0, import_defineProperty$9.default)(this, "noJsBinding", clipanion.Option.Boolean("--no-js", { description: "Whether to disable the generation JS binding file. Only works with `--platform` flag." }));
(0, import_defineProperty$9.default)(this, "jsModules", clipanion.Option.Boolean("--js-modules", { description: "Whether to generate JS binding file for each module." }));
(0, import_defineProperty$9.default)(this, "dts", clipanion.Option.String("--dts", { description: "Path and filename of generated type def file. Relative to `--output-dir`" }));
(0, import_defineProperty$9.default)(this, "dtsHeader", clipanion.Option.String("--dts-header", { description: "Custom file header for generated type def file. Only works when `typedef` feature enabled." }));
(0, import_defineProperty$9.default)(this, "noDtsHeader", clipanion.Option.Boolean("--no-dts-header", { description: "Whether to disable the default file header for generated type def file. Only works when `typedef` feature enabled." }));
(0, import_defineProperty$9.default)(this, "dtsCache", clipanion.Option.Boolean("--dts-cache", true, { description: "Whether to enable the dts cache, default to true" }));
(0, import_defineProperty$9.default)(this, "esm", clipanion.Option.Boolean("--esm", { description: "Whether to emit an ESM JS binding file instead of CJS format. Only works with `--platform` flag." }));
(0, import_defineProperty$9.default)(this, "strip", clipanion.Option.Boolean("--strip,-s", { description: "Whether strip the library to achieve the minimum file size" }));
(0, import_defineProperty$9.default)(this, "release", clipanion.Option.Boolean("--release,-r", { description: "Build in release mode" }));
(0, import_defineProperty$9.default)(this, "verbose", clipanion.Option.Boolean("--verbose,-v", { description: "Verbosely log build command trace" }));
(0, import_defineProperty$9.default)(this, "bin", clipanion.Option.String("--bin", { description: "Build only the specified binary" }));
(0, import_defineProperty$9.default)(this, "package", clipanion.Option.String("--package,-p", { description: "Build the specified library or the one at cwd" }));
(0, import_defineProperty$9.default)(this, "profile", clipanion.Option.String("--profile", { description: "Build artifacts with the specified profile" }));
(0, import_defineProperty$9.default)(this, "crossCompile", clipanion.Option.Boolean("--cross-compile,-x", { description: "[experimental] cross-compile for the specified target with `cargo-xwin` on windows and `cargo-zigbuild` on other platform" }));
(0, import_defineProperty$9.default)(this, "useCross", clipanion.Option.Boolean("--use-cross", { description: "[experimental] use [cross](https://github.com/cross-rs/cross) instead of `cargo`" }));
(0, import_defineProperty$9.default)(this, "useNapiCross", clipanion.Option.Boolean("--use-napi-cross", { description: "[experimental] use @napi-rs/cross-toolchain to cross-compile Linux arm/arm64/x64 gnu targets." }));
(0, import_defineProperty$9.default)(this, "watch", clipanion.Option.Boolean("--watch,-w", { description: "watch the crate changes and build continuously with `cargo-watch` crates" }));
(0, import_defineProperty$9.default)(this, "features", clipanion.Option.Array("--features,-F", { description: "Space-separated list of features to activate" }));
(0, import_defineProperty$9.default)(this, "allFeatures", clipanion.Option.Boolean("--all-features", { description: "Activate all available features" }));
(0, import_defineProperty$9.default)(this, "noDefaultFeatures", clipanion.Option.Boolean("--no-default-features", { description: "Do not activate the `default` feature" }));
}
getOptions() {
return {
target: this.target,
cwd: this.cwd,
manifestPath: this.manifestPath,
configPath: this.configPath,
packageJsonPath: this.packageJsonPath,
targetDir: this.targetDir,
outputDir: this.outputDir,
platform: this.platform,
jsPackageName: this.jsPackageName,
constEnum: this.constEnum,
jsBinding: this.jsBinding,
noJsBinding: this.noJsBinding,
jsModules: this.jsModules,
dts: this.dts,
dtsHeader: this.dtsHeader,
noDtsHeader: this.noDtsHeader,
dtsCache: this.dtsCache,
esm: this.esm,
strip: this.strip,
release: this.release,
verbose: this.verbose,
bin: this.bin,
package: this.package,
profile: this.profile,
crossCompile: this.crossCompile,
useCross: this.useCross,
useNapiCross: this.useNapiCross,
watch: this.watch,
features: this.features,
allFeatures: this.allFeatures,
noDefaultFeatures: this.noDefaultFeatures
};
}
};
(0, import_defineProperty$9.default)(BaseBuildCommand, "paths", [["build"]]);
(0, import_defineProperty$9.default)(BaseBuildCommand, "usage", clipanion.Command.Usage({ description: "Build the NAPI-RS project" }));
//#endregion
//#region src/api/templates/js-binding.ts
function createCjsBinding(localName, pkgName, idents, packageVersion) {
return `${bindingHeader}
const { createRequire } = require('node:module')
require = createRequire(__filename)
${createCommonBinding(localName, pkgName, packageVersion)}
module.exports = nativeBinding
${idents.map((ident) => `module.exports.${ident} = nativeBinding.${ident}`).join("\n")}
`;
}
function createCjsBindingModule(namespace, idents) {
if (namespace === void 0) return `${bindingHeader}
const nativeBinding = require('./_nativeBinding')
${idents.map((ident) => `module.exports.${ident} = nativeBinding.${ident}`).join("\n")}
`;
return `${bindingHeader}
const nativeBinding = require('./_nativeBinding')
module.exports = nativeBinding.${namespace}
${idents.map((ident) => `module.exports.${ident} = nativeBinding.${namespace}.${ident}`).join("\n")}
`;
}
function createEsmBindingModule(namespace, idents) {
return `${bindingHeader}
`;
}
function createEsmBinding(localName, pkgName, idents, packageVersion) {
return `${bindingHeader}
import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)
const __dirname = new URL('.', import.meta.url).pathname
${createCommonBinding(localName, pkgName, packageVersion)}
const { ${idents.join(", ")} } = nativeBinding
${idents.map((ident) => `export { ${ident} }`).join("\n")}
`;
}
const bindingHeader = `// prettier-ignore
/* eslint-disable */
// @ts-nocheck
/* auto-generated by NAPI-RS */
`;
function createCommonBinding(localName, pkgName, packageVersion) {
function requireTuple(tuple, identSize = 8) {
const identLow = " ".repeat(identSize - 2);
const ident = " ".repeat(identSize);
const versionCheck = packageVersion ? `
${identLow}try {
${ident}const binding = require('${pkgName}-${tuple}')
${ident}const bindingPackageVersion = require('${pkgName}-${tuple}/package.json').version
${ident}if (bindingPackageVersion !== '${packageVersion}' && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0') {
${ident} throw new Error(\`Native binding package version mismatch, expected ${packageVersion} but got \${bindingPackageVersion}. You can reinstall dependencies to fix this issue.\`)
${ident}}
${ident}return binding
${identLow}} catch (e) {
${ident}loadErrors.push(e)
${identLow}}` : `
${identLow}try {
${ident}return require('${pkgName}-${tuple}')
${identLow}} catch (e) {
${ident}loadErrors.push(e)
${identLow}}`;
return `try {
${ident}return require('./${localName}.${tuple}.node')
${identLow}} catch (e) {
${ident}loadErrors.push(e)
${identLow}}${versionCheck}`;
}
return `const { readFileSync } = require('node:fs')
let nativeBinding = null
const loadErrors = []
const isMusl = () => {
let musl = false
if (process.platform === 'linux') {
musl = isMuslFromFilesystem()
if (musl === null) {
musl = isMuslFromReport()
}
if (musl === null) {
musl = isMuslFromChildProcess()
}
}
return musl
}
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-')
const isMuslFromFilesystem = () => {
try {
return readFileSync('/usr/bin/ldd', 'utf-8').includes('musl')
} catch {
return null
}
}
const isMuslFromReport = () => {
let report = null
if (typeof process.report?.getReport === 'function') {
process.report.excludeNetwork = true
report = process.report.getReport()
}
if (!report) {
return null
}
if (report.header && report.header.glibcVersionRuntime) {
return false
}
if (Array.isArray(report.sharedObjects)) {
if (report.sharedObjects.some(isFileMusl)) {
return true
}
}
return false
}
const isMuslFromChildProcess = () => {
try {
return require('child_process').execSync('ldd --version', { encoding: 'utf8' }).includes('musl')
} catch (e) {
// If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false
return false
}
}
function requireNative() {
if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) {
try {
return require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
} catch (err) {
loadErrors.push(err)
}
} else if (process.platform === 'android') {
if (process.arch === 'arm64') {
${requireTuple("android-arm64")}
} else if (process.arch === 'arm') {
${requireTuple("android-arm-eabi")}
} else {
loadErrors.push(new Error(\`Unsupported architecture on Android \${process.arch}\`))
}
} else if (process.platform === 'win32') {
if (process.arch === 'x64') {
if (process.report?.getReport?.()?.header?.osName?.startsWith?.('MINGW')) {
${requireTuple("win32-x64-gnu")}
} else {
${requireTuple("win32-x64-msvc")}
}
} else if (process.arch === 'ia32') {
${requireTuple("win32-ia32-msvc")}
} else if (process.arch === 'arm64') {
${requireTuple("win32-arm64-msvc")}
} else {
loadErrors.push(new Error(\`Unsupported architecture on Windows: \${process.arch}\`))
}
} else if (process.platform === 'darwin') {
${requireTuple("darwin-universal", 6)}
if (process.arch === 'x64') {
${requireTuple("darwin-x64")}
} else if (process.arch === 'arm64') {
${requireTuple("darwin-arm64")}
} else {
loadErrors.push(new Error(\`Unsupported architecture on macOS: \${process.arch}\`))
}
} else if (process.platform === 'freebsd') {
if (process.arch === 'x64') {
${requireTuple("freebsd-x64")}
} else if (process.arch === 'arm64') {
${requireTuple("freebsd-arm64")}
} else {
loadErrors.push(new Error(\`Unsupported architecture on FreeBSD: \${process.arch}\`))
}
} else if (process.platform === 'linux') {
if (process.arch === 'x64') {
if (isMusl()) {
${requireTuple("linux-x64-musl", 10)}
} else {
${requireTuple("linux-x64-gnu", 10)}
}
} else if (process.arch === 'arm64') {
if (isMusl()) {
${requireTuple("linux-arm64-musl", 10)}
} else {
${requireTuple("linux-arm64-gnu", 10)}
}
} else if (process.arch === 'arm') {
if (isMusl()) {
${requireTuple("linux-arm-musleabihf", 10)}
} else {
${requireTuple("linux-arm-gnueabihf", 10)}
}
} else if (process.arch === 'loong64') {
if (isMusl()) {
${requireTuple("linux-loong64-musl", 10)}
} else {
${requireTuple("linux-loong64-gnu", 10)}
}
} else if (process.arch === 'riscv64') {
if (isMusl()) {
${requireTuple("linux-riscv64-musl", 10)}
} else {
${requireTuple("linux-riscv64-gnu", 10)}
}
} else if (process.arch === 'ppc64') {
${requireTuple("linux-ppc64-gnu")}
} else if (process.arch === 's390x') {
${requireTuple("linux-s390x-gnu")}
} else {
loadErrors.push(new Error(\`Unsupported architecture on Linux: \${process.arch}\`))
}
} else if (process.platform === 'openharmony') {
if (process.arch === 'arm64') {
${requireTuple("openharmony-arm64")}
} else if (process.arch === 'x64') {
${requireTuple("openharmony-x64")}
} else if (process.arch === 'arm') {
${requireTuple("openharmony-arm")}
} else {
loadErrors.push(new Error(\`Unsupported architecture on OpenHarmony: \${process.arch}\`))
}
} else {
loadErrors.push(new Error(\`Unsupported OS: \${process.platform}, architecture: \${process.arch}\`))
}
}
nativeBinding = requireNative()
if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
let wasiBinding = null
let wasiBindingError = null
try {
wasiBinding = require('./${localName}.wasi.cjs')
nativeBinding = wasiBinding
} catch (err) {
if (process.env.NAPI_RS_FORCE_WASI) {
wasiBindingError = err
}
}
if (!nativeBinding) {
try {
wasiBinding = require('${pkgName}-wasm32-wasi')
nativeBinding = wasiBinding
} catch (err) {
if (process.env.NAPI_RS_FORCE_WASI) {
wasiBindingError.cause = err
loadErrors.push(err)
}
}
}
if (process.env.NAPI_RS_FORCE_WASI === 'error' && !wasiBinding) {
const error = new Error('WASI binding not found and NAPI_RS_FORCE_WASI is set to error')
error.cause = wasiBindingError
throw error
}
}
if (!nativeBinding) {
if (loadErrors.length > 0) {
throw new Error(
\`Cannot find native binding. \` +
\`npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). \` +
'Please try \`npm i\` again after removing both package-lock.json and node_modules directory.',
{
cause: loadErrors.reduce((err, cur) => {
cur.cause = err
return cur
}),
},
)
}
throw new Error(\`Failed to load native binding\`)
}
`;
}
//#endregion
//#region src/api/templates/load-wasi-template.ts
const createWasiBrowserBinding = (wasiFilename, initialMemory = 4e3, maximumMemory = 65536, fs$2 = false, asyncInit = false, buffer = false) => {
return `import {
createOnMessage as __wasmCreateOnMessageForFsProxy,
getDefaultContext as __emnapiGetDefaultContext,
${asyncInit ? `instantiateNapiModule as __emnapiInstantiateNapiModule` : `instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync`},
WASI as __WASI,
} from '@napi-rs/wasm-runtime'
${fs$2 ? buffer ? `import { memfs, Buffer } from '@napi-rs/wasm-runtime/fs'` : `import { memfs } from '@napi-rs/wasm-runtime/fs'` : ""}
${buffer && !fs$2 ? `import { Buffer } from 'buffer'` : ""}
${fs$2 ? `
export const { fs: __fs, vol: __volume } = memfs()
const __wasi = new __WASI({
version: 'preview1',
fs: __fs,
preopens: {
'/': '/',
},
})` : `
const __wasi = new __WASI({
version: 'preview1',
})`}
const __wasmUrl = new URL('./${wasiFilename}.wasm', import.me