├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── README.md
├── __tests__
├── routes.spec.ts
├── setup.ts
└── utils.ts
├── example
├── .gitignore
├── index.html
├── package.json
├── pnpm-lock.yaml
├── src
│ ├── App.tsx
│ ├── main.tsx
│ ├── pages
│ │ ├── 404.tsx
│ │ ├── bar
│ │ │ └── [dynamic].jsx
│ │ ├── components
│ │ │ └── button.jsx
│ │ ├── contact.jsx
│ │ ├── error.tsx
│ │ ├── foo
│ │ │ ├── _type.jsx
│ │ │ ├── bar.jsx
│ │ │ ├── index.jsx
│ │ │ └── layout.jsx
│ │ ├── hyphen-name.tsx
│ │ ├── index.jsx
│ │ ├── layout.tsx
│ │ ├── sync.tsx
│ │ └── utils.tsx
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
├── index.ts
├── package.json
├── pnpm-lock.yaml
├── tsconfig.json
├── vite.config.ts
└── vitest.config.ts
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | - dev
8 | tags-ignore:
9 | - v*
10 | paths-ignore:
11 | - "**/README.md"
12 | pull_request:
13 | types:
14 | - open
15 | - reopened
16 | - synchronize
17 | - ready_for_review
18 | paths-ignore:
19 | - "**/README.md"
20 |
21 | concurrency:
22 | group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
23 | cancel-in-progress: true
24 |
25 | jobs:
26 | build:
27 | timeout-minutes: 20
28 | runs-on: ${{ matrix.os }}
29 | strategy:
30 | fail-fast: false
31 | matrix:
32 | os: [ubuntu-latest, macos-latest]
33 |
34 | steps:
35 | - uses: actions/checkout@v3
36 |
37 | - name: Install pnpm
38 | uses: pnpm/action-setup@v4
39 | with:
40 | version: 6.0.2
41 |
42 | - name: Set node version to ${{ matrix.node_version }}
43 | uses: actions/setup-node@v4
44 | with:
45 | node-version: 20
46 |
47 | - name: Install dependencies
48 | run: |
49 | pnpm install
50 | cd example
51 | pnpm install
52 | cd ..
53 |
54 | - name: Build
55 | run: pnpm build
56 |
57 | - name: Test
58 | run: pnpm test
59 |
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vite-plugin-react-views
2 | A vite plugin based on File System for creating routes automatically.
3 |
4 | Some rules you need to know:
5 | - Requirement: `react-router-dom@^6.9`
6 | - All files in conventional directory will become routes, except empty files and excluded files.
7 | - For code splitting, all routes will be imported dynamically by [lazy](https://reactrouter.com/en/dev/route/lazy), except layout route in root directory.
8 | - you can export `'Component'、'ErrorBoundary'、'loader'、'action', 'handle'、'shouldRevalidate'、'errorElement'、'id'` in every route file
9 | - A file starts with a `_` character or wraps by `[]` will be `dynamic route`.
10 | - Every file named `layout` in directory will become layout route.
11 | - The file named `404` in root directory will become `No Match(404) Route`.
12 |
13 | ### Installation
14 | ```js
15 | npm install vite-plugin-react-views --save-dev
16 | ```
17 |
18 | ### Usage
19 | ```js
20 | // vite.config.js
21 | import { defineConfig } from 'vite'
22 | import react from '@vitejs/plugin-react'
23 | import router from 'vite-plugin-react-views'
24 |
25 | export default defineConfig({
26 | plugins: [react(), router()]
27 | })
28 |
29 | // App.jsx
30 | import { RouterProvider, createBrowserRouter } from 'react-router-dom'
31 | // Requirement: import routes
32 | import routes from 'route-views'
33 |
34 | const router = createBrowserRouter(routes)
35 |
36 | export default function App() {
37 | return (
38 |
41 | )
42 | }
43 | ```
44 |
45 | ### Options
46 |
47 | - dir: string
48 |
49 | default: `'src/pages'`
50 |
51 | A directory path for crawling.
52 |
53 | - exclude(path): boolean
54 |
55 | A file will not become a route if return true.
56 |
57 | - sync(path): boolean
58 |
59 | A route will be imported synchronously if return true.
60 |
61 | - extensions: string[]
62 |
63 | default: `['js', 'jsx', 'ts', 'tsx']`
64 |
65 | Filename extensions which will be scanned and imported as route elements.
66 |
67 | ### Typescript
68 | ```js
69 | // src/vite-env.d.ts
70 | ///
71 |
72 | declare module 'route-views' {
73 | const routes: (import('react-router-dom').RouteObject)[];
74 |
75 | export default routes;
76 | }
77 | ```
78 |
79 | ### License
80 | MIT
81 |
--------------------------------------------------------------------------------
/__tests__/routes.spec.ts:
--------------------------------------------------------------------------------
1 | import { expect, test } from 'vitest'
2 | import { page } from './utils'
3 | import fs from 'node:fs'
4 | import path from 'node:path'
5 |
6 | test('/', async () => {
7 | expect(await page.textContent('.layout')).toBe('layout')
8 | expect(await page.textContent('.content')).toBe('index')
9 | })
10 |
11 | test('Test root layout\'s loader', async () => {
12 | expect(await page.textContent('.layout-loader-data')).toBe('root')
13 | })
14 |
15 | test('Test synchronous route', async () => {
16 | expect((await page.content()).includes('id="sync"')).toBeTruthy()
17 | })
18 |
19 | test('Nested layout should not be imported synchronously', async () => {
20 | expect((await page.content()).includes('id="foo_layout"')).toBeFalsy()
21 | })
22 |
23 | test('Should not create Route for excluded directory', async () => {
24 | await page.click('.excluded-components')
25 | expect(await page.textContent('.content')).toContain('404 Not Found')
26 | await page.goBack()
27 | })
28 |
29 | test('/contact', async () => {
30 | await page.click('.contact')
31 | expect(await page.textContent('.layout')).toBe('layout')
32 | expect(await page.textContent('.content')).toBe('contact')
33 | })
34 |
35 | test('/bar/:dynamic (test dynamic route format `[name]`)', async () => {
36 | await page.click('.bar-dynamic')
37 | expect(await page.textContent('.layout')).toBe('layout')
38 | expect(await page.textContent('.dynamic')).toBe('dynamic')
39 | })
40 |
41 | test('/foo', async () => {
42 | await page.click('.foo')
43 | expect(await page.textContent('.layout')).toBe('layout')
44 | expect(await page.textContent('.foo-layout')).toBe('layout-foo')
45 | expect(await page.textContent('.foo-content')).toBe('foo')
46 | })
47 |
48 | test('/foo/bar', async () => {
49 | await page.click('.foo-bar')
50 | expect(await page.textContent('.layout')).toBe('layout')
51 | expect(await page.textContent('.foo-layout')).toBe('layout-foo')
52 | expect(await page.textContent('.foo-content')).toBe('bar')
53 | })
54 |
55 | test('/foo/:type', async () => {
56 | await page.click('.foo-type')
57 | expect(await page.textContent('.layout')).toBe('layout')
58 | expect(await page.textContent('.foo-layout')).toBe('layout-foo')
59 | expect(await page.textContent('.foo-content')).toBe('a')
60 | })
61 |
62 | test('hyphen-name', async () => {
63 | await page.click('.hyphen-name')
64 | expect(await page.textContent('.layout')).toBe('layout')
65 | expect(await page.textContent('.content')).toBe('hyphen-name')
66 | })
67 |
68 | test('index', async () => {
69 | await page.click('.index')
70 | expect(await page.textContent('.layout')).toBe('layout')
71 | expect(await page.textContent('.content')).toBe('index')
72 | })
73 |
74 | test('/utils (exclude)', async () => {
75 | await page.click('.utils')
76 | expect(await page.textContent('.content')).toContain('404 Not Found')
77 |
78 | await page.goBack()
79 | expect(await page.textContent('.layout')).toBe('layout')
80 | expect(await page.textContent('.content')).toBe('index')
81 | })
82 |
83 | test('/error', async () => {
84 | await page.click('.error')
85 | expect(await page.textContent('.route-error')).toContain('Route Error')
86 |
87 | await page.goBack()
88 | })
89 |
90 | if (!process.env.VITEST_BUILD) {
91 | test('HMR', async () => {
92 | await page.click('.about')
93 | expect(await page.textContent('.content')).toContain('404 Not Found')
94 |
95 | const aboutFile = path.join(process.cwd(), 'example/src/pages/about.jsx')
96 | fs.writeFileSync(aboutFile, '')
97 | fs.writeFileSync(aboutFile, `export function Component() {
98 | return
about
99 | }`)
100 |
101 | expect(await page.textContent('.layout')).toBe('layout')
102 | expect(await page.textContent('.content')).toBe('about')
103 |
104 | fs.rmSync(aboutFile)
105 | })
106 | }
107 |
108 |
109 |
--------------------------------------------------------------------------------
/__tests__/setup.ts:
--------------------------------------------------------------------------------
1 | import path from 'node:path'
2 | import { chromium } from 'playwright-chromium'
3 | import { createServer, build, preview, loadConfigFromFile, mergeConfig } from 'vite'
4 | import { beforeAll } from 'vitest'
5 | import type { InlineConfig, ViteDevServer } from 'vite'
6 | import type { BrowserServer, Page, Browser } from 'playwright-chromium'
7 |
8 | const isBuild = !!process.env.VITEST_BUILD
9 | let testConfig: InlineConfig
10 | let server: ViteDevServer
11 |
12 | let browserServer: BrowserServer
13 | let browser: Browser
14 | export let page: Page
15 |
16 | beforeAll(async () => {
17 | browserServer = await chromium.launchServer()
18 | browser = await chromium.connect(browserServer.wsEndpoint())
19 | page = await browser.newPage()
20 |
21 | try {
22 | await startPrepare()
23 | } catch (e) {
24 | await server?.close()
25 | throw e
26 | }
27 |
28 | return async () => {
29 | await server?.close()
30 | await page.close()
31 | await browser.close()
32 | await browserServer.close()
33 | }
34 | })
35 |
36 | async function startPrepare() {
37 | const testDir = path.join(process.cwd(), 'example')
38 |
39 | const res = await loadConfigFromFile(
40 | {
41 | command: isBuild ? 'build' : 'serve',
42 | mode: isBuild ? 'production' : 'development'
43 | },
44 | undefined,
45 | testDir
46 | )
47 |
48 | const options: InlineConfig = {
49 | root: testDir,
50 | configFile: false,
51 | build: {
52 | target: 'esnext'
53 | }
54 | }
55 |
56 | testConfig = mergeConfig(options, res!.config)
57 | if (isBuild) {
58 | await build(testConfig)
59 | const previewServer = await preview(testConfig)
60 | await page.goto(previewServer.resolvedUrls.local[0]!)
61 | } else {
62 | server = await (await createServer(testConfig)).listen()
63 | await page.goto(`http://localhost:${server.config.server.port}`)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/__tests__/utils.ts:
--------------------------------------------------------------------------------
1 | export * from './setup'
2 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + React + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "v6.9",
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 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "react-router-dom": "^6.10.0"
15 | },
16 | "devDependencies": {
17 | "@types/node": "^22.1.0",
18 | "@types/react": "^18.3.3",
19 | "@types/react-dom": "^18.3.0",
20 | "@vitejs/plugin-react-swc": "^3.2.0",
21 | "typescript": "^5.5.4",
22 | "vite": "^5.3.5",
23 | "vite-plugin-react-views": "link:.."
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/example/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | dependencies:
11 | react:
12 | specifier: ^18.2.0
13 | version: 18.3.1
14 | react-dom:
15 | specifier: ^18.2.0
16 | version: 18.3.1(react@18.3.1)
17 | react-router-dom:
18 | specifier: ^6.10.0
19 | version: 6.26.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
20 | devDependencies:
21 | '@types/node':
22 | specifier: ^22.1.0
23 | version: 22.1.0
24 | '@types/react':
25 | specifier: ^18.3.3
26 | version: 18.3.3
27 | '@types/react-dom':
28 | specifier: ^18.3.0
29 | version: 18.3.0
30 | '@vitejs/plugin-react-swc':
31 | specifier: ^3.2.0
32 | version: 3.7.0(vite@5.3.5(@types/node@22.1.0))
33 | typescript:
34 | specifier: ^5.5.4
35 | version: 5.5.4
36 | vite:
37 | specifier: ^5.3.5
38 | version: 5.3.5(@types/node@22.1.0)
39 | vite-plugin-react-views:
40 | specifier: link:..
41 | version: link:..
42 |
43 | packages:
44 |
45 | '@esbuild/aix-ppc64@0.21.5':
46 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
47 | engines: {node: '>=12'}
48 | cpu: [ppc64]
49 | os: [aix]
50 |
51 | '@esbuild/android-arm64@0.21.5':
52 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
53 | engines: {node: '>=12'}
54 | cpu: [arm64]
55 | os: [android]
56 |
57 | '@esbuild/android-arm@0.21.5':
58 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
59 | engines: {node: '>=12'}
60 | cpu: [arm]
61 | os: [android]
62 |
63 | '@esbuild/android-x64@0.21.5':
64 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
65 | engines: {node: '>=12'}
66 | cpu: [x64]
67 | os: [android]
68 |
69 | '@esbuild/darwin-arm64@0.21.5':
70 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
71 | engines: {node: '>=12'}
72 | cpu: [arm64]
73 | os: [darwin]
74 |
75 | '@esbuild/darwin-x64@0.21.5':
76 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
77 | engines: {node: '>=12'}
78 | cpu: [x64]
79 | os: [darwin]
80 |
81 | '@esbuild/freebsd-arm64@0.21.5':
82 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
83 | engines: {node: '>=12'}
84 | cpu: [arm64]
85 | os: [freebsd]
86 |
87 | '@esbuild/freebsd-x64@0.21.5':
88 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
89 | engines: {node: '>=12'}
90 | cpu: [x64]
91 | os: [freebsd]
92 |
93 | '@esbuild/linux-arm64@0.21.5':
94 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
95 | engines: {node: '>=12'}
96 | cpu: [arm64]
97 | os: [linux]
98 |
99 | '@esbuild/linux-arm@0.21.5':
100 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
101 | engines: {node: '>=12'}
102 | cpu: [arm]
103 | os: [linux]
104 |
105 | '@esbuild/linux-ia32@0.21.5':
106 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
107 | engines: {node: '>=12'}
108 | cpu: [ia32]
109 | os: [linux]
110 |
111 | '@esbuild/linux-loong64@0.21.5':
112 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
113 | engines: {node: '>=12'}
114 | cpu: [loong64]
115 | os: [linux]
116 |
117 | '@esbuild/linux-mips64el@0.21.5':
118 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
119 | engines: {node: '>=12'}
120 | cpu: [mips64el]
121 | os: [linux]
122 |
123 | '@esbuild/linux-ppc64@0.21.5':
124 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
125 | engines: {node: '>=12'}
126 | cpu: [ppc64]
127 | os: [linux]
128 |
129 | '@esbuild/linux-riscv64@0.21.5':
130 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
131 | engines: {node: '>=12'}
132 | cpu: [riscv64]
133 | os: [linux]
134 |
135 | '@esbuild/linux-s390x@0.21.5':
136 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
137 | engines: {node: '>=12'}
138 | cpu: [s390x]
139 | os: [linux]
140 |
141 | '@esbuild/linux-x64@0.21.5':
142 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
143 | engines: {node: '>=12'}
144 | cpu: [x64]
145 | os: [linux]
146 |
147 | '@esbuild/netbsd-x64@0.21.5':
148 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
149 | engines: {node: '>=12'}
150 | cpu: [x64]
151 | os: [netbsd]
152 |
153 | '@esbuild/openbsd-x64@0.21.5':
154 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
155 | engines: {node: '>=12'}
156 | cpu: [x64]
157 | os: [openbsd]
158 |
159 | '@esbuild/sunos-x64@0.21.5':
160 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
161 | engines: {node: '>=12'}
162 | cpu: [x64]
163 | os: [sunos]
164 |
165 | '@esbuild/win32-arm64@0.21.5':
166 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
167 | engines: {node: '>=12'}
168 | cpu: [arm64]
169 | os: [win32]
170 |
171 | '@esbuild/win32-ia32@0.21.5':
172 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
173 | engines: {node: '>=12'}
174 | cpu: [ia32]
175 | os: [win32]
176 |
177 | '@esbuild/win32-x64@0.21.5':
178 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
179 | engines: {node: '>=12'}
180 | cpu: [x64]
181 | os: [win32]
182 |
183 | '@remix-run/router@1.19.0':
184 | resolution: {integrity: sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==}
185 | engines: {node: '>=14.0.0'}
186 |
187 | '@rollup/rollup-android-arm-eabi@4.20.0':
188 | resolution: {integrity: sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==}
189 | cpu: [arm]
190 | os: [android]
191 |
192 | '@rollup/rollup-android-arm64@4.20.0':
193 | resolution: {integrity: sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==}
194 | cpu: [arm64]
195 | os: [android]
196 |
197 | '@rollup/rollup-darwin-arm64@4.20.0':
198 | resolution: {integrity: sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==}
199 | cpu: [arm64]
200 | os: [darwin]
201 |
202 | '@rollup/rollup-darwin-x64@4.20.0':
203 | resolution: {integrity: sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==}
204 | cpu: [x64]
205 | os: [darwin]
206 |
207 | '@rollup/rollup-linux-arm-gnueabihf@4.20.0':
208 | resolution: {integrity: sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==}
209 | cpu: [arm]
210 | os: [linux]
211 | libc: [glibc]
212 |
213 | '@rollup/rollup-linux-arm-musleabihf@4.20.0':
214 | resolution: {integrity: sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==}
215 | cpu: [arm]
216 | os: [linux]
217 | libc: [musl]
218 |
219 | '@rollup/rollup-linux-arm64-gnu@4.20.0':
220 | resolution: {integrity: sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==}
221 | cpu: [arm64]
222 | os: [linux]
223 | libc: [glibc]
224 |
225 | '@rollup/rollup-linux-arm64-musl@4.20.0':
226 | resolution: {integrity: sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==}
227 | cpu: [arm64]
228 | os: [linux]
229 | libc: [musl]
230 |
231 | '@rollup/rollup-linux-powerpc64le-gnu@4.20.0':
232 | resolution: {integrity: sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==}
233 | cpu: [ppc64]
234 | os: [linux]
235 | libc: [glibc]
236 |
237 | '@rollup/rollup-linux-riscv64-gnu@4.20.0':
238 | resolution: {integrity: sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==}
239 | cpu: [riscv64]
240 | os: [linux]
241 | libc: [glibc]
242 |
243 | '@rollup/rollup-linux-s390x-gnu@4.20.0':
244 | resolution: {integrity: sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==}
245 | cpu: [s390x]
246 | os: [linux]
247 | libc: [glibc]
248 |
249 | '@rollup/rollup-linux-x64-gnu@4.20.0':
250 | resolution: {integrity: sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==}
251 | cpu: [x64]
252 | os: [linux]
253 | libc: [glibc]
254 |
255 | '@rollup/rollup-linux-x64-musl@4.20.0':
256 | resolution: {integrity: sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==}
257 | cpu: [x64]
258 | os: [linux]
259 | libc: [musl]
260 |
261 | '@rollup/rollup-win32-arm64-msvc@4.20.0':
262 | resolution: {integrity: sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==}
263 | cpu: [arm64]
264 | os: [win32]
265 |
266 | '@rollup/rollup-win32-ia32-msvc@4.20.0':
267 | resolution: {integrity: sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==}
268 | cpu: [ia32]
269 | os: [win32]
270 |
271 | '@rollup/rollup-win32-x64-msvc@4.20.0':
272 | resolution: {integrity: sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==}
273 | cpu: [x64]
274 | os: [win32]
275 |
276 | '@swc/core-darwin-arm64@1.7.5':
277 | resolution: {integrity: sha512-Y+bvW9C4/u26DskMbtQKT4FU6QQenaDYkKDi028vDIKAa7v1NZqYG9wmhD/Ih7n5EUy2uJ5I5EWD7WaoLzT6PA==}
278 | engines: {node: '>=10'}
279 | cpu: [arm64]
280 | os: [darwin]
281 |
282 | '@swc/core-darwin-x64@1.7.5':
283 | resolution: {integrity: sha512-AuIbDlcaAhYS6mtF4UqvXgrLeAfXZbVf4pgtgShPbutF80VbCQiIB55zOFz5aZdCpsBVuCWcBq0zLneK+VQKkQ==}
284 | engines: {node: '>=10'}
285 | cpu: [x64]
286 | os: [darwin]
287 |
288 | '@swc/core-linux-arm-gnueabihf@1.7.5':
289 | resolution: {integrity: sha512-99uBPHITRqgGwCXAjHY94VaV3Z40+D2NQNgR1t6xQpO8ZnevI6YSzX6GVZfBnV7+7oisiGkrVEwfIRRa+1s8FA==}
290 | engines: {node: '>=10'}
291 | cpu: [arm]
292 | os: [linux]
293 |
294 | '@swc/core-linux-arm64-gnu@1.7.5':
295 | resolution: {integrity: sha512-xHL3Erlz+OGGCG4h6K2HWiR56H5UYMuBWWPbbUufi2bJpfhuKQy/X3vWffwL8ZVfJmCUwr4/G91GHcm32uYzRg==}
296 | engines: {node: '>=10'}
297 | cpu: [arm64]
298 | os: [linux]
299 | libc: [glibc]
300 |
301 | '@swc/core-linux-arm64-musl@1.7.5':
302 | resolution: {integrity: sha512-5ArGdqvFMszNHdi4a67vopeYq8d1K+FuTWDrblHrAvZFhAyv+GQz2PnKqYOgl0sWmQxsNPfNwBFtxACpUO3Jzg==}
303 | engines: {node: '>=10'}
304 | cpu: [arm64]
305 | os: [linux]
306 | libc: [musl]
307 |
308 | '@swc/core-linux-x64-gnu@1.7.5':
309 | resolution: {integrity: sha512-mSVVV/PFzCGtI1nVQQyx34NwCMgSurF6ZX/me8pUAX054vsE/pSFL66xN+kQOe/1Z/LOd4UmXFkZ/EzOSnYcSg==}
310 | engines: {node: '>=10'}
311 | cpu: [x64]
312 | os: [linux]
313 | libc: [glibc]
314 |
315 | '@swc/core-linux-x64-musl@1.7.5':
316 | resolution: {integrity: sha512-09hY3ZKMUORXVunESKS9yuP78+gQbr759GKHo8wyCdtAx8lCZdEjfI5NtC7/1VqwfeE32/U6u+5MBTVhZTt0AA==}
317 | engines: {node: '>=10'}
318 | cpu: [x64]
319 | os: [linux]
320 | libc: [musl]
321 |
322 | '@swc/core-win32-arm64-msvc@1.7.5':
323 | resolution: {integrity: sha512-B/UDtPI3RlYRFW42xQxOpl6kI/9LtkD7No+XeRIKQTPe15EP2o+rUlv7CmKljVBXgJ8KmaQbZlaEh1YP+QZEEQ==}
324 | engines: {node: '>=10'}
325 | cpu: [arm64]
326 | os: [win32]
327 |
328 | '@swc/core-win32-ia32-msvc@1.7.5':
329 | resolution: {integrity: sha512-BgLesVGmIY6Nub/sURqtSRvWYcbCE/ACfuZB3bZHVKD6nsZJJuOpdB8oC41fZPyc8yZUzL3XTBIifkT2RP+w9w==}
330 | engines: {node: '>=10'}
331 | cpu: [ia32]
332 | os: [win32]
333 |
334 | '@swc/core-win32-x64-msvc@1.7.5':
335 | resolution: {integrity: sha512-CnF557tidLfQRPczcqDJ8x+LBQYsFa0Ra6w2+YU1iFUboaI2jJVuqt3vEChu80y6JiRIBAaaV2L/GawDJh1dIQ==}
336 | engines: {node: '>=10'}
337 | cpu: [x64]
338 | os: [win32]
339 |
340 | '@swc/core@1.7.5':
341 | resolution: {integrity: sha512-qKK0/Ta4qvxs/ok3XyYVPT7OBenwRn1sSINf1cKQTBHPqr7U/uB4k2GTl6JgEs8H4PiJrMTNWfMLTucIoVSfAg==}
342 | engines: {node: '>=10'}
343 | peerDependencies:
344 | '@swc/helpers': '*'
345 | peerDependenciesMeta:
346 | '@swc/helpers':
347 | optional: true
348 |
349 | '@swc/counter@0.1.3':
350 | resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
351 |
352 | '@swc/types@0.1.12':
353 | resolution: {integrity: sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==}
354 |
355 | '@types/estree@1.0.5':
356 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
357 |
358 | '@types/node@22.1.0':
359 | resolution: {integrity: sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==}
360 |
361 | '@types/prop-types@15.7.12':
362 | resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
363 |
364 | '@types/react-dom@18.3.0':
365 | resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==}
366 |
367 | '@types/react@18.3.3':
368 | resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
369 |
370 | '@vitejs/plugin-react-swc@3.7.0':
371 | resolution: {integrity: sha512-yrknSb3Dci6svCd/qhHqhFPDSw0QtjumcqdKMoNNzmOl5lMXTTiqzjWtG4Qask2HdvvzaNgSunbQGet8/GrKdA==}
372 | peerDependencies:
373 | vite: ^4 || ^5
374 |
375 | csstype@3.1.3:
376 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
377 |
378 | esbuild@0.21.5:
379 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
380 | engines: {node: '>=12'}
381 | hasBin: true
382 |
383 | fsevents@2.3.3:
384 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
385 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
386 | os: [darwin]
387 |
388 | js-tokens@4.0.0:
389 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
390 |
391 | loose-envify@1.4.0:
392 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
393 | hasBin: true
394 |
395 | nanoid@3.3.7:
396 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
397 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
398 | hasBin: true
399 |
400 | picocolors@1.0.1:
401 | resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
402 |
403 | postcss@8.4.40:
404 | resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==}
405 | engines: {node: ^10 || ^12 || >=14}
406 |
407 | react-dom@18.3.1:
408 | resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
409 | peerDependencies:
410 | react: ^18.3.1
411 |
412 | react-router-dom@6.26.0:
413 | resolution: {integrity: sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==}
414 | engines: {node: '>=14.0.0'}
415 | peerDependencies:
416 | react: '>=16.8'
417 | react-dom: '>=16.8'
418 |
419 | react-router@6.26.0:
420 | resolution: {integrity: sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==}
421 | engines: {node: '>=14.0.0'}
422 | peerDependencies:
423 | react: '>=16.8'
424 |
425 | react@18.3.1:
426 | resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
427 | engines: {node: '>=0.10.0'}
428 |
429 | rollup@4.20.0:
430 | resolution: {integrity: sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==}
431 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
432 | hasBin: true
433 |
434 | scheduler@0.23.2:
435 | resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
436 |
437 | source-map-js@1.2.0:
438 | resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
439 | engines: {node: '>=0.10.0'}
440 |
441 | typescript@5.5.4:
442 | resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
443 | engines: {node: '>=14.17'}
444 | hasBin: true
445 |
446 | undici-types@6.13.0:
447 | resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==}
448 |
449 | vite@5.3.5:
450 | resolution: {integrity: sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==}
451 | engines: {node: ^18.0.0 || >=20.0.0}
452 | hasBin: true
453 | peerDependencies:
454 | '@types/node': ^18.0.0 || >=20.0.0
455 | less: '*'
456 | lightningcss: ^1.21.0
457 | sass: '*'
458 | stylus: '*'
459 | sugarss: '*'
460 | terser: ^5.4.0
461 | peerDependenciesMeta:
462 | '@types/node':
463 | optional: true
464 | less:
465 | optional: true
466 | lightningcss:
467 | optional: true
468 | sass:
469 | optional: true
470 | stylus:
471 | optional: true
472 | sugarss:
473 | optional: true
474 | terser:
475 | optional: true
476 |
477 | snapshots:
478 |
479 | '@esbuild/aix-ppc64@0.21.5':
480 | optional: true
481 |
482 | '@esbuild/android-arm64@0.21.5':
483 | optional: true
484 |
485 | '@esbuild/android-arm@0.21.5':
486 | optional: true
487 |
488 | '@esbuild/android-x64@0.21.5':
489 | optional: true
490 |
491 | '@esbuild/darwin-arm64@0.21.5':
492 | optional: true
493 |
494 | '@esbuild/darwin-x64@0.21.5':
495 | optional: true
496 |
497 | '@esbuild/freebsd-arm64@0.21.5':
498 | optional: true
499 |
500 | '@esbuild/freebsd-x64@0.21.5':
501 | optional: true
502 |
503 | '@esbuild/linux-arm64@0.21.5':
504 | optional: true
505 |
506 | '@esbuild/linux-arm@0.21.5':
507 | optional: true
508 |
509 | '@esbuild/linux-ia32@0.21.5':
510 | optional: true
511 |
512 | '@esbuild/linux-loong64@0.21.5':
513 | optional: true
514 |
515 | '@esbuild/linux-mips64el@0.21.5':
516 | optional: true
517 |
518 | '@esbuild/linux-ppc64@0.21.5':
519 | optional: true
520 |
521 | '@esbuild/linux-riscv64@0.21.5':
522 | optional: true
523 |
524 | '@esbuild/linux-s390x@0.21.5':
525 | optional: true
526 |
527 | '@esbuild/linux-x64@0.21.5':
528 | optional: true
529 |
530 | '@esbuild/netbsd-x64@0.21.5':
531 | optional: true
532 |
533 | '@esbuild/openbsd-x64@0.21.5':
534 | optional: true
535 |
536 | '@esbuild/sunos-x64@0.21.5':
537 | optional: true
538 |
539 | '@esbuild/win32-arm64@0.21.5':
540 | optional: true
541 |
542 | '@esbuild/win32-ia32@0.21.5':
543 | optional: true
544 |
545 | '@esbuild/win32-x64@0.21.5':
546 | optional: true
547 |
548 | '@remix-run/router@1.19.0': {}
549 |
550 | '@rollup/rollup-android-arm-eabi@4.20.0':
551 | optional: true
552 |
553 | '@rollup/rollup-android-arm64@4.20.0':
554 | optional: true
555 |
556 | '@rollup/rollup-darwin-arm64@4.20.0':
557 | optional: true
558 |
559 | '@rollup/rollup-darwin-x64@4.20.0':
560 | optional: true
561 |
562 | '@rollup/rollup-linux-arm-gnueabihf@4.20.0':
563 | optional: true
564 |
565 | '@rollup/rollup-linux-arm-musleabihf@4.20.0':
566 | optional: true
567 |
568 | '@rollup/rollup-linux-arm64-gnu@4.20.0':
569 | optional: true
570 |
571 | '@rollup/rollup-linux-arm64-musl@4.20.0':
572 | optional: true
573 |
574 | '@rollup/rollup-linux-powerpc64le-gnu@4.20.0':
575 | optional: true
576 |
577 | '@rollup/rollup-linux-riscv64-gnu@4.20.0':
578 | optional: true
579 |
580 | '@rollup/rollup-linux-s390x-gnu@4.20.0':
581 | optional: true
582 |
583 | '@rollup/rollup-linux-x64-gnu@4.20.0':
584 | optional: true
585 |
586 | '@rollup/rollup-linux-x64-musl@4.20.0':
587 | optional: true
588 |
589 | '@rollup/rollup-win32-arm64-msvc@4.20.0':
590 | optional: true
591 |
592 | '@rollup/rollup-win32-ia32-msvc@4.20.0':
593 | optional: true
594 |
595 | '@rollup/rollup-win32-x64-msvc@4.20.0':
596 | optional: true
597 |
598 | '@swc/core-darwin-arm64@1.7.5':
599 | optional: true
600 |
601 | '@swc/core-darwin-x64@1.7.5':
602 | optional: true
603 |
604 | '@swc/core-linux-arm-gnueabihf@1.7.5':
605 | optional: true
606 |
607 | '@swc/core-linux-arm64-gnu@1.7.5':
608 | optional: true
609 |
610 | '@swc/core-linux-arm64-musl@1.7.5':
611 | optional: true
612 |
613 | '@swc/core-linux-x64-gnu@1.7.5':
614 | optional: true
615 |
616 | '@swc/core-linux-x64-musl@1.7.5':
617 | optional: true
618 |
619 | '@swc/core-win32-arm64-msvc@1.7.5':
620 | optional: true
621 |
622 | '@swc/core-win32-ia32-msvc@1.7.5':
623 | optional: true
624 |
625 | '@swc/core-win32-x64-msvc@1.7.5':
626 | optional: true
627 |
628 | '@swc/core@1.7.5':
629 | dependencies:
630 | '@swc/counter': 0.1.3
631 | '@swc/types': 0.1.12
632 | optionalDependencies:
633 | '@swc/core-darwin-arm64': 1.7.5
634 | '@swc/core-darwin-x64': 1.7.5
635 | '@swc/core-linux-arm-gnueabihf': 1.7.5
636 | '@swc/core-linux-arm64-gnu': 1.7.5
637 | '@swc/core-linux-arm64-musl': 1.7.5
638 | '@swc/core-linux-x64-gnu': 1.7.5
639 | '@swc/core-linux-x64-musl': 1.7.5
640 | '@swc/core-win32-arm64-msvc': 1.7.5
641 | '@swc/core-win32-ia32-msvc': 1.7.5
642 | '@swc/core-win32-x64-msvc': 1.7.5
643 |
644 | '@swc/counter@0.1.3': {}
645 |
646 | '@swc/types@0.1.12':
647 | dependencies:
648 | '@swc/counter': 0.1.3
649 |
650 | '@types/estree@1.0.5': {}
651 |
652 | '@types/node@22.1.0':
653 | dependencies:
654 | undici-types: 6.13.0
655 |
656 | '@types/prop-types@15.7.12': {}
657 |
658 | '@types/react-dom@18.3.0':
659 | dependencies:
660 | '@types/react': 18.3.3
661 |
662 | '@types/react@18.3.3':
663 | dependencies:
664 | '@types/prop-types': 15.7.12
665 | csstype: 3.1.3
666 |
667 | '@vitejs/plugin-react-swc@3.7.0(vite@5.3.5(@types/node@22.1.0))':
668 | dependencies:
669 | '@swc/core': 1.7.5
670 | vite: 5.3.5(@types/node@22.1.0)
671 | transitivePeerDependencies:
672 | - '@swc/helpers'
673 |
674 | csstype@3.1.3: {}
675 |
676 | esbuild@0.21.5:
677 | optionalDependencies:
678 | '@esbuild/aix-ppc64': 0.21.5
679 | '@esbuild/android-arm': 0.21.5
680 | '@esbuild/android-arm64': 0.21.5
681 | '@esbuild/android-x64': 0.21.5
682 | '@esbuild/darwin-arm64': 0.21.5
683 | '@esbuild/darwin-x64': 0.21.5
684 | '@esbuild/freebsd-arm64': 0.21.5
685 | '@esbuild/freebsd-x64': 0.21.5
686 | '@esbuild/linux-arm': 0.21.5
687 | '@esbuild/linux-arm64': 0.21.5
688 | '@esbuild/linux-ia32': 0.21.5
689 | '@esbuild/linux-loong64': 0.21.5
690 | '@esbuild/linux-mips64el': 0.21.5
691 | '@esbuild/linux-ppc64': 0.21.5
692 | '@esbuild/linux-riscv64': 0.21.5
693 | '@esbuild/linux-s390x': 0.21.5
694 | '@esbuild/linux-x64': 0.21.5
695 | '@esbuild/netbsd-x64': 0.21.5
696 | '@esbuild/openbsd-x64': 0.21.5
697 | '@esbuild/sunos-x64': 0.21.5
698 | '@esbuild/win32-arm64': 0.21.5
699 | '@esbuild/win32-ia32': 0.21.5
700 | '@esbuild/win32-x64': 0.21.5
701 |
702 | fsevents@2.3.3:
703 | optional: true
704 |
705 | js-tokens@4.0.0: {}
706 |
707 | loose-envify@1.4.0:
708 | dependencies:
709 | js-tokens: 4.0.0
710 |
711 | nanoid@3.3.7: {}
712 |
713 | picocolors@1.0.1: {}
714 |
715 | postcss@8.4.40:
716 | dependencies:
717 | nanoid: 3.3.7
718 | picocolors: 1.0.1
719 | source-map-js: 1.2.0
720 |
721 | react-dom@18.3.1(react@18.3.1):
722 | dependencies:
723 | loose-envify: 1.4.0
724 | react: 18.3.1
725 | scheduler: 0.23.2
726 |
727 | react-router-dom@6.26.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
728 | dependencies:
729 | '@remix-run/router': 1.19.0
730 | react: 18.3.1
731 | react-dom: 18.3.1(react@18.3.1)
732 | react-router: 6.26.0(react@18.3.1)
733 |
734 | react-router@6.26.0(react@18.3.1):
735 | dependencies:
736 | '@remix-run/router': 1.19.0
737 | react: 18.3.1
738 |
739 | react@18.3.1:
740 | dependencies:
741 | loose-envify: 1.4.0
742 |
743 | rollup@4.20.0:
744 | dependencies:
745 | '@types/estree': 1.0.5
746 | optionalDependencies:
747 | '@rollup/rollup-android-arm-eabi': 4.20.0
748 | '@rollup/rollup-android-arm64': 4.20.0
749 | '@rollup/rollup-darwin-arm64': 4.20.0
750 | '@rollup/rollup-darwin-x64': 4.20.0
751 | '@rollup/rollup-linux-arm-gnueabihf': 4.20.0
752 | '@rollup/rollup-linux-arm-musleabihf': 4.20.0
753 | '@rollup/rollup-linux-arm64-gnu': 4.20.0
754 | '@rollup/rollup-linux-arm64-musl': 4.20.0
755 | '@rollup/rollup-linux-powerpc64le-gnu': 4.20.0
756 | '@rollup/rollup-linux-riscv64-gnu': 4.20.0
757 | '@rollup/rollup-linux-s390x-gnu': 4.20.0
758 | '@rollup/rollup-linux-x64-gnu': 4.20.0
759 | '@rollup/rollup-linux-x64-musl': 4.20.0
760 | '@rollup/rollup-win32-arm64-msvc': 4.20.0
761 | '@rollup/rollup-win32-ia32-msvc': 4.20.0
762 | '@rollup/rollup-win32-x64-msvc': 4.20.0
763 | fsevents: 2.3.3
764 |
765 | scheduler@0.23.2:
766 | dependencies:
767 | loose-envify: 1.4.0
768 |
769 | source-map-js@1.2.0: {}
770 |
771 | typescript@5.5.4: {}
772 |
773 | undici-types@6.13.0: {}
774 |
775 | vite@5.3.5(@types/node@22.1.0):
776 | dependencies:
777 | esbuild: 0.21.5
778 | postcss: 8.4.40
779 | rollup: 4.20.0
780 | optionalDependencies:
781 | '@types/node': 22.1.0
782 | fsevents: 2.3.3
783 |
--------------------------------------------------------------------------------
/example/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { RouterProvider, createBrowserRouter } from 'react-router-dom'
2 | import routes from 'route-views'
3 |
4 | const router = createBrowserRouter(routes)
5 |
6 | function App() {
7 | return (
8 |
11 | )
12 | }
13 |
14 | export default App
15 |
--------------------------------------------------------------------------------
/example/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import App from './App'
4 |
5 | ReactDOM.createRoot(document.getElementById('root')!).render(
6 |
7 |
8 |
9 | )
10 |
--------------------------------------------------------------------------------
/example/src/pages/404.tsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | return (
3 | 404 Not Found
4 | )
5 | }
--------------------------------------------------------------------------------
/example/src/pages/bar/[dynamic].jsx:
--------------------------------------------------------------------------------
1 | import { useParams } from 'react-router-dom'
2 |
3 | export function Component() {
4 | const { dynamic } = useParams()
5 |
6 | return {dynamic}
7 | }
8 |
9 | if (import.meta.env.DEV) {
10 | Component.displayName = 'Dynamic'
11 | }
12 |
--------------------------------------------------------------------------------
/example/src/pages/components/button.jsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | return 'button'
3 | }
4 |
5 | if (import.meta.env.DEV) {
6 | Component.displayName = 'Button'
7 | }
8 |
--------------------------------------------------------------------------------
/example/src/pages/contact.jsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | return contact
3 | }
4 |
5 | if (import.meta.env.DEV) {
6 | Component.displayName = 'Contact'
7 | }
8 |
--------------------------------------------------------------------------------
/example/src/pages/error.tsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | throw new Error('route-error')
3 | }
--------------------------------------------------------------------------------
/example/src/pages/foo/_type.jsx:
--------------------------------------------------------------------------------
1 | import { useParams } from 'react-router-dom'
2 |
3 | export function Component() {
4 | const { type } = useParams()
5 |
6 | return {type}
7 | }
8 |
9 | if (import.meta.env.DEV) {
10 | Component.displayName = 'Type'
11 | }
12 |
--------------------------------------------------------------------------------
/example/src/pages/foo/bar.jsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | return bar
3 | }
4 |
5 | if (import.meta.env.DEV) {
6 | Component.displayName = 'Bar'
7 | }
8 |
--------------------------------------------------------------------------------
/example/src/pages/foo/index.jsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | return foo
3 | }
4 |
5 | if (import.meta.env.DEV) {
6 | Component.displayName = 'Foo'
7 | }
8 |
--------------------------------------------------------------------------------
/example/src/pages/foo/layout.jsx:
--------------------------------------------------------------------------------
1 | import { Outlet } from 'react-router-dom'
2 |
3 | const el = document.createElement('div')
4 | el.id = 'foo_layout'
5 | document.body.appendChild(el)
6 |
7 | export function Component() {
8 | return (
9 | <>
10 | layout-foo
11 |
12 | >
13 | )
14 | }
15 |
16 | if (import.meta.env.DEV) {
17 | Component.displayName = 'FooLayout'
18 | }
19 |
--------------------------------------------------------------------------------
/example/src/pages/hyphen-name.tsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | return hyphen-name
3 | }
4 |
5 | if (import.meta.env.DEV) {
6 | Component.displayName = 'HyphenName'
7 | }
8 |
--------------------------------------------------------------------------------
/example/src/pages/index.jsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | return index
3 | }
4 |
5 | if (import.meta.env.DEV) {
6 | Component.displayName = 'Home'
7 | }
8 |
--------------------------------------------------------------------------------
/example/src/pages/layout.tsx:
--------------------------------------------------------------------------------
1 | import { Outlet, Link, useRouteLoaderData } from 'react-router-dom'
2 |
3 | export const id = '/'
4 |
5 | export function loader() {
6 | return {
7 | root: 'root'
8 | }
9 | }
10 |
11 | export function handle() {}
12 |
13 | export function action() {}
14 |
15 | export function ErrorBoundary() {
16 | return (
17 | Route Error
18 | )
19 | }
20 |
21 | export function shouldRevalidate() {
22 | return false
23 | }
24 |
25 | export function Component() {
26 | const data = useRouteLoaderData('/') as { root: string }
27 |
28 | return (
29 | <>
30 |
31 | index{' '}
32 | /contact{' '}
33 | /about{' '}
34 | /utils{' '}
35 | /foo{' '}
36 | /foo/bar{' '}
37 | /foo/:type{' '}
38 | /bar/:dynamic{' '}
39 | /hyphen-name{' '}
40 | /excluded/components
41 | /error
42 |
43 | layout
44 | {data.root}
45 |
46 | >
47 | )
48 | }
49 |
50 | if (import.meta.env.DEV) {
51 | Component.displayName = 'Layout'
52 | }
53 |
--------------------------------------------------------------------------------
/example/src/pages/sync.tsx:
--------------------------------------------------------------------------------
1 | const el = document.createElement('div')
2 | el.id = 'sync'
3 | document.body.appendChild(el)
4 |
5 | export function Component() {
6 | return 'sync'
7 | }
8 |
9 | if (import.meta.env.DEV) {
10 | Component.displayName = 'SyncRoute'
11 | }
12 |
--------------------------------------------------------------------------------
/example/src/pages/utils.tsx:
--------------------------------------------------------------------------------
1 | export function Component() {
2 | return 'utils'
3 | }
4 |
5 | if (import.meta.env.DEV) {
6 | Component.displayName = 'Utils'
7 | }
8 |
--------------------------------------------------------------------------------
/example/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module 'route-views' {
4 | const routes: (import('react-router-dom').RouteObject)[];
5 |
6 | export default routes;
7 | }
8 |
--------------------------------------------------------------------------------
/example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/example/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/example/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react-swc'
3 | import router from 'vite-plugin-react-views'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig({
7 | plugins: [
8 | react(),
9 | router({
10 | exclude(path) {
11 | return path.includes('utils') || path.includes('components')
12 | },
13 | sync(path) {
14 | return path.includes('sync') || path.includes('foo') || path.includes('hyphen-name')
15 | }
16 | })
17 | ],
18 | })
19 |
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | import fs from 'node:fs'
2 | import path from 'node:path'
3 | import { init, parse } from 'es-module-lexer'
4 | import { transformWithEsbuild, normalizePath } from 'vite'
5 | import type { PluginOption, ResolvedConfig, EsbuildTransformOptions } from 'vite'
6 | import type { RouteObject } from 'react-router-dom'
7 |
8 | interface Options {
9 | dir?: string;
10 | exclude?(path: string): boolean;
11 | sync?(path: string): boolean;
12 | extensions?: string[];
13 | }
14 |
15 | function readContent(id: string) {
16 | return fs.readFileSync(id).toString().trim()
17 | }
18 |
19 | function join(...rest: string[]) {
20 | return normalizePath(path.join(...rest))
21 | }
22 |
23 | function getComponentPrefix(path: string) {
24 | return path
25 | .slice(0)
26 | .split('/')
27 | .map(segment => segment
28 | .replace(/^([a-z])/, (_, $1) => $1.toUpperCase())
29 | .replace(/[^a-zA-Z0-9_$]/g, '_')
30 | )
31 | .join('')
32 | }
33 |
34 | function removeExt(file: string) {
35 | return file.slice(0, file.length - path.extname(file).length)
36 | }
37 |
38 | function toDynamic(segment: string) {
39 | return segment.replace(/^(?:_(.+)|\[(.+)\])$/, (_, $1, $2) => `:${$1 || $2}`)
40 | }
41 |
42 | const splitMark = '__'
43 | const routeArgs = ['Component', 'ErrorBoundary', 'loader', 'action', 'handle', 'shouldRevalidate', 'errorElement', 'id']
44 | const re = new RegExp(`"(\\(\\) => import\\(.+\\))"|: "(.+${splitMark}(?:${routeArgs.join('|')}))"`, 'g')
45 |
46 | function VitePluginReactRouter(opts: Options = {}): PluginOption {
47 | const {
48 | dir = 'src/pages',
49 | exclude,
50 | sync,
51 | extensions = ['js', 'jsx', 'ts', 'tsx']
52 | } = opts
53 |
54 | let _config: ResolvedConfig
55 | let originDirPath: string
56 | const ROUTE_RE = new RegExp(`\\.(${extensions.join('|')})$`)
57 | const MODULE_NAME = 'route-views'
58 | const VIRTUAL_MODULE = '\0' + MODULE_NAME + `.${extensions[1]}`
59 | const emptyFiles = new Set()
60 | const nonEmptyFiles = new Set()
61 |
62 | async function createRoutes() {
63 | originDirPath = join(_config.root, dir)
64 | let stackDirs = [originDirPath]
65 | let stackFiles: string[][] = []
66 | let stackIndexs: number[] = []
67 |
68 | let currentFiles = fs.readdirSync(originDirPath)
69 | let currentIndex = 0
70 |
71 | let workFile: string | undefined = currentFiles[currentIndex++]
72 | let workRoute: RouteObject = { path: '/', children: [] }
73 | let stackRoutes: RouteObject[] = [workRoute]
74 |
75 | let syncRoutesMap: Record> = {}
76 |
77 | async function parseRoute(code: string, id: string, routePath: string) {
78 | const result = await transformWithEsbuild(code, id, {
79 | loader: path.extname(id).slice(1) as EsbuildTransformOptions['loader']
80 | })
81 |
82 | let prefix = getComponentPrefix(removeExt(routePath))
83 | const route: Record = {}
84 |
85 | try {
86 | await init
87 | const [, exports] = parse(result.code)
88 | for (const e of exports) {
89 | const key = e.n as keyof RouteObject
90 | if (routeArgs.includes(key)) {
91 | route[key] = prefix + splitMark + key
92 | }
93 | }
94 | } catch (error) {
95 | console.error(`[parse error]: `, error)
96 | }
97 |
98 | syncRoutesMap[id] = { ...route }
99 | return route
100 | }
101 |
102 | const getElement = async (id: string, code?: string, routePath?: string, sync?: boolean) => {
103 | if (sync) {
104 | return await parseRoute(code!, id, routePath!)
105 | }
106 |
107 | return { lazy: `() => import('${id}')` as any }
108 | }
109 |
110 | while (workFile != null) {
111 | const filePath = join(...stackDirs, workFile)
112 | const routePath = filePath.slice(originDirPath.length)
113 | const stat = fs.statSync(filePath)
114 |
115 | if (stat.isDirectory() && !exclude?.(routePath)) {
116 | const nextFiles = fs.readdirSync(filePath)
117 |
118 | if (nextFiles.length) {
119 | stackDirs.push(workFile)
120 | stackFiles.push(currentFiles)
121 | stackIndexs.push(currentIndex)
122 |
123 | const len: number = workRoute.children!.push({ path: workFile, children: [] })
124 | stackRoutes.push(workRoute)
125 |
126 | workRoute = workRoute.children![len - 1]!
127 | currentIndex = 0
128 | currentFiles = nextFiles
129 | }
130 | } else if (ROUTE_RE.test(workFile) && !exclude?.(removeExt(routePath))) {
131 | const content = readContent(filePath)
132 | if (content) {
133 | nonEmptyFiles.add(filePath)
134 | const segment = removeExt(workFile)
135 | const isRoot = stackFiles.length === 0
136 |
137 | if (segment === 'layout') {
138 | Object.assign(workRoute, await getElement(filePath, content, routePath, isRoot))
139 | } else {
140 | const route = await getElement(filePath, content, routePath, sync?.(routePath)) as RouteObject
141 |
142 | if (isRoot && segment === '404') {
143 | route.path = '*'
144 | stackRoutes.push(route)
145 | } else {
146 | if (segment === 'index') {
147 | route.index = true
148 | } else {
149 | route.path = toDynamic(segment)
150 | }
151 |
152 | workRoute.children?.push(route)
153 | }
154 | }
155 | } else {
156 | emptyFiles.add(filePath)
157 | }
158 | }
159 |
160 | while (currentIndex != null && currentFiles && currentIndex >= currentFiles.length) {
161 | currentFiles = stackFiles.pop()!
162 | currentIndex = stackIndexs.pop()!
163 | workRoute = stackRoutes.pop()!
164 | stackDirs.pop()
165 | }
166 |
167 | if (currentFiles && currentFiles.length) {
168 | workFile = currentFiles[currentIndex++]
169 | } else {
170 | workFile = undefined
171 | }
172 | }
173 |
174 | return { routes: stackRoutes.concat(workRoute), syncRoutesMap }
175 | }
176 |
177 | return {
178 | name: 'vite-plugin-react-views',
179 | enforce: 'post',
180 | configResolved(c) {
181 | _config = c
182 | },
183 | configureServer(server) {
184 | function handleFileChange(path: string) {
185 | path = normalizePath(removeExt(path))
186 |
187 | if (path.includes(dir) && !exclude?.(path.slice(originDirPath.length))) {
188 | const mod = server.moduleGraph.getModuleById(VIRTUAL_MODULE)
189 | if (mod) {
190 | server.moduleGraph.invalidateModule(mod)
191 | }
192 |
193 | server.ws.send({ type: 'full-reload' })
194 | }
195 | }
196 |
197 | server.watcher.on('add', handleFileChange)
198 | server.watcher.on('unlink', handleFileChange)
199 | server.watcher.on('change', (path) => {
200 | path = normalizePath(path)
201 | const content = readContent(path)
202 |
203 | if (emptyFiles.has(path) && content) {
204 | emptyFiles.delete(path)
205 | nonEmptyFiles.add(path)
206 | handleFileChange(path)
207 | } else if (nonEmptyFiles.has(path) && !content) {
208 | emptyFiles.add(path)
209 | nonEmptyFiles.delete(path)
210 | handleFileChange(path)
211 | }
212 | })
213 | },
214 | resolveId(id: string) {
215 | if (id === MODULE_NAME) {
216 | return VIRTUAL_MODULE
217 | }
218 | },
219 | async load(id) {
220 | if (id === VIRTUAL_MODULE) {
221 | const { routes, syncRoutesMap } = await createRoutes()
222 |
223 | return `${Object.keys(syncRoutesMap).map(id => {
224 | const route = syncRoutesMap[id]
225 | return `import { ${Object.keys(route).map(routeKey => `${routeKey} as ${route[routeKey]}`).join(', ')} } from '${id}'`
226 | }).join('\n')}
227 |
228 | export default ${JSON.stringify(routes, null, 2)
229 | .replace(re, (_, $1, $2) => $2 ? `: ${$2}` : $1)}`
230 | }
231 | },
232 | }
233 | }
234 |
235 | export default VitePluginReactRouter
236 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite-plugin-react-views",
3 | "version": "2.1.1",
4 | "description": "A vite plugin based on File System for creating routes automatically.",
5 | "main": "./dist/index.js",
6 | "type": "module",
7 | "types": "./dist/index.d.ts",
8 | "scripts": {
9 | "dev": "vite build --watch",
10 | "build": "vite build && tsc",
11 | "test": "pnpm test-serve && pnpm test-build",
12 | "test-serve": "vitest run",
13 | "test-build": "VITEST_BUILD=1 vitest run"
14 | },
15 | "homepage": "https://github.com/KAROTT7/vite-plugin-react-views",
16 | "keywords": [
17 | "vite",
18 | "vite-plugin",
19 | "react",
20 | "router",
21 | "react-router"
22 | ],
23 | "exports": {
24 | "import": "./dist/index.js",
25 | "require": "./dist/index.cjs",
26 | "types": "./dist/index.d.ts"
27 | },
28 | "files": [
29 | "dist"
30 | ],
31 | "author": "KAROTT7",
32 | "license": "MIT",
33 | "dependencies": {
34 | "es-module-lexer": "^1.2.1"
35 | },
36 | "devDependencies": {
37 | "@types/node": "^22.1.0",
38 | "@types/react": "^18.0.28",
39 | "playwright-chromium": "^1.27.1",
40 | "react-router-dom": ">=6.9.0",
41 | "typescript": "^5.5.4",
42 | "vite": "^5.3.5",
43 | "vitest": "^2.0.5"
44 | },
45 | "peerDependencies": {
46 | "react-router-dom": ">=6.9.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | dependencies:
11 | es-module-lexer:
12 | specifier: ^1.2.1
13 | version: 1.5.4
14 | devDependencies:
15 | '@types/node':
16 | specifier: ^22.1.0
17 | version: 22.1.0
18 | '@types/react':
19 | specifier: ^18.0.28
20 | version: 18.3.3
21 | playwright-chromium:
22 | specifier: ^1.27.1
23 | version: 1.45.3
24 | react-router-dom:
25 | specifier: '>=6.9.0'
26 | version: 6.26.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
27 | typescript:
28 | specifier: ^5.5.4
29 | version: 5.5.4
30 | vite:
31 | specifier: ^5.3.5
32 | version: 5.3.5(@types/node@22.1.0)
33 | vitest:
34 | specifier: ^2.0.5
35 | version: 2.0.5(@types/node@22.1.0)
36 |
37 | packages:
38 |
39 | '@ampproject/remapping@2.3.0':
40 | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
41 | engines: {node: '>=6.0.0'}
42 |
43 | '@esbuild/aix-ppc64@0.21.5':
44 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
45 | engines: {node: '>=12'}
46 | cpu: [ppc64]
47 | os: [aix]
48 |
49 | '@esbuild/android-arm64@0.21.5':
50 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
51 | engines: {node: '>=12'}
52 | cpu: [arm64]
53 | os: [android]
54 |
55 | '@esbuild/android-arm@0.21.5':
56 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
57 | engines: {node: '>=12'}
58 | cpu: [arm]
59 | os: [android]
60 |
61 | '@esbuild/android-x64@0.21.5':
62 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
63 | engines: {node: '>=12'}
64 | cpu: [x64]
65 | os: [android]
66 |
67 | '@esbuild/darwin-arm64@0.21.5':
68 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
69 | engines: {node: '>=12'}
70 | cpu: [arm64]
71 | os: [darwin]
72 |
73 | '@esbuild/darwin-x64@0.21.5':
74 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
75 | engines: {node: '>=12'}
76 | cpu: [x64]
77 | os: [darwin]
78 |
79 | '@esbuild/freebsd-arm64@0.21.5':
80 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
81 | engines: {node: '>=12'}
82 | cpu: [arm64]
83 | os: [freebsd]
84 |
85 | '@esbuild/freebsd-x64@0.21.5':
86 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
87 | engines: {node: '>=12'}
88 | cpu: [x64]
89 | os: [freebsd]
90 |
91 | '@esbuild/linux-arm64@0.21.5':
92 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
93 | engines: {node: '>=12'}
94 | cpu: [arm64]
95 | os: [linux]
96 |
97 | '@esbuild/linux-arm@0.21.5':
98 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
99 | engines: {node: '>=12'}
100 | cpu: [arm]
101 | os: [linux]
102 |
103 | '@esbuild/linux-ia32@0.21.5':
104 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
105 | engines: {node: '>=12'}
106 | cpu: [ia32]
107 | os: [linux]
108 |
109 | '@esbuild/linux-loong64@0.21.5':
110 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
111 | engines: {node: '>=12'}
112 | cpu: [loong64]
113 | os: [linux]
114 |
115 | '@esbuild/linux-mips64el@0.21.5':
116 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
117 | engines: {node: '>=12'}
118 | cpu: [mips64el]
119 | os: [linux]
120 |
121 | '@esbuild/linux-ppc64@0.21.5':
122 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
123 | engines: {node: '>=12'}
124 | cpu: [ppc64]
125 | os: [linux]
126 |
127 | '@esbuild/linux-riscv64@0.21.5':
128 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
129 | engines: {node: '>=12'}
130 | cpu: [riscv64]
131 | os: [linux]
132 |
133 | '@esbuild/linux-s390x@0.21.5':
134 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
135 | engines: {node: '>=12'}
136 | cpu: [s390x]
137 | os: [linux]
138 |
139 | '@esbuild/linux-x64@0.21.5':
140 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
141 | engines: {node: '>=12'}
142 | cpu: [x64]
143 | os: [linux]
144 |
145 | '@esbuild/netbsd-x64@0.21.5':
146 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
147 | engines: {node: '>=12'}
148 | cpu: [x64]
149 | os: [netbsd]
150 |
151 | '@esbuild/openbsd-x64@0.21.5':
152 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
153 | engines: {node: '>=12'}
154 | cpu: [x64]
155 | os: [openbsd]
156 |
157 | '@esbuild/sunos-x64@0.21.5':
158 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
159 | engines: {node: '>=12'}
160 | cpu: [x64]
161 | os: [sunos]
162 |
163 | '@esbuild/win32-arm64@0.21.5':
164 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
165 | engines: {node: '>=12'}
166 | cpu: [arm64]
167 | os: [win32]
168 |
169 | '@esbuild/win32-ia32@0.21.5':
170 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
171 | engines: {node: '>=12'}
172 | cpu: [ia32]
173 | os: [win32]
174 |
175 | '@esbuild/win32-x64@0.21.5':
176 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
177 | engines: {node: '>=12'}
178 | cpu: [x64]
179 | os: [win32]
180 |
181 | '@jridgewell/gen-mapping@0.3.5':
182 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
183 | engines: {node: '>=6.0.0'}
184 |
185 | '@jridgewell/resolve-uri@3.1.2':
186 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
187 | engines: {node: '>=6.0.0'}
188 |
189 | '@jridgewell/set-array@1.2.1':
190 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
191 | engines: {node: '>=6.0.0'}
192 |
193 | '@jridgewell/sourcemap-codec@1.5.0':
194 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
195 |
196 | '@jridgewell/trace-mapping@0.3.25':
197 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
198 |
199 | '@remix-run/router@1.19.0':
200 | resolution: {integrity: sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==}
201 | engines: {node: '>=14.0.0'}
202 |
203 | '@rollup/rollup-android-arm-eabi@4.20.0':
204 | resolution: {integrity: sha512-TSpWzflCc4VGAUJZlPpgAJE1+V60MePDQnBd7PPkpuEmOy8i87aL6tinFGKBFKuEDikYpig72QzdT3QPYIi+oA==}
205 | cpu: [arm]
206 | os: [android]
207 |
208 | '@rollup/rollup-android-arm64@4.20.0':
209 | resolution: {integrity: sha512-u00Ro/nok7oGzVuh/FMYfNoGqxU5CPWz1mxV85S2w9LxHR8OoMQBuSk+3BKVIDYgkpeOET5yXkx90OYFc+ytpQ==}
210 | cpu: [arm64]
211 | os: [android]
212 |
213 | '@rollup/rollup-darwin-arm64@4.20.0':
214 | resolution: {integrity: sha512-uFVfvzvsdGtlSLuL0ZlvPJvl6ZmrH4CBwLGEFPe7hUmf7htGAN+aXo43R/V6LATyxlKVC/m6UsLb7jbG+LG39Q==}
215 | cpu: [arm64]
216 | os: [darwin]
217 |
218 | '@rollup/rollup-darwin-x64@4.20.0':
219 | resolution: {integrity: sha512-xbrMDdlev53vNXexEa6l0LffojxhqDTBeL+VUxuuIXys4x6xyvbKq5XqTXBCEUA8ty8iEJblHvFaWRJTk/icAQ==}
220 | cpu: [x64]
221 | os: [darwin]
222 |
223 | '@rollup/rollup-linux-arm-gnueabihf@4.20.0':
224 | resolution: {integrity: sha512-jMYvxZwGmoHFBTbr12Xc6wOdc2xA5tF5F2q6t7Rcfab68TT0n+r7dgawD4qhPEvasDsVpQi+MgDzj2faOLsZjA==}
225 | cpu: [arm]
226 | os: [linux]
227 | libc: [glibc]
228 |
229 | '@rollup/rollup-linux-arm-musleabihf@4.20.0':
230 | resolution: {integrity: sha512-1asSTl4HKuIHIB1GcdFHNNZhxAYEdqML/MW4QmPS4G0ivbEcBr1JKlFLKsIRqjSwOBkdItn3/ZDlyvZ/N6KPlw==}
231 | cpu: [arm]
232 | os: [linux]
233 | libc: [musl]
234 |
235 | '@rollup/rollup-linux-arm64-gnu@4.20.0':
236 | resolution: {integrity: sha512-COBb8Bkx56KldOYJfMf6wKeYJrtJ9vEgBRAOkfw6Ens0tnmzPqvlpjZiLgkhg6cA3DGzCmLmmd319pmHvKWWlQ==}
237 | cpu: [arm64]
238 | os: [linux]
239 | libc: [glibc]
240 |
241 | '@rollup/rollup-linux-arm64-musl@4.20.0':
242 | resolution: {integrity: sha512-+it+mBSyMslVQa8wSPvBx53fYuZK/oLTu5RJoXogjk6x7Q7sz1GNRsXWjn6SwyJm8E/oMjNVwPhmNdIjwP135Q==}
243 | cpu: [arm64]
244 | os: [linux]
245 | libc: [musl]
246 |
247 | '@rollup/rollup-linux-powerpc64le-gnu@4.20.0':
248 | resolution: {integrity: sha512-yAMvqhPfGKsAxHN8I4+jE0CpLWD8cv4z7CK7BMmhjDuz606Q2tFKkWRY8bHR9JQXYcoLfopo5TTqzxgPUjUMfw==}
249 | cpu: [ppc64]
250 | os: [linux]
251 | libc: [glibc]
252 |
253 | '@rollup/rollup-linux-riscv64-gnu@4.20.0':
254 | resolution: {integrity: sha512-qmuxFpfmi/2SUkAw95TtNq/w/I7Gpjurx609OOOV7U4vhvUhBcftcmXwl3rqAek+ADBwSjIC4IVNLiszoj3dPA==}
255 | cpu: [riscv64]
256 | os: [linux]
257 | libc: [glibc]
258 |
259 | '@rollup/rollup-linux-s390x-gnu@4.20.0':
260 | resolution: {integrity: sha512-I0BtGXddHSHjV1mqTNkgUZLnS3WtsqebAXv11D5BZE/gfw5KoyXSAXVqyJximQXNvNzUo4GKlCK/dIwXlz+jlg==}
261 | cpu: [s390x]
262 | os: [linux]
263 | libc: [glibc]
264 |
265 | '@rollup/rollup-linux-x64-gnu@4.20.0':
266 | resolution: {integrity: sha512-y+eoL2I3iphUg9tN9GB6ku1FA8kOfmF4oUEWhztDJ4KXJy1agk/9+pejOuZkNFhRwHAOxMsBPLbXPd6mJiCwew==}
267 | cpu: [x64]
268 | os: [linux]
269 | libc: [glibc]
270 |
271 | '@rollup/rollup-linux-x64-musl@4.20.0':
272 | resolution: {integrity: sha512-hM3nhW40kBNYUkZb/r9k2FKK+/MnKglX7UYd4ZUy5DJs8/sMsIbqWK2piZtVGE3kcXVNj3B2IrUYROJMMCikNg==}
273 | cpu: [x64]
274 | os: [linux]
275 | libc: [musl]
276 |
277 | '@rollup/rollup-win32-arm64-msvc@4.20.0':
278 | resolution: {integrity: sha512-psegMvP+Ik/Bg7QRJbv8w8PAytPA7Uo8fpFjXyCRHWm6Nt42L+JtoqH8eDQ5hRP7/XW2UiIriy1Z46jf0Oa1kA==}
279 | cpu: [arm64]
280 | os: [win32]
281 |
282 | '@rollup/rollup-win32-ia32-msvc@4.20.0':
283 | resolution: {integrity: sha512-GabekH3w4lgAJpVxkk7hUzUf2hICSQO0a/BLFA11/RMxQT92MabKAqyubzDZmMOC/hcJNlc+rrypzNzYl4Dx7A==}
284 | cpu: [ia32]
285 | os: [win32]
286 |
287 | '@rollup/rollup-win32-x64-msvc@4.20.0':
288 | resolution: {integrity: sha512-aJ1EJSuTdGnM6qbVC4B5DSmozPTqIag9fSzXRNNo+humQLG89XpPgdt16Ia56ORD7s+H8Pmyx44uczDQ0yDzpg==}
289 | cpu: [x64]
290 | os: [win32]
291 |
292 | '@types/estree@1.0.5':
293 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
294 |
295 | '@types/node@22.1.0':
296 | resolution: {integrity: sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==}
297 |
298 | '@types/prop-types@15.7.12':
299 | resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
300 |
301 | '@types/react@18.3.3':
302 | resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==}
303 |
304 | '@vitest/expect@2.0.5':
305 | resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==}
306 |
307 | '@vitest/pretty-format@2.0.5':
308 | resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==}
309 |
310 | '@vitest/runner@2.0.5':
311 | resolution: {integrity: sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig==}
312 |
313 | '@vitest/snapshot@2.0.5':
314 | resolution: {integrity: sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew==}
315 |
316 | '@vitest/spy@2.0.5':
317 | resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==}
318 |
319 | '@vitest/utils@2.0.5':
320 | resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==}
321 |
322 | assertion-error@2.0.1:
323 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
324 | engines: {node: '>=12'}
325 |
326 | cac@6.7.14:
327 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
328 | engines: {node: '>=8'}
329 |
330 | chai@5.1.1:
331 | resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==}
332 | engines: {node: '>=12'}
333 |
334 | check-error@2.1.1:
335 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
336 | engines: {node: '>= 16'}
337 |
338 | cross-spawn@7.0.3:
339 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
340 | engines: {node: '>= 8'}
341 |
342 | csstype@3.1.3:
343 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
344 |
345 | debug@4.3.6:
346 | resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
347 | engines: {node: '>=6.0'}
348 | peerDependencies:
349 | supports-color: '*'
350 | peerDependenciesMeta:
351 | supports-color:
352 | optional: true
353 |
354 | deep-eql@5.0.2:
355 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
356 | engines: {node: '>=6'}
357 |
358 | es-module-lexer@1.5.4:
359 | resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
360 |
361 | esbuild@0.21.5:
362 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
363 | engines: {node: '>=12'}
364 | hasBin: true
365 |
366 | estree-walker@3.0.3:
367 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
368 |
369 | execa@8.0.1:
370 | resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
371 | engines: {node: '>=16.17'}
372 |
373 | fsevents@2.3.3:
374 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
375 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
376 | os: [darwin]
377 |
378 | get-func-name@2.0.2:
379 | resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==}
380 |
381 | get-stream@8.0.1:
382 | resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
383 | engines: {node: '>=16'}
384 |
385 | human-signals@5.0.0:
386 | resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
387 | engines: {node: '>=16.17.0'}
388 |
389 | is-stream@3.0.0:
390 | resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
391 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
392 |
393 | isexe@2.0.0:
394 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
395 |
396 | js-tokens@4.0.0:
397 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
398 |
399 | loose-envify@1.4.0:
400 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
401 | hasBin: true
402 |
403 | loupe@3.1.1:
404 | resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==}
405 |
406 | magic-string@0.30.11:
407 | resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
408 |
409 | merge-stream@2.0.0:
410 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
411 |
412 | mimic-fn@4.0.0:
413 | resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
414 | engines: {node: '>=12'}
415 |
416 | ms@2.1.2:
417 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
418 |
419 | nanoid@3.3.7:
420 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
421 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
422 | hasBin: true
423 |
424 | npm-run-path@5.3.0:
425 | resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
426 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
427 |
428 | onetime@6.0.0:
429 | resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
430 | engines: {node: '>=12'}
431 |
432 | path-key@3.1.1:
433 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
434 | engines: {node: '>=8'}
435 |
436 | path-key@4.0.0:
437 | resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
438 | engines: {node: '>=12'}
439 |
440 | pathe@1.1.2:
441 | resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
442 |
443 | pathval@2.0.0:
444 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==}
445 | engines: {node: '>= 14.16'}
446 |
447 | picocolors@1.0.1:
448 | resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
449 |
450 | playwright-chromium@1.45.3:
451 | resolution: {integrity: sha512-GXY/+1HScU5soR06lu8sc7cnXWBnfWDGH2JV+D3wqxApb9qJbSxDK40H8loOok+naxMO7x6yhgPHwpRSCV9dug==}
452 | engines: {node: '>=18'}
453 | hasBin: true
454 |
455 | playwright-core@1.45.3:
456 | resolution: {integrity: sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==}
457 | engines: {node: '>=18'}
458 | hasBin: true
459 |
460 | postcss@8.4.40:
461 | resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==}
462 | engines: {node: ^10 || ^12 || >=14}
463 |
464 | react-dom@18.3.1:
465 | resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
466 | peerDependencies:
467 | react: ^18.3.1
468 |
469 | react-router-dom@6.26.0:
470 | resolution: {integrity: sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==}
471 | engines: {node: '>=14.0.0'}
472 | peerDependencies:
473 | react: '>=16.8'
474 | react-dom: '>=16.8'
475 |
476 | react-router@6.26.0:
477 | resolution: {integrity: sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==}
478 | engines: {node: '>=14.0.0'}
479 | peerDependencies:
480 | react: '>=16.8'
481 |
482 | react@18.3.1:
483 | resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
484 | engines: {node: '>=0.10.0'}
485 |
486 | rollup@4.20.0:
487 | resolution: {integrity: sha512-6rbWBChcnSGzIlXeIdNIZTopKYad8ZG8ajhl78lGRLsI2rX8IkaotQhVas2Ma+GPxJav19wrSzvRvuiv0YKzWw==}
488 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
489 | hasBin: true
490 |
491 | scheduler@0.23.2:
492 | resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
493 |
494 | shebang-command@2.0.0:
495 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
496 | engines: {node: '>=8'}
497 |
498 | shebang-regex@3.0.0:
499 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
500 | engines: {node: '>=8'}
501 |
502 | siginfo@2.0.0:
503 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
504 |
505 | signal-exit@4.1.0:
506 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
507 | engines: {node: '>=14'}
508 |
509 | source-map-js@1.2.0:
510 | resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
511 | engines: {node: '>=0.10.0'}
512 |
513 | stackback@0.0.2:
514 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
515 |
516 | std-env@3.7.0:
517 | resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==}
518 |
519 | strip-final-newline@3.0.0:
520 | resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
521 | engines: {node: '>=12'}
522 |
523 | tinybench@2.9.0:
524 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
525 |
526 | tinypool@1.0.0:
527 | resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==}
528 | engines: {node: ^18.0.0 || >=20.0.0}
529 |
530 | tinyrainbow@1.2.0:
531 | resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
532 | engines: {node: '>=14.0.0'}
533 |
534 | tinyspy@3.0.0:
535 | resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==}
536 | engines: {node: '>=14.0.0'}
537 |
538 | typescript@5.5.4:
539 | resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
540 | engines: {node: '>=14.17'}
541 | hasBin: true
542 |
543 | undici-types@6.13.0:
544 | resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==}
545 |
546 | vite-node@2.0.5:
547 | resolution: {integrity: sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==}
548 | engines: {node: ^18.0.0 || >=20.0.0}
549 | hasBin: true
550 |
551 | vite@5.3.5:
552 | resolution: {integrity: sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==}
553 | engines: {node: ^18.0.0 || >=20.0.0}
554 | hasBin: true
555 | peerDependencies:
556 | '@types/node': ^18.0.0 || >=20.0.0
557 | less: '*'
558 | lightningcss: ^1.21.0
559 | sass: '*'
560 | stylus: '*'
561 | sugarss: '*'
562 | terser: ^5.4.0
563 | peerDependenciesMeta:
564 | '@types/node':
565 | optional: true
566 | less:
567 | optional: true
568 | lightningcss:
569 | optional: true
570 | sass:
571 | optional: true
572 | stylus:
573 | optional: true
574 | sugarss:
575 | optional: true
576 | terser:
577 | optional: true
578 |
579 | vitest@2.0.5:
580 | resolution: {integrity: sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA==}
581 | engines: {node: ^18.0.0 || >=20.0.0}
582 | hasBin: true
583 | peerDependencies:
584 | '@edge-runtime/vm': '*'
585 | '@types/node': ^18.0.0 || >=20.0.0
586 | '@vitest/browser': 2.0.5
587 | '@vitest/ui': 2.0.5
588 | happy-dom: '*'
589 | jsdom: '*'
590 | peerDependenciesMeta:
591 | '@edge-runtime/vm':
592 | optional: true
593 | '@types/node':
594 | optional: true
595 | '@vitest/browser':
596 | optional: true
597 | '@vitest/ui':
598 | optional: true
599 | happy-dom:
600 | optional: true
601 | jsdom:
602 | optional: true
603 |
604 | which@2.0.2:
605 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
606 | engines: {node: '>= 8'}
607 | hasBin: true
608 |
609 | why-is-node-running@2.3.0:
610 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
611 | engines: {node: '>=8'}
612 | hasBin: true
613 |
614 | snapshots:
615 |
616 | '@ampproject/remapping@2.3.0':
617 | dependencies:
618 | '@jridgewell/gen-mapping': 0.3.5
619 | '@jridgewell/trace-mapping': 0.3.25
620 |
621 | '@esbuild/aix-ppc64@0.21.5':
622 | optional: true
623 |
624 | '@esbuild/android-arm64@0.21.5':
625 | optional: true
626 |
627 | '@esbuild/android-arm@0.21.5':
628 | optional: true
629 |
630 | '@esbuild/android-x64@0.21.5':
631 | optional: true
632 |
633 | '@esbuild/darwin-arm64@0.21.5':
634 | optional: true
635 |
636 | '@esbuild/darwin-x64@0.21.5':
637 | optional: true
638 |
639 | '@esbuild/freebsd-arm64@0.21.5':
640 | optional: true
641 |
642 | '@esbuild/freebsd-x64@0.21.5':
643 | optional: true
644 |
645 | '@esbuild/linux-arm64@0.21.5':
646 | optional: true
647 |
648 | '@esbuild/linux-arm@0.21.5':
649 | optional: true
650 |
651 | '@esbuild/linux-ia32@0.21.5':
652 | optional: true
653 |
654 | '@esbuild/linux-loong64@0.21.5':
655 | optional: true
656 |
657 | '@esbuild/linux-mips64el@0.21.5':
658 | optional: true
659 |
660 | '@esbuild/linux-ppc64@0.21.5':
661 | optional: true
662 |
663 | '@esbuild/linux-riscv64@0.21.5':
664 | optional: true
665 |
666 | '@esbuild/linux-s390x@0.21.5':
667 | optional: true
668 |
669 | '@esbuild/linux-x64@0.21.5':
670 | optional: true
671 |
672 | '@esbuild/netbsd-x64@0.21.5':
673 | optional: true
674 |
675 | '@esbuild/openbsd-x64@0.21.5':
676 | optional: true
677 |
678 | '@esbuild/sunos-x64@0.21.5':
679 | optional: true
680 |
681 | '@esbuild/win32-arm64@0.21.5':
682 | optional: true
683 |
684 | '@esbuild/win32-ia32@0.21.5':
685 | optional: true
686 |
687 | '@esbuild/win32-x64@0.21.5':
688 | optional: true
689 |
690 | '@jridgewell/gen-mapping@0.3.5':
691 | dependencies:
692 | '@jridgewell/set-array': 1.2.1
693 | '@jridgewell/sourcemap-codec': 1.5.0
694 | '@jridgewell/trace-mapping': 0.3.25
695 |
696 | '@jridgewell/resolve-uri@3.1.2': {}
697 |
698 | '@jridgewell/set-array@1.2.1': {}
699 |
700 | '@jridgewell/sourcemap-codec@1.5.0': {}
701 |
702 | '@jridgewell/trace-mapping@0.3.25':
703 | dependencies:
704 | '@jridgewell/resolve-uri': 3.1.2
705 | '@jridgewell/sourcemap-codec': 1.5.0
706 |
707 | '@remix-run/router@1.19.0': {}
708 |
709 | '@rollup/rollup-android-arm-eabi@4.20.0':
710 | optional: true
711 |
712 | '@rollup/rollup-android-arm64@4.20.0':
713 | optional: true
714 |
715 | '@rollup/rollup-darwin-arm64@4.20.0':
716 | optional: true
717 |
718 | '@rollup/rollup-darwin-x64@4.20.0':
719 | optional: true
720 |
721 | '@rollup/rollup-linux-arm-gnueabihf@4.20.0':
722 | optional: true
723 |
724 | '@rollup/rollup-linux-arm-musleabihf@4.20.0':
725 | optional: true
726 |
727 | '@rollup/rollup-linux-arm64-gnu@4.20.0':
728 | optional: true
729 |
730 | '@rollup/rollup-linux-arm64-musl@4.20.0':
731 | optional: true
732 |
733 | '@rollup/rollup-linux-powerpc64le-gnu@4.20.0':
734 | optional: true
735 |
736 | '@rollup/rollup-linux-riscv64-gnu@4.20.0':
737 | optional: true
738 |
739 | '@rollup/rollup-linux-s390x-gnu@4.20.0':
740 | optional: true
741 |
742 | '@rollup/rollup-linux-x64-gnu@4.20.0':
743 | optional: true
744 |
745 | '@rollup/rollup-linux-x64-musl@4.20.0':
746 | optional: true
747 |
748 | '@rollup/rollup-win32-arm64-msvc@4.20.0':
749 | optional: true
750 |
751 | '@rollup/rollup-win32-ia32-msvc@4.20.0':
752 | optional: true
753 |
754 | '@rollup/rollup-win32-x64-msvc@4.20.0':
755 | optional: true
756 |
757 | '@types/estree@1.0.5': {}
758 |
759 | '@types/node@22.1.0':
760 | dependencies:
761 | undici-types: 6.13.0
762 |
763 | '@types/prop-types@15.7.12': {}
764 |
765 | '@types/react@18.3.3':
766 | dependencies:
767 | '@types/prop-types': 15.7.12
768 | csstype: 3.1.3
769 |
770 | '@vitest/expect@2.0.5':
771 | dependencies:
772 | '@vitest/spy': 2.0.5
773 | '@vitest/utils': 2.0.5
774 | chai: 5.1.1
775 | tinyrainbow: 1.2.0
776 |
777 | '@vitest/pretty-format@2.0.5':
778 | dependencies:
779 | tinyrainbow: 1.2.0
780 |
781 | '@vitest/runner@2.0.5':
782 | dependencies:
783 | '@vitest/utils': 2.0.5
784 | pathe: 1.1.2
785 |
786 | '@vitest/snapshot@2.0.5':
787 | dependencies:
788 | '@vitest/pretty-format': 2.0.5
789 | magic-string: 0.30.11
790 | pathe: 1.1.2
791 |
792 | '@vitest/spy@2.0.5':
793 | dependencies:
794 | tinyspy: 3.0.0
795 |
796 | '@vitest/utils@2.0.5':
797 | dependencies:
798 | '@vitest/pretty-format': 2.0.5
799 | estree-walker: 3.0.3
800 | loupe: 3.1.1
801 | tinyrainbow: 1.2.0
802 |
803 | assertion-error@2.0.1: {}
804 |
805 | cac@6.7.14: {}
806 |
807 | chai@5.1.1:
808 | dependencies:
809 | assertion-error: 2.0.1
810 | check-error: 2.1.1
811 | deep-eql: 5.0.2
812 | loupe: 3.1.1
813 | pathval: 2.0.0
814 |
815 | check-error@2.1.1: {}
816 |
817 | cross-spawn@7.0.3:
818 | dependencies:
819 | path-key: 3.1.1
820 | shebang-command: 2.0.0
821 | which: 2.0.2
822 |
823 | csstype@3.1.3: {}
824 |
825 | debug@4.3.6:
826 | dependencies:
827 | ms: 2.1.2
828 |
829 | deep-eql@5.0.2: {}
830 |
831 | es-module-lexer@1.5.4: {}
832 |
833 | esbuild@0.21.5:
834 | optionalDependencies:
835 | '@esbuild/aix-ppc64': 0.21.5
836 | '@esbuild/android-arm': 0.21.5
837 | '@esbuild/android-arm64': 0.21.5
838 | '@esbuild/android-x64': 0.21.5
839 | '@esbuild/darwin-arm64': 0.21.5
840 | '@esbuild/darwin-x64': 0.21.5
841 | '@esbuild/freebsd-arm64': 0.21.5
842 | '@esbuild/freebsd-x64': 0.21.5
843 | '@esbuild/linux-arm': 0.21.5
844 | '@esbuild/linux-arm64': 0.21.5
845 | '@esbuild/linux-ia32': 0.21.5
846 | '@esbuild/linux-loong64': 0.21.5
847 | '@esbuild/linux-mips64el': 0.21.5
848 | '@esbuild/linux-ppc64': 0.21.5
849 | '@esbuild/linux-riscv64': 0.21.5
850 | '@esbuild/linux-s390x': 0.21.5
851 | '@esbuild/linux-x64': 0.21.5
852 | '@esbuild/netbsd-x64': 0.21.5
853 | '@esbuild/openbsd-x64': 0.21.5
854 | '@esbuild/sunos-x64': 0.21.5
855 | '@esbuild/win32-arm64': 0.21.5
856 | '@esbuild/win32-ia32': 0.21.5
857 | '@esbuild/win32-x64': 0.21.5
858 |
859 | estree-walker@3.0.3:
860 | dependencies:
861 | '@types/estree': 1.0.5
862 |
863 | execa@8.0.1:
864 | dependencies:
865 | cross-spawn: 7.0.3
866 | get-stream: 8.0.1
867 | human-signals: 5.0.0
868 | is-stream: 3.0.0
869 | merge-stream: 2.0.0
870 | npm-run-path: 5.3.0
871 | onetime: 6.0.0
872 | signal-exit: 4.1.0
873 | strip-final-newline: 3.0.0
874 |
875 | fsevents@2.3.3:
876 | optional: true
877 |
878 | get-func-name@2.0.2: {}
879 |
880 | get-stream@8.0.1: {}
881 |
882 | human-signals@5.0.0: {}
883 |
884 | is-stream@3.0.0: {}
885 |
886 | isexe@2.0.0: {}
887 |
888 | js-tokens@4.0.0: {}
889 |
890 | loose-envify@1.4.0:
891 | dependencies:
892 | js-tokens: 4.0.0
893 |
894 | loupe@3.1.1:
895 | dependencies:
896 | get-func-name: 2.0.2
897 |
898 | magic-string@0.30.11:
899 | dependencies:
900 | '@jridgewell/sourcemap-codec': 1.5.0
901 |
902 | merge-stream@2.0.0: {}
903 |
904 | mimic-fn@4.0.0: {}
905 |
906 | ms@2.1.2: {}
907 |
908 | nanoid@3.3.7: {}
909 |
910 | npm-run-path@5.3.0:
911 | dependencies:
912 | path-key: 4.0.0
913 |
914 | onetime@6.0.0:
915 | dependencies:
916 | mimic-fn: 4.0.0
917 |
918 | path-key@3.1.1: {}
919 |
920 | path-key@4.0.0: {}
921 |
922 | pathe@1.1.2: {}
923 |
924 | pathval@2.0.0: {}
925 |
926 | picocolors@1.0.1: {}
927 |
928 | playwright-chromium@1.45.3:
929 | dependencies:
930 | playwright-core: 1.45.3
931 |
932 | playwright-core@1.45.3: {}
933 |
934 | postcss@8.4.40:
935 | dependencies:
936 | nanoid: 3.3.7
937 | picocolors: 1.0.1
938 | source-map-js: 1.2.0
939 |
940 | react-dom@18.3.1(react@18.3.1):
941 | dependencies:
942 | loose-envify: 1.4.0
943 | react: 18.3.1
944 | scheduler: 0.23.2
945 |
946 | react-router-dom@6.26.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
947 | dependencies:
948 | '@remix-run/router': 1.19.0
949 | react: 18.3.1
950 | react-dom: 18.3.1(react@18.3.1)
951 | react-router: 6.26.0(react@18.3.1)
952 |
953 | react-router@6.26.0(react@18.3.1):
954 | dependencies:
955 | '@remix-run/router': 1.19.0
956 | react: 18.3.1
957 |
958 | react@18.3.1:
959 | dependencies:
960 | loose-envify: 1.4.0
961 |
962 | rollup@4.20.0:
963 | dependencies:
964 | '@types/estree': 1.0.5
965 | optionalDependencies:
966 | '@rollup/rollup-android-arm-eabi': 4.20.0
967 | '@rollup/rollup-android-arm64': 4.20.0
968 | '@rollup/rollup-darwin-arm64': 4.20.0
969 | '@rollup/rollup-darwin-x64': 4.20.0
970 | '@rollup/rollup-linux-arm-gnueabihf': 4.20.0
971 | '@rollup/rollup-linux-arm-musleabihf': 4.20.0
972 | '@rollup/rollup-linux-arm64-gnu': 4.20.0
973 | '@rollup/rollup-linux-arm64-musl': 4.20.0
974 | '@rollup/rollup-linux-powerpc64le-gnu': 4.20.0
975 | '@rollup/rollup-linux-riscv64-gnu': 4.20.0
976 | '@rollup/rollup-linux-s390x-gnu': 4.20.0
977 | '@rollup/rollup-linux-x64-gnu': 4.20.0
978 | '@rollup/rollup-linux-x64-musl': 4.20.0
979 | '@rollup/rollup-win32-arm64-msvc': 4.20.0
980 | '@rollup/rollup-win32-ia32-msvc': 4.20.0
981 | '@rollup/rollup-win32-x64-msvc': 4.20.0
982 | fsevents: 2.3.3
983 |
984 | scheduler@0.23.2:
985 | dependencies:
986 | loose-envify: 1.4.0
987 |
988 | shebang-command@2.0.0:
989 | dependencies:
990 | shebang-regex: 3.0.0
991 |
992 | shebang-regex@3.0.0: {}
993 |
994 | siginfo@2.0.0: {}
995 |
996 | signal-exit@4.1.0: {}
997 |
998 | source-map-js@1.2.0: {}
999 |
1000 | stackback@0.0.2: {}
1001 |
1002 | std-env@3.7.0: {}
1003 |
1004 | strip-final-newline@3.0.0: {}
1005 |
1006 | tinybench@2.9.0: {}
1007 |
1008 | tinypool@1.0.0: {}
1009 |
1010 | tinyrainbow@1.2.0: {}
1011 |
1012 | tinyspy@3.0.0: {}
1013 |
1014 | typescript@5.5.4: {}
1015 |
1016 | undici-types@6.13.0: {}
1017 |
1018 | vite-node@2.0.5(@types/node@22.1.0):
1019 | dependencies:
1020 | cac: 6.7.14
1021 | debug: 4.3.6
1022 | pathe: 1.1.2
1023 | tinyrainbow: 1.2.0
1024 | vite: 5.3.5(@types/node@22.1.0)
1025 | transitivePeerDependencies:
1026 | - '@types/node'
1027 | - less
1028 | - lightningcss
1029 | - sass
1030 | - stylus
1031 | - sugarss
1032 | - supports-color
1033 | - terser
1034 |
1035 | vite@5.3.5(@types/node@22.1.0):
1036 | dependencies:
1037 | esbuild: 0.21.5
1038 | postcss: 8.4.40
1039 | rollup: 4.20.0
1040 | optionalDependencies:
1041 | '@types/node': 22.1.0
1042 | fsevents: 2.3.3
1043 |
1044 | vitest@2.0.5(@types/node@22.1.0):
1045 | dependencies:
1046 | '@ampproject/remapping': 2.3.0
1047 | '@vitest/expect': 2.0.5
1048 | '@vitest/pretty-format': 2.0.5
1049 | '@vitest/runner': 2.0.5
1050 | '@vitest/snapshot': 2.0.5
1051 | '@vitest/spy': 2.0.5
1052 | '@vitest/utils': 2.0.5
1053 | chai: 5.1.1
1054 | debug: 4.3.6
1055 | execa: 8.0.1
1056 | magic-string: 0.30.11
1057 | pathe: 1.1.2
1058 | std-env: 3.7.0
1059 | tinybench: 2.9.0
1060 | tinypool: 1.0.0
1061 | tinyrainbow: 1.2.0
1062 | vite: 5.3.5(@types/node@22.1.0)
1063 | vite-node: 2.0.5(@types/node@22.1.0)
1064 | why-is-node-running: 2.3.0
1065 | optionalDependencies:
1066 | '@types/node': 22.1.0
1067 | transitivePeerDependencies:
1068 | - less
1069 | - lightningcss
1070 | - sass
1071 | - stylus
1072 | - sugarss
1073 | - supports-color
1074 | - terser
1075 |
1076 | which@2.0.2:
1077 | dependencies:
1078 | isexe: 2.0.0
1079 |
1080 | why-is-node-running@2.3.0:
1081 | dependencies:
1082 | siginfo: 2.0.0
1083 | stackback: 0.0.2
1084 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "declarationDir": "dist",
5 | "emitDeclarationOnly": true,
6 | "strict": true,
7 | "module": "NodeNext",
8 | "skipLibCheck": true
9 | },
10 | "include": ["index.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 |
3 | export default defineConfig({
4 | build: {
5 | outDir: 'dist',
6 | minify: false,
7 | lib: {
8 | entry: './index.ts',
9 | formats: ['es', 'cjs'],
10 | fileName: 'index'
11 | },
12 | rollupOptions: {
13 | external: ['node:path', 'node:fs', 'vite']
14 | }
15 | },
16 | })
17 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config'
2 |
3 | export default defineConfig({
4 | test: {
5 | setupFiles: ['./__tests__/setup.ts'],
6 | include: ['./__tests__/*.spec.ts']
7 | }
8 | })
9 |
--------------------------------------------------------------------------------