UNPKG

@vmg-anysphere/napi-rs-cli

Version:
1,275 lines (1,238 loc) 548 kB
#!/usr/bin/env node import { createRequire } from "node:module"; import { Cli, Command, Option } from "clipanion"; import path, { join, parse, resolve } from "node:path"; import * as colors from "colorette"; import { underline, yellow } from "colorette"; import rawDebug from "debug"; import { access, copyFile, mkdir, readFile, readdir, rename, stat, unlink, writeFile } from "node:fs/promises"; import { exec, execSync, spawn, spawnSync } from "node:child_process"; import fs, { existsSync, mkdirSync, promises, rmSync, statSync } from "node:fs"; import { isNil, merge, omit, omitBy, pick, sortBy } from "es-toolkit"; import { createHash } from "node:crypto"; import { homedir } from "node:os"; import { parse as parse$1 } from "semver"; import { checkbox, confirm, input, select } from "@inquirer/prompts"; import { dump, load } from "js-yaml"; import * as typanion from "typanion"; import * as find from "empathic/find"; import { Octokit } from "@octokit/rest"; //#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 //#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$14(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$14, module.exports.__esModule = true, module.exports["default"] = module.exports; }) }); //#endregion //#region src/def/artifacts.ts var import_defineProperty$13 = /* @__PURE__ */ __toESM(require_defineProperty(), 1); var BaseArtifactsCommand = class extends Command { constructor(..._args) { super(..._args); (0, import_defineProperty$13.default)(this, "cwd", 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$13.default)(this, "configPath", Option.String("--config-path,-c", { description: "Path to `napi` config json file" })); (0, import_defineProperty$13.default)(this, "packageJsonPath", Option.String("--package-json-path", "package.json", { description: "Path to `package.json`" })); (0, import_defineProperty$13.default)(this, "outputDir", 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$13.default)(this, "npmDir", Option.String("--npm-dir", "npm", { description: "Path to the folder where the npm packages put" })); (0, import_defineProperty$13.default)(this, "buildOutputDir", 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$13.default)(BaseArtifactsCommand, "paths", [["artifacts"]]); (0, import_defineProperty$13.default)(BaseArtifactsCommand, "usage", 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 rawDebug.formatters.i = (v) => { return colors.green(v); }; const debugFactory = (namespace) => { const debug$10 = rawDebug(`napi:${namespace}`); debug$10.info = (...args) => console.error(colors.black(colors.bgGreen(" INFO ")), ...args); debug$10.warn = (...args) => console.error(colors.black(colors.bgYellow(" WARNING ")), ...args); debug$10.error = (...args) => console.error(colors.white(colors.bgRed(" ERROR ")), ...args.map((arg) => arg instanceof Error ? arg.stack ?? arg.message : arg)); return debug$10; }; const debug$9 = 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 = { ".": { "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, files, keywords, maintainers, repository, publishConfig, bugs, dependencies, devDependencies, peerDependencies, peerDependenciesMeta, funding, scripts, ava }; //#endregion //#region src/utils/misc.ts const readFileAsync = readFile; const writeFileAsync = writeFile; const unlinkAsync = unlink; const copyFileAsync = copyFile; const mkdirAsync = mkdir; const statAsync = stat; const readdirAsync = readdir; function fileExists(path$1) { return 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$9(`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 = 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 (!fs.existsSync(manifestPath)) throw new Error(`No crate found in manifest: ${manifestPath}`); const childProcess = 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$1) => { childProcess.on("close", (code) => { status = code ?? 0; resolve$1(); }); }); 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 = underline(path$1); const configPathUnderline = underline(configPath); console.warn(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 = merge({ binaryName: "index", packageName: pkgJson.name, targets: [], packageJson: pkgJson, npmClient: "npm" }, omit(userNapiConfig, ["targets"])); let targets = userNapiConfig.targets ?? []; if (userNapiConfig?.name) { console.warn(yellow(`[DEPRECATED] napi.name is deprecated, use napi.binaryName instead.`)); napiConfig.binaryName = userNapiConfig.name; } if (!targets.length) { let deprecatedWarned = false; const warning = 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$9("Cargo binary already installed: %s", name$1); return; } try { debug$9("Installing cargo binary: %s", name$1); 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$9("Detecting cargo binary: %s", bin$1); try { execSync(`cargo help ${bin$1}`, { stdio: "ignore" }); debug$9("Cargo binary detected: %s", bin$1); return true; } catch { debug$9("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$1 = []; return { declaration: defs.map((def) => { switch (def.kind) { case TypeDefKind.Const: case TypeDefKind.Enum: case TypeDefKind.StringEnum: case TypeDefKind.Fn: case TypeDefKind.Struct: exports$1.push(def.name); if (def.original_name && def.original_name !== def.name) exports$1.push(def.original_name); break; default: break; } return prettyPrint(def, constEnum, 0); }).join("\n\n"), exports: exports$1 }; } async function processTypeDefModules(intermediateTypeFile, constEnum) { const defs = await readIntermediateTypeFile(intermediateTypeFile); const groupedDefs = preprocessTypeDef(defs); const sortedNamespaces = 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$1 } = processOneTypedef(defs$1, constEnum); declarations.set(namespace, { declaration, exports: exports$1 }); } return declarations; } async function processTypeDef(intermediateTypeFile, constEnum) { const exports$1 = []; const defs = await readIntermediateTypeFile(intermediateTypeFile); const groupedDefs = preprocessTypeDef(defs); return { dts: sortBy(Array.from(groupedDefs), [([namespace]) => namespace]).map(([namespace, defs$1]) => { if (namespace === TOP_LEVEL_NAMESPACE) { const { declaration, exports: addExports } = processOneTypedef(defs$1, constEnum); exports$1.push(...addExports); return declaration; } else { exports$1.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$1 }; } 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) => 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$8 = debugFactory("artifacts"); async function collectArtifacts(userOptions) { const options = applyDefaultArtifactsOptions(userOptions); const resolvePath = (...paths) => 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) => 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(join(options.cwd, options.outputDir)).then((output) => Promise.all(output.map(async (filePath) => { debug$8.info(`Read [${colors.yellowBright(filePath)}]`); const sourceContent = await readFileAsync(filePath); const parsedName = parse(filePath); const terms = parsedName.name.split("."); const platformArchABI = terms.pop(); const _binaryName = terms.join("."); if (_binaryName !== binaryName) { debug$8.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$8.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 = join(dir, parsedName.base); debug$8.info(`Write file content to [${colors.yellowBright(distFilePath)}]`); await writeFileAsync(distFilePath, sourceContent); const distFilePathLocal = join(parse(packageJsonPath).dir, parsedName.base); debug$8.info(`Write file content to [${colors.yellowBright(distFilePathLocal)}]`); await writeFileAsync(distFilePathLocal, sourceContent); }))); const wasiTarget = targets.find((t) => t.platform === "wasi"); if (wasiTarget) { const wasiDir = join(options.cwd, options.npmDir, wasiTarget.platformArchABI); const cjsFile = join(options.buildOutputDir ?? options.cwd, `${binaryName}.wasi.cjs`); const workerFile = join(options.buildOutputDir ?? options.cwd, `wasi-worker.mjs`); const browserEntry = join(options.buildOutputDir ?? options.cwd, `${binaryName}.wasi-browser.js`); const browserWorkerFile = join(options.buildOutputDir ?? options.cwd, `wasi-worker-browser.mjs`); debug$8.info(`Move wasi binding file [${colors.yellowBright(cjsFile)}] to [${colors.yellowBright(wasiDir)}]`); await writeFileAsync(join(wasiDir, `${binaryName}.wasi.cjs`), await readFileAsync(cjsFile)); debug$8.info(`Move wasi worker file [${colors.yellowBright(workerFile)}] to [${colors.yellowBright(wasiDir)}]`); await writeFileAsync(join(wasiDir, `wasi-worker.mjs`), await readFileAsync(workerFile)); debug$8.info(`Move wasi browser entry file [${colors.yellowBright(browserEntry)}] to [${colors.yellowBright(wasiDir)}]`); await writeFileAsync(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$8.info(`Move wasi browser worker file [${colors.yellowBright(browserWorkerFile)}] to [${colors.yellowBright(wasiDir)}]`); await writeFileAsync(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) => 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(join(root, dir.name))); return nodeBinaries; } //#endregion //#region src/commands/artifacts.ts var import_defineProperty$12 = /* @__PURE__ */ __toESM(require_defineProperty(), 1); var ArtifactsCommand = class extends BaseArtifactsCommand { async execute() { await collectArtifacts(this.getOptions()); } }; (0, import_defineProperty$12.default)(ArtifactsCommand, "usage", Command.Usage({ description: "Copy artifacts from Github Actions into specified dir", examples: [["$0 artifacts --output-dir ./artifacts --dist ./npm", `Copy [binaryName].[platform].node under current dir(.) into packages under npm dir. e.g: index.linux-x64-gnu.node --> ./npm/linux-x64-gnu/index.linux-x64-gnu.node`]] })); (0, import_defineProperty$12.default)(ArtifactsCommand, "paths", [["artifacts"]]); //#endregion //#region src/def/build.ts var import_defineProperty$11 = /* @__PURE__ */ __toESM(require_defineProperty(), 1); var BaseBuildCommand = class extends Command { constructor(..._args) { super(..._args); (0, import_defineProperty$11.default)(this, "target", Option.String("--target,-t", { description: "Build for the target triple, bypassed to `cargo build --target`" })); (0, import_defineProperty$11.default)(this, "cwd", 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$11.default)(this, "manifestPath", Option.String("--manifest-path", { description: "Path to `Cargo.toml`" })); (0, import_defineProperty$11.default)(this, "configPath", Option.String("--config-path,-c", { description: "Path to `napi` config json file" })); (0, import_defineProperty$11.default)(this, "packageJsonPath", Option.String("--package-json-path", { description: "Path to `package.json`" })); (0, import_defineProperty$11.default)(this, "targetDir", Option.String("--target-dir", { description: "Directory for all crate generated artifacts, see `cargo build --target-dir`" })); (0, import_defineProperty$11.default)(this, "outputDir", Option.String("--output-dir,-o", { description: "Path to where all the built files would be put. Default to the crate folder" })); (0, import_defineProperty$11.default)(this, "platform", Option.Boolean("--platform", { description: "Add platform triple to the generated nodejs binding file, eg: `[name].linux-x64-gnu.node`" })); (0, import_defineProperty$11.default)(this, "jsPackageName", Option.String("--js-package-name", { description: "Package name in generated js binding file. Only works with `--platform` flag" })); (0, import_defineProperty$11.default)(this, "constEnum", Option.Boolean("--const-enum", { description: "Whether generate const enum for typescript bindings" })); (0, import_defineProperty$11.default)(this, "jsBinding", Option.String("--js", { description: "Path and filename of generated JS binding file. Only works with `--platform` flag. Relative to `--output-dir`." })); (0, import_defineProperty$11.default)(this, "noJsBinding", Option.Boolean("--no-js", { description: "Whether to disable the generation JS binding file. Only works with `--platform` flag." })); (0, import_defineProperty$11.default)(this, "jsModules", Option.Boolean("--js-modules", { description: "Whether to generate JS binding file for each module." })); (0, import_defineProperty$11.default)(this, "dts", Option.String("--dts", { description: "Path and filename of generated type def file. Relative to `--output-dir`" })); (0, import_defineProperty$11.default)(this, "dtsHeader", Option.String("--dts-header", { description: "Custom file header for generated type def file. Only works when `typedef` feature enabled." })); (0, import_defineProperty$11.default)(this, "noDtsHeader", 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$11.default)(this, "dtsCache", Option.Boolean("--dts-cache", true, { description: "Whether to enable the dts cache, default to true" })); (0, import_defineProperty$11.default)(this, "esm", Option.Boolean("--esm", { description: "Whether to emit an ESM JS binding file instead of CJS format. Only works with `--platform` flag." })); (0, import_defineProperty$11.default)(this, "strip", Option.Boolean("--strip,-s", { description: "Whether strip the library to achieve the minimum file size" })); (0, import_defineProperty$11.default)(this, "release", Option.Boolean("--release,-r", { description: "Build in release mode" })); (0, import_defineProperty$11.default)(this, "verbose", Option.Boolean("--verbose,-v", { description: "Verbosely log build command trace" })); (0, import_defineProperty$11.default)(this, "bin", Option.String("--bin", { description: "Build only the specified binary" })); (0, import_defineProperty$11.default)(this, "package", Option.String("--package,-p", { description: "Build the specified library or the one at cwd" })); (0, import_defineProperty$11.default)(this, "profile", Option.String("--profile", { description: "Build artifacts with the specified profile" })); (0, import_defineProperty$11.default)(this, "crossCompile", 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$11.default)(this, "useCross", Option.Boolean("--use-cross", { description: "[experimental] use [cross](https://github.com/cross-rs/cross) instead of `cargo`" })); (0, import_defineProperty$11.default)(this, "useNapiCross", Option.Boolean("--use-napi-cross", { description: "[experimental] use @napi-rs/cross-toolchain to cross-compile Linux arm/arm64/x64 gnu targets." })); (0, import_defineProperty$11.default)(this, "watch", Option.Boolean("--watch,-w", { description: "watch the crate changes and build continuously with `cargo-watch` crates" })); (0, import_defineProperty$11.default)(this, "features", Option.Array("--features,-F", { description: "Space-separated list of features to activate" })); (0, import_defineProperty$11.default)(this, "allFeatures", Option.Boolean("--all-features", { description: "Activate all available features" })); (0, import_defineProperty$11.default)(this, "noDefaultFeatures", 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$11.default)(BaseBuildCommand, "paths", [["build"]]); (0, import_defineProperty$11.default)(BaseBuildCommand, "usage", 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$1 = 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$1 ? buffer ? `import { memfs, Buffer } from '@napi-rs/wasm-runtime/fs'` : `import { memfs } from '@napi-rs/wasm-runtime/fs'` : ""} ${buffer && !fs$1 ? `import { Buffer } from 'buffer'` : ""} ${fs$1 ? ` 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.meta.url).href const __emnapiContext = __emnapiGetDefaultContext() ${buffer ? "__emnapiContext.feature.Buffer = Buffer" : ""} const __sharedMemory = new WebAssembly.Memory({ initial: ${initialMemory}, maximum: ${maximumMemory}, shared: true, }) const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer()) const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule, } = ${asyncInit ? `await __emnapiInstantiateNapiModule` : `__emnapiInstantiateNapiModuleSync`}(__wasmFile, { context: __emnapiContext, asyncWorkPoolSize: 4, wasi: __wasi, onCreateWor