├── .gitignore ├── renovate.json ├── test-minimal-example ├── .gitignore ├── src │ ├── vite-env.d.ts │ ├── shared-worker.ts │ ├── worker.ts │ ├── nested-worker.ts │ ├── conditional-worker.ts │ └── main.ts ├── vite.config.ts ├── index.html ├── package.json ├── tsconfig.json └── test-runner.js ├── example ├── src │ ├── worker.ts │ ├── worker2-2.ts │ ├── worker3.do.ts │ ├── worker.shared1.ts │ ├── vite-env.d.ts │ ├── a │ │ └── a │ │ │ └── w4.ts │ ├── worker2-1.ts │ ├── main.ts │ └── typescript.svg ├── .gitignore ├── vite.config.ts ├── index.html ├── package.json ├── tsconfig.json ├── public │ └── vite.svg └── package-lock.json ├── .npmignore ├── tsup.config.ts ├── SECURITY.md ├── .github ├── workflows │ ├── node.js.yml │ ├── codeql-analysis.yml │ └── test-latest-vite.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── tsconfig.json ├── client.d.ts ├── LICENSE ├── package.json ├── src ├── symbol.ts └── index.ts └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:recommended" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /test-minimal-example/.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | dist 3 | node_modules 4 | -------------------------------------------------------------------------------- /example/src/worker.ts: -------------------------------------------------------------------------------- 1 | export function add(a:number,b:number) { 2 | return a+b; 3 | } -------------------------------------------------------------------------------- /example/src/worker2-2.ts: -------------------------------------------------------------------------------- 1 | export function add(a:number,b:number) { 2 | return a+b; 3 | } -------------------------------------------------------------------------------- /example/src/worker3.do.ts: -------------------------------------------------------------------------------- 1 | export function add(a:number,b:number) { 2 | return a+b; 3 | } 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src 2 | example 3 | .github 4 | renovate.json 5 | tsconfig.json 6 | test-minimal-example 7 | -------------------------------------------------------------------------------- /example/src/worker.shared1.ts: -------------------------------------------------------------------------------- 1 | export function add(a:number,b:number) { 2 | return a+b; 3 | } 4 | -------------------------------------------------------------------------------- /example/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /test-minimal-example/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /example/src/a/a/w4.ts: -------------------------------------------------------------------------------- 1 | export const w4 = new ComlinkWorker(new URL("../../worker", import.meta.url)) 2 | console.log(await w4.add(6,5)) 3 | 4 | -------------------------------------------------------------------------------- /example/src/worker2-1.ts: -------------------------------------------------------------------------------- 1 | const w = new ComlinkWorker(new URL("./worker2-2.ts", import.meta.url)) 2 | export const add = (a: number,b: number) => w.add(a,b) 3 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup' 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts', 'src/symbol.ts'], 5 | format: ['esm'], 6 | dts: true, 7 | clean: true 8 | }) -------------------------------------------------------------------------------- /test-minimal-example/src/shared-worker.ts: -------------------------------------------------------------------------------- 1 | let counter = 0 2 | 3 | export function increment(): number { 4 | return ++counter 5 | } 6 | 7 | export function getCount(): number { 8 | return counter 9 | } 10 | 11 | export function reset(): void { 12 | counter = 0 13 | } -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | As this is a small project of only myself the only supported version is the latest version. No LTS provided - sorry. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | In the security-tab you can report a vulnerability via github. 10 | -------------------------------------------------------------------------------- /test-minimal-example/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { comlink } from 'vite-plugin-comlink' 3 | 4 | export default defineConfig({ 5 | plugins: [comlink()], 6 | worker: { 7 | plugins: () => [comlink()] 8 | }, 9 | build: { 10 | sourcemap: true 11 | } 12 | }) -------------------------------------------------------------------------------- /test-minimal-example/src/worker.ts: -------------------------------------------------------------------------------- 1 | export function add(a: number, b: number): number { 2 | return a + b 3 | } 4 | 5 | export function greet(name: string): string { 6 | return `Hello, ${name}!` 7 | } 8 | 9 | export async function asyncTask(): Promise { 10 | await new Promise(resolve => setTimeout(resolve, 100)) 11 | return 'Async task completed' 12 | } -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /example/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import comlink from "../src/index"; 3 | import { join, dirname } from "node:path"; 4 | import inspect from "vite-plugin-inspect"; 5 | 6 | export default defineConfig({ 7 | plugins: [ 8 | comlink(), 9 | inspect() 10 | ], 11 | worker: { 12 | plugins: () => ([ 13 | comlink() 14 | ]) 15 | } 16 | }); -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: Setup Node.js 16 | uses: actions/setup-node@v4 17 | with: 18 | node-version: 22 19 | - run: npm install 20 | - run: npm run build 21 | -------------------------------------------------------------------------------- /test-minimal-example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vite Plugin Comlink Test 7 | 8 | 9 |
10 |

Vite Plugin Comlink Test

