├── .gitattributes ├── .gitignore ├── examples ├── plain │ ├── src │ │ └── main.ts │ ├── scripts │ │ ├── dev.ts │ │ ├── release.ts │ │ └── vite.ts │ ├── index.html │ ├── deno.json │ └── deno.lock └── preact │ ├── src │ ├── vite-env.d.ts │ ├── style-import.js │ ├── main.tsx │ ├── app.css │ ├── app.tsx │ ├── index.css │ └── assets │ │ └── preact.svg │ ├── scripts │ ├── dev.ts │ ├── release.ts │ └── vite.ts │ ├── README.md │ ├── .gitignore │ ├── index.html │ ├── public │ ├── vite.svg │ └── Deno.svg │ ├── deno.json │ └── deno.lock ├── .vscode └── settings.json ├── .github └── workflows │ └── jsr.yml ├── src ├── ray.ts ├── constants.ts ├── specifier.test.ts ├── options.ts ├── exclude.ts ├── undeclared_npm.ts ├── ast-ops.test.ts ├── ast-ops.ts ├── ast-pool.ts ├── ast-worker.ts ├── specifier.ts ├── resolve.ts ├── npm.ts └── graph.ts ├── deno.json ├── mod.ts ├── README.md └── LICENSE /.gitattributes: -------------------------------------------------------------------------------- 1 | * eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vite 3 | dist 4 | -------------------------------------------------------------------------------- /examples/plain/src/main.ts: -------------------------------------------------------------------------------- 1 | console.log("Hello, world!"); 2 | -------------------------------------------------------------------------------- /examples/preact/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/preact/src/style-import.js: -------------------------------------------------------------------------------- 1 | import "./index.css"; 2 | import "./app.css"; 3 | -------------------------------------------------------------------------------- /examples/preact/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { render } from "preact"; 2 | import { App } from "./app.tsx"; 3 | 4 | render(, document.getElementById("app")!); 5 | -------------------------------------------------------------------------------- /examples/plain/scripts/dev.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from "vite"; 2 | import { config } from "./vite.ts"; 3 | 4 | const server = await createServer(config); 5 | await server.listen(); 6 | server.printUrls(); 7 | -------------------------------------------------------------------------------- /examples/preact/scripts/dev.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from "vite"; 2 | import { config } from "./vite.ts"; 3 | 4 | const server = await createServer(config); 5 | await server.listen(); 6 | server.printUrls(); 7 | -------------------------------------------------------------------------------- /examples/plain/scripts/release.ts: -------------------------------------------------------------------------------- 1 | import { build } from "vite"; 2 | import { config } from "./vite.ts"; 3 | 4 | await build(config); 5 | 6 | // Vite spawns esbuild which prevents this from exiting automatically 7 | Deno.exit(0); 8 | -------------------------------------------------------------------------------- /examples/preact/scripts/release.ts: -------------------------------------------------------------------------------- 1 | import { build } from "vite"; 2 | import { config } from "./vite.ts"; 3 | 4 | await build(config); 5 | 6 | // Vite spawns esbuild which prevents this from exiting automatically 7 | Deno.exit(0); 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enable": true, 3 | "cSpell.words": [ 4 | "compat", 5 | "Deno", 6 | "jsdelivr", 7 | "lockfiles", 8 | "polyfilling", 9 | "Preact", 10 | "prefresh" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /examples/preact/README.md: -------------------------------------------------------------------------------- 1 | # Preact example 2 | 3 | This is an adapted version of Vite's `preact-ts` template. 4 | 5 | ## Credits 6 | 7 | This is derived from https://github.com/vitejs/vite/tree/main/packages/create-vite 8 | 9 | The Deno logo is from https://deno.com/artwork 10 | -------------------------------------------------------------------------------- /examples/plain/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vite Plugin Deno 7 | 8 | 9 | 10 |
Hi
11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/preact/.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 | -------------------------------------------------------------------------------- /examples/plain/scripts/vite.ts: -------------------------------------------------------------------------------- 1 | import { pluginDeno } from "@deno-plc/vite-plugin-deno"; 2 | import type { InlineConfig } from "vite"; 3 | 4 | export const config: InlineConfig = { 5 | configFile: false, // configuration is inlined here 6 | server: { 7 | port: 8000, 8 | }, 9 | plugins: [ 10 | pluginDeno({ 11 | // see configuration docs 12 | }), 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /examples/plain/deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "dev": "deno run -A scripts/dev.ts", 4 | "release": "deno run -A scripts/release.ts" 5 | }, 6 | "nodeModulesDir": "auto", 7 | "compilerOptions": { 8 | "lib": [ 9 | "deno.window", 10 | "deno.ns", 11 | "ESNext", 12 | "DOM", 13 | "DOM.Iterable", 14 | "DOM.AsyncIterable", 15 | "webworker" 16 | ] 17 | }, 18 | "importMap": "../../deno.json" 19 | } 20 | -------------------------------------------------------------------------------- /examples/preact/src/app.css: -------------------------------------------------------------------------------- 1 | #app { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | width: 6em; 11 | padding: 1.5em; 12 | display: inline-block; 13 | } 14 | .logo:hover { 15 | filter: drop-shadow(0 0 2em #646cffaa); 16 | } 17 | .logo.preact:hover { 18 | filter: drop-shadow(0 0 2em #673ab8aa); 19 | } 20 | 21 | .card { 22 | padding: 2em; 23 | } 24 | 25 | .read-the-docs { 26 | color: #888; 27 | } 28 | -------------------------------------------------------------------------------- /examples/preact/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Preact + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/jsr.yml: -------------------------------------------------------------------------------- 1 | name: JSR Publish 2 | on: 3 | push: 4 | branches: main 5 | 6 | jobs: 7 | publish: 8 | name: Publish 9 | runs-on: ubuntu-latest 10 | 11 | permissions: 12 | contents: read 13 | id-token: write 14 | 15 | steps: 16 | - name: Clone repository 17 | uses: actions/checkout@v3 18 | 19 | - name: Install Deno 20 | uses: denoland/setup-deno@v1 21 | with: 22 | deno-version: v2.x 23 | 24 | - name: Test 25 | run: deno task check-ci 26 | 27 | - name: Publish package to JSR 28 | run: deno publish 29 | -------------------------------------------------------------------------------- /src/ray.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2025 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | export class Ray { 25 | constructor(readonly id: string, readonly referrer: string) { 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | export const supported_extensions = [ 25 | "js", 26 | "jsx", 27 | "ts", 28 | "tsx", 29 | "mjs", 30 | "cjs", 31 | "json", 32 | ]; 33 | -------------------------------------------------------------------------------- /src/specifier.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { assertEquals } from "@std/assert"; 25 | import { parseModuleSpecifier } from "./specifier.ts"; 26 | 27 | Deno.test("parseModuleSpecifier", () => { 28 | assertEquals(parseModuleSpecifier(`npm:foo`).href, `npm:foo`); 29 | assertEquals(parseModuleSpecifier(`npm:/foo`).href, `npm:foo`); 30 | }); 31 | -------------------------------------------------------------------------------- /src/options.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 - 2025 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import type { Logger } from "@logtape/logtape"; 25 | 26 | export interface Opt { 27 | deno_json?: string; 28 | deno_lock?: string; 29 | extra_import_map: Map>; 30 | environment: "deno" | "browser"; 31 | exclude: RegExp[]; 32 | legacy_npm: string[]; 33 | logger: Logger; 34 | } 35 | -------------------------------------------------------------------------------- /examples/preact/src/app.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from "preact/hooks"; 2 | 3 | export function App() { 4 | const [count, setCount] = useState(0); 5 | 6 | const viteLogo = new URL("/vite.svg", import.meta.url).href; 7 | const preactLogo = new URL("./assets/preact.svg", import.meta.url).href; 8 | const denoLogo = new URL("/Deno.svg", import.meta.url).href; 9 | 10 | return ( 11 | <> 12 | 23 |

Vite + Deno + Preact

24 |
25 | 28 |

29 | Edit src/app.tsx and save to test HMR 30 |

31 |
32 | 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /examples/preact/scripts/vite.ts: -------------------------------------------------------------------------------- 1 | import { pluginDeno } from "@deno-plc/vite-plugin-deno"; 2 | import prefresh from "@prefresh/vite"; 3 | import type { InlineConfig, Plugin } from "vite"; 4 | 5 | export const config: InlineConfig = { 6 | configFile: false, // configuration is inlined here 7 | server: { 8 | port: 8000, 9 | }, 10 | plugins: [ 11 | pluginDeno({ 12 | exclude: [/style-import\.js/], 13 | env: "browser", 14 | undeclared_npm_imports: [ 15 | // injected by JSX transform 16 | "preact/jsx-runtime", 17 | "preact/jsx-dev-runtime", 18 | // injected by HMR 19 | "@prefresh/core", 20 | "@prefresh/utils", 21 | // injected by react compat 22 | "@preact/compat", 23 | ], 24 | extra_import_map: new Map([ 25 | // react compat 26 | ["react", "@preact/compat"], 27 | ["react-dom", "@preact/compat"], 28 | ]), 29 | }) as Plugin, 30 | // HMR Plugin 31 | prefresh({ 32 | // `node_modules` is excluded internally, lets do the same 33 | exclude: [/^npm/, /registry.npmjs.org/, /^jsr/, /^https?/], 34 | }) as Plugin, 35 | ], 36 | esbuild: { 37 | jsx: "automatic", 38 | jsxImportSource: "preact", 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /examples/preact/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/preact/src/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; 3 | line-height: 1.5; 4 | font-weight: 400; 5 | 6 | color-scheme: light dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | 10 | font-synthesis: none; 11 | text-rendering: optimizeLegibility; 12 | -webkit-font-smoothing: antialiased; 13 | -moz-osx-font-smoothing: grayscale; 14 | } 15 | 16 | a { 17 | font-weight: 500; 18 | color: #646cff; 19 | text-decoration: inherit; 20 | } 21 | a:hover { 22 | color: #535bf2; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | display: flex; 28 | place-items: center; 29 | min-width: 320px; 30 | min-height: 100vh; 31 | } 32 | 33 | h1 { 34 | font-size: 3.2em; 35 | line-height: 1.1; 36 | } 37 | 38 | button { 39 | border-radius: 8px; 40 | border: 1px solid transparent; 41 | padding: 0.6em 1.2em; 42 | font-size: 1em; 43 | font-weight: 500; 44 | font-family: inherit; 45 | background-color: #1a1a1a; 46 | cursor: pointer; 47 | transition: border-color 0.25s; 48 | } 49 | button:hover { 50 | border-color: #646cff; 51 | } 52 | button:focus, 53 | button:focus-visible { 54 | outline: 4px auto -webkit-focus-ring-color; 55 | } 56 | 57 | @media (prefers-color-scheme: light) { 58 | :root { 59 | color: #213547; 60 | background-color: #ffffff; 61 | } 62 | a:hover { 63 | color: #747bff; 64 | } 65 | button { 66 | background-color: #f9f9f9; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /examples/preact/src/assets/preact.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/preact/deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "dev": "deno run -A scripts/dev.ts", 4 | "release": "deno run -A scripts/release.ts" 5 | }, 6 | "nodeModulesDir": "auto", 7 | "compilerOptions": { 8 | "lib": [ 9 | "deno.window", 10 | "deno.ns", 11 | "ESNext", 12 | "DOM", 13 | "DOM.Iterable", 14 | "DOM.AsyncIterable", 15 | "webworker" 16 | ], 17 | "jsx": "react-jsx", 18 | "jsxImportSource": "preact" 19 | }, 20 | "imports": { 21 | "preact": "npm:preact@^10.24.3", 22 | "@preact/compat": "npm:@preact/compat@^18.3.1", 23 | "@prefresh/core": "npm:@prefresh/core@^1.5.2", 24 | "@prefresh/utils": "npm:@prefresh/utils@^1.2.0", 25 | "@prefresh/vite": "npm:@prefresh/vite@^2.4.6", 26 | "@deno-plc/vite-plugin-deno": "../../mod.ts", 27 | "@coderspirit/nominal": "npm:@coderspirit/nominal@^4.1.1", 28 | "@logtape/logtape": "jsr:@logtape/logtape@^0.8.2", 29 | "@std/assert": "jsr:@std/assert@^0.223.0", 30 | "@std/encoding": "jsr:@std/encoding@^0.223.0", 31 | "@std/fs": "jsr:@std/fs@^0.223.0", 32 | "@std/path": "jsr:@std/path@^0.225.1", 33 | "@std/semver": "jsr:@std/semver@^1.0.2", 34 | "acorn": "npm:acorn@^8.12.1", 35 | "acorn-walk": "npm:acorn-walk@^8.3.3", 36 | "lebab": "npm:lebab@^3.2.4", 37 | "resolve.exports": "npm:resolve.exports@^2.0.2", 38 | "validate-npm-package-name": "npm:validate-npm-package-name@^5.0.1", 39 | "vite": "npm:vite@^6.1.1", 40 | "zod": "npm:zod@^3.22.5" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/exclude.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import type { Opt } from "./options.ts"; 25 | 26 | function is_excluded_inner(spec: string, o: Opt) { 27 | for (const exclude of o.exclude) { 28 | if (exclude.test(spec)) { 29 | return true; 30 | } 31 | } 32 | return false; 33 | } 34 | 35 | const cache = new Map(); 36 | 37 | export function is_excluded(spec: string, o: Opt): boolean { 38 | return cache.get(spec) ?? (() => { 39 | const excl = is_excluded_inner(spec, o); 40 | cache.set(spec, excl); 41 | return excl; 42 | })(); 43 | } 44 | 45 | // function* cache_info() { 46 | // for (const [id, excl] of cache) { 47 | // yield `${excl ? "-" : "+"} ${id}`; 48 | // } 49 | // } 50 | -------------------------------------------------------------------------------- /src/undeclared_npm.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { z } from "zod"; 25 | import { parseModuleSpecifier } from "./specifier.ts"; 26 | import type { ModuleGraph } from "./graph.ts"; 27 | 28 | const Schema = z.object({ 29 | redirects: z.record(z.string().transform(parseModuleSpecifier)), 30 | }); 31 | 32 | export function resolve_undeclared_npm( 33 | packages: string[], 34 | graph: ModuleGraph, 35 | extra_import_map: Map>, 36 | ) { 37 | for (const pkg of packages) { 38 | extra_import_map.set( 39 | pkg, 40 | graph 41 | .call_deno(`npm:${pkg}`) 42 | .then(Schema.parse) 43 | .then(({ redirects }) => `${redirects[`npm:${pkg}`].href}#standalone`), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@deno-plc/vite-plugin-deno", 3 | "version": "2.3.4", 4 | "exports": "./mod.ts", 5 | "compilerOptions": { 6 | "lib": [ 7 | "deno.window", 8 | "deno.ns", 9 | "ESNext", 10 | "webworker" 11 | ] 12 | }, 13 | "fmt": { 14 | "indentWidth": 4, 15 | "lineWidth": 120, 16 | "exclude": [ 17 | "examples/**/dist/**" 18 | ] 19 | }, 20 | "tasks": { 21 | "check": "deno fmt && deno lint && deno publish --dry-run --allow-dirty && deno test -A --parallel", 22 | "check-ci": "deno fmt --check && deno lint && deno publish --dry-run && deno test -A --parallel" 23 | }, 24 | "lint": { 25 | "rules": { 26 | "exclude": [ 27 | "no-misused-new" 28 | ] 29 | }, 30 | "exclude": [ 31 | "examples/**/dist/**" 32 | ] 33 | }, 34 | "imports": { 35 | "@deno-plc/vite-plugin-deno": "./mod.ts", 36 | "@coderspirit/nominal": "npm:@coderspirit/nominal@^4.1.1", 37 | "@logtape/logtape": "jsr:@logtape/logtape@^0.8.2", 38 | "@std/assert": "jsr:@std/assert@^0.223.0", 39 | "@std/encoding": "jsr:@std/encoding@^0.223.0", 40 | "@std/fs": "jsr:@std/fs@^0.223.0", 41 | "@std/path": "jsr:@std/path@^0.225.1", 42 | "@std/semver": "jsr:@std/semver@^1.0.2", 43 | "acorn": "npm:acorn@^8.12.1", 44 | "acorn-walk": "npm:acorn-walk@^8.3.3", 45 | "lebab": "npm:lebab@^3.2.4", 46 | "resolve.exports": "npm:resolve.exports@^2.0.2", 47 | "validate-npm-package-name": "npm:validate-npm-package-name@^5.0.1", 48 | "vite": "npm:vite@^6.1.1", 49 | "zod": "npm:zod@^3.22.5" 50 | }, 51 | "publish": { 52 | "exclude": [ 53 | "examples" 54 | ] 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ast-ops.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { assert } from "@std/assert"; 25 | import { has_default_export } from "./ast-ops.ts"; 26 | import type { Opt } from "./options.ts"; 27 | import { getLogger } from "@logtape/logtape"; 28 | 29 | const o: Opt = { 30 | deno_json: "", 31 | deno_lock: "", 32 | extra_import_map: new Map(), 33 | environment: "deno", 34 | exclude: [], 35 | legacy_npm: [], 36 | logger: getLogger("vite-plugin-deno/test"), 37 | }; 38 | 39 | Deno.test("has default export", async () => { 40 | assert(await has_default_export(o, `export default function foo(){}`) === true); 41 | assert(await has_default_export(o, `function foo(){}\n export {foo as default};`) === true); 42 | assert(await has_default_export(o, `// export default`) === false); 43 | assert(await has_default_export(o, `/*\nexport default\n*/`) === false); 44 | assert(await has_default_export(o, `// export {foo as default}`) === false); 45 | }); 46 | -------------------------------------------------------------------------------- /src/ast-ops.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 - 2025 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { WorkerPool } from "./ast-pool.ts"; 25 | import type { Opt } from "./options.ts"; 26 | 27 | const pool = new WorkerPool(navigator.hardwareConcurrency ?? 4); 28 | 29 | export async function toESM(o: Opt, raw_code: string, id: string) { 30 | if (raw_code.includes("require") || raw_code.includes("module")) { 31 | return (await pool.run(o, { 32 | task_id: pool.get_task_id(), 33 | kind: "cjs-to-esm", 34 | id, 35 | raw_code, 36 | })).code!; 37 | } else { 38 | return raw_code; 39 | } 40 | } 41 | 42 | const default_export_cache = new Map | boolean>(); 43 | 44 | export async function has_default_export(o: Opt, code: string, id: string = code): Promise { 45 | if (default_export_cache.has(id)) { 46 | return default_export_cache.get(id)!; 47 | } 48 | if (!code.includes("default")) { 49 | default_export_cache.set(id, false); 50 | return false; 51 | } 52 | 53 | const pr = (async () => 54 | (await pool.run(o, { 55 | task_id: pool.get_task_id(), 56 | kind: "default-exports", 57 | id, 58 | raw_code: code, 59 | })).has_default_export!)(); 60 | 61 | default_export_cache.set(id, pr); 62 | const has_default_export = await pr; 63 | default_export_cache.set(id, has_default_export); 64 | return has_default_export; 65 | } 66 | -------------------------------------------------------------------------------- /src/ast-pool.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 - 2025 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import type { AstResult, AstTask } from "./ast-worker.ts"; 25 | import { assert } from "@std/assert/assert"; 26 | import type { Opt } from "./options.ts"; 27 | 28 | export class WorkerPool { 29 | constructor(readonly concurrency: number) { 30 | assert(concurrency > 0); 31 | assert(concurrency % 1 === 0); // int 32 | for (let i = 0; i < concurrency; i++) { 33 | this.#pool.push(this.#spawn_worker()); 34 | } 35 | } 36 | #spawn_worker() { 37 | const worker = new Worker(new URL("./ast-worker.ts", import.meta.url), { 38 | type: "module", 39 | name: `ast-worker-${this.#pool.length}`, 40 | }); 41 | worker.addEventListener("message", (ev) => { 42 | const result = ev.data as AstResult; 43 | const listener = this.#listener.get(result.task_id); 44 | listener?.(result); 45 | this.#listener.delete(result.task_id); 46 | 47 | const waiting = this.#waiting.shift(); 48 | if (waiting) { 49 | waiting(worker); 50 | } else { 51 | this.#free_pool.push(worker); 52 | } 53 | }); 54 | this.#free_pool.push(worker); 55 | return worker; 56 | } 57 | #pool: Worker[] = []; 58 | #free_pool: Worker[] = []; 59 | #waiting: ((worker: Worker) => void)[] = []; 60 | #listener = new Map void>(); 61 | #run_task(o: Opt, task: AstTask, worker: Worker): Promise { 62 | o.logger.debug(`running AST operation {kind} {id}`, { ...task }); 63 | return new Promise((resolve) => { 64 | this.#listener.set(task.task_id, resolve); 65 | worker.postMessage(task); 66 | }); 67 | } 68 | public run(o: Opt, task: AstTask): Promise { 69 | const worker = this.#free_pool.shift(); 70 | if (worker) { 71 | return this.#run_task(o, task, worker); 72 | } else { 73 | return new Promise((resolve) => { 74 | this.#waiting.push((worker) => { 75 | this.#run_task(o, task, worker).then(resolve); 76 | }); 77 | }); 78 | } 79 | } 80 | #task_id = 0; 81 | public get_task_id(): number { 82 | return this.#task_id++; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/ast-worker.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { transform } from "lebab"; 25 | import { parse } from "acorn"; 26 | import { simple as walk_simple } from "acorn-walk"; 27 | 28 | export interface AstTask { 29 | task_id: number; 30 | kind: "cjs-to-esm" | "default-exports"; 31 | id: string; 32 | raw_code: string; 33 | } 34 | 35 | export interface AstResult { 36 | task_id: number; 37 | code?: string; 38 | has_default_export?: boolean; 39 | } 40 | 41 | function run_task(task: AstTask): Omit { 42 | try { 43 | if (task.kind === "cjs-to-esm") { 44 | const { code, warnings } = transform( 45 | task.raw_code, 46 | ["commonjs"], 47 | ); 48 | for (const $ of warnings) { 49 | if ($.msg === "export can only be at root level") { 50 | throw new Error(`Failed to transform to ESM: ${task.id} does UGLY things with Cjs exports.`); 51 | } else { 52 | console.warn(task.id, $); 53 | } 54 | } 55 | 56 | return { 57 | code, 58 | }; 59 | } else { 60 | const ast = parse(task.raw_code, { 61 | ecmaVersion: 2023, 62 | sourceType: "module", 63 | }); 64 | 65 | let has_default_export = false; 66 | 67 | walk_simple(ast, { 68 | ExportDefaultDeclaration(_node) { 69 | has_default_export = true; 70 | }, 71 | ExportNamedDeclaration(node) { 72 | if (node.specifiers) { 73 | for (const specifier of node.specifiers) { 74 | // @ts-ignore missing typedef 75 | if (specifier.type === "ExportSpecifier" && specifier.exported?.name === "default") { 76 | has_default_export = true; 77 | } 78 | } 79 | } 80 | }, 81 | }); 82 | 83 | return { 84 | has_default_export, 85 | }; 86 | } 87 | } catch (err) { 88 | if (err instanceof Error) { 89 | throw new Error(`Failed to run task ${task.id}: ${err.message}`); 90 | } else { 91 | throw new Error(`Failed to run task ${task.id}: ${err}`); 92 | } 93 | } 94 | } 95 | 96 | self.onmessage = (e) => { 97 | const task = e.data as AstTask; 98 | 99 | const res: AstResult = { 100 | task_id: task.task_id, 101 | ...run_task(task), 102 | }; 103 | 104 | self.postMessage(res); 105 | }; 106 | -------------------------------------------------------------------------------- /src/specifier.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { parse, type SemVer } from "@std/semver"; 25 | import validate from "validate-npm-package-name"; 26 | import type { FastBrand } from "@coderspirit/nominal"; 27 | 28 | export type ModuleSpecifier = FastBrand; 29 | 30 | export function parseModuleSpecifier(inp: string | URL): ModuleSpecifier { 31 | const url = new URL(inp); 32 | if (url.href.includes("\\")) { 33 | return parseModuleSpecifier(url.href.replaceAll("\\", "/")); 34 | } 35 | if (url.protocol === "https:") { 36 | return url as ModuleSpecifier; 37 | } else if (url.protocol === "file:") { 38 | if (!url.href.startsWith("file:///")) { 39 | return new URL(url.href.replace("file://", "file:///")) as ModuleSpecifier; 40 | } 41 | return url as ModuleSpecifier; 42 | } else if (url.pathname.startsWith("/")) { 43 | return new URL(url.href.replace(url.pathname, url.pathname.substring(1))) as ModuleSpecifier; 44 | } else { 45 | return url as ModuleSpecifier; 46 | } 47 | } 48 | 49 | export interface NPMExact { 50 | name: string; 51 | version: SemVer; 52 | path: string; 53 | } 54 | 55 | export function parseNPMExact(spec: string): NPMExact | null { 56 | spec = spec.trim(); 57 | if (spec.startsWith("npm:")) { 58 | spec = spec.substring(4); 59 | } 60 | let marker = 0; 61 | marker = spec.indexOf("/"); 62 | if (spec[0] === "@") { 63 | // @scope/package contains one more slash 64 | marker = spec.indexOf("/", marker + 1); 65 | } 66 | if (marker === -1) { 67 | marker = Infinity; 68 | } 69 | // exclude trailing @ 70 | const version_marker = spec.indexOf("@", 2); 71 | 72 | if (version_marker > marker) { 73 | return null; 74 | } 75 | 76 | let version: SemVer | null = null; 77 | let name = spec.substring(0, marker); 78 | 79 | if (version_marker !== -1) { 80 | version = parse(spec.substring(version_marker + 1, marker)); 81 | name = spec.substring(0, version_marker); 82 | } else { 83 | return null; 84 | } 85 | 86 | const path = spec.substring(marker + 1); 87 | 88 | if (!validate(name)) { 89 | return null; 90 | } 91 | 92 | return { 93 | version, 94 | name, 95 | path, 96 | }; 97 | } 98 | 99 | export interface NPMImport { 100 | name: string; 101 | path: string; 102 | } 103 | 104 | export function parseNPMImport(spec: string): NPMImport | null { 105 | spec = spec.trim(); 106 | if (spec.startsWith("npm:")) { 107 | spec = spec.substring(4); 108 | } 109 | let marker = 0; 110 | marker = spec.indexOf("/"); 111 | if (spec[0] === "@") { 112 | // @scope/package contains one more slash 113 | marker = spec.indexOf("/", marker + 1); 114 | } 115 | if (marker === -1) { 116 | marker = Infinity; 117 | } 118 | 119 | const name = spec.substring(0, marker); 120 | 121 | const path = spec.substring(marker + 1); 122 | 123 | if (!validate(name)) { 124 | return null; 125 | } 126 | 127 | return { 128 | name, 129 | path, 130 | }; 131 | } 132 | -------------------------------------------------------------------------------- /src/resolve.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 - 2025 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { fromFileUrl, isAbsolute, join, normalize, toFileUrl } from "@std/path"; 25 | import type { ModuleGraph } from "./graph.ts"; 26 | import { type ModuleSpecifier, parseModuleSpecifier, parseNPMImport } from "./specifier.ts"; 27 | import type { Opt } from "./options.ts"; 28 | import type { Ray } from "./ray.ts"; 29 | 30 | async function exists(path: string): Promise { 31 | try { 32 | await Deno.stat(path); 33 | return true; 34 | } catch (_) { 35 | return false; 36 | } 37 | } 38 | 39 | export async function resolve( 40 | o: Opt, 41 | ray: Ray, 42 | graph: ModuleGraph, 43 | id: string, 44 | referrer?: string, 45 | may_fetch: boolean = true, 46 | ): Promise { 47 | // console.log(`%c[RESOLVE] ${id}`, "color:#ff0"); 48 | // console.log(`%c[REFERRER] ${referrer} (${isAbsolute(referrer || "") ? "" : "!"}abs)`, "color: gray"); 49 | if (o.extra_import_map.has(id)) { 50 | return await resolve(o, ray, graph, await o.extra_import_map.get(id)!, referrer, may_fetch); 51 | } 52 | 53 | if (referrer === undefined) { 54 | // local entrypoint 55 | id = join(Deno.cwd(), id); 56 | } 57 | 58 | const fast_forward = graph.get_resolved(id); 59 | 60 | if (fast_forward) { 61 | return fast_forward.specifier; 62 | } 63 | 64 | let referrer_mod = referrer ? graph.get_resolved(referrer) : null; 65 | 66 | if ( 67 | referrer && !referrer_mod && isAbsolute(referrer) && !referrer.includes(`registry.npmjs.org`) && 68 | await exists(referrer) 69 | ) { 70 | referrer_mod = await graph.get_module(toFileUrl(referrer) as ModuleSpecifier); 71 | } 72 | 73 | if (id.endsWith("#standalone")) { 74 | const mod = await graph.get_module(parseModuleSpecifier(id.substring(0, id.length - "#standalone".length))); 75 | if (mod) { 76 | return mod.specifier; 77 | } 78 | } 79 | 80 | if (referrer_mod) { 81 | // console.log(`%c[REFERRER] ${referrer_mod.specifier.href}`, "color: green"); 82 | const ref = await referrer_mod.resolve_import(id); 83 | if (ref) { 84 | return ref.specifier; 85 | } else { 86 | if (!id.startsWith("npm")) { 87 | if (may_fetch) { 88 | await graph.update_info(referrer_mod.specifier); 89 | return await resolve(o, ray, graph, id, referrer, false); 90 | } else { 91 | throw new Error(`cannot resolve '${id}' from ${referrer_mod.specifier.href}`); 92 | } 93 | } 94 | } 95 | } 96 | 97 | if (isAbsolute(id)) { 98 | if (await exists(id)) { 99 | const mod = await graph.get_module(toFileUrl(id) as ModuleSpecifier); 100 | 101 | if (mod) { 102 | // console.log(`%c[RESOLVED ABS] ${mod.specifier.href}`, "color:blue"); 103 | 104 | return mod.specifier; 105 | } 106 | } else { 107 | const project_abs = join(Deno.cwd(), id); 108 | if (await exists(project_abs)) { 109 | const mod = await graph.get_module(toFileUrl(project_abs) as ModuleSpecifier); 110 | 111 | if (mod) { 112 | // console.log(`%c[RESOLVED ABS] ${mod.specifier.href}`, "color:blue"); 113 | 114 | return mod.specifier; 115 | } 116 | } 117 | } 118 | } 119 | if (URL.canParse(id)) { 120 | const mod = await graph.get_module(parseModuleSpecifier(id)); 121 | if (mod) { 122 | return mod.specifier; 123 | } 124 | } 125 | 126 | const npm = parseNPMImport(id); 127 | if (npm) { 128 | if (graph.npm_package_versions.has(npm.name)) { 129 | const versions = graph.npm_package_versions.get(npm.name)!; 130 | throw new Error(`cannot resolve ${id} from ${referrer} 131 | ${npm.name} has been recognized as an NPM package, if it is an injected import you may want to add "${npm.name}" to undeclared_npm_imports or one of the following entries to extra_import_map: 132 | ${ 133 | [...versions.values()].map((version) => 134 | `"${id}" => "npm:${npm.name}@${version}${npm.path ? `/${npm.path}` : ""}"` 135 | ).join("\n") 136 | }`); 137 | } 138 | } 139 | if (referrer?.endsWith(".html")) { 140 | return null; 141 | } 142 | throw new Error(`cannot resolve ${id} from ${referrer}`); 143 | } 144 | 145 | const fs_remap = new Map(); 146 | 147 | export function encodeSpec(spec: ModuleSpecifier) { 148 | if (spec.protocol === "file:") { 149 | const path = fromFileUrl(spec.href); 150 | fs_remap.set(path, spec); 151 | return path; 152 | } 153 | return `${encodeURIComponent(spec.href)}`; 154 | } 155 | 156 | export function decodeSpec(spec: string) { 157 | const normalized = normalize(spec); 158 | if (fs_remap.has(normalized)) { 159 | return fs_remap.get(normalized)!.href; 160 | } 161 | return decodeURIComponent(spec); 162 | } 163 | -------------------------------------------------------------------------------- /examples/preact/public/Deno.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.15, written by Peter Selinger 2001-2017 9 | 10 | 11 | 13 | 88 | 90 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /src/npm.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 - 2025 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { format, type SemVer } from "@std/semver"; 25 | import { fromFileUrl, join, toFileUrl } from "@std/path"; 26 | import { z } from "zod"; 27 | import type { ModuleGraph, NPMImportInfo } from "./graph.ts"; 28 | import * as npmResolver from "resolve.exports"; 29 | import { assert } from "jsr:@std/assert@^0.225.2/assert"; 30 | import { type ModuleSpecifier, parseModuleSpecifier, parseNPMExact } from "./specifier.ts"; 31 | import { has_default_export, toESM } from "./ast-ops.ts"; 32 | import type { Opt } from "./options.ts"; 33 | 34 | export const PackageJSON = z.object({ 35 | name: z.string(), 36 | version: z.string(), 37 | main: z.unknown().optional(), 38 | browser: z.unknown().optional(), 39 | exports: z.unknown().optional(), 40 | }); 41 | export type PackageJSON = z.infer; 42 | 43 | const cacheDir = (async () => 44 | z 45 | .object({ 46 | npmCache: z.string().transform(toFileUrl), 47 | }) 48 | .parse( 49 | JSON.parse( 50 | new TextDecoder().decode( 51 | (await new Deno.Command(Deno.execPath(), { 52 | args: ["info", "--json"], 53 | stdout: "piped", 54 | }).output()) 55 | .stdout, 56 | ), 57 | ), 58 | ) 59 | .npmCache)(); 60 | 61 | const pending = new Map>(); 62 | 63 | export async function getNPMPath(name: string, version: SemVer) { 64 | return join(fromFileUrl(await cacheDir), `registry.npmjs.org/${name}/${format(version)}`); 65 | } 66 | 67 | export async function getPackageMetadata(name: string, version: SemVer): Promise { 68 | const id = `${name}@${format(version)}`; 69 | if (pending.has(id)) { 70 | return await pending.get(id)!; 71 | } else { 72 | const pr = (async () => { 73 | const path = join(await getNPMPath(name, version), "package.json"); 74 | const content = await Deno.readTextFile(path).catch(() => { 75 | return null; 76 | }); 77 | if (content) { 78 | const data = JSON.parse(content); 79 | const parsed = PackageJSON.safeParse(data); 80 | if (parsed.success) { 81 | return parsed.data; 82 | } else { 83 | console.error(`Failed to parse package.json for ${id}`); 84 | throw { 85 | zod: parsed.error, 86 | message: `Failed to parse package.json for ${id}`, 87 | package: data, 88 | }; 89 | } 90 | } else { 91 | return null; 92 | } 93 | })(); 94 | pending.set(id, pr); 95 | return await pr; 96 | } 97 | } 98 | 99 | export class NPMPackage { 100 | constructor( 101 | readonly name: string, 102 | readonly version: SemVer, 103 | readonly raw_dependencies: string[], 104 | readonly graph: ModuleGraph, 105 | ) { 106 | this.metadata = getPackageMetadata(name, version); 107 | this.dependencies.set(this.name, this); 108 | } 109 | readonly metadata; 110 | readonly dependencies = new Map(); 111 | async fetch_metadata() { 112 | await this.metadata; 113 | } 114 | 115 | link() { 116 | for (const dep of this.raw_dependencies) { 117 | const pkg = this.graph.npm_packages.get(dep); 118 | assert(pkg, `failed to link dependency ${dep} of ${this.name}@${format(this.version)}`); 119 | this.dependencies.set(pkg.name, pkg); 120 | } 121 | } 122 | 123 | public async resolve_import(path: string): Promise { 124 | const metadata = await this.metadata; 125 | const resolved = npmResolver.exports(metadata, path, { 126 | browser: this.graph.o.environment === "browser", 127 | }); 128 | 129 | if (resolved) { 130 | for (const path of resolved) { 131 | const realPath = join(await getNPMPath(this.name, this.version), path); 132 | 133 | if ((await stat(realPath))?.isFile) { 134 | return parseModuleSpecifier(`npm-data:${this.name}@${format(this.version)}/${path.substring(2)}`); 135 | } 136 | } 137 | throw new Error(`export ${path} from ${this.name}@${format(this.version)} could not be resolved`); 138 | } else if (path) { 139 | return parseModuleSpecifier(join(`npm-probe:${this.name}@${format(this.version)}/`, path)); 140 | } else { 141 | const res = npmResolver.legacy(metadata, { 142 | browser: this.graph.o.environment === "browser", 143 | }); 144 | assert(typeof res === "string", `legacy resolution failed for ${this.name}@${format(this.version)}`); 145 | return parseModuleSpecifier(join(`npm-probe:${this.name}@${format(this.version)}/`, res)); 146 | } 147 | } 148 | } 149 | 150 | const npm_data_transform_cache = new Map>(); 151 | 152 | export async function getNPMData(o: Opt, specifier: ModuleSpecifier) { 153 | if (npm_data_transform_cache.has(specifier.href)) { 154 | return npm_data_transform_cache.get(specifier.href)!; 155 | } 156 | 157 | const pr = getNPMDataInner(o, specifier); 158 | npm_data_transform_cache.set(specifier.href, pr); 159 | const code = await pr; 160 | npm_data_transform_cache.set(specifier.href, code); 161 | return code; 162 | } 163 | 164 | async function getNPMDataInner(o: Opt, specifier: ModuleSpecifier) { 165 | const id = parseNPMExact(specifier.pathname); 166 | assert(id); 167 | const raw_code = await Deno.readTextFile(join(await getNPMPath(id.name, id.version), id.path)); 168 | let code = await toESM(o, raw_code, specifier.href); 169 | code = code.replace(/\/\/# sourceMappingURL.+/, ""); // TODO resolve source map url 170 | return code; 171 | } 172 | 173 | export async function get_npm_import_link(o: Opt, info: NPMImportInfo): Promise { 174 | const importedCode = await getNPMData(o, info.module); 175 | 176 | if (await has_default_export(o, importedCode, info.specifier.href)) { 177 | return ` 178 | // npm:${info.package.name}@${format(info.package.version)} 179 | 180 | export * from "${info.module.href}"; 181 | import d from "${info.module.href}"; 182 | export default d;`; 183 | } else { 184 | return ` 185 | // npm:${info.package.name}@${format(info.package.version)} 186 | 187 | export * from "${info.module.href}";`; 188 | } 189 | } 190 | 191 | function stat(path: string | URL) { 192 | return Deno.stat(path).catch(() => null); 193 | } 194 | 195 | export async function importProbe(path: string, virtualPath: string = path) { 196 | const direct = await stat(path); 197 | if (direct?.isFile) { 198 | return virtualPath; 199 | } else if (direct?.isDirectory) { 200 | return await importProbe(`${path}/index`, `${virtualPath}/index`); 201 | } else { 202 | for (const ext of ["js", "mjs", "cjs"]) { 203 | if (await stat(`${path}.${ext}`)) { 204 | return `${virtualPath}.${ext}`; 205 | } 206 | } 207 | } 208 | return null; 209 | } 210 | -------------------------------------------------------------------------------- /mod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 - 2025 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import type { HmrContext, PluginOption } from "vite"; 25 | import type { Opt } from "./src/options.ts"; 26 | import { ModuleGraph } from "./src/graph.ts"; 27 | import { decodeSpec, encodeSpec, resolve } from "./src/resolve.ts"; 28 | import { resolve_undeclared_npm } from "./src/undeclared_npm.ts"; 29 | import { is_excluded } from "./src/exclude.ts"; 30 | import { getLogger } from "@logtape/logtape"; 31 | import { Ray } from "./src/ray.ts"; 32 | 33 | /** 34 | * Plugin configuration 35 | */ 36 | export interface PluginDenoOptions { 37 | /** 38 | * override path to deno.json 39 | */ 40 | deno_json?: string; 41 | 42 | /** 43 | * override path to deno.lock 44 | */ 45 | deno_lock?: string; 46 | 47 | /** 48 | * bundling context 49 | * 1. Controls the Node module resolution conditions (when set to `"browser"` the package.json 50 | * `browser` entry is preferred over `main`) 51 | * 2. `node:` imports are only allowed when set to `"deno"` 52 | */ 53 | env?: "deno" | "browser"; 54 | 55 | /** 56 | * Those NPM packages will always be allowed even if they are not included in Deno's module graph. 57 | * 58 | * This can be used to resolve packages that are imported by injected code like HMR. 59 | */ 60 | undeclared_npm_imports?: string[]; 61 | 62 | /** 63 | * Those npm dependencies are left over to vite for resolution. This requires a `node_nodules` folder (like the symlinked one deno generates) 64 | */ 65 | legacy_npm?: string[]; 66 | 67 | /** 68 | * import map that is only applied to build module resolution. 69 | * 70 | * Useful for polyfilling `node:` and handling injected imports (JSX runtime, HMR, ...) 71 | * 72 | * Sometimes it might be required to add `#standalone` to the replaced import, otherwise 73 | * you will get errors because the replaced import is (of course) not reported by deno info. 74 | * The `#standalone` instructs the plugin to treat the import like an independent entrypoint. 75 | */ 76 | extra_import_map?: [string, string][] | Map>; 77 | 78 | /** 79 | * All specifiers that are equal to this or match the RegExp are ignored, deferring 80 | * resolution to other plugins and Vite. 81 | * 82 | * Using strings is deprecated (strings are converted to RegExps anyway) 83 | * 84 | * Note that the specifiers passed to this might be in different formats (even for the 85 | * same one) depending on the circumstances where it is checked: It might be absolute 86 | * or relative, as path or `file:` URL and with or without `npm:` prefix, semver version 87 | * or version range. 88 | * 89 | * The RegExps should not be too expensive to check 90 | */ 91 | exclude?: (string | RegExp)[]; 92 | 93 | /** 94 | * @logtape/logtape logger id 95 | * @default "vite-plugin-deno" 96 | */ 97 | log_id?: string; 98 | 99 | /** 100 | * Minimum time in milliseconds between hot updates, see Issue #5 101 | * @default 0 102 | */ 103 | hot_update_min_time?: number; 104 | } 105 | 106 | /** 107 | * see {@link PluginDenoOptions} 108 | */ 109 | export function pluginDeno(options: PluginDenoOptions): PluginOption { 110 | const extra_import_map = new Map(options.extra_import_map); 111 | const o: Opt = { 112 | logger: getLogger(options.log_id ?? "vite-plugin-deno"), 113 | deno_json: options.deno_json, 114 | deno_lock: options.deno_lock, 115 | extra_import_map, 116 | environment: options.env ?? "browser", 117 | exclude: [ 118 | ...options.exclude?.map((excl) => { 119 | if (excl instanceof RegExp) { 120 | return excl; 121 | } else { 122 | // transform to regexp 123 | return new RegExp(`^${excl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`); 124 | } 125 | }) ?? [], 126 | ], 127 | legacy_npm: options.legacy_npm ?? [], 128 | }; 129 | 130 | const legacy_npm_regex = new RegExp(`"npm:(${o.legacy_npm.join("|")})(@.+)"`, "g"); 131 | 132 | if (o.environment === "deno") { 133 | o.exclude.push(/^node:/); 134 | } 135 | o.exclude.push(/\/@(fs|id)/); 136 | o.exclude.push(/\/?(@|\.)vite\//); 137 | o.exclude.push(/\/node_modules\//); 138 | o.exclude.push(/^$/); 139 | 140 | const graph = new ModuleGraph(o); 141 | 142 | resolve_undeclared_npm(options.undeclared_npm_imports ?? [], graph, extra_import_map); 143 | 144 | return { 145 | // @ts-ignore some of the Plugin type definitions do not include name 146 | name: "vite-plugin-deno", 147 | enforce: "pre", 148 | config() { 149 | if (o.environment === "deno") { 150 | return { 151 | build: { 152 | rollupOptions: { 153 | external: [/^node:/], 154 | }, 155 | }, 156 | }; 157 | } 158 | }, 159 | resolveId: { 160 | order: "pre", 161 | async handler(raw_id: string, raw_referrer: string | undefined) { 162 | const start = performance.now(); 163 | const id = decodeSpec(raw_id); 164 | const referrer = raw_referrer && decodeSpec(raw_referrer); 165 | 166 | o.logger.debug( 167 | `Resolve module {id}${id !== raw_id ? `({raw_id})` : ""} from {referrer}${ 168 | referrer !== raw_referrer ? `({raw_referrer})` : "" 169 | }`, 170 | { 171 | id, 172 | raw_id, 173 | referrer, 174 | raw_referrer, 175 | }, 176 | ); 177 | 178 | const ray = new Ray(id, referrer ?? ""); 179 | 180 | if (id.endsWith(".html")) { 181 | return null; 182 | } 183 | 184 | if (is_excluded(id, o)) { 185 | o.logger.debug(`skipping (excluded specifier) {id}`, { ...ray }); 186 | return null; 187 | } 188 | 189 | if (referrer && is_excluded(referrer, o)) { 190 | o.logger.debug(`skipping (excluded referrer) {id} from {referrer}`, { ...ray }); 191 | return null; 192 | } 193 | 194 | if (o.legacy_npm.includes(id)) { 195 | o.logger.info(`skipping (legacy npm) {id}`, { ...ray }); 196 | return null; 197 | } 198 | 199 | const resolved = await resolve(o, ray, graph, id, referrer); 200 | 201 | if (resolved) { 202 | o.logger.debug(`resolved {id} from {referrer} to {resolved} ({duration}ms)`, { 203 | ...ray, 204 | resolved: resolved.href, 205 | duration: performance.now() - start, 206 | }); 207 | const encoded = encodeSpec(resolved); 208 | 209 | /** 210 | * Does not work with workspaces, because workspace imports would be skipped 211 | */ 212 | // if (resolved.protocol === "file:" && referrer?.startsWith("file://")) { 213 | // o.logger.debug(`resolved file specifier {id} from {referrer} to {resolved} ({duration}ms)`, { 214 | // ...ray, 215 | // resolved: resolved.href, 216 | // duration: performance.now() - start, 217 | // }); 218 | // return null; 219 | // } 220 | 221 | return encoded; 222 | } else { 223 | return null; 224 | } 225 | }, 226 | }, 227 | async load(raw_id: string) { 228 | const id = decodeSpec(raw_id); 229 | // const id = decodeURIComponent(raw_id); 230 | o.logger.debug(`Loading module {id}({raw_id})`, { id, raw_id }); 231 | 232 | const mod = graph.get_resolved(id); 233 | 234 | if (!mod) { 235 | o.logger.warn(`[loader] failed to resolve {id}`, { id }); 236 | return; 237 | } 238 | 239 | let result = await mod.load(); 240 | 241 | result = result.replaceAll(legacy_npm_regex, (_, package_name) => `"${package_name}"`); 242 | 243 | if (id.startsWith("http")) { 244 | result = result.replace(/\/\/# sourceMappingURL.+/, ""); 245 | } 246 | 247 | if (id.endsWith(".tsx")) { 248 | result = result.replaceAll(/\/\*\* \@jsx.+\*\//g, ""); 249 | } 250 | 251 | o.logger.debug(`loaded {id}`, { id }); 252 | 253 | return result; 254 | }, 255 | handleHotUpdate(ctx: HmrContext) { 256 | // console.log({ ...ctx, server: undefined, read: undefined, modules: undefined }); 257 | const last_file_update = last_update.get(ctx.file); 258 | last_update.set(ctx.file, ctx.timestamp); 259 | 260 | if (last_file_update && (ctx.timestamp - last_file_update) < (options.hot_update_min_time ?? 0)) { 261 | o.logger.error(`skipping HMR update for {file}, too early (d={diff})`, { 262 | file: ctx.file, 263 | last_update: last_file_update, 264 | timestamp: ctx.timestamp, 265 | hot_update_min_time: options.hot_update_min_time, 266 | diff: ctx.timestamp - last_file_update, 267 | }); 268 | return []; 269 | } 270 | }, 271 | }; 272 | } 273 | 274 | const last_update = new Map(); 275 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [@Deno-PLC](https://github.com/deno-plc) / [vite-plugin-deno](https://jsr.io/@deno-plc/vite-plugin-deno) 2 | 3 | Native Vite support for Deno imports (jsr:, npm:, https://). 4 | 5 | Use Deno for the frontend and enjoy development without the hassle of `node_modules` and package managers! 6 | 7 | ## Overview 8 | 9 | 1. Enable Deno for the whole workspace 10 | 11 | 2. Adjust your Vite config to use this plugin 12 | 13 | 3. Enjoy development without `node_modules` and package managers 14 | 15 | ## Project status 16 | 17 | `vite-plugin-deno` can be considered 'ready' for standard setups, however in more complex setups or when using NPM 18 | dependencies that do hacky things, builds might fail. 19 | 20 | In this case good knowledge of module resolution is required to troubleshoot these problems. Of course I will assist you 21 | in this process, feel free to contact [me](https://github.com/hansSchall) via GitHub or Matrix. Please always open an 22 | Github Issue to help others in the same situation. 23 | 24 | _**Short: Nothing fow newbies...**_ 25 | 26 | Please read the [FAQ / Known limitations](#faq--known-limitations) section first and make sure you are not using 27 | anything that is described as incompatible there. 28 | 29 | I use the plugin on my own for a quite large codebase that includes SSR, multiple frontend builds, server code bundling, 30 | WebAssembly and a number of commonly used dependencies. This is used as a reference project for testing. While this can 31 | never be a replacement for unit tests, a real world project is a pretty good testing playground for this kind of 32 | software and ensures the plugin always works with the latest Deno versions (failing builds are very likely to be noticed 33 | on my biggest project...). 34 | 35 | ## How does this work? 36 | 37 | This plugin injects a custom rollup resolver at the earliest stage possible (even before the builtin fs loader) which 38 | catches nearly every import. 39 | 40 | Instead of letting Vite resolve the imports the plugin consults the Deno CLI (`deno info --json`). This ensures that all 41 | imports link to exactly the same files Deno would use (including import mapping). 42 | 43 | Additionally the plugin contains a Node.js/NPM compatible resolver (including probing and package.json exports), because 44 | `deno info` only outputs the resolved npm package versions, not the exact files. 45 | 46 | A custom loader is able to locate the source code for all those new specifier schemes (for example in the global deno 47 | cache). `file:` URLs are mapped back to ordinary paths to make HMR work (Vite has no clue about `file:` URLs). The 48 | source code of `npm:` imports is transformed from CJS to ESM if necessary. 49 | 50 | ## Supported imports 51 | 52 | ### Provided by Deno 53 | 54 | - `./foo.ts`: relative imports 55 | - `https://deno.land/x/foo@1.2.3/mod.ts`: HTTPS imports 56 | - `jsr:@scope/foo`: JSR 57 | - `npm:foo@^1.0.0`: NPM with version range 58 | - `foo`: Mapped imports (`deno.json`>`imports`) 59 | 60 | ... and maybe imports that are not even invented yet, none of the imports above is explicitly handled by the plugin, 61 | `deno info` tells us everything that is needed to get the module source code. 62 | 63 | ### Provided by the Plugin 64 | 65 | - `npm:foo@1.2.3`: resolved NPM imports (including subpath imports) 66 | 67 | The following imports are only used internally, but you may get in contact with them in the DevTools. You cannot use 68 | them in your source code because Deno wont be able to resolve them, but you may specify them in 69 | [`extra_import_map`](https://jsr.io/@deno-plc/vite-plugin-deno/doc/~/PluginDenoOptions.extra_import_map) 70 | 71 | - `npm-data:foo@1.2.3/bar.js`: This references an internal file of the package tarball (remember, not all files in an 72 | NPM package can be imported from the outside) 73 | - `npm-probe:foo@1.2.3/bar`: Same as above, but with probing. Will be resolved to a `npm-data:` URL 74 | 75 | ## Usage 76 | 77 | Currently only build script configurations are supported because `vite.config.ts` will always be run with Node :-(. It 78 | is not that complicated as it sounds, you just have to use the JS API of Vite. 79 | 80 | ### `scripts/vite.ts` 81 | 82 | ```ts 83 | import { pluginDeno } from "@deno-plc/vite-plugin-deno"; 84 | import type { InlineConfig } from "vite"; 85 | 86 | export const config: InlineConfig = { 87 | configFile: false, // configuration is inlined here 88 | server: { 89 | port: 80, 90 | }, 91 | plugins: [ 92 | pluginDeno({ 93 | // see configuration docs 94 | }), 95 | ], 96 | }; 97 | ``` 98 | 99 | ### `scripts/dev.ts`: 100 | 101 | ```ts 102 | import { createServer } from "vite"; 103 | import { config } from "./vite.ts"; 104 | 105 | const server = await createServer(config); 106 | await server.listen(); 107 | server.printUrls(); 108 | ``` 109 | 110 | ### `scripts/release.ts` 111 | 112 | ```ts 113 | import { build } from "vite"; 114 | import { config } from "./vite.ts"; 115 | 116 | await build(config); 117 | ``` 118 | 119 | ### `Deno.json` 120 | 121 | Include the DOM in the TS compiler options and define the build tasks 122 | 123 | ```json 124 | { 125 | "tasks": { 126 | "dev": "deno run -A scripts/dev.ts", 127 | "release": "deno run -A scripts/release.ts" 128 | }, 129 | "compilerOptions": { 130 | "lib": [ 131 | "deno.window", 132 | "deno.ns", 133 | "ESNext", 134 | "DOM", 135 | "DOM.Iterable", 136 | "DOM.AsyncIterable", 137 | "webworker" 138 | ] 139 | } 140 | } 141 | ``` 142 | 143 | For an example/template see [examples/plain](examples/plain/README.md) 144 | 145 | ## Configuration options (Overview) 146 | 147 | [> for a full version visit the JSR Docs](https://jsr.io/@deno-plc/vite-plugin-deno/doc/~/PluginDenoOptions) 148 | 149 | ### `deno_json` and `deno_lock` 150 | 151 | Override the locations of `deno.json` and `deno.lock`. Passed to `deno --config ...` and `deno --lock ...` 152 | 153 | ### `env`: `"deno"` or `"browser"`(default) 154 | 155 | Set to `"deno"` if you are bundling for Deno. This enables `node:` imports. 156 | 157 | Set to `"browser"` (default) if you are bundling for Browsers. This prefers NPM `browser` exports. 158 | 159 | ### `undeclared_npm_imports`: `string[]` 160 | 161 | Those packages can always be imported, even when they don't show up in the deno module graph. This can be used to 162 | resolve packages that are imported by injected code like HMR. 163 | 164 | ### `extra_import_map`: `string` => `string` 165 | 166 | This can be a anything the `Map` constructor supports. (yes, we use a Map for the import map) 167 | 168 | This import map can be used to polyfill `node:` (for details see [here](#polyfilling-node)) or do the same as 169 | `undeclared_npm_imports` on a more granular level. 170 | 171 | Sometimes it might be required to add `#standalone` to the replaced import, otherwise you will get errors because the 172 | replaced import is (of course) not reported by `deno info`. The `#standalone` instructs the plugin to treat the import 173 | like an independent entrypoint. 174 | 175 | ### `exclude`: `(string | RegExp)[]` 176 | 177 | Those imports wont be touched. RegExps are preferred (strings are converted to RegExps anyway). Note: Deno still checks 178 | these imports so make sure they are valid anyway. 179 | 180 | ### `legacy_npm`: `string[]` 181 | 182 | These npm packages are left over to Vite 183 | 184 | ## `node_modules` 185 | 186 | This plugin works without `node_modules` most of the time, but in some cases this directory is required to make things 187 | work. 188 | 189 | There are various reasons why a dependency has to reside in `node_modules`. Some dependencies like `@xterm/xterm` do 190 | ugly things with their exports (like exporting inside if-blocks), so it is impossible for this plugin to transform them 191 | to ESM. In this case we let Vite do it using plain old `node_modules` instead. 192 | 193 | There are good news: Deno supports `node_modules` natively! (= you don't even need Node.js and NPM) Just set 194 | `"nodeModulesDir": "auto",` in your `deno.json` and add the respective dependency to the `legacy_npm` option of this 195 | plugin. 196 | 197 | Don't worry about the `node_modules` folder, it only contains symlinks to the global cache! 198 | [Read more](https://deno.com/blog/your-new-js-package-manager) 199 | 200 | ## Polyfilling `node:` 201 | 202 | This plugin does not automatically polyfill `node:` in browsers, but you can easily do so by setting `extra_import_map`. 203 | 204 | Unfortunately most polyfill packages do crazy things with exports (I tested `buffer` and `util`, both didn't worked out 205 | of the box for different reasons). This is why it is not as straightforward as mapping `node:buffer` to `npm:buffer` 206 | 207 | 1. Select an appropriate polyfill package (likely on NPM) 208 | 2. Look up its most recent version 209 | 3. link it in `extra_import_map`: `"node:buffer", "https://cdn.jsdelivr.net/npm/buffer@6.0.3/+esm#standalone"` 210 | 211 | We use a https:// import to get rid of CommonJS issues, but in the end it is just a Deno remote import (=Deno downloads 212 | the file, no CDN import) 213 | 214 | Make sure to add [`#standalone`](#extra_import_map-string--string) to the replaced import. 215 | 216 | In case you don't want to polyfill a module and instead let the import fail, redirect it to `virtual:node:null` (this 217 | time without `#standalone`). This makes Vite happy but any attempt to load the module will fail with an error (It 218 | resolves to a file that just contains a `throw` statement). This is useful if a package does feature detection: It tries 219 | to dynamically import `node:fs` (or any other module), if it succeeds it uses the filesystem and if it fails it simply 220 | doesn't do anything filesystem-related. This mechanism is used by many packages that use the filesystem when used with 221 | Node/Deno, but work in browsers, too. 222 | 223 | ## Usage with React 224 | 225 | Currently React is unsupported. 226 | 227 | 1. The Deno LSP has problems with React. It is about missing JSXRuntime types... 228 | 2. `react-dom` does some extremely ugly things with cjs exports (like exporting inside an if statement ...). For this 229 | reason it cannot be transformed to ESM correctly. At the same time it needs to be linked by JSX which makes it 230 | extremely difficult to use it via the `node_modules` fallback. 231 | 232 | I personally only use Preact, so this is not top priority. 233 | 234 | Until this is supported out of the box you could use the [Preact configuration](#usage-with-preact). If you are doing 235 | this, all react imports are redirected to preact and the whole application is run with the react compatibility layer... 236 | (this works without any problems 🤯) Read more: https://preactjs.com/guide/v10/switching-to-preact. You do not need to 237 | care about the bundler setup shown there, the setup [below](#usage-with-preact) already configures everything. 238 | 239 | If you really need React, please file an issue. This should be a very rare case because the `preact/compat` layer covers 240 | nearly the whole React API. By the way, Preact is a bit faster than React... 241 | 242 | ## Usage with Preact 243 | 244 | For an example/template see [examples/preact](examples/preact/README.md) 245 | 246 | Although `@preact/preset-vite` works when the respective Babel plugins are linked via `node_modules`, I do recommend 247 | _**against**_ using it. 248 | 249 | With a only few lines of configuration you can do exactly the same. By the way: this speeds up the development server a 250 | lot, because it uses ESBuild instead of Babel 251 | 252 | Just update your Vite config to set up prefresh (the Preact HMR Engine) and ESBuild for JSX transformation: 253 | 254 | ```typescript 255 | import { pluginDeno } from "@deno-plc/vite-plugin-deno"; 256 | import prefresh from "@prefresh/vite"; // HMR 257 | import type { InlineConfig, Plugin } from "vite"; 258 | 259 | export const config: InlineConfig = { 260 | plugins: [ 261 | pluginDeno({ 262 | env: "browser", 263 | undeclared_npm_imports: [ 264 | // injected by JSX transform 265 | "preact/jsx-runtime", 266 | "preact/jsx-dev-runtime", 267 | // injected by HMR 268 | "@prefresh/core", 269 | "@prefresh/utils", 270 | // injected by react compat 271 | "@preact/compat", 272 | ], 273 | extra_import_map: new Map([ 274 | // react compat 275 | ["react", "@preact/compat"], 276 | ["react-dom", "@preact/compat"], 277 | ]), 278 | }), 279 | // HMR Plugin 280 | prefresh({ 281 | // `node_modules` is excluded internally, lets do the same 282 | exclude: [/^npm/, /registry.npmjs.org/, /^jsr/, /^https?/], 283 | }) as Plugin, 284 | ], 285 | // JSX transform 286 | esbuild: { 287 | jsx: "automatic", 288 | jsxImportSource: "preact", 289 | }, 290 | }; 291 | ``` 292 | 293 | And your `deno.json`: 294 | 295 | ```json 296 | "compilerOptions": { 297 | "jsx": "react-jsx", 298 | "jsxImportSource": "preact", 299 | } 300 | ``` 301 | 302 | If you want to use the Preact DevTools, follow the instructions there: https://preactjs.github.io/preact-devtools/ (it's 303 | one import) 304 | 305 | We need the prefresh exclude rule to replicate the internal exclude of all paths containing `node_modules`. Otherwise 306 | prefresh would inject HMR helpers into libraries and the code that powers HMR, which causes very strange errors. 307 | 308 | If you are on Windows, a [little workaround](#denostat-workaround-needed-windows-only) is required. 309 | 310 | ## Usage with Deno (Code bundling) 311 | 312 | Just set the `env` option to `deno`, everything should work out of the box! (even with `node:` imports) 313 | 314 | This can replace `deno bundle`. 315 | 316 | If you want a lightweight solution, check out 317 | [esbuild_deno_loader](https://github.com/lucacasonato/esbuild_deno_loader), which is exactly the same for esbuild. 318 | 319 | ## FAQ / Known limitations 320 | 321 | ### Asset imports 322 | 323 | Importing assets like `import imgUrl from './img.png'` will throw errors, because Deno simply cannot handle such 324 | imports. Currently it is not even possible to exclude these files :-( 325 | 326 | Instead of asset imports you should use `const imgUrl = new URL("/img.png", import.meta.url).href` which provides 327 | exactly the same functionality while being compatible with Deno. 328 | 329 | ### CSS imports 330 | 331 | Similar to asset imports, CSS imports are vite-only, so Deno complains about them... 332 | 333 | **Solution 1:** Import your CSS directly from the HTML 334 | 335 | **Solution 2:** Import your CSS fom a JS file that is imported from the HTML, excluded from this plugin and not imported 336 | from the rest of the JS/TS code (like this one: 337 | [examples/preact/src/style-import.js](examples/preact/src/style-import.js)) 338 | 339 | ### Fullstack Frameworks 340 | 341 | Fullstack frameworks are most likely incompatible with this / Deno. They are unhappy with swapping out internal parts in 342 | general, especially when it affects a fundamental thing like module resolution. Additionally most of them use React. 343 | 344 | ### React does not work (and maybe more packages that do ugly things with exports) 345 | 346 | See [Usage with React](#usage-with-react) 347 | 348 | For other packages it might be possible to use the [`node_modules` fallback](#node_modules) 349 | 350 | ### Build scripts 351 | 352 | The classic `vite.config.ts` file would be executed using Node.js instead of Deno. Just use scripts as shown above. 353 | 354 | ### Dependency optimization 355 | 356 | Unsupported because dependency optimization relies on `node_modules`. If you really need it (lodash), see 357 | [`node_modules` section](#node_modules) 358 | 359 | ### Babel/PostCSS 360 | 361 | Some other plugins require Babel or PostCSS or one of their plugins. Their plugin loaders depend on `node_modules`, see 362 | [`node_modules` section](#node_modules). 363 | 364 | In order to get the best DX possible, you should avoid Babel based plugins. For most setups Babel isn't really needed, 365 | see [Usage wit Preact](#usage-with-preact). Using builtin esbuild is usually many times faster. 366 | 367 | ### TailwindCSS 368 | 369 | The `tailwindcss` PostCSS plugin currently needs to be installed in `node_modules`, see 370 | [`node_modules` section](#node_modules) 371 | 372 | The recommended way is to use [Tailwind Play CDN](https://tailwindcss.com/docs/installation/play-cdn) during development 373 | and the [Tailwind CLI](https://tailwindcss.com/docs/installation) for release build. 374 | 375 | ### `Deno.stat` workaround is not needed anymore 376 | 377 | The issue has been fixed by Deno. In case you use an old Deno version (1.x and early 2.x) read about it 378 | [here](https://github.com/deno-plc/vite-plugin-deno/tree/c917814f5b4cf0fdcbfcd9a09772fe6644e24cb0?tab=readme-ov-file#denostat-workaround-needed-windows-only) 379 | 380 | ### Deno 2.x 381 | 382 | Versions older than 2.1.7 do not support Deno 2.0. 383 | 384 | ## Acknowledgements 385 | 386 | [esbuild_deno_loader](https://github.com/lucacasonato/esbuild_deno_loader) does exactly the same for esbuild. The basic 387 | principle of operation is the same. 388 | 389 | [resolve.exports](https://github.com/lukeed/resolve.exports) helped a lot, it handles all the `package.json` fields. 390 | 391 | ## License (LGPL-2.1-or-later) 392 | 393 | Copyright (C) 2024 Hans Schallmoser 394 | 395 | This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public 396 | License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later 397 | version. 398 | 399 | This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 400 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 401 | details. 402 | 403 | You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the 404 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or see 405 | https://www.gnu.org/licenses/ 406 | -------------------------------------------------------------------------------- /src/graph.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @license LGPL-2.1-or-later 3 | * 4 | * vite-plugin-deno 5 | * 6 | * Copyright (C) 2024 - 2025 Hans Schallmoser 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 21 | * USA or see . 22 | */ 23 | 24 | import { join, toFileUrl } from "@std/path"; 25 | import { z } from "zod"; 26 | import type { Opt } from "./options.ts"; 27 | import { format, parse } from "@std/semver"; 28 | import { get_npm_import_link, getNPMData, getNPMPath, importProbe, NPMPackage } from "./npm.ts"; 29 | import { type ModuleSpecifier, parseModuleSpecifier, parseNPMExact, parseNPMImport } from "./specifier.ts"; 30 | import { assert } from "jsr:@std/assert@^0.225.2/assert"; 31 | import { is_excluded } from "./exclude.ts"; 32 | import { supported_extensions } from "./constants.ts"; 33 | 34 | const DenoInfoPosition = z.object({ 35 | line: z.number().int().nonnegative(), 36 | character: z.number().int().nonnegative(), 37 | }); 38 | 39 | const DenoInfoImport = z.object({ 40 | specifier: z.string(), 41 | span: z.object({ 42 | start: DenoInfoPosition, 43 | end: DenoInfoPosition, 44 | }), 45 | }); 46 | 47 | const DenoInfoModule = z.union([ 48 | z.object({ 49 | kind: z.literal("esm"), 50 | specifier: z.string().transform(parseModuleSpecifier), 51 | mediaType: z.enum(["TypeScript", "JavaScript", "TSX", "Dts"]), 52 | dependencies: z.object({ 53 | specifier: z.string(), 54 | type: DenoInfoImport.optional(), 55 | code: DenoInfoImport.optional(), 56 | }).array().default([]), 57 | local: z.string().transform(toFileUrl), 58 | size: z.number().int().nonnegative(), 59 | }), 60 | z.object({ 61 | kind: z.literal("asserted"), 62 | specifier: z.string().transform(parseModuleSpecifier), 63 | mediaType: z.enum(["Json"]), 64 | local: z.string().transform(toFileUrl), 65 | size: z.number().int().nonnegative(), 66 | }), 67 | z.object({ 68 | kind: z.literal("node"), 69 | specifier: z.string().transform(parseModuleSpecifier), 70 | moduleName: z.string(), 71 | }), 72 | z.object({ 73 | kind: z.literal("npm"), 74 | specifier: z.string().transform(parseModuleSpecifier), 75 | npmPackage: z.string(), 76 | }), 77 | ]); 78 | type DenoInfoModule = z.infer; 79 | 80 | const DenoInfoNPMPackage = z.object({ 81 | name: z.string(), 82 | version: z.string().transform((version) => parse(version)), 83 | dependencies: z.string().array(), 84 | }); 85 | 86 | const DenoInfoOutput = z.object({ 87 | roots: z.string().array(), 88 | modules: DenoInfoModule.array(), 89 | redirects: z.record(z.string().transform(parseModuleSpecifier)), 90 | packages: z.record(z.string()), 91 | npmPackages: z.record(DenoInfoNPMPackage), 92 | }); 93 | 94 | export const npmImportKind = Symbol(); 95 | export const npmDataKind = Symbol(); 96 | export const virtualImportKind = Symbol(); 97 | 98 | export interface NPMImportInfo { 99 | kind: typeof npmImportKind; 100 | specifier: ModuleSpecifier; 101 | package: NPMPackage; 102 | module: ModuleSpecifier; 103 | } 104 | 105 | export interface NPMDataInfo { 106 | kind: typeof npmDataKind; 107 | specifier: ModuleSpecifier; 108 | package: NPMPackage; 109 | } 110 | 111 | export interface VirtualInfo { 112 | kind: typeof virtualImportKind; 113 | specifier: ModuleSpecifier; 114 | code: () => Promise; 115 | } 116 | 117 | export class GraphModule { 118 | readonly specifier: ModuleSpecifier; 119 | readonly esm_dependencies = new Map(); 120 | private constructor( 121 | readonly def: DenoInfoModule | NPMImportInfo | NPMDataInfo | VirtualInfo, 122 | readonly graph: ModuleGraph, 123 | ) { 124 | this.specifier = def.specifier; 125 | 126 | graph.modules.set(this.specifier.href, this); 127 | 128 | // this.load(); 129 | } 130 | 131 | public static new( 132 | def: DenoInfoModule | NPMImportInfo | NPMDataInfo | VirtualInfo, 133 | graph: ModuleGraph, 134 | ): GraphModule { 135 | const spec = def.specifier.href; 136 | const mod = graph.modules.get(spec) || new GraphModule(def, graph); 137 | 138 | if (def.kind === "esm") { 139 | for (const dep of def.dependencies) { 140 | if (dep.code) { 141 | graph.get_module(parseModuleSpecifier(dep.code.specifier), false).then((dep_mod) => { 142 | if (dep_mod) { 143 | mod.esm_dependencies.set(dep.specifier, dep_mod); 144 | } 145 | }); 146 | } 147 | } 148 | } 149 | 150 | return mod; 151 | } 152 | 153 | private code: string | Promise | null = null; 154 | 155 | async #load() { 156 | if (this.def.kind === "esm") { 157 | return await Deno.readTextFile(this.def.local); 158 | } else if (this.def.kind === npmImportKind) { 159 | return await get_npm_import_link(this.graph.o, this.def); 160 | } else if (this.def.kind === npmDataKind) { 161 | return await getNPMData(this.graph.o, this.def.specifier); 162 | } else if (this.def.kind === virtualImportKind) { 163 | return await this.def.code(); 164 | } 165 | throw new Error(`module type ${this.def.kind} unsupported`); 166 | } 167 | 168 | async load(): Promise { 169 | if (this.code) { 170 | return this.code; 171 | } else { 172 | const pr = this.#load(); 173 | this.code = pr; 174 | const code = await pr; 175 | if (this.specifier.protocol === "file:") { 176 | this.code = null; 177 | } else { 178 | this.code = code; 179 | } 180 | return code; 181 | } 182 | } 183 | 184 | async resolve_import(spec: string): Promise { 185 | if (this.def.kind === npmDataKind) { 186 | if (spec.startsWith(".")) { 187 | return await this.graph.get_module( 188 | parseModuleSpecifier(`npm-probe:${join(this.specifier.pathname, "../", spec)}`), 189 | ); 190 | } else { 191 | const imp = parseNPMImport(spec); 192 | assert(imp); 193 | const pkg = this.def.package.dependencies.get(imp.name); 194 | assert(pkg, `cannot find dependency ${imp.name}(${spec}) on ${this.def.package.name}`); 195 | return await this.graph.get_module(await pkg.resolve_import(imp.path)); 196 | } 197 | } else if (this.def.kind === "esm") { 198 | return this.esm_dependencies.get(spec) || null; 199 | } 200 | return null; 201 | } 202 | } 203 | 204 | export class ModuleGraph { 205 | constructor(readonly o: Opt) { 206 | GraphModule.new({ 207 | kind: virtualImportKind, 208 | specifier: parseModuleSpecifier("virtual:node:null"), 209 | code() { 210 | return Promise.resolve(`throw new Error("");`); 211 | }, 212 | }, this); 213 | } 214 | 215 | #pending: Promise | null = null; 216 | readonly modules = new Map(); 217 | readonly #redirects = new Map(); 218 | readonly #npm_extended_id = new Map(); 219 | readonly npm_packages = new Map(); 220 | readonly npm_package_versions = new Map>(); 221 | 222 | async call_deno(root: string) { 223 | const args = ["info", "--json"]; 224 | if (this.o.deno_json) { 225 | args.push("--config", this.o.deno_json); 226 | } 227 | if (this.o.deno_lock) { 228 | args.push("--lock", this.o.deno_lock); 229 | } 230 | args.push(root); 231 | const start = performance.now(); 232 | const info = new Deno.Command(Deno.execPath(), { 233 | args, 234 | env: { DENO_NO_PACKAGE_JSON: "true" }, 235 | stdout: "piped", 236 | stderr: "inherit", 237 | }); 238 | 239 | const output = await info.output(); 240 | const duration = performance.now() - start; 241 | this.o.logger.info(`deno info {root} took {duration}ms`, { 242 | root, 243 | duration, 244 | }); 245 | const data = JSON.parse(new TextDecoder().decode(output.stdout)); 246 | return data; 247 | } 248 | 249 | private async get_deno_info(root: string) { 250 | const deno_info = await this.call_deno(root); 251 | const parsed = DenoInfoOutput.safeParse(deno_info); 252 | 253 | if (!parsed.success) { 254 | const partial_parse = z.object({ 255 | modules: z.object({ 256 | error: z.string().optional(), 257 | specifier: z.string().transform(parseModuleSpecifier), 258 | }).array(), 259 | }).safeParse(deno_info); 260 | if (partial_parse.success) { 261 | const { modules } = partial_parse.data; 262 | const errors: string[] = []; 263 | for (const { specifier, error } of modules) { 264 | if (error) { 265 | errors.push(`${specifier}: ${error}`); 266 | } 267 | } 268 | if (errors.length > 0) { 269 | throw new Error(`failed to look up module graph of ${root}:\n${errors.join("\n")}`); 270 | } 271 | } 272 | throw new Error(`failed to look up module graph of ${root}: Invalid Output:\n ${parsed.error}`); 273 | } 274 | 275 | const { modules, redirects, npmPackages, roots } = parsed.data; 276 | 277 | assert(roots.length === 1); 278 | 279 | const waitNPM: Promise[] = []; 280 | 281 | for (const extended_id in npmPackages) { 282 | const { name, version, dependencies } = npmPackages[extended_id]; 283 | 284 | if (this.npm_package_versions.has(name)) { 285 | this.npm_package_versions.get(name)!.add(format(version)); 286 | } else { 287 | this.npm_package_versions.set(name, new Set([format(version)])); 288 | } 289 | 290 | const npm_name = `${name}@${format(version)}`; 291 | 292 | // { 293 | // if (this.#npm_extended_id.has(npm_name)) { 294 | // if (this.#npm_extended_id.get(npm_name) !== extended_id) { 295 | // throw new Error( 296 | // `Expectation failed: underscore version extension differs while processing package '${name}'@'${ 297 | // format(version) 298 | // }' processing '${extended_id}' hit '${ 299 | // this.#npm_extended_id.get(npm_name) 300 | // }'. Please file an issue: https://github.com/deno-plc/vite-plugin-deno/issues/new`, 301 | // ); 302 | // } 303 | // } else { 304 | // this.#npm_extended_id.set(npm_name, extended_id); 305 | // } 306 | // } 307 | 308 | const specifier = parseModuleSpecifier(`npm:${npm_name}`); 309 | if (npm_name !== extended_id) { 310 | this.#redirects.set(parseModuleSpecifier(`npm:${extended_id}`).href, specifier); 311 | } 312 | 313 | if (this.npm_packages.has(npm_name)) { 314 | if (!this.npm_packages.has(extended_id)) { 315 | this.npm_packages.set(extended_id, this.npm_packages.get(npm_name)!); 316 | } 317 | continue; 318 | } 319 | 320 | const pkg = new NPMPackage(name, version, dependencies, this); 321 | 322 | this.npm_packages.set(npm_name, pkg); 323 | this.npm_packages.set(extended_id, pkg); 324 | 325 | waitNPM.push(pkg.fetch_metadata()); 326 | } 327 | 328 | for (const redirect in redirects) { 329 | this.#redirects.set(parseModuleSpecifier(redirect).href, redirects[redirect]); 330 | } 331 | 332 | // remove self-redirects 333 | for (const [k, v] of this.#redirects) { 334 | if (k === v.href) { 335 | this.#redirects.delete(k); 336 | } 337 | } 338 | 339 | Promise.all(waitNPM).then(() => { 340 | for (const [_id, pkg] of this.npm_packages) { 341 | pkg.link(); 342 | } 343 | }); 344 | 345 | for (const mod of modules) { 346 | if (mod.kind === "esm") { 347 | GraphModule.new(mod, this); 348 | } 349 | } 350 | } 351 | 352 | async update_info(specifier: ModuleSpecifier) { 353 | const pr = this.get_deno_info(specifier.href); 354 | this.#pending = pr; 355 | await pr; 356 | this.#pending = null; 357 | } 358 | 359 | async get_module(specifier: ModuleSpecifier, may_fetch: boolean = true): Promise { 360 | if (is_excluded(specifier.href, this.o)) { 361 | return null; 362 | } 363 | const spec_ext = specifier.pathname.split(".").pop(); 364 | if (spec_ext && /^[a-zA-Z]{1,20}$/.test(spec_ext) && !supported_extensions.includes(spec_ext)) { 365 | return null; 366 | } 367 | if (this.#redirects.has(specifier.href)) { 368 | // console.log(`redirecting ${specifier}`); 369 | return await this.get_module(this.#redirects.get(specifier.href)!, may_fetch); 370 | } 371 | if (this.o.extra_import_map.has(specifier.href)) { 372 | return await this.get_module( 373 | parseModuleSpecifier(await this.o.extra_import_map.get(specifier.href)!), 374 | may_fetch, 375 | ); 376 | } 377 | if (this.modules.has(specifier.href)) { 378 | return this.modules.get(specifier.href)!; 379 | } 380 | if (this.#pending) { 381 | await this.#pending; 382 | return await this.get_module(specifier, may_fetch); 383 | } 384 | if (specifier.protocol === "npm:") { 385 | const id = parseNPMExact(specifier.pathname); 386 | if (id) { 387 | const pkg = this.npm_packages.get(`${id.name}@${format(id.version)}`); 388 | if (pkg) { 389 | const spec = await pkg.resolve_import(id.path); 390 | const mod = GraphModule.new({ 391 | kind: npmImportKind, 392 | package: pkg, 393 | specifier, 394 | module: spec, 395 | }, this); 396 | // free-running prefetch 397 | this.get_module(spec, false); 398 | return mod; 399 | } 400 | } 401 | } 402 | if (specifier.protocol === "npm-probe:") { 403 | // console.log(`%c[PROBING] ${specifier}`, "color:#f00"); 404 | const id = parseNPMExact(specifier.pathname); 405 | if (id) { 406 | const pkg = this.npm_packages.get(`${id.name}@${format(id.version)}`); 407 | if (pkg) { 408 | const probe_res = await importProbe( 409 | join(await getNPMPath(pkg.name, pkg.version), id.path), 410 | id.path, 411 | ); 412 | if (probe_res) { 413 | const spec = parseModuleSpecifier(`npm-data:${pkg.name}@${format(pkg.version)}/${probe_res}`); 414 | const mod = GraphModule.new({ 415 | kind: npmDataKind, 416 | specifier: spec, 417 | package: pkg, 418 | }, this); 419 | return mod; 420 | } 421 | } 422 | } 423 | throw new Error(`Failed to probe ${specifier}`); 424 | } 425 | if (specifier.protocol === "npm-data:") { 426 | const id = parseNPMExact(specifier.pathname); 427 | if (id) { 428 | const pkg = this.npm_packages.get(`${id.name}@${format(id.version)}`); 429 | if (pkg) { 430 | const mod = GraphModule.new({ 431 | kind: npmDataKind, 432 | specifier, 433 | package: pkg, 434 | }, this); 435 | return mod; 436 | } 437 | } 438 | throw new Error(`Failed to parse as npm-data: ${specifier}`); 439 | } 440 | if (may_fetch) { 441 | await this.update_info(specifier); 442 | return await this.get_module(specifier, false); 443 | } else { 444 | // console.log(`Specifier ${specifier} could not be resolved`); 445 | // throw new Error(`Specifier ${specifier} could not be resolved`); 446 | 447 | return null; 448 | } 449 | } 450 | 451 | get_resolved(specifier: string): GraphModule | null { 452 | if (this.#redirects.has(specifier)) { 453 | return this.get_resolved(this.#redirects.get(specifier)!.href); 454 | } else if (this.modules.has(specifier)) { 455 | return this.modules.get(specifier)!; 456 | } else { 457 | return null; 458 | } 459 | } 460 | } 461 | -------------------------------------------------------------------------------- /examples/plain/deno.lock: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "specifiers": { 4 | "jsr:@std/assert@0.223": "0.223.0", 5 | "jsr:@std/assert@0.226": "0.226.0", 6 | "jsr:@std/assert@~0.225.2": "0.225.3", 7 | "jsr:@std/path@~0.225.1": "0.225.2", 8 | "jsr:@std/semver@^1.0.2": "1.0.3", 9 | "npm:acorn-walk@^8.3.3": "8.3.4", 10 | "npm:acorn@^8.12.1": "8.13.0", 11 | "npm:lebab@^3.2.4": "3.2.4", 12 | "npm:resolve.exports@^2.0.2": "2.0.2", 13 | "npm:validate-npm-package-name@^5.0.1": "5.0.1", 14 | "npm:vite@^5.2.12": "5.4.9", 15 | "npm:zod@^3.22.5": "3.23.8" 16 | }, 17 | "jsr": { 18 | "@std/assert@0.223.0": { 19 | "integrity": "eb8d6d879d76e1cc431205bd346ed4d88dc051c6366365b1af47034b0670be24" 20 | }, 21 | "@std/assert@0.225.3": { 22 | "integrity": "b3c2847aecf6955b50644cdb9cf072004ea3d1998dd7579fc0acb99dbb23bd4f" 23 | }, 24 | "@std/assert@0.226.0": { 25 | "integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3" 26 | }, 27 | "@std/path@0.225.2": { 28 | "integrity": "0f2db41d36b50ef048dcb0399aac720a5348638dd3cb5bf80685bf2a745aa506", 29 | "dependencies": [ 30 | "jsr:@std/assert@0.226" 31 | ] 32 | }, 33 | "@std/semver@1.0.3": { 34 | "integrity": "7c139c6076a080eeaa4252c78b95ca5302818d7eafab0470d34cafd9930c13c8" 35 | } 36 | }, 37 | "npm": { 38 | "@esbuild/aix-ppc64@0.21.5": { 39 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==" 40 | }, 41 | "@esbuild/android-arm64@0.21.5": { 42 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==" 43 | }, 44 | "@esbuild/android-arm@0.21.5": { 45 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==" 46 | }, 47 | "@esbuild/android-x64@0.21.5": { 48 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==" 49 | }, 50 | "@esbuild/darwin-arm64@0.21.5": { 51 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==" 52 | }, 53 | "@esbuild/darwin-x64@0.21.5": { 54 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==" 55 | }, 56 | "@esbuild/freebsd-arm64@0.21.5": { 57 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==" 58 | }, 59 | "@esbuild/freebsd-x64@0.21.5": { 60 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==" 61 | }, 62 | "@esbuild/linux-arm64@0.21.5": { 63 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==" 64 | }, 65 | "@esbuild/linux-arm@0.21.5": { 66 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==" 67 | }, 68 | "@esbuild/linux-ia32@0.21.5": { 69 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==" 70 | }, 71 | "@esbuild/linux-loong64@0.21.5": { 72 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==" 73 | }, 74 | "@esbuild/linux-mips64el@0.21.5": { 75 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==" 76 | }, 77 | "@esbuild/linux-ppc64@0.21.5": { 78 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==" 79 | }, 80 | "@esbuild/linux-riscv64@0.21.5": { 81 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==" 82 | }, 83 | "@esbuild/linux-s390x@0.21.5": { 84 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==" 85 | }, 86 | "@esbuild/linux-x64@0.21.5": { 87 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==" 88 | }, 89 | "@esbuild/netbsd-x64@0.21.5": { 90 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==" 91 | }, 92 | "@esbuild/openbsd-x64@0.21.5": { 93 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==" 94 | }, 95 | "@esbuild/sunos-x64@0.21.5": { 96 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==" 97 | }, 98 | "@esbuild/win32-arm64@0.21.5": { 99 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==" 100 | }, 101 | "@esbuild/win32-ia32@0.21.5": { 102 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==" 103 | }, 104 | "@esbuild/win32-x64@0.21.5": { 105 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==" 106 | }, 107 | "@isaacs/cliui@8.0.2": { 108 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 109 | "dependencies": [ 110 | "string-width@5.1.2", 111 | "string-width-cjs@npm:string-width@4.2.3", 112 | "strip-ansi@7.1.0", 113 | "strip-ansi-cjs@npm:strip-ansi@6.0.1", 114 | "wrap-ansi@8.1.0", 115 | "wrap-ansi-cjs@npm:wrap-ansi@7.0.0" 116 | ] 117 | }, 118 | "@pkgjs/parseargs@0.11.0": { 119 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==" 120 | }, 121 | "@rollup/rollup-android-arm-eabi@4.24.0": { 122 | "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==" 123 | }, 124 | "@rollup/rollup-android-arm64@4.24.0": { 125 | "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==" 126 | }, 127 | "@rollup/rollup-darwin-arm64@4.24.0": { 128 | "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==" 129 | }, 130 | "@rollup/rollup-darwin-x64@4.24.0": { 131 | "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==" 132 | }, 133 | "@rollup/rollup-linux-arm-gnueabihf@4.24.0": { 134 | "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==" 135 | }, 136 | "@rollup/rollup-linux-arm-musleabihf@4.24.0": { 137 | "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==" 138 | }, 139 | "@rollup/rollup-linux-arm64-gnu@4.24.0": { 140 | "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==" 141 | }, 142 | "@rollup/rollup-linux-arm64-musl@4.24.0": { 143 | "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==" 144 | }, 145 | "@rollup/rollup-linux-powerpc64le-gnu@4.24.0": { 146 | "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==" 147 | }, 148 | "@rollup/rollup-linux-riscv64-gnu@4.24.0": { 149 | "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==" 150 | }, 151 | "@rollup/rollup-linux-s390x-gnu@4.24.0": { 152 | "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==" 153 | }, 154 | "@rollup/rollup-linux-x64-gnu@4.24.0": { 155 | "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==" 156 | }, 157 | "@rollup/rollup-linux-x64-musl@4.24.0": { 158 | "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==" 159 | }, 160 | "@rollup/rollup-win32-arm64-msvc@4.24.0": { 161 | "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==" 162 | }, 163 | "@rollup/rollup-win32-ia32-msvc@4.24.0": { 164 | "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==" 165 | }, 166 | "@rollup/rollup-win32-x64-msvc@4.24.0": { 167 | "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==" 168 | }, 169 | "@types/estree@1.0.6": { 170 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" 171 | }, 172 | "acorn-jsx@5.3.2_acorn@8.13.0": { 173 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 174 | "dependencies": [ 175 | "acorn" 176 | ] 177 | }, 178 | "acorn-walk@8.3.4": { 179 | "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", 180 | "dependencies": [ 181 | "acorn" 182 | ] 183 | }, 184 | "acorn@8.13.0": { 185 | "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==" 186 | }, 187 | "ansi-regex@5.0.1": { 188 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 189 | }, 190 | "ansi-regex@6.1.0": { 191 | "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==" 192 | }, 193 | "ansi-styles@4.3.0": { 194 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 195 | "dependencies": [ 196 | "color-convert" 197 | ] 198 | }, 199 | "ansi-styles@6.2.1": { 200 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" 201 | }, 202 | "ast-types@0.16.1": { 203 | "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", 204 | "dependencies": [ 205 | "tslib" 206 | ] 207 | }, 208 | "balanced-match@1.0.2": { 209 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 210 | }, 211 | "brace-expansion@2.0.1": { 212 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 213 | "dependencies": [ 214 | "balanced-match" 215 | ] 216 | }, 217 | "color-convert@2.0.1": { 218 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 219 | "dependencies": [ 220 | "color-name" 221 | ] 222 | }, 223 | "color-name@1.1.4": { 224 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 225 | }, 226 | "commander@11.1.0": { 227 | "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==" 228 | }, 229 | "cross-spawn@7.0.3": { 230 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 231 | "dependencies": [ 232 | "path-key", 233 | "shebang-command", 234 | "which" 235 | ] 236 | }, 237 | "eastasianwidth@0.2.0": { 238 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 239 | }, 240 | "emoji-regex@8.0.0": { 241 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 242 | }, 243 | "emoji-regex@9.2.2": { 244 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 245 | }, 246 | "esbuild@0.21.5": { 247 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 248 | "dependencies": [ 249 | "@esbuild/aix-ppc64", 250 | "@esbuild/android-arm", 251 | "@esbuild/android-arm64", 252 | "@esbuild/android-x64", 253 | "@esbuild/darwin-arm64", 254 | "@esbuild/darwin-x64", 255 | "@esbuild/freebsd-arm64", 256 | "@esbuild/freebsd-x64", 257 | "@esbuild/linux-arm", 258 | "@esbuild/linux-arm64", 259 | "@esbuild/linux-ia32", 260 | "@esbuild/linux-loong64", 261 | "@esbuild/linux-mips64el", 262 | "@esbuild/linux-ppc64", 263 | "@esbuild/linux-riscv64", 264 | "@esbuild/linux-s390x", 265 | "@esbuild/linux-x64", 266 | "@esbuild/netbsd-x64", 267 | "@esbuild/openbsd-x64", 268 | "@esbuild/sunos-x64", 269 | "@esbuild/win32-arm64", 270 | "@esbuild/win32-ia32", 271 | "@esbuild/win32-x64" 272 | ] 273 | }, 274 | "escope@4.0.0": { 275 | "integrity": "sha512-E36qlD/r6RJHVpPKArgMoMlNJzoRJFH8z/cAZlI9lbc45zB3+S7i9k6e/MNb+7bZQzNEa6r8WKN3BovpeIBwgA==", 276 | "dependencies": [ 277 | "esrecurse", 278 | "estraverse@4.3.0" 279 | ] 280 | }, 281 | "eslint-visitor-keys@3.4.3": { 282 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" 283 | }, 284 | "espree@9.6.1_acorn@8.13.0": { 285 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", 286 | "dependencies": [ 287 | "acorn", 288 | "acorn-jsx", 289 | "eslint-visitor-keys" 290 | ] 291 | }, 292 | "esprima@4.0.1": { 293 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 294 | }, 295 | "esrecurse@4.3.0": { 296 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 297 | "dependencies": [ 298 | "estraverse@5.3.0" 299 | ] 300 | }, 301 | "estraverse@4.3.0": { 302 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" 303 | }, 304 | "estraverse@5.3.0": { 305 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" 306 | }, 307 | "f-matches@1.1.0": { 308 | "integrity": "sha512-8NALQS5oB1+9hkEwiRjsRroTAQ7zKmXjxe0ZcMHDRrFIR54PhSJp7Rm+Q5+tgJ7eO5ejCgbUPNXeiflX18Rt0Q==", 309 | "dependencies": [ 310 | "lodash" 311 | ] 312 | }, 313 | "foreground-child@3.3.0": { 314 | "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", 315 | "dependencies": [ 316 | "cross-spawn", 317 | "signal-exit" 318 | ] 319 | }, 320 | "fsevents@2.3.3": { 321 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==" 322 | }, 323 | "glob@10.4.5": { 324 | "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", 325 | "dependencies": [ 326 | "foreground-child", 327 | "jackspeak", 328 | "minimatch", 329 | "minipass", 330 | "package-json-from-dist", 331 | "path-scurry" 332 | ] 333 | }, 334 | "is-fullwidth-code-point@3.0.0": { 335 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 336 | }, 337 | "isexe@2.0.0": { 338 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" 339 | }, 340 | "jackspeak@3.4.3": { 341 | "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", 342 | "dependencies": [ 343 | "@isaacs/cliui", 344 | "@pkgjs/parseargs" 345 | ] 346 | }, 347 | "lebab@3.2.4": { 348 | "integrity": "sha512-rtffzCSZ3LFG92Mqd05i2HcaMq73HfXtZWvP3AkvS3DdvfLAEr2pAcgpeQ7r/6DVoNBiFmMyK5Ho4t6AIkQU1w==", 349 | "dependencies": [ 350 | "commander", 351 | "escope", 352 | "espree", 353 | "estraverse@5.3.0", 354 | "f-matches", 355 | "glob", 356 | "lodash", 357 | "recast" 358 | ] 359 | }, 360 | "lodash@4.17.21": { 361 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 362 | }, 363 | "lru-cache@10.4.3": { 364 | "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" 365 | }, 366 | "minimatch@9.0.5": { 367 | "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 368 | "dependencies": [ 369 | "brace-expansion" 370 | ] 371 | }, 372 | "minipass@7.1.2": { 373 | "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" 374 | }, 375 | "nanoid@3.3.7": { 376 | "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" 377 | }, 378 | "package-json-from-dist@1.0.1": { 379 | "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" 380 | }, 381 | "path-key@3.1.1": { 382 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" 383 | }, 384 | "path-scurry@1.11.1": { 385 | "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", 386 | "dependencies": [ 387 | "lru-cache", 388 | "minipass" 389 | ] 390 | }, 391 | "picocolors@1.1.1": { 392 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" 393 | }, 394 | "postcss@8.4.47": { 395 | "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", 396 | "dependencies": [ 397 | "nanoid", 398 | "picocolors", 399 | "source-map-js" 400 | ] 401 | }, 402 | "recast@0.23.9": { 403 | "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", 404 | "dependencies": [ 405 | "ast-types", 406 | "esprima", 407 | "source-map", 408 | "tiny-invariant", 409 | "tslib" 410 | ] 411 | }, 412 | "resolve.exports@2.0.2": { 413 | "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==" 414 | }, 415 | "rollup@4.24.0": { 416 | "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", 417 | "dependencies": [ 418 | "@rollup/rollup-android-arm-eabi", 419 | "@rollup/rollup-android-arm64", 420 | "@rollup/rollup-darwin-arm64", 421 | "@rollup/rollup-darwin-x64", 422 | "@rollup/rollup-linux-arm-gnueabihf", 423 | "@rollup/rollup-linux-arm-musleabihf", 424 | "@rollup/rollup-linux-arm64-gnu", 425 | "@rollup/rollup-linux-arm64-musl", 426 | "@rollup/rollup-linux-powerpc64le-gnu", 427 | "@rollup/rollup-linux-riscv64-gnu", 428 | "@rollup/rollup-linux-s390x-gnu", 429 | "@rollup/rollup-linux-x64-gnu", 430 | "@rollup/rollup-linux-x64-musl", 431 | "@rollup/rollup-win32-arm64-msvc", 432 | "@rollup/rollup-win32-ia32-msvc", 433 | "@rollup/rollup-win32-x64-msvc", 434 | "@types/estree", 435 | "fsevents" 436 | ] 437 | }, 438 | "shebang-command@2.0.0": { 439 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 440 | "dependencies": [ 441 | "shebang-regex" 442 | ] 443 | }, 444 | "shebang-regex@3.0.0": { 445 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" 446 | }, 447 | "signal-exit@4.1.0": { 448 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" 449 | }, 450 | "source-map-js@1.2.1": { 451 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" 452 | }, 453 | "source-map@0.6.1": { 454 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 455 | }, 456 | "string-width@4.2.3": { 457 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 458 | "dependencies": [ 459 | "emoji-regex@8.0.0", 460 | "is-fullwidth-code-point", 461 | "strip-ansi@6.0.1" 462 | ] 463 | }, 464 | "string-width@5.1.2": { 465 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 466 | "dependencies": [ 467 | "eastasianwidth", 468 | "emoji-regex@9.2.2", 469 | "strip-ansi@7.1.0" 470 | ] 471 | }, 472 | "strip-ansi@6.0.1": { 473 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 474 | "dependencies": [ 475 | "ansi-regex@5.0.1" 476 | ] 477 | }, 478 | "strip-ansi@7.1.0": { 479 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 480 | "dependencies": [ 481 | "ansi-regex@6.1.0" 482 | ] 483 | }, 484 | "tiny-invariant@1.3.3": { 485 | "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" 486 | }, 487 | "tslib@2.8.0": { 488 | "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==" 489 | }, 490 | "validate-npm-package-name@5.0.1": { 491 | "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==" 492 | }, 493 | "vite@5.4.9": { 494 | "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", 495 | "dependencies": [ 496 | "esbuild", 497 | "fsevents", 498 | "postcss", 499 | "rollup" 500 | ] 501 | }, 502 | "which@2.0.2": { 503 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 504 | "dependencies": [ 505 | "isexe" 506 | ] 507 | }, 508 | "wrap-ansi@7.0.0": { 509 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 510 | "dependencies": [ 511 | "ansi-styles@4.3.0", 512 | "string-width@4.2.3", 513 | "strip-ansi@6.0.1" 514 | ] 515 | }, 516 | "wrap-ansi@8.1.0": { 517 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 518 | "dependencies": [ 519 | "ansi-styles@6.2.1", 520 | "string-width@5.1.2", 521 | "strip-ansi@7.1.0" 522 | ] 523 | }, 524 | "zod@3.23.8": { 525 | "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==" 526 | } 527 | } 528 | } 529 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 5 | Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 6 | 7 | [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public 8 | License, version 2, hence the version number 2.1.] 9 | 10 | Preamble 11 | 12 | The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU 13 | General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the 14 | software is free for all its users. 15 | 16 | This license, the Lesser General Public License, applies to some specially designated software packages--typically 17 | libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest 18 | you first think carefully about whether this license or the ordinary General Public License is the better strategy to 19 | use in any particular case, based on the explanations below. 20 | 21 | When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed 22 | to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); 23 | that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new 24 | free programs; and that you are informed that you can do these things. 25 | 26 | To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to 27 | surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the 28 | library or if you modify it. 29 | 30 | For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the 31 | rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code 32 | with the library, you must provide complete object files to the recipients, so that they can relink them with the 33 | library after making changes to the library and recompiling it. And you must show them these terms so they know their 34 | rights. 35 | 36 | We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which 37 | gives you legal permission to copy, distribute and/or modify the library. 38 | 39 | To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the 40 | library is modified by someone else and passed on, the recipients should know that what they have is not the original 41 | version, so that the original author's reputation will not be affected by problems that might be introduced by others. 42 | 43 | Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a 44 | company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. 45 | Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full 46 | freedom of use specified in this license. 47 | 48 | Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the 49 | GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary 50 | General Public License. We use this license for certain libraries in order to permit linking those libraries into 51 | non-free programs. 52 | 53 | When a program is linked with a library, whether statically or using a shared library, the combination of the two is 54 | legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore 55 | permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License 56 | permits more lax criteria for linking other code with the library. 57 | 58 | We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the 59 | ordinary General Public License. It also provides other free software developers Less of an advantage over competing 60 | non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. 61 | However, the Lesser license provides advantages in certain special circumstances. 62 | 63 | For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, 64 | so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more 65 | frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little 66 | to gain by limiting the free library to free software only, so we use the Lesser General Public License. 67 | 68 | In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a 69 | large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more 70 | people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. 71 | 72 | Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a 73 | program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version 74 | of the Library. 75 | 76 | The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the 77 | difference between a "work based on the library" and a "work that uses the library". The former contains code derived 78 | from the library, whereas the latter must be combined with the library in order to run. 79 | 80 | GNU LESSER GENERAL PUBLIC LICENSE 81 | 82 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 83 | 84 | 0. This License Agreement applies to any software library or other program which contains a notice placed by the 85 | copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public 86 | License (also called "this License"). Each licensee is addressed as "you". 87 | 88 | A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with 89 | application programs (which use some of those functions and data) to form executables. 90 | 91 | The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work 92 | based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work 93 | containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly 94 | into another language. (Hereinafter, translation is included without limitation in the term "modification".) 95 | 96 | "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete 97 | source code means all the source code for all modules it contains, plus any associated interface definition files, plus 98 | the scripts used to control compilation and installation of the library. 99 | 100 | Activities other than copying, distribution and modification are not covered by this License; they are outside its 101 | scope. The act of running a program using the Library is not restricted, and output from such a program is covered only 102 | if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). 103 | Whether that is true depends on what the Library does and what the program that uses the Library does. 104 | 105 | 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, 106 | provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer 107 | of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and 108 | distribute a copy of this License along with the Library. 109 | 110 | You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection 111 | in exchange for a fee. 112 | 113 | 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and 114 | copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of 115 | these conditions: 116 | 117 | a) The modified work must itself be a software library. 118 | 119 | b) You must cause the files modified to carry prominent notices 120 | stating that you changed the files and the date of any change. 121 | 122 | c) You must cause the whole of the work to be licensed at no 123 | charge to all third parties under the terms of this License. 124 | 125 | d) If a facility in the modified Library refers to a function or a 126 | table of data to be supplied by an application program that uses 127 | the facility, other than as an argument passed when the facility 128 | is invoked, then you must make a good faith effort to ensure that, 129 | in the event an application does not supply such function or 130 | table, the facility still operates, and performs whatever part of 131 | its purpose remains meaningful. 132 | 133 | (For example, a function in a library to compute square roots has 134 | a purpose that is entirely well-defined independent of the 135 | application. Therefore, Subsection 2d requires that any 136 | application-supplied function or table used by this function must 137 | be optional: if the application does not supply it, the square 138 | root function must still compute square roots.) 139 | 140 | These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the 141 | Library, and can be reasonably considered independent and separate works in themselves, then this License, and its 142 | terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same 143 | sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of 144 | this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part 145 | regardless of who wrote it. 146 | 147 | Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; 148 | rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the 149 | Library. 150 | 151 | In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the 152 | Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 153 | 154 | 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of 155 | the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the 156 | ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the 157 | ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make 158 | any other change in these notices. 159 | 160 | Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License 161 | applies to all subsequent copies and derivative works made from that copy. 162 | 163 | This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 164 | 165 | 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or 166 | executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete 167 | corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a 168 | medium customarily used for software interchange. 169 | 170 | If distribution of object code is made by offering access to copy from a designated place, then offering equivalent 171 | access to copy the source code from the same place satisfies the requirement to distribute the source code, even though 172 | third parties are not compelled to copy the source along with the object code. 173 | 174 | 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by 175 | being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a 176 | derivative work of the Library, and therefore falls outside the scope of this License. 177 | 178 | However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the 179 | Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is 180 | therefore covered by this License. Section 6 states terms for distribution of such executables. 181 | 182 | When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for 183 | the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially 184 | significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to 185 | be true is not precisely defined by law. 186 | 187 | If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small 188 | inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether 189 | it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall 190 | under Section 6.) 191 | 192 | Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms 193 | of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly 194 | with the Library itself. 195 | 196 | 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library 197 | to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided 198 | that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such 199 | modifications. 200 | 201 | You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its 202 | use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright 203 | notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to 204 | the copy of this License. Also, you must do one of these things: 205 | 206 | a) Accompany the work with the complete corresponding 207 | machine-readable source code for the Library including whatever 208 | changes were used in the work (which must be distributed under 209 | Sections 1 and 2 above); and, if the work is an executable linked 210 | with the Library, with the complete machine-readable "work that 211 | uses the Library", as object code and/or source code, so that the 212 | user can modify the Library and then relink to produce a modified 213 | executable containing the modified Library. (It is understood 214 | that the user who changes the contents of definitions files in the 215 | Library will not necessarily be able to recompile the application 216 | to use the modified definitions.) 217 | 218 | b) Use a suitable shared library mechanism for linking with the 219 | Library. A suitable mechanism is one that (1) uses at run time a 220 | copy of the library already present on the user's computer system, 221 | rather than copying library functions into the executable, and (2) 222 | will operate properly with a modified version of the library, if 223 | the user installs one, as long as the modified version is 224 | interface-compatible with the version that the work was made with. 225 | 226 | c) Accompany the work with a written offer, valid for at 227 | least three years, to give the same user the materials 228 | specified in Subsection 6a, above, for a charge no more 229 | than the cost of performing this distribution. 230 | 231 | d) If distribution of the work is made by offering access to copy 232 | from a designated place, offer equivalent access to copy the above 233 | specified materials from the same place. 234 | 235 | e) Verify that the user has already received a copy of these 236 | materials or that you have already sent this user a copy. 237 | 238 | For an executable, the required form of the "work that uses the Library" must include any data and utility programs 239 | needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not 240 | include anything that is normally distributed (in either source or binary form) with the major components (compiler, 241 | kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the 242 | executable. 243 | 244 | It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not 245 | normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in 246 | an executable that you distribute. 247 | 248 | 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with 249 | other library facilities not covered by this License, and distribute such a combined library, provided that the 250 | separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, 251 | and provided that you do these two things: 252 | 253 | a) Accompany the combined library with a copy of the same work 254 | based on the Library, uncombined with any other library 255 | facilities. This must be distributed under the terms of the 256 | Sections above. 257 | 258 | b) Give prominent notice with the combined library of the fact 259 | that part of it is a work based on the Library, and explaining 260 | where to find the accompanying uncombined form of the same work. 261 | 262 | 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this 263 | License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will 264 | automatically terminate your rights under this License. However, parties who have received copies, or rights, from 265 | you under this License will not have their licenses terminated so long as such parties remain in full compliance. 266 | 267 | 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you 268 | permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do 269 | not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you 270 | indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or 271 | modifying the Library or works based on it. 272 | 273 | 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a 274 | license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and 275 | conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 276 | You are not responsible for enforcing compliance by third parties with this License. 277 | 278 | 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited 279 | to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict 280 | the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute 281 | so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a 282 | consequence you may not distribute the Library at all. For example, if a patent license would not permit 283 | royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then 284 | the only way you could satisfy both it and this License would be to refrain entirely from distribution of the 285 | Library. 286 | 287 | If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the 288 | section is intended to apply, and the section as a whole is intended to apply in other circumstances. 289 | 290 | It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest 291 | validity of any such claims; this section has the sole purpose of protecting the integrity of the free software 292 | distribution system which is implemented by public license practices. Many people have made generous contributions to 293 | the wide range of software distributed through that system in reliance on consistent application of that system; it is 294 | up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee 295 | cannot impose that choice. 296 | 297 | This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 298 | 299 | 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted 300 | interfaces, the original copyright holder who places the Library under this License may add an explicit geographical 301 | distribution limitation excluding those countries, so that distribution is permitted only in or among countries not 302 | thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 303 | 304 | 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time 305 | to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new 306 | problems or concerns. 307 | 308 | Each version is given a distinguishing version number. If the Library specifies a version number of this License which 309 | applies to it and "any later version", you have the option of following the terms and conditions either of that version 310 | or of any later version published by the Free Software Foundation. If the Library does not specify a license version 311 | number, you may choose any version ever published by the Free Software Foundation. 312 | 313 | 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are 314 | incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free 315 | Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will 316 | be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting 317 | the sharing and reuse of software generally. 318 | 319 | NO WARRANTY 320 | 321 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY 322 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE 323 | LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 324 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND 325 | PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY 326 | SERVICING, REPAIR OR CORRECTION. 327 | 328 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY 329 | WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 330 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY 331 | (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 332 | PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN 333 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 334 | 335 | END OF TERMS AND CONDITIONS 336 | 337 | How to Apply These Terms to Your New Libraries 338 | 339 | If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it 340 | free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms 341 | (or, alternatively, under the terms of the ordinary General Public License). 342 | 343 | To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each 344 | source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" 345 | line and a pointer to where the full notice is found. 346 | 347 | 348 | Copyright (C) 349 | 350 | This library is free software; you can redistribute it and/or 351 | modify it under the terms of the GNU Lesser General Public 352 | License as published by the Free Software Foundation; either 353 | version 2.1 of the License, or (at your option) any later version. 354 | 355 | This library is distributed in the hope that it will be useful, 356 | but WITHOUT ANY WARRANTY; without even the implied warranty of 357 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 358 | Lesser General Public License for more details. 359 | 360 | You should have received a copy of the GNU Lesser General Public 361 | License along with this library; if not, write to the Free Software 362 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 363 | USA 364 | 365 | Also add information on how to contact you by electronic and paper mail. 366 | 367 | You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" 368 | for the library, if necessary. Here is a sample; alter the names: 369 | 370 | Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by 371 | James Random Hacker. 372 | 373 | , 1 April 1990 Ty Coon, President of Vice 374 | 375 | That's all there is to it! 376 | -------------------------------------------------------------------------------- /examples/preact/deno.lock: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4", 3 | "specifiers": { 4 | "jsr:@logtape/logtape@~0.8.2": "0.8.2", 5 | "jsr:@std/assert@0.223": "0.223.0", 6 | "jsr:@std/assert@0.226": "0.226.0", 7 | "jsr:@std/assert@~0.225.2": "0.225.3", 8 | "jsr:@std/encoding@0.223": "0.223.0", 9 | "jsr:@std/fmt@0.223": "0.223.0", 10 | "jsr:@std/fs@0.223": "0.223.0", 11 | "jsr:@std/path@0.223": "0.223.0", 12 | "jsr:@std/path@~0.225.1": "0.225.2", 13 | "jsr:@std/semver@^1.0.2": "1.0.3", 14 | "npm:@coderspirit/nominal@^4.1.1": "4.1.1", 15 | "npm:@preact/compat@*": "18.3.1_preact@10.24.3", 16 | "npm:@preact/compat@^18.3.1": "18.3.1_preact@10.24.3", 17 | "npm:@prefresh/core@*": "1.5.3_preact@10.24.3", 18 | "npm:@prefresh/core@^1.5.2": "1.5.3_preact@10.24.3", 19 | "npm:@prefresh/utils@*": "1.2.0", 20 | "npm:@prefresh/utils@^1.2.0": "1.2.0", 21 | "npm:@prefresh/vite@^2.4.6": "2.4.7_preact@10.24.3_vite@5.4.14__@types+node@22.5.4_@types+node@22.5.4", 22 | "npm:@types/node@*": "22.5.4", 23 | "npm:acorn-walk@^8.3.3": "8.3.4", 24 | "npm:acorn@^8.12.1": "8.13.0", 25 | "npm:lebab@^3.2.4": "3.2.4", 26 | "npm:preact@*": "10.24.3", 27 | "npm:preact@^10.24.3": "10.24.3", 28 | "npm:resolve.exports@^2.0.2": "2.0.2", 29 | "npm:validate-npm-package-name@^5.0.1": "5.0.1", 30 | "npm:vite@^5.2.12": "5.4.14_@types+node@22.5.4", 31 | "npm:vite@^6.1.1": "6.1.1_@types+node@22.5.4", 32 | "npm:zod@^3.22.5": "3.23.8" 33 | }, 34 | "jsr": { 35 | "@logtape/logtape@0.8.2": { 36 | "integrity": "e2ae1fc2561e8d010359b9894efb39bdb559dae44f5824540cbb26a78eee36bc" 37 | }, 38 | "@std/assert@0.223.0": { 39 | "integrity": "eb8d6d879d76e1cc431205bd346ed4d88dc051c6366365b1af47034b0670be24", 40 | "dependencies": [ 41 | "jsr:@std/fmt" 42 | ] 43 | }, 44 | "@std/assert@0.225.3": { 45 | "integrity": "b3c2847aecf6955b50644cdb9cf072004ea3d1998dd7579fc0acb99dbb23bd4f" 46 | }, 47 | "@std/assert@0.226.0": { 48 | "integrity": "0dfb5f7c7723c18cec118e080fec76ce15b4c31154b15ad2bd74822603ef75b3" 49 | }, 50 | "@std/encoding@0.223.0": { 51 | "integrity": "2b5615a75e00337ce113f34cf2f9b8c18182c751a8dcc8b1a2c2fc0e117bef00" 52 | }, 53 | "@std/fmt@0.223.0": { 54 | "integrity": "6deb37794127dfc7d7bded2586b9fc6f5d50e62a8134846608baf71ffc1a5208" 55 | }, 56 | "@std/fs@0.223.0": { 57 | "integrity": "3b4b0550b2c524cbaaa5a9170c90e96cbb7354e837ad1bdaf15fc9df1ae9c31c", 58 | "dependencies": [ 59 | "jsr:@std/assert@0.223", 60 | "jsr:@std/path@0.223" 61 | ] 62 | }, 63 | "@std/path@0.223.0": { 64 | "integrity": "593963402d7e6597f5a6e620931661053572c982fc014000459edc1f93cc3989", 65 | "dependencies": [ 66 | "jsr:@std/assert@0.223" 67 | ] 68 | }, 69 | "@std/path@0.225.2": { 70 | "integrity": "0f2db41d36b50ef048dcb0399aac720a5348638dd3cb5bf80685bf2a745aa506", 71 | "dependencies": [ 72 | "jsr:@std/assert@0.226" 73 | ] 74 | }, 75 | "@std/semver@1.0.3": { 76 | "integrity": "7c139c6076a080eeaa4252c78b95ca5302818d7eafab0470d34cafd9930c13c8" 77 | } 78 | }, 79 | "npm": { 80 | "@ampproject/remapping@2.3.0": { 81 | "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", 82 | "dependencies": [ 83 | "@jridgewell/gen-mapping", 84 | "@jridgewell/trace-mapping" 85 | ] 86 | }, 87 | "@babel/code-frame@7.26.2": { 88 | "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", 89 | "dependencies": [ 90 | "@babel/helper-validator-identifier", 91 | "js-tokens", 92 | "picocolors" 93 | ] 94 | }, 95 | "@babel/compat-data@7.26.8": { 96 | "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==" 97 | }, 98 | "@babel/core@7.26.9": { 99 | "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", 100 | "dependencies": [ 101 | "@ampproject/remapping", 102 | "@babel/code-frame", 103 | "@babel/generator", 104 | "@babel/helper-compilation-targets", 105 | "@babel/helper-module-transforms", 106 | "@babel/helpers", 107 | "@babel/parser", 108 | "@babel/template", 109 | "@babel/traverse", 110 | "@babel/types", 111 | "convert-source-map", 112 | "debug", 113 | "gensync", 114 | "json5", 115 | "semver" 116 | ] 117 | }, 118 | "@babel/generator@7.26.9": { 119 | "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", 120 | "dependencies": [ 121 | "@babel/parser", 122 | "@babel/types", 123 | "@jridgewell/gen-mapping", 124 | "@jridgewell/trace-mapping", 125 | "jsesc" 126 | ] 127 | }, 128 | "@babel/helper-compilation-targets@7.26.5": { 129 | "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", 130 | "dependencies": [ 131 | "@babel/compat-data", 132 | "@babel/helper-validator-option", 133 | "browserslist", 134 | "lru-cache@5.1.1", 135 | "semver" 136 | ] 137 | }, 138 | "@babel/helper-module-imports@7.25.9": { 139 | "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", 140 | "dependencies": [ 141 | "@babel/traverse", 142 | "@babel/types" 143 | ] 144 | }, 145 | "@babel/helper-module-transforms@7.26.0_@babel+core@7.26.9": { 146 | "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", 147 | "dependencies": [ 148 | "@babel/core", 149 | "@babel/helper-module-imports", 150 | "@babel/helper-validator-identifier", 151 | "@babel/traverse" 152 | ] 153 | }, 154 | "@babel/helper-string-parser@7.25.9": { 155 | "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==" 156 | }, 157 | "@babel/helper-validator-identifier@7.25.9": { 158 | "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==" 159 | }, 160 | "@babel/helper-validator-option@7.25.9": { 161 | "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==" 162 | }, 163 | "@babel/helpers@7.26.9": { 164 | "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", 165 | "dependencies": [ 166 | "@babel/template", 167 | "@babel/types" 168 | ] 169 | }, 170 | "@babel/parser@7.26.9": { 171 | "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", 172 | "dependencies": [ 173 | "@babel/types" 174 | ] 175 | }, 176 | "@babel/template@7.26.9": { 177 | "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", 178 | "dependencies": [ 179 | "@babel/code-frame", 180 | "@babel/parser", 181 | "@babel/types" 182 | ] 183 | }, 184 | "@babel/traverse@7.26.9": { 185 | "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", 186 | "dependencies": [ 187 | "@babel/code-frame", 188 | "@babel/generator", 189 | "@babel/parser", 190 | "@babel/template", 191 | "@babel/types", 192 | "debug", 193 | "globals" 194 | ] 195 | }, 196 | "@babel/types@7.26.9": { 197 | "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", 198 | "dependencies": [ 199 | "@babel/helper-string-parser", 200 | "@babel/helper-validator-identifier" 201 | ] 202 | }, 203 | "@coderspirit/nominal-symbols@2.0.1_typescript@5.6.3": { 204 | "integrity": "sha512-OV2eZ9wJkukMCW5KXCGrhPcp8pSeB517/0BaRL3r979U18Q7oYmNxnGogyIWQOUUglMrhB/jnUpP77QbZuZsNA==", 205 | "dependencies": [ 206 | "typescript" 207 | ] 208 | }, 209 | "@coderspirit/nominal@4.1.1": { 210 | "integrity": "sha512-m37GfF/N1QzJBE1HHGpSJhAyDtkExzwx3AnGk0n2SRyFSVxtwpTRWLl6lkubUfXiZeOTFqXjVjOxseMh3YffLg==", 211 | "dependencies": [ 212 | "@coderspirit/nominal-symbols" 213 | ] 214 | }, 215 | "@esbuild/aix-ppc64@0.21.5": { 216 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==" 217 | }, 218 | "@esbuild/aix-ppc64@0.24.2": { 219 | "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==" 220 | }, 221 | "@esbuild/android-arm64@0.21.5": { 222 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==" 223 | }, 224 | "@esbuild/android-arm64@0.24.2": { 225 | "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==" 226 | }, 227 | "@esbuild/android-arm@0.21.5": { 228 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==" 229 | }, 230 | "@esbuild/android-arm@0.24.2": { 231 | "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==" 232 | }, 233 | "@esbuild/android-x64@0.21.5": { 234 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==" 235 | }, 236 | "@esbuild/android-x64@0.24.2": { 237 | "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==" 238 | }, 239 | "@esbuild/darwin-arm64@0.21.5": { 240 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==" 241 | }, 242 | "@esbuild/darwin-arm64@0.24.2": { 243 | "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==" 244 | }, 245 | "@esbuild/darwin-x64@0.21.5": { 246 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==" 247 | }, 248 | "@esbuild/darwin-x64@0.24.2": { 249 | "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==" 250 | }, 251 | "@esbuild/freebsd-arm64@0.21.5": { 252 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==" 253 | }, 254 | "@esbuild/freebsd-arm64@0.24.2": { 255 | "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==" 256 | }, 257 | "@esbuild/freebsd-x64@0.21.5": { 258 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==" 259 | }, 260 | "@esbuild/freebsd-x64@0.24.2": { 261 | "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==" 262 | }, 263 | "@esbuild/linux-arm64@0.21.5": { 264 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==" 265 | }, 266 | "@esbuild/linux-arm64@0.24.2": { 267 | "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==" 268 | }, 269 | "@esbuild/linux-arm@0.21.5": { 270 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==" 271 | }, 272 | "@esbuild/linux-arm@0.24.2": { 273 | "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==" 274 | }, 275 | "@esbuild/linux-ia32@0.21.5": { 276 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==" 277 | }, 278 | "@esbuild/linux-ia32@0.24.2": { 279 | "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==" 280 | }, 281 | "@esbuild/linux-loong64@0.21.5": { 282 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==" 283 | }, 284 | "@esbuild/linux-loong64@0.24.2": { 285 | "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==" 286 | }, 287 | "@esbuild/linux-mips64el@0.21.5": { 288 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==" 289 | }, 290 | "@esbuild/linux-mips64el@0.24.2": { 291 | "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==" 292 | }, 293 | "@esbuild/linux-ppc64@0.21.5": { 294 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==" 295 | }, 296 | "@esbuild/linux-ppc64@0.24.2": { 297 | "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==" 298 | }, 299 | "@esbuild/linux-riscv64@0.21.5": { 300 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==" 301 | }, 302 | "@esbuild/linux-riscv64@0.24.2": { 303 | "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==" 304 | }, 305 | "@esbuild/linux-s390x@0.21.5": { 306 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==" 307 | }, 308 | "@esbuild/linux-s390x@0.24.2": { 309 | "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==" 310 | }, 311 | "@esbuild/linux-x64@0.21.5": { 312 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==" 313 | }, 314 | "@esbuild/linux-x64@0.24.2": { 315 | "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==" 316 | }, 317 | "@esbuild/netbsd-arm64@0.24.2": { 318 | "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==" 319 | }, 320 | "@esbuild/netbsd-x64@0.21.5": { 321 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==" 322 | }, 323 | "@esbuild/netbsd-x64@0.24.2": { 324 | "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==" 325 | }, 326 | "@esbuild/openbsd-arm64@0.24.2": { 327 | "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==" 328 | }, 329 | "@esbuild/openbsd-x64@0.21.5": { 330 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==" 331 | }, 332 | "@esbuild/openbsd-x64@0.24.2": { 333 | "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==" 334 | }, 335 | "@esbuild/sunos-x64@0.21.5": { 336 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==" 337 | }, 338 | "@esbuild/sunos-x64@0.24.2": { 339 | "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==" 340 | }, 341 | "@esbuild/win32-arm64@0.21.5": { 342 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==" 343 | }, 344 | "@esbuild/win32-arm64@0.24.2": { 345 | "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==" 346 | }, 347 | "@esbuild/win32-ia32@0.21.5": { 348 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==" 349 | }, 350 | "@esbuild/win32-ia32@0.24.2": { 351 | "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==" 352 | }, 353 | "@esbuild/win32-x64@0.21.5": { 354 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==" 355 | }, 356 | "@esbuild/win32-x64@0.24.2": { 357 | "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==" 358 | }, 359 | "@isaacs/cliui@8.0.2": { 360 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 361 | "dependencies": [ 362 | "string-width@5.1.2", 363 | "string-width-cjs@npm:string-width@4.2.3", 364 | "strip-ansi@7.1.0", 365 | "strip-ansi-cjs@npm:strip-ansi@6.0.1", 366 | "wrap-ansi@8.1.0", 367 | "wrap-ansi-cjs@npm:wrap-ansi@7.0.0" 368 | ] 369 | }, 370 | "@jridgewell/gen-mapping@0.3.8": { 371 | "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", 372 | "dependencies": [ 373 | "@jridgewell/set-array", 374 | "@jridgewell/sourcemap-codec", 375 | "@jridgewell/trace-mapping" 376 | ] 377 | }, 378 | "@jridgewell/resolve-uri@3.1.2": { 379 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" 380 | }, 381 | "@jridgewell/set-array@1.2.1": { 382 | "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" 383 | }, 384 | "@jridgewell/sourcemap-codec@1.5.0": { 385 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" 386 | }, 387 | "@jridgewell/trace-mapping@0.3.25": { 388 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 389 | "dependencies": [ 390 | "@jridgewell/resolve-uri", 391 | "@jridgewell/sourcemap-codec" 392 | ] 393 | }, 394 | "@pkgjs/parseargs@0.11.0": { 395 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==" 396 | }, 397 | "@preact/compat@18.3.1_preact@10.24.3": { 398 | "integrity": "sha512-Kog4PSRxtT4COtOXjsuQPV1vMXpUzREQfv+6Dmcy9/rMk0HOPK0HTE9fspFjAmY8R80T/T8gtgmZ68u5bOSngw==", 399 | "dependencies": [ 400 | "preact" 401 | ] 402 | }, 403 | "@prefresh/babel-plugin@0.5.1": { 404 | "integrity": "sha512-uG3jGEAysxWoyG3XkYfjYHgaySFrSsaEb4GagLzYaxlydbuREtaX+FTxuIidp241RaLl85XoHg9Ej6E4+V1pcg==" 405 | }, 406 | "@prefresh/core@1.5.3_preact@10.24.3": { 407 | "integrity": "sha512-nDzxj0tA1/M6APNAWqaxkZ+3sTdPHESa+gol4+Bw7rMc2btWdkLoNH7j9rGhUb8SThC0Vz0VoXtq+U+9azGLHg==", 408 | "dependencies": [ 409 | "preact" 410 | ] 411 | }, 412 | "@prefresh/utils@1.2.0": { 413 | "integrity": "sha512-KtC/fZw+oqtwOLUFM9UtiitB0JsVX0zLKNyRTA332sqREqSALIIQQxdUCS1P3xR/jT1e2e8/5rwH6gdcMLEmsQ==" 414 | }, 415 | "@prefresh/vite@2.4.7_preact@10.24.3_vite@5.4.14__@types+node@22.5.4_@types+node@22.5.4": { 416 | "integrity": "sha512-zmCEDWSFHl5A7PciXa/fe+OUjoGi4iiCQclpWfpIg7LjxwWrtlUT4DfxDBcQwHfTyipS/XDm8x7WYrkiTW0q+w==", 417 | "dependencies": [ 418 | "@babel/core", 419 | "@prefresh/babel-plugin", 420 | "@prefresh/core", 421 | "@prefresh/utils", 422 | "@rollup/pluginutils", 423 | "preact", 424 | "vite@5.4.14_@types+node@22.5.4" 425 | ] 426 | }, 427 | "@rollup/pluginutils@4.2.1": { 428 | "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", 429 | "dependencies": [ 430 | "estree-walker", 431 | "picomatch" 432 | ] 433 | }, 434 | "@rollup/rollup-android-arm-eabi@4.34.8": { 435 | "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==" 436 | }, 437 | "@rollup/rollup-android-arm64@4.34.8": { 438 | "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==" 439 | }, 440 | "@rollup/rollup-darwin-arm64@4.34.8": { 441 | "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==" 442 | }, 443 | "@rollup/rollup-darwin-x64@4.34.8": { 444 | "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==" 445 | }, 446 | "@rollup/rollup-freebsd-arm64@4.34.8": { 447 | "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==" 448 | }, 449 | "@rollup/rollup-freebsd-x64@4.34.8": { 450 | "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==" 451 | }, 452 | "@rollup/rollup-linux-arm-gnueabihf@4.34.8": { 453 | "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==" 454 | }, 455 | "@rollup/rollup-linux-arm-musleabihf@4.34.8": { 456 | "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==" 457 | }, 458 | "@rollup/rollup-linux-arm64-gnu@4.34.8": { 459 | "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==" 460 | }, 461 | "@rollup/rollup-linux-arm64-musl@4.34.8": { 462 | "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==" 463 | }, 464 | "@rollup/rollup-linux-loongarch64-gnu@4.34.8": { 465 | "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==" 466 | }, 467 | "@rollup/rollup-linux-powerpc64le-gnu@4.34.8": { 468 | "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==" 469 | }, 470 | "@rollup/rollup-linux-riscv64-gnu@4.34.8": { 471 | "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==" 472 | }, 473 | "@rollup/rollup-linux-s390x-gnu@4.34.8": { 474 | "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==" 475 | }, 476 | "@rollup/rollup-linux-x64-gnu@4.34.8": { 477 | "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==" 478 | }, 479 | "@rollup/rollup-linux-x64-musl@4.34.8": { 480 | "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==" 481 | }, 482 | "@rollup/rollup-win32-arm64-msvc@4.34.8": { 483 | "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==" 484 | }, 485 | "@rollup/rollup-win32-ia32-msvc@4.34.8": { 486 | "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==" 487 | }, 488 | "@rollup/rollup-win32-x64-msvc@4.34.8": { 489 | "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==" 490 | }, 491 | "@types/estree@1.0.6": { 492 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" 493 | }, 494 | "@types/node@22.5.4": { 495 | "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", 496 | "dependencies": [ 497 | "undici-types" 498 | ] 499 | }, 500 | "acorn-jsx@5.3.2_acorn@8.13.0": { 501 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 502 | "dependencies": [ 503 | "acorn" 504 | ] 505 | }, 506 | "acorn-walk@8.3.4": { 507 | "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", 508 | "dependencies": [ 509 | "acorn" 510 | ] 511 | }, 512 | "acorn@8.13.0": { 513 | "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==" 514 | }, 515 | "ansi-regex@5.0.1": { 516 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 517 | }, 518 | "ansi-regex@6.1.0": { 519 | "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==" 520 | }, 521 | "ansi-styles@4.3.0": { 522 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 523 | "dependencies": [ 524 | "color-convert" 525 | ] 526 | }, 527 | "ansi-styles@6.2.1": { 528 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" 529 | }, 530 | "ast-types@0.16.1": { 531 | "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", 532 | "dependencies": [ 533 | "tslib" 534 | ] 535 | }, 536 | "balanced-match@1.0.2": { 537 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 538 | }, 539 | "brace-expansion@2.0.1": { 540 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 541 | "dependencies": [ 542 | "balanced-match" 543 | ] 544 | }, 545 | "browserslist@4.24.4": { 546 | "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", 547 | "dependencies": [ 548 | "caniuse-lite", 549 | "electron-to-chromium", 550 | "node-releases", 551 | "update-browserslist-db" 552 | ] 553 | }, 554 | "caniuse-lite@1.0.30001700": { 555 | "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==" 556 | }, 557 | "color-convert@2.0.1": { 558 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 559 | "dependencies": [ 560 | "color-name" 561 | ] 562 | }, 563 | "color-name@1.1.4": { 564 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 565 | }, 566 | "commander@11.1.0": { 567 | "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==" 568 | }, 569 | "convert-source-map@2.0.0": { 570 | "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" 571 | }, 572 | "cross-spawn@7.0.3": { 573 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 574 | "dependencies": [ 575 | "path-key", 576 | "shebang-command", 577 | "which" 578 | ] 579 | }, 580 | "debug@4.4.0": { 581 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 582 | "dependencies": [ 583 | "ms" 584 | ] 585 | }, 586 | "eastasianwidth@0.2.0": { 587 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" 588 | }, 589 | "electron-to-chromium@1.5.102": { 590 | "integrity": "sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==" 591 | }, 592 | "emoji-regex@8.0.0": { 593 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 594 | }, 595 | "emoji-regex@9.2.2": { 596 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" 597 | }, 598 | "esbuild@0.21.5": { 599 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 600 | "dependencies": [ 601 | "@esbuild/aix-ppc64@0.21.5", 602 | "@esbuild/android-arm@0.21.5", 603 | "@esbuild/android-arm64@0.21.5", 604 | "@esbuild/android-x64@0.21.5", 605 | "@esbuild/darwin-arm64@0.21.5", 606 | "@esbuild/darwin-x64@0.21.5", 607 | "@esbuild/freebsd-arm64@0.21.5", 608 | "@esbuild/freebsd-x64@0.21.5", 609 | "@esbuild/linux-arm@0.21.5", 610 | "@esbuild/linux-arm64@0.21.5", 611 | "@esbuild/linux-ia32@0.21.5", 612 | "@esbuild/linux-loong64@0.21.5", 613 | "@esbuild/linux-mips64el@0.21.5", 614 | "@esbuild/linux-ppc64@0.21.5", 615 | "@esbuild/linux-riscv64@0.21.5", 616 | "@esbuild/linux-s390x@0.21.5", 617 | "@esbuild/linux-x64@0.21.5", 618 | "@esbuild/netbsd-x64@0.21.5", 619 | "@esbuild/openbsd-x64@0.21.5", 620 | "@esbuild/sunos-x64@0.21.5", 621 | "@esbuild/win32-arm64@0.21.5", 622 | "@esbuild/win32-ia32@0.21.5", 623 | "@esbuild/win32-x64@0.21.5" 624 | ] 625 | }, 626 | "esbuild@0.24.2": { 627 | "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", 628 | "dependencies": [ 629 | "@esbuild/aix-ppc64@0.24.2", 630 | "@esbuild/android-arm@0.24.2", 631 | "@esbuild/android-arm64@0.24.2", 632 | "@esbuild/android-x64@0.24.2", 633 | "@esbuild/darwin-arm64@0.24.2", 634 | "@esbuild/darwin-x64@0.24.2", 635 | "@esbuild/freebsd-arm64@0.24.2", 636 | "@esbuild/freebsd-x64@0.24.2", 637 | "@esbuild/linux-arm@0.24.2", 638 | "@esbuild/linux-arm64@0.24.2", 639 | "@esbuild/linux-ia32@0.24.2", 640 | "@esbuild/linux-loong64@0.24.2", 641 | "@esbuild/linux-mips64el@0.24.2", 642 | "@esbuild/linux-ppc64@0.24.2", 643 | "@esbuild/linux-riscv64@0.24.2", 644 | "@esbuild/linux-s390x@0.24.2", 645 | "@esbuild/linux-x64@0.24.2", 646 | "@esbuild/netbsd-arm64", 647 | "@esbuild/netbsd-x64@0.24.2", 648 | "@esbuild/openbsd-arm64", 649 | "@esbuild/openbsd-x64@0.24.2", 650 | "@esbuild/sunos-x64@0.24.2", 651 | "@esbuild/win32-arm64@0.24.2", 652 | "@esbuild/win32-ia32@0.24.2", 653 | "@esbuild/win32-x64@0.24.2" 654 | ] 655 | }, 656 | "escalade@3.2.0": { 657 | "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" 658 | }, 659 | "escope@4.0.0": { 660 | "integrity": "sha512-E36qlD/r6RJHVpPKArgMoMlNJzoRJFH8z/cAZlI9lbc45zB3+S7i9k6e/MNb+7bZQzNEa6r8WKN3BovpeIBwgA==", 661 | "dependencies": [ 662 | "esrecurse", 663 | "estraverse@4.3.0" 664 | ] 665 | }, 666 | "eslint-visitor-keys@3.4.3": { 667 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==" 668 | }, 669 | "espree@9.6.1_acorn@8.13.0": { 670 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", 671 | "dependencies": [ 672 | "acorn", 673 | "acorn-jsx", 674 | "eslint-visitor-keys" 675 | ] 676 | }, 677 | "esprima@4.0.1": { 678 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 679 | }, 680 | "esrecurse@4.3.0": { 681 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 682 | "dependencies": [ 683 | "estraverse@5.3.0" 684 | ] 685 | }, 686 | "estraverse@4.3.0": { 687 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" 688 | }, 689 | "estraverse@5.3.0": { 690 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" 691 | }, 692 | "estree-walker@2.0.2": { 693 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" 694 | }, 695 | "f-matches@1.1.0": { 696 | "integrity": "sha512-8NALQS5oB1+9hkEwiRjsRroTAQ7zKmXjxe0ZcMHDRrFIR54PhSJp7Rm+Q5+tgJ7eO5ejCgbUPNXeiflX18Rt0Q==", 697 | "dependencies": [ 698 | "lodash" 699 | ] 700 | }, 701 | "foreground-child@3.3.0": { 702 | "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", 703 | "dependencies": [ 704 | "cross-spawn", 705 | "signal-exit" 706 | ] 707 | }, 708 | "fsevents@2.3.3": { 709 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==" 710 | }, 711 | "gensync@1.0.0-beta.2": { 712 | "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" 713 | }, 714 | "glob@10.4.5": { 715 | "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", 716 | "dependencies": [ 717 | "foreground-child", 718 | "jackspeak", 719 | "minimatch", 720 | "minipass", 721 | "package-json-from-dist", 722 | "path-scurry" 723 | ] 724 | }, 725 | "globals@11.12.0": { 726 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" 727 | }, 728 | "is-fullwidth-code-point@3.0.0": { 729 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 730 | }, 731 | "isexe@2.0.0": { 732 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" 733 | }, 734 | "jackspeak@3.4.3": { 735 | "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", 736 | "dependencies": [ 737 | "@isaacs/cliui", 738 | "@pkgjs/parseargs" 739 | ] 740 | }, 741 | "js-tokens@4.0.0": { 742 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 743 | }, 744 | "jsesc@3.1.0": { 745 | "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==" 746 | }, 747 | "json5@2.2.3": { 748 | "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" 749 | }, 750 | "lebab@3.2.4": { 751 | "integrity": "sha512-rtffzCSZ3LFG92Mqd05i2HcaMq73HfXtZWvP3AkvS3DdvfLAEr2pAcgpeQ7r/6DVoNBiFmMyK5Ho4t6AIkQU1w==", 752 | "dependencies": [ 753 | "commander", 754 | "escope", 755 | "espree", 756 | "estraverse@5.3.0", 757 | "f-matches", 758 | "glob", 759 | "lodash", 760 | "recast" 761 | ] 762 | }, 763 | "lodash@4.17.21": { 764 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 765 | }, 766 | "lru-cache@10.4.3": { 767 | "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" 768 | }, 769 | "lru-cache@5.1.1": { 770 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 771 | "dependencies": [ 772 | "yallist" 773 | ] 774 | }, 775 | "minimatch@9.0.5": { 776 | "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 777 | "dependencies": [ 778 | "brace-expansion" 779 | ] 780 | }, 781 | "minipass@7.1.2": { 782 | "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" 783 | }, 784 | "ms@2.1.3": { 785 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 786 | }, 787 | "nanoid@3.3.8": { 788 | "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==" 789 | }, 790 | "node-releases@2.0.19": { 791 | "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" 792 | }, 793 | "package-json-from-dist@1.0.1": { 794 | "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" 795 | }, 796 | "path-key@3.1.1": { 797 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" 798 | }, 799 | "path-scurry@1.11.1": { 800 | "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", 801 | "dependencies": [ 802 | "lru-cache@10.4.3", 803 | "minipass" 804 | ] 805 | }, 806 | "picocolors@1.1.1": { 807 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" 808 | }, 809 | "picomatch@2.3.1": { 810 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" 811 | }, 812 | "postcss@8.5.3": { 813 | "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", 814 | "dependencies": [ 815 | "nanoid", 816 | "picocolors", 817 | "source-map-js" 818 | ] 819 | }, 820 | "preact@10.24.3": { 821 | "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==" 822 | }, 823 | "recast@0.23.9": { 824 | "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", 825 | "dependencies": [ 826 | "ast-types", 827 | "esprima", 828 | "source-map", 829 | "tiny-invariant", 830 | "tslib" 831 | ] 832 | }, 833 | "resolve.exports@2.0.2": { 834 | "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==" 835 | }, 836 | "rollup@4.34.8": { 837 | "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", 838 | "dependencies": [ 839 | "@rollup/rollup-android-arm-eabi", 840 | "@rollup/rollup-android-arm64", 841 | "@rollup/rollup-darwin-arm64", 842 | "@rollup/rollup-darwin-x64", 843 | "@rollup/rollup-freebsd-arm64", 844 | "@rollup/rollup-freebsd-x64", 845 | "@rollup/rollup-linux-arm-gnueabihf", 846 | "@rollup/rollup-linux-arm-musleabihf", 847 | "@rollup/rollup-linux-arm64-gnu", 848 | "@rollup/rollup-linux-arm64-musl", 849 | "@rollup/rollup-linux-loongarch64-gnu", 850 | "@rollup/rollup-linux-powerpc64le-gnu", 851 | "@rollup/rollup-linux-riscv64-gnu", 852 | "@rollup/rollup-linux-s390x-gnu", 853 | "@rollup/rollup-linux-x64-gnu", 854 | "@rollup/rollup-linux-x64-musl", 855 | "@rollup/rollup-win32-arm64-msvc", 856 | "@rollup/rollup-win32-ia32-msvc", 857 | "@rollup/rollup-win32-x64-msvc", 858 | "@types/estree", 859 | "fsevents" 860 | ] 861 | }, 862 | "semver@6.3.1": { 863 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" 864 | }, 865 | "shebang-command@2.0.0": { 866 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 867 | "dependencies": [ 868 | "shebang-regex" 869 | ] 870 | }, 871 | "shebang-regex@3.0.0": { 872 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" 873 | }, 874 | "signal-exit@4.1.0": { 875 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" 876 | }, 877 | "source-map-js@1.2.1": { 878 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" 879 | }, 880 | "source-map@0.6.1": { 881 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 882 | }, 883 | "string-width@4.2.3": { 884 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 885 | "dependencies": [ 886 | "emoji-regex@8.0.0", 887 | "is-fullwidth-code-point", 888 | "strip-ansi@6.0.1" 889 | ] 890 | }, 891 | "string-width@5.1.2": { 892 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 893 | "dependencies": [ 894 | "eastasianwidth", 895 | "emoji-regex@9.2.2", 896 | "strip-ansi@7.1.0" 897 | ] 898 | }, 899 | "strip-ansi@6.0.1": { 900 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 901 | "dependencies": [ 902 | "ansi-regex@5.0.1" 903 | ] 904 | }, 905 | "strip-ansi@7.1.0": { 906 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 907 | "dependencies": [ 908 | "ansi-regex@6.1.0" 909 | ] 910 | }, 911 | "tiny-invariant@1.3.3": { 912 | "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" 913 | }, 914 | "tslib@2.8.0": { 915 | "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==" 916 | }, 917 | "typescript@5.6.3": { 918 | "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==" 919 | }, 920 | "undici-types@6.19.8": { 921 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" 922 | }, 923 | "update-browserslist-db@1.1.2_browserslist@4.24.4": { 924 | "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", 925 | "dependencies": [ 926 | "browserslist", 927 | "escalade", 928 | "picocolors" 929 | ] 930 | }, 931 | "validate-npm-package-name@5.0.1": { 932 | "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==" 933 | }, 934 | "vite@5.4.14_@types+node@22.5.4": { 935 | "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==", 936 | "dependencies": [ 937 | "@types/node", 938 | "esbuild@0.21.5", 939 | "fsevents", 940 | "postcss", 941 | "rollup" 942 | ] 943 | }, 944 | "vite@6.1.1_@types+node@22.5.4": { 945 | "integrity": "sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA==", 946 | "dependencies": [ 947 | "@types/node", 948 | "esbuild@0.24.2", 949 | "fsevents", 950 | "postcss", 951 | "rollup" 952 | ] 953 | }, 954 | "which@2.0.2": { 955 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 956 | "dependencies": [ 957 | "isexe" 958 | ] 959 | }, 960 | "wrap-ansi@7.0.0": { 961 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 962 | "dependencies": [ 963 | "ansi-styles@4.3.0", 964 | "string-width@4.2.3", 965 | "strip-ansi@6.0.1" 966 | ] 967 | }, 968 | "wrap-ansi@8.1.0": { 969 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 970 | "dependencies": [ 971 | "ansi-styles@6.2.1", 972 | "string-width@5.1.2", 973 | "strip-ansi@7.1.0" 974 | ] 975 | }, 976 | "yallist@3.1.1": { 977 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 978 | }, 979 | "zod@3.23.8": { 980 | "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==" 981 | } 982 | }, 983 | "workspace": { 984 | "dependencies": [ 985 | "jsr:@logtape/logtape@~0.8.2", 986 | "jsr:@std/assert@0.223", 987 | "jsr:@std/encoding@0.223", 988 | "jsr:@std/fs@0.223", 989 | "jsr:@std/path@~0.225.1", 990 | "jsr:@std/semver@^1.0.2", 991 | "npm:@coderspirit/nominal@^4.1.1", 992 | "npm:@preact/compat@^18.3.1", 993 | "npm:@prefresh/core@^1.5.2", 994 | "npm:@prefresh/utils@^1.2.0", 995 | "npm:@prefresh/vite@^2.4.6", 996 | "npm:acorn-walk@^8.3.3", 997 | "npm:acorn@^8.12.1", 998 | "npm:lebab@^3.2.4", 999 | "npm:preact@^10.24.3", 1000 | "npm:resolve.exports@^2.0.2", 1001 | "npm:validate-npm-package-name@^5.0.1", 1002 | "npm:vite@^6.1.1", 1003 | "npm:zod@^3.22.5" 1004 | ] 1005 | } 1006 | } 1007 | --------------------------------------------------------------------------------