diff --git a/.claude/rules/project.md b/.claude/rules/project.md index 49db112c..877ba6b3 100644 --- a/.claude/rules/project.md +++ b/.claude/rules/project.md @@ -22,3 +22,8 @@ This is `yao-pkg/pkg` — a maintained fork of the archived `vercel/pkg`. - `lib/bin.js` — CLI entry point - `prelude/bootstrap.js` — Injected into every packaged executable - `dictionary/*.js` — Special handling for specific npm packages + +## Architecture Reference + +- `docs/ARCHITECTURE.md` — **detailed** contributor/agent reference. Full build pipelines, binary layout, VFS provider, worker-thread bootstrap, patch tables. Read this when working on `lib/` or `prelude/`. +- `docs-site/architecture.md` — short user-facing overview (linked from the published docs site). Don't duplicate internals here; link back to `docs/ARCHITECTURE.md`. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 123a824b..3920edc2 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -236,7 +236,7 @@ Follow conventional commits format: 1. **Read existing code**: Look at similar functionality before implementing new features 2. **Add tests**: Every new feature or bug fix should include a test -3. **Update documentation**: Update README.md and DEVELOPMENT.md as needed +3. **Update documentation**: Update the docs site (`docs-site/`) as needed — guides live under `docs-site/guide/`, development notes in `docs-site/development.md`, architecture in `docs-site/architecture.md` 4. **Check CI**: Ensure all CI checks pass before requesting review 5. **Small PRs**: Keep pull requests focused and reasonably sized 6. **Follow patterns**: Match existing code style and patterns @@ -275,8 +275,8 @@ The project uses GitHub Actions workflows: - **Issues**: Report bugs and feature requests on GitHub - **Discussions**: Use GitHub Discussions for questions -- **Documentation**: See README.md for user documentation -- **Development Guide**: See DEVELOPMENT.md for development details +- **Documentation**: See the docs site at https://yao-pkg.github.io/pkg/ (sources in `docs-site/`) +- **Development Guide**: See `docs-site/development.md` (published at https://yao-pkg.github.io/pkg/development) - **Related Projects**: - [pkg-fetch](https://github.com/yao-pkg/pkg-fetch) - Pre-compiled Node.js binaries - [pkg-binaries](https://github.com/yao-pkg/pkg-binaries) - Binaries for unsupported architectures diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..260395d7 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,61 @@ +name: Deploy docs + +on: + push: + branches: [main] + paths: + - 'docs-site/**' + - '.github/workflows/docs.yml' + pull_request: + paths: + - 'docs-site/**' + - '.github/workflows/docs.yml' + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: docs-site + steps: + - uses: actions/checkout@v6 + + - uses: actions/setup-node@v6 + with: + node-version: 22 + cache: 'npm' + cache-dependency-path: docs-site/package-lock.json + + - name: Install dependencies + run: npm ci --no-audit --no-fund + + - name: Build with VitePress + run: npm run docs:build + + - name: Upload Pages artifact + if: github.event_name != 'pull_request' + uses: actions/upload-pages-artifact@v3 + with: + path: docs-site/.vitepress/dist + + deploy: + if: github.event_name != 'pull_request' + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 1c4fb161..f740374e 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,82 +1,10 @@ -# PKG Development - -This document aims to help you get started with `pkg` developemnt. - -## Release Process - -In order to create release just run the command: - -```bash -npm run release -``` - -This command will start an interactive process that will guide you through the release process using [release-it](https://github.com/release-it/release-it) - -## Testing - -Before running tests ensure you have build the project by running: - -```bash -npm run build -``` - -> [!NOTE] -> Remember to run again `npm run build` after changing source code (everything inside `lib` folder). - -Than you can use the following command to run tests: - -```bash -node test/test.js [no-npm | only-npm | all] [] -``` - -- `` is the node target the test will use when creating executables, can be `nodeXX` (like `node20`) or `host` (uses host node version as target). -- `[no-npm | only-npm | all]` to specify which tests to run. `no-npm` will run tests that don't require npm, `only-npm` will run against some specific npm modules, and `all` will run all tests. -- `` to use when you want to run only tests matching a specific pattern. Example: `node test/test.js all test-99-*`. You can also set this by using `FLAVOR` environment variable. - -Each test is located inside `test` directory into a dedicated folder named following the pattern `test-XX-*`. The `XX` is a number that represents the order the tests will run. + + -When running `node test/test.js all`, based on the options, each test will be run consecutively by running `main.js` file inside the test folder. - -### Example test - -Create a directory named `test-XX-` and inside it create a `main.js` file with the following content: - -```javascript -#!/usr/bin/env node - -'use strict'; - -const assert = require('assert'); -const utils = require('../utils.js'); - -assert(!module.parent); -assert(__dirname === process.cwd()); - -const input = './test-x-index'; - -const newcomers = [ - 'test-x-index-linux', - 'test-x-index-macos', - 'test-x-index-win.exe', -]; - -const before = utils.filesBefore(newcomers); - -utils.pkg.sync([input], { stdio: 'inherit' }); - -utils.filesAfter(before, newcomers); -``` - -Explaining the code above: +# PKG Development -- `assert(!module.parent);` ensures the script is being run directly. -- `assert(__dirname === process.cwd());` ensures the script is being run from the correct directory. -- `utils.filesBefore(newcomers);` get current files in the directory. -- `utils.pkg.sync([input], { stdio: 'inherit' });` runs `pkg` passing input file as only argument. -- `utils.filesAfter(before, newcomers);` checks if the output files were created correctly and cleans up the directory to the original state. +Development documentation has moved to the official docs site: -### Special tests +**→ [yao-pkg.github.io/pkg/development](https://yao-pkg.github.io/pkg/development)** -- `test-79-npm`: It's the only test runned when using `only-npm`. It install and tests all node modules listed inside that dir and verifies if they are working correctly. -- `test-42-fetch-all`: Foreach known node version verifies there is a patch existing for it using pkg-fetch. -- `test-46-multi-arch`: Tries to cross-compile a binary for all known architectures. +For the canonical source of this page, see [`docs-site/development.md`](docs-site/development.md). diff --git a/README.md b/README.md index 0f3282a9..ff7ad688 100644 --- a/README.md +++ b/README.md @@ -1,708 +1,60 @@ -# pkg +

+ pkg +