11 |
12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "declaration": true, 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true, 12 | "lib": ["esnext", "DOM"], 13 | "outDir": "dist" 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] 16 | } 17 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "typescript": "^5.2.2", 13 | "vite": "^7.0.6", 14 | "vite-plugin-comlink": "../", 15 | "vite-plugin-inspect": "^11.3.2" 16 | }, 17 | "dependencies": { 18 | "comlink": "^4.4.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test-minimal-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-plugin-comlink-test", 3 | "private": true, 4 | "version": "1.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "test": "vite build && node test-runner.js" 10 | }, 11 | "devDependencies": { 12 | "@playwright/test": "^1.40.0", 13 | "@types/node": "^22.0.0", 14 | "typescript": "^5.0.0", 15 | "vite": "latest" 16 | }, 17 | "dependencies": { 18 | "comlink": "^4.4.1", 19 | "vite-plugin-comlink": "file:.." 20 | } 21 | } -------------------------------------------------------------------------------- /client.d.ts: -------------------------------------------------------------------------------- 1 | import type { Remote } from 'comlink' 2 | import { endpointSymbol as sym } from "./dist/symbol"; 3 | 4 | declare global { 5 | var ComlinkWorker: { 6 | new(scriptURL: URL, options?: ComlinkWorkerOptions): { readonly [sym]: Worker } & Remote; 7 | }; 8 | 9 | var ComlinkSharedWorker: { 10 | new(scriptURL: URL, options?: ComlinkWorkerOptions): { readonly [sym]: SharedWorker } & Remote; 11 | }; 12 | 13 | interface ComlinkWorkerOptions extends WorkerOptions { 14 | replacement?: string 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test-minimal-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | "moduleResolution": "bundler", 9 | "allowImportingTsExtensions": true, 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "noEmit": true, 13 | "strict": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "noFallthroughCasesInSwitch": true 17 | }, 18 | "include": ["src"] 19 | } -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true 21 | }, 22 | "include": ["src"] 23 | } 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /example/src/main.ts: -------------------------------------------------------------------------------- 1 | import { endpointSymbol } from "vite-plugin-comlink/symbol"; 2 | 3 | const w = new ComlinkWorker(new URL("./worker.ts", import.meta.url)) 4 | const x = w[endpointSymbol] 5 | 6 | console.log(x instanceof Worker ? 'symbol ok' : 'symbol bad') 7 | console.log(x) 8 | console.log(await w.add(5,3)) 9 | 10 | const w2 = new ComlinkWorker(new URL("./worker2-1.ts", import.meta.url)) 11 | console.log(await w2.add(6,3)) 12 | 13 | const w3 = new ComlinkWorker(new URL("./worker3.do", import.meta.url)) 14 | console.log(await w3.add(6,4)) 15 | 16 | await import("./a/a/w4.ts") 17 | 18 | 19 | const w4 = new ComlinkSharedWorker(new URL("./worker.shared1", import.meta.url)) 20 | console.log(await w4.add(6,4)) 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. Provide a full reproduction example. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Desktop (please complete the following information):** 23 | - OS: [e.g. iOS] 24 | - Browser [e.g. chrome, safari] 25 | - Version [e.g. 22] 26 | 27 | **Smartphone (please complete the following information):** 28 | - Device: [e.g. iPhone6] 29 | - OS: [e.g. iOS8.1] 30 | - Browser [e.g. stock browser, safari] 31 | - Version [e.g. 22] 32 | 33 | **Additional context** 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 - 2024 Sebastian Krüger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test-minimal-example/src/nested-worker.ts: -------------------------------------------------------------------------------- 1 | // Test nested worker creation (simulated) 2 | export async function createNestedWorker() { 3 | // Create a worker to simulate nested worker operations 4 | const nestedWorker = new ComlinkWorker( 5 | new URL('./worker.ts', import.meta.url) 6 | ); 7 | 8 | // Test the worker and return results instead of the worker itself 9 | const addResult = await nestedWorker.add(5, 7); 10 | const greetResult = await nestedWorker.greet('Nested'); 11 | 12 | return { 13 | addViaNestedWorker: async () => addResult, 14 | greetViaNestedWorker: async () => greetResult, 15 | }; 16 | } 17 | 18 | export function processComplexData(data: { numbers: number[]; multiplier: number }) { 19 | return data.numbers.map(n => n * data.multiplier).reduce((sum, n) => sum + n, 0); 20 | } 21 | 22 | export async function asyncChainOperation() { 23 | const step1 = await new Promise(resolve => setTimeout(() => resolve(5), 50)); 24 | const step2 = await new Promise(resolve => setTimeout(() => resolve(step1 * 2), 50)); 25 | const step3 = await new Promise(resolve => setTimeout(() => resolve(step2 + 10), 50)); 26 | return step3; 27 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-plugin-comlink", 3 | "version": "5.3.0", 4 | "description": "Comlink for Vite", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/mathe42/vite-plugin-comlink.git" 8 | }, 9 | "type": "module", 10 | "main": "dist/index.js", 11 | "types": "dist/index.d.ts", 12 | "module": "dist/index.js", 13 | "exports": { 14 | ".": { 15 | "types": "./dist/index.d.ts", 16 | "default": "./dist/index.js" 17 | }, 18 | "./client": { 19 | "types": "./client.d.ts" 20 | }, 21 | "./symbol": { 22 | "types": "./dist/symbol.d.ts", 23 | "default": "./dist/symbol.js" 24 | } 25 | }, 26 | "author": "Sebastian Krüger (@mathe42)", 27 | "license": "MIT", 28 | "scripts": { 29 | "build": "tsup", 30 | "prepublishOnly": "npm run build" 31 | }, 32 | "dependencies": { 33 | "json5": "2.2.3", 34 | "magic-string": "0.30.17", 35 | "source-map": "^0.7.4" 36 | }, 37 | "devDependencies": { 38 | "@types/node": "22.17.0", 39 | "comlink": "4.4.2", 40 | "tsup": "8.5.0", 41 | "typescript": "5.9.2", 42 | "vite": "7.0.6" 43 | }, 44 | "peerDependencies": { 45 | "comlink": "^4.3.1", 46 | "vite": ">=4" 47 | }, 48 | "volta": { 49 | "node": "22.18.0" 50 | } 51 | } -------------------------------------------------------------------------------- /example/src/typescript.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test-minimal-example/src/conditional-worker.ts: -------------------------------------------------------------------------------- 1 | export function conditionalWorkerCreation(shouldCreateShared: boolean) { 2 | // Check if we're in a worker context or main thread 3 | const isMainThread = typeof window !== 'undefined'; 4 | const hasSharedWorker = isMainThread && typeof SharedWorker !== 'undefined'; 5 | 6 | if (shouldCreateShared && hasSharedWorker) { 7 | return { type: 'shared', supported: true, context: 'main', hasSharedWorker }; 8 | } else { 9 | return { type: 'regular', supported: true, context: isMainThread ? 'main' : 'worker', hasSharedWorker }; 10 | } 11 | } 12 | 13 | export async function testWorkerInFunction() { 14 | const worker = new ComlinkWorker( 15 | new URL('./worker.ts', import.meta.url) 16 | ); 17 | 18 | const result = await worker.add(10, 20); 19 | return result; 20 | } 21 | 22 | // Test multiple workers creation and management 23 | let workers: Array = []; 24 | 25 | export async function createMultipleWorkers(count: number) { 26 | workers = []; 27 | for (let i = 0; i < count; i++) { 28 | const worker = new ComlinkWorker( 29 | new URL('./worker.ts', import.meta.url) 30 | ); 31 | workers.push(worker); 32 | } 33 | return workers.length; 34 | } 35 | 36 | export async function testAllWorkers() { 37 | const promises = workers.map((worker, index) => 38 | worker.add(index, index + 1) 39 | ); 40 | return Promise.all(promises); 41 | } -------------------------------------------------------------------------------- /src/symbol.ts: -------------------------------------------------------------------------------- 1 | import { wrap as comlink_wrap } from "comlink"; 2 | 3 | // Re-export commonly used Comlink utilities for convenience 4 | export { 5 | proxy, 6 | proxyMarker, 7 | finalizer, 8 | releaseProxy, 9 | createEndpoint 10 | } from 'comlink' 11 | 12 | /** 13 | * Symbol used to access the underlying Worker/SharedWorker instance 14 | * from a Comlink-wrapped worker proxy. 15 | * 16 | * Usage: 17 | * ```ts 18 | * const worker = new ComlinkWorker( 19 | * new URL('./worker', import.meta.url) 20 | * ); 21 | * const nativeWorker = worker[endpointSymbol]; // Access underlying Worker 22 | * ``` 23 | */ 24 | export const endpointSymbol = Symbol("getEndpoint"); 25 | 26 | /** 27 | * Enhanced wrap function that extends Comlink's wrap with endpoint access. 28 | * 29 | * This function wraps a Worker/SharedWorker endpoint with Comlink's proxy, 30 | * but also adds the ability to access the original endpoint via a symbol. 31 | * This allows users to access native Worker methods and properties when needed. 32 | * 33 | * @param ep - The endpoint (Worker, SharedWorker.port, MessagePort, etc.) to wrap 34 | * @returns Comlink proxy with additional endpoint access via endpointSymbol 35 | * 36 | * @internal This is used internally by the plugin transformation 37 | */ 38 | export const wrap: typeof comlink_wrap = (ep) => { 39 | // Create the standard Comlink proxy 40 | const wrapped = comlink_wrap(ep); 41 | 42 | // Enhance the proxy to expose the underlying endpoint via symbol 43 | return new Proxy(wrapped, { 44 | get(target, prop, receiver) { 45 | // If accessing the endpoint symbol, return the original endpoint 46 | if (prop === endpointSymbol) return ep; 47 | 48 | // Otherwise, delegate to the wrapped Comlink proxy 49 | return Reflect.get(target, prop, receiver); 50 | } 51 | }) as any; 52 | } -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '31 18 * * 2' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v4 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v3 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v3 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v3 71 | -------------------------------------------------------------------------------- /.github/workflows/test-latest-vite.yml: -------------------------------------------------------------------------------- 1 | name: Test with Latest Vite 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | schedule: 9 | # Run daily at 2 AM UTC 10 | - cron: '0 2 * * *' 11 | workflow_dispatch: 12 | 13 | jobs: 14 | test-vite-versions: 15 | runs-on: ${{ matrix.os }} 16 | strategy: 17 | matrix: 18 | os: [ubuntu-latest] 19 | node-version: [22, 'latest'] 20 | vite-version: ['5', '6', '7', 'latest', 'beta', 'alpha'] 21 | fail-fast: false 22 | 23 | steps: 24 | - uses: actions/checkout@v4 25 | 26 | - name: Setup Node.js 27 | uses: actions/setup-node@v4 28 | with: 29 | node-version: ${{matrix.node-version}} 30 | 31 | - name: Install root dependencies 32 | run: npm install 33 | 34 | - name: Build plugin 35 | run: npm run build 36 | 37 | - name: Install test dependencies with specific Vite version 38 | working-directory: test-minimal-example 39 | run: | 40 | npm install vite@${{ matrix.vite-version }} --save-dev 41 | npm install 42 | 43 | - name: Install Playwright browsers 44 | working-directory: test-minimal-example 45 | run: npx playwright install chromium firefox 46 | 47 | - name: Run tests 48 | working-directory: test-minimal-example 49 | env: 50 | CI: true 51 | run: npm test 52 | 53 | - name: Report Vite version 54 | working-directory: test-minimal-example 55 | run: | 56 | echo "Testing with Vite version:" 57 | npx vite --version 58 | 59 | test-vite-rolldown: 60 | runs-on: ${{ matrix.os }} 61 | strategy: 62 | matrix: 63 | os: [ubuntu-latest] 64 | node-version: [22, 'latest'] 65 | vite-version: ['latest', 'beta', 'alpha'] 66 | fail-fast: false 67 | 68 | steps: 69 | - uses: actions/checkout@v4 70 | 71 | - name: Setup Node.js 72 | uses: actions/setup-node@v4 73 | with: 74 | node-version: ${{matrix.node-version}} 75 | 76 | - name: Install root dependencies 77 | run: npm install 78 | 79 | - name: Build plugin 80 | run: npm run build 81 | 82 | - name: Install test dependencies with Rolldown-Vite 83 | working-directory: test-minimal-example 84 | run: npm install vite@npm:rolldown-vite@${{ matrix.vite-version }} --save-dev 85 | 86 | - name: Install Playwright browsers 87 | working-directory: test-minimal-example 88 | run: npx playwright install chromium firefox 89 | 90 | - name: Run tests with Rolldown 91 | working-directory: test-minimal-example 92 | env: 93 | CI: true 94 | run: npm test 95 | 96 | - name: Report Vite and Rolldown versions 97 | working-directory: test-minimal-example 98 | run: | 99 | echo "Testing with Rolldown-Vite version:" 100 | npx vite --version 101 | echo "Package info:" 102 | npm list vite -------------------------------------------------------------------------------- /test-minimal-example/test-runner.js: -------------------------------------------------------------------------------- 1 | import { chromium, firefox, webkit } from '@playwright/test' 2 | import { preview } from 'vite' 3 | import { fileURLToPath } from 'url' 4 | import { dirname, join } from 'path' 5 | 6 | const __dirname = dirname(fileURLToPath(import.meta.url)) 7 | 8 | async function runTestsInBrowser(browserType, browserName) { 9 | console.log(`\n🌐 Testing in ${browserName}...`) 10 | 11 | let browser 12 | let exitCode = 0 13 | 14 | try { 15 | // Launch browser 16 | browser = await browserType.launch({ headless: true }) 17 | const page = await browser.newPage() 18 | 19 | // Collect console logs and errors 20 | const consoleLogs = [] 21 | page.on('console', msg => { 22 | if (msg.type() === 'log' && msg.text().includes('TEST RESULTS:')) { 23 | consoleLogs.push(msg.text()) 24 | } 25 | }) 26 | 27 | page.on('pageerror', error => { 28 | console.error(`${browserName} page error:`, error) 29 | }) 30 | 31 | // Navigate to the app 32 | await page.goto('http://localhost:4173') 33 | 34 | // Wait for tests to complete with longer timeout for complex tests 35 | await page.waitForSelector('[data-tests-complete="true"]', { timeout: 60000 }) 36 | 37 | // Check if all tests passed 38 | const testsPassed = await page.getAttribute('body', 'data-tests-passed') 39 | 40 | // Get test results from page 41 | const results = await page.evaluate(() => { 42 | const resultsEl = document.getElementById('results') 43 | return resultsEl ? resultsEl.innerText : 'No results found' 44 | }) 45 | 46 | console.log(`\n📊 ${browserName} Results:`) 47 | console.log(results) 48 | 49 | if (testsPassed !== 'true') { 50 | console.error(`\n❌ ${browserName}: Some tests failed!`) 51 | exitCode = 1 52 | } else { 53 | console.log(`\n✅ ${browserName}: All tests passed!`) 54 | } 55 | 56 | } catch (error) { 57 | console.error(`${browserName} test error:`, error) 58 | exitCode = 1 59 | } finally { 60 | if (browser) await browser.close() 61 | } 62 | 63 | return exitCode 64 | } 65 | 66 | async function runTests() { 67 | let server 68 | let overallExitCode = 0 69 | 70 | try { 71 | // Build is already done by npm script 72 | 73 | // Start preview server 74 | console.log('Starting preview server...') 75 | server = await preview({ 76 | root: __dirname, 77 | preview: { 78 | port: 4173 79 | } 80 | }) 81 | 82 | // Wait a moment for server to be ready 83 | await new Promise(resolve => setTimeout(resolve, 1000)) 84 | 85 | // Test in multiple browsers 86 | const browsers = [ 87 | { type: chromium, name: 'Chromium' }, 88 | { type: firefox, name: 'Firefox' }, 89 | // Safari/WebKit only works on macOS 90 | ...(process.platform === 'darwin' ? [{ type: webkit, name: 'Safari' }] : []) 91 | ] 92 | 93 | console.log(`\n🚀 Running tests in ${browsers.length} browser(s)...`) 94 | 95 | for (const { type, name } of browsers) { 96 | try { 97 | const exitCode = await runTestsInBrowser(type, name) 98 | if (exitCode !== 0) overallExitCode = 1 99 | } catch (error) { 100 | console.error(`Failed to test in ${name}:`, error) 101 | overallExitCode = 1 102 | } 103 | } 104 | 105 | if (overallExitCode === 0) { 106 | console.log('\n🎉 All browser tests passed!') 107 | } else { 108 | console.error('\n💥 Some browser tests failed!') 109 | } 110 | 111 | } catch (error) { 112 | console.error('Test runner error:', error) 113 | overallExitCode = 1 114 | } finally { 115 | if (server) await server.close() 116 | process.exit(overallExitCode) 117 | } 118 | } 119 | 120 | runTests() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vite-plugin-comlink 2 | 3 | ![NPM Version](https://img.shields.io/npm/l/vite-plugin-comlink) 4 | ![NPM Version](https://img.shields.io/npm/v/vite-plugin-comlink) 5 | ![NPM Version](https://img.shields.io/bundlephobia/minzip/vite-plugin-comlink) 6 | ![NPM Version](https://img.shields.io/npm/dm/vite-plugin-comlink) 7 | ![NPM Version](https://img.shields.io/npm/d18m/vite-plugin-comlink) 8 | 9 | 10 | > This plugin requires vite >=5 11 | 12 | Use WebWorkers with comlink. 13 | 14 | This plugin removes the need to call `expose`, `wrap` from comlink and also you don't need to create the worker on your own. 15 | 16 | ## Install 17 | 18 | ```sh 19 | npm i --save-dev vite-plugin-comlink # yarn add -D vite-plugin-comlink 20 | npm i --save comlink # yarn add comlink 21 | ``` 22 | 23 | ### Comlink install 24 | 25 | As you don't want to wait for a new release for this plugin when a new version of comlink is released, this plugin has comlink as a peer dependency so you can install the version of comlink that you need. 26 | 27 | ### Add it to vite.config.js 28 | 29 | ```ts 30 | // vite.config.js 31 | import { comlink } from "vite-plugin-comlink"; 32 | 33 | export default { 34 | plugins: [comlink()], 35 | worker: { 36 | plugins: () => [comlink()], 37 | }, 38 | }; 39 | ``` 40 | 41 | ### Plugin order 42 | 43 | Put this plugin as one of the first plugins. Only other plugins that create `ComlinkWorker` or `ComlinkSharedWorker` or transform files based on the existence of `ComlinkWorker` or `ComlinkSharedWorker` should come before this plugin! 44 | 45 | ## Usage 46 | 47 | ```ts 48 | // worker.js 49 | export const add = (a: number, b: number) => a + b; 50 | 51 | // main.ts 52 | 53 | // Create Worker 54 | const instance = new ComlinkWorker(new URL("./worker.js", import.meta.url), { 55 | /* normal Worker options*/ 56 | }); 57 | const result = await instance.add(2, 3); 58 | 59 | result === 5; 60 | 61 | // Create SharedWorker 62 | const instance = new ComlinkSharedWorker( 63 | new URL("./worker.js", import.meta.url), 64 | { 65 | /* normal Worker options*/ 66 | } 67 | ); 68 | const result = await instance.add(2, 3); 69 | 70 | result === 5; 71 | ``` 72 | 73 | ### With TypeScript 74 | 75 | Add 76 | 77 | ```ts 78 | /// 79 | ``` 80 | 81 | to your vite-env.d.ts file to make sure typescript will use `vite-plugin-comlink/client`. 82 | 83 | ```ts 84 | // worker.ts 85 | export const add = (a: number, b: number) => a + b; 86 | 87 | // main.ts 88 | 89 | // Create Worker 90 | const instance = new ComlinkWorker( 91 | new URL("./worker", import.meta.url), 92 | { 93 | /* normal Worker options*/ 94 | } 95 | ); 96 | const result = await instance.add(2, 3); 97 | 98 | result === 5; 99 | 100 | // Create SharedWorker 101 | const instance = new ComlinkSharedWorker( 102 | new URL("./worker", import.meta.url), 103 | { 104 | /* normal Worker options*/ 105 | } 106 | ); 107 | const result = await instance.add(2, 3); 108 | 109 | result === 5; 110 | ``` 111 | 112 | ### Get Worker Instance 113 | 114 | You can get to the worker instance like this: 115 | 116 | ```ts 117 | import { endpointSymbol } from "vite-plugin-comlink/symbol"; 118 | 119 | const api = new ComlinkWorker( 120 | new URL("./worker", import.meta.url), 121 | { 122 | /* normal Worker options*/ 123 | } 124 | ); 125 | const worker = api[endpointSymbol]; 126 | ``` 127 | 128 | ## Module Worker 129 | 130 | Not all Browsers support module Workers (see https://caniuse.com/mdn-api_worker_worker_ecmascript_modules). 131 | 132 | This results in some drawbacks for fastest and best support: 133 | 134 | For fast development we use module Workers as bundling the complete worker on the fly is not performant. 135 | 136 | In default settings we bundle the whole worker at build to a single file. Therefore all browsers that support Workers, work in production. 137 | 138 | This is the same behavior as vite and it is NOT CHANGEABLE! 139 | 140 | If you want a worker to be a module worker in production, add `type: 'module'` to the worker constructor options. 141 | 142 | ### What this means: 143 | 144 | 1. In development you need a browser that supports module Worker (see https://caniuse.com/mdn-api_worker_worker_ecmascript_modules) 145 | 2. In production all browsers are supported 146 | 147 | ## Breaking changes 148 | 149 | ### v2 to v3 150 | 151 | - remove of customConfigs breaking FF support in development for some projects and removing the abbility for inline worker. This is a limitation of vite so if vite adds support of it this plugin will follow 152 | - remove of typefile. For typescript support please write your own type file or switch to the new syntax. 153 | - remove of ServiceWorker support. This was considered unstable an it was hacky so it got removed. If vite adds support for building ServiceWorker this will be added! 154 | - you have to add comlink to `worker.plugins` array. 155 | 156 | ### v3 to v4 157 | 158 | - the import syntax will be removed you have to switch to the new syntax! 159 | - Removal of Warnings of leagacy (v2) options 160 | - ESM support 161 | - Better Source Maps 162 | 163 | ### v4 to v5 164 | 165 | - some undocumented internal options got removed. 166 | - full rewrite of the core transformer to fix a lot of bugs 167 | - should be breaking free but as this is a big rewrite there might be breaking changes 168 | 169 | ## Resources 170 | 171 | https://github.com/GoogleChromeLabs/comlink 172 | https://github.com/surma/rollup-plugin-comlink 173 | -------------------------------------------------------------------------------- /test-minimal-example/src/main.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { endpointSymbol } from 'vite-plugin-comlink/symbol' 4 | 5 | const results = document.getElementById('results')! 6 | 7 | async function runTests() { 8 | const testResults: { name: string; passed: boolean; message: string }[] = [] 9 | 10 | // Test 1: Basic ComlinkWorker 11 | try { 12 | const worker = new ComlinkWorker( 13 | new URL('./worker.ts', import.meta.url) 14 | ) 15 | 16 | const sum = await worker.add(2, 3) 17 | const greeting = await worker.greet('World') 18 | const asyncResult = await worker.asyncTask() 19 | 20 | testResults.push({ 21 | name: 'ComlinkWorker Basic', 22 | passed: sum === 5 && greeting === 'Hello, World!' && asyncResult === 'Async task completed', 23 | message: `add(2,3)=${sum}, greet('World')="${greeting}", asyncTask()="${asyncResult}"` 24 | }) 25 | } catch (error) { 26 | testResults.push({ 27 | name: 'ComlinkWorker Basic', 28 | passed: false, 29 | message: `Error: ${error}` 30 | }) 31 | } 32 | 33 | // Test 2: Endpoint access 34 | try { 35 | const worker = new ComlinkWorker( 36 | new URL('./worker.ts', import.meta.url) 37 | ) 38 | 39 | const endpoint = worker[endpointSymbol] 40 | const isWorker = endpoint instanceof Worker 41 | 42 | testResults.push({ 43 | name: 'Endpoint Access', 44 | passed: isWorker, 45 | message: `endpoint is Worker: ${isWorker}` 46 | }) 47 | } catch (error) { 48 | testResults.push({ 49 | name: 'Endpoint Access', 50 | passed: false, 51 | message: `Error: ${error}` 52 | }) 53 | } 54 | 55 | // Test 3: ComlinkSharedWorker (if supported) 56 | if (typeof SharedWorker !== 'undefined') { 57 | try { 58 | const sharedWorker1 = new ComlinkSharedWorker( 59 | new URL('./shared-worker.ts', import.meta.url) 60 | ) 61 | 62 | const sharedWorker2 = new ComlinkSharedWorker( 63 | new URL('./shared-worker.ts', import.meta.url) 64 | ) 65 | 66 | await sharedWorker1.reset() 67 | const count1 = await sharedWorker1.increment() 68 | const count2 = await sharedWorker2.increment() 69 | const finalCount = await sharedWorker1.getCount() 70 | 71 | testResults.push({ 72 | name: 'ComlinkSharedWorker', 73 | passed: count1 === 1 && count2 === 2 && finalCount === 2, 74 | message: `Shared state works: count1=${count1}, count2=${count2}, final=${finalCount}` 75 | }) 76 | } catch (error) { 77 | testResults.push({ 78 | name: 'ComlinkSharedWorker', 79 | passed: false, 80 | message: `Error: ${error}` 81 | }) 82 | } 83 | } else { 84 | testResults.push({ 85 | name: 'ComlinkSharedWorker', 86 | passed: false, 87 | message: 'SharedWorker not supported' 88 | }) 89 | } 90 | 91 | // Test 4: Nested Worker Creation (simulation test) 92 | try { 93 | const nestedWorker = new ComlinkWorker( 94 | new URL('./nested-worker.ts', import.meta.url) 95 | ) 96 | 97 | // Test that the nested worker creates and uses another worker internally 98 | const complexResult = await nestedWorker.processComplexData({ 99 | numbers: [1, 2, 3], 100 | multiplier: 3 101 | }) 102 | 103 | const asyncResult = await nestedWorker.asyncChainOperation() 104 | 105 | testResults.push({ 106 | name: 'Nested Worker Simulation', 107 | passed: complexResult === 18 && asyncResult === 20, 108 | message: `Nested simulation: complex=${complexResult}, async=${asyncResult}` 109 | }) 110 | } catch (error) { 111 | testResults.push({ 112 | name: 'Nested Worker Simulation', 113 | passed: false, 114 | message: `Error: ${error}` 115 | }) 116 | } 117 | 118 | // Test 5: Complex Data Processing 119 | try { 120 | const nestedWorker = new ComlinkWorker( 121 | new URL('./nested-worker.ts', import.meta.url) 122 | ) 123 | 124 | const complexResult = await nestedWorker.processComplexData({ 125 | numbers: [1, 2, 3, 4, 5], 126 | multiplier: 2 127 | }) 128 | 129 | const asyncChainResult = await nestedWorker.asyncChainOperation() 130 | 131 | testResults.push({ 132 | name: 'Complex Data Processing', 133 | passed: complexResult === 30 && asyncChainResult === 20, 134 | message: `Complex: sum=${complexResult}, chain=${asyncChainResult}` 135 | }) 136 | } catch (error) { 137 | testResults.push({ 138 | name: 'Complex Data Processing', 139 | passed: false, 140 | message: `Error: ${error}` 141 | }) 142 | } 143 | 144 | // Test 6: Worker in Function (moved up) 145 | try { 146 | const conditionalWorker = new ComlinkWorker( 147 | new URL('./conditional-worker.ts', import.meta.url) 148 | ) 149 | 150 | const functionResult = await conditionalWorker.testWorkerInFunction() 151 | 152 | testResults.push({ 153 | name: 'Worker in Function', 154 | passed: functionResult === 30, 155 | message: `Function worker: add(10,20)=${functionResult}` 156 | }) 157 | } catch (error) { 158 | testResults.push({ 159 | name: 'Worker in Function', 160 | passed: false, 161 | message: `Error: ${error}` 162 | }) 163 | } 164 | 165 | // Test 7: Multiple Workers Management 166 | try { 167 | const conditionalWorker = new ComlinkWorker( 168 | new URL('./conditional-worker.ts', import.meta.url) 169 | ) 170 | 171 | const workerCount = await conditionalWorker.createMultipleWorkers(3) 172 | const results = await conditionalWorker.testAllWorkers() 173 | 174 | const expectedResults = [1, 3, 5] // [0+1, 1+2, 2+3] 175 | const resultsMatch = results.length === 3 && 176 | results[0] === expectedResults[0] && 177 | results[1] === expectedResults[1] && 178 | results[2] === expectedResults[2] 179 | 180 | testResults.push({ 181 | name: 'Multiple Workers Management', 182 | passed: workerCount === 3 && resultsMatch, 183 | message: `Manager: created=${workerCount}, results=[${results.join(', ')}]` 184 | }) 185 | } catch (error) { 186 | testResults.push({ 187 | name: 'Multiple Workers Management', 188 | passed: false, 189 | message: `Error: ${error}` 190 | }) 191 | } 192 | 193 | // Display results 194 | const allPassed = testResults.every(r => r.passed) 195 | 196 | results.innerHTML = ` 197 |

Test Results: ${allPassed ? '✅ ALL PASSED' : '❌ SOME FAILED'}

198 | ${testResults.map(r => ` 199 |
200 | ${r.passed ? '✅' : '❌'} ${r.name}
201 | ${r.message} 202 |
203 | `).join('')} 204 | ` 205 | 206 | // Set data attribute for automated testing 207 | document.body.setAttribute('data-tests-complete', 'true') 208 | document.body.setAttribute('data-tests-passed', allPassed.toString()) 209 | 210 | // Also log to console for CI 211 | console.log('TEST RESULTS:', JSON.stringify(testResults, null, 2)) 212 | 213 | return allPassed 214 | } 215 | 216 | // Run tests when page loads 217 | window.addEventListener('load', runTests) -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import JSON5 from "json5"; 2 | import MagicString from "magic-string"; 3 | import { Plugin, normalizePath } from "vite"; 4 | import { SourceMapConsumer, SourceMapGenerator } from "source-map"; 5 | 6 | // Template string to avoid static analysis issues with import.meta.url 7 | const importMetaUrl = `${"import"}.meta.url`; 8 | 9 | // Virtual module prefixes for identifying Comlink worker modules 10 | const urlPrefix_normal = "internal:comlink:"; 11 | const urlPrefix_shared = "internal:comlink-shared:"; 12 | 13 | // Global state to track build mode and project root 14 | // These are set during Vite's config resolution phase 15 | let mode = ""; 16 | let root = ""; 17 | 18 | /** 19 | * Vite plugin that automatically integrates Comlink with WebWorkers and SharedWorkers. 20 | * 21 | * This plugin transforms ComlinkWorker and ComlinkSharedWorker constructor calls 22 | * to regular Worker/SharedWorker instances wrapped with Comlink's expose/wrap functionality. 23 | * 24 | * @returns Array of Vite plugins (currently contains only one plugin) 25 | */ 26 | export function comlink(): Plugin[] { 27 | return [ 28 | { 29 | /** 30 | * Store Vite configuration values for later use in transformations 31 | */ 32 | configResolved(conf) { 33 | mode = conf.mode; 34 | root = conf.root; 35 | }, 36 | name: "comlink", 37 | 38 | /** 39 | * Resolve virtual module IDs for Comlink worker wrappers. 40 | * 41 | * When a ComlinkWorker/ComlinkSharedWorker is detected, we create virtual modules 42 | * with special prefixes that contain the Comlink setup code. 43 | * 44 | * @param id - Module ID to resolve 45 | * @returns Resolved ID if it's a Comlink virtual module, undefined otherwise 46 | */ 47 | resolveId(id) { 48 | if (id.includes(urlPrefix_normal)) { 49 | return urlPrefix_normal + id.split(urlPrefix_normal)[1]; 50 | } 51 | if (id.includes(urlPrefix_shared)) { 52 | return urlPrefix_shared + id.split(urlPrefix_shared)[1]; 53 | } 54 | }, 55 | /** 56 | * Load virtual modules that contain Comlink worker setup code. 57 | * 58 | * This creates wrapper modules that automatically call Comlink's expose() 59 | * function with the worker's exported API. 60 | * 61 | * @param id - Module ID to load 62 | * @returns Generated module code for Comlink setup, or undefined 63 | */ 64 | async load(id) { 65 | if (id.includes(urlPrefix_normal)) { 66 | // Extract the real worker file path from the virtual module ID 67 | const realID = normalizePath(id.replace(urlPrefix_normal, "")); 68 | 69 | // Generate wrapper code for regular Workers 70 | // This imports the worker's API and exposes it through Comlink 71 | return ` 72 | import {expose} from 'comlink' 73 | import * as api from '${normalizePath(realID)}' 74 | 75 | expose(api) 76 | `; 77 | } 78 | 79 | if (id.includes(urlPrefix_shared)) { 80 | // Extract the real worker file path from the virtual module ID 81 | const realID = normalizePath(id.replace(urlPrefix_shared, "")); 82 | 83 | // Generate wrapper code for SharedWorkers 84 | // SharedWorkers need to handle the 'connect' event and expose on each port 85 | return ` 86 | import {expose} from 'comlink' 87 | import * as api from '${normalizePath(realID)}' 88 | 89 | addEventListener('connect', (event) => { 90 | const port = event.ports[0]; 91 | 92 | expose(api, port); 93 | // Note: port.start() is typically not needed as expose() handles this 94 | }) 95 | `; 96 | } 97 | }, 98 | /** 99 | * Transform source code to replace ComlinkWorker/ComlinkSharedWorker constructors. 100 | * 101 | * This is the core transformation that: 102 | * 1. Finds ComlinkWorker/ComlinkSharedWorker constructor calls 103 | * 2. Extracts the worker URL and options 104 | * 3. Replaces them with regular Worker/SharedWorker constructors 105 | * 4. Wraps the result with Comlink's wrap() function 106 | * 5. Redirects to virtual modules for automatic Comlink setup 107 | * 108 | * @param code - Source code to transform 109 | * @param id - File ID being transformed 110 | * @returns Transformed code with source maps, or undefined if no changes needed 111 | */ 112 | async transform(code: string, id: string) { 113 | // Early exit if file doesn't contain Comlink worker constructors 114 | if ( 115 | !code.includes("ComlinkWorker") && 116 | !code.includes("ComlinkSharedWorker") 117 | ) 118 | return; 119 | 120 | // Regex to match ComlinkWorker/ComlinkSharedWorker constructor patterns 121 | // Captures: new keyword, constructor type, URL parameters, options, closing parenthesis 122 | const workerSearcher = 123 | /(\bnew\s+)(ComlinkWorker|ComlinkSharedWorker)(\s*\(\s*new\s+URL\s*\(\s*)('[^']+'|"[^"]+"|`[^`]+`)(\s*,\s*import\.meta\.url\s*\)\s*)(,?)([^\)]*)(\))/g; 124 | 125 | let s: MagicString = new MagicString(code); 126 | 127 | const matches = code.matchAll(workerSearcher); 128 | 129 | // Process each matched ComlinkWorker/ComlinkSharedWorker constructor 130 | for (const match of matches) { 131 | const index = match.index!; 132 | const matchCode = match[0]; 133 | 134 | // Extract regex capture groups 135 | const c1_new = match[1]; // "new " keyword 136 | const c2_type = match[2]; // "ComlinkWorker" or "ComlinkSharedWorker" 137 | const c3_new_url = match[3]; // "new URL(" part 138 | let c4_path = match[4]; // The quoted path string 139 | const c5_import_meta = match[5]; // ", import.meta.url)" part 140 | const c6_koma = match[6]; // Optional comma before options 141 | const c7_options = match[7]; // Worker options object 142 | const c8_end = match[8]; // Closing parenthesis 143 | 144 | // Parse worker options using JSON5 (supports comments, trailing commas, etc.) 145 | const opt = c7_options ? JSON5.parse(c7_options) : {}; 146 | 147 | // Extract and remove quotes from the path 148 | const urlQuote = c4_path[0]; 149 | c4_path = c4_path.substring(1, c4_path.length - 1); 150 | 151 | // Force module type in development for better debugging experience 152 | if (mode === "development") { 153 | opt.type = "module"; 154 | } 155 | const options = JSON.stringify(opt); 156 | 157 | // Determine virtual module prefix and native worker class based on type 158 | const prefix = 159 | c2_type === "ComlinkWorker" ? urlPrefix_normal : urlPrefix_shared; 160 | const className = 161 | c2_type == "ComlinkWorker" ? "Worker" : "SharedWorker"; 162 | 163 | // Resolve the worker file path using Vite's resolution system 164 | const res = await this.resolve(c4_path, id, {}); 165 | let path = c4_path; 166 | 167 | if (res) { 168 | path = res.id; 169 | // Convert absolute path to relative if it's within project root 170 | if (path.startsWith(root)) { 171 | path = path.substring(root.length); 172 | } 173 | } 174 | 175 | // Build the new worker constructor with virtual module URL 176 | const worker_constructor = `${c1_new}${className}${c3_new_url}${urlQuote}${prefix}${path}${urlQuote}${c5_import_meta},${options}${c8_end}`; 177 | 178 | // SharedWorkers need .port property to access MessagePort 179 | const extra_shared = c2_type == "ComlinkWorker" ? "" : ".port"; 180 | 181 | // Generate the final code that wraps the worker with Comlink 182 | const insertCode = `___wrap((${worker_constructor})${extra_shared});\n`; 183 | 184 | // Replace the original constructor call with our transformed version 185 | s.overwrite(index, index + matchCode.length, insertCode); 186 | } 187 | 188 | // Add import for Comlink wrap function at the top of the file 189 | s.appendLeft( 190 | 0, 191 | `import {wrap as ___wrap} from 'vite-plugin-comlink/symbol';\n` 192 | ); 193 | 194 | // Generate source map for our transformations with high resolution 195 | const magicStringMap = s.generateMap({ 196 | source: id, 197 | includeContent: true, 198 | hires: true // High-resolution source maps for better debugging 199 | }); 200 | 201 | // Get the existing source map from previous transforms in the pipeline 202 | const existingMap = this.getCombinedSourcemap(); 203 | 204 | let finalMap = magicStringMap; 205 | 206 | // Combine source maps if there are previous transformations 207 | // This ensures debugging works correctly through the entire transformation chain 208 | if (existingMap && existingMap.mappings && existingMap.mappings !== '') { 209 | try { 210 | // Create consumers for both source maps 211 | const existingConsumer = await new SourceMapConsumer(existingMap); 212 | const newConsumer = await new SourceMapConsumer(magicStringMap); 213 | 214 | // Create a new generator and apply the transformations 215 | const generator = SourceMapGenerator.fromSourceMap(newConsumer); 216 | generator.applySourceMap(existingConsumer, id); 217 | 218 | finalMap = generator.toJSON() as any; 219 | 220 | // Clean up consumers to prevent memory leaks 221 | existingConsumer.destroy(); 222 | newConsumer.destroy(); 223 | } catch (error) { 224 | // If source map combination fails, fall back to our generated map 225 | // This ensures the build doesn't fail due to source map issues 226 | console.warn('Failed to combine source maps:', error); 227 | finalMap = magicStringMap; 228 | } 229 | } 230 | 231 | return { 232 | code: s.toString(), 233 | map: finalMap, 234 | }; 235 | }, 236 | } as Plugin, 237 | ]; 238 | } 239 | 240 | // Export as default for convenience 241 | export default comlink; 242 | -------------------------------------------------------------------------------- /example/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "example", 9 | "version": "0.0.0", 10 | "dependencies": { 11 | "comlink": "^4.4.1" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.2.2", 15 | "vite": "^7.0.6", 16 | "vite-plugin-comlink": "../", 17 | "vite-plugin-inspect": "^11.3.2" 18 | } 19 | }, 20 | "..": { 21 | "version": "5.3.0", 22 | "dev": true, 23 | "license": "MIT", 24 | "dependencies": { 25 | "json5": "2.2.3", 26 | "magic-string": "0.30.17", 27 | "source-map": "^0.7.4" 28 | }, 29 | "devDependencies": { 30 | "@types/node": "22.17.0", 31 | "comlink": "4.4.2", 32 | "tsup": "8.5.0", 33 | "typescript": "5.7.3", 34 | "vite": "5.4.19" 35 | }, 36 | "peerDependencies": { 37 | "comlink": "^4.3.1", 38 | "vite": ">=2.9.6" 39 | } 40 | }, 41 | "node_modules/@esbuild/aix-ppc64": { 42 | "version": "0.25.8", 43 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", 44 | "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", 45 | "cpu": [ 46 | "ppc64" 47 | ], 48 | "dev": true, 49 | "license": "MIT", 50 | "optional": true, 51 | "os": [ 52 | "aix" 53 | ], 54 | "engines": { 55 | "node": ">=18" 56 | } 57 | }, 58 | "node_modules/@esbuild/android-arm": { 59 | "version": "0.25.8", 60 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", 61 | "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", 62 | "cpu": [ 63 | "arm" 64 | ], 65 | "dev": true, 66 | "license": "MIT", 67 | "optional": true, 68 | "os": [ 69 | "android" 70 | ], 71 | "engines": { 72 | "node": ">=18" 73 | } 74 | }, 75 | "node_modules/@esbuild/android-arm64": { 76 | "version": "0.25.8", 77 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", 78 | "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", 79 | "cpu": [ 80 | "arm64" 81 | ], 82 | "dev": true, 83 | "license": "MIT", 84 | "optional": true, 85 | "os": [ 86 | "android" 87 | ], 88 | "engines": { 89 | "node": ">=18" 90 | } 91 | }, 92 | "node_modules/@esbuild/android-x64": { 93 | "version": "0.25.8", 94 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", 95 | "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", 96 | "cpu": [ 97 | "x64" 98 | ], 99 | "dev": true, 100 | "license": "MIT", 101 | "optional": true, 102 | "os": [ 103 | "android" 104 | ], 105 | "engines": { 106 | "node": ">=18" 107 | } 108 | }, 109 | "node_modules/@esbuild/darwin-arm64": { 110 | "version": "0.25.8", 111 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", 112 | "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", 113 | "cpu": [ 114 | "arm64" 115 | ], 116 | "dev": true, 117 | "license": "MIT", 118 | "optional": true, 119 | "os": [ 120 | "darwin" 121 | ], 122 | "engines": { 123 | "node": ">=18" 124 | } 125 | }, 126 | "node_modules/@esbuild/darwin-x64": { 127 | "version": "0.25.8", 128 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", 129 | "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", 130 | "cpu": [ 131 | "x64" 132 | ], 133 | "dev": true, 134 | "license": "MIT", 135 | "optional": true, 136 | "os": [ 137 | "darwin" 138 | ], 139 | "engines": { 140 | "node": ">=18" 141 | } 142 | }, 143 | "node_modules/@esbuild/freebsd-arm64": { 144 | "version": "0.25.8", 145 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", 146 | "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", 147 | "cpu": [ 148 | "arm64" 149 | ], 150 | "dev": true, 151 | "license": "MIT", 152 | "optional": true, 153 | "os": [ 154 | "freebsd" 155 | ], 156 | "engines": { 157 | "node": ">=18" 158 | } 159 | }, 160 | "node_modules/@esbuild/freebsd-x64": { 161 | "version": "0.25.8", 162 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", 163 | "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", 164 | "cpu": [ 165 | "x64" 166 | ], 167 | "dev": true, 168 | "license": "MIT", 169 | "optional": true, 170 | "os": [ 171 | "freebsd" 172 | ], 173 | "engines": { 174 | "node": ">=18" 175 | } 176 | }, 177 | "node_modules/@esbuild/linux-arm": { 178 | "version": "0.25.8", 179 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", 180 | "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", 181 | "cpu": [ 182 | "arm" 183 | ], 184 | "dev": true, 185 | "license": "MIT", 186 | "optional": true, 187 | "os": [ 188 | "linux" 189 | ], 190 | "engines": { 191 | "node": ">=18" 192 | } 193 | }, 194 | "node_modules/@esbuild/linux-arm64": { 195 | "version": "0.25.8", 196 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", 197 | "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", 198 | "cpu": [ 199 | "arm64" 200 | ], 201 | "dev": true, 202 | "license": "MIT", 203 | "optional": true, 204 | "os": [ 205 | "linux" 206 | ], 207 | "engines": { 208 | "node": ">=18" 209 | } 210 | }, 211 | "node_modules/@esbuild/linux-ia32": { 212 | "version": "0.25.8", 213 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", 214 | "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", 215 | "cpu": [ 216 | "ia32" 217 | ], 218 | "dev": true, 219 | "license": "MIT", 220 | "optional": true, 221 | "os": [ 222 | "linux" 223 | ], 224 | "engines": { 225 | "node": ">=18" 226 | } 227 | }, 228 | "node_modules/@esbuild/linux-loong64": { 229 | "version": "0.25.8", 230 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", 231 | "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", 232 | "cpu": [ 233 | "loong64" 234 | ], 235 | "dev": true, 236 | "license": "MIT", 237 | "optional": true, 238 | "os": [ 239 | "linux" 240 | ], 241 | "engines": { 242 | "node": ">=18" 243 | } 244 | }, 245 | "node_modules/@esbuild/linux-mips64el": { 246 | "version": "0.25.8", 247 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", 248 | "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", 249 | "cpu": [ 250 | "mips64el" 251 | ], 252 | "dev": true, 253 | "license": "MIT", 254 | "optional": true, 255 | "os": [ 256 | "linux" 257 | ], 258 | "engines": { 259 | "node": ">=18" 260 | } 261 | }, 262 | "node_modules/@esbuild/linux-ppc64": { 263 | "version": "0.25.8", 264 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", 265 | "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", 266 | "cpu": [ 267 | "ppc64" 268 | ], 269 | "dev": true, 270 | "license": "MIT", 271 | "optional": true, 272 | "os": [ 273 | "linux" 274 | ], 275 | "engines": { 276 | "node": ">=18" 277 | } 278 | }, 279 | "node_modules/@esbuild/linux-riscv64": { 280 | "version": "0.25.8", 281 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", 282 | "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", 283 | "cpu": [ 284 | "riscv64" 285 | ], 286 | "dev": true, 287 | "license": "MIT", 288 | "optional": true, 289 | "os": [ 290 | "linux" 291 | ], 292 | "engines": { 293 | "node": ">=18" 294 | } 295 | }, 296 | "node_modules/@esbuild/linux-s390x": { 297 | "version": "0.25.8", 298 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", 299 | "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", 300 | "cpu": [ 301 | "s390x" 302 | ], 303 | "dev": true, 304 | "license": "MIT", 305 | "optional": true, 306 | "os": [ 307 | "linux" 308 | ], 309 | "engines": { 310 | "node": ">=18" 311 | } 312 | }, 313 | "node_modules/@esbuild/linux-x64": { 314 | "version": "0.25.8", 315 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", 316 | "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", 317 | "cpu": [ 318 | "x64" 319 | ], 320 | "dev": true, 321 | "license": "MIT", 322 | "optional": true, 323 | "os": [ 324 | "linux" 325 | ], 326 | "engines": { 327 | "node": ">=18" 328 | } 329 | }, 330 | "node_modules/@esbuild/netbsd-arm64": { 331 | "version": "0.25.8", 332 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", 333 | "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", 334 | "cpu": [ 335 | "arm64" 336 | ], 337 | "dev": true, 338 | "license": "MIT", 339 | "optional": true, 340 | "os": [ 341 | "netbsd" 342 | ], 343 | "engines": { 344 | "node": ">=18" 345 | } 346 | }, 347 | "node_modules/@esbuild/netbsd-x64": { 348 | "version": "0.25.8", 349 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", 350 | "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", 351 | "cpu": [ 352 | "x64" 353 | ], 354 | "dev": true, 355 | "license": "MIT", 356 | "optional": true, 357 | "os": [ 358 | "netbsd" 359 | ], 360 | "engines": { 361 | "node": ">=18" 362 | } 363 | }, 364 | "node_modules/@esbuild/openbsd-arm64": { 365 | "version": "0.25.8", 366 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", 367 | "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", 368 | "cpu": [ 369 | "arm64" 370 | ], 371 | "dev": true, 372 | "license": "MIT", 373 | "optional": true, 374 | "os": [ 375 | "openbsd" 376 | ], 377 | "engines": { 378 | "node": ">=18" 379 | } 380 | }, 381 | "node_modules/@esbuild/openbsd-x64": { 382 | "version": "0.25.8", 383 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", 384 | "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", 385 | "cpu": [ 386 | "x64" 387 | ], 388 | "dev": true, 389 | "license": "MIT", 390 | "optional": true, 391 | "os": [ 392 | "openbsd" 393 | ], 394 | "engines": { 395 | "node": ">=18" 396 | } 397 | }, 398 | "node_modules/@esbuild/openharmony-arm64": { 399 | "version": "0.25.8", 400 | "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", 401 | "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", 402 | "cpu": [ 403 | "arm64" 404 | ], 405 | "dev": true, 406 | "license": "MIT", 407 | "optional": true, 408 | "os": [ 409 | "openharmony" 410 | ], 411 | "engines": { 412 | "node": ">=18" 413 | } 414 | }, 415 | "node_modules/@esbuild/sunos-x64": { 416 | "version": "0.25.8", 417 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", 418 | "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", 419 | "cpu": [ 420 | "x64" 421 | ], 422 | "dev": true, 423 | "license": "MIT", 424 | "optional": true, 425 | "os": [ 426 | "sunos" 427 | ], 428 | "engines": { 429 | "node": ">=18" 430 | } 431 | }, 432 | "node_modules/@esbuild/win32-arm64": { 433 | "version": "0.25.8", 434 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", 435 | "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", 436 | "cpu": [ 437 | "arm64" 438 | ], 439 | "dev": true, 440 | "license": "MIT", 441 | "optional": true, 442 | "os": [ 443 | "win32" 444 | ], 445 | "engines": { 446 | "node": ">=18" 447 | } 448 | }, 449 | "node_modules/@esbuild/win32-ia32": { 450 | "version": "0.25.8", 451 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", 452 | "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", 453 | "cpu": [ 454 | "ia32" 455 | ], 456 | "dev": true, 457 | "license": "MIT", 458 | "optional": true, 459 | "os": [ 460 | "win32" 461 | ], 462 | "engines": { 463 | "node": ">=18" 464 | } 465 | }, 466 | "node_modules/@esbuild/win32-x64": { 467 | "version": "0.25.8", 468 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", 469 | "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", 470 | "cpu": [ 471 | "x64" 472 | ], 473 | "dev": true, 474 | "license": "MIT", 475 | "optional": true, 476 | "os": [ 477 | "win32" 478 | ], 479 | "engines": { 480 | "node": ">=18" 481 | } 482 | }, 483 | "node_modules/@polka/url": { 484 | "version": "1.0.0-next.29", 485 | "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", 486 | "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", 487 | "dev": true, 488 | "license": "MIT" 489 | }, 490 | "node_modules/@rollup/rollup-android-arm-eabi": { 491 | "version": "4.46.2", 492 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", 493 | "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", 494 | "cpu": [ 495 | "arm" 496 | ], 497 | "dev": true, 498 | "license": "MIT", 499 | "optional": true, 500 | "os": [ 501 | "android" 502 | ] 503 | }, 504 | "node_modules/@rollup/rollup-android-arm64": { 505 | "version": "4.46.2", 506 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", 507 | "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", 508 | "cpu": [ 509 | "arm64" 510 | ], 511 | "dev": true, 512 | "license": "MIT", 513 | "optional": true, 514 | "os": [ 515 | "android" 516 | ] 517 | }, 518 | "node_modules/@rollup/rollup-darwin-arm64": { 519 | "version": "4.46.2", 520 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", 521 | "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", 522 | "cpu": [ 523 | "arm64" 524 | ], 525 | "dev": true, 526 | "license": "MIT", 527 | "optional": true, 528 | "os": [ 529 | "darwin" 530 | ] 531 | }, 532 | "node_modules/@rollup/rollup-darwin-x64": { 533 | "version": "4.46.2", 534 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", 535 | "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", 536 | "cpu": [ 537 | "x64" 538 | ], 539 | "dev": true, 540 | "license": "MIT", 541 | "optional": true, 542 | "os": [ 543 | "darwin" 544 | ] 545 | }, 546 | "node_modules/@rollup/rollup-freebsd-arm64": { 547 | "version": "4.46.2", 548 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", 549 | "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", 550 | "cpu": [ 551 | "arm64" 552 | ], 553 | "dev": true, 554 | "license": "MIT", 555 | "optional": true, 556 | "os": [ 557 | "freebsd" 558 | ] 559 | }, 560 | "node_modules/@rollup/rollup-freebsd-x64": { 561 | "version": "4.46.2", 562 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", 563 | "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", 564 | "cpu": [ 565 | "x64" 566 | ], 567 | "dev": true, 568 | "license": "MIT", 569 | "optional": true, 570 | "os": [ 571 | "freebsd" 572 | ] 573 | }, 574 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 575 | "version": "4.46.2", 576 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", 577 | "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", 578 | "cpu": [ 579 | "arm" 580 | ], 581 | "dev": true, 582 | "license": "MIT", 583 | "optional": true, 584 | "os": [ 585 | "linux" 586 | ] 587 | }, 588 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 589 | "version": "4.46.2", 590 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", 591 | "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", 592 | "cpu": [ 593 | "arm" 594 | ], 595 | "dev": true, 596 | "license": "MIT", 597 | "optional": true, 598 | "os": [ 599 | "linux" 600 | ] 601 | }, 602 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 603 | "version": "4.46.2", 604 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", 605 | "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", 606 | "cpu": [ 607 | "arm64" 608 | ], 609 | "dev": true, 610 | "license": "MIT", 611 | "optional": true, 612 | "os": [ 613 | "linux" 614 | ] 615 | }, 616 | "node_modules/@rollup/rollup-linux-arm64-musl": { 617 | "version": "4.46.2", 618 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", 619 | "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", 620 | "cpu": [ 621 | "arm64" 622 | ], 623 | "dev": true, 624 | "license": "MIT", 625 | "optional": true, 626 | "os": [ 627 | "linux" 628 | ] 629 | }, 630 | "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 631 | "version": "4.46.2", 632 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", 633 | "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", 634 | "cpu": [ 635 | "loong64" 636 | ], 637 | "dev": true, 638 | "license": "MIT", 639 | "optional": true, 640 | "os": [ 641 | "linux" 642 | ] 643 | }, 644 | "node_modules/@rollup/rollup-linux-ppc64-gnu": { 645 | "version": "4.46.2", 646 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", 647 | "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", 648 | "cpu": [ 649 | "ppc64" 650 | ], 651 | "dev": true, 652 | "license": "MIT", 653 | "optional": true, 654 | "os": [ 655 | "linux" 656 | ] 657 | }, 658 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 659 | "version": "4.46.2", 660 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", 661 | "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", 662 | "cpu": [ 663 | "riscv64" 664 | ], 665 | "dev": true, 666 | "license": "MIT", 667 | "optional": true, 668 | "os": [ 669 | "linux" 670 | ] 671 | }, 672 | "node_modules/@rollup/rollup-linux-riscv64-musl": { 673 | "version": "4.46.2", 674 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", 675 | "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", 676 | "cpu": [ 677 | "riscv64" 678 | ], 679 | "dev": true, 680 | "license": "MIT", 681 | "optional": true, 682 | "os": [ 683 | "linux" 684 | ] 685 | }, 686 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 687 | "version": "4.46.2", 688 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", 689 | "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", 690 | "cpu": [ 691 | "s390x" 692 | ], 693 | "dev": true, 694 | "license": "MIT", 695 | "optional": true, 696 | "os": [ 697 | "linux" 698 | ] 699 | }, 700 | "node_modules/@rollup/rollup-linux-x64-gnu": { 701 | "version": "4.46.2", 702 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", 703 | "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", 704 | "cpu": [ 705 | "x64" 706 | ], 707 | "dev": true, 708 | "license": "MIT", 709 | "optional": true, 710 | "os": [ 711 | "linux" 712 | ] 713 | }, 714 | "node_modules/@rollup/rollup-linux-x64-musl": { 715 | "version": "4.46.2", 716 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", 717 | "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", 718 | "cpu": [ 719 | "x64" 720 | ], 721 | "dev": true, 722 | "license": "MIT", 723 | "optional": true, 724 | "os": [ 725 | "linux" 726 | ] 727 | }, 728 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 729 | "version": "4.46.2", 730 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", 731 | "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", 732 | "cpu": [ 733 | "arm64" 734 | ], 735 | "dev": true, 736 | "license": "MIT", 737 | "optional": true, 738 | "os": [ 739 | "win32" 740 | ] 741 | }, 742 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 743 | "version": "4.46.2", 744 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", 745 | "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", 746 | "cpu": [ 747 | "ia32" 748 | ], 749 | "dev": true, 750 | "license": "MIT", 751 | "optional": true, 752 | "os": [ 753 | "win32" 754 | ] 755 | }, 756 | "node_modules/@rollup/rollup-win32-x64-msvc": { 757 | "version": "4.46.2", 758 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", 759 | "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", 760 | "cpu": [ 761 | "x64" 762 | ], 763 | "dev": true, 764 | "license": "MIT", 765 | "optional": true, 766 | "os": [ 767 | "win32" 768 | ] 769 | }, 770 | "node_modules/@types/estree": { 771 | "version": "1.0.8", 772 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", 773 | "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", 774 | "dev": true, 775 | "license": "MIT" 776 | }, 777 | "node_modules/ansis": { 778 | "version": "4.1.0", 779 | "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.1.0.tgz", 780 | "integrity": "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==", 781 | "dev": true, 782 | "license": "ISC", 783 | "engines": { 784 | "node": ">=14" 785 | } 786 | }, 787 | "node_modules/birpc": { 788 | "version": "2.5.0", 789 | "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.5.0.tgz", 790 | "integrity": "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==", 791 | "dev": true, 792 | "license": "MIT", 793 | "funding": { 794 | "url": "https://github.com/sponsors/antfu" 795 | } 796 | }, 797 | "node_modules/bundle-name": { 798 | "version": "4.1.0", 799 | "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", 800 | "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", 801 | "dev": true, 802 | "license": "MIT", 803 | "dependencies": { 804 | "run-applescript": "^7.0.0" 805 | }, 806 | "engines": { 807 | "node": ">=18" 808 | }, 809 | "funding": { 810 | "url": "https://github.com/sponsors/sindresorhus" 811 | } 812 | }, 813 | "node_modules/comlink": { 814 | "version": "4.4.2", 815 | "resolved": "https://registry.npmjs.org/comlink/-/comlink-4.4.2.tgz", 816 | "integrity": "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==", 817 | "license": "Apache-2.0" 818 | }, 819 | "node_modules/debug": { 820 | "version": "4.4.1", 821 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", 822 | "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", 823 | "dev": true, 824 | "license": "MIT", 825 | "dependencies": { 826 | "ms": "^2.1.3" 827 | }, 828 | "engines": { 829 | "node": ">=6.0" 830 | }, 831 | "peerDependenciesMeta": { 832 | "supports-color": { 833 | "optional": true 834 | } 835 | } 836 | }, 837 | "node_modules/default-browser": { 838 | "version": "5.2.1", 839 | "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", 840 | "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", 841 | "dev": true, 842 | "license": "MIT", 843 | "dependencies": { 844 | "bundle-name": "^4.1.0", 845 | "default-browser-id": "^5.0.0" 846 | }, 847 | "engines": { 848 | "node": ">=18" 849 | }, 850 | "funding": { 851 | "url": "https://github.com/sponsors/sindresorhus" 852 | } 853 | }, 854 | "node_modules/default-browser-id": { 855 | "version": "5.0.0", 856 | "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", 857 | "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", 858 | "dev": true, 859 | "license": "MIT", 860 | "engines": { 861 | "node": ">=18" 862 | }, 863 | "funding": { 864 | "url": "https://github.com/sponsors/sindresorhus" 865 | } 866 | }, 867 | "node_modules/define-lazy-prop": { 868 | "version": "3.0.0", 869 | "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", 870 | "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", 871 | "dev": true, 872 | "license": "MIT", 873 | "engines": { 874 | "node": ">=12" 875 | }, 876 | "funding": { 877 | "url": "https://github.com/sponsors/sindresorhus" 878 | } 879 | }, 880 | "node_modules/error-stack-parser-es": { 881 | "version": "1.0.5", 882 | "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", 883 | "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", 884 | "dev": true, 885 | "license": "MIT", 886 | "funding": { 887 | "url": "https://github.com/sponsors/antfu" 888 | } 889 | }, 890 | "node_modules/esbuild": { 891 | "version": "0.25.8", 892 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", 893 | "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", 894 | "dev": true, 895 | "hasInstallScript": true, 896 | "license": "MIT", 897 | "bin": { 898 | "esbuild": "bin/esbuild" 899 | }, 900 | "engines": { 901 | "node": ">=18" 902 | }, 903 | "optionalDependencies": { 904 | "@esbuild/aix-ppc64": "0.25.8", 905 | "@esbuild/android-arm": "0.25.8", 906 | "@esbuild/android-arm64": "0.25.8", 907 | "@esbuild/android-x64": "0.25.8", 908 | "@esbuild/darwin-arm64": "0.25.8", 909 | "@esbuild/darwin-x64": "0.25.8", 910 | "@esbuild/freebsd-arm64": "0.25.8", 911 | "@esbuild/freebsd-x64": "0.25.8", 912 | "@esbuild/linux-arm": "0.25.8", 913 | "@esbuild/linux-arm64": "0.25.8", 914 | "@esbuild/linux-ia32": "0.25.8", 915 | "@esbuild/linux-loong64": "0.25.8", 916 | "@esbuild/linux-mips64el": "0.25.8", 917 | "@esbuild/linux-ppc64": "0.25.8", 918 | "@esbuild/linux-riscv64": "0.25.8", 919 | "@esbuild/linux-s390x": "0.25.8", 920 | "@esbuild/linux-x64": "0.25.8", 921 | "@esbuild/netbsd-arm64": "0.25.8", 922 | "@esbuild/netbsd-x64": "0.25.8", 923 | "@esbuild/openbsd-arm64": "0.25.8", 924 | "@esbuild/openbsd-x64": "0.25.8", 925 | "@esbuild/openharmony-arm64": "0.25.8", 926 | "@esbuild/sunos-x64": "0.25.8", 927 | "@esbuild/win32-arm64": "0.25.8", 928 | "@esbuild/win32-ia32": "0.25.8", 929 | "@esbuild/win32-x64": "0.25.8" 930 | } 931 | }, 932 | "node_modules/fsevents": { 933 | "version": "2.3.3", 934 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 935 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 936 | "dev": true, 937 | "hasInstallScript": true, 938 | "optional": true, 939 | "os": [ 940 | "darwin" 941 | ], 942 | "engines": { 943 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 944 | } 945 | }, 946 | "node_modules/is-docker": { 947 | "version": "3.0.0", 948 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", 949 | "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", 950 | "dev": true, 951 | "license": "MIT", 952 | "bin": { 953 | "is-docker": "cli.js" 954 | }, 955 | "engines": { 956 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 957 | }, 958 | "funding": { 959 | "url": "https://github.com/sponsors/sindresorhus" 960 | } 961 | }, 962 | "node_modules/is-inside-container": { 963 | "version": "1.0.0", 964 | "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", 965 | "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", 966 | "dev": true, 967 | "license": "MIT", 968 | "dependencies": { 969 | "is-docker": "^3.0.0" 970 | }, 971 | "bin": { 972 | "is-inside-container": "cli.js" 973 | }, 974 | "engines": { 975 | "node": ">=14.16" 976 | }, 977 | "funding": { 978 | "url": "https://github.com/sponsors/sindresorhus" 979 | } 980 | }, 981 | "node_modules/is-wsl": { 982 | "version": "3.1.0", 983 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", 984 | "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", 985 | "dev": true, 986 | "license": "MIT", 987 | "dependencies": { 988 | "is-inside-container": "^1.0.0" 989 | }, 990 | "engines": { 991 | "node": ">=16" 992 | }, 993 | "funding": { 994 | "url": "https://github.com/sponsors/sindresorhus" 995 | } 996 | }, 997 | "node_modules/mrmime": { 998 | "version": "2.0.1", 999 | "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", 1000 | "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", 1001 | "dev": true, 1002 | "license": "MIT", 1003 | "engines": { 1004 | "node": ">=10" 1005 | } 1006 | }, 1007 | "node_modules/ms": { 1008 | "version": "2.1.3", 1009 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1010 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1011 | "dev": true, 1012 | "license": "MIT" 1013 | }, 1014 | "node_modules/nanoid": { 1015 | "version": "3.3.11", 1016 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 1017 | "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1018 | "dev": true, 1019 | "funding": [ 1020 | { 1021 | "type": "github", 1022 | "url": "https://github.com/sponsors/ai" 1023 | } 1024 | ], 1025 | "license": "MIT", 1026 | "bin": { 1027 | "nanoid": "bin/nanoid.cjs" 1028 | }, 1029 | "engines": { 1030 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1031 | } 1032 | }, 1033 | "node_modules/ohash": { 1034 | "version": "2.0.11", 1035 | "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", 1036 | "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", 1037 | "dev": true, 1038 | "license": "MIT" 1039 | }, 1040 | "node_modules/open": { 1041 | "version": "10.2.0", 1042 | "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", 1043 | "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", 1044 | "dev": true, 1045 | "license": "MIT", 1046 | "dependencies": { 1047 | "default-browser": "^5.2.1", 1048 | "define-lazy-prop": "^3.0.0", 1049 | "is-inside-container": "^1.0.0", 1050 | "wsl-utils": "^0.1.0" 1051 | }, 1052 | "engines": { 1053 | "node": ">=18" 1054 | }, 1055 | "funding": { 1056 | "url": "https://github.com/sponsors/sindresorhus" 1057 | } 1058 | }, 1059 | "node_modules/pathe": { 1060 | "version": "2.0.3", 1061 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 1062 | "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 1063 | "dev": true, 1064 | "license": "MIT" 1065 | }, 1066 | "node_modules/perfect-debounce": { 1067 | "version": "1.0.0", 1068 | "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", 1069 | "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", 1070 | "dev": true, 1071 | "license": "MIT" 1072 | }, 1073 | "node_modules/picocolors": { 1074 | "version": "1.1.1", 1075 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1076 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1077 | "dev": true, 1078 | "license": "ISC" 1079 | }, 1080 | "node_modules/picomatch": { 1081 | "version": "4.0.3", 1082 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", 1083 | "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", 1084 | "dev": true, 1085 | "license": "MIT", 1086 | "engines": { 1087 | "node": ">=12" 1088 | }, 1089 | "funding": { 1090 | "url": "https://github.com/sponsors/jonschlinkert" 1091 | } 1092 | }, 1093 | "node_modules/postcss": { 1094 | "version": "8.5.6", 1095 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", 1096 | "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", 1097 | "dev": true, 1098 | "funding": [ 1099 | { 1100 | "type": "opencollective", 1101 | "url": "https://opencollective.com/postcss/" 1102 | }, 1103 | { 1104 | "type": "tidelift", 1105 | "url": "https://tidelift.com/funding/github/npm/postcss" 1106 | }, 1107 | { 1108 | "type": "github", 1109 | "url": "https://github.com/sponsors/ai" 1110 | } 1111 | ], 1112 | "license": "MIT", 1113 | "dependencies": { 1114 | "nanoid": "^3.3.11", 1115 | "picocolors": "^1.1.1", 1116 | "source-map-js": "^1.2.1" 1117 | }, 1118 | "engines": { 1119 | "node": "^10 || ^12 || >=14" 1120 | } 1121 | }, 1122 | "node_modules/rollup": { 1123 | "version": "4.46.2", 1124 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", 1125 | "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", 1126 | "dev": true, 1127 | "license": "MIT", 1128 | "dependencies": { 1129 | "@types/estree": "1.0.8" 1130 | }, 1131 | "bin": { 1132 | "rollup": "dist/bin/rollup" 1133 | }, 1134 | "engines": { 1135 | "node": ">=18.0.0", 1136 | "npm": ">=8.0.0" 1137 | }, 1138 | "optionalDependencies": { 1139 | "@rollup/rollup-android-arm-eabi": "4.46.2", 1140 | "@rollup/rollup-android-arm64": "4.46.2", 1141 | "@rollup/rollup-darwin-arm64": "4.46.2", 1142 | "@rollup/rollup-darwin-x64": "4.46.2", 1143 | "@rollup/rollup-freebsd-arm64": "4.46.2", 1144 | "@rollup/rollup-freebsd-x64": "4.46.2", 1145 | "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", 1146 | "@rollup/rollup-linux-arm-musleabihf": "4.46.2", 1147 | "@rollup/rollup-linux-arm64-gnu": "4.46.2", 1148 | "@rollup/rollup-linux-arm64-musl": "4.46.2", 1149 | "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", 1150 | "@rollup/rollup-linux-ppc64-gnu": "4.46.2", 1151 | "@rollup/rollup-linux-riscv64-gnu": "4.46.2", 1152 | "@rollup/rollup-linux-riscv64-musl": "4.46.2", 1153 | "@rollup/rollup-linux-s390x-gnu": "4.46.2", 1154 | "@rollup/rollup-linux-x64-gnu": "4.46.2", 1155 | "@rollup/rollup-linux-x64-musl": "4.46.2", 1156 | "@rollup/rollup-win32-arm64-msvc": "4.46.2", 1157 | "@rollup/rollup-win32-ia32-msvc": "4.46.2", 1158 | "@rollup/rollup-win32-x64-msvc": "4.46.2", 1159 | "fsevents": "~2.3.2" 1160 | } 1161 | }, 1162 | "node_modules/run-applescript": { 1163 | "version": "7.0.0", 1164 | "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", 1165 | "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", 1166 | "dev": true, 1167 | "license": "MIT", 1168 | "engines": { 1169 | "node": ">=18" 1170 | }, 1171 | "funding": { 1172 | "url": "https://github.com/sponsors/sindresorhus" 1173 | } 1174 | }, 1175 | "node_modules/sirv": { 1176 | "version": "3.0.1", 1177 | "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", 1178 | "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", 1179 | "dev": true, 1180 | "license": "MIT", 1181 | "dependencies": { 1182 | "@polka/url": "^1.0.0-next.24", 1183 | "mrmime": "^2.0.0", 1184 | "totalist": "^3.0.0" 1185 | }, 1186 | "engines": { 1187 | "node": ">=18" 1188 | } 1189 | }, 1190 | "node_modules/source-map-js": { 1191 | "version": "1.2.1", 1192 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1193 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1194 | "dev": true, 1195 | "license": "BSD-3-Clause", 1196 | "engines": { 1197 | "node": ">=0.10.0" 1198 | } 1199 | }, 1200 | "node_modules/tinyglobby": { 1201 | "version": "0.2.14", 1202 | "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", 1203 | "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", 1204 | "dev": true, 1205 | "license": "MIT", 1206 | "dependencies": { 1207 | "fdir": "^6.4.4", 1208 | "picomatch": "^4.0.2" 1209 | }, 1210 | "engines": { 1211 | "node": ">=12.0.0" 1212 | }, 1213 | "funding": { 1214 | "url": "https://github.com/sponsors/SuperchupuDev" 1215 | } 1216 | }, 1217 | "node_modules/tinyglobby/node_modules/fdir": { 1218 | "version": "6.4.6", 1219 | "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", 1220 | "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", 1221 | "dev": true, 1222 | "license": "MIT", 1223 | "peerDependencies": { 1224 | "picomatch": "^3 || ^4" 1225 | }, 1226 | "peerDependenciesMeta": { 1227 | "picomatch": { 1228 | "optional": true 1229 | } 1230 | } 1231 | }, 1232 | "node_modules/totalist": { 1233 | "version": "3.0.1", 1234 | "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", 1235 | "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", 1236 | "dev": true, 1237 | "license": "MIT", 1238 | "engines": { 1239 | "node": ">=6" 1240 | } 1241 | }, 1242 | "node_modules/typescript": { 1243 | "version": "5.9.2", 1244 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", 1245 | "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", 1246 | "dev": true, 1247 | "license": "Apache-2.0", 1248 | "bin": { 1249 | "tsc": "bin/tsc", 1250 | "tsserver": "bin/tsserver" 1251 | }, 1252 | "engines": { 1253 | "node": ">=14.17" 1254 | } 1255 | }, 1256 | "node_modules/unplugin-utils": { 1257 | "version": "0.2.4", 1258 | "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.2.4.tgz", 1259 | "integrity": "sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==", 1260 | "dev": true, 1261 | "license": "MIT", 1262 | "dependencies": { 1263 | "pathe": "^2.0.2", 1264 | "picomatch": "^4.0.2" 1265 | }, 1266 | "engines": { 1267 | "node": ">=18.12.0" 1268 | }, 1269 | "funding": { 1270 | "url": "https://github.com/sponsors/sxzz" 1271 | } 1272 | }, 1273 | "node_modules/vite": { 1274 | "version": "7.0.6", 1275 | "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz", 1276 | "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==", 1277 | "dev": true, 1278 | "license": "MIT", 1279 | "dependencies": { 1280 | "esbuild": "^0.25.0", 1281 | "fdir": "^6.4.6", 1282 | "picomatch": "^4.0.3", 1283 | "postcss": "^8.5.6", 1284 | "rollup": "^4.40.0", 1285 | "tinyglobby": "^0.2.14" 1286 | }, 1287 | "bin": { 1288 | "vite": "bin/vite.js" 1289 | }, 1290 | "engines": { 1291 | "node": "^20.19.0 || >=22.12.0" 1292 | }, 1293 | "funding": { 1294 | "url": "https://github.com/vitejs/vite?sponsor=1" 1295 | }, 1296 | "optionalDependencies": { 1297 | "fsevents": "~2.3.3" 1298 | }, 1299 | "peerDependencies": { 1300 | "@types/node": "^20.19.0 || >=22.12.0", 1301 | "jiti": ">=1.21.0", 1302 | "less": "^4.0.0", 1303 | "lightningcss": "^1.21.0", 1304 | "sass": "^1.70.0", 1305 | "sass-embedded": "^1.70.0", 1306 | "stylus": ">=0.54.8", 1307 | "sugarss": "^5.0.0", 1308 | "terser": "^5.16.0", 1309 | "tsx": "^4.8.1", 1310 | "yaml": "^2.4.2" 1311 | }, 1312 | "peerDependenciesMeta": { 1313 | "@types/node": { 1314 | "optional": true 1315 | }, 1316 | "jiti": { 1317 | "optional": true 1318 | }, 1319 | "less": { 1320 | "optional": true 1321 | }, 1322 | "lightningcss": { 1323 | "optional": true 1324 | }, 1325 | "sass": { 1326 | "optional": true 1327 | }, 1328 | "sass-embedded": { 1329 | "optional": true 1330 | }, 1331 | "stylus": { 1332 | "optional": true 1333 | }, 1334 | "sugarss": { 1335 | "optional": true 1336 | }, 1337 | "terser": { 1338 | "optional": true 1339 | }, 1340 | "tsx": { 1341 | "optional": true 1342 | }, 1343 | "yaml": { 1344 | "optional": true 1345 | } 1346 | } 1347 | }, 1348 | "node_modules/vite-dev-rpc": { 1349 | "version": "1.1.0", 1350 | "resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz", 1351 | "integrity": "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==", 1352 | "dev": true, 1353 | "license": "MIT", 1354 | "dependencies": { 1355 | "birpc": "^2.4.0", 1356 | "vite-hot-client": "^2.1.0" 1357 | }, 1358 | "funding": { 1359 | "url": "https://github.com/sponsors/antfu" 1360 | }, 1361 | "peerDependencies": { 1362 | "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0" 1363 | } 1364 | }, 1365 | "node_modules/vite-hot-client": { 1366 | "version": "2.1.0", 1367 | "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.1.0.tgz", 1368 | "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", 1369 | "dev": true, 1370 | "license": "MIT", 1371 | "funding": { 1372 | "url": "https://github.com/sponsors/antfu" 1373 | }, 1374 | "peerDependencies": { 1375 | "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" 1376 | } 1377 | }, 1378 | "node_modules/vite-plugin-comlink": { 1379 | "resolved": "..", 1380 | "link": true 1381 | }, 1382 | "node_modules/vite-plugin-inspect": { 1383 | "version": "11.3.2", 1384 | "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.3.2.tgz", 1385 | "integrity": "sha512-nzwvyFQg58XSMAmKVLr2uekAxNYvAbz1lyPmCAFVIBncCgN9S/HPM+2UM9Q9cvc4JEbC5ZBgwLAdaE2onmQuKg==", 1386 | "dev": true, 1387 | "license": "MIT", 1388 | "dependencies": { 1389 | "ansis": "^4.1.0", 1390 | "debug": "^4.4.1", 1391 | "error-stack-parser-es": "^1.0.5", 1392 | "ohash": "^2.0.11", 1393 | "open": "^10.2.0", 1394 | "perfect-debounce": "^1.0.0", 1395 | "sirv": "^3.0.1", 1396 | "unplugin-utils": "^0.2.4", 1397 | "vite-dev-rpc": "^1.1.0" 1398 | }, 1399 | "engines": { 1400 | "node": ">=14" 1401 | }, 1402 | "funding": { 1403 | "url": "https://github.com/sponsors/antfu" 1404 | }, 1405 | "peerDependencies": { 1406 | "vite": "^6.0.0 || ^7.0.0-0" 1407 | }, 1408 | "peerDependenciesMeta": { 1409 | "@nuxt/kit": { 1410 | "optional": true 1411 | } 1412 | } 1413 | }, 1414 | "node_modules/vite/node_modules/fdir": { 1415 | "version": "6.4.6", 1416 | "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", 1417 | "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", 1418 | "dev": true, 1419 | "license": "MIT", 1420 | "peerDependencies": { 1421 | "picomatch": "^3 || ^4" 1422 | }, 1423 | "peerDependenciesMeta": { 1424 | "picomatch": { 1425 | "optional": true 1426 | } 1427 | } 1428 | }, 1429 | "node_modules/wsl-utils": { 1430 | "version": "0.1.0", 1431 | "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", 1432 | "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", 1433 | "dev": true, 1434 | "license": "MIT", 1435 | "dependencies": { 1436 | "is-wsl": "^3.1.0" 1437 | }, 1438 | "engines": { 1439 | "node": ">=18" 1440 | }, 1441 | "funding": { 1442 | "url": "https://github.com/sponsors/sindresorhus" 1443 | } 1444 | } 1445 | } 1446 | } 1447 | --------------------------------------------------------------------------------