diff --git a/examples/javascript-ext/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions.AppHost/AppHost.cs b/examples/javascript-ext/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions.AppHost/AppHost.cs
index 98e710107..8a4b5bc9b 100644
--- a/examples/javascript-ext/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions.AppHost/AppHost.cs
+++ b/examples/javascript-ext/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions.AppHost/AppHost.cs
@@ -23,4 +23,13 @@
.WithMappedEndpointPort()
.WithHttpHealthCheck();
+var vp = builder.AddVitePlusApp("vp-demo")
+ .WithNpm(install: true)
+ .WithPackageManagerLaunch();
+
+vp.AddApp("vp-web", "apps/website")
+ .WithHttpEndpoint(env: "PORT")
+ .WithMappedEndpointPort()
+ .WithHttpHealthCheck();
+
builder.Build().Run();
diff --git a/examples/javascript-ext/vp-demo/.gitignore b/examples/javascript-ext/vp-demo/.gitignore
new file mode 100644
index 000000000..9e0f87e8e
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/.gitignore
@@ -0,0 +1,36 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# dotenv environment variable files
+.env
+.env.*
+!.env.example
+
+# Editor directories and files
+.vscode/*
+!.vscode/settings.json
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+# AI agent worktrees
+.claude/worktrees/
+!.vscode/
+!.vscode/settings.json
+!.vscode/extensions.json
diff --git a/examples/javascript-ext/vp-demo/.vscode/extensions.json b/examples/javascript-ext/vp-demo/.vscode/extensions.json
new file mode 100644
index 000000000..cd4f5c182
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["VoidZero.vite-plus-extension-pack"]
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/.vscode/settings.json b/examples/javascript-ext/vp-demo/.vscode/settings.json
new file mode 100644
index 000000000..0950519cd
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/.vscode/settings.json
@@ -0,0 +1,23 @@
+{
+ "npm.scriptRunner": "vp",
+ "editor.defaultFormatter": "oxc.oxc-vscode",
+ "[javascript]": {
+ "editor.defaultFormatter": "oxc.oxc-vscode"
+ },
+ "[javascriptreact]": {
+ "editor.defaultFormatter": "oxc.oxc-vscode"
+ },
+ "[typescript]": {
+ "editor.defaultFormatter": "oxc.oxc-vscode"
+ },
+ "[typescriptreact]": {
+ "editor.defaultFormatter": "oxc.oxc-vscode"
+ },
+ "oxc.disableNestedConfig": true,
+ "oxc.fmt.disableNestedConfig": true,
+ "editor.formatOnSave": true,
+ "editor.formatOnSaveMode": "file",
+ "editor.codeActionsOnSave": {
+ "source.fixAll.oxc": "explicit"
+ }
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/README.md b/examples/javascript-ext/vp-demo/README.md
new file mode 100644
index 000000000..f9bae5210
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/README.md
@@ -0,0 +1,29 @@
+# Vite+ Monorepo Starter
+
+A starter for creating a Vite+ monorepo.
+
+## Development
+
+- Check everything is ready:
+
+```bash
+vp run ready
+```
+
+- Run the tests:
+
+```bash
+vp run -r test
+```
+
+- Build the monorepo:
+
+```bash
+vp run -r build
+```
+
+- Run the development server:
+
+```bash
+vp run dev
+```
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/apps/website/.gitignore b/examples/javascript-ext/vp-demo/apps/website/.gitignore
new file mode 100644
index 000000000..a547bf36d
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/examples/javascript-ext/vp-demo/apps/website/index.html b/examples/javascript-ext/vp-demo/apps/website/index.html
new file mode 100644
index 000000000..6ea677b1f
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ website
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/apps/website/package.json b/examples/javascript-ext/vp-demo/apps/website/package.json
new file mode 100644
index 000000000..eee774a10
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "website",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vp dev",
+ "build": "tsc && vp build",
+ "preview": "vp preview"
+ },
+ "devDependencies": {
+ "typescript": "^7.0.2",
+ "vite-plus": "1.3.0"
+ }
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/apps/website/public/favicon.svg b/examples/javascript-ext/vp-demo/apps/website/public/favicon.svg
new file mode 100644
index 000000000..6893eb132
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/public/favicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/apps/website/public/icons.svg b/examples/javascript-ext/vp-demo/apps/website/public/icons.svg
new file mode 100644
index 000000000..e9522193d
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/public/icons.svg
@@ -0,0 +1,24 @@
+
diff --git a/examples/javascript-ext/vp-demo/apps/website/src/assets/hero.png b/examples/javascript-ext/vp-demo/apps/website/src/assets/hero.png
new file mode 100644
index 000000000..02251f4b9
Binary files /dev/null and b/examples/javascript-ext/vp-demo/apps/website/src/assets/hero.png differ
diff --git a/examples/javascript-ext/vp-demo/apps/website/src/assets/typescript.svg b/examples/javascript-ext/vp-demo/apps/website/src/assets/typescript.svg
new file mode 100644
index 000000000..6c9d69ce4
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/src/assets/typescript.svg
@@ -0,0 +1 @@
+
diff --git a/examples/javascript-ext/vp-demo/apps/website/src/assets/vite.svg b/examples/javascript-ext/vp-demo/apps/website/src/assets/vite.svg
new file mode 100644
index 000000000..5101b674d
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/src/assets/vite.svg
@@ -0,0 +1 @@
+
diff --git a/examples/javascript-ext/vp-demo/apps/website/src/counter.ts b/examples/javascript-ext/vp-demo/apps/website/src/counter.ts
new file mode 100644
index 000000000..e2fc51631
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/src/counter.ts
@@ -0,0 +1,9 @@
+export function setupCounter(element: HTMLButtonElement) {
+ let counter = 0;
+ const setCounter = (count: number) => {
+ counter = count;
+ element.innerHTML = `Count is ${counter}`;
+ };
+ element.addEventListener("click", () => setCounter(counter + 1));
+ setCounter(0);
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/apps/website/src/main.ts b/examples/javascript-ext/vp-demo/apps/website/src/main.ts
new file mode 100644
index 000000000..961d17ec8
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/src/main.ts
@@ -0,0 +1,60 @@
+import "./style.css";
+import heroImg from "./assets/hero.png";
+import typescriptLogo from "./assets/typescript.svg";
+import viteLogo from "./assets/vite.svg";
+import { setupCounter } from "./counter.ts";
+
+document.querySelector("#app")!.innerHTML = `
+
+
+
+
Get started
+
Edit src/main.ts and save to test HMR
+
+
+
+
+
+
+
+
+
+
Documentation
+
Your questions, answered
+
+
+
+
+
Connect with us
+
Join the Vite community
+
+
+
+
+
+
+`;
+
+setupCounter(document.querySelector("#counter")!);
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/apps/website/src/style.css b/examples/javascript-ext/vp-demo/apps/website/src/style.css
new file mode 100644
index 000000000..63c1ad533
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/src/style.css
@@ -0,0 +1,292 @@
+:root {
+ --text: #6b6375;
+ --text-h: #08060d;
+ --bg: #fff;
+ --border: #e5e4e7;
+ --code-bg: #f4f3ec;
+ --accent: #aa3bff;
+ --accent-bg: rgba(170, 59, 255, 0.1);
+ --accent-border: rgba(170, 59, 255, 0.5);
+ --social-bg: rgba(244, 243, 236, 0.5);
+ --shadow: rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
+
+ --sans: system-ui, "Segoe UI", Roboto, sans-serif;
+ --heading: system-ui, "Segoe UI", Roboto, sans-serif;
+ --mono: ui-monospace, Consolas, monospace;
+
+ font: 18px/145% var(--sans);
+ letter-spacing: 0.18px;
+ color-scheme: light dark;
+ color: var(--text);
+ background: var(--bg);
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ @media (max-width: 1024px) {
+ font-size: 16px;
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --text: #9ca3af;
+ --text-h: #f3f4f6;
+ --bg: #16171d;
+ --border: #2e303a;
+ --code-bg: #1f2028;
+ --accent: #c084fc;
+ --accent-bg: rgba(192, 132, 252, 0.15);
+ --accent-border: rgba(192, 132, 252, 0.5);
+ --social-bg: rgba(47, 48, 58, 0.5);
+ --shadow: rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
+ }
+
+ #social .button-icon {
+ filter: invert(1) brightness(2);
+ }
+}
+
+body {
+ margin: 0;
+}
+
+h1,
+h2 {
+ font-family: var(--heading);
+ font-weight: 500;
+ color: var(--text-h);
+}
+
+h1 {
+ font-size: 56px;
+ letter-spacing: -1.68px;
+ margin: 32px 0;
+ @media (max-width: 1024px) {
+ font-size: 36px;
+ margin: 20px 0;
+ }
+}
+h2 {
+ font-size: 24px;
+ line-height: 118%;
+ letter-spacing: -0.24px;
+ margin: 0 0 8px;
+ @media (max-width: 1024px) {
+ font-size: 20px;
+ }
+}
+p {
+ margin: 0;
+}
+
+code,
+.counter {
+ font-family: var(--mono);
+ display: inline-flex;
+ border-radius: 4px;
+ color: var(--text-h);
+}
+
+code {
+ font-size: 15px;
+ line-height: 135%;
+ padding: 4px 8px;
+ background: var(--code-bg);
+}
+
+.counter {
+ font-size: 16px;
+ padding: 5px 10px;
+ border-radius: 5px;
+ color: var(--accent);
+ background: var(--accent-bg);
+ border: 2px solid transparent;
+ transition: border-color 0.3s;
+ margin-bottom: 24px;
+
+ &:hover {
+ border-color: var(--accent-border);
+ }
+ &:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+ }
+}
+
+.hero {
+ position: relative;
+
+ .base,
+ .framework,
+ .vite {
+ inset-inline: 0;
+ margin: 0 auto;
+ }
+
+ .base {
+ width: 170px;
+ position: relative;
+ z-index: 0;
+ }
+
+ .framework,
+ .vite {
+ position: absolute;
+ }
+
+ .framework {
+ z-index: 1;
+ top: 34px;
+ height: 28px;
+ transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg) scale(1.4);
+ }
+
+ .vite {
+ z-index: 0;
+ top: 107px;
+ height: 26px;
+ width: auto;
+ transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg) scale(0.8);
+ }
+}
+
+#app {
+ width: 1126px;
+ max-width: 100%;
+ margin: 0 auto;
+ text-align: center;
+ border-inline: 1px solid var(--border);
+ min-height: 100svh;
+ display: flex;
+ flex-direction: column;
+ box-sizing: border-box;
+}
+
+#center {
+ display: flex;
+ flex-direction: column;
+ gap: 25px;
+ place-content: center;
+ place-items: center;
+ flex-grow: 1;
+
+ @media (max-width: 1024px) {
+ padding: 32px 20px 24px;
+ gap: 18px;
+ }
+}
+
+#next-steps {
+ display: flex;
+ border-top: 1px solid var(--border);
+ text-align: left;
+
+ & > div {
+ flex: 1 1 0;
+ padding: 32px;
+ @media (max-width: 1024px) {
+ padding: 24px 20px;
+ }
+ }
+
+ .icon {
+ margin-bottom: 16px;
+ width: 22px;
+ height: 22px;
+ }
+
+ @media (max-width: 1024px) {
+ flex-direction: column;
+ text-align: center;
+ }
+}
+
+#docs {
+ border-right: 1px solid var(--border);
+
+ @media (max-width: 1024px) {
+ border-right: none;
+ border-bottom: 1px solid var(--border);
+ }
+}
+
+#next-steps ul {
+ list-style: none;
+ padding: 0;
+ display: flex;
+ gap: 8px;
+ margin: 32px 0 0;
+
+ .logo {
+ height: 18px;
+ }
+
+ a {
+ color: var(--text-h);
+ font-size: 16px;
+ border-radius: 6px;
+ background: var(--social-bg);
+ display: flex;
+ padding: 6px 12px;
+ align-items: center;
+ gap: 8px;
+ text-decoration: none;
+ transition: box-shadow 0.3s;
+
+ &:hover {
+ box-shadow: var(--shadow);
+ }
+ .button-icon {
+ height: 18px;
+ width: 18px;
+ }
+ }
+
+ @media (max-width: 1024px) {
+ margin-top: 20px;
+ flex-wrap: wrap;
+ justify-content: center;
+
+ li {
+ flex: 1 1 calc(50% - 8px);
+ }
+
+ a {
+ width: 100%;
+ justify-content: center;
+ box-sizing: border-box;
+ }
+ }
+}
+
+#spacer {
+ height: 88px;
+ border-top: 1px solid var(--border);
+ @media (max-width: 1024px) {
+ height: 48px;
+ }
+}
+
+.ticks {
+ position: relative;
+ width: 100%;
+
+ &::before,
+ &::after {
+ content: "";
+ position: absolute;
+ top: -4.5px;
+ border: 5px solid transparent;
+ }
+
+ &::before {
+ left: 0;
+ border-left-color: var(--border);
+ }
+ &::after {
+ right: 0;
+ border-right-color: var(--border);
+ }
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/apps/website/tsconfig.json b/examples/javascript-ext/vp-demo/apps/website/tsconfig.json
new file mode 100644
index 000000000..e945e379f
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/apps/website/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "target": "es2023",
+ "module": "esnext",
+ "lib": ["ES2023", "DOM"],
+ "types": ["vite/client"],
+ "allowArbitraryExtensions": true,
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"]
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/package-lock.json b/examples/javascript-ext/vp-demo/package-lock.json
new file mode 100644
index 000000000..15fd763b7
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/package-lock.json
@@ -0,0 +1,3188 @@
+{
+ "name": "vp-demo",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "vp-demo",
+ "version": "0.0.0",
+ "workspaces": [
+ "packages/*",
+ "apps/*",
+ "tools/*"
+ ],
+ "devDependencies": {
+ "vite-plus": "1.3.0"
+ },
+ "engines": {
+ "node": ">=22.18.0"
+ }
+ },
+ "apps/website": {
+ "version": "0.0.0",
+ "devDependencies": {
+ "typescript": "^7.0.2",
+ "vite-plus": "1.3.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
+ "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.29.7",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.29.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+ "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.29.10",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.10.tgz",
+ "integrity": "sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@blazediff/core": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@blazediff/core/-/core-1.10.0.tgz",
+ "integrity": "sha512-AOQff0zgR7cGsZL+4E7hVkmujoPUpm0J9xzWGWZj5wCjd3gmxESXAPfKyuzs93VdpQNFhHlBhfOjrcZ+XTERtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
+ "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@oxc-project/runtime": {
+ "version": "0.154.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.154.0.tgz",
+ "integrity": "sha512-cBQNGoh659BNgvA8OC/e4BNDtFkv03dJaYdkp2adgOQNtISNAPQ+nB4S8XvWtNk7Xl+0g+7aa+iRGR25Xycd1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.154.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.154.0.tgz",
+ "integrity": "sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/oxc-project"
+ }
+ },
+ "node_modules/@oxfmt/binding-android-arm-eabi": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.73.0.tgz",
+ "integrity": "sha512-dhunAdMbi/4o0Y66/+Wl6rpsNqpvE4i26Qw6bB77A97L2lJoktWg6m+X9QOon8iOEEqzD9rEZqFi5uZ4oIzhCA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-android-arm64": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.73.0.tgz",
+ "integrity": "sha512-dBoypjC2/xeyKyIhN2waX0/XeoccH9k0lVVe+sGRc4X8HSJVRtqyZDoXdr7bGY9A75c51dX0z0dLDpGQKwCdCg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-darwin-arm64": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.73.0.tgz",
+ "integrity": "sha512-Tn7Y+qWIpCQK+qdYwBcn6YvqeBuPiuG3tcNlYg16a5QL2o3rSmrgBB1nCyYqo0uvc1LNrfQW9/CK2tzFuID/Fg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-darwin-x64": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.73.0.tgz",
+ "integrity": "sha512-yVb0E0tg/+9Xc9YJCBq66qF1DC/aN5mhb5nnHz0k4ikwkMANtSul2VPDSwjYdXR6/DFimc+pPUgLBqkIa5Ctuw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-freebsd-x64": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.73.0.tgz",
+ "integrity": "sha512-IKR4lFnBkYNL9Uqdxa5GMTQLvnLj+3sDwTvh2atHCzah0xeo+1xR5bigRU8uyXlOsA4VpXUn0UAimq4E4RBGmQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-arm-gnueabihf": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.73.0.tgz",
+ "integrity": "sha512-7qnZ4g0ZCO3aZevOOQpZIABYwwXJW1lLDo2elviGdPQ0i11255xKEMFsi97fC1/nauQFseCJfELUy/k2JoOP+g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-arm-musleabihf": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.73.0.tgz",
+ "integrity": "sha512-36eBico2j/WPB84gb4FYd/jjqGCKOwU4M+TWLBUIqlnzTozQueLy0joA5BwsSp2OZFVkOlpCwvA3ndPamdiyLw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-arm64-gnu": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.73.0.tgz",
+ "integrity": "sha512-VZ3cSgCAT18knKo52DcACmAuIoqG6qVEyeZRFbJd0xmYQ8GyYjuBc6IAh6MZHijT6q7p4/HPI+6ZWsCuhdV6iw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-arm64-musl": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.73.0.tgz",
+ "integrity": "sha512-8YVzH59XSHcqwXNgc5qK851zCqwpmBgOifARXEPPe5/xTsIbHceYoPZAyqfpYV0CfKmzSaEDBgYHFza4rhx+Zw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-ppc64-gnu": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.73.0.tgz",
+ "integrity": "sha512-MqRJnmCys0rwOgpWyEidSA7v/bvOqfNDJhPkQoR9mPVYrvSmMaW2Xhdpl28cbTA+brOM1is62GjIvJplVlUVpw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-riscv64-gnu": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.73.0.tgz",
+ "integrity": "sha512-4t2F3SWJSK/O/kRRFnL0elJzn75fJGGu71gs1HtiWcS80SmJOpkHiwwLnTp9suGdns8VHEPxYS0GTcyVwHKWBA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-riscv64-musl": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.73.0.tgz",
+ "integrity": "sha512-D8b4I8I1kLdJQFwdFXNV+cwh3xWSiNKofjdGUk0nDpc0AHOds8T+poGbP9RWQMvgsvMb9OMgp/aV7ahBR37TbQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-s390x-gnu": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.73.0.tgz",
+ "integrity": "sha512-QrC1S5VL1+N5rvorB15jH7CPvjVHA7GyUI5oVEd8Bd9m5605RDBQYTxDQ920DuylRoZOh2V7/xXpfCtFUrojUQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-x64-gnu": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.73.0.tgz",
+ "integrity": "sha512-dFcUKQPltCEPa+YlkF3zqufn6nJPZdG73LpnjBvZFFsU3laCMssDXSYB99mVaj43FqdEgjpz5TO6gbYXcczd9g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-x64-musl": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.73.0.tgz",
+ "integrity": "sha512-LmQe+nV8e+eUwfPNCxDF+owbsg88toBiR/8rZRgVOeKQP3MaGefXZRvBoc1UG37iWEQ/9JlCXG9Mc4nf4N3agw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-openharmony-arm64": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.73.0.tgz",
+ "integrity": "sha512-8weOr1OKknE0G2DbR6ejJUT9AOsoBU6cXlsetmbihHv1K+bK7qP61T6lJxY0k/aAO7GyOJiRGNlL+04r4eH8Xg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-win32-arm64-msvc": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.73.0.tgz",
+ "integrity": "sha512-mZV+QxXYgb8E18gzAFItb937VIsE4dqWdStrD3tRRC52UubOYEuU+e7NaIqUsGdB5YsJqNeuck3Ue/af2r9wyA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-win32-ia32-msvc": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.73.0.tgz",
+ "integrity": "sha512-QJPUsbgUb97ZPPMkFUq6VQq0fLhC4Np19KL9aB/qKVwXnpKE6MIiILXqzhKnQ/UbnEDjKJ7Xv1d6zH4bYPCUdQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-win32-x64-msvc": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.73.0.tgz",
+ "integrity": "sha512-cGcze2fu+ykIaFtkEvZlkZ3HvnCLk+WISthtq99zWTWn0x13t5L9TxvGdLZMUMvtfYR+ICkiCwKnguVubdcw0w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint-tsgolint/darwin-arm64": {
+ "version": "7.0.2004",
+ "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/darwin-arm64/-/darwin-arm64-7.0.2004.tgz",
+ "integrity": "sha512-uJk3ttju7Lz+Nv8WG4CsLyewoL1qf/Ny8S8OksJ7Bm/F14Tc9gMfW6arM1PCc57IzH/X/I79YsCWTgxX1FKibQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@oxlint-tsgolint/darwin-x64": {
+ "version": "7.0.2004",
+ "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/darwin-x64/-/darwin-x64-7.0.2004.tgz",
+ "integrity": "sha512-0BFfHTzDxNDFPcu0UZAXT6CyCJHAXM0dZveyDb4KEHa2qF/DSnOKOrmvK/wFuFol9kvijbGM9JfuOsor+zWXRw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@oxlint-tsgolint/linux-arm64": {
+ "version": "7.0.2004",
+ "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/linux-arm64/-/linux-arm64-7.0.2004.tgz",
+ "integrity": "sha512-TAehQc+qdRXyDN3nl/r/3/oPrBVrbtrDeGMkFyG6mf+XphpoJ2lAMVFLclyvrVZCw02RbKROjyw8h72XwQQHcw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@oxlint-tsgolint/linux-x64": {
+ "version": "7.0.2004",
+ "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/linux-x64/-/linux-x64-7.0.2004.tgz",
+ "integrity": "sha512-LPunZvm6ZbWPfHMAyfZf9ci3HHvNEzLejO8zdqO3GoVGoSEHqqufHUD7+OgeatVSaJP7uXDJ2HaNOHIoH7go4Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@oxlint-tsgolint/win32-arm64": {
+ "version": "7.0.2004",
+ "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/win32-arm64/-/win32-arm64-7.0.2004.tgz",
+ "integrity": "sha512-FVWplzDImWhiuawnIZVETaQecv4GWom6Jv4Fx2xj7hhXXDZ5okEgiw1gTCImHTIQsi2ycC5oSxVwrn69bMh7iw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@oxlint-tsgolint/win32-x64": {
+ "version": "7.0.2004",
+ "resolved": "https://registry.npmjs.org/@oxlint-tsgolint/win32-x64/-/win32-x64-7.0.2004.tgz",
+ "integrity": "sha512-7PsxuUx11Ry9DYTWcljTzRbmZY9B6O9fFFfZV+aodQEMy6pfRT3fhoQRv9PtGN/89z1pPz3nFKrsFm6WqNtX7w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@oxlint/binding-android-arm-eabi": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.88.0.tgz",
+ "integrity": "sha512-k6Fgkf86ubfeH4GvqYsRolfuVAp0pfYVZvifSlXNHPdMaWUOfxUrmLEeDD7hF6U2oJuhsVxhSWq86/xCJ+9MmA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-android-arm64": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.88.0.tgz",
+ "integrity": "sha512-AsIyhl9o1ejwtac7NMbhKpMdSml6NWR0ljKjZERxC8OHYDAW8o/Om9n1QHVLi4VCEUo42Zte2/Op9kyoGpJZMg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-darwin-arm64": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.88.0.tgz",
+ "integrity": "sha512-qgBjB7eEKcCB4RqjXGuoSZq74g0wD09fWFJ+HWcCJcKaga8TeUHtb+BY0SsxdleSLBgx4RZ7qmgo0EzqEq7JoQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-darwin-x64": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.88.0.tgz",
+ "integrity": "sha512-sCz3X5Mw/xdzEzn4fsCt1Iq8NKJnGNfhR+b9B5k+4DysYAHsmIhYoocnBPiQ9kvY3+pUun2A0Z8Vtun/Nv6YoQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-freebsd-x64": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.88.0.tgz",
+ "integrity": "sha512-xTOdYOIqCufgIj0knvxu86FBfovP6QBiD7ngNva01gb8xPQCD5gXkE5APGczH35zStim1O3zqvFbLQmY85xXRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-arm-gnueabihf": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.88.0.tgz",
+ "integrity": "sha512-BLadtw88NdYJBrAtC1dYzrPfSP2d5zgx6iuZycdD0YmZBJ2Nqbit9Z4PSaIb6gxK25dweArGMPbOmq/0ugwUPg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-arm-musleabihf": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.88.0.tgz",
+ "integrity": "sha512-wILSczl/DaZsCcf7j7tvNbssp8hxEHIJxrv4j7+JjI3TAL1U/JTWbeUtoJJC/vo8+2hkTmHLYoKJjmiNbijdXw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-arm64-gnu": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.88.0.tgz",
+ "integrity": "sha512-jutT2Hy8JCuZuMwIFHo2HtyxfOfBJHyQxlBHBK1SL9W2f8n/WhjAP0FnDMz9d/mjhv9+QA0mx5AdQ9fDjsrFFg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-arm64-musl": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.88.0.tgz",
+ "integrity": "sha512-8N8iGV9hh4Lkeuq7QsEkjoXNRRflqR1G2qyoGYXcA0k5qllrdqmfylKEXyHIVERxqNDyMO4StqDQ0uLxXcBQAg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-ppc64-gnu": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.88.0.tgz",
+ "integrity": "sha512-5ydcQt3znNQ/rGEWYRvpS2cK9+T18P2VYgnyJ+eloEAwi9YUmsXy5VGrRqNWIK6qzWwHGnEE3ojVqqQNo+f0hA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-riscv64-gnu": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.88.0.tgz",
+ "integrity": "sha512-iGx0uvFT54b/5DPJdEBCxYIrVB3v0uTy+JhRh3CyEp8/22BXDkG8rffkFwREdLsdj9mOrPbJYVOZw8ipcBuzjw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-riscv64-musl": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.88.0.tgz",
+ "integrity": "sha512-Wt47mKMWelVjRjuR7BCFxXkB0m79K1sTEbqMHRWciKUgo5iv7sWsF4RXSOyFYHD9zerNrkRZblnN273rhwOA1Q==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-s390x-gnu": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.88.0.tgz",
+ "integrity": "sha512-g3L12KCS4+1gtUt3RbJ4F+Yxx4LNmmZLEPfhd8rAHEJjJk2lAgNfnjGoP/phJyhG5WS6VbNYbJtadJelNfvTMA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-x64-gnu": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.88.0.tgz",
+ "integrity": "sha512-og/XHVDOD9ZJgRiZkT9DgzQd4sr+JZW7e4l17Q/jVMZiIbeEd4uIu9iAoUbTF1gIvVZoRc4QDOxyVUvQGp4WHg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-linux-x64-musl": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.88.0.tgz",
+ "integrity": "sha512-EmhBsp+xuKb6YbZNEMLBo80Xw71AZOIm18do8ni/GLX/Lw1XzNhVYpbxO1KasYtoAvrGtCOdCPULRlIE0bPbTQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-openharmony-arm64": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.88.0.tgz",
+ "integrity": "sha512-DBUcx/KwYdg1DAz+G01P/GFv512J04EsZadbHptx2FTpWT/MWRg21ZToNHt9pnsfQRBQ3et/g+vqzbvrdAVbuA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-win32-arm64-msvc": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.88.0.tgz",
+ "integrity": "sha512-xeVd0n4XG5HvynxfYvXi6uB+JvZbVZataowPS8cYpMbYg9mwE4sSyElFQd4LVJFifq8bRLDSR18XgEildmcXAg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-win32-ia32-msvc": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.88.0.tgz",
+ "integrity": "sha512-MA6iOw//amleaz2mVMsZrA7NHlEexjTrhIxSMFCXQi6IUuQO+3Od00GZhr2iCYw6RFzMW36jkKK/WHBXMsoQAw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/binding-win32-x64-msvc": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.88.0.tgz",
+ "integrity": "sha512-3Sz6rVWe8Dy+ufsXurFN1GX2dX43F/lQMSLelK9gFjiba7nHvLlqlhR5cHlWVnCpSqUY1hN9pyCX9XToe6ve6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxlint/plugins": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/@oxlint/plugins/-/plugins-1.88.0.tgz",
+ "integrity": "sha512-G2xbfWTrbqYRhR/vfeKNMQf/sS3/ti0iKJAAkRxHuXWZH/hne/dyIb9QKk5LuR6cJLARxsL6FMoAYmfspd74MQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/oxc-project"
+ }
+ },
+ "node_modules/@polka/url": {
+ "version": "1.0.0-next.29",
+ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
+ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@quansync/fs": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.1.0.tgz",
+ "integrity": "sha512-qAPG/t3HqML1TlN7sY/pTbEjzFVAKsMjNNMGheyDosro+kT4iw2KCUoHcVdmliwWjorm4elZbgNQyU2eD97eDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "quansync": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ },
+ "node_modules/@testing-library/dom": {
+ "version": "10.4.2",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.2.tgz",
+ "integrity": "sha512-yzr2S9HyAIdhz2/6qHgbs665Q7PKVcDF05vsOlHPxG1mo36gKVesdYVeDLnXgfjJ03CrKRk08knc6+E/9m8v2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "picocolors": "1.1.1",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@testing-library/user-event": {
+ "version": "14.6.8",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.8.tgz",
+ "integrity": "sha512-vgSSqnANMnkcYR/vUNDbwS7aM3OErRLNUG8vCVVlj4oc6cKffUrccX7UAS5AmJQQNZTSibi9z5GvvRZ0aYgUCQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": ">=7.21.4"
+ }
+ },
+ "node_modules/@types/aria-query": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
+ "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/chai": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/deep-eql": "*",
+ "assertion-error": "^2.0.1"
+ }
+ },
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
+ "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "26.6.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.5.tgz",
+ "integrity": "sha512-uMzsv9stDdofIZBx4UGh4Z9ZgXnGC9seRDscilBcTHAeOFk67MZg/k9bWVfO+bk4qZmG+l52hRnLwUiH2LnJTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~8.9.0"
+ }
+ },
+ "node_modules/@typescript/typescript-aix-ppc64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz",
+ "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-darwin-arm64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz",
+ "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-darwin-x64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz",
+ "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-freebsd-arm64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz",
+ "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-freebsd-x64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz",
+ "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-linux-arm": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz",
+ "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-linux-arm64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz",
+ "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-linux-loong64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz",
+ "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-linux-mips64el": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz",
+ "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-linux-ppc64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz",
+ "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-linux-riscv64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz",
+ "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-linux-s390x": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz",
+ "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-linux-x64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz",
+ "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-netbsd-arm64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz",
+ "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-netbsd-x64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz",
+ "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-openbsd-arm64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz",
+ "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-openbsd-x64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz",
+ "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-sunos-x64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz",
+ "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-win32-arm64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz",
+ "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@typescript/typescript-win32-x64": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz",
+ "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=16.20.0"
+ }
+ },
+ "node_modules/@vitest/browser": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-5.0.5.tgz",
+ "integrity": "sha512-IDMoZX/iZ8rkilw7weaSgN8tJ7iZ9hUv0wYoKXyiyjWjWFwLSWAY707DcVTgxTYOudWC1E3HA9LYn7kVa9a7uQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@blazediff/core": "1.10.0",
+ "@vitest/mocker": "5.0.5",
+ "@vitest/ui": "5.0.5",
+ "@vitest/utils": "5.0.5",
+ "magic-string": "^1.4.3",
+ "pngjs": "^7.0.0",
+ "sirv": "^3.0.2",
+ "tinyrainbow": "^3.2.0",
+ "ws": "^8.22.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "vitest": "5.0.5"
+ }
+ },
+ "node_modules/@vitest/browser-preview": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/browser-preview/-/browser-preview-5.0.5.tgz",
+ "integrity": "sha512-ViNg4UlomGSJHtnnr7Txm+55P7/aAMMoS+1WYnWjp5w5tzf7YEUAICcs2sb1uMovEnC8el/8zUfkWZ8+7fPCKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@testing-library/dom": "^10.4.2",
+ "@testing-library/user-event": "^14.6.7",
+ "@vitest/browser": "5.0.5"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "vitest": "5.0.5"
+ }
+ },
+ "node_modules/@vitest/mocker": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.5.tgz",
+ "integrity": "sha512-xLL3lkDegJZw+MGoGaCCsFayDZthGgpAtr3Vziyfc4p7xH89K7KRPcRBBh/kEYm0Aqkt5DtTmkYpBtRV/FrHZg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.31",
+ "@vitest/spy": "5.0.5",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^1.4.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "msw": "^2.4.9 || ^3.0.0",
+ "vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vitest/pretty-format": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-5.0.5.tgz",
+ "integrity": "sha512-24sSdIlMA9DVPXnYiB9siwU0bTd887Y9jX3+vabztCSsvHwo7ipvJ/a2L3Rljw8+2rK1f5fCj3h5U9I/Jsqgbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/snapshot": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-5.0.5.tgz",
+ "integrity": "sha512-dHyFElWMQy0wFBGrIaPPeUWfJFh+jAUrv46ImIJGd8CADdKV3mlrAu3FyD0wesdxELFCs9M807e040Kba/XKtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "5.0.5",
+ "@vitest/utils": "5.0.5",
+ "magic-string": "^1.4.3",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/spy": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.5.tgz",
+ "integrity": "sha512-lwJRExuH417257Q5wv9QYugN9IMJkoxcrKrYxGPQkBzl7wlNpTUxD/5yNX4ESKVUIShKPgkGchYPFMWOOk0wzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@vitest/ui": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-5.0.5.tgz",
+ "integrity": "sha512-dCoGUOdgmCaSB2g+WQ/spPCBkytAWdNUkFSXY4z+eYp2d8JEOY8v0uDRaJTG9qf/kTlTVZ4CuYMYMz/f1HS/qQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "5.0.5",
+ "fflate": "^0.8.3",
+ "flatted": "^3.4.4",
+ "pathe": "^2.0.3",
+ "sirv": "^3.0.2",
+ "tinyrainbow": "^3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "vitest": "5.0.5"
+ }
+ },
+ "node_modules/@vitest/utils": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-5.0.5.tgz",
+ "integrity": "sha512-/rBu7gzLDQI/SC79Tn98b5DwOgaHU/Gt4I9OVeP3YofzNaYtbImRCOJQmT1S6vOJg9gEIlWC+r3QxKkjuSa1nQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "5.0.5",
+ "convert-source-map": "^2.0.0",
+ "tinyrainbow": "^3.2.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/@voidzero-dev/vite-plus-darwin-arm64": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-darwin-arm64/-/vite-plus-darwin-arm64-1.3.0.tgz",
+ "integrity": "sha512-BF4W+UwGxUkHPrH2pZLhafJfkJT20WZIbMzZgZLGQ44LPpZPX8Sb+qtblUnXUkkCzTqad4XtSPgiLKglvZkNQQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@voidzero-dev/vite-plus-darwin-x64": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-darwin-x64/-/vite-plus-darwin-x64-1.3.0.tgz",
+ "integrity": "sha512-vLZTk0r+s3e7mycj4SGBbcpK+xyM8a86hXQZtQbJyW7xrGJzsavISy7/m4gGZpWN32Hl4Tmx9V/ffeaoXLkRdg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@voidzero-dev/vite-plus-linux-arm64-gnu": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-linux-arm64-gnu/-/vite-plus-linux-arm64-gnu-1.3.0.tgz",
+ "integrity": "sha512-H43Dj9RkEyjOFXxTk3DLTa6hqmHhxUN9vbbqNdwQoc3/TPNhC1zsLZy3qgUFbYGLdS7M9jICCqFzj5GDSYrhIw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@voidzero-dev/vite-plus-linux-arm64-musl": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-linux-arm64-musl/-/vite-plus-linux-arm64-musl-1.3.0.tgz",
+ "integrity": "sha512-Se2GlvzUZOvFy+5hoQHoG7LFeiplKs+EJwaskayCSLwZAP+e6/LTK7EK+8OcdMpmdsLPtZoTJHkIjSzrQowJwQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@voidzero-dev/vite-plus-linux-x64-gnu": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-linux-x64-gnu/-/vite-plus-linux-x64-gnu-1.3.0.tgz",
+ "integrity": "sha512-moxojk6zmog2SaLE4/cG75acE6X3cjR0/52Ba8OG2ct0r+dv55VSE0kellAuxS6o9VHy7TBhkIpwpFpQ34rnAA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@voidzero-dev/vite-plus-linux-x64-musl": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-linux-x64-musl/-/vite-plus-linux-x64-musl-1.3.0.tgz",
+ "integrity": "sha512-CykxH008Dy9u20Myki9/UIqq3Dbo1ZMqa098aS6AtWp3QKyEKzSLPB3jKDUklgmu83xiFe5BpPA+33oF0yNY7A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@voidzero-dev/vite-plus-win32-arm64-msvc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-win32-arm64-msvc/-/vite-plus-win32-arm64-msvc-1.3.0.tgz",
+ "integrity": "sha512-l61S9b8aeiDpi8wPRfz4HonqRkLpt/OVYs0sCskvlXYSW/L8qfLOtuWH/xpF8xDjMIfBefKejBVfU1UlRax5Tw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@voidzero-dev/vite-plus-win32-x64-msvc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-win32-x64-msvc/-/vite-plus-win32-x64-msvc-1.3.0.tgz",
+ "integrity": "sha512-b6Ng8YezA6JA3adQBNA+8Mn26+OX4fw/tsPfnk//5Cx+1XFDZoAxWYXtGzc0yUQPEKnoGtfw/0OUvcibg61yYg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@yuku-core/binding-android-arm64": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-android-arm64/-/binding-android-arm64-0.19.0.tgz",
+ "integrity": "sha512-wdL2XmTiZixAOaHk9Z0JJZ8u9Qm8d333Zjpc6gaxXFX+UR5BlsfxZ7a2+2Rm71pamppsPYGUGFq2oVLbh6DISw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@yuku-core/binding-darwin-arm64": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-darwin-arm64/-/binding-darwin-arm64-0.19.0.tgz",
+ "integrity": "sha512-7sNJa6XJhyetnTy64jw3NEi4YgUcezHk1G5GH9FSvXAuC8wIlbaOwT9lgq5qo5sspjrZJQlBR1TWflP49uRpMw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@yuku-core/binding-darwin-x64": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-darwin-x64/-/binding-darwin-x64-0.19.0.tgz",
+ "integrity": "sha512-pTC7dYEc59isdyizc3nsuyFNBu2LU5wMYZ1be6UMr59PY/AJNtO1aBLWV0MgL/z7C1nv/2sX4TNjGgKLoeevJw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@yuku-core/binding-freebsd-x64": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-freebsd-x64/-/binding-freebsd-x64-0.19.0.tgz",
+ "integrity": "sha512-xrZjF6XOEwyLOiDIfrwDdRCS6ghxcJeirNC1KivQhVcUwlRonaU79S3/Uiyx3lBylPnT8qKJ3/aMT+H52nGTJQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@yuku-core/binding-linux-arm-gnu": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.19.0.tgz",
+ "integrity": "sha512-0OyIH53C0I1CbADHn9FSdCfX5qbpeLwJhmOVhonFJNYheybOnkSJ50qGMfTJIb8y5zrwqvLs7FVBvz6Fk8maZg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@yuku-core/binding-linux-arm-musl": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-arm-musl/-/binding-linux-arm-musl-0.19.0.tgz",
+ "integrity": "sha512-z/iPfkCOCSXE34VXNt0uP1ORSW+4mEa9b5CiJcWZeqZH08g49bFU/jRM2T04f+Wpw5mJ6HIzNBiojxeAbrHjeg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@yuku-core/binding-linux-arm64-gnu": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.19.0.tgz",
+ "integrity": "sha512-jLNTi+gzaRwBJ+gwhCJ+rDb5dmx/8hEBx93UWd7hjMSqPTL1D1wvVSvXVAldV5kALvju7b0/m51EHEhs4+I1fA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@yuku-core/binding-linux-arm64-musl": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.19.0.tgz",
+ "integrity": "sha512-YwyPIdW/rN2Fmv0MTFWi47FaB3F9g+2b+sJISyAw83Yd60RWH4T3Nx6XkAHHVN+uKJNBAd6So7/BVihSiFYvuQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@yuku-core/binding-linux-x64-gnu": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.19.0.tgz",
+ "integrity": "sha512-/vskaAXVX3ESR43FiTdfiYS7z1b9uoQJwVQ/0RgUHgN2sWoAyCZs+aX4CgU7eKGIHTVfp9VFwv+c+2XchYiEtQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@yuku-core/binding-linux-x64-musl": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-linux-x64-musl/-/binding-linux-x64-musl-0.19.0.tgz",
+ "integrity": "sha512-FuXL5igeSKib9Rye02TdH+D6SQezTyGxIATMu1Qsn/QywrzwpGl35OLpS2C1x5vpGLeVE2XgiLd5mVPFHmIglQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@yuku-core/binding-win32-arm64": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-win32-arm64/-/binding-win32-arm64-0.19.0.tgz",
+ "integrity": "sha512-YuJAe7zEKT1Xa7LuHlhGJpPnYQeVtvo0rZvNjJRqkH0hQGOw4C8QeP30Tg5VKGzZfo2x8CjhjEhKt4TmLwfmdg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@yuku-core/binding-win32-x64": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-core/binding-win32-x64/-/binding-win32-x64-0.19.0.tgz",
+ "integrity": "sha512-o8iY/mXwlRkedp0LNTr4+TEfXTPQwoNZmv6k+1WIAd1ZXEn8xJJTBCtB0osaVvdZo/x/cNmV16UrWrrGpM5Mvw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@yuku-toolchain/types": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.19.0.tgz",
+ "integrity": "sha512-tFkNbsP4WXX9UMUC5syJGdK9dPMLK0PPaIuXCcCYH75sZ8MrebfBZ2XvCILRTw8AgLivSSCfDa4R67iYBDa4Kg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/args-tokenizer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/args-tokenizer/-/args-tokenizer-0.3.0.tgz",
+ "integrity": "sha512-xXAd7G2Mll5W8uo37GETpQ2VrE84M181Z7ugHFGQnJZ50M2mbOv0osSZ9VsSgPfJQ+LVG0prSi0th+ELMsno7Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/bumpp": {
+ "version": "12.3.0",
+ "resolved": "https://registry.npmjs.org/bumpp/-/bumpp-12.3.0.tgz",
+ "integrity": "sha512-YgW09sgbIGQmAD/Jk7FEGP0tm0PeDz+Zgk+IAk+MOHhb/98pj/l3CgkxSjd7C1O99JPxTNwS+bPOTNaHuNh6lQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "args-tokenizer": "^0.3.0",
+ "cac": "^7.0.0",
+ "jsonc-parser": "^3.3.1",
+ "package-manager-detector": "^1.8.0",
+ "tinyexec": "^1.3.0",
+ "tinyglobby": "^0.2.17",
+ "unconfig": "^7.5.0",
+ "verkit": "^0.4.0",
+ "yaml": "^2.9.0"
+ },
+ "bin": {
+ "bumpp": "bin/bumpp.mjs"
+ },
+ "engines": {
+ "node": "^22.18.0 || ^24.11.0 || >=26.0.0"
+ }
+ },
+ "node_modules/cac": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cac/-/cac-7.1.0.tgz",
+ "integrity": "sha512-LMDU/U2yA4IPIY8KT0NsNPWEYZvAMkbgyspxJ6btJaYV+WMDOHAZCmB0lsTObiHaRS1V/ztKAl7+TSkTqXyeoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.19.0"
+ }
+ },
+ "node_modules/chai": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.3.0.tgz",
+ "integrity": "sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/defu": {
+ "version": "6.1.7",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz",
+ "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dom-accessibility-api": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
+ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/es-module-lexer": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz",
+ "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
+ "node_modules/expect-type": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz",
+ "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fflate": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
+ "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/flatted": {
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz",
+ "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "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/jiti": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
+ "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jsonc-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lightningcss": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz",
+ "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.33.0",
+ "lightningcss-darwin-arm64": "1.33.0",
+ "lightningcss-darwin-x64": "1.33.0",
+ "lightningcss-freebsd-x64": "1.33.0",
+ "lightningcss-linux-arm-gnueabihf": "1.33.0",
+ "lightningcss-linux-arm64-gnu": "1.33.0",
+ "lightningcss-linux-arm64-musl": "1.33.0",
+ "lightningcss-linux-x64-gnu": "1.33.0",
+ "lightningcss-linux-x64-musl": "1.33.0",
+ "lightningcss-win32-arm64-msvc": "1.33.0",
+ "lightningcss-win32-x64-msvc": "1.33.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz",
+ "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz",
+ "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz",
+ "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz",
+ "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz",
+ "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz",
+ "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz",
+ "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz",
+ "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz",
+ "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz",
+ "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz",
+ "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lz-string": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
+ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "lz-string": "bin/bin.js"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.3.tgz",
+ "integrity": "sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.6.0"
+ }
+ },
+ "node_modules/mrmime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.20",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",
+ "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/obug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-3.0.0.tgz",
+ "integrity": "sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==",
+ "dev": true,
+ "funding": [
+ "https://github.com/sponsors/sxzz",
+ "https://opencollective.com/debug"
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/oxfmt": {
+ "version": "0.73.0",
+ "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.73.0.tgz",
+ "integrity": "sha512-Ke4xbpuzqIBP4bkd48q815RhqWNJqOBzxVA9199M4qcF0y0LtpUv7UTg1dJ5ea6jw0RBUDZvX3qOUMNmmxfxbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinypool": "2.2.0"
+ },
+ "bin": {
+ "oxfmt": "bin/oxfmt"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/oxc-project"
+ },
+ "optionalDependencies": {
+ "@oxfmt/binding-android-arm-eabi": "0.73.0",
+ "@oxfmt/binding-android-arm64": "0.73.0",
+ "@oxfmt/binding-darwin-arm64": "0.73.0",
+ "@oxfmt/binding-darwin-x64": "0.73.0",
+ "@oxfmt/binding-freebsd-x64": "0.73.0",
+ "@oxfmt/binding-linux-arm-gnueabihf": "0.73.0",
+ "@oxfmt/binding-linux-arm-musleabihf": "0.73.0",
+ "@oxfmt/binding-linux-arm64-gnu": "0.73.0",
+ "@oxfmt/binding-linux-arm64-musl": "0.73.0",
+ "@oxfmt/binding-linux-ppc64-gnu": "0.73.0",
+ "@oxfmt/binding-linux-riscv64-gnu": "0.73.0",
+ "@oxfmt/binding-linux-riscv64-musl": "0.73.0",
+ "@oxfmt/binding-linux-s390x-gnu": "0.73.0",
+ "@oxfmt/binding-linux-x64-gnu": "0.73.0",
+ "@oxfmt/binding-linux-x64-musl": "0.73.0",
+ "@oxfmt/binding-openharmony-arm64": "0.73.0",
+ "@oxfmt/binding-win32-arm64-msvc": "0.73.0",
+ "@oxfmt/binding-win32-ia32-msvc": "0.73.0",
+ "@oxfmt/binding-win32-x64-msvc": "0.73.0"
+ },
+ "peerDependencies": {
+ "@astrojs/compiler-rs": "^0.4.0 || ^0.5.0",
+ "svelte": "^5.0.0",
+ "vite-plus": "*"
+ },
+ "peerDependenciesMeta": {
+ "@astrojs/compiler-rs": {
+ "optional": true
+ },
+ "svelte": {
+ "optional": true
+ },
+ "vite-plus": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/oxlint": {
+ "version": "1.88.0",
+ "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.88.0.tgz",
+ "integrity": "sha512-uIcFgw8BmqvFRGzH5+r7d2zJMEexwNSrEmM6WQNnGh3VkO0XYTEFoyxyNE6tjKMUib9Cue4XJA2DoWruO5D6aw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "oxlint": "bin/oxlint"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/oxc-project"
+ },
+ "optionalDependencies": {
+ "@oxlint/binding-android-arm-eabi": "1.88.0",
+ "@oxlint/binding-android-arm64": "1.88.0",
+ "@oxlint/binding-darwin-arm64": "1.88.0",
+ "@oxlint/binding-darwin-x64": "1.88.0",
+ "@oxlint/binding-freebsd-x64": "1.88.0",
+ "@oxlint/binding-linux-arm-gnueabihf": "1.88.0",
+ "@oxlint/binding-linux-arm-musleabihf": "1.88.0",
+ "@oxlint/binding-linux-arm64-gnu": "1.88.0",
+ "@oxlint/binding-linux-arm64-musl": "1.88.0",
+ "@oxlint/binding-linux-ppc64-gnu": "1.88.0",
+ "@oxlint/binding-linux-riscv64-gnu": "1.88.0",
+ "@oxlint/binding-linux-riscv64-musl": "1.88.0",
+ "@oxlint/binding-linux-s390x-gnu": "1.88.0",
+ "@oxlint/binding-linux-x64-gnu": "1.88.0",
+ "@oxlint/binding-linux-x64-musl": "1.88.0",
+ "@oxlint/binding-openharmony-arm64": "1.88.0",
+ "@oxlint/binding-win32-arm64-msvc": "1.88.0",
+ "@oxlint/binding-win32-ia32-msvc": "1.88.0",
+ "@oxlint/binding-win32-x64-msvc": "1.88.0"
+ },
+ "peerDependencies": {
+ "oxlint-tsgolint": ">=7.0.2003",
+ "vite-plus": "*"
+ },
+ "peerDependenciesMeta": {
+ "oxlint-tsgolint": {
+ "optional": true
+ },
+ "vite-plus": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/oxlint-tsgolint": {
+ "version": "7.0.2004",
+ "resolved": "https://registry.npmjs.org/oxlint-tsgolint/-/oxlint-tsgolint-7.0.2004.tgz",
+ "integrity": "sha512-vQ9WDF3fiZJvRdSDosNOflerOCOpwol6vWzVDxW76RcU19cjTh7engvkHLvmv+tzedR8fAiJUVUGr6IVZdkzXQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "tsgolint": "bin/tsgolint.js"
+ },
+ "optionalDependencies": {
+ "@oxlint-tsgolint/darwin-arm64": "7.0.2004",
+ "@oxlint-tsgolint/darwin-x64": "7.0.2004",
+ "@oxlint-tsgolint/linux-arm64": "7.0.2004",
+ "@oxlint-tsgolint/linux-x64": "7.0.2004",
+ "@oxlint-tsgolint/win32-arm64": "7.0.2004",
+ "@oxlint-tsgolint/win32-x64": "7.0.2004"
+ }
+ },
+ "node_modules/package-manager-detector": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.9.0.tgz",
+ "integrity": "sha512-zAMfbta9nPA8AKkA4WdmNAT8R8s6Dk0/xwPsqNnRidMFcLo1YkLuPDTgs2f64XdzS8vbLNnoJ+uUIkgbz7oRHA==",
+ "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/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/picomatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pngjs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz",
+ "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.19.0"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz",
+ "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==",
+ "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.20",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^17.0.1"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
+ "node_modules/quansync": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/quansync/-/quansync-1.0.0.tgz",
+ "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/antfu"
+ },
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/react-is": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/sirv": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz",
+ "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@polka/url": "^1.0.0-next.24",
+ "mrmime": "^2.0.0",
+ "totalist": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
+ "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/std-env": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz",
+ "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinybench": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.2.2.tgz",
+ "integrity": "sha512-nIZ2N2dFpjBsg2hgitKu7mA+FvsIJuGJOwysRngmVRRmWgR/UyPjwJj8c/fT/dhm8EkHnF5EOogRf+0Z2qrimA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/tinyexec": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.1.tgz",
+ "integrity": "sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinypool": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.2.0.tgz",
+ "integrity": "sha512-jBrmx4lYmaC9k/mgPbylxs7kBUxHtD8256up+HjLaDFfXScKJQyil+SWXSvhAtT7XHo+yTVlpB81PGmHP8oLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^20.0.0 || >=22.0.0"
+ }
+ },
+ "node_modules/tinyrainbow": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.2.0.tgz",
+ "integrity": "sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/totalist": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
+ "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz",
+ "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc"
+ },
+ "engines": {
+ "node": ">=16.20.0"
+ },
+ "optionalDependencies": {
+ "@typescript/typescript-aix-ppc64": "7.0.2",
+ "@typescript/typescript-darwin-arm64": "7.0.2",
+ "@typescript/typescript-darwin-x64": "7.0.2",
+ "@typescript/typescript-freebsd-arm64": "7.0.2",
+ "@typescript/typescript-freebsd-x64": "7.0.2",
+ "@typescript/typescript-linux-arm": "7.0.2",
+ "@typescript/typescript-linux-arm64": "7.0.2",
+ "@typescript/typescript-linux-loong64": "7.0.2",
+ "@typescript/typescript-linux-mips64el": "7.0.2",
+ "@typescript/typescript-linux-ppc64": "7.0.2",
+ "@typescript/typescript-linux-riscv64": "7.0.2",
+ "@typescript/typescript-linux-s390x": "7.0.2",
+ "@typescript/typescript-linux-x64": "7.0.2",
+ "@typescript/typescript-netbsd-arm64": "7.0.2",
+ "@typescript/typescript-netbsd-x64": "7.0.2",
+ "@typescript/typescript-openbsd-arm64": "7.0.2",
+ "@typescript/typescript-openbsd-x64": "7.0.2",
+ "@typescript/typescript-sunos-x64": "7.0.2",
+ "@typescript/typescript-win32-arm64": "7.0.2",
+ "@typescript/typescript-win32-x64": "7.0.2"
+ }
+ },
+ "node_modules/unconfig": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.5.0.tgz",
+ "integrity": "sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@quansync/fs": "^1.0.0",
+ "defu": "^6.1.4",
+ "jiti": "^2.6.1",
+ "quansync": "^1.0.0",
+ "unconfig-core": "7.5.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/unconfig-core": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.5.0.tgz",
+ "integrity": "sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@quansync/fs": "^1.0.0",
+ "quansync": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz",
+ "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/utils": {
+ "resolved": "packages/utils",
+ "link": true
+ },
+ "node_modules/verkit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/verkit/-/verkit-0.4.1.tgz",
+ "integrity": "sha512-mMVzj0TXExtVdlDEq+Mzp0eyOuyznNpFobNM3uAqe3HVm/Ps2c+u17BligMkZjZCA6EiXpoon8iRTer3iu40SQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ },
+ "node_modules/vite": {
+ "name": "@voidzero-dev/vite-plus-core",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@voidzero-dev/vite-plus-core/-/vite-plus-core-1.3.0.tgz",
+ "integrity": "sha512-Bk/LBwNrxoB8XbGUtGJE3r+U9P4puvdZ6UH36ekygE1J+on/ytwM/yBgQwBnvmX6/MVax+2xxj8wk0N/KkyNeA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/runtime": "=0.154.0",
+ "@oxc-project/types": "=0.154.0",
+ "lightningcss": "^1.33.0",
+ "postcss": "^8.5.29",
+ "yuku-parser": "0.19.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.18.0 || >=24.11.0"
+ },
+ "optionalDependencies": {
+ "@voidzero-dev/vite-plus-darwin-arm64": "1.3.0",
+ "@voidzero-dev/vite-plus-darwin-x64": "1.3.0",
+ "@voidzero-dev/vite-plus-linux-arm64-gnu": "1.3.0",
+ "@voidzero-dev/vite-plus-linux-arm64-musl": "1.3.0",
+ "@voidzero-dev/vite-plus-linux-x64-gnu": "1.3.0",
+ "@voidzero-dev/vite-plus-linux-x64-musl": "1.3.0",
+ "@voidzero-dev/vite-plus-win32-arm64-msvc": "1.3.0",
+ "@voidzero-dev/vite-plus-win32-x64-msvc": "1.3.0",
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@arethetypeswrong/core": "^0.18.1",
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "@typescript/native-preview": "*",
+ "@vitejs/devtools": "^0.7.1",
+ "@volar/typescript": "~2.4.0",
+ "@vue/language-core": "~3.2.0 || ~3.3.0",
+ "esbuild": "^0.27.0 || ^0.28.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "publint": "^0.3.8",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "typescript": "^5.0.0 || ^6.0.0 || ^7.0.0",
+ "unplugin-unused": ">=0.5.0",
+ "unrun": "*",
+ "vue-tsc": "~3.2.0 || ~3.3.0",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@arethetypeswrong/core": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@typescript/native-preview": {
+ "optional": true
+ },
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "@volar/typescript": {
+ "optional": true
+ },
+ "@vue/language-core": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "publint": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "typescript": {
+ "optional": true
+ },
+ "unplugin-unused": {
+ "optional": true
+ },
+ "unrun": {
+ "optional": true
+ },
+ "vue-tsc": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite-plus": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/vite-plus/-/vite-plus-1.3.0.tgz",
+ "integrity": "sha512-wZGsDeYfPcrCegqgY68pJJHGTpEZdsZvIMH2/mWXkGkBD72UY3M7z24Sv3ZeOL/FrqbbtyqBOfkKO6BvoQ8wMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.154.0",
+ "@oxlint/plugins": "=1.88.0",
+ "@vitest/browser": "5.0.5",
+ "@vitest/browser-preview": "5.0.5",
+ "@vitest/mocker": "5.0.5",
+ "@vitest/pretty-format": "5.0.5",
+ "@vitest/snapshot": "5.0.5",
+ "@vitest/spy": "5.0.5",
+ "@vitest/utils": "5.0.5",
+ "oxfmt": "=0.73.0",
+ "oxlint": "=1.88.0",
+ "oxlint-tsgolint": "=7.0.2004",
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.3.0",
+ "vitest": "5.0.5"
+ },
+ "bin": {
+ "vp": "bin/vp",
+ "vpr": "bin/vpr"
+ },
+ "engines": {
+ "node": "^22.18.0 || ^24.11.0 || >=26.0.0"
+ },
+ "optionalDependencies": {
+ "@voidzero-dev/vite-plus-darwin-arm64": "1.3.0",
+ "@voidzero-dev/vite-plus-darwin-x64": "1.3.0",
+ "@voidzero-dev/vite-plus-linux-arm64-gnu": "1.3.0",
+ "@voidzero-dev/vite-plus-linux-arm64-musl": "1.3.0",
+ "@voidzero-dev/vite-plus-linux-x64-gnu": "1.3.0",
+ "@voidzero-dev/vite-plus-linux-x64-musl": "1.3.0",
+ "@voidzero-dev/vite-plus-win32-arm64-msvc": "1.3.0",
+ "@voidzero-dev/vite-plus-win32-x64-msvc": "1.3.0"
+ },
+ "peerDependencies": {
+ "@vitest/browser-playwright": "5.0.5",
+ "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0",
+ "playwright": "*"
+ },
+ "peerDependenciesMeta": {
+ "@vitest/browser-playwright": {
+ "optional": true
+ },
+ "@vitest/browser-webdriverio": {
+ "optional": true
+ },
+ "playwright": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitest": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.5.tgz",
+ "integrity": "sha512-cPODOMF8YnkiiYtDdHo6n4wWmBrOBBbOIYH2d33M4l3CdNn72h+qMmO6uXffUN6A5AZFXNND/d+krS9mgkXRfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/chai": "^5.2.2",
+ "@vitest/mocker": "5.0.5",
+ "chai": "^6.3.0",
+ "es-module-lexer": "^2.3.2",
+ "expect-type": "^1.4.0",
+ "magic-string": "^1.4.3",
+ "obug": "^3.0.0",
+ "picomatch": "^4.0.7",
+ "std-env": "^4.3.0",
+ "tinybench": "^6.2.2",
+ "tinyexec": "^1.3.1",
+ "tinyglobby": "^0.2.17",
+ "why-is-node-running": "3.2.1"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
+ },
+ "engines": {
+ "node": "^22.12.0 || ^24.0.0 || >=26.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@opentelemetry/api": "^1.9.0",
+ "@types/node": "^22.0.0 || >=24.0.0",
+ "@vitest/browser-playwright": "5.0.5",
+ "@vitest/browser-preview": "5.0.5",
+ "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0",
+ "@vitest/coverage-istanbul": "5.0.5",
+ "@vitest/coverage-v8": "5.0.5",
+ "@vitest/ui": "5.0.5",
+ "happy-dom": "*",
+ "jsdom": "*",
+ "vite": "^6.4.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser-playwright": {
+ "optional": true
+ },
+ "@vitest/browser-preview": {
+ "optional": true
+ },
+ "@vitest/browser-webdriverio": {
+ "optional": true
+ },
+ "@vitest/coverage-istanbul": {
+ "optional": true
+ },
+ "@vitest/coverage-v8": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ },
+ "vite": {
+ "optional": false
+ }
+ }
+ },
+ "node_modules/website": {
+ "resolved": "apps/website",
+ "link": true
+ },
+ "node_modules/why-is-node-running": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.1.tgz",
+ "integrity": "sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "why-is-node-running": "cli.js"
+ },
+ "engines": {
+ "node": ">=20.11"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.22.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz",
+ "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/yaml": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz",
+ "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/yuku-core": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/yuku-core/-/yuku-core-0.19.0.tgz",
+ "integrity": "sha512-kYK9e1XdfirNhkipzW0wmMcSWcVF/CWnuugodfVYRCUwvoBefweL9HzB96OiKEhsx78V5WbUxbJqlizMX869Qg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@yuku-toolchain/types": "^0.19.0"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ },
+ "optionalDependencies": {
+ "@yuku-core/binding-android-arm64": "0.19.0",
+ "@yuku-core/binding-darwin-arm64": "0.19.0",
+ "@yuku-core/binding-darwin-x64": "0.19.0",
+ "@yuku-core/binding-freebsd-x64": "0.19.0",
+ "@yuku-core/binding-linux-arm-gnu": "0.19.0",
+ "@yuku-core/binding-linux-arm-musl": "0.19.0",
+ "@yuku-core/binding-linux-arm64-gnu": "0.19.0",
+ "@yuku-core/binding-linux-arm64-musl": "0.19.0",
+ "@yuku-core/binding-linux-x64-gnu": "0.19.0",
+ "@yuku-core/binding-linux-x64-musl": "0.19.0",
+ "@yuku-core/binding-win32-arm64": "0.19.0",
+ "@yuku-core/binding-win32-x64": "0.19.0"
+ }
+ },
+ "node_modules/yuku-parser": {
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/yuku-parser/-/yuku-parser-0.19.0.tgz",
+ "integrity": "sha512-XrBh9ZiQK5mJVRxZBAvD6LwRyAYrK3MFtH3+onyuxFL5hFD44EC3QOmIC1FjTj6H2MMwq46/NAI+NZxLZPZgxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@yuku-toolchain/types": "^0.19.0",
+ "yuku-core": "0.19.0"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "packages/utils": {
+ "version": "0.0.0",
+ "license": "MIT",
+ "devDependencies": {
+ "@types/node": "^26.6.5",
+ "bumpp": "^12.3.0",
+ "typescript": "^7.0.2",
+ "vite-plus": "^1.2.0"
+ }
+ }
+ }
+}
diff --git a/examples/javascript-ext/vp-demo/package.json b/examples/javascript-ext/vp-demo/package.json
new file mode 100644
index 000000000..9634e5cb4
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "vp-demo",
+ "version": "0.0.0",
+ "private": true,
+ "workspaces": [
+ "packages/*",
+ "apps/*",
+ "tools/*"
+ ],
+ "type": "module",
+ "scripts": {
+ "ready": "vp check && vp run -r test && vp run -r build",
+ "dev": "vp run website#dev"
+ },
+ "devDependencies": {
+ "vite-plus": "1.3.0"
+ },
+ "overrides": {
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.3.0"
+ },
+ "engines": {
+ "node": ">=22.18.0"
+ }
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/packages/utils/.gitignore b/examples/javascript-ext/vp-demo/packages/utils/.gitignore
new file mode 100644
index 000000000..753521168
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/packages/utils/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+dist
+*.log
+.DS_Store
diff --git a/examples/javascript-ext/vp-demo/packages/utils/README.md b/examples/javascript-ext/vp-demo/packages/utils/README.md
new file mode 100644
index 000000000..fcd91a7ed
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/packages/utils/README.md
@@ -0,0 +1,23 @@
+# vite-plus-starter
+
+A starter for creating a Vite Plus project.
+
+## Development
+
+- Install dependencies:
+
+```bash
+vp install
+```
+
+- Run the unit tests:
+
+```bash
+vp test
+```
+
+- Build the library:
+
+```bash
+vp pack
+```
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/packages/utils/package.json b/examples/javascript-ext/vp-demo/packages/utils/package.json
new file mode 100644
index 000000000..088dd0cf6
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/packages/utils/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "utils",
+ "version": "0.0.0",
+ "description": "A starter for creating a TypeScript package.",
+ "homepage": "https://github.com/author/library#readme",
+ "bugs": {
+ "url": "https://github.com/author/library/issues"
+ },
+ "license": "MIT",
+ "author": "Author Name ",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/author/library.git"
+ },
+ "files": [
+ "dist"
+ ],
+ "type": "module",
+ "exports": {
+ ".": "./dist/index.mjs",
+ "./package.json": "./package.json"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "scripts": {
+ "build": "vp pack",
+ "dev": "vp pack --watch",
+ "test": "vp test",
+ "check": "vp check",
+ "prepublishOnly": "vp run build"
+ },
+ "devDependencies": {
+ "@types/node": "^26.6.5",
+ "bumpp": "^12.3.0",
+ "typescript": "^7.0.2",
+ "vite-plus": "^1.2.0"
+ }
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/packages/utils/src/index.ts b/examples/javascript-ext/vp-demo/packages/utils/src/index.ts
new file mode 100644
index 000000000..64cfeb3fa
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/packages/utils/src/index.ts
@@ -0,0 +1,3 @@
+export function fn() {
+ return "Hello, Vite+!";
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/packages/utils/tests/index.test.ts b/examples/javascript-ext/vp-demo/packages/utils/tests/index.test.ts
new file mode 100644
index 000000000..354dcc564
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/packages/utils/tests/index.test.ts
@@ -0,0 +1,6 @@
+import { expect, test } from "vite-plus/test";
+import { fn } from "../src/index.ts";
+
+test("fn", () => {
+ expect(fn()).toBe("Hello, Vite+!");
+});
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/packages/utils/tsconfig.json b/examples/javascript-ext/vp-demo/packages/utils/tsconfig.json
new file mode 100644
index 000000000..423be8fb1
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/packages/utils/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "esnext",
+ "lib": ["es2023"],
+ "moduleDetection": "force",
+ "module": "nodenext",
+ "moduleResolution": "nodenext",
+ "resolveJsonModule": true,
+ "types": ["node"],
+ "strict": true,
+ "noUnusedLocals": true,
+ "declaration": true,
+ "noEmit": true,
+ "allowImportingTsExtensions": true,
+ "esModuleInterop": true,
+ "isolatedModules": true,
+ "verbatimModuleSyntax": true,
+ "skipLibCheck": true
+ }
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/packages/utils/vite.config.ts b/examples/javascript-ext/vp-demo/packages/utils/vite.config.ts
new file mode 100644
index 000000000..5ecec6aee
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/packages/utils/vite.config.ts
@@ -0,0 +1,16 @@
+import { defineConfig } from "vite-plus";
+
+export default defineConfig({
+ pack: {
+ deps: {
+ // tsdown <0.23 compatibility: resolve external dependency subpaths.
+ // Remove to preserve subpath imports as written (the new default).
+ // https://tsdown.dev/options/dependencies#deps-resolvedepsubpath
+ resolveDepSubpath: true,
+ },
+ dts: {
+ generator: "tsgo",
+ },
+ exports: true,
+ },
+});
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/tsconfig.json b/examples/javascript-ext/vp-demo/tsconfig.json
new file mode 100644
index 000000000..6ccfedcc6
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "noEmit": true,
+ "module": "nodenext",
+ "moduleResolution": "nodenext",
+ "allowImportingTsExtensions": true,
+ "esModuleInterop": true
+ }
+}
\ No newline at end of file
diff --git a/examples/javascript-ext/vp-demo/vite.config.ts b/examples/javascript-ext/vp-demo/vite.config.ts
new file mode 100644
index 000000000..173d44f2f
--- /dev/null
+++ b/examples/javascript-ext/vp-demo/vite.config.ts
@@ -0,0 +1,13 @@
+import { defineConfig } from "vite-plus";
+
+export default defineConfig({
+ fmt: {},
+ lint: {
+ jsPlugins: [{ name: "vite-plus", specifier: "vite-plus/oxlint-plugin" }],
+ rules: { "vite-plus/prefer-vite-plus-imports": "error" },
+ options: { typeAware: true, typeCheck: true },
+ },
+ run: {
+ cache: true,
+ },
+});
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/JavaScriptHostingExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/JavaScriptHostingExtensions.cs
index 823b1df18..d33864dc5 100644
--- a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/JavaScriptHostingExtensions.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/JavaScriptHostingExtensions.cs
@@ -1,251 +1,14 @@
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.JavaScript;
-using CommunityToolkit.Aspire.Utils;
using Microsoft.Extensions.Hosting;
-#pragma warning disable ASPIREATS001 // AspireExport is experimental
-
namespace Aspire.Hosting;
///
/// Provides extension methods for adding JavaScript applications to the distributed application builder.
///
-public static partial class JavaScriptHostingExtensions
+public static class JavaScriptHostingExtensions
{
- ///
- /// Adds an Nx monorepo workspace to the distributed application builder.
- ///
- /// The to add the resource to.
- /// The name of the Nx workspace resource.
- /// The working directory of the Nx workspace. If not specified, it will be set to a path that is a sibling of the AppHost directory using the as the folder.
- /// A reference to the .
- [AspireExport]
- public static IResourceBuilder AddNxApp(this IDistributedApplicationBuilder builder, [ResourceName] string name, string? workingDirectory = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(name);
-
- string wd = workingDirectory ?? Path.Combine("..", name);
- workingDirectory = PathNormalizer.NormalizePathForCurrentPlatform(Path.Combine(builder.AppHostDirectory, wd));
-
- var resource = new NxResource(name, workingDirectory);
- return builder.AddResource(resource)
- .WithIconName("CodeJsRectangle")
- .WithInitialState(new CustomResourceSnapshot { Properties = [], ResourceType = "NxWorkspace", State = KnownResourceStates.Running });
- }
-
- ///
- /// Adds a Turborepo monorepo workspace to the distributed application builder.
- ///
- /// The to add the resource to.
- /// The name of the Turborepo workspace resource.
- /// The working directory of the Turborepo workspace. If not specified, it will be set to a path that is a sibling of the AppHost directory using the as the folder.
- /// A reference to the .
- [AspireExport]
- public static IResourceBuilder AddTurborepoApp(this IDistributedApplicationBuilder builder, [ResourceName] string name, string? workingDirectory = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(name);
-
- string wd = workingDirectory ?? Path.Combine("..", name);
- workingDirectory = PathNormalizer.NormalizePathForCurrentPlatform(Path.Combine(builder.AppHostDirectory, wd));
-
- var resource = new TurborepoResource(name, workingDirectory);
- return builder.AddResource(resource)
- .WithIconName("CodeJsRectangle")
- .WithInitialState(new CustomResourceSnapshot { Properties = [], ResourceType = "TurborepoWorkspace", State = KnownResourceStates.Running });
- }
-
- ///
- /// Adds an individual app to an Nx workspace.
- ///
- /// The Nx workspace resource builder.
- /// The name of the app resource.
- /// The Nx app name to run. If not specified, uses the .
- /// A function to configure the app resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The configure callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder AddApp(this IResourceBuilder builder, [ResourceName] string name, string? appName = null, Func, IResourceBuilder>? configure = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(name);
-
- appName ??= name;
-
- var resource = new NxAppResource(name, builder.Resource.WorkingDirectory, appName);
-
- var rb = builder.ApplicationBuilder.AddResource(resource)
- .WithNodeDefaults()
- .WithIconName("CodeJsRectangle")
- .WithArgs("serve", appName)
- .WithParentRelationship(builder.Resource);
-
- // If the workspace is configured to use a package manager, bring that annotation forward
- if (builder.Resource.TryGetLastAnnotation(out var executionAnnotation))
- {
- rb.WithCommand(executionAnnotation.ExecutableName switch
- {
- "npm" => "npx",
- "yarn" => "yarn",
- "pnpm" => "pnpx",
- "bun" => "bunx",
- _ => executionAnnotation.ExecutableName
- })
- .WithArgs(context =>
- {
- context.Args.Insert(0, executionAnnotation.ScriptCommand ?? "nx");
- });
- }
-
- // If the workspace has an installer annotation, wait for the installer to complete
- if (builder.Resource.TryGetLastAnnotation(out var installerAnnotation))
- {
- rb.WaitForCompletion(builder.ApplicationBuilder.CreateResourceBuilder(installerAnnotation.Resource));
- }
-
- configure?.Invoke(rb);
-
- return rb;
- }
-
- [AspireExport(MethodName = "addApp")]
- internal static IResourceBuilder AddNxWorkspaceApp(this IResourceBuilder builder, [ResourceName] string name, string? appName = null) =>
- builder.AddApp(name, appName, configure: null);
-
- ///
- /// Adds an individual app to a Turborepo workspace.
- ///
- /// The Turborepo workspace resource builder.
- /// The name of the app resource.
- /// The Turborepo filter to use. If not specified, uses the .
- /// A function to configure the app resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The configure callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder AddApp(this IResourceBuilder builder, [ResourceName] string name, string? filter = null, Func, IResourceBuilder>? configure = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
- ArgumentNullException.ThrowIfNull(name);
-
- filter ??= name;
-
- var resource = new TurborepoAppResource(name, builder.Resource.WorkingDirectory, filter);
-
- var rb = builder.ApplicationBuilder.AddResource(resource)
- .WithNodeDefaults()
- .WithIconName("CodeJsRectangle")
- .WithArgs("run", "dev", "--filter", filter)
- .WithParentRelationship(builder.Resource);
-
- // If the workspace is configured to use a package manager, bring that annotation forward
- if (builder.Resource.TryGetLastAnnotation(out var executionAnnotation))
- {
- rb.WithCommand(executionAnnotation.ExecutableName switch
- {
- "npm" => "npx",
- "yarn" => "yarn",
- "pnpm" => "pnpx",
- "bun" => "bunx",
- _ => executionAnnotation.ExecutableName
- })
- .WithArgs(context =>
- {
- context.Args.Insert(0, executionAnnotation.ScriptCommand ?? "nx");
- });
- }
-
- // If the workspace has an installer annotation, wait for the installer to complete
- if (builder.Resource.TryGetLastAnnotation(out var installerAnnotation))
- {
- rb.WaitForCompletion(builder.ApplicationBuilder.CreateResourceBuilder(installerAnnotation.Resource));
- }
-
- configure?.Invoke(rb);
-
- return rb;
- }
-
- [AspireExport(MethodName = "addApp")]
- internal static IResourceBuilder AddTurborepoWorkspaceApp(this IResourceBuilder builder, [ResourceName] string name, string? filter = null) =>
- builder.AddApp(name, filter, configure: null);
-
- ///
- /// Configures the Nx workspace to use the specified JavaScript package manager when starting apps.
- ///
- /// The Nx workspace resource builder.
- /// The package manager to use. If none is provided it will attempt to use the installer annotation's resource command.
- /// A reference to the .
- /// Thrown if the Nx workspace is already configured to use a different package manager.
- [AspireExport("withNxPackageManagerLaunch", MethodName = "withPackageManagerLaunch")]
- public static IResourceBuilder WithPackageManagerLaunch(this IResourceBuilder builder, string? packageManager = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- if (builder.Resource.TryGetLastAnnotation(out var existingExecution))
- {
- if (packageManager is null || existingExecution.ExecutableName == packageManager)
- {
- // already configured with execution annotation
- return builder;
- }
- throw new InvalidOperationException($"The Nx workspace '{builder.Resource.Name}' is already configured to run with the '{existingExecution.ExecutableName}' package manager.");
- }
-
- // If no explicit package manager provided, try to infer from configured annotation
- if (packageManager is null)
- {
- if (builder.Resource.TryGetLastAnnotation(out var configured))
- {
- packageManager = configured.PackageManager;
- }
- else
- {
- throw new InvalidOperationException($"The Nx workspace '{builder.Resource.Name}' is not configured with a package manager. Call WithNpm/WithYarn/WithPnpm/WithBun first, or provide an explicit package manager.");
- }
- }
-
- return builder.WithAnnotation(new JavaScriptPackageManagerAnnotation(packageManager, runScriptCommand: "nx"));
- }
-
- ///
- /// Configures the Turborepo workspace to use the specified JavaScript package manager when starting apps.
- ///
- /// The Turborepo workspace resource builder.
- /// The package manager to use. If none is provided it will attempt to use the installer annotation's resource command.
- /// A reference to the .
- /// Thrown if the Turborepo workspace is already configured to use a different package manager.
- [AspireExport("withTurborepoPackageManagerLaunch", MethodName = "withPackageManagerLaunch")]
- public static IResourceBuilder WithPackageManagerLaunch(this IResourceBuilder builder, string? packageManager = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- if (builder.Resource.TryGetLastAnnotation(out var existingExecution))
- {
- if (packageManager is null || existingExecution.ExecutableName == packageManager)
- {
- // already configured with execution annotation
- return builder;
- }
- throw new InvalidOperationException($"The Turborepo workspace '{builder.Resource.Name}' is already configured to run with the '{existingExecution.ExecutableName}' package manager.");
- }
-
- // If no explicit package manager provided, try to infer from configured annotation
- if (packageManager is null)
- {
- if (builder.Resource.TryGetLastAnnotation(out var configured))
- {
- packageManager = configured.PackageManager;
- }
- else
- {
- throw new InvalidOperationException($"The Turborepo workspace '{builder.Resource.Name}' is not configured with a package manager. Call WithNpm/WithYarn/WithPnpm/WithBun first, or provide an explicit package manager.");
- }
- }
-
- return builder.WithAnnotation(new JavaScriptPackageManagerAnnotation(packageManager, runScriptCommand: "turbo"));
- }
-
///
/// Maps the endpoint port for the to the appropriate command line argument.
///
@@ -278,176 +41,8 @@ public static IResourceBuilder WithMappedEndpointPort(this
});
}
- ///
- /// Configures the Nx workspace to use npm as the package manager and optionally installs packages before apps start.
- ///
- /// The Nx workspace resource builder.
- /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
- /// A function to configure the installer resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder WithNpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- AddMonorepoInstaller(builder, "npm", install, configureInstaller);
- return builder;
- }
-
- [AspireExport(MethodName = "withNpm")]
- internal static IResourceBuilder WithNxNpm(this IResourceBuilder builder, bool install = false) =>
- builder.WithNpm(install, configureInstaller: null);
-
- ///
- /// Configures the Nx workspace to use yarn as the package manager and optionally installs packages before apps start.
- ///
- /// The Nx workspace resource builder.
- /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
- /// A function to configure the installer resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder WithYarn(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- AddMonorepoInstaller(builder, "yarn", install, configureInstaller);
- return builder;
- }
-
- [AspireExport(MethodName = "withYarn")]
- internal static IResourceBuilder WithNxYarn(this IResourceBuilder builder, bool install = false) =>
- builder.WithYarn(install, configureInstaller: null);
-
- ///
- /// Configures the Nx workspace to use pnpm as the package manager and optionally installs packages before apps start.
- ///
- /// The Nx workspace resource builder.
- /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
- /// A function to configure the installer resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder WithPnpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- AddMonorepoInstaller(builder, "pnpm", install, configureInstaller);
- return builder;
- }
-
- [AspireExport(MethodName = "withPnpm")]
- internal static IResourceBuilder WithNxPnpm(this IResourceBuilder builder, bool install = false) =>
- builder.WithPnpm(install, configureInstaller: null);
-
- ///
- /// Configures the Nx workspace to use bun as the package manager and optionally installs packages before apps start.
- ///
- /// The Nx workspace resource builder.
- /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
- /// A function to configure the installer resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder WithBun(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- AddMonorepoInstaller(builder, "bun", install, configureInstaller);
- return builder;
- }
-
- [AspireExport(MethodName = "withBun")]
- internal static IResourceBuilder WithNxBun(this IResourceBuilder builder, bool install = false) =>
- builder.WithBun(install, configureInstaller: null);
-
- ///
- /// Configures the Turborepo workspace to use npm as the package manager and optionally installs packages before apps start.
- ///
- /// The Turborepo workspace resource builder.
- /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
- /// A function to configure the installer resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder WithNpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- AddMonorepoInstaller(builder, "npm", install, configureInstaller);
- return builder;
- }
-
- [AspireExport(MethodName = "withNpm")]
- internal static IResourceBuilder WithTurborepoNpm(this IResourceBuilder builder, bool install = false) =>
- builder.WithNpm(install, configureInstaller: null);
-
- ///
- /// Configures the Turborepo workspace to use yarn as the package manager and optionally installs packages before apps start.
- ///
- /// The Turborepo workspace resource builder.
- /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
- /// A function to configure the installer resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder WithYarn(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- AddMonorepoInstaller(builder, "yarn", install, configureInstaller);
- return builder;
- }
-
- [AspireExport(MethodName = "withYarn")]
- internal static IResourceBuilder WithTurborepoYarn(this IResourceBuilder builder, bool install = false) =>
- builder.WithYarn(install, configureInstaller: null);
-
- ///
- /// Configures the Turborepo workspace to use pnpm as the package manager and optionally installs packages before apps start.
- ///
- /// The Turborepo workspace resource builder.
- /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
- /// A function to configure the installer resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder WithPnpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- AddMonorepoInstaller(builder, "pnpm", install, configureInstaller);
- return builder;
- }
-
- [AspireExport(MethodName = "withPnpm")]
- internal static IResourceBuilder WithTurborepoPnpm(this IResourceBuilder builder, bool install = false) =>
- builder.WithPnpm(install, configureInstaller: null);
-
- ///
- /// Configures the Turborepo workspace to use bun as the package manager and optionally installs packages before apps start.
- ///
- /// The Turborepo workspace resource builder.
- /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
- /// A function to configure the installer resource builder.
- /// A reference to the .
- /// This overload is not available in polyglot app hosts. Use instead.
- [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
- public static IResourceBuilder WithBun(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
- {
- ArgumentNullException.ThrowIfNull(builder);
-
- AddMonorepoInstaller(builder, "bun", install, configureInstaller);
- return builder;
- }
-
- [AspireExport(MethodName = "withBun")]
- internal static IResourceBuilder WithTurborepoBun(this IResourceBuilder builder, bool install = false) =>
- builder.WithBun(install, configureInstaller: null);
-
- private static void AddMonorepoInstaller(
- IResourceBuilder builder,
+ internal static void AddMonorepoInstaller(
+ this IResourceBuilder builder,
string packageManager,
bool install,
Action>? configureInstaller)
@@ -464,6 +59,7 @@ private static void AddMonorepoInstaller(
{
NxResource nx => nx.WorkingDirectory,
TurborepoResource turbo => turbo.WorkingDirectory,
+ VitePlusResource vitePlus => vitePlus.WorkingDirectory,
_ => throw new InvalidOperationException($"Unsupported resource type: {builder.Resource.GetType().Name}")
};
@@ -493,7 +89,7 @@ private static void AddMonorepoInstaller(
}
}
- private static IResourceBuilder WithNodeDefaults(this IResourceBuilder builder) where TResource : JavaScriptAppResource =>
+ internal static IResourceBuilder WithNodeDefaults(this IResourceBuilder builder) where TResource : JavaScriptAppResource =>
builder.WithOtlpExporter()
.WithEnvironment("NODE_ENV", builder.ApplicationBuilder.Environment.IsDevelopment() ? "development" : "production")
.WithCertificateTrustConfiguration((ctx) =>
@@ -510,5 +106,3 @@ private static IResourceBuilder WithNodeDefaults(this IRes
return Task.CompletedTask;
});
}
-
-#pragma warning restore ASPIREATS001 // AspireExport is experimental
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/MONOREPO.md b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/MONOREPO.md
index b12c2b63e..ef951c88b 100644
--- a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/MONOREPO.md
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/MONOREPO.md
@@ -1,6 +1,6 @@
# Frontend Monorepo Support
-This extension now provides built-in support for frontend monorepos using [Nx](https://nx.dev) and [Turborepo](https://turborepo.com).
+This extension now provides built-in support for frontend monorepos using [Nx](https://nx.dev), [Turborepo](https://turborepo.com), and [Vite+](https://viteplus.dev).
## The Problem
@@ -44,9 +44,21 @@ var app2 = turbo.AddApp("app2", filter: "custom-filter"); // Custom filter
var app3 = turbo.AddApp("app3");
```
+### Vite+ Support
+
+```csharp
+var vitePlus = builder.AddVitePlusApp("vp-demo", workingDirectory: "../frontend")
+ .WithNpm(install: true); // Single shared installer
+
+var app1 = vitePlus.AddApp("website"); // Defaults to the apps/website directory
+var app2 = vitePlus.AddApp("docs", directory: "packages/docs"); // Custom directory
+```
+
+Vite+ targets packages with the global `-C` flag (`vp -C apps/web dev`), which runs the command as if you had `cd`'d into the package first. This is different from passing a directory as a positional argument (`vp dev apps/web`), which only sets Vite's `root` option without changing the working directory.
+
## Package Managers
-Both Nx and Turborepo support yarn, pnpm, and bun package managers:
+Nx, Turborepo, and Vite+ support yarn, pnpm, and bun package managers:
- `.WithYarn(install: true)` - uses yarn
- `.WithPnpm(install: true)` - uses pnpm
@@ -76,9 +88,9 @@ nxDefault.AddApp("app1"); // Runs: nx serve app1 (no package manager prefix)
**Command Generation Examples:**
-- `WithPackageManagerLaunch("yarn")` → `yarn nx serve app1` or `yarn turbo run dev --filter app1`
-- `WithPackageManagerLaunch("pnpm")` → `pnpm nx serve app1` or `pnpm turbo run dev --filter app1`
-- No `WithPackageManagerLaunch()` → `nx serve app1` or `turbo run dev --filter app1`
+- `WithPackageManagerLaunch("yarn")` → `yarn nx serve app1`, `yarn turbo run dev --filter app1`, or `yarn vp -C apps/web dev`
+- `WithPackageManagerLaunch("pnpm")` → `pnpm nx serve app1`, `pnpm turbo run dev --filter app1`, or `pnpm vp -C apps/web dev`
+- No `WithPackageManagerLaunch()` → `nx serve app1`, `turbo run dev --filter app1`, or `vp -C apps/web dev`
## How It Works
@@ -98,6 +110,11 @@ nxDefault.AddApp("app1"); // Runs: nx serve app1 (no package manager prefix)
- Command: `turbo run dev --filter {filter}`
- The `filter` parameter controls which packages Turborepo builds/serves
+### Vite+ Apps
+
+- Command: `vp -C {directory} dev`
+- The `directory` parameter is passed to the global `-C` flag so the built-in Vite dev server runs with the package as its working directory. It defaults to `apps/{name}` when not specified
+
## Migration
If you're currently using the workaround pattern:
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxAppResource.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxAppResource.cs
index eff0932d5..0126adcaa 100644
--- a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxAppResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxAppResource.cs
@@ -9,7 +9,7 @@ namespace Aspire.Hosting.ApplicationModel;
/// The working directory of the application.
/// The Nx app name to run (used in 'nx serve {appName}').
/// The command to run (default is 'nx').
-public class NxAppResource(string name, string workingDirectory, string appName, string command = "nx")
+public class NxAppResource(string name, string workingDirectory, string appName, string command = NxHostingExtensions.CliName)
: JavaScriptAppResource(name, command, workingDirectory)
{
///
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxHostingExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxHostingExtensions.cs
new file mode 100644
index 000000000..45254f00f
--- /dev/null
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxHostingExtensions.cs
@@ -0,0 +1,214 @@
+using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.JavaScript;
+using CommunityToolkit.Aspire.Utils;
+
+namespace Aspire.Hosting;
+
+///
+/// Provides extension methods for adding Nx applications to the distributed application builder.
+///
+public static class NxHostingExtensions
+{
+ internal const string CliName = "nx";
+
+ ///
+ /// Adds an Nx monorepo workspace to the distributed application builder.
+ ///
+ /// The to add the resource to.
+ /// The name of the Nx workspace resource.
+ /// The working directory of the Nx workspace. If not specified, it will be set to a path that is a sibling of the AppHost directory using the as the folder.
+ /// A reference to the .
+ [AspireExport]
+ public static IResourceBuilder AddNxApp(this IDistributedApplicationBuilder builder, [ResourceName] string name, string? workingDirectory = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(name);
+
+ string wd = workingDirectory ?? Path.Combine("..", name);
+ workingDirectory = Path.Combine(builder.AppHostDirectory, wd).NormalizePathForCurrentPlatform();
+
+ var resource = new NxResource(name, workingDirectory);
+ return builder.AddResource(resource)
+ .WithIconName("CodeJsRectangle")
+ .WithInitialState(new CustomResourceSnapshot { Properties = [], ResourceType = "NxWorkspace", State = KnownResourceStates.Running });
+ }
+
+ ///
+ /// Adds an individual app to an Nx workspace.
+ ///
+ /// The Nx workspace resource builder.
+ /// The name of the app resource.
+ /// The Nx app name to run. If not specified, uses the .
+ /// A function to configure the app resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The configure callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder AddApp(this IResourceBuilder builder, [ResourceName] string name, string? appName = null, Func, IResourceBuilder>? configure = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(name);
+
+ appName ??= name;
+
+ var resource = new NxAppResource(name, builder.Resource.WorkingDirectory, appName);
+
+ var rb = builder.ApplicationBuilder.AddResource(resource)
+ .WithNodeDefaults()
+ .WithIconName("CodeJsRectangle")
+ .WithArgs("serve", appName)
+ .WithParentRelationship(builder.Resource);
+
+ // If the workspace is configured to use a package manager, bring that annotation forward
+ if (builder.Resource.TryGetLastAnnotation(out var executionAnnotation))
+ {
+ rb.WithCommand(executionAnnotation.ExecutableName switch
+ {
+ "npm" => "npx",
+ "yarn" => "yarn",
+ "pnpm" => "pnpx",
+ "bun" => "bunx",
+ _ => executionAnnotation.ExecutableName
+ })
+ .WithArgs(context =>
+ {
+ context.Args.Insert(0, executionAnnotation.ScriptCommand ?? CliName);
+ });
+ }
+
+ // If the workspace has an installer annotation, wait for the installer to complete
+ if (builder.Resource.TryGetLastAnnotation(out var installerAnnotation))
+ {
+ rb.WaitForCompletion(builder.ApplicationBuilder.CreateResourceBuilder(installerAnnotation.Resource));
+ }
+
+ configure?.Invoke(rb);
+
+ return rb;
+ }
+
+ [AspireExport(MethodName = "addApp")]
+ internal static IResourceBuilder AddNxWorkspaceApp(this IResourceBuilder builder, [ResourceName] string name, string? appName = null) =>
+ builder.AddApp(name, appName, configure: null);
+
+ ///
+ /// Configures the Nx workspace to use the specified JavaScript package manager when starting apps.
+ ///
+ /// The Nx workspace resource builder.
+ /// The package manager to use. If none is provided it will attempt to use the installer annotation's resource command.
+ /// A reference to the .
+ /// Thrown if the Nx workspace is already configured to use a different package manager.
+ [AspireExport("withNxPackageManagerLaunch", MethodName = "withPackageManagerLaunch")]
+ public static IResourceBuilder WithPackageManagerLaunch(this IResourceBuilder builder, string? packageManager = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ if (builder.Resource.TryGetLastAnnotation(out var existingExecution))
+ {
+ if (packageManager is null || existingExecution.ExecutableName == packageManager)
+ {
+ // already configured with execution annotation
+ return builder;
+ }
+ throw new InvalidOperationException($"The Nx workspace '{builder.Resource.Name}' is already configured to run with the '{existingExecution.ExecutableName}' package manager.");
+ }
+
+ // If no explicit package manager provided, try to infer from configured annotation
+ if (packageManager is null)
+ {
+ if (builder.Resource.TryGetLastAnnotation(out var configured))
+ {
+ packageManager = configured.PackageManager;
+ }
+ else
+ {
+ throw new InvalidOperationException($"The Nx workspace '{builder.Resource.Name}' is not configured with a package manager. Call WithNpm/WithYarn/WithPnpm/WithBun first, or provide an explicit package manager.");
+ }
+ }
+
+ return builder.WithAnnotation(new JavaScriptPackageManagerAnnotation(packageManager, runScriptCommand: CliName));
+ }
+
+ ///
+ /// Configures the Nx workspace to use npm as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Nx workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithNpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("npm", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withNpm")]
+ internal static IResourceBuilder WithNxNpm(this IResourceBuilder builder, bool install = false) =>
+ builder.WithNpm(install, configureInstaller: null);
+
+ ///
+ /// Configures the Nx workspace to use yarn as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Nx workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithYarn(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("yarn", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withYarn")]
+ internal static IResourceBuilder WithNxYarn(this IResourceBuilder builder, bool install = false) =>
+ builder.WithYarn(install, configureInstaller: null);
+
+ ///
+ /// Configures the Nx workspace to use pnpm as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Nx workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithPnpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("pnpm", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withPnpm")]
+ internal static IResourceBuilder WithNxPnpm(this IResourceBuilder builder, bool install = false) =>
+ builder.WithPnpm(install, configureInstaller: null);
+
+ ///
+ /// Configures the Nx workspace to use bun as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Nx workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithBun(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("bun", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withBun")]
+ internal static IResourceBuilder WithNxBun(this IResourceBuilder builder, bool install = false) =>
+ builder.WithBun(install, configureInstaller: null);
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxResource.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxResource.cs
index 321bbef3c..9a4620e12 100644
--- a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/NxResource.cs
@@ -1,5 +1,3 @@
-using Aspire.Hosting.ApplicationModel;
-
namespace Aspire.Hosting.ApplicationModel;
///
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/README.md b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/README.md
index 0dbd2582a..009681e6d 100644
--- a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/README.md
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/README.md
@@ -1,6 +1,6 @@
# CommunityToolkit.Aspire.Hosting.JavaScript.Extensions library
-This integration contains extensions for the [Node.js hosting package](https://nuget.org/packages/Aspire.Hosting.JavaScript) for Aspire, including support for frontend monorepos (Nx, Turborepo).
+This integration contains extensions for the [Node.js hosting package](https://nuget.org/packages/Aspire.Hosting.JavaScript) for Aspire, including support for frontend monorepos (Nx, Turborepo, Vite+).
## Getting Started
@@ -31,6 +31,14 @@ var turbo = builder.AddTurborepoApp("turbo", workingDirectory: "../frontend")
var turboApp1 = turbo.AddApp("app1");
var turboApp2 = turbo.AddApp("app2", filter: "custom-filter");
+
+// Vite+ workspace
+var vitePlus = builder.AddVitePlusApp("vp-demo")
+ .WithNpm(install: true)
+ .WithPackageManagerLaunch();
+
+vitePlus.AddApp("website"); // Runs: npx vp -C apps/website dev
+vitePlus.AddApp("docs", directory: "packages/docs");
```
See [MONOREPO.md](./MONOREPO.md) for detailed documentation on monorepo support.
@@ -59,8 +67,11 @@ var bunRepo = builder.AddTurborepoApp("bun-repo", workingDirectory: "../frontend
// Nx with yarn: yarn nx serve app1
// Turborepo with pnpm: pnpm turbo run dev --filter app1
// Turborepo with bun: bunx turbo run dev --filter app1
+// Vite+ with npm: npx vp -C apps/website dev
```
+> **Note**: Vite's dev server moves to the next free port if the assigned one is taken. When mapping an endpoint, consider adding `--strictPort` via `WithArgs` so the app fails fast instead of drifting away from the mapped port.
+
### Package installation with custom flags
You can pass additional flags to package managers during installation:
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoAppResource.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoAppResource.cs
index ae9194a46..8073a85b7 100644
--- a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoAppResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoAppResource.cs
@@ -9,7 +9,7 @@ namespace Aspire.Hosting.ApplicationModel;
/// The working directory of the application.
/// The Turborepo filter to use (used in 'turbo run dev --filter={filter}').
/// The command to run (default is 'turbo').
-public class TurborepoAppResource(string name, string workingDirectory, string filter, string command = "turbo")
+public class TurborepoAppResource(string name, string workingDirectory, string filter, string command = TurborepoHostingExtensions.CliName)
: JavaScriptAppResource(name, command, workingDirectory)
{
///
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoHostingExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoHostingExtensions.cs
new file mode 100644
index 000000000..6cda76955
--- /dev/null
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoHostingExtensions.cs
@@ -0,0 +1,214 @@
+using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.JavaScript;
+using CommunityToolkit.Aspire.Utils;
+
+namespace Aspire.Hosting;
+
+///
+/// Provides extension methods for adding Turborepo applications to the distributed application builder.
+///
+public static class TurborepoHostingExtensions
+{
+ internal const string CliName = "turbo";
+
+ ///
+ /// Adds a Turborepo monorepo workspace to the distributed application builder.
+ ///
+ /// The to add the resource to.
+ /// The name of the Turborepo workspace resource.
+ /// The working directory of the Turborepo workspace. If not specified, it will be set to a path that is a sibling of the AppHost directory using the as the folder.
+ /// A reference to the .
+ [AspireExport]
+ public static IResourceBuilder AddTurborepoApp(this IDistributedApplicationBuilder builder, [ResourceName] string name, string? workingDirectory = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(name);
+
+ string wd = workingDirectory ?? Path.Combine("..", name);
+ workingDirectory = Path.Combine(builder.AppHostDirectory, wd).NormalizePathForCurrentPlatform();
+
+ var resource = new TurborepoResource(name, workingDirectory);
+ return builder.AddResource(resource)
+ .WithIconName("CodeJsRectangle")
+ .WithInitialState(new CustomResourceSnapshot { Properties = [], ResourceType = "TurborepoWorkspace", State = KnownResourceStates.Running });
+ }
+
+ ///
+ /// Adds an individual app to a Turborepo workspace.
+ ///
+ /// The Turborepo workspace resource builder.
+ /// The name of the app resource.
+ /// The Turborepo filter to use. If not specified, uses the .
+ /// A function to configure the app resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The configure callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder AddApp(this IResourceBuilder builder, [ResourceName] string name, string? filter = null, Func, IResourceBuilder>? configure = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(name);
+
+ filter ??= name;
+
+ var resource = new TurborepoAppResource(name, builder.Resource.WorkingDirectory, filter);
+
+ var rb = builder.ApplicationBuilder.AddResource(resource)
+ .WithNodeDefaults()
+ .WithIconName("CodeJsRectangle")
+ .WithArgs("run", "dev", "--filter", filter)
+ .WithParentRelationship(builder.Resource);
+
+ // If the workspace is configured to use a package manager, bring that annotation forward
+ if (builder.Resource.TryGetLastAnnotation(out var executionAnnotation))
+ {
+ rb.WithCommand(executionAnnotation.ExecutableName switch
+ {
+ "npm" => "npx",
+ "yarn" => "yarn",
+ "pnpm" => "pnpx",
+ "bun" => "bunx",
+ _ => executionAnnotation.ExecutableName
+ })
+ .WithArgs(context =>
+ {
+ context.Args.Insert(0, executionAnnotation.ScriptCommand ?? CliName);
+ });
+ }
+
+ // If the workspace has an installer annotation, wait for the installer to complete
+ if (builder.Resource.TryGetLastAnnotation(out var installerAnnotation))
+ {
+ rb.WaitForCompletion(builder.ApplicationBuilder.CreateResourceBuilder(installerAnnotation.Resource));
+ }
+
+ configure?.Invoke(rb);
+
+ return rb;
+ }
+
+ [AspireExport(MethodName = "addApp")]
+ internal static IResourceBuilder AddTurborepoWorkspaceApp(this IResourceBuilder builder, [ResourceName] string name, string? filter = null) =>
+ builder.AddApp(name, filter, configure: null);
+
+ ///
+ /// Configures the Turborepo workspace to use the specified JavaScript package manager when starting apps.
+ ///
+ /// The Turborepo workspace resource builder.
+ /// The package manager to use. If none is provided it will attempt to use the installer annotation's resource command.
+ /// A reference to the .
+ /// Thrown if the Turborepo workspace is already configured to use a different package manager.
+ [AspireExport("withTurborepoPackageManagerLaunch", MethodName = "withPackageManagerLaunch")]
+ public static IResourceBuilder WithPackageManagerLaunch(this IResourceBuilder builder, string? packageManager = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ if (builder.Resource.TryGetLastAnnotation(out var existingExecution))
+ {
+ if (packageManager is null || existingExecution.ExecutableName == packageManager)
+ {
+ // already configured with execution annotation
+ return builder;
+ }
+ throw new InvalidOperationException($"The Turborepo workspace '{builder.Resource.Name}' is already configured to run with the '{existingExecution.ExecutableName}' package manager.");
+ }
+
+ // If no explicit package manager provided, try to infer from configured annotation
+ if (packageManager is null)
+ {
+ if (builder.Resource.TryGetLastAnnotation(out var configured))
+ {
+ packageManager = configured.PackageManager;
+ }
+ else
+ {
+ throw new InvalidOperationException($"The Turborepo workspace '{builder.Resource.Name}' is not configured with a package manager. Call WithNpm/WithYarn/WithPnpm/WithBun first, or provide an explicit package manager.");
+ }
+ }
+
+ return builder.WithAnnotation(new JavaScriptPackageManagerAnnotation(packageManager, runScriptCommand: CliName));
+ }
+
+ ///
+ /// Configures the Turborepo workspace to use npm as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Turborepo workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithNpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("npm", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withNpm")]
+ internal static IResourceBuilder WithTurborepoNpm(this IResourceBuilder builder, bool install = false) =>
+ builder.WithNpm(install, configureInstaller: null);
+
+ ///
+ /// Configures the Turborepo workspace to use yarn as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Turborepo workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithYarn(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("yarn", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withYarn")]
+ internal static IResourceBuilder WithTurborepoYarn(this IResourceBuilder builder, bool install = false) =>
+ builder.WithYarn(install, configureInstaller: null);
+
+ ///
+ /// Configures the Turborepo workspace to use pnpm as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Turborepo workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithPnpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("pnpm", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withPnpm")]
+ internal static IResourceBuilder WithTurborepoPnpm(this IResourceBuilder builder, bool install = false) =>
+ builder.WithPnpm(install, configureInstaller: null);
+
+ ///
+ /// Configures the Turborepo workspace to use bun as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Turborepo workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithBun(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("bun", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withBun")]
+ internal static IResourceBuilder WithTurborepoBun(this IResourceBuilder builder, bool install = false) =>
+ builder.WithBun(install, configureInstaller: null);
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoResource.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoResource.cs
index b6baabd06..e00863dd4 100644
--- a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoResource.cs
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/TurborepoResource.cs
@@ -1,5 +1,3 @@
-using Aspire.Hosting.ApplicationModel;
-
namespace Aspire.Hosting.ApplicationModel;
///
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusAppResource.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusAppResource.cs
new file mode 100644
index 000000000..2d0066f6c
--- /dev/null
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusAppResource.cs
@@ -0,0 +1,19 @@
+using Aspire.Hosting.JavaScript;
+
+namespace Aspire.Hosting.ApplicationModel;
+
+///
+/// A resource that represents a Node.js application running under Vite+.
+///
+/// The name of the resource.
+/// The working directory of the Vite+ workspace.
+/// The directory of the app within the workspace, relative to the workspace root. It is passed to vp -C.
+/// The command to run (default is 'vp').
+public class VitePlusAppResource(string name, string workingDirectory, string directory, string command = VitePlusHostingExtensions.CliName)
+ : JavaScriptAppResource(name, command, workingDirectory)
+{
+ ///
+ /// Gets the directory of the app within the Vite+ workspace, relative to the workspace root.
+ ///
+ public string Directory { get; } = directory;
+}
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusHostingExtensions.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusHostingExtensions.cs
new file mode 100644
index 000000000..f0f9ba734
--- /dev/null
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusHostingExtensions.cs
@@ -0,0 +1,214 @@
+using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.JavaScript;
+using CommunityToolkit.Aspire.Utils;
+
+namespace Aspire.Hosting;
+
+///
+/// Provides extension methods for adding Vite+ applications to the distributed application builder.
+///
+public static class VitePlusHostingExtensions
+{
+ internal const string CliName = "vp";
+
+ ///
+ /// Adds a Vite+ monorepo workspace to the distributed application builder.
+ ///
+ /// The to add the resource to.
+ /// The name of the Vite+ workspace resource.
+ /// The working directory of the Vite+ workspace. If not specified, it will be set to a path that is a sibling of the AppHost directory using the as the folder.
+ /// A reference to the .
+ [AspireExport]
+ public static IResourceBuilder AddVitePlusApp(this IDistributedApplicationBuilder builder, [ResourceName] string name, string? workingDirectory = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(name);
+
+ string wd = workingDirectory ?? Path.Combine("..", name);
+ workingDirectory = Path.Combine(builder.AppHostDirectory, wd).NormalizePathForCurrentPlatform();
+
+ var resource = new VitePlusResource(name, workingDirectory);
+ return builder.AddResource(resource)
+ .WithIconName("CodeJsRectangle")
+ .WithInitialState(new CustomResourceSnapshot { Properties = [], ResourceType = "VitePlusWorkspace", State = KnownResourceStates.Running });
+ }
+
+ ///
+ /// Adds an individual app to a Vite+ workspace.
+ ///
+ /// The Vite+ workspace resource builder.
+ /// The name of the app resource.
+ /// The directory of the app within the Vite+ workspace, relative to the workspace root. It is passed to vp -C so the app behaves as if you had cd'd into it. If not specified, defaults to apps/{name}.
+ /// A function to configure the app resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The configure callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder AddApp(this IResourceBuilder builder, [ResourceName] string name, string? directory = null, Func, IResourceBuilder>? configure = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+ ArgumentNullException.ThrowIfNull(name);
+
+ directory ??= Path.Combine("apps", name);
+
+ var resource = new VitePlusAppResource(name, builder.Resource.WorkingDirectory, directory);
+
+ var rb = builder.ApplicationBuilder.AddResource(resource)
+ .WithNodeDefaults()
+ .WithIconName("CodeJsRectangle")
+ .WithArgs("-C", directory, "dev")
+ .WithParentRelationship(builder.Resource);
+
+ // If the workspace is configured to use a package manager, bring that annotation forward
+ if (builder.Resource.TryGetLastAnnotation(out var executionAnnotation))
+ {
+ rb.WithCommand(executionAnnotation.ExecutableName switch
+ {
+ "npm" => "npx",
+ "yarn" => "yarn",
+ "pnpm" => "pnpx",
+ "bun" => "bunx",
+ _ => executionAnnotation.ExecutableName
+ })
+ .WithArgs(context =>
+ {
+ context.Args.Insert(0, executionAnnotation.ScriptCommand ?? CliName);
+ });
+ }
+
+ // If the workspace has an installer annotation, wait for the installer to complete
+ if (builder.Resource.TryGetLastAnnotation(out var installerAnnotation))
+ {
+ rb.WaitForCompletion(builder.ApplicationBuilder.CreateResourceBuilder(installerAnnotation.Resource));
+ }
+
+ configure?.Invoke(rb);
+
+ return rb;
+ }
+
+ [AspireExport(MethodName = "addApp")]
+ internal static IResourceBuilder AddVitePlusWorkspaceApp(this IResourceBuilder builder, [ResourceName] string name, string? directory = null) =>
+ builder.AddApp(name, directory, configure: null);
+
+ ///
+ /// Configures the Vite+ workspace to use the specified JavaScript package manager when starting apps.
+ ///
+ /// The Vite+ workspace resource builder.
+ /// The package manager to use. If none is provided it will attempt to use the installer annotation's resource command.
+ /// A reference to the .
+ /// Thrown if the Vite+ workspace is already configured to use a different package manager.
+ [AspireExport("withVitePlusPackageManagerLaunch", MethodName = "withPackageManagerLaunch")]
+ public static IResourceBuilder WithPackageManagerLaunch(this IResourceBuilder builder, string? packageManager = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ if (builder.Resource.TryGetLastAnnotation(out var existingExecution))
+ {
+ if (packageManager is null || existingExecution.ExecutableName == packageManager)
+ {
+ // already configured with execution annotation
+ return builder;
+ }
+ throw new InvalidOperationException($"The Vite+ workspace '{builder.Resource.Name}' is already configured to run with the '{existingExecution.ExecutableName}' package manager.");
+ }
+
+ // If no explicit package manager provided, try to infer from configured annotation
+ if (packageManager is null)
+ {
+ if (builder.Resource.TryGetLastAnnotation(out var configured))
+ {
+ packageManager = configured.PackageManager;
+ }
+ else
+ {
+ throw new InvalidOperationException($"The Vite+ workspace '{builder.Resource.Name}' is not configured with a package manager. Call WithNpm/WithYarn/WithPnpm/WithBun first, or provide an explicit package manager.");
+ }
+ }
+
+ return builder.WithAnnotation(new JavaScriptPackageManagerAnnotation(packageManager, runScriptCommand: CliName));
+ }
+
+ ///
+ /// Configures the Vite+ workspace to use npm as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Vite+ workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithNpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("npm", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withNpm")]
+ internal static IResourceBuilder WithVitePlusNpm(this IResourceBuilder builder, bool install = false) =>
+ builder.WithNpm(install, configureInstaller: null);
+
+ ///
+ /// Configures the Vite+ workspace to use yarn as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Vite+ workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithYarn(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("yarn", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withYarn")]
+ internal static IResourceBuilder WithVitePlusYarn(this IResourceBuilder builder, bool install = false) =>
+ builder.WithYarn(install, configureInstaller: null);
+
+ ///
+ /// Configures the Vite+ workspace to use pnpm as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Vite+ workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithPnpm(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("pnpm", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withPnpm")]
+ internal static IResourceBuilder WithVitePlusPnpm(this IResourceBuilder builder, bool install = false) =>
+ builder.WithPnpm(install, configureInstaller: null);
+
+ ///
+ /// Configures the Vite+ workspace to use bun as the package manager and optionally installs packages before apps start.
+ ///
+ /// The Vite+ workspace resource builder.
+ /// When true, automatically installs packages before apps start. When false (default), only sets the package manager annotation without creating an installer resource.
+ /// A function to configure the installer resource builder.
+ /// A reference to the .
+ /// This overload is not available in polyglot app hosts. Use instead.
+ [AspireExportIgnore(Reason = "The installer configuration callback is not ATS-compatible. Use the overload without the configure callback instead.")]
+ public static IResourceBuilder WithBun(this IResourceBuilder builder, bool install = false, Action>? configureInstaller = null)
+ {
+ ArgumentNullException.ThrowIfNull(builder);
+
+ builder.AddMonorepoInstaller("bun", install, configureInstaller);
+ return builder;
+ }
+
+ [AspireExport(MethodName = "withBun")]
+ internal static IResourceBuilder WithVitePlusBun(this IResourceBuilder builder, bool install = false) =>
+ builder.WithBun(install, configureInstaller: null);
+}
\ No newline at end of file
diff --git a/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusResource.cs b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusResource.cs
new file mode 100644
index 000000000..3ef61df6b
--- /dev/null
+++ b/src/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions/VitePlusResource.cs
@@ -0,0 +1,14 @@
+namespace Aspire.Hosting.ApplicationModel;
+
+///
+/// A resource that represents an Vite+ monorepo workspace.
+///
+/// The name of the resource.
+/// The working directory of the Vite+ workspace.
+public class VitePlusResource(string name, string workingDirectory) : Resource(name)
+{
+ ///
+ /// Gets the working directory of the Vite+ workspace.
+ ///
+ public string WorkingDirectory { get; } = workingDirectory;
+}
\ No newline at end of file
diff --git a/tests/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions.Tests/AppHostTests.cs b/tests/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions.Tests/AppHostTests.cs
index fd01a487a..8cfc6a036 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions.Tests/AppHostTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.JavaScript.Extensions.Tests/AppHostTests.cs
@@ -8,6 +8,7 @@ public class AppHostTests(AspireIntegrationTestFixture();
+ var vitePlusResource = Assert.Single(appModel.Resources.OfType());
+
+ Assert.Equal("test-vp", vitePlusResource.Name);
+ Assert.NotEmpty(vitePlusResource.WorkingDirectory);
+ }
+
+ [Fact]
+ public void VitePlusResource_DefaultWorkingDirectory()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("my-vp");
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+ var vitePlusResource = Assert.Single(appModel.Resources.OfType());
+
+ Assert.Contains("my-vp", vitePlusResource.WorkingDirectory);
+ }
+
+ [Fact]
+ public void VitePlusResource_IsRunningState()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-running");
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+ var vpResource = Assert.Single(appModel.Resources.OfType());
+
+ Assert.True(vpResource.TryGetAnnotationsOfType(out var annotations));
+ var annotation = Assert.Single(annotations);
+
+ Assert.Equal(KnownResourceStates.Running, annotation.InitialSnapshot.State?.Text);
+ }
+
+ [Fact]
+ public async Task VitePlus_AddApp_DefaultDirectoryIsAppsName()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-default-dir");
+ vp.AddApp("app1");
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+ var vpApp = Assert.Single(appModel.Resources.OfType());
+
+ Assert.Equal(Path.Combine("apps", "app1"), vpApp.Directory);
+ Assert.Equal("vp", vpApp.Command);
+ var args = await vpApp.GetArgumentListAsync();
+ Assert.Collection(args,
+ arg => Assert.Equal("-C", arg),
+ arg => Assert.Equal(Path.Combine("apps", "app1"), arg),
+ arg => Assert.Equal("dev", arg));
+ }
+
+ [Fact]
+ public async Task VitePlus_AddApp_ExplicitDirectoryIsPassedThrough()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-explicit-dir");
+ vp.AddApp("docs", directory: "packages/docs");
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+ var vpApp = Assert.Single(appModel.Resources.OfType());
+
+ Assert.Equal("packages/docs", vpApp.Directory);
+ Assert.Equal("vp", vpApp.Command);
+ var args = await vpApp.GetArgumentListAsync();
+ Assert.Collection(args,
+ arg => Assert.Equal("-C", arg),
+ arg => Assert.Equal("packages/docs", arg),
+ arg => Assert.Equal("dev", arg));
+ }
+
+ [Theory]
+ [InlineData("npm")]
+ [InlineData("yarn")]
+ [InlineData("pnpm")]
+ [InlineData("bun")]
+ public async Task VitePlus_WithPackageManagerLaunch_InfersFromInstallerWhenNotProvided(string packageManager)
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-default");
+
+ vp = (packageManager switch
+ {
+ "npm" => vp.WithNpm(),
+ "yarn" => vp.WithYarn(),
+ "pnpm" => vp.WithPnpm(),
+ "bun" => vp.WithBun(),
+ _ => throw new ArgumentOutOfRangeException(nameof(packageManager), $"Unsupported package manager: {packageManager}"),
+ }).WithPackageManagerLaunch();
+
+ // Add an app to the Vite+ workspace to verify app-level command/args
+ var app1 = vp.AddApp("app1");
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+ var vpResource = Assert.Single(appModel.Resources.OfType());
+
+ Assert.True(vpResource.TryGetLastAnnotation(out var pm));
+ Assert.Equal(packageManager, pm.ExecutableName);
+
+ // Verify Vite+ app command and args
+ var vpApp = Assert.Single(appModel.Resources.OfType());
+ // For the inferred package manager, AddApp uses the corresponding command
+ Assert.Equal(packageManager switch
+ {
+ "npm" => "npx",
+ "yarn" => "yarn",
+ "pnpm" => "pnpx",
+ "bun" => "bunx",
+ _ => packageManager
+ }, vpApp.Command);
+ var vpArgs = await vpApp.GetArgumentListAsync();
+ Assert.Collection(vpArgs,
+ arg => Assert.Equal("vp", arg),
+ arg => Assert.Equal("-C", arg),
+ arg => Assert.Equal(Path.Combine("apps", "app1"), arg),
+ arg => Assert.Equal("dev", arg));
+ }
+
+ [Fact]
+ public async Task VitePlus_WithPackageManagerLaunch_WithPnpmAndYarn()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vpPnpm = builder.AddVitePlusApp("vp-pnpm").WithPnpm().WithPackageManagerLaunch();
+ var vpYarn = builder.AddVitePlusApp("vp-yarn").WithYarn().WithPackageManagerLaunch();
+
+ vpPnpm.AddApp("app1-pnpm");
+ vpYarn.AddApp("app1-yarn");
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+
+ var vpPnpmResource = appModel.Resources.OfType().Single(r => r.Name == "vp-pnpm");
+ Assert.True(vpPnpmResource.TryGetLastAnnotation(out var vpmPnpm));
+ Assert.Equal("pnpm", vpmPnpm.ExecutableName);
+
+ var vpPnpmApp = appModel.Resources.OfType().Single(r => r.Name == "app1-pnpm");
+ Assert.Equal("pnpx", vpPnpmApp.Command);
+ var vppnpmArgs = await vpPnpmApp.GetArgumentListAsync();
+ Assert.Collection(vppnpmArgs,
+ arg => Assert.Equal("vp", arg),
+ arg => Assert.Equal("-C", arg),
+ arg => Assert.Equal(Path.Combine("apps", "app1-pnpm"), arg),
+ arg => Assert.Equal("dev", arg));
+
+ var vpYarnResource = appModel.Resources.OfType().Single(r => r.Name == "vp-yarn");
+ Assert.True(vpYarnResource.TryGetLastAnnotation(out var vpmYarn));
+ Assert.Equal("yarn", vpmYarn.ExecutableName);
+
+ var vpYarnApp = appModel.Resources.OfType().Single(r => r.Name == "app1-yarn");
+ Assert.Equal("yarn", vpYarnApp.Command);
+ var vpyarnArgs = await vpYarnApp.GetArgumentListAsync();
+ Assert.Collection(vpyarnArgs,
+ arg => Assert.Equal("vp", arg),
+ arg => Assert.Equal("-C", arg),
+ arg => Assert.Equal(Path.Combine("apps", "app1-yarn"), arg),
+ arg => Assert.Equal("dev", arg));
+ }
+
+ [Fact]
+ public async Task VitePlus_NoWithPackageManagerLaunch_Defaults_AppCommandsIncludeNpxOrDefault()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ // Vite+ without WithPackageManagerLaunch or installer
+ var vp = builder.AddVitePlusApp("vp-default");
+ vp.AddApp("app-vp-default");
+
+ using var app = builder.Build();
+
+ var appModel = app.Services.GetRequiredService();
+
+ var vpApp = appModel.Resources.OfType().Single(r => r.Name == "app-vp-default");
+ // Command should be 'vp' (default) and args should target the app directory via -C
+ Assert.Equal("vp", vpApp.Command);
+ var vpArgs = await vpApp.GetArgumentListAsync();
+ Assert.Collection(vpArgs,
+ arg => Assert.Equal("-C", arg),
+ arg => Assert.Equal(Path.Combine("apps", "app-vp-default"), arg),
+ arg => Assert.Equal("dev", arg));
+ }
+
+ [Theory]
+ [InlineData("npm")]
+ [InlineData("yarn")]
+ [InlineData("pnpm")]
+ [InlineData("bun")]
+ public async Task VitePlus_WithPackageManager_WithoutRunWith_DoesNotAffectAppExecution(string packageManager)
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vpBuilder = builder.AddVitePlusApp("vp-configured-only");
+ vpBuilder = packageManager switch
+ {
+ "npm" => vpBuilder.WithNpm(),
+ "yarn" => vpBuilder.WithYarn(),
+ "pnpm" => vpBuilder.WithPnpm(),
+ "bun" => vpBuilder.WithBun(),
+ _ => throw new ArgumentOutOfRangeException(nameof(packageManager))
+ };
+
+ vpBuilder.AddApp("test-app");
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ // Workspace should have configured annotation but not execution annotation
+ var vpResource = Assert.Single(appModel.Resources.OfType());
+ Assert.True(vpResource.TryGetLastAnnotation(out var configured));
+ Assert.Equal(packageManager, configured.PackageManager);
+ Assert.False(vpResource.TryGetLastAnnotation(out _));
+
+ // App should use "vp" directly, not wrapped via package manager
+ var vpApp = Assert.Single(appModel.Resources.OfType());
+ Assert.Equal("vp", vpApp.Command);
+ var args = await vpApp.GetArgumentListAsync();
+ Assert.Collection(args,
+ arg => Assert.Equal("-C", arg),
+ arg => Assert.Equal(Path.Combine("apps", "test-app"), arg),
+ arg => Assert.Equal("dev", arg));
+ }
+
+ [Fact]
+ public void VitePlus_WithPackageManagerLaunch_CalledTwiceWithDifferent_Throws()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-conflict")
+ .WithPnpm()
+ .WithPackageManagerLaunch();
+
+ var ex = Assert.Throws(() => vp.WithPackageManagerLaunch("npm"));
+ Assert.Contains("already configured to run with the 'pnpm' package manager", ex.Message);
+ }
+
+ [Fact]
+ public void VitePlus_WithPackageManagerLaunch_ThrowsWhenNotConfigured()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var ex = Assert.Throws(() =>
+ builder.AddVitePlusApp("vp-no-config").WithPackageManagerLaunch());
+
+ Assert.Contains("not configured with a package manager", ex.Message);
+ }
+
+ [Fact]
+ public void VitePlus_WithPackageManagerLaunch_ExplicitOverride_UsesExplicitValue()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ // Configure with npm but explicitly run with yarn
+ var vp = builder.AddVitePlusApp("vp-override")
+ .WithNpm()
+ .WithPackageManagerLaunch("yarn");
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ var vpResource = Assert.Single(appModel.Resources.OfType());
+
+ // Should have configured annotation for npm
+ Assert.True(vpResource.TryGetLastAnnotation(out var configured));
+ Assert.Equal("npm", configured.PackageManager);
+
+ // But execution annotation should be yarn (explicit override)
+ Assert.True(vpResource.TryGetLastAnnotation(out var execution));
+ Assert.Equal("yarn", execution.ExecutableName);
+ }
+
+ [Fact]
+ public void VitePlus_WithPackageManagerLaunch_CalledTwiceWithSame_DoesNotThrow()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-idempotent")
+ .WithYarn()
+ .WithPackageManagerLaunch()
+ .WithPackageManagerLaunch(); // Second call with same inferred value
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ var vpResource = Assert.Single(appModel.Resources.OfType());
+ Assert.True(vpResource.TryGetLastAnnotation(out var execution));
+ Assert.Equal("yarn", execution.ExecutableName);
+ }
+
+ [Theory]
+ [InlineData("npm")]
+ [InlineData("yarn")]
+ [InlineData("pnpm")]
+ [InlineData("bun")]
+ public async Task VitePlus_MultipleApps_AllInheritExecutionAnnotation(string packageManager)
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-multi");
+ vp = packageManager switch
+ {
+ "npm" => vp.WithNpm(),
+ "yarn" => vp.WithYarn(),
+ "pnpm" => vp.WithPnpm(),
+ "bun" => vp.WithBun(),
+ _ => throw new ArgumentOutOfRangeException(nameof(packageManager))
+ };
+ vp = vp.WithPackageManagerLaunch();
+
+ vp.AddApp("app1");
+ vp.AddApp("app2");
+ vp.AddApp("app3");
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ var apps = appModel.Resources.OfType().ToList();
+ Assert.Equal(3, apps.Count);
+
+ foreach (var vpApp in apps)
+ {
+ var launcherName = packageManager switch
+ {
+ "npm" => "npx",
+ "yarn" => "yarn",
+ "pnpm" => "pnpx",
+ "bun" => "bunx",
+ _ => throw new ArgumentOutOfRangeException(nameof(packageManager))
+ };
+
+ Assert.Equal(launcherName, vpApp.Command);
+ var args = await vpApp.GetArgumentListAsync();
+ Assert.Collection(args,
+ arg => Assert.Equal("vp", arg),
+ arg => Assert.Equal("-C", arg),
+ arg => Assert.Equal(Path.Combine("apps", vpApp.Name), arg),
+ arg => Assert.Equal("dev", arg));
+ }
+ }
+
+ [Fact]
+ public void VitePlus_WithNpm_WithoutInstallFlag_DoesNotCreateInstallerResource()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-no-installer")
+ .WithNpm(); // install defaults to false
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ // Should have configured annotation
+ var vpResource = Assert.Single(appModel.Resources.OfType());
+ Assert.True(vpResource.TryGetLastAnnotation(out _));
+
+ // But no installer annotation or resource
+ Assert.False(vpResource.TryGetLastAnnotation(out _));
+ Assert.Empty(appModel.Resources.OfType());
+ }
+
+ [Fact]
+ public void VitePlus_ConfiguredAnnotation_AddedEvenWithInstallFalse()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-configured")
+ .WithPnpm(install: false);
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ var vpResource = Assert.Single(appModel.Resources.OfType());
+
+ // Configured annotation should always be present
+ Assert.True(vpResource.TryGetLastAnnotation(out var configured));
+ Assert.Equal("pnpm", configured.PackageManager);
+
+ // But no installer
+ Assert.False(vpResource.TryGetLastAnnotation(out _));
+ }
+
+ [Fact]
+ public void VitePlus_WithInstallTrue_AppsWaitForInstaller()
+ {
+ var builder = DistributedApplication.CreateBuilder();
+
+ var vp = builder.AddVitePlusApp("vp-with-install")
+ .WithYarn(install: true)
+ .WithPackageManagerLaunch();
+
+ vp.AddApp("app1");
+
+ using var app = builder.Build();
+ var appModel = app.Services.GetRequiredService();
+
+ // Verify installer resource exists
+ var vpResource = Assert.Single(appModel.Resources.OfType());
+ Assert.True(vpResource.TryGetLastAnnotation(out var installerAnnotation));
+
+ var installer = installerAnnotation.Resource;
+ Assert.NotNull(installer);
+ Assert.Equal("vp-with-install-installer", installer.Name);
+
+ // Verify app has WaitFor relationship
+ var vpApp = Assert.Single(appModel.Resources.OfType());
+ Assert.True(vpApp.TryGetAnnotationsOfType(out var waitAnnotations));
+ var waitAnnotation = Assert.Single(waitAnnotations);
+ Assert.Equal(installer, waitAnnotation.Resource);
+ }
+}
Connect with us
+Join the Vite community
++- GitHub
+ - Discord
+ - X.com
+ - Bluesky
+
+