├── bench
├── bench-browser
│ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── main.tsx
│ │ ├── styles
│ │ │ └── main.scss
│ │ └── App.tsx
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.json
│ └── public
│ │ └── vite.svg
└── bench-node
│ ├── tsconfig.json
│ ├── package.json
│ └── src
│ └── index.ts
├── screen.jpg
├── .gitignore
├── examples
├── browser
│ ├── tsconfig.json
│ ├── index.html
│ ├── package.json
│ ├── vite.config.ts
│ ├── src
│ │ └── index.ts
│ └── package-lock.json
└── node
│ ├── package.json
│ ├── package-lock.json
│ └── index.js
├── .npmignore
├── src
├── index.ts
├── helpers.ts
└── debug.ts
├── tsup.config.ts
├── tsconfig.json
├── .github
└── workflows
│ ├── ci.yml
│ └── deploy.yml
├── LICENSE
├── package.json
├── README.md
└── test
└── debug.test.ts
/bench/bench-browser/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/screen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/localnerve/debug/public-package/screen.jpg
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | .idea
4 | tsconfig.tsbuildinfo
5 | .cache
6 | .parcel-cache
7 | dist
8 | tmp
--------------------------------------------------------------------------------
/examples/browser/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "esnext",
4 | "target": "esnext",
5 | "moduleResolution": "node",
6 | "types": ["node"],
7 | },
8 | }
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .cache
3 | .parcel-cache
4 | node_modules
5 | src
6 | test
7 | tmp
8 | stories
9 | examples
10 | bench
11 | .babelrc
12 | .github
13 | .prettierrc
14 | screen.jpg
15 | tsconfig.json
16 | tsup.config.ts
17 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Export as es6 module
3 | *
4 | * Usage ex:
5 | *
6 | * import debug from "@wbe/debug"
7 | * const log = debug("namespace")
8 | * // ...
9 | * log("...")
10 | *
11 | */
12 | export { debug as default } from "./debug"
13 |
--------------------------------------------------------------------------------
/bench/bench-browser/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { render } from "preact"
2 | import { BenchmarkApp } from "./App"
3 | import "./styles/main.scss"
4 |
5 | localStorage.setItem("debug", "*")
6 | ;(() => {
7 | render(, document.getElementById("app")!)
8 | })()
9 |
--------------------------------------------------------------------------------
/examples/browser/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | debug
6 |
7 |
8 | Check your console
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/bench/bench-node/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "module": "ESNext",
5 | "moduleResolution": "bundler",
6 | "esModuleInterop": true,
7 | "strict": true,
8 | "outDir": "dist",
9 | "skipLibCheck": true
10 | },
11 | "include": ["src"]
12 | }
--------------------------------------------------------------------------------
/examples/browser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "browser",
3 | "scripts": {
4 | "dev": "vite --host",
5 | "build": "vite build"
6 | },
7 | "dependencies": {
8 | "debug": "latest",
9 | "@localnerve/debug": "latest"
10 | },
11 | "devDependencies": {
12 | "vite": "^7.2.6"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/browser/vite.config.ts:
--------------------------------------------------------------------------------
1 | // default vite config
2 |
3 | import { defineConfig } from "vite"
4 | const isProd = process.env.NODE_ENV === "production"
5 | console.log("isProd", isProd)
6 | export default defineConfig({
7 | esbuild: {
8 | pure: isProd ? ["console.log"] : [],
9 | //drop: ["console"],
10 | },
11 | })
12 |
--------------------------------------------------------------------------------
/examples/node/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node",
3 | "main": "index.js",
4 | "type": "module",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1",
7 | "start": "DEBUG=namespace:*,otherspace node index.js"
8 | },
9 | "dependencies": {
10 | "@localnerve/debug": "latest"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/bench/bench-browser/.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 |
--------------------------------------------------------------------------------
/bench/bench-node/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bench-node",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "start": "tsx src/index.ts",
8 | "build": "tsc"
9 | },
10 | "dependencies": {
11 | "@localnerve/debug": "workspace:*",
12 | "debug": "4.4.0",
13 | "chalk": "^5.4.1"
14 | },
15 | "devDependencies": {
16 | "typescript": "~5.8.3",
17 | "tsx": "^4.19.4"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/bench/bench-browser/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @wbe/debug vs debug - Benchmark
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/bench/bench-browser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "browser-bench",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "@localnerve/debug": "latest",
13 | "debug": "4.4.0",
14 | "preact": "^10.26.5"
15 | },
16 | "devDependencies": {
17 | "sass": "^1.87.0",
18 | "typescript": "~5.8.3",
19 | "vite": "^6.3.5"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/tsup.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "tsup"
2 | import { spawn } from "child_process"
3 |
4 | export default defineConfig({
5 | entry: { index: "src/index.ts" },
6 | splitting: false,
7 | clean: true,
8 | dts: true,
9 | target: "es2020",
10 | format: ["esm"],
11 | name: "debug",
12 | minify: "terser",
13 | terserOptions: {
14 | compress: true,
15 | },
16 | async onSuccess() {
17 | const process = spawn("npm", ["run", "size"], { shell: true })
18 | process.stdout.on("data", (data) => console.log(data.toString()))
19 | },
20 | })
21 |
--------------------------------------------------------------------------------
/examples/node/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node",
3 | "lockfileVersion": 3,
4 | "requires": true,
5 | "packages": {
6 | "": {
7 | "name": "node",
8 | "dependencies": {
9 | "@localnerve/debug": "latest"
10 | }
11 | },
12 | "node_modules/@localnerve/debug": {
13 | "version": "1.0.10",
14 | "resolved": "https://registry.npmjs.org/@localnerve/debug/-/debug-1.0.10.tgz",
15 | "integrity": "sha512-/ZmDemh/+DTmR5slBgpIKa+RyYFt5HTk93PvUw5+2yYmfhw0NAkk0U/QXz7FH5qJlNJB2Od9WKeiFdKkrftIhA==",
16 | "license": "MIT"
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "./dist",
4 | "rootDir": "./src",
5 | "module": "esnext",
6 | "target": "esnext",
7 | "lib": ["es2015.promise", "es6", "dom", "esnext"],
8 | "jsx": "react",
9 | "moduleResolution": "node",
10 | "types": ["node"],
11 | "declaration": true,
12 | "isolatedModules": false,
13 | "noImplicitAny": false,
14 | "esModuleInterop": true,
15 | "preserveConstEnums": true,
16 | "strictNullChecks": false
17 | },
18 | "include": ["./src/*"],
19 | "exclude": ["node_modules", "dist",
20 | "examples"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/examples/node/index.js:
--------------------------------------------------------------------------------
1 | import debug from "@localnerve/debug"
2 | const str = "hello debug!"
3 |
4 | debug("namespace:01")(str)
5 | debug("namespace:02")(str)
6 | debug("namespace:03")(str)
7 | debug("namespace:04")(str)
8 | debug("namespace:05")(str)
9 | debug("namespace:06")(str)
10 | debug("namespace:07")(str)
11 | debug("namespace:08")(str)
12 | debug("namespace:09")(str)
13 | debug("namespace:10")(str)
14 | debug("namespace:11")(str)
15 | debug("namespace:12")(str)
16 | debug("namespace:13")(str)
17 | debug("namespace:14")(str)
18 | debug("otherspace")(str)
19 | debug("otherspace")(str)
20 | debug("otherspace")(str)
21 | debug("otherspace")(str)
22 | debug("otherspace")(str)
23 | console.log("")
24 | console.log("")
25 | console.log("")
26 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 | on:
3 | push:
4 | branches: [ main, public-package ]
5 | pull_request:
6 | branches: [ main, public-package ]
7 | jobs:
8 | ci:
9 | runs-on: ubuntu-24.04
10 | strategy:
11 | matrix:
12 | node-version: [20.x, 22.x, 24.x]
13 | steps:
14 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # 6.0.1
15 | - name: Use Node.js ${{ matrix.node-version }}
16 | uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # 6.1.0
17 | with:
18 | node-version: ${{ matrix.node-version }}
19 | - run: npm ci
20 |
21 | - name: build
22 | run: npm run build
23 |
24 | - name: test
25 | run: npm test
26 |
27 | - name: size
28 | run: npm run size
29 |
--------------------------------------------------------------------------------
/bench/bench-browser/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
7 | "skipLibCheck": true,
8 |
9 | /* Bundler mode */
10 | "moduleResolution": "bundler",
11 | "allowImportingTsExtensions": true,
12 | "isolatedModules": true,
13 | "moduleDetection": "force",
14 | "noEmit": true,
15 |
16 | /* JSX Support for Preact */
17 | "jsx": "react-jsx",
18 | "jsxImportSource": "preact",
19 |
20 | /* Linting */
21 | "strict": false,
22 | "noUnusedLocals": true,
23 | "noUnusedParameters": true,
24 | "noFallthroughCasesInSwitch": true,
25 | "noUncheckedSideEffectImports": true
26 | },
27 | "include": ["src"],
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy
2 | on:
3 | push:
4 | branches: [ public-package ]
5 |
6 | jobs:
7 | deploy:
8 | runs-on: ubuntu-24.04
9 | permissions:
10 | contents: read
11 | id-token: write
12 | steps:
13 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # 6.0.1
14 | - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # 6.1.0
15 | with:
16 | node-version: '24.x'
17 | registry-url: 'https://registry.npmjs.org'
18 | - name: Update npm
19 | run: npm install -g npm@latest # ensure npm 11.5.1 or later
20 | - run: npm ci
21 | - name: Verify
22 | run: npm test
23 | - name: Build
24 | run: npm run build
25 | - name: Publish
26 | if: ${{ success() }}
27 | run: npm publish --provenance --access public
28 | env:
29 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Willy Brauner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/browser/src/index.ts:
--------------------------------------------------------------------------------
1 | import debug from "debug"
2 | import debugWbe from "@localnerve/debug"
3 |
4 | const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
5 |
6 | const test = async (lib) => {
7 | const log = lib("front:index")
8 | log("index log", { props: "foo" })
9 |
10 | for (let i = 0; i < 10; i++) {
11 | const log = lib(`front:${i}`)
12 | await sleep(10)
13 | log(`index log ${i}`)
14 | await sleep(10)
15 | log(`index log ${i}`)
16 | await sleep(100)
17 | log(`index log ${i}`)
18 | }
19 |
20 | lib(`front:others-types`)(
21 | `new log`,
22 | [
23 | { name: "foo", value: "bar" },
24 | { name: "bar", value: "foo" },
25 | { name: "baz", value: "qux" },
26 | { name: "qux", value: "baz" },
27 | ],
28 | null,
29 | undefined,
30 | "foo"
31 | )
32 |
33 | console.log("native console log (should be removed by esbuild in production)")
34 |
35 | for (let i = 0; i < 3; i++) {
36 | console.log("native console log", i)
37 | }
38 | }
39 |
40 | for (let lib of ["debug-js/debug", "@localnerve/debug"]) {
41 | console.log(
42 | `--------------------------------------------------- ${lib} ---------------------------------------------------`
43 | )
44 | await test(lib === "debug-js/debug" ? debug : debugWbe)
45 | }
46 |
--------------------------------------------------------------------------------
/bench/bench-browser/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/helpers.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Check if is browser env
3 | */
4 | export function isBrowser(): boolean {
5 | return typeof window !== "undefined"
6 | }
7 |
8 | /**
9 | * Transform string to RGB
10 | * @param str
11 | */
12 | export function stringToRgb(str: string): [number, number, number] {
13 | if (!str) return [128, 128, 128]
14 |
15 | // Add a salt to make numbers at the end produce different colors
16 | const salt = "x7f2q9"
17 | const stringToHash = str + salt
18 |
19 | let hash = 0
20 | for (let i = 0; i < stringToHash.length; i++) {
21 | let character = stringToHash.charCodeAt(i)
22 | hash = (hash << 5) - hash + character
23 | hash = Math.abs(hash & hash)
24 | }
25 |
26 | // Create more variance in the RGB values
27 | const r = (hash & 0xff0000) >> 16
28 | const g = ((hash >> 3) & 0x00ff00) >> 8
29 | const b = (hash >> 6) & 0x0000ff
30 |
31 | return [r, g, b]
32 | }
33 |
34 | /**
35 | * ansi RGB
36 | */
37 | // Wraper for ansi 256 code
38 | const _wrapAnsi256 = (code) => `\u001B[${38};5;${code}m`
39 | // Convert RGB color to ansi 256
40 | const _rgbToAnsi256 = (red: number, green: number, blue: number): number => {
41 | if (red === green && green === blue) {
42 | if (red < 8) return 16
43 | if (red > 248) return 231
44 | return Math.round(((red - 8) / 247) * 24) + 232
45 | }
46 | return (
47 | 16 +
48 | 36 * Math.round((red / 255) * 5) +
49 | 6 * Math.round((green / 255) * 5) +
50 | Math.round((blue / 255) * 5)
51 | )
52 | }
53 | export function ansiRgb(r: number, g: number, b: number) {
54 | return function (str: string): string {
55 | const _close = "\u001B[39m"
56 | return _wrapAnsi256(_rgbToAnsi256(r, g, b)) + str + _close
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@localnerve/debug",
3 | "version": "1.0.12",
4 | "description": "Tiny debug tool (~500 bytes) for terminal and browser inspired by debug-js/debug API.",
5 | "author": "Willy Brauner",
6 | "maintainers": [{
7 | "email": "alex@localnerve.com",
8 | "name": "Alex Grant",
9 | "url": "https://localnerve.com"
10 | }],
11 | "license": "MIT",
12 | "type": "module",
13 | "exports": {
14 | ".": {
15 | "types": "./dist/index.d.ts",
16 | "import": "./dist/index.js"
17 | }
18 | },
19 | "types": "./dist/index.d.ts",
20 | "sideEffects": false,
21 | "repository": {
22 | "type": "git",
23 | "url": "https://github.com/localnerve/debug.git"
24 | },
25 | "keywords": [
26 | "debug",
27 | "debugger",
28 | "log",
29 | "logger",
30 | "console.log",
31 | "nodejs",
32 | "browser"
33 | ],
34 | "publishConfig": {
35 | "access": "public"
36 | },
37 | "files": [
38 | "dist/**"
39 | ],
40 | "scripts": {
41 | "build": "tsup",
42 | "build:watch": "tsup --watch --sourcemap",
43 | "clean": "rm -rf ./dist && rm -rf tsconfig.tsbuildinfo",
44 | "dev:example-browser": "cd examples/browser && npm i && npm run build && npm run dev",
45 | "dev:example-node": "cd examples/node && npm i && DEBUG=* node index.js && cd -",
46 | "pre-publish": "npm run build && npm test",
47 | "test:watch": "vitest",
48 | "test": "vitest --run",
49 | "ncu": "find . -name 'node_modules' -prune -o -name 'package.json' -execdir ncu -u ';'",
50 | "size": "size-limit"
51 | },
52 | "devDependencies": {
53 | "@size-limit/preset-small-lib": "^12.0.0",
54 | "@types/node": "^25.0.0",
55 | "size-limit": "^12.0.0",
56 | "terser": "^5.44.1",
57 | "tsup": "^8.5.1",
58 | "typescript": "^5.9.3",
59 | "vitest": "^4.0.15"
60 | },
61 | "prettier": {
62 | "semi": false
63 | },
64 | "size-limit": [
65 | {
66 | "name": "@localnerve/debug",
67 | "path": "dist/index.js",
68 | "limit": "655 B"
69 | }
70 | ]
71 | }
72 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # @localnerve/debug
2 |
3 | Tiny debug tool (~650 bytes) for terminal and browser inspired by [debug-js/debug](https://github.com/debug-js/debug) API.
4 |
5 | 
6 | 
7 | 
8 | 
9 |
10 | 
11 |
12 | ## Motivation
13 |
14 | Forked from `@wbe/debug`, this was built in order to be as light as possible for terminal and browser,
15 | as the same way as the great debug-js/debug tool, with a few added debug-js/debug parity features.
16 | The package is less than 10k unpacked on disk, and published directly from Github with provenance.
17 |
18 | ## Installation
19 |
20 | ```shell script
21 | $ npm i @localnerve/debug
22 | ```
23 |
24 | ## debug node
25 |
26 | ```shell
27 | DEBUG=* node file.js
28 | ```
29 |
30 | file.js:
31 |
32 | ```js
33 | import debug from "@localnerve/debug"
34 | const log = debug("namespace")
35 | log("hello") // "namespace hello"
36 | ```
37 |
38 | `process.env.DEBUG` value can be defined as a specific namespace too:
39 |
40 | ```shell
41 | DEBUG=namespace-1 node file.js
42 | ```
43 |
44 | Only debug function declaration with `namespace-1` declared as namespace will be printed in the console:
45 |
46 | ```js
47 | import debug from "@localnerve/debug"
48 | const log = debug("namespace-1")
49 | log("hello") // "namespace-1 hello"
50 | ```
51 |
52 | `process.env.DEBUG` value accept "one glob parameter level":
53 |
54 | ```shell
55 | DEBUG=config:* node file.js
56 | ```
57 |
58 | Every debug function declaration with namespace `config:{somestring}` will be logged.
59 |
60 | ## debug in browser
61 |
62 | In the same way as nodejs usage, `debug` is browser compatible with the same API. The only difference is
63 | we need to set the current namespace in localStorage.
64 |
65 | Add on your browser localStorage:
66 |
67 | ```shell
68 | localStorage.debug = "foo"
69 | ```
70 |
71 | Use debug in javascript:
72 |
73 | ```js
74 | // es6 import
75 | import debug from "@localnerve/debug"
76 | const log = debug("foo")
77 | log("bar") // "foo bar"
78 | ```
79 |
80 | ## Examples
81 |
82 | Install dependencies:
83 |
84 | Start example:
85 |
86 | ```shell
87 | # browser example
88 | npm run dev:example-browser
89 | # node example
90 | npm run dev:example-dev
91 | ```
92 |
93 | ## Credits
94 |
95 | Willy Brauner
96 |
97 | ## Licence
98 |
99 | MIT
100 |
--------------------------------------------------------------------------------
/bench/bench-browser/src/styles/main.scss:
--------------------------------------------------------------------------------
1 | // Variables
2 | $primary-color: #4caf50;
3 | $primary-hover-color: #45a049;
4 | $secondary-color: #3498db;
5 | $accent-color: #2ecc71;
6 | $text-color: #333;
7 | $text-secondary: #666;
8 | $border-color: #ddd;
9 | $bg-light: #f8f9fa;
10 | $bg-white: #fff;
11 | $bg-disabled: #cccccc;
12 |
13 | // Base styles
14 | body {
15 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
16 | line-height: 1.6;
17 | margin: 0;
18 | padding: 0;
19 | color: $text-color;
20 | }
21 |
22 | #app {
23 | max-width: 1000px;
24 | margin: 0 auto;
25 | padding: 20px;
26 | }
27 |
28 | // Header
29 | .header {
30 | text-align: center;
31 | margin-bottom: 30px;
32 |
33 | h1 {
34 | margin-bottom: 10px;
35 | }
36 | }
37 |
38 | .description {
39 | color: $text-secondary;
40 | font-size: 18px;
41 | }
42 |
43 | // Console output section
44 | .console-output {
45 | background-color: $bg-light;
46 | border-radius: 4px;
47 | padding: 15px;
48 | margin-bottom: 30px;
49 | border: 1px solid $border-color;
50 | overflow: auto;
51 | max-height: 300px;
52 |
53 | h2 {
54 | margin-top: 0;
55 | }
56 | }
57 |
58 | pre {
59 | background-color: $bg-light;
60 | border-radius: 4px;
61 | padding: 10px;
62 | overflow: auto;
63 | }
64 |
65 | // Benchmark components
66 | .loading {
67 | padding: 20px;
68 | background-color: $bg-light;
69 | border-radius: 4px;
70 | text-align: center;
71 | margin-bottom: 20px;
72 | font-weight: bold;
73 | }
74 |
75 | .results {
76 | padding: 20px;
77 | background-color: $bg-white;
78 | border-radius: 8px;
79 | box-shadow: 0 2px 10px rgba(0,0,0,0.1);
80 | margin-bottom: 30px;
81 | }
82 |
83 | .summary {
84 | margin-bottom: 20px;
85 | padding: 15px;
86 | background-color: $bg-light;
87 | border-radius: 4px;
88 | }
89 |
90 | .winner {
91 | font-size: 18px;
92 | }
93 |
94 | // Bars for visualizing results
95 | .result-bars {
96 | margin-bottom: 20px;
97 | }
98 |
99 | .bar-container {
100 | margin-bottom: 20px;
101 | }
102 |
103 | .bar-label {
104 | margin-bottom: 5px;
105 | }
106 |
107 | .bar {
108 | height: 30px;
109 | border-radius: 4px;
110 | display: flex;
111 | align-items: center;
112 | padding-left: 10px;
113 | color: white;
114 | font-weight: bold;
115 | transition: width 1s;
116 | box-shadow: 0 1px 3px rgba(0,0,0,0.1);
117 |
118 | &.original-bar {
119 | background-color: $secondary-color;
120 | }
121 |
122 | &.wbe-bar {
123 | background-color: $accent-color;
124 | }
125 | }
126 |
127 | // Test details section
128 | .test-details {
129 | margin-top: 30px;
130 | padding: 15px;
131 | background-color: $bg-light;
132 | border-radius: 4px;
133 | }
134 |
135 | // Action buttons
136 | .actions {
137 | margin-top: 20px;
138 | text-align: center;
139 | }
140 |
141 | .run-btn {
142 | padding: 10px 20px;
143 | background-color: $primary-color;
144 | color: white;
145 | border: none;
146 | border-radius: 4px;
147 | cursor: pointer;
148 | font-size: 16px;
149 | transition: background-color 0.3s;
150 |
151 | &:hover {
152 | background-color: $primary-hover-color;
153 | }
154 |
155 | &:disabled {
156 | background-color: $bg-disabled;
157 | cursor: not-allowed;
158 | }
159 | }
--------------------------------------------------------------------------------
/src/debug.ts:
--------------------------------------------------------------------------------
1 | import { ansiRgb, isBrowser, stringToRgb } from "./helpers"
2 |
3 | // Store timers per namespace instead of using a global timer
4 | let TIMERS: Record = {}
5 |
6 | // Maximum number of namespaces to track before cleanup
7 | const MAX_NAMESPACES = 1000
8 |
9 | /**
10 | * debug
11 | * @param namespace - The namespace to log
12 | * @param elapsedTime - Whether to show elapsed time since the last log
13 | * @returns A function that logs the namespace and arguments to the console
14 | */
15 | export const debug = (namespace?: string, elapsedTime = true) => {
16 | const rgb = stringToRgb(namespace)
17 |
18 | // Define when to show the log
19 | const showLog = (value: string): boolean => {
20 | const debugSpecs = value?.split(",");
21 | return debugSpecs?.some(spec => {
22 | const split = spec.split(/(\:\*)|(?:\*)/)
23 | const fragment = split[0]
24 | const fragmentStop = split[1] ? ":" : ""
25 | return value==="*" || namespace.startsWith(`${fragment}${fragmentStop}`)
26 | });
27 | }
28 |
29 | return (...rest: any[]): void => {
30 | // check if debug env exist in both environments
31 | if (
32 | !showLog(isBrowser() ? localStorage.getItem("debug") : process.env.DEBUG)
33 | )
34 | return
35 |
36 | // Calculate elapsed time for each namespace to avoid global state & Cleanup if needed
37 | const now = Date.now()
38 | let elapsed = 0
39 | if (TIMERS[namespace]) {
40 | elapsed = now - TIMERS[namespace]
41 | } else {
42 | if (Object.keys(TIMERS).length >= MAX_NAMESPACES) {
43 | TIMERS = {}
44 | }
45 | }
46 | TIMERS[namespace] = now
47 | const elapsedString =
48 | elapsed > 1000 ? `+${Math.floor(elapsed / 1000)}s` : `+${elapsed}ms`
49 |
50 | // Allow to bypass dropping of console.log from the build process
51 | // has been test with esbuild drop: ["console"] & pure: ["console.log"]
52 | const log = console["log"]
53 |
54 | /**
55 | * Browser environment
56 | */
57 | if (isBrowser()) {
58 | const colorStyle = `color: rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]});`
59 | const args = []
60 |
61 | // Start with the colored namespace format specifier and its style
62 | let format = `%c${namespace}`
63 | args.push(colorStyle)
64 | // Process the rest arguments
65 | // Use %c for strings to allow potential future styling or just display
66 | // Use %o for objects, arrays, etc., for better inspection
67 | for (let i = 0; i < rest.length; i++) {
68 | const arg = rest[i]
69 | if (typeof arg === "string") {
70 | format += ` %c${arg}`
71 | args.push("color: inherit")
72 | } else {
73 | format += " %o"
74 | args.push(arg)
75 | }
76 | }
77 | // Append the elapsed time format specifier and its style
78 | if (elapsedTime) {
79 | format += ` %c${elapsedString}`
80 | args.push(colorStyle)
81 | }
82 | // Append the whole formatted string and log it
83 | args.unshift(format)
84 | log(...args)
85 | } else {
86 | /**
87 | * Node.js environment
88 | */
89 | const wColor = (s: string) => ansiRgb(rgb[0], rgb[1], rgb[2])(s)
90 | const nspace = wColor(namespace)
91 | elapsedTime
92 | ? log(nspace, ...rest, wColor(elapsedString))
93 | : log(nspace, ...rest)
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/test/debug.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect, beforeEach, afterEach } from "vitest"
2 | import debug from "../src"
3 |
4 | describe("debug", () => {
5 | // Mock console.log
6 | const originalConsoleLog = console.log
7 | let consoleLogCalls: any[][] = []
8 |
9 | beforeEach(() => {
10 | // Reset mock calls before each test
11 | consoleLogCalls = []
12 | console.log = (...args: any[]) => {
13 | consoleLogCalls.push(args)
14 | return originalConsoleLog(...args)
15 | }
16 | })
17 |
18 | afterEach(() => {
19 | // Restore original console.log
20 | console.log = originalConsoleLog
21 | // Clear process.env.DEBUG
22 | delete process.env.DEBUG
23 | })
24 |
25 | it("should log only if we add DEBUG={namespace} as env var", () => {
26 | // Test when DEBUG equals the namespace
27 | process.env.DEBUG = "test-namespace"
28 | const testDebug = debug("test-namespace")
29 | testDebug("Test message")
30 | expect(consoleLogCalls.length).toBe(1)
31 | expect(consoleLogCalls[0][1]).toBe("Test message")
32 |
33 | // Test when DEBUG equals *
34 | process.env.DEBUG = "*"
35 | const testDebugWildcard = debug("any-namespace")
36 | testDebugWildcard("Wildcard test")
37 | expect(consoleLogCalls.length).toBe(2)
38 | expect(consoleLogCalls[1][1]).toBe("Wildcard test")
39 |
40 | // Test when DEBUG uses wildcard prefix (namespace:*)
41 | process.env.DEBUG = "prefix:*"
42 | const testDebugPrefix = debug("prefix:something")
43 | testDebugPrefix("Prefix test")
44 | expect(consoleLogCalls.length).toBe(3)
45 | expect(consoleLogCalls[2][1]).toBe("Prefix test")
46 |
47 | // Test when DEBUG doesn't match
48 | process.env.DEBUG = "different-namespace"
49 | const testNoDebug = debug("test-namespace")
50 | testNoDebug("Should not log")
51 | expect(consoleLogCalls.length).toBe(3) // Count shouldn't increase
52 | })
53 |
54 | it("should log only logs from a spectific namespace", () => {
55 | // Create multiple debug loggers with different namespaces
56 | const debug1 = debug("namespace1")
57 | const debug2 = debug("namespace2")
58 | const debug3 = debug("namespace3")
59 |
60 | // Set DEBUG to only match one namespace
61 | process.env.DEBUG = "namespace2"
62 |
63 | // Call all loggers
64 | debug1("Message from namespace1")
65 | debug2("Message from namespace2")
66 | debug3("Message from namespace3")
67 |
68 | // Verify only namespace2 logged a message
69 | expect(consoleLogCalls.length).toBe(1)
70 | expect(consoleLogCalls[0][1]).toBe("Message from namespace2")
71 | })
72 |
73 | it("should not handle undefined namespace", () => {
74 | process.env.DEBUG = "*"
75 | const testDebug = debug(undefined)
76 | testDebug("Test with undefined namespace")
77 | expect(consoleLogCalls.length).toBe(1)
78 | })
79 |
80 | it("should log multiple arguments correctly", async () => {
81 | await new Promise((resolve) => setTimeout(resolve, 1000))
82 | process.env.DEBUG = "test-namespace"
83 | const testDebug = debug("test-namespace")
84 | testDebug("First argument", "Second argument", { key: "value" }, 123)
85 | expect(consoleLogCalls.length).toBe(1)
86 | expect(consoleLogCalls[0][1]).toBe("First argument")
87 | expect(consoleLogCalls[0][2]).toBe("Second argument")
88 | expect(consoleLogCalls[0][3]).toEqual({ key: "value" })
89 | expect(consoleLogCalls[0][4]).toBe(123)
90 | })
91 |
92 | it("should not log when DEBUG is not set", () => {
93 | // DEBUG is already deleted in afterEach
94 | const testDebug = debug("test-namespace")
95 | testDebug("Should not log")
96 | expect(consoleLogCalls.length).toBe(0)
97 | })
98 |
99 | it("should handle multiple debug namespaces", () => {
100 | process.env.DEBUG = "one,two,three,fo*,five:*,seven";
101 | const debug1 = debug("one")
102 | const debug2 = debug("two")
103 | const debug3 = debug("three")
104 | const debug4 = debug("four")
105 | const debug5 = debug("fort")
106 | const debug51 = debug("free");
107 | const debug6 = debug("five:five-test")
108 | const debug7 = debug("five:five-six")
109 | const debug71 = debug("fiver:seven-one")
110 | const debug8 = debug("seven")
111 |
112 | debug1("Should log one")
113 | debug2("Should log two")
114 | debug3("Should log three")
115 | debug4("Should log four")
116 | debug5("Should log fort")
117 | debug51("Should not log free")
118 | debug6("Should log five")
119 | debug7("Should log six")
120 | debug71("Should not log a similar colon:splat prefix")
121 | debug8("Should log seven")
122 |
123 | expect(consoleLogCalls.length).toBe(8)
124 | expect(consoleLogCalls[0][0]).toContain("one")
125 | expect(consoleLogCalls[0][1]).toBe("Should log one")
126 | expect(consoleLogCalls[1][0]).toContain("two")
127 | expect(consoleLogCalls[1][1]).toBe("Should log two")
128 | expect(consoleLogCalls[2][0]).toContain("three")
129 | expect(consoleLogCalls[2][1]).toBe("Should log three")
130 | expect(consoleLogCalls[3][0]).toContain("four")
131 | expect(consoleLogCalls[3][1]).toBe("Should log four")
132 | expect(consoleLogCalls[4][0]).toContain("fort")
133 | expect(consoleLogCalls[4][1]).toBe("Should log fort")
134 | expect(consoleLogCalls[5][0]).toContain("five")
135 | expect(consoleLogCalls[5][1]).toBe("Should log five")
136 | expect(consoleLogCalls[6][0]).toContain("six")
137 | expect(consoleLogCalls[6][1]).toBe("Should log six")
138 | expect(consoleLogCalls[7][0]).toContain("seven")
139 | expect(consoleLogCalls[7][1]).toBe("Should log seven")
140 | })
141 | })
142 |
--------------------------------------------------------------------------------
/bench/bench-node/src/index.ts:
--------------------------------------------------------------------------------
1 | import debugOriginal from "debug"
2 | import debugWbe from "@localnerve/debug"
3 | import chalk from "chalk"
4 |
5 | // Enable logs for both libraries but redirect to null
6 | // This allows the libraries to run their code paths but without the I/O overhead
7 | process.env.DEBUG = "*"
8 |
9 | // Redirect console output during benchmarking
10 | const originalConsoleLog = console.log
11 | const disableConsoleOutput = () => {
12 | console.log = () => {}
13 | }
14 | const restoreConsoleOutput = () => {
15 | console.log = originalConsoleLog
16 | }
17 |
18 | // Function to format numbers with commas for better readability
19 | const formatNumber = (num: number): string => {
20 | return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
21 | }
22 |
23 | /**
24 | * Benchmark class to compare @wbe/debug vs debug performances
25 | */
26 | class Benchmark {
27 | private readonly iterations: number
28 | private readonly warmupIterations: number
29 | private results: {
30 | debugOriginal: number
31 | debugWbe: number
32 | }
33 | private testMessages: any[]
34 |
35 | constructor(iterations: number = 100000, warmupIterations: number = 1000) {
36 | this.iterations = iterations
37 | this.warmupIterations = warmupIterations
38 | this.results = {
39 | debugOriginal: 0,
40 | debugWbe: 0,
41 | }
42 |
43 | // Create a variety of test messages to use in benchmarks
44 | this.testMessages = [
45 | "Simple string message",
46 | ["Array", "of", "strings"],
47 | { complex: "object", with: { nested: "properties" } },
48 | ["Mixed", 123, { type: "content" }],
49 | ]
50 | }
51 |
52 | /**
53 | * Run warmup phase to initialize both libraries
54 | */
55 | private warmup(): void {
56 | console.log(chalk.dim("Warming up..."))
57 |
58 | const logOriginal = debugOriginal("bench:original:warmup")
59 | const logWbe = debugWbe("bench:wbe:warmup")
60 |
61 | disableConsoleOutput()
62 | for (let i = 0; i < this.warmupIterations; i++) {
63 | logOriginal("warmup")
64 | logWbe("warmup")
65 | }
66 | restoreConsoleOutput()
67 | }
68 |
69 | /**
70 | * Benchmark the original debug library
71 | */
72 | private benchmarkOriginal(): void {
73 | console.log(
74 | chalk.blue.bold(
75 | `\nBenchmarking ${chalk.underline("original debug")} library...`
76 | )
77 | )
78 |
79 | const logOriginal = debugOriginal("bench:original")
80 |
81 | disableConsoleOutput()
82 | const start = process.hrtime.bigint()
83 |
84 | for (let i = 0; i < this.iterations; i++) {
85 | const msgIndex = i % this.testMessages.length
86 | logOriginal(this.testMessages[msgIndex])
87 | }
88 |
89 | const end = process.hrtime.bigint()
90 | restoreConsoleOutput()
91 |
92 | this.results.debugOriginal = Number(end - start) / 1_000_000 // Convert to ms
93 | }
94 |
95 | /**
96 | * Benchmark the @wbe/debug library
97 | */
98 | private benchmarkWbe(): void {
99 | console.log(
100 | chalk.green.bold(
101 | `\nBenchmarking ${chalk.underline("@wbe/debug")} library...`
102 | )
103 | )
104 |
105 | const logWbe = debugWbe("bench:wbe")
106 |
107 | disableConsoleOutput()
108 | const start = process.hrtime.bigint()
109 |
110 | for (let i = 0; i < this.iterations; i++) {
111 | const msgIndex = i % this.testMessages.length
112 | logWbe(this.testMessages[msgIndex])
113 | }
114 |
115 | const end = process.hrtime.bigint()
116 | restoreConsoleOutput()
117 |
118 | this.results.debugWbe = Number(end - start) / 1_000_000 // Convert to ms
119 | }
120 |
121 | /**
122 | * Display the benchmark results
123 | */
124 | private displayResults(): void {
125 | console.log("\n" + chalk.yellow.bold("=".repeat(50)))
126 | console.log(chalk.yellow.bold(" BENCHMARK RESULTS"))
127 | console.log(chalk.yellow.bold("=".repeat(50)) + "\n")
128 |
129 | const { debugOriginal, debugWbe } = this.results
130 |
131 | console.log(
132 | `Total iterations per library: ${chalk.bold(
133 | formatNumber(this.iterations)
134 | )}`
135 | )
136 | console.log(
137 | `Test messages: ${chalk.dim(JSON.stringify(this.testMessages))}\n`
138 | )
139 |
140 | // Calculate per-operation times
141 | const originalPerOp = debugOriginal / this.iterations
142 | const wbePerOp = debugWbe / this.iterations
143 |
144 | // Display the results for the original debug library
145 | console.log(chalk.blue.bold("Original debug:"))
146 | console.log(` Total time: ${chalk.bold(debugOriginal.toFixed(2) + " ms")}`)
147 | console.log(
148 | ` Per operation: ${chalk.bold(originalPerOp.toFixed(6) + " ms")}\n`
149 | )
150 |
151 | // Display the results for @wbe/debug
152 | console.log(chalk.green.bold("@wbe/debug:"))
153 | console.log(` Total time: ${chalk.bold(debugWbe.toFixed(2) + " ms")}`)
154 | console.log(` Per operation: ${chalk.bold(wbePerOp.toFixed(6) + " ms")}\n`)
155 |
156 | // Display the difference
157 | const diff = debugWbe - debugOriginal
158 | console.log(
159 | `Absolute difference: ${chalk.bold(Math.abs(diff).toFixed(2) + " ms")}`
160 | )
161 |
162 | // Calculate which one is faster
163 | if (debugWbe < debugOriginal) {
164 | const percentFaster = ((debugOriginal / debugWbe - 1) * 100).toFixed(2)
165 | console.log(
166 | chalk.green.bold(
167 | `@wbe/debug is ${percentFaster}% faster than original debug`
168 | )
169 | )
170 | } else {
171 | const percentFaster = ((debugWbe / debugOriginal - 1) * 100).toFixed(2)
172 | console.log(
173 | chalk.blue.bold(
174 | `Original debug is ${percentFaster}% faster than @wbe/debug`
175 | )
176 | )
177 | }
178 |
179 | // Display a simple visualization of the results
180 | this.displayVisualization()
181 | }
182 |
183 | /**
184 | * Display a simple ASCII visualization of the benchmark results
185 | */
186 | private displayVisualization(): void {
187 | const { debugOriginal, debugWbe } = this.results
188 | const maxTime = Math.max(debugOriginal, debugWbe)
189 |
190 | // Calculate bar lengths (max 40 chars)
191 | const maxBarLength = 40
192 | const originalBarLength = Math.round(
193 | (debugOriginal / maxTime) * maxBarLength
194 | )
195 | const wbeBarLength = Math.round((debugWbe / maxTime) * maxBarLength)
196 |
197 | console.log("\n" + chalk.yellow.bold("Performance Comparison:"))
198 |
199 | // Original debug bar
200 | process.stdout.write(chalk.blue.bold("Original debug: "))
201 | process.stdout.write(chalk.blue("█".repeat(originalBarLength)))
202 | console.log(` ${debugOriginal.toFixed(2)} ms`)
203 |
204 | // @wbe/debug bar
205 | process.stdout.write(chalk.green.bold("@wbe/debug: "))
206 | process.stdout.write(chalk.green("█".repeat(wbeBarLength)))
207 | console.log(` ${debugWbe.toFixed(2)} ms`)
208 |
209 | console.log("\n" + chalk.yellow.bold("=".repeat(50)))
210 | }
211 |
212 | /**
213 | * Run the complete benchmark
214 | */
215 | public async run(): Promise {
216 | console.log(
217 | chalk.bold("\n🚀 Starting Node.js benchmark: @wbe/debug vs debug")
218 | )
219 | console.log(
220 | chalk.dim(`Running with ${formatNumber(this.iterations)} iterations`)
221 | )
222 |
223 | // First warm up
224 | this.warmup()
225 |
226 | // Benchmark original debug
227 | this.benchmarkOriginal()
228 |
229 | // Benchmark @wbe/debug
230 | this.benchmarkWbe()
231 |
232 | // Display results
233 | this.displayResults()
234 | }
235 | }
236 |
237 | // Run the benchmark with 100,000 iterations
238 | const benchmark = new Benchmark(100000)
239 | benchmark.run().catch(console.error)
240 |
--------------------------------------------------------------------------------
/bench/bench-browser/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "preact/hooks"
2 | import debugOriginal from "debug"
3 | import debugWbe from "@localnerve/debug"
4 |
5 | interface BenchmarkResults {
6 | debugOriginal: number
7 | debugWbe: number
8 | iterations: number
9 | testMessages: any[]
10 | completed: boolean
11 | }
12 |
13 | export const BenchmarkApp = () => {
14 | const [results, setResults] = useState({
15 | debugOriginal: 0,
16 | debugWbe: 0,
17 | iterations: 10000,
18 | testMessages: [],
19 | completed: false,
20 | })
21 | const [isRunning, setIsRunning] = useState(false)
22 |
23 | useEffect(() => {
24 | runBenchmark()
25 | }, [])
26 |
27 | const runBenchmark = async () => {
28 | setIsRunning(true)
29 |
30 | const logBench = debugWbe("bench:main")
31 | logBench("Starting browser benchmark...")
32 |
33 | // Setup for benchmarking
34 | const iterations = results.iterations
35 | const benchResults = {
36 | debugOriginal: 0,
37 | debugWbe: 0,
38 | }
39 |
40 | // Create loggers for each library
41 | const logOriginal = debugOriginal("bench:original")
42 | const logWbe = debugWbe("bench:wbe")
43 |
44 | // Warmup phase - warm up both libraries more thoroughly
45 | logBench("Warming up...")
46 | for (let i = 0; i < 1000; i++) {
47 | logOriginal("warmup")
48 | logWbe("warmup")
49 | }
50 |
51 | // Setup test messages with different complexity
52 | const testMessages = [
53 | "Simple string message",
54 | ["Array", "of", "strings"],
55 | { complex: "object", with: { nested: "properties" } },
56 | ["Mixed", 123, { type: "content" }],
57 | ]
58 |
59 | // Update state with test messages
60 | setResults((prev) => ({ ...prev, testMessages }))
61 |
62 | // Run multiple rounds of benchmarking in alternating order
63 | const numberOfRounds = 4
64 | const roundResults = {
65 | debugOriginal: [] as number[],
66 | debugWbe: [] as number[],
67 | }
68 |
69 | logBench(
70 | `Running ${numberOfRounds} rounds of benchmarks in alternating order...`
71 | )
72 |
73 | for (let round = 0; round < numberOfRounds; round++) {
74 | logBench(`Round ${round + 1}/${numberOfRounds}`)
75 |
76 | // Determine order based on round number (alternate)
77 | const runFirstSecond =
78 | round % 2 === 0
79 | ? [runOriginalBenchmark, runWbeBenchmark]
80 | : [runWbeBenchmark, runOriginalBenchmark]
81 |
82 | // Run benchmarks in determined order
83 | await new Promise((resolve) => setTimeout(resolve, 100)) // Small pause between rounds
84 | const result1 = await runFirstSecond[0]()
85 | await new Promise((resolve) => setTimeout(resolve, 100)) // Small pause between tests
86 | const result2 = await runFirstSecond[1]()
87 |
88 | // Store results in correct slots regardless of execution order
89 | if (round % 2 === 0) {
90 | roundResults.debugOriginal.push(result1)
91 | roundResults.debugWbe.push(result2)
92 | } else {
93 | roundResults.debugWbe.push(result1)
94 | roundResults.debugOriginal.push(result2)
95 | }
96 | }
97 |
98 | // Calculate average results
99 | benchResults.debugOriginal =
100 | roundResults.debugOriginal.reduce((a, b) => a + b, 0) / numberOfRounds
101 | benchResults.debugWbe =
102 | roundResults.debugWbe.reduce((a, b) => a + b, 0) / numberOfRounds
103 |
104 | logBench("All benchmark rounds completed.")
105 |
106 | // Function to benchmark original debug
107 | async function runOriginalBenchmark() {
108 | logBench("Benchmarking original debug library...")
109 | const start = performance.now()
110 |
111 | for (let i = 0; i < iterations; i++) {
112 | const msgIndex = i % testMessages.length
113 | logOriginal(testMessages[msgIndex])
114 | }
115 |
116 | const duration = performance.now() - start
117 | logBench(`Original debug completed in ${duration.toFixed(2)}ms`)
118 | return duration
119 | }
120 |
121 | // Function to benchmark @wbe/debug
122 | async function runWbeBenchmark() {
123 | logBench("Benchmarking @wbe/debug library...")
124 | const start = performance.now()
125 |
126 | for (let i = 0; i < iterations; i++) {
127 | const msgIndex = i % testMessages.length
128 | logWbe(testMessages[msgIndex])
129 | }
130 |
131 | const duration = performance.now() - start
132 | logBench(`@wbe/debug completed in ${duration.toFixed(2)}ms`)
133 | return duration
134 | }
135 |
136 | // Display results
137 | logBench("Browser benchmark completed.")
138 |
139 | console.log(
140 | "%c---- BENCHMARK RESULTS ----",
141 | "font-weight: bold; font-size: 16px;"
142 | )
143 | console.log(`Total iterations per library: ${iterations}`)
144 | console.log(
145 | `Original debug: ${benchResults.debugOriginal.toFixed(2)}ms (${(
146 | benchResults.debugOriginal / iterations
147 | ).toFixed(3)}ms per call)`
148 | )
149 | console.log(
150 | `@wbe/debug: ${benchResults.debugWbe.toFixed(2)}ms (${(
151 | benchResults.debugWbe / iterations
152 | ).toFixed(3)}ms per call)`
153 | )
154 | console.log(
155 | `Difference: ${(
156 | benchResults.debugWbe - benchResults.debugOriginal
157 | ).toFixed(2)}ms`
158 | )
159 |
160 | if (benchResults.debugWbe < benchResults.debugOriginal) {
161 | console.log(
162 | `%c@wbe/debug is ${(
163 | (benchResults.debugOriginal / benchResults.debugWbe - 1) *
164 | 100
165 | ).toFixed(2)}% faster`,
166 | "color: green; font-weight: bold"
167 | )
168 | } else {
169 | console.log(
170 | `%cOriginal debug is ${(
171 | (benchResults.debugWbe / benchResults.debugOriginal - 1) *
172 | 100
173 | ).toFixed(2)}% faster`,
174 | "color: red; font-weight: bold"
175 | )
176 | }
177 |
178 | // Update state with results
179 | setResults({
180 | debugOriginal: benchResults.debugOriginal,
181 | debugWbe: benchResults.debugWbe,
182 | iterations,
183 | testMessages,
184 | completed: true,
185 | })
186 |
187 | setIsRunning(false)
188 | }
189 |
190 | return (
191 |
192 |
193 |
196 |
197 |
198 | {results.completed &&
}
199 |
200 | )
201 | }
202 |
203 | const BenchmarkResults = ({ results }: { results: BenchmarkResults }) => {
204 | const { debugOriginal, debugWbe, iterations, testMessages } = results
205 |
206 | const originalPerCall = debugOriginal / iterations
207 | const wbePerCall = debugWbe / iterations
208 | const difference = debugWbe - debugOriginal
209 |
210 | // Calculate percentage difference
211 | const isWbeFaster = debugWbe < debugOriginal
212 | const percentDiff = isWbeFaster
213 | ? ((debugOriginal / debugWbe - 1) * 100).toFixed(2)
214 | : ((debugWbe / debugOriginal - 1) * 100).toFixed(2)
215 |
216 | // Calculate bar widths
217 | const maxTime = Math.max(debugOriginal, debugWbe)
218 | const originalBarWidth = `${Math.min(100, (debugOriginal / maxTime) * 100)}%`
219 | const wbeBarWidth = `${Math.min(100, (debugWbe / maxTime) * 100)}%`
220 |
221 | return (
222 |
223 |
Benchmark Results
224 |
225 |
226 |
227 | Total iterations per library: {iterations}
228 |
229 |
230 |
231 | {isWbeFaster
232 | ? `@wbe/debug is ${percentDiff}% faster`
233 | : `Original debug is ${percentDiff}% faster`}
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 | Original debug: {debugOriginal.toFixed(2)}ms (
242 | {originalPerCall.toFixed(3)}ms per call)
243 |
244 |
245 | {originalPerCall.toFixed(3)}ms
246 |
247 |
248 |
249 |
250 |
251 | @wbe/debug: {debugWbe.toFixed(2)}ms ({wbePerCall.toFixed(3)}ms per
252 | call)
253 |
254 |
255 | {wbePerCall.toFixed(3)}ms
256 |
257 |
258 |
259 |
260 |
261 |
Difference: {difference.toFixed(2)}ms
262 |
263 |
264 |
265 |
Test Details
266 |
267 | - Iterations: {iterations}
268 | - Test performed on: {new Date().toLocaleString()}
269 | - Browser: {navigator.userAgent}
270 |
271 |
272 |
Test Messages
273 |
{JSON.stringify(testMessages, null, 2)}
274 |
275 |
276 | )
277 | }
278 |
--------------------------------------------------------------------------------
/examples/browser/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "browser",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "browser",
9 | "dependencies": {
10 | "@localnerve/debug": "latest",
11 | "debug": "latest"
12 | },
13 | "devDependencies": {
14 | "vite": "^7.2.6"
15 | }
16 | },
17 | "node_modules/@esbuild/aix-ppc64": {
18 | "version": "0.25.4",
19 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz",
20 | "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==",
21 | "cpu": [
22 | "ppc64"
23 | ],
24 | "dev": true,
25 | "license": "MIT",
26 | "optional": true,
27 | "os": [
28 | "aix"
29 | ],
30 | "engines": {
31 | "node": ">=18"
32 | }
33 | },
34 | "node_modules/@esbuild/android-arm": {
35 | "version": "0.25.4",
36 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz",
37 | "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==",
38 | "cpu": [
39 | "arm"
40 | ],
41 | "dev": true,
42 | "license": "MIT",
43 | "optional": true,
44 | "os": [
45 | "android"
46 | ],
47 | "engines": {
48 | "node": ">=18"
49 | }
50 | },
51 | "node_modules/@esbuild/android-arm64": {
52 | "version": "0.25.4",
53 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz",
54 | "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==",
55 | "cpu": [
56 | "arm64"
57 | ],
58 | "dev": true,
59 | "license": "MIT",
60 | "optional": true,
61 | "os": [
62 | "android"
63 | ],
64 | "engines": {
65 | "node": ">=18"
66 | }
67 | },
68 | "node_modules/@esbuild/android-x64": {
69 | "version": "0.25.4",
70 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz",
71 | "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==",
72 | "cpu": [
73 | "x64"
74 | ],
75 | "dev": true,
76 | "license": "MIT",
77 | "optional": true,
78 | "os": [
79 | "android"
80 | ],
81 | "engines": {
82 | "node": ">=18"
83 | }
84 | },
85 | "node_modules/@esbuild/darwin-arm64": {
86 | "version": "0.25.4",
87 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz",
88 | "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==",
89 | "cpu": [
90 | "arm64"
91 | ],
92 | "dev": true,
93 | "license": "MIT",
94 | "optional": true,
95 | "os": [
96 | "darwin"
97 | ],
98 | "engines": {
99 | "node": ">=18"
100 | }
101 | },
102 | "node_modules/@esbuild/darwin-x64": {
103 | "version": "0.25.4",
104 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz",
105 | "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==",
106 | "cpu": [
107 | "x64"
108 | ],
109 | "dev": true,
110 | "license": "MIT",
111 | "optional": true,
112 | "os": [
113 | "darwin"
114 | ],
115 | "engines": {
116 | "node": ">=18"
117 | }
118 | },
119 | "node_modules/@esbuild/freebsd-arm64": {
120 | "version": "0.25.4",
121 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz",
122 | "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==",
123 | "cpu": [
124 | "arm64"
125 | ],
126 | "dev": true,
127 | "license": "MIT",
128 | "optional": true,
129 | "os": [
130 | "freebsd"
131 | ],
132 | "engines": {
133 | "node": ">=18"
134 | }
135 | },
136 | "node_modules/@esbuild/freebsd-x64": {
137 | "version": "0.25.4",
138 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz",
139 | "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==",
140 | "cpu": [
141 | "x64"
142 | ],
143 | "dev": true,
144 | "license": "MIT",
145 | "optional": true,
146 | "os": [
147 | "freebsd"
148 | ],
149 | "engines": {
150 | "node": ">=18"
151 | }
152 | },
153 | "node_modules/@esbuild/linux-arm": {
154 | "version": "0.25.4",
155 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz",
156 | "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==",
157 | "cpu": [
158 | "arm"
159 | ],
160 | "dev": true,
161 | "license": "MIT",
162 | "optional": true,
163 | "os": [
164 | "linux"
165 | ],
166 | "engines": {
167 | "node": ">=18"
168 | }
169 | },
170 | "node_modules/@esbuild/linux-arm64": {
171 | "version": "0.25.4",
172 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz",
173 | "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==",
174 | "cpu": [
175 | "arm64"
176 | ],
177 | "dev": true,
178 | "license": "MIT",
179 | "optional": true,
180 | "os": [
181 | "linux"
182 | ],
183 | "engines": {
184 | "node": ">=18"
185 | }
186 | },
187 | "node_modules/@esbuild/linux-ia32": {
188 | "version": "0.25.4",
189 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz",
190 | "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==",
191 | "cpu": [
192 | "ia32"
193 | ],
194 | "dev": true,
195 | "license": "MIT",
196 | "optional": true,
197 | "os": [
198 | "linux"
199 | ],
200 | "engines": {
201 | "node": ">=18"
202 | }
203 | },
204 | "node_modules/@esbuild/linux-loong64": {
205 | "version": "0.25.4",
206 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz",
207 | "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==",
208 | "cpu": [
209 | "loong64"
210 | ],
211 | "dev": true,
212 | "license": "MIT",
213 | "optional": true,
214 | "os": [
215 | "linux"
216 | ],
217 | "engines": {
218 | "node": ">=18"
219 | }
220 | },
221 | "node_modules/@esbuild/linux-mips64el": {
222 | "version": "0.25.4",
223 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz",
224 | "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==",
225 | "cpu": [
226 | "mips64el"
227 | ],
228 | "dev": true,
229 | "license": "MIT",
230 | "optional": true,
231 | "os": [
232 | "linux"
233 | ],
234 | "engines": {
235 | "node": ">=18"
236 | }
237 | },
238 | "node_modules/@esbuild/linux-ppc64": {
239 | "version": "0.25.4",
240 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz",
241 | "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==",
242 | "cpu": [
243 | "ppc64"
244 | ],
245 | "dev": true,
246 | "license": "MIT",
247 | "optional": true,
248 | "os": [
249 | "linux"
250 | ],
251 | "engines": {
252 | "node": ">=18"
253 | }
254 | },
255 | "node_modules/@esbuild/linux-riscv64": {
256 | "version": "0.25.4",
257 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz",
258 | "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==",
259 | "cpu": [
260 | "riscv64"
261 | ],
262 | "dev": true,
263 | "license": "MIT",
264 | "optional": true,
265 | "os": [
266 | "linux"
267 | ],
268 | "engines": {
269 | "node": ">=18"
270 | }
271 | },
272 | "node_modules/@esbuild/linux-s390x": {
273 | "version": "0.25.4",
274 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz",
275 | "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==",
276 | "cpu": [
277 | "s390x"
278 | ],
279 | "dev": true,
280 | "license": "MIT",
281 | "optional": true,
282 | "os": [
283 | "linux"
284 | ],
285 | "engines": {
286 | "node": ">=18"
287 | }
288 | },
289 | "node_modules/@esbuild/linux-x64": {
290 | "version": "0.25.4",
291 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz",
292 | "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==",
293 | "cpu": [
294 | "x64"
295 | ],
296 | "dev": true,
297 | "license": "MIT",
298 | "optional": true,
299 | "os": [
300 | "linux"
301 | ],
302 | "engines": {
303 | "node": ">=18"
304 | }
305 | },
306 | "node_modules/@esbuild/netbsd-arm64": {
307 | "version": "0.25.4",
308 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz",
309 | "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==",
310 | "cpu": [
311 | "arm64"
312 | ],
313 | "dev": true,
314 | "license": "MIT",
315 | "optional": true,
316 | "os": [
317 | "netbsd"
318 | ],
319 | "engines": {
320 | "node": ">=18"
321 | }
322 | },
323 | "node_modules/@esbuild/netbsd-x64": {
324 | "version": "0.25.4",
325 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz",
326 | "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==",
327 | "cpu": [
328 | "x64"
329 | ],
330 | "dev": true,
331 | "license": "MIT",
332 | "optional": true,
333 | "os": [
334 | "netbsd"
335 | ],
336 | "engines": {
337 | "node": ">=18"
338 | }
339 | },
340 | "node_modules/@esbuild/openbsd-arm64": {
341 | "version": "0.25.4",
342 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz",
343 | "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==",
344 | "cpu": [
345 | "arm64"
346 | ],
347 | "dev": true,
348 | "license": "MIT",
349 | "optional": true,
350 | "os": [
351 | "openbsd"
352 | ],
353 | "engines": {
354 | "node": ">=18"
355 | }
356 | },
357 | "node_modules/@esbuild/openbsd-x64": {
358 | "version": "0.25.4",
359 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz",
360 | "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==",
361 | "cpu": [
362 | "x64"
363 | ],
364 | "dev": true,
365 | "license": "MIT",
366 | "optional": true,
367 | "os": [
368 | "openbsd"
369 | ],
370 | "engines": {
371 | "node": ">=18"
372 | }
373 | },
374 | "node_modules/@esbuild/sunos-x64": {
375 | "version": "0.25.4",
376 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz",
377 | "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==",
378 | "cpu": [
379 | "x64"
380 | ],
381 | "dev": true,
382 | "license": "MIT",
383 | "optional": true,
384 | "os": [
385 | "sunos"
386 | ],
387 | "engines": {
388 | "node": ">=18"
389 | }
390 | },
391 | "node_modules/@esbuild/win32-arm64": {
392 | "version": "0.25.4",
393 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz",
394 | "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==",
395 | "cpu": [
396 | "arm64"
397 | ],
398 | "dev": true,
399 | "license": "MIT",
400 | "optional": true,
401 | "os": [
402 | "win32"
403 | ],
404 | "engines": {
405 | "node": ">=18"
406 | }
407 | },
408 | "node_modules/@esbuild/win32-ia32": {
409 | "version": "0.25.4",
410 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz",
411 | "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==",
412 | "cpu": [
413 | "ia32"
414 | ],
415 | "dev": true,
416 | "license": "MIT",
417 | "optional": true,
418 | "os": [
419 | "win32"
420 | ],
421 | "engines": {
422 | "node": ">=18"
423 | }
424 | },
425 | "node_modules/@esbuild/win32-x64": {
426 | "version": "0.25.4",
427 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz",
428 | "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==",
429 | "cpu": [
430 | "x64"
431 | ],
432 | "dev": true,
433 | "license": "MIT",
434 | "optional": true,
435 | "os": [
436 | "win32"
437 | ],
438 | "engines": {
439 | "node": ">=18"
440 | }
441 | },
442 | "node_modules/@localnerve/debug": {
443 | "version": "1.0.10",
444 | "resolved": "https://registry.npmjs.org/@localnerve/debug/-/debug-1.0.10.tgz",
445 | "integrity": "sha512-/ZmDemh/+DTmR5slBgpIKa+RyYFt5HTk93PvUw5+2yYmfhw0NAkk0U/QXz7FH5qJlNJB2Od9WKeiFdKkrftIhA==",
446 | "license": "MIT"
447 | },
448 | "node_modules/@rollup/rollup-android-arm-eabi": {
449 | "version": "4.53.3",
450 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz",
451 | "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==",
452 | "cpu": [
453 | "arm"
454 | ],
455 | "dev": true,
456 | "license": "MIT",
457 | "optional": true,
458 | "os": [
459 | "android"
460 | ]
461 | },
462 | "node_modules/@rollup/rollup-android-arm64": {
463 | "version": "4.53.3",
464 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz",
465 | "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==",
466 | "cpu": [
467 | "arm64"
468 | ],
469 | "dev": true,
470 | "license": "MIT",
471 | "optional": true,
472 | "os": [
473 | "android"
474 | ]
475 | },
476 | "node_modules/@rollup/rollup-darwin-arm64": {
477 | "version": "4.53.3",
478 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz",
479 | "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==",
480 | "cpu": [
481 | "arm64"
482 | ],
483 | "dev": true,
484 | "license": "MIT",
485 | "optional": true,
486 | "os": [
487 | "darwin"
488 | ]
489 | },
490 | "node_modules/@rollup/rollup-darwin-x64": {
491 | "version": "4.53.3",
492 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz",
493 | "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==",
494 | "cpu": [
495 | "x64"
496 | ],
497 | "dev": true,
498 | "license": "MIT",
499 | "optional": true,
500 | "os": [
501 | "darwin"
502 | ]
503 | },
504 | "node_modules/@rollup/rollup-freebsd-arm64": {
505 | "version": "4.53.3",
506 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz",
507 | "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==",
508 | "cpu": [
509 | "arm64"
510 | ],
511 | "dev": true,
512 | "license": "MIT",
513 | "optional": true,
514 | "os": [
515 | "freebsd"
516 | ]
517 | },
518 | "node_modules/@rollup/rollup-freebsd-x64": {
519 | "version": "4.53.3",
520 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz",
521 | "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==",
522 | "cpu": [
523 | "x64"
524 | ],
525 | "dev": true,
526 | "license": "MIT",
527 | "optional": true,
528 | "os": [
529 | "freebsd"
530 | ]
531 | },
532 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
533 | "version": "4.53.3",
534 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz",
535 | "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==",
536 | "cpu": [
537 | "arm"
538 | ],
539 | "dev": true,
540 | "license": "MIT",
541 | "optional": true,
542 | "os": [
543 | "linux"
544 | ]
545 | },
546 | "node_modules/@rollup/rollup-linux-arm-musleabihf": {
547 | "version": "4.53.3",
548 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz",
549 | "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==",
550 | "cpu": [
551 | "arm"
552 | ],
553 | "dev": true,
554 | "license": "MIT",
555 | "optional": true,
556 | "os": [
557 | "linux"
558 | ]
559 | },
560 | "node_modules/@rollup/rollup-linux-arm64-gnu": {
561 | "version": "4.53.3",
562 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz",
563 | "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==",
564 | "cpu": [
565 | "arm64"
566 | ],
567 | "dev": true,
568 | "license": "MIT",
569 | "optional": true,
570 | "os": [
571 | "linux"
572 | ]
573 | },
574 | "node_modules/@rollup/rollup-linux-arm64-musl": {
575 | "version": "4.53.3",
576 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz",
577 | "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==",
578 | "cpu": [
579 | "arm64"
580 | ],
581 | "dev": true,
582 | "license": "MIT",
583 | "optional": true,
584 | "os": [
585 | "linux"
586 | ]
587 | },
588 | "node_modules/@rollup/rollup-linux-loong64-gnu": {
589 | "version": "4.53.3",
590 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz",
591 | "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==",
592 | "cpu": [
593 | "loong64"
594 | ],
595 | "dev": true,
596 | "license": "MIT",
597 | "optional": true,
598 | "os": [
599 | "linux"
600 | ]
601 | },
602 | "node_modules/@rollup/rollup-linux-ppc64-gnu": {
603 | "version": "4.53.3",
604 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz",
605 | "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==",
606 | "cpu": [
607 | "ppc64"
608 | ],
609 | "dev": true,
610 | "license": "MIT",
611 | "optional": true,
612 | "os": [
613 | "linux"
614 | ]
615 | },
616 | "node_modules/@rollup/rollup-linux-riscv64-gnu": {
617 | "version": "4.53.3",
618 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz",
619 | "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==",
620 | "cpu": [
621 | "riscv64"
622 | ],
623 | "dev": true,
624 | "license": "MIT",
625 | "optional": true,
626 | "os": [
627 | "linux"
628 | ]
629 | },
630 | "node_modules/@rollup/rollup-linux-riscv64-musl": {
631 | "version": "4.53.3",
632 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz",
633 | "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==",
634 | "cpu": [
635 | "riscv64"
636 | ],
637 | "dev": true,
638 | "license": "MIT",
639 | "optional": true,
640 | "os": [
641 | "linux"
642 | ]
643 | },
644 | "node_modules/@rollup/rollup-linux-s390x-gnu": {
645 | "version": "4.53.3",
646 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz",
647 | "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==",
648 | "cpu": [
649 | "s390x"
650 | ],
651 | "dev": true,
652 | "license": "MIT",
653 | "optional": true,
654 | "os": [
655 | "linux"
656 | ]
657 | },
658 | "node_modules/@rollup/rollup-linux-x64-gnu": {
659 | "version": "4.53.3",
660 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz",
661 | "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==",
662 | "cpu": [
663 | "x64"
664 | ],
665 | "dev": true,
666 | "license": "MIT",
667 | "optional": true,
668 | "os": [
669 | "linux"
670 | ]
671 | },
672 | "node_modules/@rollup/rollup-linux-x64-musl": {
673 | "version": "4.53.3",
674 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz",
675 | "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==",
676 | "cpu": [
677 | "x64"
678 | ],
679 | "dev": true,
680 | "license": "MIT",
681 | "optional": true,
682 | "os": [
683 | "linux"
684 | ]
685 | },
686 | "node_modules/@rollup/rollup-openharmony-arm64": {
687 | "version": "4.53.3",
688 | "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz",
689 | "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==",
690 | "cpu": [
691 | "arm64"
692 | ],
693 | "dev": true,
694 | "license": "MIT",
695 | "optional": true,
696 | "os": [
697 | "openharmony"
698 | ]
699 | },
700 | "node_modules/@rollup/rollup-win32-arm64-msvc": {
701 | "version": "4.53.3",
702 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz",
703 | "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==",
704 | "cpu": [
705 | "arm64"
706 | ],
707 | "dev": true,
708 | "license": "MIT",
709 | "optional": true,
710 | "os": [
711 | "win32"
712 | ]
713 | },
714 | "node_modules/@rollup/rollup-win32-ia32-msvc": {
715 | "version": "4.53.3",
716 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz",
717 | "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==",
718 | "cpu": [
719 | "ia32"
720 | ],
721 | "dev": true,
722 | "license": "MIT",
723 | "optional": true,
724 | "os": [
725 | "win32"
726 | ]
727 | },
728 | "node_modules/@rollup/rollup-win32-x64-gnu": {
729 | "version": "4.53.3",
730 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz",
731 | "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==",
732 | "cpu": [
733 | "x64"
734 | ],
735 | "dev": true,
736 | "license": "MIT",
737 | "optional": true,
738 | "os": [
739 | "win32"
740 | ]
741 | },
742 | "node_modules/@rollup/rollup-win32-x64-msvc": {
743 | "version": "4.53.3",
744 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz",
745 | "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==",
746 | "cpu": [
747 | "x64"
748 | ],
749 | "dev": true,
750 | "license": "MIT",
751 | "optional": true,
752 | "os": [
753 | "win32"
754 | ]
755 | },
756 | "node_modules/@types/estree": {
757 | "version": "1.0.8",
758 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
759 | "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
760 | "dev": true,
761 | "license": "MIT"
762 | },
763 | "node_modules/debug": {
764 | "version": "4.4.0",
765 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
766 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
767 | "license": "MIT",
768 | "dependencies": {
769 | "ms": "^2.1.3"
770 | },
771 | "engines": {
772 | "node": ">=6.0"
773 | },
774 | "peerDependenciesMeta": {
775 | "supports-color": {
776 | "optional": true
777 | }
778 | }
779 | },
780 | "node_modules/esbuild": {
781 | "version": "0.25.4",
782 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz",
783 | "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==",
784 | "dev": true,
785 | "hasInstallScript": true,
786 | "license": "MIT",
787 | "bin": {
788 | "esbuild": "bin/esbuild"
789 | },
790 | "engines": {
791 | "node": ">=18"
792 | },
793 | "optionalDependencies": {
794 | "@esbuild/aix-ppc64": "0.25.4",
795 | "@esbuild/android-arm": "0.25.4",
796 | "@esbuild/android-arm64": "0.25.4",
797 | "@esbuild/android-x64": "0.25.4",
798 | "@esbuild/darwin-arm64": "0.25.4",
799 | "@esbuild/darwin-x64": "0.25.4",
800 | "@esbuild/freebsd-arm64": "0.25.4",
801 | "@esbuild/freebsd-x64": "0.25.4",
802 | "@esbuild/linux-arm": "0.25.4",
803 | "@esbuild/linux-arm64": "0.25.4",
804 | "@esbuild/linux-ia32": "0.25.4",
805 | "@esbuild/linux-loong64": "0.25.4",
806 | "@esbuild/linux-mips64el": "0.25.4",
807 | "@esbuild/linux-ppc64": "0.25.4",
808 | "@esbuild/linux-riscv64": "0.25.4",
809 | "@esbuild/linux-s390x": "0.25.4",
810 | "@esbuild/linux-x64": "0.25.4",
811 | "@esbuild/netbsd-arm64": "0.25.4",
812 | "@esbuild/netbsd-x64": "0.25.4",
813 | "@esbuild/openbsd-arm64": "0.25.4",
814 | "@esbuild/openbsd-x64": "0.25.4",
815 | "@esbuild/sunos-x64": "0.25.4",
816 | "@esbuild/win32-arm64": "0.25.4",
817 | "@esbuild/win32-ia32": "0.25.4",
818 | "@esbuild/win32-x64": "0.25.4"
819 | }
820 | },
821 | "node_modules/fdir": {
822 | "version": "6.5.0",
823 | "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
824 | "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
825 | "dev": true,
826 | "license": "MIT",
827 | "engines": {
828 | "node": ">=12.0.0"
829 | },
830 | "peerDependencies": {
831 | "picomatch": "^3 || ^4"
832 | },
833 | "peerDependenciesMeta": {
834 | "picomatch": {
835 | "optional": true
836 | }
837 | }
838 | },
839 | "node_modules/fsevents": {
840 | "version": "2.3.3",
841 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
842 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
843 | "dev": true,
844 | "hasInstallScript": true,
845 | "license": "MIT",
846 | "optional": true,
847 | "os": [
848 | "darwin"
849 | ],
850 | "engines": {
851 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
852 | }
853 | },
854 | "node_modules/ms": {
855 | "version": "2.1.3",
856 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
857 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
858 | "license": "MIT"
859 | },
860 | "node_modules/nanoid": {
861 | "version": "3.3.11",
862 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
863 | "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
864 | "dev": true,
865 | "funding": [
866 | {
867 | "type": "github",
868 | "url": "https://github.com/sponsors/ai"
869 | }
870 | ],
871 | "license": "MIT",
872 | "bin": {
873 | "nanoid": "bin/nanoid.cjs"
874 | },
875 | "engines": {
876 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
877 | }
878 | },
879 | "node_modules/picocolors": {
880 | "version": "1.1.1",
881 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
882 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
883 | "dev": true,
884 | "license": "ISC"
885 | },
886 | "node_modules/picomatch": {
887 | "version": "4.0.3",
888 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
889 | "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
890 | "dev": true,
891 | "license": "MIT",
892 | "engines": {
893 | "node": ">=12"
894 | },
895 | "funding": {
896 | "url": "https://github.com/sponsors/jonschlinkert"
897 | }
898 | },
899 | "node_modules/postcss": {
900 | "version": "8.5.6",
901 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
902 | "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
903 | "dev": true,
904 | "funding": [
905 | {
906 | "type": "opencollective",
907 | "url": "https://opencollective.com/postcss/"
908 | },
909 | {
910 | "type": "tidelift",
911 | "url": "https://tidelift.com/funding/github/npm/postcss"
912 | },
913 | {
914 | "type": "github",
915 | "url": "https://github.com/sponsors/ai"
916 | }
917 | ],
918 | "license": "MIT",
919 | "dependencies": {
920 | "nanoid": "^3.3.11",
921 | "picocolors": "^1.1.1",
922 | "source-map-js": "^1.2.1"
923 | },
924 | "engines": {
925 | "node": "^10 || ^12 || >=14"
926 | }
927 | },
928 | "node_modules/rollup": {
929 | "version": "4.53.3",
930 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz",
931 | "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
932 | "dev": true,
933 | "license": "MIT",
934 | "dependencies": {
935 | "@types/estree": "1.0.8"
936 | },
937 | "bin": {
938 | "rollup": "dist/bin/rollup"
939 | },
940 | "engines": {
941 | "node": ">=18.0.0",
942 | "npm": ">=8.0.0"
943 | },
944 | "optionalDependencies": {
945 | "@rollup/rollup-android-arm-eabi": "4.53.3",
946 | "@rollup/rollup-android-arm64": "4.53.3",
947 | "@rollup/rollup-darwin-arm64": "4.53.3",
948 | "@rollup/rollup-darwin-x64": "4.53.3",
949 | "@rollup/rollup-freebsd-arm64": "4.53.3",
950 | "@rollup/rollup-freebsd-x64": "4.53.3",
951 | "@rollup/rollup-linux-arm-gnueabihf": "4.53.3",
952 | "@rollup/rollup-linux-arm-musleabihf": "4.53.3",
953 | "@rollup/rollup-linux-arm64-gnu": "4.53.3",
954 | "@rollup/rollup-linux-arm64-musl": "4.53.3",
955 | "@rollup/rollup-linux-loong64-gnu": "4.53.3",
956 | "@rollup/rollup-linux-ppc64-gnu": "4.53.3",
957 | "@rollup/rollup-linux-riscv64-gnu": "4.53.3",
958 | "@rollup/rollup-linux-riscv64-musl": "4.53.3",
959 | "@rollup/rollup-linux-s390x-gnu": "4.53.3",
960 | "@rollup/rollup-linux-x64-gnu": "4.53.3",
961 | "@rollup/rollup-linux-x64-musl": "4.53.3",
962 | "@rollup/rollup-openharmony-arm64": "4.53.3",
963 | "@rollup/rollup-win32-arm64-msvc": "4.53.3",
964 | "@rollup/rollup-win32-ia32-msvc": "4.53.3",
965 | "@rollup/rollup-win32-x64-gnu": "4.53.3",
966 | "@rollup/rollup-win32-x64-msvc": "4.53.3",
967 | "fsevents": "~2.3.2"
968 | }
969 | },
970 | "node_modules/source-map-js": {
971 | "version": "1.2.1",
972 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
973 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
974 | "dev": true,
975 | "license": "BSD-3-Clause",
976 | "engines": {
977 | "node": ">=0.10.0"
978 | }
979 | },
980 | "node_modules/tinyglobby": {
981 | "version": "0.2.15",
982 | "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
983 | "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
984 | "dev": true,
985 | "license": "MIT",
986 | "dependencies": {
987 | "fdir": "^6.5.0",
988 | "picomatch": "^4.0.3"
989 | },
990 | "engines": {
991 | "node": ">=12.0.0"
992 | },
993 | "funding": {
994 | "url": "https://github.com/sponsors/SuperchupuDev"
995 | }
996 | },
997 | "node_modules/vite": {
998 | "version": "7.2.6",
999 | "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz",
1000 | "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==",
1001 | "dev": true,
1002 | "license": "MIT",
1003 | "dependencies": {
1004 | "esbuild": "^0.25.0",
1005 | "fdir": "^6.5.0",
1006 | "picomatch": "^4.0.3",
1007 | "postcss": "^8.5.6",
1008 | "rollup": "^4.43.0",
1009 | "tinyglobby": "^0.2.15"
1010 | },
1011 | "bin": {
1012 | "vite": "bin/vite.js"
1013 | },
1014 | "engines": {
1015 | "node": "^20.19.0 || >=22.12.0"
1016 | },
1017 | "funding": {
1018 | "url": "https://github.com/vitejs/vite?sponsor=1"
1019 | },
1020 | "optionalDependencies": {
1021 | "fsevents": "~2.3.3"
1022 | },
1023 | "peerDependencies": {
1024 | "@types/node": "^20.19.0 || >=22.12.0",
1025 | "jiti": ">=1.21.0",
1026 | "less": "^4.0.0",
1027 | "lightningcss": "^1.21.0",
1028 | "sass": "^1.70.0",
1029 | "sass-embedded": "^1.70.0",
1030 | "stylus": ">=0.54.8",
1031 | "sugarss": "^5.0.0",
1032 | "terser": "^5.16.0",
1033 | "tsx": "^4.8.1",
1034 | "yaml": "^2.4.2"
1035 | },
1036 | "peerDependenciesMeta": {
1037 | "@types/node": {
1038 | "optional": true
1039 | },
1040 | "jiti": {
1041 | "optional": true
1042 | },
1043 | "less": {
1044 | "optional": true
1045 | },
1046 | "lightningcss": {
1047 | "optional": true
1048 | },
1049 | "sass": {
1050 | "optional": true
1051 | },
1052 | "sass-embedded": {
1053 | "optional": true
1054 | },
1055 | "stylus": {
1056 | "optional": true
1057 | },
1058 | "sugarss": {
1059 | "optional": true
1060 | },
1061 | "terser": {
1062 | "optional": true
1063 | },
1064 | "tsx": {
1065 | "optional": true
1066 | },
1067 | "yaml": {
1068 | "optional": true
1069 | }
1070 | }
1071 | }
1072 | },
1073 | "dependencies": {
1074 | "@esbuild/aix-ppc64": {
1075 | "version": "0.25.4",
1076 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz",
1077 | "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==",
1078 | "dev": true,
1079 | "optional": true
1080 | },
1081 | "@esbuild/android-arm": {
1082 | "version": "0.25.4",
1083 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz",
1084 | "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==",
1085 | "dev": true,
1086 | "optional": true
1087 | },
1088 | "@esbuild/android-arm64": {
1089 | "version": "0.25.4",
1090 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz",
1091 | "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==",
1092 | "dev": true,
1093 | "optional": true
1094 | },
1095 | "@esbuild/android-x64": {
1096 | "version": "0.25.4",
1097 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz",
1098 | "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==",
1099 | "dev": true,
1100 | "optional": true
1101 | },
1102 | "@esbuild/darwin-arm64": {
1103 | "version": "0.25.4",
1104 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz",
1105 | "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==",
1106 | "dev": true,
1107 | "optional": true
1108 | },
1109 | "@esbuild/darwin-x64": {
1110 | "version": "0.25.4",
1111 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz",
1112 | "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==",
1113 | "dev": true,
1114 | "optional": true
1115 | },
1116 | "@esbuild/freebsd-arm64": {
1117 | "version": "0.25.4",
1118 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz",
1119 | "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==",
1120 | "dev": true,
1121 | "optional": true
1122 | },
1123 | "@esbuild/freebsd-x64": {
1124 | "version": "0.25.4",
1125 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz",
1126 | "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==",
1127 | "dev": true,
1128 | "optional": true
1129 | },
1130 | "@esbuild/linux-arm": {
1131 | "version": "0.25.4",
1132 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz",
1133 | "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==",
1134 | "dev": true,
1135 | "optional": true
1136 | },
1137 | "@esbuild/linux-arm64": {
1138 | "version": "0.25.4",
1139 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz",
1140 | "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==",
1141 | "dev": true,
1142 | "optional": true
1143 | },
1144 | "@esbuild/linux-ia32": {
1145 | "version": "0.25.4",
1146 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz",
1147 | "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==",
1148 | "dev": true,
1149 | "optional": true
1150 | },
1151 | "@esbuild/linux-loong64": {
1152 | "version": "0.25.4",
1153 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz",
1154 | "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==",
1155 | "dev": true,
1156 | "optional": true
1157 | },
1158 | "@esbuild/linux-mips64el": {
1159 | "version": "0.25.4",
1160 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz",
1161 | "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==",
1162 | "dev": true,
1163 | "optional": true
1164 | },
1165 | "@esbuild/linux-ppc64": {
1166 | "version": "0.25.4",
1167 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz",
1168 | "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==",
1169 | "dev": true,
1170 | "optional": true
1171 | },
1172 | "@esbuild/linux-riscv64": {
1173 | "version": "0.25.4",
1174 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz",
1175 | "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==",
1176 | "dev": true,
1177 | "optional": true
1178 | },
1179 | "@esbuild/linux-s390x": {
1180 | "version": "0.25.4",
1181 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz",
1182 | "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==",
1183 | "dev": true,
1184 | "optional": true
1185 | },
1186 | "@esbuild/linux-x64": {
1187 | "version": "0.25.4",
1188 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz",
1189 | "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==",
1190 | "dev": true,
1191 | "optional": true
1192 | },
1193 | "@esbuild/netbsd-arm64": {
1194 | "version": "0.25.4",
1195 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz",
1196 | "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==",
1197 | "dev": true,
1198 | "optional": true
1199 | },
1200 | "@esbuild/netbsd-x64": {
1201 | "version": "0.25.4",
1202 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz",
1203 | "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==",
1204 | "dev": true,
1205 | "optional": true
1206 | },
1207 | "@esbuild/openbsd-arm64": {
1208 | "version": "0.25.4",
1209 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz",
1210 | "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==",
1211 | "dev": true,
1212 | "optional": true
1213 | },
1214 | "@esbuild/openbsd-x64": {
1215 | "version": "0.25.4",
1216 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz",
1217 | "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==",
1218 | "dev": true,
1219 | "optional": true
1220 | },
1221 | "@esbuild/sunos-x64": {
1222 | "version": "0.25.4",
1223 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz",
1224 | "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==",
1225 | "dev": true,
1226 | "optional": true
1227 | },
1228 | "@esbuild/win32-arm64": {
1229 | "version": "0.25.4",
1230 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz",
1231 | "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==",
1232 | "dev": true,
1233 | "optional": true
1234 | },
1235 | "@esbuild/win32-ia32": {
1236 | "version": "0.25.4",
1237 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz",
1238 | "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==",
1239 | "dev": true,
1240 | "optional": true
1241 | },
1242 | "@esbuild/win32-x64": {
1243 | "version": "0.25.4",
1244 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz",
1245 | "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==",
1246 | "dev": true,
1247 | "optional": true
1248 | },
1249 | "@localnerve/debug": {
1250 | "version": "1.0.10",
1251 | "resolved": "https://registry.npmjs.org/@localnerve/debug/-/debug-1.0.10.tgz",
1252 | "integrity": "sha512-/ZmDemh/+DTmR5slBgpIKa+RyYFt5HTk93PvUw5+2yYmfhw0NAkk0U/QXz7FH5qJlNJB2Od9WKeiFdKkrftIhA=="
1253 | },
1254 | "@rollup/rollup-android-arm-eabi": {
1255 | "version": "4.53.3",
1256 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz",
1257 | "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==",
1258 | "dev": true,
1259 | "optional": true
1260 | },
1261 | "@rollup/rollup-android-arm64": {
1262 | "version": "4.53.3",
1263 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz",
1264 | "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==",
1265 | "dev": true,
1266 | "optional": true
1267 | },
1268 | "@rollup/rollup-darwin-arm64": {
1269 | "version": "4.53.3",
1270 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz",
1271 | "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==",
1272 | "dev": true,
1273 | "optional": true
1274 | },
1275 | "@rollup/rollup-darwin-x64": {
1276 | "version": "4.53.3",
1277 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz",
1278 | "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==",
1279 | "dev": true,
1280 | "optional": true
1281 | },
1282 | "@rollup/rollup-freebsd-arm64": {
1283 | "version": "4.53.3",
1284 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz",
1285 | "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==",
1286 | "dev": true,
1287 | "optional": true
1288 | },
1289 | "@rollup/rollup-freebsd-x64": {
1290 | "version": "4.53.3",
1291 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz",
1292 | "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==",
1293 | "dev": true,
1294 | "optional": true
1295 | },
1296 | "@rollup/rollup-linux-arm-gnueabihf": {
1297 | "version": "4.53.3",
1298 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz",
1299 | "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==",
1300 | "dev": true,
1301 | "optional": true
1302 | },
1303 | "@rollup/rollup-linux-arm-musleabihf": {
1304 | "version": "4.53.3",
1305 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz",
1306 | "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==",
1307 | "dev": true,
1308 | "optional": true
1309 | },
1310 | "@rollup/rollup-linux-arm64-gnu": {
1311 | "version": "4.53.3",
1312 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz",
1313 | "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==",
1314 | "dev": true,
1315 | "optional": true
1316 | },
1317 | "@rollup/rollup-linux-arm64-musl": {
1318 | "version": "4.53.3",
1319 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz",
1320 | "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==",
1321 | "dev": true,
1322 | "optional": true
1323 | },
1324 | "@rollup/rollup-linux-loong64-gnu": {
1325 | "version": "4.53.3",
1326 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz",
1327 | "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==",
1328 | "dev": true,
1329 | "optional": true
1330 | },
1331 | "@rollup/rollup-linux-ppc64-gnu": {
1332 | "version": "4.53.3",
1333 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz",
1334 | "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==",
1335 | "dev": true,
1336 | "optional": true
1337 | },
1338 | "@rollup/rollup-linux-riscv64-gnu": {
1339 | "version": "4.53.3",
1340 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz",
1341 | "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==",
1342 | "dev": true,
1343 | "optional": true
1344 | },
1345 | "@rollup/rollup-linux-riscv64-musl": {
1346 | "version": "4.53.3",
1347 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz",
1348 | "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==",
1349 | "dev": true,
1350 | "optional": true
1351 | },
1352 | "@rollup/rollup-linux-s390x-gnu": {
1353 | "version": "4.53.3",
1354 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz",
1355 | "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==",
1356 | "dev": true,
1357 | "optional": true
1358 | },
1359 | "@rollup/rollup-linux-x64-gnu": {
1360 | "version": "4.53.3",
1361 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz",
1362 | "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==",
1363 | "dev": true,
1364 | "optional": true
1365 | },
1366 | "@rollup/rollup-linux-x64-musl": {
1367 | "version": "4.53.3",
1368 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz",
1369 | "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==",
1370 | "dev": true,
1371 | "optional": true
1372 | },
1373 | "@rollup/rollup-openharmony-arm64": {
1374 | "version": "4.53.3",
1375 | "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz",
1376 | "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==",
1377 | "dev": true,
1378 | "optional": true
1379 | },
1380 | "@rollup/rollup-win32-arm64-msvc": {
1381 | "version": "4.53.3",
1382 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz",
1383 | "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==",
1384 | "dev": true,
1385 | "optional": true
1386 | },
1387 | "@rollup/rollup-win32-ia32-msvc": {
1388 | "version": "4.53.3",
1389 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz",
1390 | "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==",
1391 | "dev": true,
1392 | "optional": true
1393 | },
1394 | "@rollup/rollup-win32-x64-gnu": {
1395 | "version": "4.53.3",
1396 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz",
1397 | "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==",
1398 | "dev": true,
1399 | "optional": true
1400 | },
1401 | "@rollup/rollup-win32-x64-msvc": {
1402 | "version": "4.53.3",
1403 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz",
1404 | "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==",
1405 | "dev": true,
1406 | "optional": true
1407 | },
1408 | "@types/estree": {
1409 | "version": "1.0.8",
1410 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
1411 | "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
1412 | "dev": true
1413 | },
1414 | "debug": {
1415 | "version": "4.4.0",
1416 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
1417 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
1418 | "requires": {
1419 | "ms": "^2.1.3"
1420 | }
1421 | },
1422 | "esbuild": {
1423 | "version": "0.25.4",
1424 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz",
1425 | "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==",
1426 | "dev": true,
1427 | "requires": {
1428 | "@esbuild/aix-ppc64": "0.25.4",
1429 | "@esbuild/android-arm": "0.25.4",
1430 | "@esbuild/android-arm64": "0.25.4",
1431 | "@esbuild/android-x64": "0.25.4",
1432 | "@esbuild/darwin-arm64": "0.25.4",
1433 | "@esbuild/darwin-x64": "0.25.4",
1434 | "@esbuild/freebsd-arm64": "0.25.4",
1435 | "@esbuild/freebsd-x64": "0.25.4",
1436 | "@esbuild/linux-arm": "0.25.4",
1437 | "@esbuild/linux-arm64": "0.25.4",
1438 | "@esbuild/linux-ia32": "0.25.4",
1439 | "@esbuild/linux-loong64": "0.25.4",
1440 | "@esbuild/linux-mips64el": "0.25.4",
1441 | "@esbuild/linux-ppc64": "0.25.4",
1442 | "@esbuild/linux-riscv64": "0.25.4",
1443 | "@esbuild/linux-s390x": "0.25.4",
1444 | "@esbuild/linux-x64": "0.25.4",
1445 | "@esbuild/netbsd-arm64": "0.25.4",
1446 | "@esbuild/netbsd-x64": "0.25.4",
1447 | "@esbuild/openbsd-arm64": "0.25.4",
1448 | "@esbuild/openbsd-x64": "0.25.4",
1449 | "@esbuild/sunos-x64": "0.25.4",
1450 | "@esbuild/win32-arm64": "0.25.4",
1451 | "@esbuild/win32-ia32": "0.25.4",
1452 | "@esbuild/win32-x64": "0.25.4"
1453 | }
1454 | },
1455 | "fdir": {
1456 | "version": "6.5.0",
1457 | "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
1458 | "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
1459 | "dev": true,
1460 | "requires": {}
1461 | },
1462 | "fsevents": {
1463 | "version": "2.3.3",
1464 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
1465 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
1466 | "dev": true,
1467 | "optional": true
1468 | },
1469 | "ms": {
1470 | "version": "2.1.3",
1471 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1472 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
1473 | },
1474 | "nanoid": {
1475 | "version": "3.3.11",
1476 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
1477 | "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
1478 | "dev": true
1479 | },
1480 | "picocolors": {
1481 | "version": "1.1.1",
1482 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
1483 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
1484 | "dev": true
1485 | },
1486 | "picomatch": {
1487 | "version": "4.0.3",
1488 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
1489 | "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
1490 | "dev": true
1491 | },
1492 | "postcss": {
1493 | "version": "8.5.6",
1494 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
1495 | "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
1496 | "dev": true,
1497 | "requires": {
1498 | "nanoid": "^3.3.11",
1499 | "picocolors": "^1.1.1",
1500 | "source-map-js": "^1.2.1"
1501 | }
1502 | },
1503 | "rollup": {
1504 | "version": "4.53.3",
1505 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz",
1506 | "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
1507 | "dev": true,
1508 | "requires": {
1509 | "@rollup/rollup-android-arm-eabi": "4.53.3",
1510 | "@rollup/rollup-android-arm64": "4.53.3",
1511 | "@rollup/rollup-darwin-arm64": "4.53.3",
1512 | "@rollup/rollup-darwin-x64": "4.53.3",
1513 | "@rollup/rollup-freebsd-arm64": "4.53.3",
1514 | "@rollup/rollup-freebsd-x64": "4.53.3",
1515 | "@rollup/rollup-linux-arm-gnueabihf": "4.53.3",
1516 | "@rollup/rollup-linux-arm-musleabihf": "4.53.3",
1517 | "@rollup/rollup-linux-arm64-gnu": "4.53.3",
1518 | "@rollup/rollup-linux-arm64-musl": "4.53.3",
1519 | "@rollup/rollup-linux-loong64-gnu": "4.53.3",
1520 | "@rollup/rollup-linux-ppc64-gnu": "4.53.3",
1521 | "@rollup/rollup-linux-riscv64-gnu": "4.53.3",
1522 | "@rollup/rollup-linux-riscv64-musl": "4.53.3",
1523 | "@rollup/rollup-linux-s390x-gnu": "4.53.3",
1524 | "@rollup/rollup-linux-x64-gnu": "4.53.3",
1525 | "@rollup/rollup-linux-x64-musl": "4.53.3",
1526 | "@rollup/rollup-openharmony-arm64": "4.53.3",
1527 | "@rollup/rollup-win32-arm64-msvc": "4.53.3",
1528 | "@rollup/rollup-win32-ia32-msvc": "4.53.3",
1529 | "@rollup/rollup-win32-x64-gnu": "4.53.3",
1530 | "@rollup/rollup-win32-x64-msvc": "4.53.3",
1531 | "@types/estree": "1.0.8",
1532 | "fsevents": "~2.3.2"
1533 | }
1534 | },
1535 | "source-map-js": {
1536 | "version": "1.2.1",
1537 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1538 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1539 | "dev": true
1540 | },
1541 | "tinyglobby": {
1542 | "version": "0.2.15",
1543 | "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
1544 | "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
1545 | "dev": true,
1546 | "requires": {
1547 | "fdir": "^6.5.0",
1548 | "picomatch": "^4.0.3"
1549 | }
1550 | },
1551 | "vite": {
1552 | "version": "7.2.6",
1553 | "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz",
1554 | "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==",
1555 | "dev": true,
1556 | "requires": {
1557 | "esbuild": "^0.25.0",
1558 | "fdir": "^6.5.0",
1559 | "fsevents": "~2.3.3",
1560 | "picomatch": "^4.0.3",
1561 | "postcss": "^8.5.6",
1562 | "rollup": "^4.43.0",
1563 | "tinyglobby": "^0.2.15"
1564 | }
1565 | }
1566 | }
1567 | }
1568 |
--------------------------------------------------------------------------------