-[![Build Status](https://github.com/yao-pkg/pkg/actions/workflows/ci.yml/badge.svg)](https://github.com/yao-pkg/pkg/actions/workflows/ci.yml) -[![npm version](https://img.shields.io/npm/v/@yao-pkg/pkg)](https://www.npmjs.com/package/@yao-pkg/pkg) -[![npm downloads](https://img.shields.io/npm/dm/@yao-pkg/pkg)](https://www.npmjs.com/package/@yao-pkg/pkg) -[![license](https://img.shields.io/npm/l/@yao-pkg/pkg)](https://github.com/yao-pkg/pkg/blob/main/LICENSE) +

pkg

-This command line interface enables you to package your Node.js project into an executable that can be run even on devices without Node.js installed. +

+ Package your Node.js project into a single self-contained executable. +

-## Use Cases +

+ Build Status + npm version + npm downloads + license +

-- Make a commercial version of your application without sources -- Make a demo/evaluation/trial version of your app without sources -- Instantly make executables for other platforms (cross-compilation) -- Make some kind of self-extracting archive or installer -- No need to install Node.js and npm to run the packaged application -- No need to download hundreds of files via `npm install` to deploy - your application. Deploy it as a single file -- Put your assets inside the executable to make it even more portable -- Test your app against new Node.js version without installing it +

+ 📚 Full documentation: yao-pkg.github.io/pkg +

-## Usage +--- -```sh -npm install -g @yao-pkg/pkg -``` - -After installing it, run `pkg --help` without arguments to see list of options: - -```console - pkg [options] - - Options: - - -h, --help output usage information - -v, --version output pkg version - -t, --targets comma-separated list of targets (see examples) - -c, --config package.json or any json file with top-level config - --options bake v8 options into executable to run with them on - -o, --output output file name or template for several files - --out-path path to save output one or more executables - -d, --debug show more information during packaging process [off] - -b, --build don't download prebuilt base binaries, build them - --public speed up and disclose the sources of top-level project - --public-packages force specified packages to be considered public - --no-bytecode skip bytecode generation and include source files as plain js - --no-native-build skip native addons build - --no-dict comma-separated list of packages names to ignore dictionaries. Use --no-dict * to disable all dictionaries - -C, --compress [default=None] compression algorithm = Brotli or GZip - --sea (Experimental) compile using node's SEA feature. With package.json input and node >= 22, uses enhanced mode with full dependency walking and VFS - - Examples: - - – Makes executables for Linux, macOS and Windows - $ pkg index.js - – Takes package.json from cwd and follows 'bin' entry - $ pkg . - – Makes executable for particular target machine - $ pkg -t node22-win-arm64 index.js - – Makes executables for target machines of your choice - $ pkg -t node22-linux,node24-linux,node24-win index.js - – Bakes '--expose-gc' and '--max-heap-size=34' into executable - $ pkg --options "expose-gc,max-heap-size=34" index.js - – Consider packageA and packageB to be public - $ pkg --public-packages "packageA,packageB" index.js - – Consider all packages to be public - $ pkg --public-packages "*" index.js - – Bakes '--expose-gc' into executable - $ pkg --options expose-gc index.js - – reduce size of the data packed inside the executable with GZip - $ pkg --compress GZip index.js - – compile the file using node's SEA feature. Creates executables for Linux, macOS and Windows - $ pkg --sea index.js -``` - -The entrypoint of your project is a mandatory CLI argument. It may be: - -- Path to entry file. Suppose it is `/path/app.js`, then - packaged app will work the same way as `node /path/app.js` -- Path to `package.json`. `Pkg` will follow `bin` property of - the specified `package.json` and use it as entry file. -- Path to directory. `Pkg` will look for `package.json` in - the specified directory. See above. - -### Targets - -`pkg` can generate executables for several target machines at a -time. You can specify a comma-separated list of targets via `--targets` -option. A canonical target consists of 3 elements, separated by -dashes, for example `node22-macos-x64` or `node24-linux-arm64`: - -- **nodeRange** node22, node24 or latest -- **platform** alpine, linux, linuxstatic, win, macos, (freebsd) -- **arch** x64, arm64, (armv6, armv7) - -(element) is unsupported, but you may try to compile yourself. - -If your target is available in the assets of the latest [pkg-fetch release](https://github.com/yao-pkg/pkg-fetch/releases), -`pkg` downloads the pre-compiled Node.js binary from that project. Otherwise, -or if you specify the `--build` option, it will build the binary from source -(takes a very long time). -Pre-compiled Node.js binaries for some unsupported architectures and -instructions for using them are available in the [pkg-binaries](https://github.com/yao-pkg/pkg-binaries) -project. - -You may omit any element (and specify just `node22` for example). -The omitted elements will be taken from current platform or -system-wide Node.js installation (its version and arch). -There is also an alias `host`, that means that all 3 elements -are taken from current platform/Node.js. By default targets are -`linux,macos,win` for current Node.js version and arch. - -If you want to generate executable for different architectures, -note that by default `pkg` has to run the executable of the -**target** arch to generate bytecodes: - -- Linux: configure binfmt with [QEMU](https://wiki.debian.org/QemuUserEmulation). -- macOS: possible to build `x64` on `arm64` with `Rosetta 2` but not opposite. -- Windows: possible to build `x64` on `arm64` with `x64 emulation` but not opposite. -- or, disable bytecode generation with `--no-bytecode --public-packages "*" --public`. - -`macos-arm64` is experimental. Be careful about the [mandatory code signing requirement](https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11_0_1-universal-apps-release-notes). -The final executable has to be signed (ad-hoc signature is sufficient) with `codesign` -utility of macOS (or `ldid` utility on Linux). Otherwise, the executable will be killed -by kernel and the end-user has no way to permit it to run at all. `pkg` tries to ad-hoc -sign the final executable. If necessary, you can replace this signature with your own -trusted Apple Developer ID. - -To be able to generate executables for all supported architectures and platforms, run -`pkg` on a Linux host with binfmt (`QEMU` emulation) configured and `ldid` installed. - -### Config - -During packaging process `pkg` parses your sources, detects -calls to `require`, traverses the dependencies of your project -and includes them into executable. In most cases you -don't need to specify anything manually. - -However your code may have `require(variable)` calls (so called non-literal -argument to `require`) or use non-javascript files (for -example views, css, images etc). - -```js -require('./build/' + cmd + '.js'); -path.join(__dirname, 'views/' + viewName); -``` - -Such cases are not handled by `pkg`. So you must specify the -files - scripts and assets - manually in `pkg` property of -your `package.json` file. - -```json - "pkg": { - "scripts": "build/**/*.js", - "assets": "views/**/*", - "targets": ["node22-linux-arm64"], - "outputPath": "dist" - } -``` - -The above example will include everything in `assets/` and -every .js file in `build/`, build only for `node22-linux-arm64`, -and place the executable inside `dist/`. - -You may also specify arrays of globs: - -``` - "assets": [ "assets/**/*", "images/**/*" ] -``` - -Just be sure to call `pkg package.json` or `pkg .` to make -use of `package.json` configuration. - -### Scripts - -`scripts` is a [glob](https://github.com/SuperchupuDev/tinyglobby) -or list of globs. Files specified as `scripts` will be compiled -using `v8::ScriptCompiler` and placed into executable without -sources. They must conform to the JS standards of those Node.js versions -you target (see [Targets](#targets)), i.e. be already transpiled. - -### Assets - -`assets` is a [glob](https://github.com/SuperchupuDev/tinyglobby) -or list of globs. Files specified as `assets` will be packaged -into executable as raw content without modifications. Javascript -files may also be specified as `assets`. Their sources will -not be stripped as it improves execution performance of the -files and simplifies debugging. - -See also -[Detecting assets in source code](#detecting-assets-in-source-code) and -[Snapshot filesystem](#snapshot-filesystem). - -### Ignore files - -`ignore` is a list of globs. Files matching the paths specified as `ignore` -will be excluded from the final executable. - -This is useful when you want to exclude some files from the final executable, -like tests, documentation or build files that could have been included by a dependency. - -```json - "pkg": { - "ignore": [ "**/*/dependency-name/build.c" ] - } -``` - -Note that both `**` and `*` would not match dotfiles e.g. `.git`, -the dotfile names must be in the glob explicitly to be matched. +`pkg` takes your Node.js project and ships it as a single binary that runs on devices without Node.js installed. Cross-compile for Linux, macOS, and Windows from any host. -To see if you have unwanted files in your executable, read the [Exploring virtual file system embedded in debug mode](#exploring-virtual-file-system-embedded-in-debug-mode) section. - -### Options - -Node.js application can be called with runtime options -(belonging to Node.js or V8). To list them type `node --help` or `node --v8-options`. - -You can "bake" these runtime options into packaged application. The app will always run with the options -turned on. Just remove `--` from option name. - -You can specify multiple options by joining them in a single string, comma (`,`) separated: - -```sh -pkg app.js --options expose-gc -pkg app.js --options max_old_space_size=4096 -pkg app.js --options max-old-space-size=1024,tls-min-v1.0,expose-gc -``` - -### Output - -You may specify `--output` if you create only one executable -or `--out-path` to place executables for multiple targets. - -### Debug - -Pass `--debug` to `pkg` to get a log of packaging process. -If you have issues with some particular file (seems not packaged -into executable), it may be useful to look through the log. - -In order to get more detailed logs on startup, after you packaged your application using `--debug`, you can start your application with the environment variable `DEBUG_PKG` set to `1` or `2` if you want more verbose debugging. This will load `prelude/diagnostic.js` that will print the snapshot tree and the symlink table, when set to `2` it will also mock `fs` in order to print logs when a method is called. - -This is useful to see what's included in your bundle and detect possible missing files or large files that could be removed from it in order to reduce the size of the executable. - -You can also use `SIZE_LIMIT_PKG` and `FOLDER_LIMIT_PKG` to print files/folders that are larger than the specified size limit (in bytes). By default, the size limit is set to 5MB for files and 10MB for folders. - -### Bytecode (reproducibility) - -By default, your source code is precompiled to v8 bytecode before being written -to the output file. To disable this feature, pass `--no-bytecode` to `pkg`. - -#### Why would you want to do this? - -If you need a reproducible build -process where your executable hashes (e.g. md5, sha1, sha256, etc.) are the -same value between builds. Because compiling bytecode is not deterministic -(see [here](https://ui.adsabs.harvard.edu/abs/2019arXiv191003478C/abstract) or -[here](https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775)) it -results in executables with differing hashed values. Disabling bytecode -compilation allows a given input to always have the same output. - -#### Why would you NOT want to do this? - -While compiling to bytecode does not make your source code 100% secure, it does -add a small layer of security/privacy/obscurity to your source code. Turning -off bytecode compilation causes the raw source code to be written directly to -the executable file. If you're on \*nix machine and would like an example, run -`pkg` with the `--no-bytecode` flag, and use the GNU strings tool on the -output. You then should be able to grep your source code. - -#### Other considerations - -Specifying `--no-bytecode` will fail if there are any packages in your project that aren't explicitly marked -as public by the `license` in their `package.json`. -By default, `pkg` will check the license of each package and make sure that stuff that isn't meant for the public will -only be included as bytecode. - -If you do require building pkg binaries for other architectures and/or depend on a package with a broken -`license` in its `package.json`, you can override this behaviour by either explicitly whitelisting packages to be public -using `--public-packages "packageA,packageB"` or setting all packages to public using `--public-packages "*"` - -### Build - -`pkg` has so called "base binaries" - they are actually same -`node` executables but with some patches applied. They are -used as a base for every executable `pkg` creates. `pkg` -downloads precompiled base binaries before packaging your -application. If you prefer to compile base binaries from -source instead of downloading them, you may pass `--build` -option to `pkg`. First ensure your computer meets the -requirements to compile original Node.js: -[BUILDING.md](https://github.com/nodejs/node/blob/HEAD/BUILDING.md) - -See [pkg-fetch](https://github.com/yao-pkg/pkg-fetch) for more info. - -### Compression - -Pass `--compress Brotli` or `--compress GZip` to `pkg` to compress further the content of the files stored in the executable. - -This option can reduce the size of the embedded file system by up to 60%. - -The startup time of the application might be reduced slightly. - -`-C` can be used as a shortcut for `--compress`. - -### SEA Mode (Single Executable Application) - -The `--sea` flag uses Node.js [Single Executable Applications](https://nodejs.org/api/single-executable-applications.html) to package your project. There are two variants: - -**Simple SEA** — For a single pre-bundled `.js` file (Node 22+): +## Install ```sh -pkg --sea index.js +npm install -g @yao-pkg/pkg ``` -**Enhanced SEA** — Automatically used when the input has a `package.json` and all targets are Node >= 22. Uses the full dependency walker with [`@roberts_lando/vfs`](https://github.com/robertsLando/vfs) for transparent `fs`/`require`/`import` support: +## Quick start ```sh -pkg . --sea # walks dependencies, builds VFS -pkg . --sea -t node24-linux # target specific platform -``` - -Enhanced SEA mode: - -- Walks dependencies like traditional mode, but skips V8 bytecode compilation and ESM-to-CJS transforms — files stay as-is -- Bundles all files into a single archive blob with offset-based zero-copy access at runtime -- Supports worker threads (VFS hooks are automatically injected into `/snapshot/...` workers) -- Native addon extraction works the same as traditional mode -- ESM entry points (`"type": "module"`) work on every supported target (Node >= 22), **including entrypoints that use top-level await**. ESM entries are dispatched via `vm.Script` + `USE_MAIN_CONTEXT_DEFAULT_LOADER`, which routes dynamic `import()` through the default ESM loader — no Node-version split, no build-time warning. CJS entries go through `Module.runMain()` -- `seaConfig.useSnapshot` is not supported in enhanced SEA mode (incompatible with the VFS bootstrap); set it to `false` or omit it. `useCodeCache` is forwarded as-is -- Runtime diagnostics via `DEBUG_PKG` / `SIZE_LIMIT_PKG` / `FOLDER_LIMIT_PKG` work the same as in traditional mode, but only when the binary was built with `--debug` (release builds cannot be coerced into dumping the VFS tree) -- Migration path to `node:vfs` when it lands in Node.js core - -**Trade-offs vs traditional mode**: Enhanced SEA builds faster and uses official Node.js APIs, but stores source code in plaintext (no bytecode protection) and does not support compression. See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for a detailed comparison. - -### Environment - -All pkg-cache [environment vars](https://github.com/yao-pkg/pkg-fetch#environment), plus: - -| Var | Description | -| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `CHDIR` | Override process `chdir` | -| `PKG_NATIVE_CACHE_PATH` | Override the base directory for caching extracted native addons at runtime (default: `~/.cache`) | -| `PKG_STRICT_VER` | Turn on some assertion in the walker code to assert that each file content/state that we appending to the virtual file system applies to a real file, not a symlink. | -| `PKG_EXECPATH` | Used internally by `pkg`, do not override | - -Examples - -```bash -# 1 - Set cache path at build time (for pkg-fetch to cache Node.js binaries) -export PKG_CACHE_PATH=/my/cache -pkg app.js - -# 2 - Set cache path at runtime (for packaged app to cache extracted native addons) -PKG_NATIVE_CACHE_PATH=/opt/myapp/cache ./myapp - -# 3 - Both can be used together -PKG_CACHE_PATH=/build/cache PKG_NATIVE_CACHE_PATH=/runtime/cache pkg app.js +pkg . ``` -## Usage of packaged app +That's it. `pkg` reads `package.json`, follows the `bin` entry, walks your dependencies, and produces executables for Linux, macOS, and Windows. -Command line call to packaged app `./app a b` is equivalent -to `node app.js a b` - -## Snapshot filesystem - -During packaging process `pkg` collects project files and places -them into executable. It is called a snapshot. At run time the -packaged application has access to snapshot filesystem where all -that files reside. - -Packaged files have `/snapshot/` prefix in their paths (or -`C:\snapshot\` in Windows). If you used `pkg /path/app.js` command line, -then `__filename` value will be likely `/snapshot/path/app.js` -at run time. `__dirname` will be `/snapshot/path` as well. Here is -the comparison table of path-related values: - -| value | with `node` | packaged | comments | -| ----------------------------- | --------------- | ------------------------ | ------------------------------ | -| \_\_filename | /project/app.js | /snapshot/project/app.js | -| \_\_dirname | /project | /snapshot/project | -| process.cwd() | /project | /deploy | suppose the app is called ... | -| process.execPath | /usr/bin/nodejs | /deploy/app-x64 | `app-x64` and run in `/deploy` | -| process.argv[0] | /usr/bin/nodejs | /deploy/app-x64 | -| process.argv[1] | /project/app.js | /snapshot/project/app.js | -| process.pkg.entrypoint | undefined | /snapshot/project/app.js | -| process.pkg.defaultEntrypoint | undefined | /snapshot/project/app.js | -| require.main.filename | /project/app.js | /snapshot/project/app.js | - -Hence, in order to make use of a file collected at packaging -time (`require` a javascript file or serve an asset) you should -take `__filename`, `__dirname`, `process.pkg.defaultEntrypoint` -or `require.main.filename` as a base for your path calculations. -For javascript files you can just `require` or `require.resolve` -because they use current `__dirname` by default. For assets use -`path.join(__dirname, '../path/to/asset')`. Learn more about -`path.join` in -[Detecting assets in source code](#detecting-assets-in-source-code). - -On the other hand, in order to access real file system at run time -(pick up a user's external javascript plugin, json configuration or -even get a list of user's directory) you should take `process.cwd()` -or `path.dirname(process.execPath)`. - -## Detecting assets in source code - -When `pkg` encounters `path.join(__dirname, '../path/to/asset')`, -it automatically packages the file specified as an asset. See -[Assets](#assets). Pay attention that `path.join` must have two -arguments and the last one must be a string literal. - -This way you may even avoid creating `pkg` config for your project. - -## Native addons - -Native addons (`.node` files) use is supported. When `pkg` encounters -a `.node` file in a `require` call, it will package this like an asset. -In some cases (like with the `bindings` package), the module path is generated -dynamically and `pkg` won't be able to detect it. In this case, you should -add the `.node` file directly in the `assets` field in `package.json`. - -The way Node.js requires native addon is different from a classic JS -file. It needs to have a file on disk to load it, but `pkg` only generates -one file. To circumvent this, `pkg` will extract native addon files to -`$HOME/.cache/pkg/` by default. These files will stay on the disk after the -process has exited and will be used again on the next process launch. - -You can customize the cache directory by setting the `PKG_NATIVE_CACHE_PATH` -environment variable. This is useful in enterprise environments where specific -directories may be restricted or monitored: - -```bash -# Set custom cache path for native addons -PKG_NATIVE_CACHE_PATH=/opt/myapp/cache ./myapp -``` - -When a package, that contains a native module, is being installed, -the native module is compiled against current system-wide Node.js -version. Then, when you compile your project with `pkg`, pay attention -to `--target` option. You should specify the same Node.js version -as your system-wide Node.js to make compiled executable compatible -with `.node` files. - -Note that fully static Node binaries are not capable of loading native -bindings, so you may not use Node bindings with `linuxstatic`. - -## API - -`const { exec } = require('pkg')` - -`exec(args)` takes an array of command line arguments and returns -a promise. For example: - -```js -await exec(['app.js', '--target', 'host', '--output', 'app.exe']); -// do something with app.exe, run, test, upload, deploy, etc -``` - -## ECMAScript Modules (ESM) Support - -Starting from version **6.13.0**, pkg has improved support for ECMAScript Modules (ESM). Most ESM features are now automatically transformed to CommonJS during the packaging process. - -### Supported ESM Features - -The following ESM features are now supported and will work in your packaged executables: - -- **`import` and `export` statements** - Automatically transformed to `require()` and `module.exports` -- **Top-level `await`** - Wrapped in an async IIFE to work in CommonJS context -- **Top-level `for await...of`** - Wrapped in an async IIFE to work in CommonJS context -- **`import.meta.url`** - Polyfilled to provide the file URL of the current module -- **`import.meta.dirname`** - Polyfilled to provide the directory path (Node.js 20.11+ property) -- **`import.meta.filename`** - Polyfilled to provide the file path (Node.js 20.11+ property) - -### Known Limitations - -While most ESM features work, there are some limitations to be aware of: - -1. **Modules with both top-level await and exports**: Modules that use `export` statements alongside top-level `await` cannot be wrapped in an async IIFE and will not be transformed to bytecode. These modules will be included as source code instead. - -2. **`import.meta.main`** and other custom properties: Only the standard `import.meta` properties listed above are polyfilled. Custom properties added by your code or other tools may not work as expected. - -3. **Dynamic imports**: `import()` expressions work but may have limitations depending on the module being imported. - -### Best Practices - -- For entry point scripts (the main file you're packaging), feel free to use top-level await -- For library modules that will be imported by other code, avoid using both exports and top-level await together -- Test your packaged executable to ensure all ESM features work as expected in your specific use case - -## Use custom Node.js binary - -In case you want to use custom node binary, you can set `PKG_NODE_PATH` environment variable to the path of the node binary you want to use and `pkg` will use it instead of the default one. - -```bash -PKG_NODE_PATH=/path/to/node pkg app.js -``` - -## Troubleshooting - -### Error: Error [ERR_REQUIRE_ESM]: require() of ES Module - -This error is tracked by issue [#16](https://github.com/yao-pkg/pkg/issues/16#issuecomment-1945486658). Follow the link in order to find a workaround. - -In most cases adding `--options experimental-require-module` to `pkg` command line will solve the issue. - -> [!NOTE] -> This option is not needed anymore starting from NodeJS v22.12.0 - -### Error: Cannot find module XXX (when using `child_process`) - -When using `child_process` methods to run a new process pkg by default will invoke it using NodeJS runtime that is built into the executable. This means that if you are trying to spawn the packaged app itself you will get above error. In order to avoid this you must set `PKG_EXECPATH` env set to `""`: - -```js -const { spawn } = require('child_process'); - -const child = spawn(process.execPath, [process.argv[1]], { - env: { - ...process.env, - PKG_EXECPATH: '', - }, -}); -``` - -More info [here](https://github.com/yao-pkg/pkg/pull/90) - -### Error: Cannot execute binary from snapshot - -Binaries must be extracted from snapshot in order to be executed. In order to do this you can use this approach: - -```js -const cp = require('child_process'); -const fs = require('fs'); -const { pipeline } = require('stream/promises'); - -let ffmpeg = require('@ffmpeg-installer/ffmpeg').path; - -const loadPlugin = async () => { - if (process.pkg) { - // copy ffmpeg to the current directory - const file = fs.createWriteStream('ffmpeg'); - await pipeline(fs.createReadStream(ffmpeg), file); - - fs.chmodSync('ffmpeg', 0o755); - console.log('ffmpeg copied to the current directory'); - ffmpeg = './ffmpeg'; - } - - cp.execSync(ffmpeg); -}; - -loadPlugin(); -``` - -### Error: ENOENT: no such file or directory, uv_chdir - -This error can be caused by deleting the directory the application is -run from. Or, generally, deleting `process.cwd()` directory when the -application is running. - -### Error: ERR_INSPECTOR_NOT_AVAILABLE - -This error can be caused by using `NODE_OPTIONS` variable to force to -run `node` with the debug mode enabled. Debugging options are disallowed -, as **pkg** executables are usually used for production environments. -If you do need to use inspector, you can [build a debuggable Node.js](https://github.com/yao-pkg/pkg/issues/93#issuecomment-301210543) yourself. - -### Error: require(...).internalModuleStat is not a function - -This error can be caused by using `NODE_OPTIONS` variable with some -bootstrap or `node` options causing conflicts with **pkg**. Some -IDEs, such as **VS Code**, may add this env variable automatically. - -You could check on **Unix systems** (Linux/macOS) in `bash`: - -```bash -printenv | grep NODE -``` - -## Advanced - -### Exploring virtual file system embedded in debug mode - -When you are using the `--debug` flag when building your executable, -`pkg` add the ability to display the content of the virtual file system -and the symlink table on the console, when the application starts, -providing that the environement variable DEBUG_PKG is set. -This feature can be useful to inspect if symlinks are correctly handled, -and check that all the required files for your application are properly -incorporated to the final executable. - - pkg --debug app.js -o output - DEBUG_PKG=1 output - -or - - C:\> pkg --debug app.js -o output.exe - C:\> set DEBUG_PKG=1 - C:\> output.exe - -Note: make sure not to use --debug flag in production. - -### Injecting Windows Executable Metadata After Packaging - -Executables created with `pkg` are based on a Node.js binary and, by default, -inherit its embedded metadata – such as version number, product name, company -name, icon, and description. This can be misleading or unpolished in -distributed applications. - -There are two ways to customize the metadata of the resulting `.exe`: - -1. **Use a custom Node.js binary** with your own metadata already embedded. - See: [Use Custom Node.js Binary](#use-custom-nodejs-binary) - -2. **Post-process the generated executable** using - [`resedit`](https://www.npmjs.com/package/resedit), a Node.js-compatible - tool for modifying Windows executable resources. This allows injecting - correct version info, icons, copyright, - and more. - -This section focuses on the second approach: post-processing the packaged -binary using [`resedit`](https://www.npmjs.com/package/resedit). - -> ⚠️ Other tools may corrupt the executable, resulting in runtime errors such as -> `Pkg: Error reading from file.` – -> [`resedit`](https://www.npmjs.com/package/resedit) has proven to work reliably -> with `pkg`-generated binaries. - -Below is a working example for post-processing an `.exe` file using the Node.js API of [`resedit`](https://www.npmjs.com/package/resedit): - -```ts -import * as ResEdit from 'resedit'; -import * as fs from 'fs'; -import * as path from 'path'; - -// Set your inputs: -const exePath = 'dist/my-tool.exe'; // Path to the generated executable -const outputPath = exePath; // Overwrite or use a different path -const version = '1.2.3'; // Your application version - -const lang = 1033; // en-US -const codepage = 1200; // Unicode - -const exeData = fs.readFileSync(exePath); -const exe = ResEdit.NtExecutable.from(exeData); -const res = ResEdit.NtExecutableResource.from(exe); - -const viList = ResEdit.Resource.VersionInfo.fromEntries(res.entries); -const vi = viList[0]; - -const [major, minor, patch] = version.split('.'); -vi.setFileVersion(Number(major), Number(minor), Number(patch), 0, lang); -vi.setProductVersion(Number(major), Number(minor), Number(patch), 0, lang); - -vi.setStringValues( - { lang, codepage }, - { - FileDescription: 'ACME CLI Tool', - ProductName: 'ACME Application', - CompanyName: 'ACME Corporation', - ProductVersion: version, - FileVersion: version, - OriginalFilename: path.basename(exePath), - LegalCopyright: `© ${new Date().getFullYear()} ACME Corporation`, - }, -); - -vi.outputToResourceEntries(res.entries); -res.outputResource(exe); -const newBinary = exe.generate(); - -fs.writeFileSync(outputPath, Buffer.from(newBinary)); -``` +## Documentation -As an alternative to the Node.js API, -[`resedit`](https://www.npmjs.com/package/resedit) also supports command–line -usage. This can be convenient for simple use cases in build scripts. +Everything lives on the docs site: -The following command examples inject an icon and metadata into the executable -`dist/bin/app_with_metadata.exe`, based on the original built file -`dist/bin/app.exe`. +- **[Getting started](https://yao-pkg.github.io/pkg/guide/getting-started)** — install, CLI reference, first build +- **[Targets](https://yao-pkg.github.io/pkg/guide/targets)** — cross-compile for other platforms +- **[Configuration](https://yao-pkg.github.io/pkg/guide/configuration)** — `pkg` property in `package.json`, scripts, assets, ignore +- **[SEA vs Standard mode](https://yao-pkg.github.io/pkg/guide/sea-vs-standard)** — which packaging mode to pick and why +- **[Snapshot filesystem](https://yao-pkg.github.io/pkg/guide/snapshot-fs)** — how paths work at runtime +- **[Native addons](https://yao-pkg.github.io/pkg/guide/native-addons)**, **[ESM support](https://yao-pkg.github.io/pkg/guide/esm)**, **[API](https://yao-pkg.github.io/pkg/guide/api)** +- **[Troubleshooting](https://yao-pkg.github.io/pkg/guide/troubleshooting)** +- **[Architecture](https://yao-pkg.github.io/pkg/architecture)** — traditional mode vs enhanced SEA mode +- **[Contributing](https://yao-pkg.github.io/pkg/development)** — release process, running tests -- **Example (PowerShell on Windows)** +## About this fork - ```powershell - npx resedit dist/bin/app.exe dist/bin/app_with_metadata.exe ` - --icon 1,dist/favicon.ico ` - --company-name "ACME Corporation" ` - --file-description "ACME CLI Tool" ` - --product-name "ACME Application" ` - --file-version 1.2.3.4 - ``` +This is **`yao-pkg/pkg`** — the actively maintained fork of the archived [`vercel/pkg`](https://github.com/vercel/pkg). New releases ship as [`@yao-pkg/pkg`](https://www.npmjs.com/package/@yao-pkg/pkg). -- **Example (bash on Linux/macOS)** - ```bash - npx resedit dist/bin/app.exe dist/bin/app_with_metadata.exe \ - --icon 1,dist/favicon.ico \ - --company-name "ACME Corporation" \ - --file-description "ACME CLI Tool" \ - --product-name "ACME Application" \ - --file-version 1.2.3.4 - ``` - > 💡 This is especially useful when cross-compiling Windows executables from - > Linux or macOS using `pkg`. +## License -> 📚 **More information:** See the -> [`resedit`](https://www.npmjs.com/package/resedit) package on npm for -> additional examples and full API documentation. +[MIT](LICENSE) diff --git a/docs-site/.gitignore b/docs-site/.gitignore new file mode 100644 index 00000000..55065682 --- /dev/null +++ b/docs-site/.gitignore @@ -0,0 +1,3 @@ +node_modules +.vitepress/cache +.vitepress/dist diff --git a/docs-site/.nvmrc b/docs-site/.nvmrc new file mode 100644 index 00000000..2bd5a0a9 --- /dev/null +++ b/docs-site/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/docs-site/.vitepress/config.ts b/docs-site/.vitepress/config.ts new file mode 100644 index 00000000..63d35bd7 --- /dev/null +++ b/docs-site/.vitepress/config.ts @@ -0,0 +1,153 @@ +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { withMermaid } from 'vitepress-plugin-mermaid'; + +const pkg = JSON.parse( + readFileSync( + fileURLToPath(new URL('../../package.json', import.meta.url)), + 'utf-8', + ), +) as { version: string }; + +const referenceSidebar = [ + { text: 'Architecture', link: '/architecture' }, + { text: 'Contributing', link: '/development' }, + { text: 'Changelog', link: '/changelog' }, +]; + +export default withMermaid({ + title: 'pkg', + description: + 'Package Node.js projects into single executables — no runtime, no npm, cross-compiled for Linux, macOS, and Windows.', + lang: 'en-US', + base: '/pkg/', + cleanUrls: true, + lastUpdated: true, + sitemap: { + hostname: 'https://yao-pkg.github.io/pkg/', + }, + head: [ + ['link', { rel: 'icon', type: 'image/png', href: '/pkg/logo.png' }], + ['meta', { name: 'theme-color', content: '#E89B2C' }], + [ + 'meta', + { property: 'og:title', content: 'pkg — Node.js to single executable' }, + ], + [ + 'meta', + { + property: 'og:description', + content: + 'Package your Node.js project into an executable that runs on devices without Node.js installed.', + }, + ], + [ + 'meta', + { + property: 'og:image', + content: 'https://yao-pkg.github.io/pkg/logo.png', + }, + ], + ['meta', { name: 'twitter:card', content: 'summary_large_image' }], + ], + themeConfig: { + logo: '/logo.png', + siteTitle: 'pkg', + nav: [ + { text: 'Guide', link: '/guide/getting-started', activeMatch: '/guide/' }, + { text: 'Recipes', link: '/guide/recipes' }, + { text: 'SEA vs Standard', link: '/guide/sea-vs-standard' }, + { text: 'Architecture', link: '/architecture' }, + { + text: `v${pkg.version}`, + items: [ + { text: 'Changelog', link: '/changelog' }, + { text: 'Migration from vercel/pkg', link: '/guide/migration' }, + { text: 'Contributing', link: '/development' }, + { text: 'npm', link: 'https://www.npmjs.com/package/@yao-pkg/pkg' }, + { text: 'Issues', link: 'https://github.com/yao-pkg/pkg/issues' }, + ], + }, + ], + sidebar: { + '/guide/': [ + { + text: 'Learn', + items: [ + { text: 'What is pkg?', link: '/guide/' }, + { text: 'Getting started', link: '/guide/getting-started' }, + { text: 'SEA vs Standard', link: '/guide/sea-vs-standard' }, + { text: 'Migration from vercel/pkg', link: '/guide/migration' }, + ], + }, + { + text: 'Build', + items: [ + { text: 'Targets', link: '/guide/targets' }, + { text: 'Configuration', link: '/guide/configuration' }, + { text: 'CLI options', link: '/guide/options' }, + { text: 'Output & debug', link: '/guide/output' }, + { text: 'Bytecode', link: '/guide/bytecode' }, + { text: 'Compression', link: '/guide/compression' }, + { text: 'SEA mode', link: '/guide/sea-mode' }, + { text: 'Environment vars', link: '/guide/environment' }, + { text: 'Build from source', link: '/guide/build' }, + ], + }, + { + text: 'Run', + items: [ + { text: 'Packaged app usage', link: '/guide/packaged-app' }, + { text: 'Snapshot filesystem', link: '/guide/snapshot-fs' }, + { text: 'Detecting assets', link: '/guide/detecting-assets' }, + { text: 'Native addons', link: '/guide/native-addons' }, + { text: 'ESM support', link: '/guide/esm' }, + { text: 'Custom Node.js binary', link: '/guide/custom-node' }, + { text: 'Node.js API', link: '/guide/api' }, + ], + }, + { + text: 'Cookbook', + items: [ + { text: 'Recipes', link: '/guide/recipes' }, + { text: 'Troubleshooting', link: '/guide/troubleshooting' }, + ], + }, + { + text: 'Advanced', + items: [ + { text: 'Debug virtual FS', link: '/guide/advanced-debug-vfs' }, + { + text: 'Windows metadata', + link: '/guide/advanced-windows-metadata', + }, + ], + }, + ], + '/architecture': referenceSidebar, + '/development': referenceSidebar, + '/changelog': referenceSidebar, + }, + socialLinks: [ + { icon: 'github', link: 'https://github.com/yao-pkg/pkg' }, + { icon: 'npm', link: 'https://www.npmjs.com/package/@yao-pkg/pkg' }, + ], + editLink: { + pattern: 'https://github.com/yao-pkg/pkg/edit/main/docs-site/:path', + text: 'Edit this page on GitHub', + }, + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright © 2023-present yao-pkg contributors', + }, + search: { provider: 'local' }, + outline: { level: [2, 4] }, + }, + mermaid: { + // theme intentionally unset — vitepress-plugin-mermaid auto-switches + // between 'default' (light) and 'dark' based on VitePress appearance + }, + mermaidPlugin: { + class: 'mermaid-diagram', + }, +}); diff --git a/docs-site/.vitepress/theme/custom.css b/docs-site/.vitepress/theme/custom.css new file mode 100644 index 00000000..9df91170 --- /dev/null +++ b/docs-site/.vitepress/theme/custom.css @@ -0,0 +1,205 @@ +/** + * pkg brand palette — sampled from logo + * box amber, heart pink, cream cardboard + */ +:root { + --vp-c-brand-1: #c87f0a; + --vp-c-brand-2: #e89b2c; + --vp-c-brand-3: #e89b2c; + --vp-c-brand-soft: rgba(232, 155, 44, 0.14); + + --vp-c-brand-light: #f5c26b; + --vp-c-brand-lighter: #fbe4b3; + --vp-c-brand-dark: #b8750f; + --vp-c-brand-darker: #8a5508; + + --vp-c-tip-1: var(--vp-c-brand-1); + --vp-c-tip-2: var(--vp-c-brand-2); + --vp-c-tip-3: var(--vp-c-brand-3); + --vp-c-tip-soft: var(--vp-c-brand-soft); + + --vp-button-brand-border: transparent; + --vp-button-brand-text: #ffffff; + --vp-button-brand-bg: #e89b2c; + --vp-button-brand-hover-border: transparent; + --vp-button-brand-hover-text: #ffffff; + --vp-button-brand-hover-bg: #d68715; + --vp-button-brand-active-border: transparent; + --vp-button-brand-active-text: #ffffff; + --vp-button-brand-active-bg: #b8750f; + + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: linear-gradient(-30deg, #e89b2c 30%, #ec7a96); + + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + #f5c26b 50%, + #ec7a96 50% + ); + --vp-home-hero-image-filter: blur(44px); +} + +.dark { + --vp-c-brand-1: #f5c26b; + --vp-c-brand-2: #e89b2c; + --vp-c-brand-3: #e89b2c; + --vp-c-brand-soft: rgba(245, 194, 107, 0.16); +} + +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} + +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(68px); + } +} + +/* rounded hero logo */ +.VPHero .image-container img { + border-radius: 24px; +} + +/* responsive hero image on small viewports */ +@media (max-width: 640px) { + .VPHero .VPImage { + max-width: 40vw; + height: auto; + } +} + +/* mermaid diagram sizing + dark-mode readability */ +.mermaid-diagram { + margin: 1.75rem 0; + padding: 1rem; + text-align: center; + background: var(--vp-c-bg-soft); + border: 1px solid var(--vp-c-divider); + border-radius: 10px; + overflow-x: auto; +} + +.mermaid-diagram svg { + width: 100%; + max-width: 960px; + height: auto; + min-height: 220px; +} + +/* bump label contrast and font-size so diagrams stay legible at full width */ +.mermaid-diagram svg .nodeLabel, +.mermaid-diagram svg .edgeLabel, +.mermaid-diagram svg .cluster-label, +.mermaid-diagram svg text { + font-size: 15px !important; +} + +/* dark mode: force readable label colors — mermaid's dark theme + sometimes leaves inherited fills that blend into the background */ +.dark .mermaid-diagram svg .nodeLabel, +.dark .mermaid-diagram svg .edgeLabel, +.dark .mermaid-diagram svg .cluster-label, +.dark .mermaid-diagram svg text { + color: var(--vp-c-text-1) !important; + fill: var(--vp-c-text-1) !important; +} + +.dark .mermaid-diagram svg .edgeLabel { + background-color: var(--vp-c-bg-soft) !important; +} + +.dark .mermaid-diagram svg .edgePath path, +.dark .mermaid-diagram svg .flowchart-link { + stroke: var(--vp-c-text-2) !important; +} + +/* lift node rects off the card background in dark mode so they're + visible without relying solely on stroke */ +.dark .mermaid-diagram svg .node rect, +.dark .mermaid-diagram svg .node polygon, +.dark .mermaid-diagram svg .node circle, +.dark .mermaid-diagram svg .node ellipse, +.dark .mermaid-diagram svg .node path { + fill: #2d2f36 !important; +} + +.dark .mermaid-diagram svg .cluster rect { + fill: #1a1b1f !important; + stroke: var(--vp-c-divider) !important; +} + +/* fork banner callout on the landing page */ +.fork-banner { + max-width: 960px; + margin: 1.5rem auto 0; + padding: 0.9rem 1.25rem; + border-radius: 10px; + border: 1px solid var(--vp-c-brand-2); + background: var(--vp-c-brand-soft); + font-size: 0.92rem; + line-height: 1.55; +} + +.fork-banner strong { + color: var(--vp-c-brand-1); +} + +.dark .fork-banner strong { + color: var(--vp-c-brand-light); +} + +/* landing page badge row — force inline flow, kill paragraph wrapping */ +.landing-badges { + max-width: 960px; + margin: 2rem auto 0; + padding: 0 1.5rem; + text-align: center; +} + +.landing-badges p { + margin: 0; + display: flex; + flex-wrap: wrap; + gap: 0.4rem 0.6rem; + justify-content: center; + align-items: center; +} + +.landing-badges img { + display: inline-block; + vertical-align: middle; + height: 20px; +} + +/* landing page demo (terminal GIF) */ +.landing-demo { + max-width: 900px; + margin: 2rem auto 0; + padding: 0 1.5rem; + text-align: center; +} + +.landing-demo img { + width: 100%; + height: auto; + border-radius: 10px; + box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.35); + border: 1px solid var(--vp-c-divider); +} + +.landing-demo figcaption { + margin-top: 0.75rem; + font-size: 0.88rem; + color: var(--vp-c-text-2); + font-style: italic; +} + +/* landing body content — inherits VitePress prose styles */ +.landing-body { + max-width: 960px; + margin: 3rem auto 0; + padding: 0 1.5rem; +} diff --git a/docs-site/.vitepress/theme/index.ts b/docs-site/.vitepress/theme/index.ts new file mode 100644 index 00000000..149273e8 --- /dev/null +++ b/docs-site/.vitepress/theme/index.ts @@ -0,0 +1,4 @@ +import DefaultTheme from 'vitepress/theme'; +import './custom.css'; + +export default DefaultTheme; diff --git a/docs-site/architecture.md b/docs-site/architecture.md new file mode 100644 index 00000000..fa5d5b11 --- /dev/null +++ b/docs-site/architecture.md @@ -0,0 +1,114 @@ +--- +title: Architecture +description: High-level overview of how pkg packages Node.js applications — the two build modes, the virtual filesystem, and where to go for deeper internals. +--- + +# Architecture + +How `pkg` turns a Node.js project into a single executable, at a glance. + +::: tip Looking for deeper internals? +This page is the short version — build pipelines, binary layout, VFS provider, worker-thread bootstrap, and patch tables all live in **[`docs/ARCHITECTURE.md`](https://github.com/yao-pkg/pkg/blob/main/docs/ARCHITECTURE.md)**. Read that one if you're contributing to `pkg` or debugging the runtime. +::: + +## The two modes + +`pkg` supports two packaging strategies, selected via the `--sea` flag: + +```bash +pkg . # Traditional mode (default) +pkg . --sea # Enhanced SEA mode (Node ≥ 22 with package.json) +pkg single-file.js --sea # Simple SEA mode (single .js file) +``` + +Both start from the same project and end with one executable, but they take very different paths: + +```mermaid +flowchart TD + P["package.json + src/"] + + P --> T1["Traditional
walker + bytecode"] + P --> S1["Enhanced SEA
walker, no bytecode"] + + T1 --> T2["Inject payload into
patched Node.js binary"] + T2 --> TB["Executable with
custom VFS"] + + S1 --> S2["Build SEA blob
+ manifest"] + S2 --> S3["postject inject"] + S3 --> SB["Executable with
NODE_SEA_BLOB"] + + style P stroke:#e89b2c,stroke-width:2px + style TB stroke:#ec7a96,stroke-width:2px + style SB stroke:#66bb6a,stroke-width:2px +``` + +| Aspect | Traditional | Enhanced SEA | +| -------------- | --------------------- | -------------------- | +| Node.js API | Binary patching | Official `node:sea` | +| Base binary | Patched (`pkg-fetch`) | Stock | +| VFS | Custom binary format | `@roberts_lando/vfs` | +| Bytecode | V8 compiled | Source as-is | +| ESM | Transformed to CJS | Native | +| Compression | Brotli / GZip | None | +| Code stripping | Yes (`sourceless`) | No (plaintext) | + +See **[SEA vs Standard](/guide/sea-vs-standard)** for the full decision guide. + +## Traditional mode in one paragraph + +The walker parses the entry file, resolves every `require`/`import`, transforms ESM to CJS, and compiles each module to V8 bytecode. Files are serialized into "stripes" (path + store type + data), optionally compressed, and injected into a patched Node.js binary at placeholder offsets. At runtime, the injected `bootstrap.js` patches `fs`, `Module`, `child_process`, and `process.dlopen` so that anything inside `/snapshot/` is served from the payload instead of disk. + +Strength: V8 bytecode can be stored without source, so code is not trivially extractable. Weakness: the patched binary comes from `pkg-fetch`, which lags behind upstream Node.js releases. + +## Enhanced SEA mode in one paragraph + +The walker runs with `seaMode: true` — no bytecode, no ESM transform. All files are concatenated into a single `__pkg_archive__` blob with a `__pkg_manifest__.json` that maps each path to `[offset, length]`. `node --experimental-sea-config` produces a prep blob, which `postject` injects into a stock Node.js binary as a `NODE_SEA_BLOB` resource. At runtime, a small bootstrap loads the archive via `sea.getRawAsset()` (zero-copy) and mounts it through `@roberts_lando/vfs` (or `node:vfs` once it lands upstream). + +Strength: uses official Node.js APIs, stock binaries, future-proof. Weakness: source code is stored in plaintext. + +## The virtual filesystem + +Both modes expose packaged files under a `/snapshot/` prefix. User code calling `fs.readFileSync('/snapshot/app/config.json')` is intercepted and served from the payload: + +```mermaid +flowchart LR + U["User code
fs.readFileSync /snapshot/app/x.js"] + V["VFS layer"] + P["Payload
(archive or stripes)"] + OUT["Buffer"] + + U --> V --> P --> OUT + style U stroke:#e89b2c,stroke-width:2px + style OUT stroke:#66bb6a,stroke-width:2px +``` + +Traditional mode patches ~20 `fs` functions by hand inside `bootstrap.js`. SEA mode delegates to `@roberts_lando/vfs`, which intercepts 164+ functions and hooks the module resolution system automatically. + +Native addons (`.node` files) can't be loaded straight from memory, so both modes extract them to `~/.cache/pkg//` on first load and call the real `process.dlopen` against the extracted path. See [Native addons](/guide/native-addons). + +## Worker threads + +Workers spawned from a packaged app don't inherit the main thread's `fs` patches. SEA mode solves this by monkey-patching the `Worker` constructor: if the worker script is inside `/snapshot/`, pkg reads the source through the VFS, prepends the VFS bootstrap, and spawns the worker with `{ eval: true }` so it runs in memory with the same VFS mounted. + +## Which files matter + +If you want to read the source, these are the entry points: + +| File | Role | +| ------------------------------- | ------------------------------------------------------------- | +| `lib/index.ts` | CLI entry, mode routing | +| `lib/walker.ts` | Dependency walker (traditional + SEA) | +| `lib/packer.ts` + `producer.ts` | Traditional payload assembly + binary injection | +| `lib/sea.ts` + `sea-assets.ts` | SEA orchestrator + archive/manifest generation | +| `prelude/bootstrap.js` | Traditional runtime (fs/Module/process patching) | +| `prelude/sea-bootstrap.js` | SEA runtime (CJS wrapper for CJS + ESM/TLA entries) | +| `prelude/sea-vfs-setup.js` | SEA VFS core: `SEAProvider`, archive loading, Windows patches | +| `prelude/bootstrap-shared.js` | Shared patches: `dlopen`, `child_process`, `process.pkg` | + +For line-by-line pipelines, binary layouts, patch tables, and the upstream Node.js dependency map, see **[`docs/ARCHITECTURE.md`](https://github.com/yao-pkg/pkg/blob/main/docs/ARCHITECTURE.md)**. + +## Where `pkg` is heading + +The long-term goal is to eliminate patched Node.js binaries entirely and ship `pkg` on stock Node via SEA + `node:vfs`. Progress is tracked in **[#231](https://github.com/yao-pkg/pkg/issues/231)**. + +Once `node:vfs` lands upstream, `@roberts_lando/vfs` becomes a fallback and the SEA bootstrap shrinks to almost nothing — the VFS provider and manual mount are no longer needed. diff --git a/docs-site/changelog.md b/docs-site/changelog.md new file mode 100644 index 00000000..46d87bc4 --- /dev/null +++ b/docs-site/changelog.md @@ -0,0 +1,7 @@ +--- +title: Changelog +description: Release history for @yao-pkg/pkg. +editLink: false +--- + + diff --git a/docs-site/development.md b/docs-site/development.md new file mode 100644 index 00000000..a1c09dcb --- /dev/null +++ b/docs-site/development.md @@ -0,0 +1,146 @@ +--- +title: Contributing +description: Local development setup for pkg itself — build, test, release — plus how to hack on this docs site. +--- + +# PKG Development + +This document aims to help you get started with `pkg` development. + +## Release Process + +In order to create release just run the command: + +```bash +npm run release +``` + +This command will start an interactive process that will guide you through the release process using [release-it](https://github.com/release-it/release-it) + +## Testing + +Before running tests ensure you have build the project by running: + +```bash +npm run build +``` + +> [!NOTE] +> Remember to run again `npm run build` after changing source code (everything inside `lib` folder). + +Then you can use the following command to run tests: + +```bash +node test/test.js [no-npm | only-npm | all] [] +``` + +- `` is the node target the test will use when creating executables, can be `nodeXX` (like `node20`) or `host` (uses host node version as target). +- `[no-npm | only-npm | all]` to specify which tests to run. `no-npm` will run tests that don't require npm, `only-npm` will run against some specific npm modules, and `all` will run all tests. +- `` to use when you want to run only tests matching a specific pattern. Example: `node test/test.js all test-99-*`. You can also set this by using `FLAVOR` environment variable. + +Each test is located inside `test` directory into a dedicated folder named following the pattern `test-XX-*`. The `XX` is a number that represents the order the tests will run. + +When running `node test/test.js all`, based on the options, each test will be run consecutively by running `main.js` file inside the test folder. + +### Example test + +Create a directory named `test-XX-` and inside it create a `main.js` file with the following content: + +```javascript +#!/usr/bin/env node + +'use strict'; + +const assert = require('assert'); +const utils = require('../utils.js'); + +assert(!module.parent); +assert(__dirname === process.cwd()); + +const input = './test-x-index'; + +const newcomers = [ + 'test-x-index-linux', + 'test-x-index-macos', + 'test-x-index-win.exe', +]; + +const before = utils.filesBefore(newcomers); + +utils.pkg.sync([input], { stdio: 'inherit' }); + +utils.filesAfter(before, newcomers); +``` + +Explaining the code above: + +- `assert(!module.parent);` ensures the script is being run directly. +- `assert(__dirname === process.cwd());` ensures the script is being run from the correct directory. +- `utils.filesBefore(newcomers);` get current files in the directory. +- `utils.pkg.sync([input], { stdio: 'inherit' });` runs `pkg` passing input file as only argument. +- `utils.filesAfter(before, newcomers);` checks if the output files were created correctly and cleans up the directory to the original state. + +### Special tests + +- `test-79-npm`: It's the only test runned when using `only-npm`. It install and tests all node modules listed inside that dir and verifies if they are working correctly. +- `test-42-fetch-all`: Foreach known node version verifies there is a patch existing for it using pkg-fetch. +- `test-46-multi-arch`: Tries to cross-compile a binary for all known architectures. + +## Hacking on this docs site + +The documentation you're reading lives under `docs-site/` and is built with [VitePress](https://vitepress.dev). It's a separate npm workspace from `pkg` itself — its own `package.json` and lockfile. + +```bash +cd docs-site +npm install # first time only +npm run docs:dev # hot-reload dev server on http://localhost:5173/pkg/ +``` + +Build a production snapshot and preview it: + +```bash +npm run docs:build # outputs to .vitepress/dist +npm run docs:preview +``` + +### Structure + +- `docs-site/index.md` — landing page (home layout) +- `docs-site/guide/*.md` — user guide +- `docs-site/architecture.md` — architecture deep-dive +- `docs-site/development.md` — this page +- `docs-site/.vitepress/config.ts` — sidebar, nav, mermaid config, version injection +- `docs-site/.vitepress/theme/custom.css` — pkg brand palette + overrides + +Each content page should start with frontmatter providing a `title` and `description` — they feed the ``/`<meta description>` tags and improve search indexing. + +### Mermaid diagrams + +Mermaid is wired via [`vitepress-plugin-mermaid`](https://www.npmjs.com/package/vitepress-plugin-mermaid). Use fenced blocks with the `mermaid` language: + +````md +```mermaid +flowchart LR + A --> B --> C +``` +```` + +### Adding a new page + +1. Create the markdown file with frontmatter (`title`, `description`) +2. Add a sidebar entry in `docs-site/.vitepress/config.ts` under the appropriate group +3. Link to it from related pages so it's discoverable by navigation, not just the sidebar +4. Run `npm run docs:build` — VitePress fails the build on dead links, so any typos surface immediately + +### Canonical sources + +Two repo-root files are now **stubs** that point at their docs-site counterparts: + +- `DEVELOPMENT.md` → `docs-site/development.md` +- `docs/ARCHITECTURE.md` → `docs-site/architecture.md` + +Never edit the stubs — edit the `docs-site/` versions. The stubs exist only for GitHub repo browsers that land on the root `.md` files. + +### CI + +`.github/workflows/docs.yml` runs the VitePress build on every PR that touches `docs-site/**` and deploys to GitHub Pages on every push to `main`. If your PR breaks the docs build, CI will flag it before merge. diff --git a/docs-site/guide/advanced-debug-vfs.md b/docs-site/guide/advanced-debug-vfs.md new file mode 100644 index 00000000..81282084 --- /dev/null +++ b/docs-site/guide/advanced-debug-vfs.md @@ -0,0 +1,72 @@ +--- +title: Debug virtual FS +description: Inspect the contents of a packaged binary's virtual filesystem at runtime with DEBUG_PKG. +--- + +# Exploring the virtual filesystem in debug mode + +When you build with `--debug`, `pkg` injects a diagnostic prelude into the binary. At runtime, setting the `DEBUG_PKG` environment variable dumps the virtual filesystem tree and the symlink table to the console at startup — before your app runs. + +This is the single most useful workflow for answering "why isn't my asset in the binary?" and "which dependency is bloating my bundle?". + +## Basic usage + +::: code-group + +```sh [Linux / macOS] +pkg --debug app.js -o dist/app +DEBUG_PKG=1 ./dist/app +``` + +```bat [Windows] +pkg --debug app.js -o dist\app.exe +set DEBUG_PKG=1 +dist\app.exe +``` + +::: + +`DEBUG_PKG=1` prints the snapshot tree and symlink table. +`DEBUG_PKG=2` additionally mocks `fs` to log **every** filesystem call the running app makes — file opens, stats, readdirs — so you can see exactly which paths your code touches. + +## Filtering noise + +The snapshot tree can be large. Two env vars limit the output to files / folders larger than a threshold: + +```sh +# Only show files bigger than 1 MB and folders bigger than 5 MB +SIZE_LIMIT_PKG=1048576 FOLDER_LIMIT_PKG=5242880 DEBUG_PKG=1 ./dist/app +``` + +Defaults: `SIZE_LIMIT_PKG=5242880` (5 MB), `FOLDER_LIMIT_PKG=10485760` (10 MB). + +## Typical workflow + +1. Build **once** with `--debug`: + ```sh + pkg --debug . -o dist/app + ``` +2. List everything: + ```sh + DEBUG_PKG=1 ./dist/app + ``` +3. Spot the offender — usually a big `test/` or `docs/` folder inside a dependency. +4. Add it to `pkg.ignore` in `package.json`: + ```json + { + "pkg": { + "ignore": ["**/node_modules/*/test/**", "**/node_modules/*/docs/**"] + } + } + ``` +5. Rebuild **without** `--debug` for production. + +::: warning Never ship --debug builds +Debug builds are slower, larger, and print sensitive internal paths at launch. They are for development only. Release builds cannot be coerced into dumping the VFS tree, which is intentional. +::: + +## See also + +- [Output & debug](/guide/output) +- [Environment variables](/guide/environment) +- [Configuration → ignore](/guide/configuration#ignore-files) diff --git a/docs-site/guide/advanced-windows-metadata.md b/docs-site/guide/advanced-windows-metadata.md new file mode 100644 index 00000000..16a88b7d --- /dev/null +++ b/docs-site/guide/advanced-windows-metadata.md @@ -0,0 +1,99 @@ +--- +title: Windows metadata +description: Inject version info, icon, product name, and copyright into a Windows .exe produced by pkg using resedit. +--- + +# Injecting Windows executable metadata after packaging + +Executables created with `pkg` are based on a Node.js binary and, by default, inherit its embedded metadata — version number, product name, company name, icon, description. This can be misleading or unpolished in distributed applications. + +There are two ways to customise the metadata of the resulting `.exe`: + +1. **Use a custom Node.js binary** with your own metadata already embedded — see [Custom Node.js binary](/guide/custom-node). +2. **Post-process the generated executable** using [`resedit`](https://www.npmjs.com/package/resedit), a Node.js-compatible tool for modifying Windows executable resources. This allows injecting correct version info, icons, copyright, and more. + +This page focuses on the second approach. + +::: warning +Other tools may corrupt the executable, resulting in runtime errors such as `Pkg: Error reading from file.` — [`resedit`](https://www.npmjs.com/package/resedit) has proven to work reliably with `pkg`-generated binaries. +::: + +## Node.js API + +```ts +import * as ResEdit from 'resedit'; +import * as fs from 'fs'; +import * as path from 'path'; + +// Set your inputs: +const exePath = 'dist/my-tool.exe'; // Path to the generated executable +const outputPath = exePath; // Overwrite or use a different path +const version = '1.2.3'; // Your application version + +const lang = 1033; // en-US +const codepage = 1200; // Unicode + +const exeData = fs.readFileSync(exePath); +const exe = ResEdit.NtExecutable.from(exeData); +const res = ResEdit.NtExecutableResource.from(exe); + +const viList = ResEdit.Resource.VersionInfo.fromEntries(res.entries); +const vi = viList[0]; + +const [major, minor, patch] = version.split('.'); +vi.setFileVersion(Number(major), Number(minor), Number(patch), 0, lang); +vi.setProductVersion(Number(major), Number(minor), Number(patch), 0, lang); + +vi.setStringValues( + { lang, codepage }, + { + FileDescription: 'ACME CLI Tool', + ProductName: 'ACME Application', + CompanyName: 'ACME Corporation', + ProductVersion: version, + FileVersion: version, + OriginalFilename: path.basename(exePath), + LegalCopyright: `© ${new Date().getFullYear()} ACME Corporation`, + }, +); + +vi.outputToResourceEntries(res.entries); +res.outputResource(exe); +const newBinary = exe.generate(); + +fs.writeFileSync(outputPath, Buffer.from(newBinary)); +``` + +## Command line + +[`resedit`](https://www.npmjs.com/package/resedit) also supports command-line usage. This is convenient for simple use cases in build scripts. + +The following examples inject an icon and metadata into the executable `dist/bin/app_with_metadata.exe`, based on the built file `dist/bin/app.exe`. + +::: code-group + +```powershell [PowerShell] +npx resedit dist/bin/app.exe dist/bin/app_with_metadata.exe ` + --icon 1,dist/favicon.ico ` + --company-name "ACME Corporation" ` + --file-description "ACME CLI Tool" ` + --product-name "ACME Application" ` + --file-version 1.2.3.4 +``` + +```bash [bash] +npx resedit dist/bin/app.exe dist/bin/app_with_metadata.exe \ + --icon 1,dist/favicon.ico \ + --company-name "ACME Corporation" \ + --file-description "ACME CLI Tool" \ + --product-name "ACME Application" \ + --file-version 1.2.3.4 +``` + +::: + +::: tip +This is especially useful when cross-compiling Windows executables from Linux or macOS using `pkg`. +::: + +See the [`resedit`](https://www.npmjs.com/package/resedit) package on npm for additional examples and full API documentation. diff --git a/docs-site/guide/api.md b/docs-site/guide/api.md new file mode 100644 index 00000000..f9143bed --- /dev/null +++ b/docs-site/guide/api.md @@ -0,0 +1,98 @@ +--- +title: Node.js API +description: Call pkg programmatically from a Node.js build script instead of the CLI. +--- + +# Node.js API + +In addition to the CLI, `pkg` exposes a small programmatic API so you can drive builds from a Node.js script — useful for custom release pipelines, CI integration, or wrapping `pkg` inside a bigger build tool. + +## Install + +```sh +npm install --save-dev @yao-pkg/pkg +``` + +## Import + +::: code-group + +```js [CommonJS] +const { exec } = require('@yao-pkg/pkg'); +``` + +```js [ESM] +import { exec } from '@yao-pkg/pkg'; +``` + +::: + +## `exec(args)` + +`exec(args)` takes an array of command-line arguments and returns a `Promise<void>` that resolves when the build is complete, or rejects on failure. + +```js +const { exec } = require('@yao-pkg/pkg'); + +await exec(['index.js', '--target', 'host', '--output', 'dist/app']); + +// do something with dist/app, upload, deploy, etc. +``` + +The array elements are exactly the strings you'd pass on the command line — see [Getting started → CLI reference](/guide/getting-started#cli-reference) for the full option list. + +## Build a full release pipeline + +```js +const { exec } = require('@yao-pkg/pkg'); +const { mkdir, rm } = require('node:fs/promises'); +const path = require('node:path'); + +const DIST = 'dist'; +const TARGETS = [ + 'node22-linux-x64', + 'node22-linux-arm64', + 'node22-macos-arm64', + 'node22-win-x64', +]; + +async function build() { + await rm(DIST, { recursive: true, force: true }); + await mkdir(DIST, { recursive: true }); + + await exec([ + '.', + '--targets', + TARGETS.join(','), + '--out-path', + DIST, + '--compress', + 'Brotli', + ]); + + console.log(`✅ built ${TARGETS.length} binaries into ${path.resolve(DIST)}`); +} + +build().catch((err) => { + console.error(err); + process.exit(1); +}); +``` + +## Error handling + +`exec` rejects with an `Error` whose `message` contains the same diagnostic you'd see on the CLI. Wrap in try/catch (or chain `.catch`) if you need to react to specific failures: + +```js +try { + await exec(['bad/input.js']); +} catch (err) { + console.error('pkg build failed:', err.message); + process.exitCode = 1; +} +``` + +## See also + +- [CLI options](/guide/options) +- [Recipes: build in CI](/guide/recipes#build-all-targets-in-ci) diff --git a/docs-site/guide/build.md b/docs-site/guide/build.md new file mode 100644 index 00000000..962ddda6 --- /dev/null +++ b/docs-site/guide/build.md @@ -0,0 +1,45 @@ +--- +title: Build from source +description: Compile Node.js base binaries from source instead of downloading pre-built ones from pkg-fetch. +--- + +# Build from source + +`pkg` has so-called **base binaries** — Node.js executables with some patches applied. They're used as the starting point for every executable `pkg` creates. By default `pkg` downloads pre-compiled base binaries from [`pkg-fetch`](https://github.com/yao-pkg/pkg-fetch) before packaging your application. + +If you prefer to compile base binaries from source, pass `--build`: + +```sh +pkg --build index.js +``` + +::: warning Slow +Compiling a full Node.js binary takes **tens of minutes** on a fast machine and can easily hit hours on slower hardware. Only use `--build` when you actually need a custom compile. +::: + +## Prerequisites + +Your machine needs everything Node.js requires to compile from source. The authoritative list is in [nodejs/node/BUILDING.md](https://github.com/nodejs/node/blob/HEAD/BUILDING.md). At a minimum: + +- A C/C++ toolchain (gcc, clang, or MSVC) +- Python 3 +- GNU make or Ninja +- Several GB of free disk and memory + +## When to build from source + +- Targeting an architecture not in [`pkg-fetch` releases](https://github.com/yao-pkg/pkg-fetch/releases) and not in [`pkg-binaries`](https://github.com/yao-pkg/pkg-binaries) +- Applying your own patches on top of `pkg-fetch`'s patches +- Debugging a `pkg` issue that requires a custom Node.js build + +Otherwise, stick with the default — downloaded binaries are faster, cached, and covered by CI. + +::: tip Future direction +[SEA mode](/guide/sea-mode) removes the need for patched Node.js binaries entirely. See [SEA vs Standard](/guide/sea-vs-standard) and the [pkg-fetch elimination roadmap](/guide/sea-vs-standard#roadmap-killing-pkg-fetch). If you're reaching for `--build` because `pkg-fetch` doesn't cover your target, SEA may solve it upstream. +::: + +## See also + +- [Custom Node.js binary](/guide/custom-node) +- [Targets](/guide/targets) +- [pkg-fetch releases](https://github.com/yao-pkg/pkg-fetch/releases) diff --git a/docs-site/guide/bytecode.md b/docs-site/guide/bytecode.md new file mode 100644 index 00000000..c3a45d4c --- /dev/null +++ b/docs-site/guide/bytecode.md @@ -0,0 +1,65 @@ +--- +title: Bytecode +description: V8 bytecode compilation in pkg — why it exists, when to disable it, and how it interacts with reproducible builds and licensing. +--- + +# Bytecode + +By default, your source code is precompiled to **V8 bytecode** before being written to the output file. This strips the original JavaScript source from the binary, making it harder (though not impossible) to recover. Disable with `--no-bytecode`. + +```sh +pkg --no-bytecode index.js +``` + +## Why bytecode is on by default + +- **Source obscurity.** With `--no-bytecode`, raw JavaScript is embedded directly. On a \*nix machine, `pkg` a project with `--no-bytecode` and run GNU `strings` on the output — you can grep your source. Bytecode doesn't make it _secure_, but it adds a layer of friction that deters casual reverse engineering. +- **Faster startup.** V8 can skip parsing and directly execute the bytecode. + +## Why you might disable it + +### Reproducible builds + +V8 bytecode compilation is not deterministic (see [this paper](https://ui.adsabs.harvard.edu/abs/2019arXiv191003478C/abstract) and [this post](https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775)) — different runs produce different bytecode for the same input. If you need reproducible executable hashes (md5, sha256, …) across builds, disable bytecode: + +```sh +pkg --no-bytecode --public-packages "*" index.js +``` + +### Cross-compiling without QEMU + +Bytecode generation requires running the **target** architecture's Node.js to compile the code. On Linux that means binfmt + QEMU for foreign arches. If you don't want to set that up, disabling bytecode avoids the requirement entirely: + +```sh +pkg --no-bytecode --public-packages "*" --public -t node22-linux-arm64 index.js +``` + +See [Targets → Cross-compilation notes](/guide/targets#cross-compilation-notes). + +## Licenses and `--public-packages` + +Disabling bytecode fails if any package in your project isn't explicitly marked as public via `license` in its `package.json`. `pkg` checks the license of each package and makes sure that non-public code is only included **as bytecode** — this is a legal safety net for proprietary dependencies. + +Override this behaviour by whitelisting packages: + +```sh +pkg --no-bytecode --public-packages "packageA,packageB" index.js +``` + +Or mark all packages as public: + +```sh +pkg --no-bytecode --public-packages "*" --public index.js +``` + +`--public` additionally exposes the **top-level project** sources (i.e. your own code) as plain text. + +## SEA mode + +SEA mode **never uses bytecode**. Source is always plaintext in a SEA binary. This is a deliberate trade-off — see [SEA vs Standard](/guide/sea-vs-standard). + +## See also + +- [Compression](/guide/compression) +- [Targets](/guide/targets) +- [SEA vs Standard](/guide/sea-vs-standard) diff --git a/docs-site/guide/compression.md b/docs-site/guide/compression.md new file mode 100644 index 00000000..c7c4ec1c --- /dev/null +++ b/docs-site/guide/compression.md @@ -0,0 +1,59 @@ +--- +title: Compression +description: Shrink the embedded filesystem inside your pkg binary with Brotli or GZip. +--- + +# Compression + +Pass `--compress Brotli` or `--compress GZip` to compress the contents of files stored in the executable. `-C` is a shortcut for `--compress`. + +::: code-group + +```sh [Brotli (smaller)] +pkg --compress Brotli index.js +``` + +```sh [GZip (faster to decompress)] +pkg -C GZip index.js +``` + +```json [package.json] +{ + "pkg": { + "compress": "Brotli" + } +} +``` + +::: + +## How much does it save? + +This option can reduce the size of the embedded filesystem by up to **60%**. The exact ratio depends on your project — heavy JavaScript (libraries with long variable names) compresses well, already-minified code less so. + +The startup time of the application may actually be **slightly reduced** — smaller disk reads often outweigh the decompression cost. + +## Brotli vs GZip + +| Algorithm | Compression ratio | Decompression speed | Use when | +| --------- | ----------------- | ------------------- | ------------------------------- | +| Brotli | Higher | Slower | Binary size matters most | +| GZip | Lower | Faster | Cold-start latency matters most | + +For most CLI tools, Brotli is the better default. For long-running services where the extra MB or two doesn't matter, GZip shaves a few ms off startup. + +## SEA mode + +::: warning Not supported in SEA mode +Compression is **not** available when packaging with `--sea`. The SEA binary layout uses a flat blob without per-file compression. If binary size is critical, stick with Standard mode. See [SEA vs Standard](/guide/sea-vs-standard). +::: + +## Troubleshooting + +If the compressed binary fails to start with a corruption error, try rebuilding without compression first to isolate the cause. Large files (multi-MB assets) can trip edge cases; `--debug` + `DEBUG_PKG=1` will show you the snapshot tree. + +## See also + +- [Bytecode](/guide/bytecode) +- [Targets](/guide/targets) +- [Output & debug](/guide/output) diff --git a/docs-site/guide/configuration.md b/docs-site/guide/configuration.md new file mode 100644 index 00000000..64de7313 --- /dev/null +++ b/docs-site/guide/configuration.md @@ -0,0 +1,107 @@ +--- +title: Configuration +description: Configure pkg via the pkg property in package.json — scripts, assets, ignore globs, targets, output path, and more. +--- + +# Configuration + +`pkg` auto-detects most dependencies by walking `require` / `import` from your entry file (see [how it works](/guide/)). You only need to configure it when your code uses dynamic `require(variable)` calls or non-JavaScript files (views, CSS, images, etc.): + +```js +require('./build/' + cmd + '.js'); +path.join(__dirname, 'views/' + viewName); +``` + +These cases are not handled automatically. You must specify scripts and assets manually in the `pkg` property of your `package.json`. + +```json +{ + "pkg": { + "scripts": "build/**/*.js", + "assets": "views/**/*", + "targets": ["node22-linux-arm64"], + "outputPath": "dist" + } +} +``` + +The example above includes everything in `assets/` and every `.js` file in `build/`, builds only for `node22-linux-arm64`, and places the executable inside `dist/`. + +You may also specify arrays of globs: + +```json +{ + "pkg": { + "assets": ["assets/**/*", "images/**/*"] + } +} +``` + +Call `pkg package.json` or `pkg .` to make use of the `package.json` configuration. + +## Full schema + +| Key | Type | Description | +| -------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `scripts` | glob \| string[] | JS files compiled to V8 bytecode and embedded without source — see [Scripts](#scripts) | +| `assets` | glob \| string[] | Files embedded as raw content, accessible under `/snapshot/` — see [Assets](#assets) | +| `ignore` | string[] | Globs excluded from the final executable — see [Ignore files](#ignore-files) | +| `targets` | string[] | Target triples, e.g. `node22-linux-x64` — see [Targets](/guide/targets) | +| `outputPath` | string | Directory for output binaries (equivalent to CLI `--out-path`) | +| `patches` | object | Patch modules that can't be packaged as-is — see [pkg source](https://github.com/yao-pkg/pkg/blob/main/dictionary/) for examples | +| `sea` | boolean | Opt into [SEA mode](/guide/sea-mode) without passing `--sea` | +| `seaConfig` | object | Forwarded to Node.js SEA config (`useCodeCache`, `disableExperimentalSEAWarning`, etc.) | +| `deployAssets` | boolean | Copy `assets` next to the executable at runtime instead of keeping them in the snapshot | + +## Scripts + +`scripts` is a [glob](https://github.com/SuperchupuDev/tinyglobby) or a list of globs. Files specified as `scripts` are compiled with `v8::ScriptCompiler` and placed into the executable **without sources**. They must conform to the JS standard of the Node.js versions you target (see [Targets](/guide/targets)) — i.e. be already transpiled. + +## Assets + +`assets` is a [glob](https://github.com/SuperchupuDev/tinyglobby) or a list of globs. Files specified as `assets` are packaged into the executable as raw content without modification. JavaScript files may also be specified as assets. Their sources are not stripped, which improves execution performance and simplifies debugging. + +See also [Detecting assets in source code](/guide/detecting-assets) and [Snapshot filesystem](/guide/snapshot-fs). + +## Ignore files + +`ignore` is a list of globs. Files matching these paths are excluded from the final executable. Useful when you want to exclude tests, documentation, or build files that a dependency brings along: + +```json +{ + "pkg": { + "ignore": ["**/*/dependency-name/build.c"] + } +} +``` + +Note that `**` and `*` do **not** match dotfiles like `.git`. Dotfile names must be spelled explicitly in the glob. + +To see which unwanted files ended up in your executable, read [Exploring the virtual filesystem in debug mode](/guide/advanced-debug-vfs). + +## Typical config + +A production-ready `package.json` often looks like this: + +```json +{ + "name": "my-tool", + "version": "1.0.0", + "bin": "src/cli.js", + "scripts": { + "build": "pkg ." + }, + "pkg": { + "targets": [ + "node22-linux-x64", + "node22-linux-arm64", + "node22-macos-x64", + "node22-macos-arm64", + "node22-win-x64" + ], + "assets": ["views/**/*", "public/**/*", "migrations/**/*.sql"], + "ignore": ["**/*/node_modules/*/test/**"], + "outputPath": "dist" + } +} +``` diff --git a/docs-site/guide/custom-node.md b/docs-site/guide/custom-node.md new file mode 100644 index 00000000..a79df4e2 --- /dev/null +++ b/docs-site/guide/custom-node.md @@ -0,0 +1,35 @@ +--- +title: Custom Node.js binary +description: Use your own Node.js binary as the base for a pkg build — useful for custom metadata, security patches, or unusual architectures. +--- + +# Custom Node.js binary + +By default `pkg` downloads a pre-compiled, patched Node.js binary from [`pkg-fetch`](https://github.com/yao-pkg/pkg-fetch) and uses it as the base for every executable it creates. For most projects this is exactly what you want. + +If you need a **custom** base binary — for an architecture not covered by `pkg-fetch`, a build with specific V8 flags, or a Node.js you've already patched for Windows metadata or corporate compliance — set `PKG_NODE_PATH` to point at it: + +```bash +PKG_NODE_PATH=/path/to/node pkg app.js +``` + +`pkg` will use that binary as the base instead of fetching one. + +## When to use a custom binary + +- **Unsupported architectures** — `pkg-fetch` covers Linux / macOS / Windows on x64 + arm64. For anything else (RISC-V, armv6, BSD), compile Node.js yourself or use a [`pkg-binaries`](https://github.com/yao-pkg/pkg-binaries) build. +- **Pre-embedded metadata** — on Windows, you can compile a Node.js binary that already has your product name, icon, and version baked in. Then `pkg`-ing your JS on top preserves it. See [Windows metadata](/guide/advanced-windows-metadata) for an alternative post-processing approach. +- **Security policy** — enterprises that pin Node.js to a specific internal build can feed it into `pkg`. +- **Debug builds** — a debug-enabled Node.js lets you attach a debugger to the packaged app in development. + +## Caveats + +- The binary must be a **compatible** Node.js version — `pkg` still injects its bootstrap prelude and payload, and depends on specific symbol offsets. Use a version supported by `pkg-fetch` unless you know what you're doing. +- `PKG_NODE_PATH` affects a **single target**. Multi-target builds still fetch the other platforms from `pkg-fetch` unless you set it per-run. +- SEA mode uses stock Node.js by its own mechanism and does **not** honour `PKG_NODE_PATH` in the same way. For SEA, use `process.execPath` of the Node.js you want directly. + +## See also + +- [Build from source](/guide/build) +- [Windows metadata](/guide/advanced-windows-metadata) +- [pkg-binaries](https://github.com/yao-pkg/pkg-binaries) diff --git a/docs-site/guide/detecting-assets.md b/docs-site/guide/detecting-assets.md new file mode 100644 index 00000000..2436ba50 --- /dev/null +++ b/docs-site/guide/detecting-assets.md @@ -0,0 +1,70 @@ +--- +title: Detecting assets +description: How pkg finds assets statically via path.join(__dirname, ...) — rules, pitfalls, and escape hatches. +--- + +# Detecting assets in source code + +When `pkg` encounters `path.join(__dirname, '../path/to/asset')`, it automatically packages the referenced file as an asset — no manual `assets` entry needed. This static analysis avoids forcing every project to configure its assets explicitly. + +## The supported pattern + +```js +path.join(__dirname, 'views/greeting.html'); // ✅ detected +path.join(__dirname, 'migrations/001.sql'); // ✅ detected +path.join(__dirname, '../data/cities.json'); // ✅ detected +``` + +::: warning Two arguments only +`path.join` must have **exactly two arguments**, and the second must be a **string literal**. Anything else — three args, a variable, a template literal with expressions — is not detected. +::: + +## Not detected + +```js +const view = 'greeting.html'; +path.join(__dirname, 'views', view); // ❌ three arguments +path.join(__dirname, `views/${name}.html`); // ❌ expression inside template +const p = 'views/greeting.html'; +path.join(__dirname, p); // ❌ variable, not literal +``` + +For these, list the file(s) manually in the `assets` glob — see [Configuration → Assets](/guide/configuration#assets). + +## Why this matters + +The static walker rewrites detected calls so that at runtime, the resolved path points at `/snapshot/...` and the asset is served from the virtual filesystem. If the call isn't detected, the asset isn't bundled — and your packaged binary will throw `ENOENT` at runtime. + +## How to find missing assets + +1. Build with `--debug`: + ```sh + pkg --debug index.js + ``` +2. Run the binary with `DEBUG_PKG=1`: + ```sh + DEBUG_PKG=1 ./app-linux + ``` +3. Look at the snapshot tree in the output — is your asset there? If not, either fix the call-site to match the supported pattern or add the asset to the `assets` glob. + +See [Debug virtual FS](/guide/advanced-debug-vfs) for the full debug workflow. + +## Escape hatch — dynamic assets + +If your asset paths are genuinely dynamic (e.g. user-selected theme, loaded language pack), glob the whole directory in `package.json`: + +```json +{ + "pkg": { + "assets": ["themes/**/*", "i18n/**/*.json"] + } +} +``` + +This packages everything matching the glob, regardless of whether any specific `path.join(...)` call is statically analysable. + +## See also + +- [Configuration → Assets](/guide/configuration#assets) +- [Snapshot filesystem](/guide/snapshot-fs) +- [Debug virtual FS](/guide/advanced-debug-vfs) diff --git a/docs-site/guide/environment.md b/docs-site/guide/environment.md new file mode 100644 index 00000000..826a5aa4 --- /dev/null +++ b/docs-site/guide/environment.md @@ -0,0 +1,58 @@ +--- +title: Environment variables +description: Build-time and runtime environment variables that influence pkg behaviour — cache paths, native addon extraction, debug output. +--- + +# Environment variables + +`pkg` honours its own variables plus those from `pkg-fetch` (used during base-binary download). This page lists the complete set. + +## Build-time + +Set before running the `pkg` command. + +| Variable | Default | Description | +| ---------------------------- | --------------- | ------------------------------------------------------------------------------------ | +| `PKG_CACHE_PATH` | `~/.pkg-cache/` | Where `pkg-fetch` caches downloaded Node.js base binaries | +| `PKG_IGNORE_TAG` | unset | If set, `pkg-fetch` ignores the built-in release tag and uses `latest` | +| `HTTP_PROXY` / `HTTPS_PROXY` | unset | Proxy forwarded to `pkg-fetch` downloads | +| `PKG_STRICT_VER` | unset | Enable walker assertions — each file state must apply to a real file, not a symlink | +| `NODE_OPTIONS` | unset | Honoured as per Node.js; see [Troubleshooting](/guide/troubleshooting) for conflicts | + +For the full `pkg-fetch` environment list, see the [`pkg-fetch` README](https://github.com/yao-pkg/pkg-fetch#environment). + +## Runtime (inside the packaged app) + +Set when **running** a binary produced by `pkg`. + +| Variable | Default | Description | +| ----------------------- | --------------------- | ----------------------------------------------------------------------------------------- | +| `CHDIR` | unset | Override `process.chdir` at startup | +| `PKG_NATIVE_CACHE_PATH` | `~/.cache/pkg-native` | Base directory for extracted native addons — see [Native addons](/guide/native-addons) | +| `PKG_EXECPATH` | set by `pkg` | Used internally to detect pkg-launched processes — see note below | +| `DEBUG_PKG` | unset | `1` prints snapshot tree; `2` also mocks `fs` to log every call. Requires `--debug` build | +| `SIZE_LIMIT_PKG` | `5242880` (5 MB) | With `DEBUG_PKG`, log files larger than this many bytes | +| `FOLDER_LIMIT_PKG` | `10485760` (10 MB) | With `DEBUG_PKG`, log folders larger than this many bytes | + +::: warning PKG_EXECPATH +`PKG_EXECPATH` is set by `pkg` at runtime and **should not be overridden in normal use**. There is one documented exception: when spawning a child process via `child_process` where you want the child to run a _different_ Node.js binary instead of the packaged one. Set `PKG_EXECPATH: ''` in the child's `env` — see the [child_process recipe in Troubleshooting](/guide/troubleshooting#error-cannot-find-module-xxx-when-using-child-process). +::: + +## Examples + +```bash +# 1. Build-time: override pkg-fetch cache path +export PKG_CACHE_PATH=/my/cache +pkg app.js + +# 2. Runtime: override native-addon extraction path +PKG_NATIVE_CACHE_PATH=/opt/myapp/cache ./myapp + +# 3. Build-time + runtime +PKG_CACHE_PATH=/build/cache pkg app.js +PKG_NATIVE_CACHE_PATH=/runtime/cache ./myapp + +# 4. Debug a packaged binary +pkg --debug app.js +DEBUG_PKG=1 SIZE_LIMIT_PKG=1000000 ./app +``` diff --git a/docs-site/guide/esm.md b/docs-site/guide/esm.md new file mode 100644 index 00000000..78351ff0 --- /dev/null +++ b/docs-site/guide/esm.md @@ -0,0 +1,39 @@ +--- +title: ESM support +description: Package projects that use ECMAScript modules — imports, exports, top-level await, and import.meta. +--- + +# ECMAScript Modules (ESM) + +Starting from version **6.13.0**, `pkg` has improved support for ECMAScript Modules. Most ESM features are automatically transformed to CommonJS during packaging. + +## Supported ESM features + +- **`import` and `export` statements** — automatically transformed to `require()` and `module.exports` +- **Top-level `await`** — wrapped in an async IIFE to work in a CommonJS context +- **Top-level `for await...of`** — wrapped in an async IIFE to work in a CommonJS context +- **`import.meta.url`** — polyfilled to provide the file URL of the current module +- **`import.meta.dirname`** — polyfilled to provide the directory path (Node.js 20.11+ property) +- **`import.meta.filename`** — polyfilled to provide the file path (Node.js 20.11+ property) + +## Known limitations + +1. **Modules with both top-level await and exports** — modules that use `export` statements alongside top-level `await` cannot be wrapped in an async IIFE and will not be transformed to bytecode. They are included as source code instead. +2. **`import.meta.main`** and other custom properties — only the standard `import.meta` properties listed above are polyfilled. Custom properties added by your code or other tools may not work as expected. +3. **Dynamic imports** — `import()` expressions work but may have limitations depending on the module being imported. + +## Best practices + +- For **entry-point scripts** (the main file you're packaging), feel free to use top-level await. +- For **library modules** that will be imported by other code, avoid using both exports and top-level await together. +- Test your packaged executable to ensure all ESM features work as expected in your specific use case. + +::: tip Enhanced SEA mode +In [Enhanced SEA mode](/guide/sea-mode#enhanced-sea--full-project-with-package-json), ESM entry points with top-level await work on every supported target (Node >= 22) **without** the async-IIFE transform. ESM entries are dispatched via `vm.Script` + `USE_MAIN_CONTEXT_DEFAULT_LOADER`. If your project relies heavily on modern ESM, SEA mode is the cleaner path. +::: + +## See also + +- [SEA mode](/guide/sea-mode) — first-class ESM support +- [Recipes: ship an ESM project](/guide/recipes#ship-an-esm-project-with-top-level-await) +- [Troubleshooting: `ERR_REQUIRE_ESM`](/guide/troubleshooting#error-err-require-esm) diff --git a/docs-site/guide/getting-started.md b/docs-site/guide/getting-started.md new file mode 100644 index 00000000..70cafa9e --- /dev/null +++ b/docs-site/guide/getting-started.md @@ -0,0 +1,141 @@ +--- +title: Getting started +description: Install pkg, package your first Node.js project into a single executable, and learn the CLI in under five minutes. +--- + +# Getting started + +## Prerequisites + +- **Node.js >= 22** on the build host (check with `node -v`) +- **npm or any Node.js package manager** (pnpm, yarn, bun all work) +- **~500 MB free disk** for cached base binaries on first run (`~/.pkg-cache/`) + +Cross-compiling Linux / macOS / Windows binaries from a single host is fully supported — see [Targets](/guide/targets) for per-platform caveats. + +## Install + +::: code-group + +```sh [npm] +npm install -g @yao-pkg/pkg +``` + +```sh [pnpm] +pnpm add -g @yao-pkg/pkg +``` + +```sh [yarn] +yarn global add @yao-pkg/pkg +``` + +```sh [npx (no install)] +npx @yao-pkg/pkg . +``` + +::: + +Verify the install: + +```sh +pkg --version +``` + +## Build your first binary + +Create a tiny project: + +```sh +mkdir hello-pkg && cd hello-pkg +echo 'console.log("hello from a single binary!");' > index.js +``` + +Package it: + +```sh +pkg index.js +``` + +You should now see three executables in the current directory: + +```text +index-linux +index-macos +index-win.exe +``` + +Each is a fully self-contained binary — no Node.js required on the target machine. Run the one for your host: + +::: code-group + +```sh [Linux] +./index-linux +# → hello from a single binary! +``` + +```sh [macOS] +./index-macos +# → hello from a single binary! +``` + +```powershell [Windows] +.\index-win.exe +# → hello from a single binary! +``` + +::: + +### Package a whole project + +With a `package.json` in place, `pkg` follows its `bin` entry and walks your dependencies automatically: + +```json +{ + "name": "hello-pkg", + "version": "1.0.0", + "bin": "index.js", + "pkg": { + "targets": ["node22-linux-x64", "node22-macos-arm64", "node22-win-x64"], + "outputPath": "dist" + } +} +``` + +Then: + +```sh +pkg . +``` + +`pkg` reads the `pkg` property in `package.json`, targets just the three platforms listed, and drops the output into `dist/`. See [Configuration](/guide/configuration) for the full config schema and [Targets](/guide/targets) for the target triple syntax. + +## CLI reference + +| Flag | Short | Description | +| -------------------------- | ----- | ------------------------------------------------------------------------------------------------ | +| `--help` | `-h` | Show usage | +| `--version` | `-v` | Print pkg version | +| `--targets <list>` | `-t` | Comma-separated target list, e.g. `node22-linux-x64` — see [Targets](/guide/targets) | +| `--config <path>` | `-c` | Path to `package.json` or any JSON file with a top-level `pkg` config | +| `--output <path>` | `-o` | Output file name (single-target builds only) | +| `--out-path <dir>` | | Output directory for multi-target builds | +| `--debug` | `-d` | Verbose packaging log — see [Output & debug](/guide/output) | +| `--build` | `-b` | Compile base binaries from source instead of downloading — see [Build](/guide/build) | +| `--public` | | Speed up packaging and disclose top-level sources | +| `--public-packages <list>` | | Force listed packages to be treated as public — see [Bytecode](/guide/bytecode) | +| `--no-bytecode` | | Skip V8 bytecode compilation, embed source as plain JS — see [Bytecode](/guide/bytecode) | +| `--no-native-build` | | Skip building native addons | +| `--no-dict <list>` | | Ignore bundled dictionaries for listed packages (`*` disables all) | +| `--options <list>` | | Bake V8 options into the executable — see [CLI options](/guide/options) | +| `--compress <algo>` | `-C` | Compress the embedded filesystem with `Brotli` or `GZip` — see [Compression](/guide/compression) | +| `--sea` | | Use Node.js SEA instead of the patched base binary — see [SEA mode](/guide/sea-mode) | + +Run `pkg --help` at any time for the live list of options. + +## Next steps + +- **[Targets](/guide/targets)** — cross-compile for other platforms +- **[Configuration](/guide/configuration)** — `pkg` property, assets, scripts, ignore +- **[SEA vs Standard](/guide/sea-vs-standard)** — which packaging mode to pick +- **[Recipes](/guide/recipes)** — copy-paste solutions for common tasks +- **[Troubleshooting](/guide/troubleshooting)** — if something breaks diff --git a/docs-site/guide/index.md b/docs-site/guide/index.md new file mode 100644 index 00000000..44c74892 --- /dev/null +++ b/docs-site/guide/index.md @@ -0,0 +1,52 @@ +--- +title: What is pkg? +description: pkg packages Node.js projects into single self-contained executables for Linux, macOS, and Windows — no runtime install required on the target machine. +--- + +# What is pkg? + +`pkg` is a command-line tool that packages your Node.js project into a **single self-contained executable**. The resulting binary runs on devices that don't have Node.js installed, ship no `node_modules`, and boot like any other native CLI tool. + +## Use cases + +- Make a commercial version of your application without sources +- Make a demo, evaluation, or trial version of your app without sources +- Instantly make executables for other platforms (cross-compilation) +- Make a self-extracting archive or installer +- Skip installing Node.js and npm on the deployment target +- Deploy a single file instead of hundreds of `npm install` artifacts +- Put your assets inside the executable to make it even more portable +- Test your app against a new Node.js version without installing it + +## Two packaging modes + +`pkg` builds executables in either **Standard** mode (patched Node.js, bytecode, compression) or **Enhanced SEA** mode (stock Node.js via the [Single Executable Applications](https://nodejs.org/api/single-executable-applications.html) API). See **[SEA vs Standard](/guide/sea-vs-standard)** to pick. + +## How it works + +```mermaid +flowchart LR + A[Your Node.js project] --> B[pkg walker] + B --> C[Bundled payload] + C --> D{Mode} + D -- Standard --> E[Patched Node.js + custom VFS] + D -- Enhanced SEA --> F[Stock Node.js + NODE_SEA_BLOB] + E --> G[Single executable] + F --> G + + style A stroke:#e89b2c,stroke-width:2px + style G stroke:#66bb6a,stroke-width:2px +``` + +The walker follows `require` / `import` from your entry file, pulls in every dependency, optionally compiles JavaScript to V8 bytecode (Standard) or keeps source (SEA), and injects the whole bundle into a Node.js binary. + +Want the full story? See [Architecture](/architecture). + +## Next steps + +- [Getting started](/guide/getting-started) — install and build your first binary +- [Targets](/guide/targets) — cross-compile for other platforms +- [Configuration](/guide/configuration) — scripts, assets, and the `pkg` property in `package.json` +- [SEA vs Standard](/guide/sea-vs-standard) — which mode to pick +- [Recipes](/guide/recipes) — copy-paste solutions +- [Migration from vercel/pkg](/guide/migration) diff --git a/docs-site/guide/migration.md b/docs-site/guide/migration.md new file mode 100644 index 00000000..fa06b7de --- /dev/null +++ b/docs-site/guide/migration.md @@ -0,0 +1,98 @@ +--- +title: Migration from vercel/pkg +description: How to switch from the archived vercel/pkg to the maintained yao-pkg/pkg fork — drop-in rename, differences, and compatibility notes. +--- + +# Migration from `vercel/pkg` + +[`vercel/pkg`](https://github.com/vercel/pkg) was **archived** in January 2024 and no longer receives updates. [`yao-pkg/pkg`](https://github.com/yao-pkg/pkg) is the actively maintained fork and the recommended path forward. + +For the vast majority of projects, **migration is a one-line dependency rename** — nothing else changes. + +## TL;DR + +::: code-group + +```sh [npm] +npm uninstall pkg +npm install --save-dev @yao-pkg/pkg +``` + +```sh [pnpm] +pnpm remove pkg +pnpm add -D @yao-pkg/pkg +``` + +```sh [yarn] +yarn remove pkg +yarn add -D @yao-pkg/pkg +``` + +::: + +Update any `package.json` scripts that called the bin: + +```diff + { + "scripts": { +- "build": "pkg ." ++ "build": "pkg ." + }, + "devDependencies": { +- "pkg": "^5.8.1", ++ "@yao-pkg/pkg": "^6.15.0" + } + } +``` + +The CLI name (`pkg`) is unchanged — only the npm package name differs. All existing `pkg .`, `pkg index.js`, `pkg -t ...` commands keep working. + +## What's different + +### Node.js version support + +| Fork | Supported Node.js versions | +| ------------- | -------------------------------------------------- | +| `vercel/pkg` | 12, 14, 16, 18 | +| `yao-pkg/pkg` | **22, 24** (Node >= 22 required on the build host) | + +`yao-pkg/pkg` drops the older EOL Node.js versions and keeps pace with upstream LTS. If you were packaging `node18-...` binaries with `vercel/pkg`, you'll need to update your `targets` to `node22-...` or `node24-...`. + +### New features beyond `vercel/pkg` + +- **SEA mode** — [stock Node.js packaging](/guide/sea-mode) via the official Single Executable Applications API. No patched Node.js. +- **Enhanced SEA** — full dependency walker + VFS on top of SEA. ESM with top-level await works everywhere. See [SEA vs Standard](/guide/sea-vs-standard). +- **Improved ESM** — most ESM features work transparently now, no manual transform needed. See [ESM support](/guide/esm). +- **Active bug fixes** — regular releases, responsive issue triage, up-to-date base binaries via [`pkg-fetch`](https://github.com/yao-pkg/pkg-fetch). +- **Workers + native addons** work in both standard and SEA modes. + +### Breaking changes from `vercel/pkg@5.x` + +For 99% of projects, **none**. The CLI, `package.json` config schema, and API are source-compatible. + +If you hit a corner case: + +- Dropped Node.js 12 / 14 / 16 / 18 targets — update to `node22` or `node24`. +- The `public` / `public-packages` semantics are unchanged, but `--no-bytecode` now requires explicit `--public-packages` if your deps have non-SPDX licenses. This was already the case in `vercel/pkg`, but the enforcement is stricter. +- A few internal APIs under `lib/` have been refactored. If you were importing deep paths instead of the documented `{ exec }` entry point, you may need to adjust. See [API](/guide/api) for the stable surface. + +## Verify the migration + +```sh +pkg --version # should print a 6.x version +pkg . # or your existing command +``` + +If the build succeeds and the output runs the same as before, you're done. + +## Running into trouble? + +- **CLI hangs on first run.** That's `pkg-fetch` downloading a fresh base binary on the first build for the new fork. Let it finish; subsequent builds hit the cache. +- **Error about missing target.** Check your target against `pkg-fetch` releases — older Node.js versions may no longer be built. +- **Anything else.** Open an issue on [yao-pkg/pkg](https://github.com/yao-pkg/pkg/issues) with a reproduction; maintainers actively triage. + +## See also + +- [Getting started](/guide/getting-started) +- [SEA vs Standard](/guide/sea-vs-standard) — the biggest new feature since `vercel/pkg` +- [pkg-fetch](https://github.com/yao-pkg/pkg-fetch) — where the base binaries come from diff --git a/docs-site/guide/native-addons.md b/docs-site/guide/native-addons.md new file mode 100644 index 00000000..1f017aa0 --- /dev/null +++ b/docs-site/guide/native-addons.md @@ -0,0 +1,61 @@ +--- +title: Native addons +description: Bundle .node files into your packaged binary and control where they are extracted at runtime. +--- + +# Native addons + +Native addons (`.node` files) are supported. When `pkg` encounters a `.node` file in a `require` call, it packages it like an asset. In some cases (like with the `bindings` package) the module path is generated dynamically and `pkg` can't detect it. In that case, add the `.node` file directly to the `assets` field in `package.json`. + +## Why `.node` files get extracted + +Node.js requires a **file on disk** to load a native addon — `dlopen(3)` operates on real paths, not streams. But `pkg` produces one self-contained file, so the `.node` contents live inside the snapshot. At first launch, `pkg` extracts them to a cache directory on disk and then loads them from there. + +Extracted files stay on disk after the process exits and are reused on the next launch, so subsequent startups are fast. + +## Cache location + +Default: `$HOME/.cache/pkg-native/` (resolved via the XDG cache dir on Linux / macOS, `%LOCALAPPDATA%` on Windows). + +Override with `PKG_NATIVE_CACHE_PATH`. Useful in enterprise environments where specific directories are restricted or monitored: + +::: code-group + +```sh [Linux / macOS] +PKG_NATIVE_CACHE_PATH=/opt/myapp/cache ./myapp +``` + +```powershell [Windows] +$env:PKG_NATIVE_CACHE_PATH = 'C:\ProgramData\MyApp\cache' +.\myapp.exe +``` + +::: + +See [Environment variables](/guide/environment#runtime-inside-the-packaged-app) for the full list. + +## Target compatibility + +When a package containing a native module is installed, the native module is compiled against the current system-wide Node.js version. When you compile your project with `pkg`, pay attention to the `--target` option: you should specify the **same Node.js version** as your system-wide Node.js to make the compiled executable compatible with the `.node` files. + +If you cross-compile for a different platform or arch, ensure you install the right prebuilt binary for that target (or rebuild it with `prebuildify` / `node-gyp` for each target). + +## Manual asset inclusion + +If `pkg` can't statically detect a `.node` require (e.g. `bindings` or dynamic paths), add it to `assets`: + +```json +{ + "pkg": { + "assets": ["node_modules/better-sqlite3/build/Release/better_sqlite3.node"] + } +} +``` + +Native bindings are not supported on the `linuxstatic` target — see [Targets → Alpine / musl](/guide/targets#alpine-musl). + +## See also + +- [Environment variables](/guide/environment) +- [Detecting assets](/guide/detecting-assets) +- [Recipes: bundle a SQLite addon](/guide/recipes#bundle-a-native-sqlite-addon) diff --git a/docs-site/guide/options.md b/docs-site/guide/options.md new file mode 100644 index 00000000..9212da6d --- /dev/null +++ b/docs-site/guide/options.md @@ -0,0 +1,49 @@ +--- +title: CLI options (baked) +description: Bake Node.js and V8 command-line options into your packaged executable so users always get the right flags. +--- + +# Baked CLI options + +Node.js applications can be launched with runtime options belonging to Node.js or V8 — `--max-old-space-size`, `--expose-gc`, `--tls-min-v1.0`, and friends. To list the full set, run `node --help` or `node --v8-options`. + +You can **bake** these runtime options into the packaged executable. The app will always run with the options turned on, even when the end user launches it without any flags. Just drop the leading `--` from each option name. + +## Syntax + +Join multiple options with commas, no spaces: + +```sh +pkg app.js --options expose-gc +pkg app.js --options max_old_space_size=4096 +pkg app.js --options max-old-space-size=1024,tls-min-v1.0,expose-gc +``` + +Or set `pkg.options` in `package.json`: + +```json +{ + "pkg": { + "options": "max-old-space-size=2048,expose-gc" + } +} +``` + +## Common use cases + +| Option | Why bake it | +| ----------------------------- | ------------------------------------------------------ | +| `max-old-space-size=N` | Raise the V8 heap ceiling for memory-heavy CLI tools | +| `expose-gc` | Let the app call `global.gc()` for manual collection | +| `tls-min-v1.0` | Accept legacy TLS — interop with old internal services | +| `unhandled-rejections=strict` | Turn unhandled promise rejections into hard crashes | +| `enable-source-maps` | Produce meaningful stack traces in production | + +::: tip Pass-through vs baked +Baked options **always** apply. End users can't turn them off. If you want users to override, don't bake — document the flag in your `--help` and let them pass it. +::: + +## See also + +- [Getting started → CLI reference](/guide/getting-started#cli-reference) +- [Environment variables](/guide/environment) diff --git a/docs-site/guide/output.md b/docs-site/guide/output.md new file mode 100644 index 00000000..08d21f76 --- /dev/null +++ b/docs-site/guide/output.md @@ -0,0 +1,68 @@ +--- +title: Output & debug +description: Control where pkg writes its output and how to surface build-time and runtime diagnostics. +--- + +# Output & debug + +## Output path + +You have two flags: + +| Flag | Use when | +| ------------ | ------------------------------------------------------------------------------ | +| `--output` | You're building a **single** executable and want to choose its exact file name | +| `--out-path` | You're building **multiple** targets and want them all in one directory | + +```sh +# Single target, named output +pkg -t host -o dist/mytool index.js + +# Multi target, into a directory +pkg -t node22-linux-x64,node22-win-x64,node22-macos-arm64 --out-path dist index.js +``` + +Or via `package.json`: + +```json +{ + "pkg": { + "targets": ["node22-linux-x64", "node22-macos-arm64", "node22-win-x64"], + "outputPath": "dist" + } +} +``` + +## Debug output + +Pass `--debug` (or `-d`) to get a verbose log of the packaging process. If you have issues with a particular file (seems not packaged into the executable), the log tells you exactly which files the walker found and why it included or excluded each one. + +```sh +pkg --debug index.js +``` + +For **runtime** diagnostics (what's actually inside the binary after it ships), build with `--debug` and then launch with one of the debug env vars: + +| Variable | What it does | +| -------------------- | ----------------------------------------------------------------- | +| `DEBUG_PKG=1` | Prints the snapshot tree and symlink table at startup | +| `DEBUG_PKG=2` | Same as `=1`, plus mocks `fs` to log every filesystem call | +| `SIZE_LIMIT_PKG=N` | With `DEBUG_PKG`, log files larger than N bytes (default 5 MB) | +| `FOLDER_LIMIT_PKG=N` | With `DEBUG_PKG`, log folders larger than N bytes (default 10 MB) | + +```sh +pkg --debug index.js -o dist/app +DEBUG_PKG=1 ./dist/app +``` + +This is useful to see what's included in your bundle and detect missing or unnecessarily large files. + +::: warning Do not ship debug builds +`--debug` binaries are slower, larger, and print sensitive path info at startup. Use for development only. +::: + +## See also + +- [Debug virtual FS](/guide/advanced-debug-vfs) — deep dive on `DEBUG_PKG` +- [Environment variables](/guide/environment) +- [Troubleshooting](/guide/troubleshooting) diff --git a/docs-site/guide/packaged-app.md b/docs-site/guide/packaged-app.md new file mode 100644 index 00000000..3d1a2e8f --- /dev/null +++ b/docs-site/guide/packaged-app.md @@ -0,0 +1,41 @@ +--- +title: Packaged app usage +description: How a pkg-built executable behaves at runtime — argument forwarding, working directory, and process inspection. +--- + +# Packaged app usage + +A packaged binary behaves almost identically to running your entry file under `node`. A command-line call to the packaged app `./app a b` is equivalent to `node app.js a b`. + +## Forwarded arguments + +Anything after the binary name reaches your code via `process.argv[2..]`: + +```sh +./app --foo bar --debug +# process.argv → ['/abs/path/app', '/snapshot/project/app.js', '--foo', 'bar', '--debug'] +``` + +Note that `process.argv[0]` is the path to the **binary itself** (not `node`), and `process.argv[1]` is the snapshot path of the entry file. See [Snapshot filesystem](/guide/snapshot-fs) for the full list of runtime path differences. + +## Working directory + +`process.cwd()` is the directory the user ran the binary from — just like `node`. This is **not** the `/snapshot/` path where your code lives. Use `process.cwd()` for user-facing file operations and `__dirname` for bundled resources. + +## Detecting the pkg runtime + +Check for `process.pkg` — see [Snapshot filesystem → Detecting that you're packaged](/guide/snapshot-fs#detecting-that-you-re-packaged). + +## Standard streams + +`stdin`, `stdout`, `stderr` behave identically to a regular Node.js process. Piping, redirection, TTY detection, and colours all work. + +## Signals and exit codes + +`process.exit()`, signal handlers (`SIGINT`, `SIGTERM`, …), and unhandled rejection behaviour are unchanged. The packaged binary propagates its final exit code to the shell. + +## See also + +- [Snapshot filesystem](/guide/snapshot-fs) — values of `__filename`, `__dirname`, `process.cwd()`, and friends at runtime +- [Detecting assets](/guide/detecting-assets) +- [Custom Node.js binary](/guide/custom-node) diff --git a/docs-site/guide/recipes.md b/docs-site/guide/recipes.md new file mode 100644 index 00000000..8a9ace73 --- /dev/null +++ b/docs-site/guide/recipes.md @@ -0,0 +1,236 @@ +--- +title: Recipes +description: Copy-paste solutions for common pkg tasks — cross-compile, compression, native addons, SEA mode, CI builds. +--- + +# Recipes + +Copy-paste solutions for tasks you actually do. Each recipe is self-contained — no prose, just the config and the command. + +**Jump to a recipe:** + +- [Build a binary for every mainstream platform](#build-a-binary-for-every-mainstream-platform) +- [Smallest possible binary (Brotli + Standard mode)](#smallest-possible-binary-brotli-standard-mode) +- [Reproducible builds (no bytecode, same hash every time)](#reproducible-builds-no-bytecode-same-hash-every-time) +- [Bundle a native SQLite addon](#bundle-a-native-sqlite-addon) +- [Ship an ESM project with top-level await](#ship-an-esm-project-with-top-level-await) +- [Build all targets in CI](#build-all-targets-in-ci) +- [Programmatic build with the Node.js API](#programmatic-build-with-the-node-js-api) +- [Bake V8 heap limit into the binary](#bake-v8-heap-limit-into-the-binary) +- [Cross-compile to Linux arm64 without QEMU](#cross-compile-to-linux-arm64-without-qemu) +- [Exclude test and doc directories from dependencies](#exclude-test-and-doc-directories-from-dependencies) +- [Use a glob to bundle all SQL migrations](#use-a-glob-to-bundle-all-sql-migrations) +- [Debug a missing asset](#debug-a-missing-asset) +- [Pin the base binary cache path (CI / enterprise)](#pin-the-base-binary-cache-path-ci-enterprise) + +## Build a binary for every mainstream platform + +::: code-group + +```sh [CLI] +pkg -t node22-linux-x64,node22-linux-arm64,node22-macos-x64,node22-macos-arm64,node22-win-x64 --out-path dist . +``` + +```json [package.json] +{ + "pkg": { + "targets": [ + "node22-linux-x64", + "node22-linux-arm64", + "node22-macos-x64", + "node22-macos-arm64", + "node22-win-x64" + ], + "outputPath": "dist" + } +} +``` + +::: + +## Smallest possible binary (Brotli + Standard mode) + +```sh +pkg -C Brotli -t node22-linux-x64 --out-path dist . +``` + +Combine with `--no-dict *` to drop `dictionary/` patches and shave a few more KB: + +```sh +pkg -C Brotli --no-dict '*' -t node22-linux-x64 --out-path dist . +``` + +## Reproducible builds (no bytecode, same hash every time) + +```sh +pkg --no-bytecode --public-packages '*' --public -t node22-linux-x64 -o dist/app . +sha256sum dist/app +``` + +See [Bytecode → Reproducible builds](/guide/bytecode#reproducible-builds). + +## Bundle a native SQLite addon + +```json +{ + "pkg": { + "targets": ["node22-linux-x64", "node22-win-x64"], + "assets": ["node_modules/better-sqlite3/build/Release/better_sqlite3.node"], + "outputPath": "dist" + } +} +``` + +```sh +pkg . +``` + +The `.node` file is extracted to `$HOME/.cache/pkg-native/` on first launch — change the destination with `PKG_NATIVE_CACHE_PATH`. See [Native addons](/guide/native-addons). + +## Ship an ESM project with top-level await + +`package.json`: + +```json +{ + "type": "module", + "bin": "src/main.js", + "pkg": { + "targets": ["node22-linux-x64"], + "sea": true + } +} +``` + +```sh +pkg . +``` + +[Enhanced SEA mode](/guide/sea-mode#enhanced-sea--full-project-with-package-json) handles ESM entrypoints + top-level await natively. No async-IIFE transform. + +## Build all targets in CI + +GitHub Actions: + +```yaml +name: Release binaries +on: + push: + tags: ['v*'] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npx @yao-pkg/pkg . --out-path dist + - uses: actions/upload-artifact@v4 + with: + name: binaries + path: dist/ +``` + +## Programmatic build with the Node.js API + +```js +const { exec } = require('@yao-pkg/pkg'); + +await exec([ + '.', + '--targets', + 'node22-linux-x64,node22-macos-arm64,node22-win-x64', + '--out-path', + 'dist', + '--compress', + 'Brotli', +]); +``` + +See [API](/guide/api) for full usage. + +## Bake V8 heap limit into the binary + +```sh +pkg --options max-old-space-size=4096,expose-gc . +``` + +Users can't override — the flags always apply. See [CLI options](/guide/options). + +## Cross-compile to Linux arm64 without QEMU + +```sh +pkg --no-bytecode --public-packages '*' --public -t node22-linux-arm64 . +``` + +Skips the bytecode step, so there's no need to run an arm64 interpreter on your x64 host. Trade-off: source is plaintext in the binary. See [Targets → Cross-compilation notes](/guide/targets#cross-compilation-notes). + +## Exclude test and doc directories from dependencies + +```json +{ + "pkg": { + "ignore": [ + "**/node_modules/*/test/**", + "**/node_modules/*/tests/**", + "**/node_modules/*/docs/**", + "**/node_modules/*/example/**", + "**/node_modules/*/examples/**" + ] + } +} +``` + +Typically shaves 10–30 % off the final binary. See [Configuration → ignore](/guide/configuration#ignore-files). + +## Use a glob to bundle all SQL migrations + +```json +{ + "pkg": { + "assets": ["migrations/**/*.sql"] + } +} +``` + +In code: + +```js +const path = require('node:path'); +const fs = require('node:fs'); + +const dir = path.join(__dirname, 'migrations'); +const files = fs.readdirSync(dir).sort(); +for (const f of files) { + console.log('running', f); + // ... +} +``` + +Works because `fs.readdirSync` on a `/snapshot/...` path reads from the virtual filesystem. See [Snapshot filesystem](/guide/snapshot-fs). + +## Debug a missing asset + +```sh +pkg --debug -o dist/app . +DEBUG_PKG=1 ./dist/app 2>&1 | grep my-missing-file +``` + +Full workflow in [Debug virtual FS](/guide/advanced-debug-vfs). + +## Pin the base binary cache path (CI / enterprise) + +```sh +export PKG_CACHE_PATH=/var/cache/pkg +pkg . +``` + +Keeps the `pkg-fetch` downloads outside `$HOME`, useful in locked-down build environments. See [Environment variables](/guide/environment). + +## Next steps + +Looking for something that's not here? Open an issue on [yao-pkg/pkg](https://github.com/yao-pkg/pkg/issues) and we'll add the recipe. diff --git a/docs-site/guide/sea-mode.md b/docs-site/guide/sea-mode.md new file mode 100644 index 00000000..ebf526a0 --- /dev/null +++ b/docs-site/guide/sea-mode.md @@ -0,0 +1,107 @@ +--- +title: SEA mode +description: Use Node.js Single Executable Applications to package your project with stock, unmodified Node.js binaries. +--- + +# SEA mode + +`--sea` packages your project using **stock, unmodified Node.js** via the official [Single Executable Applications](https://nodejs.org/api/single-executable-applications.html) API — no custom patches, no `pkg-fetch`. + +Looking for a conceptual overview? Jump to [SEA vs Standard](/guide/sea-vs-standard) for the full comparison, feature matrix, and patch-elimination roadmap. + +## Your first SEA binary + +Create the same hello project as in [Getting started](/guide/getting-started): + +```sh +mkdir hello-sea && cd hello-sea +echo 'console.log("stock-node hello!");' > index.js +``` + +Package it with SEA mode: + +```sh +pkg index.js --sea +``` + +Run it: + +```sh +./index-linux # or index-macos / index-win.exe +# → stock-node hello! +``` + +That's it. No patched Node, no `pkg-fetch` cache touched. + +## Two SEA variants + +`pkg` picks the variant automatically based on the input. + +### Simple SEA — single `.js` file + +For a single pre-bundled `.js` file (Node 22+): + +```sh +pkg --sea index.js +``` + +Node.js SEA supports exactly one entry file. Use this when your project is already bundled (webpack, esbuild, rollup) into one JS file. + +### Enhanced SEA — full project with `package.json` + +Automatically used when the input has a `package.json` and all targets are Node >= 22. Uses the full dependency walker with [`@roberts_lando/vfs`](https://www.npmjs.com/package/@roberts_lando/vfs) for transparent `fs` / `require` / `import` support: + +```sh +pkg . --sea # walks deps, builds VFS +pkg . --sea -t node24-linux # target a specific platform +``` + +::: code-group + +```sh [CLI] +pkg . --sea -t node24-linux-x64 +``` + +```json [package.json] +{ + "bin": "src/cli.js", + "pkg": { + "targets": ["node24-linux-x64", "node24-macos-arm64", "node24-win-x64"], + "outputPath": "dist", + "sea": true + } +} +``` + +```js [Node.js API] +const { exec } = require('@yao-pkg/pkg'); +await exec(['.', '--sea', '--out-path', 'dist']); +``` + +::: + +## What enhanced SEA does + +- **Walks dependencies** like traditional mode, but **skips V8 bytecode and ESM→CJS transforms** — files stay as-is +- **Bundles all files** into a single archive blob with offset-based zero-copy access at runtime +- **Worker threads** — VFS hooks are automatically injected into `/snapshot/...` workers +- **Native addon extraction** — works the same as traditional mode +- **ESM entry points** (`"type": "module"`) work on every supported target (Node >= 22), **including top-level await**. Dispatched via `vm.Script` + `USE_MAIN_CONTEXT_DEFAULT_LOADER`; no Node-version split, no build-time warning. CJS entries go through `Module.runMain()`. +- **Runtime diagnostics** (`DEBUG_PKG` / `SIZE_LIMIT_PKG` / `FOLDER_LIMIT_PKG`) work the same as traditional mode — but only when built with `--debug`. +- **Migration path** to **`node:vfs`** when it lands in Node.js core. + +::: warning seaConfig.useSnapshot +Not supported in enhanced SEA mode (incompatible with the VFS bootstrap). Set it to `false` or omit it. `useCodeCache` is forwarded as-is. +::: + +## Trade-offs vs Standard mode + +Enhanced SEA builds faster and uses **official Node.js APIs**, but stores source in plaintext and skips compression. Workers, native addons, ESM, cross-compile and targets all work the same. + +For the full feature matrix and decision guide, see **[SEA vs Standard](/guide/sea-vs-standard)**. + +## Next steps + +- **[SEA vs Standard](/guide/sea-vs-standard)** — feature matrix + roadmap +- **[Recipes](/guide/recipes)** — copy-paste SEA build recipes +- **[Architecture: Enhanced SEA](/architecture#enhanced-sea-mode)** — deep dive on VFS + bootstrap internals diff --git a/docs-site/guide/sea-vs-standard.md b/docs-site/guide/sea-vs-standard.md new file mode 100644 index 00000000..9ff39b25 --- /dev/null +++ b/docs-site/guide/sea-vs-standard.md @@ -0,0 +1,60 @@ +--- +title: SEA vs Standard +description: The full comparison between Standard mode (patched Node.js, bytecode, compression) and Enhanced SEA mode (stock Node.js, faster builds, zero patches). +--- + +# SEA vs Standard + +`pkg` supports two packaging modes. The single biggest difference isn't a feature toggle — it's **what Node.js binary they run on**. + +::: tip The core difference +**Standard mode** runs on a **custom-patched Node.js** binary distributed by [`pkg-fetch`](https://github.com/yao-pkg/pkg-fetch). Every Node.js release requires ~600–850 lines of patches across ~25 files to be rebased, rebuilt, and re-released. + +**SEA mode** runs on **stock, unmodified Node.js**. No patches. No waiting for `pkg-fetch` to catch up. Security fixes and new Node versions are available the moment Node.js itself releases them. +::: + +Everything else — compression, bytecode, worker threads, native addons — flows from that one decision. + +## Why stock binaries matter + +- **Security posture** — stock Node.js is auditable, signed by the Node.js project, and tracked by every vulnerability scanner. A patched fork isn't. +- **Supply chain** — fewer custom binaries in the dependency graph, fewer things to trust. +- **Release cadence** — the day Node.js 24.x ships a security fix, SEA-built apps can rebuild against it. Standard mode has to wait for `pkg-fetch` to rebase, rebuild, and publish. +- **Maintenance burden** — the ~600–850 lines of patches per Node release are the single biggest maintenance cost in this project. SEA eliminates that cost. +- **Future-proofing** — SEA is an **official Node.js API**. It will keep working as Node.js evolves. Patched builds are always one compiler change away from breaking. + +## Feature matrix + +| Feature | **Standard** | **Enhanced SEA** | +| ------------------------------- | ------------------------------ | ------------------------ | +| **Node.js binary** | Custom patched (`pkg-fetch`) | **Stock Node.js** ✨ | +| Source protection (V8 bytecode) | ✅ | ❌ plaintext | +| Compression (Brotli / GZip) | ✅ | ❌ | +| Build speed | Slower | **Faster** | +| Cross-compile | ✅ | ✅ | +| Worker threads | ✅ | ✅ | +| Native addons | ✅ | ✅ | +| ESM + top-level await | Partial | ✅ every target | +| Maintenance burden | High — patch each Node release | **Low — stock binaries** | +| Security updates | Wait for `pkg-fetch` rebuild | **Immediate** | +| Future path | Tied to `pkg-fetch` | Migrates to `node:vfs` | + +## When to pick which + +Pick **Standard** when: + +- You need **source protection** — your IP must not ship as plaintext JavaScript. +- You need **compression** — binary size matters more than build speed. + +Pick **SEA** when: + +- You don't need bytecode protection (most CLI tools, internal services, open-source apps). +- You want **faster builds**. +- You want to **stay on the latest Node.js** without waiting for `pkg-fetch`. +- You care about **supply-chain simplicity** — stock, signed, auditable binaries. + +For new projects where bytecode IP protection isn't a hard requirement, **SEA is the recommended default going forward**. + +## Roadmap + +Long-term goal: eliminate patched Node.js binaries entirely and ship `pkg` on stock Node via SEA + `node:vfs`. Progress, patch categorisation, and upstream strategy are tracked in **[#231](https://github.com/yao-pkg/pkg/issues/231)**. diff --git a/docs-site/guide/snapshot-fs.md b/docs-site/guide/snapshot-fs.md new file mode 100644 index 00000000..bbeb14ed --- /dev/null +++ b/docs-site/guide/snapshot-fs.md @@ -0,0 +1,66 @@ +--- +title: Snapshot filesystem +description: How paths work inside a packaged pkg binary — /snapshot prefix, __dirname, __filename, process.cwd, and friends. +--- + +# Snapshot filesystem + +During the packaging process `pkg` collects project files and places them into the executable. This bundle is called a **snapshot**. At run time the packaged application has access to a snapshot filesystem where all those files reside. + +Packaged files have a `/snapshot/` prefix in their paths (or `C:\snapshot\` on Windows). If you used `pkg /path/app.js`, then at runtime `__filename` is likely `/snapshot/path/app.js`, and `__dirname` is `/snapshot/path`. + +## Path values at runtime + +Comparison of path-related values when running your code under plain `node` versus inside a packaged binary: + +| value | with `node` | packaged | comments | +| ------------------------------- | ----------------- | -------------------------- | -------------------------------------------------------- | +| `__filename` | `/project/app.js` | `/snapshot/project/app.js` | | +| `__dirname` | `/project` | `/snapshot/project` | | +| `process.cwd()` | `/project` | `/deploy` | suppose the app is called `app-x64` and run in `/deploy` | +| `process.execPath` | `/usr/bin/nodejs` | `/deploy/app-x64` | | +| `process.argv[0]` | `/usr/bin/nodejs` | `/deploy/app-x64` | | +| `process.argv[1]` | `/project/app.js` | `/snapshot/project/app.js` | | +| `process.pkg.entrypoint` | `undefined` | `/snapshot/project/app.js` | | +| `process.pkg.defaultEntrypoint` | `undefined` | `/snapshot/project/app.js` | | +| `require.main.filename` | `/project/app.js` | `/snapshot/project/app.js` | | + +## Rules of thumb + +- To use a file collected **at packaging time** (`require` a JavaScript file or serve an asset), take `__filename`, `__dirname`, `process.pkg.defaultEntrypoint`, or `require.main.filename` as a base for your path calculations. +- For JavaScript files you can just `require` or `require.resolve` because they use the current `__dirname` by default. +- For assets, use `path.join(__dirname, '../path/to/asset')` — see [Detecting assets](/guide/detecting-assets) for how `pkg` picks those up statically. +- To access the **real filesystem at run time** — pick up a user's external JS plugin, JSON config, or list a user's directory — use `process.cwd()` or `path.dirname(process.execPath)`. + +## Quick example + +```js +const fs = require('fs'); +const path = require('path'); + +// bundled asset (resolved inside /snapshot) +const template = fs.readFileSync( + path.join(__dirname, 'templates/greeting.html'), + 'utf8', +); + +// real config file next to the binary at runtime +const configPath = path.join(path.dirname(process.execPath), 'config.json'); +const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); +``` + +## Detecting that you're packaged + +Check for `process.pkg`: + +```js +if (process.pkg) { + // running inside a pkg binary +} +``` + +## See also + +- [Packaged app usage](/guide/packaged-app) +- [Detecting assets](/guide/detecting-assets) +- [Debug virtual FS](/guide/advanced-debug-vfs) diff --git a/docs-site/guide/targets.md b/docs-site/guide/targets.md new file mode 100644 index 00000000..57914182 --- /dev/null +++ b/docs-site/guide/targets.md @@ -0,0 +1,85 @@ +--- +title: Targets +description: Cross-compile Node.js binaries for Linux, macOS, and Windows on x64 and arm64 from any host. +--- + +# Targets + +`pkg` can generate executables for several target machines at a time. Pass a comma-separated list via `--targets`, or set `pkg.targets` in `package.json`. + +## Target triple + +A canonical target has three parts separated by dashes: `<nodeRange>-<platform>-<arch>`. + +| Part | Values | +| ------------- | ------------------------------------------------------------- | +| **nodeRange** | `node22`, `node24`, `latest` | +| **platform** | `alpine`, `linux`, `linuxstatic`, `win`, `macos`, (`freebsd`) | +| **arch** | `x64`, `arm64`, (`armv6`, `armv7`) | + +Parenthesised values are unsupported out of the box — you may try to compile them yourself. + +::: tip host alias +The alias `host` is shorthand for "current platform + Node.js version + arch". Useful in scripts and CI. +::: + +If your target is available in the assets of the latest [pkg-fetch release](https://github.com/yao-pkg/pkg-fetch/releases), `pkg` downloads the pre-compiled Node.js binary from that project. Otherwise, or if you specify `--build`, it builds the binary from source (this takes a **very** long time). + +Pre-compiled binaries for some unsupported architectures and instructions for using them are available in the [pkg-binaries](https://github.com/yao-pkg/pkg-binaries) project. + +You may omit any element (for example `node22`). Omitted elements default to the current platform or the system-wide Node.js version and arch. By default targets are `linux,macos,win` for the current Node.js version and arch. + +## Examples + +::: code-group + +```sh [Single target] +pkg -t node22-linux-arm64 index.js +``` + +```sh [Multi-target] +pkg -t node22-linux-x64,node22-macos-arm64,node22-win-x64 index.js +``` + +```sh [Host only] +pkg -t host index.js +``` + +```json [package.json] +{ + "pkg": { + "targets": [ + "node22-linux-x64", + "node22-linux-arm64", + "node22-macos-x64", + "node22-macos-arm64", + "node22-win-x64" + ] + } +} +``` + +::: + +## Cross-compilation notes + +By default `pkg` has to run the executable of the **target** arch to generate bytecode: + +- **Linux** — configure binfmt with [QEMU](https://wiki.debian.org/QemuUserEmulation) +- **macOS** — you can build `x64` on `arm64` with Rosetta 2, but not the opposite +- **Windows** — you can build `x64` on `arm64` with x64 emulation, but not the opposite +- Or disable bytecode generation entirely with `--no-bytecode --public-packages "*" --public` + +## macOS arm64 + +`macos-arm64` is experimental. Be careful about the [mandatory code signing requirement](https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11_0_1-universal-apps-release-notes). The final executable has to be signed (an ad-hoc signature is sufficient) with the `codesign` utility on macOS (or the `ldid` utility on Linux). Otherwise the executable will be killed by the kernel and the end user has no way to permit it to run. `pkg` tries to ad-hoc sign the final executable. If necessary, replace this signature with your own trusted Apple Developer ID. + +To build executables for all supported architectures and platforms from a single host, run `pkg` on a Linux host with binfmt (QEMU emulation) configured and `ldid` installed. + +## Alpine / musl + +The `alpine` platform targets glibc-less Alpine Linux / BusyBox environments. Use it for Alpine Docker images and similar musl-based distros. If you need a fully static binary that runs on any Linux kernel, prefer `linuxstatic`. + +::: warning linuxstatic + native addons +Fully static Node binaries cannot load native bindings. If your project uses `.node` addons, `linuxstatic` will not work — use `linux` instead. See [Native addons](/guide/native-addons). +::: diff --git a/docs-site/guide/troubleshooting.md b/docs-site/guide/troubleshooting.md new file mode 100644 index 00000000..e3bc148a --- /dev/null +++ b/docs-site/guide/troubleshooting.md @@ -0,0 +1,124 @@ +--- +title: Troubleshooting +description: Fixes and workarounds for common pkg errors — ESM, child_process, inspector, NODE_OPTIONS conflicts. +--- + +# Troubleshooting + +::: tip Check this first +Most pkg issues come from one of three things: + +1. **Assets not detected** — files you expect in the binary aren't there. Build with `--debug` and run with `DEBUG_PKG=1` to list the snapshot tree. See [Debug virtual FS](/guide/advanced-debug-vfs). +2. **`NODE_OPTIONS`** leaking in from an IDE or shell. Some options conflict with pkg — see [NODE_OPTIONS conflicts](#error-require-internalmodulestat-is-not-a-function). +3. **Stale cached base binary** — blow away `~/.pkg-cache` and retry. + ::: + +## Error: `ERR_REQUIRE_ESM` + +Full message: `Error [ERR_REQUIRE_ESM]: require() of ES Module`. + +Tracked by [#16](https://github.com/yao-pkg/pkg/issues/16#issuecomment-1945486658). In most cases, adding `--options experimental-require-module` to the `pkg` command line solves it: + +```sh +pkg app.js --options experimental-require-module +``` + +::: tip Node.js >= 22.12.0 +This option is **not needed** from Node.js v22.12.0 onwards — `experimental-require-module` is the default. Drop the flag if you've upgraded your pkg target. +::: + +## Error: Cannot find module XXX (when using `child_process`) + +When you use `child_process` methods inside a packaged binary, `pkg` by default invokes the child using the **packaged Node.js runtime**, not the system `node`. If you're trying to `spawn` some external binary that happens to pass through `node`, or if the child accidentally re-enters the packaged entry file, you'll hit a `Cannot find module` error. + +**Fix:** explicitly unset `PKG_EXECPATH` in the child's environment: + +```js +const { spawn } = require('child_process'); + +const child = spawn(process.execPath, [process.argv[1]], { + env: { + ...process.env, + PKG_EXECPATH: '', // tell child: you are NOT inside a pkg binary + }, +}); +``` + +This tells the child process to behave like a plain Node.js invocation instead of a pkg-wrapped one. More context in [PR #90](https://github.com/yao-pkg/pkg/pull/90). + +## Error: Cannot execute binary from snapshot + +Binaries inside the `/snapshot/` virtual filesystem can't be `exec()`'d directly — the OS needs a real file on a real filesystem to spawn it. Extract it first: + +```js +const cp = require('child_process'); +const fs = require('fs'); +const { pipeline } = require('stream/promises'); + +let ffmpeg = require('@ffmpeg-installer/ffmpeg').path; + +async function loadPlugin() { + if (process.pkg) { + // copy ffmpeg to the current directory + const file = fs.createWriteStream('ffmpeg'); + await pipeline(fs.createReadStream(ffmpeg), file); + + fs.chmodSync('ffmpeg', 0o755); + console.log('ffmpeg copied to the current directory'); + ffmpeg = './ffmpeg'; + } + + cp.execSync(ffmpeg); +} + +loadPlugin(); +``` + +For `.node` native addons, `pkg` does this extraction automatically — see [Native addons](/guide/native-addons). For **arbitrary** binaries (ffmpeg, ripgrep, protoc, …) you have to do it yourself. + +## Error: `ENOENT: no such file or directory, uv_chdir` + +Usually means the directory the app was launched from (`process.cwd()`) was deleted while the app was still running. Check your code for anything that removes `process.cwd()` — temp directories in `/tmp` are common culprits. Not a pkg bug; reproduces under plain `node` too. + +## Error: `ERR_INSPECTOR_NOT_AVAILABLE` + +Caused by `NODE_OPTIONS` forcing `node` into debug mode. Debugging options are **intentionally disallowed** inside packaged binaries — pkg executables are usually used in production environments where exposing an inspector port is a security risk. + +**Workarounds:** + +1. Unset `NODE_OPTIONS` before launching: + ```sh + NODE_OPTIONS='' ./app + ``` +2. Or build a debuggable Node.js yourself and use it as a custom base binary — see the [issue #93 workaround](https://github.com/yao-pkg/pkg/issues/93#issuecomment-301210543) and [Custom Node.js binary](/guide/custom-node). + +## Error: `require(...).internalModuleStat is not a function` + +Same root cause as the inspector error — `NODE_OPTIONS` (typically set automatically by IDEs like VS Code) is injecting bootstrap options that conflict with pkg's prelude. + +On Unix (Linux / macOS): + +```bash +printenv | grep NODE +``` + +On Windows PowerShell: + +```powershell +Get-ChildItem Env: | Where-Object Name -match '^NODE' +``` + +**Fix:** clear `NODE_OPTIONS` and any other `NODE_*` variables in the terminal where you run the binary: + +```sh +unset NODE_OPTIONS NODE_DEBUG NODE_EXTRA_CA_CERTS NODE_NO_WARNINGS +./app +``` + +If your shell or IDE re-adds them automatically, add an exception rule — e.g. in VS Code add `"terminal.integrated.env.linux": { "NODE_OPTIONS": null }` to disable the auto-injection just for this project. + +## Still stuck? + +- Search existing issues: [github.com/yao-pkg/pkg/issues](https://github.com/yao-pkg/pkg/issues) +- Open a new one with the output of `pkg --debug` and `DEBUG_PKG=1 ./your-binary` +- Check the [recipes](/guide/recipes) for an example that matches your setup diff --git a/docs-site/index.md b/docs-site/index.md new file mode 100644 index 00000000..c6929d38 --- /dev/null +++ b/docs-site/index.md @@ -0,0 +1,111 @@ +--- +layout: home +title: pkg — Node.js to single executable +description: Ship your Node.js project as one self-contained binary. No runtime install. No npm. Cross-compiled for Linux, macOS, and Windows. + +hero: + name: pkg + text: Node.js to single executable + tagline: Ship your Node.js project as one self-contained binary. No runtime install. No npm. Just run. + image: + src: /logo.png + alt: pkg + actions: + - theme: brand + text: Get started + link: /guide/getting-started + - theme: alt + text: SEA vs Standard + link: /guide/sea-vs-standard + - theme: alt + text: View on GitHub + link: https://github.com/yao-pkg/pkg + +features: + - icon: 📦 + title: Single file deploy + details: One binary per target. No Node.js install, no node_modules, no dependency churn on the deployment host. + - icon: 🌍 + title: Cross-compile + details: Build Linux, macOS, and Windows binaries from any host. x64 and arm64 supported out of the box. + - icon: 🔒 + title: Source protection + details: V8 bytecode compilation keeps your source out of the final binary. Optional Brotli and GZip compression shrinks it further. + - icon: ⚡ + title: Native addons + details: .node files are detected, extracted, and loaded transparently at runtime. Works with the bindings package. + - icon: 🧩 + title: Virtual filesystem + details: Your project files live inside the binary under /snapshot/. require, fs, and path all Just Work. + - icon: 🚀 + title: SEA mode + details: Opt into Node.js Single Executable Applications for stock-binary packaging. No patched Node.js, faster builds. +--- + +<div class="fork-banner"> +<strong>Looking for <code>vercel/pkg</code>?</strong> This is <a href="https://github.com/yao-pkg/pkg"><code>yao-pkg/pkg</code></a> — the actively maintained fork. The original <code>vercel/pkg</code> is archived. <code>@yao-pkg/pkg</code> is a drop-in replacement — rename the dep and keep shipping. See the <a href="/pkg/guide/migration">migration guide</a>. +</div> + +<div class="landing-badges"> + +[![npm version](https://img.shields.io/npm/v/@yao-pkg/pkg?color=e89b2c&label=npm)](https://www.npmjs.com/package/@yao-pkg/pkg) [![npm downloads](https://img.shields.io/npm/dm/@yao-pkg/pkg?color=e89b2c&label=downloads)](https://www.npmjs.com/package/@yao-pkg/pkg) [![GitHub stars](https://img.shields.io/github/stars/yao-pkg/pkg?color=e89b2c&label=stars)](https://github.com/yao-pkg/pkg/stargazers) [![CI](https://github.com/yao-pkg/pkg/actions/workflows/ci.yml/badge.svg)](https://github.com/yao-pkg/pkg/actions/workflows/ci.yml) [![license](https://img.shields.io/npm/l/@yao-pkg/pkg?color=e89b2c)](https://github.com/yao-pkg/pkg/blob/main/LICENSE) + +</div> + +<figure class="landing-demo"> + <img src="/hero.gif" alt="Terminal recording: pkg index.js produces linux, macos, and windows binaries in one second" /> + <figcaption>One command. Three binaries. Runs on machines without Node.js installed.</figcaption> +</figure> + +<div class="landing-body"> + +## Quick install + +```sh +npm install -g @yao-pkg/pkg +``` + +Requires **Node.js >= 22** on the build host. + +## Your first binary + +::: code-group + +```sh [CLI, entry file] +pkg index.js +``` + +```sh [CLI, package.json] +pkg . +``` + +```js [Node.js API] +const { exec } = require('@yao-pkg/pkg'); +await exec(['index.js', '--target', 'host', '--output', 'app']); +``` + +::: + +`pkg` reads `package.json`, follows the `bin` entry, walks your dependencies, and produces executables for Linux, macOS, and Windows. + +Want to target a specific platform? + +```sh +pkg -t node22-linux-arm64 index.js +``` + +## Standard or SEA? + +Two build modes: **Standard** (`pkg .`) gives you bytecode protection and compression; **Enhanced SEA** (`pkg . --sea`) runs on stock Node.js with no patches. Pick via [SEA vs Standard](/guide/sea-vs-standard). + +## Why pkg? + +- **Commercial apps** — ship without sources +- **CLI tools** — distribute one binary, no npm install on user machines +- **Demos & trials** — no runtime, no dependencies to break +- **Self-extracting installers** — one file, portable +- **Edge & containers** — smaller, faster deploys + +See the [full use cases](/guide/) → + +</div> diff --git a/docs-site/package-lock.json b/docs-site/package-lock.json new file mode 100644 index 00000000..264fe112 --- /dev/null +++ b/docs-site/package-lock.json @@ -0,0 +1,3935 @@ +{ + "name": "@yao-pkg/pkg-docs", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@yao-pkg/pkg-docs", + "version": "0.0.0", + "devDependencies": { + "mermaid": "^11.14.0", + "vitepress": "^1.5.0", + "vitepress-plugin-mermaid": "^2.0.17" + } + }, + "node_modules/@algolia/abtesting": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.16.1.tgz", + "integrity": "sha512-Xxk4l00pYI+jE0PNw8y0MvsQWh5278WRtZQav8/BMMi3HKi2xmeuqe11WJ3y8/6nuBHdv39w76OpJb09TMfAVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.50.1.tgz", + "integrity": "sha512-4peZlPXMwTOey9q1rQKMdCnwZb/E95/1e+7KujXpLLSh0FawJzg//U2NM+r4AiJy4+naT2MTBhj0K30yshnVTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.50.1.tgz", + "integrity": "sha512-i+aWHHG8NZvGFHtPeMZkxL2Loc6Fm7iaRo15lYSMx8gFL+at9vgdWxhka7mD1fqxkrxXsQstUBCIsSY8FvkEOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.50.1.tgz", + "integrity": "sha512-Hw52Fwapyk/7hMSV/fI4+s3H9MGZEUcRh4VphyXLAk2oLYdndVUkc6KBi0zwHSzwPAr+ZBwFPe2x6naUt9mZGw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.50.1.tgz", + "integrity": "sha512-Bn/wtwhJ7p1OD/6pY+Zzn+zlu2N/SJnH46md/PAbvqIzmjVuwjNwD4y0vV5Ov8naeukXdd7UU9v550+v8+mtlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.50.1.tgz", + "integrity": "sha512-0V4Tu0RWR8YxkgI9EPVOZHGE4K5pEIhkLNN0CTkP/rnPsqaaSQpNMYW3/mGWdiKOWbX0iVmwLB9QESk3H0jS5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.50.1.tgz", + "integrity": "sha512-jofcWNYMXJDDr87Z2eivlWY6o71Zn7F7aOvQCXSDAo9QTlyf7BhXEsZymLUvF0O1yU9Q9wvrjAWn8uVHYnAvgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.50.1.tgz", + "integrity": "sha512-OteRb8WubcmEvU0YlMJwCXs3Q6xrdkb0v50/qZBJP1TF0CvujFZQM++9BjEkTER/Jr9wbPHvjSFKnbMta0b4dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.50.1.tgz", + "integrity": "sha512-0GmfSgDQK6oiIVXnJvGxtNFOfosBspRTR7csCOYCTL1P8QtxX2vDCIKwTM7xdSAEbJaZ43QlWg25q0Qdsndz8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.50.1.tgz", + "integrity": "sha512-ySuigKEe4YjYV3si8NVk9BHQpFj/1B+ON7DhhvTvbrZJseHQQloxzq0yHwKmznSdlO6C956fx4pcfOKkZClsyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.50.1.tgz", + "integrity": "sha512-Cp8T/B0gVmjFlzzp6eP47hwKh5FGyeqQp1N48/ANDdvdiQkPqLyFHQVDwLBH0LddfIPQE+yqmZIgmKc82haF4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.50.1.tgz", + "integrity": "sha512-XKdGGLikfrlK66ZSXh/vWcXZZ8Vg3byDFbJD8pwEvN1FoBRGxhxya476IY2ohoTymLa4qB5LBRlIa+2TLHx3Uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.50.1.tgz", + "integrity": "sha512-mBAU6WyVsDwhHyGM+nodt1/oebHxgvuLlOAoMGbj/1i6LygDHZWDgL1t5JEs37x9Aywv7ZGhqbM1GsfZ54sU6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.50.1.tgz", + "integrity": "sha512-qmo1LXrNKLHvJE6mdQbLnsZAoZvj7VyF2ft4xmbSGWI2WWm87fx/CjUX4kEExt4y0a6T6nEts6ofpUfH5TEE1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.2.tgz", + "integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-12.0.0.tgz", + "integrity": "sha512-fSL4KXjTl7cDgf0B5Rip9Q05BOrYvkJV/RrBTE/bKDN096E4hN/ySpcBK5B24T76dlQ2i32Zc3PAE27jFnFrKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "12.0.0", + "@chevrotain/types": "12.0.0" + } + }, + "node_modules/@chevrotain/gast": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-12.0.0.tgz", + "integrity": "sha512-1ne/m3XsIT8aEdrvT33so0GUC+wkctpUPK6zU9IlOyJLUbR0rg4G7ZiApiJbggpgPir9ERy3FRjT6T7lpgetnQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "12.0.0" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-12.0.0.tgz", + "integrity": "sha512-p+EW9MaJwgaHguhoqwOtx/FwuGr+DnNn857sXWOi/mClXIkPGl3rn7hGNWvo31HA3vyeQxjqe+H36yZJwYU8cA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-12.0.0.tgz", + "integrity": "sha512-S+04vjFQKeuYw0/eW3U52LkAHQsB1ASxsPGsLPUyQgrZ2iNNibQrsidruDzjEX2JYfespXMG0eZmXlhA6z7nWA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-12.0.0.tgz", + "integrity": "sha512-lB59uJoaGIfOOL9knQqQRfhl9g7x8/wqFkp13zTdkRu1huG9kg6IJs1O8hqj9rs6h7orGxHJUKb+mX3rPbWGhA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@docsearch/css": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz", + "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz", + "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/react": "3.8.2", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz", + "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.2", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.78", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.78.tgz", + "integrity": "sha512-I3lkNp0Qu7q2iZWkdcf/I2hqGhzK6qxdILh9T7XqowQrnpmG/BayDsiCf6PktDoWlW0U971xA5g+panm+NFrfQ==", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "mlly": "^1.8.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@mermaid-js/mermaid-mindmap": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/mermaid-mindmap/-/mermaid-mindmap-9.3.0.tgz", + "integrity": "sha512-IhtYSVBBRYviH1Ehu8gk69pMDF8DSRqXBRDMWrEfHoaMruHeaP2DXA3PBnuwsMaCdPQhlUUcy/7DBLAEIXvCAw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@braintree/sanitize-url": "^6.0.0", + "cytoscape": "^3.23.0", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.1.0", + "d3": "^7.0.0", + "khroma": "^2.0.0", + "non-layered-tidy-tree-layout": "^2.0.2" + } + }, + "node_modules/@mermaid-js/mermaid-mindmap/node_modules/@braintree/sanitize-url": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", + "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@mermaid-js/parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.0.tgz", + "integrity": "sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "langium": "^4.0.0" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz", + "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.4" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz", + "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^3.1.0" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz", + "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz", + "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz", + "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz", + "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz", + "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@upsetjs/venn.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", + "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz", + "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@vue/shared": "3.5.32", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz", + "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", + "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@vue/compiler-core": "3.5.32", + "@vue/compiler-dom": "3.5.32", + "@vue/compiler-ssr": "3.5.32", + "@vue/shared": "3.5.32", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.8", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz", + "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.32.tgz", + "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.32.tgz", + "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz", + "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.32", + "@vue/runtime-core": "3.5.32", + "@vue/shared": "3.5.32", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.32.tgz", + "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.32", + "@vue/shared": "3.5.32" + }, + "peerDependencies": { + "vue": "3.5.32" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz", + "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz", + "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/integrations": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz", + "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vueuse/core": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz", + "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz", + "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/algoliasearch": { + "version": "5.50.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.50.1.tgz", + "integrity": "sha512-/bwdue1/8LWELn/DBalGRfuLsXBLXULJo/yOeavJtDu8rBwxIzC6/Rz9Jg19S21VkJvRuZO1k8CZXBMS73mYbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.16.1", + "@algolia/client-abtesting": "5.50.1", + "@algolia/client-analytics": "5.50.1", + "@algolia/client-common": "5.50.1", + "@algolia/client-insights": "5.50.1", + "@algolia/client-personalization": "5.50.1", + "@algolia/client-query-suggestions": "5.50.1", + "@algolia/client-search": "5.50.1", + "@algolia/ingestion": "1.50.1", + "@algolia/monitoring": "1.50.1", + "@algolia/recommend": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chevrotain": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-12.0.0.tgz", + "integrity": "sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/cst-dts-gen": "12.0.0", + "@chevrotain/gast": "12.0.0", + "@chevrotain/regexp-to-ast": "12.0.0", + "@chevrotain/types": "12.0.0", + "@chevrotain/utils": "12.0.0" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.4.1.tgz", + "integrity": "sha512-PvVJm3oGqrveUVW2Vt/eZGeiAIsJszYweUcYwcskg9e+IubNYKKD+rHHem7A6XVO22eDAL+inxNIGAzZ/VIWlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^12.0.0" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "dev": true, + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cytoscape": { + "version": "3.33.2", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.2.tgz", + "integrity": "sha512-sj4HXd3DokGhzZAdjDejGvTPLqlt84vNFN8m7bGsOzDY5DyVcxIb2ejIXat2Iy7HxWhdT/N1oKyheJ5YdpsGuw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "dev": true, + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dev": true, + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "dev": true, + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dev": true, + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.14.tgz", + "integrity": "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/dayjs": { + "version": "1.11.20", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", + "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delaunator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", + "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dompurify": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.0.tgz", + "integrity": "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg==", + "dev": true, + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/focus-trap": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", + "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tabbable": "^6.4.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "dev": true, + "license": "MIT" + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/katex": { + "version": "0.16.45", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.45.tgz", + "integrity": "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA==", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==", + "dev": true + }, + "node_modules/langium": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.2.tgz", + "integrity": "sha512-JUshTRAfHI4/MF9dH2WupvjSXyn8JBuUEWazB8ZVJUtXutT0doDlAv1XKbZ1Pb5sMexa8FF4CFBc0iiul7gbUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@chevrotain/regexp-to-ast": "~12.0.0", + "chevrotain": "~12.0.0", + "chevrotain-allstar": "~0.4.1", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.1.0" + }, + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mermaid": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.14.0.tgz", + "integrity": "sha512-GSGloRsBs+JINmmhl0JDwjpuezCsHB4WGI4NASHxL3fHo3o/BRXTxhDLKnln8/Q0lRFRyDdEjmk1/d5Sn1Xz8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.2", + "@mermaid-js/parser": "^1.1.0", + "@types/d3": "^7.4.3", + "@upsetjs/venn.js": "^2.0.0", + "cytoscape": "^3.33.1", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.14", + "dayjs": "^1.11.19", + "dompurify": "^3.3.1", + "katex": "^0.16.25", + "khroma": "^2.1.0", + "lodash-es": "^4.17.23", + "marked": "^16.3.0", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "dev": true, + "license": "MIT" + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/non-layered-tidy-tree-layout": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", + "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/oniguruma-to-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", + "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "dev": true, + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, + "node_modules/postcss": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.29.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", + "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "dev": true, + "license": "Unlicense" + }, + "node_modules/rollup": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/shiki": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz", + "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/langs": "2.5.0", + "@shikijs/themes": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz", + "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ufo": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz", + "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/css": "3.8.2", + "@docsearch/js": "3.8.2", + "@iconify-json/simple-icons": "^1.2.21", + "@shikijs/core": "^2.1.0", + "@shikijs/transformers": "^2.1.0", + "@shikijs/types": "^2.1.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^5.2.1", + "@vue/devtools-api": "^7.7.0", + "@vue/shared": "^3.5.13", + "@vueuse/core": "^12.4.0", + "@vueuse/integrations": "^12.4.0", + "focus-trap": "^7.6.4", + "mark.js": "8.11.1", + "minisearch": "^7.1.1", + "shiki": "^2.1.0", + "vite": "^5.4.14", + "vue": "^3.5.13" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vitepress-plugin-mermaid": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/vitepress-plugin-mermaid/-/vitepress-plugin-mermaid-2.0.17.tgz", + "integrity": "sha512-IUzYpwf61GC6k0XzfmAmNrLvMi9TRrVRMsUyCA8KNXhg/mQ1VqWnO0/tBVPiX5UoKF1mDUwqn5QV4qAJl6JnUg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "@mermaid-js/mermaid-mindmap": "^9.3.0" + }, + "peerDependencies": { + "mermaid": "10 || 11", + "vitepress": "^1.0.0 || ^1.0.0-alpha" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dev": true, + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", + "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.32", + "@vue/compiler-sfc": "3.5.32", + "@vue/runtime-dom": "3.5.32", + "@vue/server-renderer": "3.5.32", + "@vue/shared": "3.5.32" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs-site/package.json b/docs-site/package.json new file mode 100644 index 00000000..9421748a --- /dev/null +++ b/docs-site/package.json @@ -0,0 +1,17 @@ +{ + "name": "@yao-pkg/pkg-docs", + "version": "0.0.0", + "private": true, + "type": "module", + "description": "Documentation site for @yao-pkg/pkg", + "scripts": { + "docs:dev": "vitepress dev", + "docs:build": "vitepress build", + "docs:preview": "vitepress preview" + }, + "devDependencies": { + "mermaid": "^11.14.0", + "vitepress": "^1.5.0", + "vitepress-plugin-mermaid": "^2.0.17" + } +} diff --git a/docs-site/public/hero.gif b/docs-site/public/hero.gif new file mode 100644 index 00000000..4d9d6b5b Binary files /dev/null and b/docs-site/public/hero.gif differ diff --git a/docs-site/public/logo.png b/docs-site/public/logo.png new file mode 100644 index 00000000..a6c82cea Binary files /dev/null and b/docs-site/public/logo.png differ diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 2a502bbd..493c56e6 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -2,6 +2,32 @@ This document describes how `pkg` packages Node.js applications into standalone executables, covering both the traditional binary-patching approach and the new SEA (Single Executable Application) mode with VFS support. +## Visual overview + +Both modes start from the same project and end with a single executable, but they take very different paths through the build pipeline: + +```mermaid +flowchart TD + P["package.json + src/"] + + P --> T1["Traditional: Walker"] + P --> S1["Enhanced SEA: Walker seaMode"] + + T1 --> T2["Bytecode fabricator"] + T2 --> T3["Packer + stripes"] + T3 --> T4["Payload injection"] + T4 --> TB["Patched Node.js binary<br/>with custom VFS"] + + S1 --> S2["Asset blob + manifest"] + S2 --> S3["node --experimental-sea-config"] + S3 --> S4["postject inject"] + S4 --> SB["Stock Node.js binary<br/>with NODE_SEA_BLOB"] + + style P stroke:#e89b2c,stroke-width:2px + style TB stroke:#ec7a96,stroke-width:2px + style SB stroke:#66bb6a,stroke-width:2px +``` + ## Table of Contents - [Overview](#overview) @@ -48,6 +74,30 @@ pkg single-file.js --sea # Simple SEA mode (any single .js file) ### Build Pipeline +```mermaid +flowchart TD + CLI[CLI<br/>lib/index.ts] + FETCH[pkg-fetch<br/>download base binary] + WALK[Walker<br/>lib/walker.ts] + PARSE[Babel parse entry<br/>resolve requires/imports] + ESM[ESM → CJS transform] + BYTE[Fabricator<br/>V8 bytecode compile] + COLLECT[Collect stores:<br/>BLOB / CONTENT / LINKS / STAT] + REFINE[Refiner<br/>path compression] + PACK[Packer<br/>serialize stripes + wrap bootstrap] + PROD[Producer<br/>inject into base binary] + OUT[Final executable] + + CLI --> FETCH --> WALK + WALK --> PARSE --> ESM --> BYTE --> COLLECT + COLLECT --> REFINE --> PACK --> PROD --> OUT + + style CLI stroke:#e89b2c,stroke-width:2px + style OUT stroke:#ec7a96,stroke-width:2px +``` + +Detailed pipeline: + ``` CLI (lib/index.ts) │ @@ -145,6 +195,33 @@ fs.readSync(EXECPATH_FD, buffer, offset, length, PAYLOAD_POSITION + position); ### SEA Build Pipeline +```mermaid +flowchart TD + CLI[CLI<br/>lib/index.ts] + DETECT{package.json?<br/>Node >= 22?} + WALK[Walker seaMode: true<br/>no bytecode, no ESM transform] + ASSETS[sea-assets.ts<br/>concat files into archive blob<br/>+ manifest with offsets] + SEA[sea.ts seaEnhanced] + CONFIG[Build sea-config.json] + BOOT[sea-bootstrap.bundle.js<br/>pre-bundled by esbuild] + BLOB[node --experimental-sea-config<br/>produces prep blob] + INJ[postject<br/>inject NODE_SEA_BLOB] + OUT[Stock Node.js executable<br/>+ NODE_SEA_BLOB resource] + + CLI --> DETECT + DETECT -- enhanced --> WALK + DETECT -- simple single-file --> BLOB + WALK --> ASSETS --> SEA + SEA --> CONFIG --> BLOB + SEA --> BOOT --> BLOB + BLOB --> INJ --> OUT + + style CLI stroke:#e89b2c,stroke-width:2px + style OUT stroke:#66bb6a,stroke-width:2px +``` + +Detailed pipeline: + ``` CLI (lib/index.ts) │ @@ -254,6 +331,28 @@ The VFS polyfill (`@roberts_lando/vfs`) handles all `fs` and `fs/promises` patch ### VFS Provider Architecture +```mermaid +flowchart TD + U[User code<br/>fs.readFileSync /snapshot/app/x.js] + V["@roberts_lando/vfs<br/>mounted at /snapshot"] + P[SEAProvider<br/>extends MemoryProvider] + R1[_resolveSymlink key] + C1{_fileCache hit?} + C2[return cached Buffer] + A[_archive.subarray<br/>off to off+len<br/>zero-copy from ArrayBuffer] + C3[_fileCache.set key, buf] + OUT[return Buffer copy] + + U --> V --> P --> R1 --> C1 + C1 -- yes --> C2 + C1 -- no --> A --> C3 --> OUT + + style U stroke:#e89b2c,stroke-width:2px + style A stroke:#66bb6a,stroke-width:2px +``` + +ASCII version: + ``` ┌─────────────────────────────────────────────────┐ │ User code: fs.readFileSync('/snapshot/app/x.js') │