next-vite-router 1.0.7 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +198 -167
- package/dist/cli.cjs +12 -4
- package/dist/index.js +110 -104
- package/dist/index.plugin--ecyiAem.js +132 -0
- package/dist/plugin.js +4 -57
- package/package.json +72 -70
package/README.md
CHANGED
|
@@ -1,248 +1,279 @@
|
|
|
1
|
-
|
|
1
|
+
# Next Vite Router
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
File-based routing for React + Vite.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Define routes with folders and let the package generate the
|
|
6
|
+
[React Router](https://reactrouter.com/) `RouteObject[]`. It does not replace
|
|
7
|
+
React Router, navigation, history, loaders, or application state.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
## Start here
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
npm install next-vite-router
|
|
13
|
-
# or
|
|
14
|
-
yarn add next-vite-router
|
|
12
|
+
npm create vite@latest my-app -- --template react-ts
|
|
13
|
+
cd my-app
|
|
14
|
+
npm install next-vite-router react-router-dom
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Add the plugin to `vite.config.ts`:
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
```ts
|
|
20
|
+
import { defineConfig } from "vite";
|
|
21
|
+
import react from "@vitejs/plugin-react";
|
|
22
|
+
import { nextViteRouter } from "next-vite-router/plugin";
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
pnpm dlx next-vite-router init
|
|
27
|
-
# or
|
|
28
|
-
yarn dlx next-vite-router init
|
|
29
|
-
# or
|
|
30
|
-
bunx next-vite-router init
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
plugins: [react(), nextViteRouter()],
|
|
26
|
+
});
|
|
31
27
|
```
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
Create your route tree:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
src/app/
|
|
33
|
+
├── page.tsx
|
|
34
|
+
├── about/
|
|
35
|
+
│ └── page.tsx
|
|
36
|
+
└── users/
|
|
37
|
+
├── page.tsx
|
|
38
|
+
└── [id]/
|
|
39
|
+
└── page.tsx
|
|
40
|
+
```
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
This generates:
|
|
44
43
|
|
|
45
|
-
|
|
44
|
+
```text
|
|
45
|
+
/
|
|
46
|
+
/about
|
|
47
|
+
/users
|
|
48
|
+
/users/:id
|
|
49
|
+
```
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
- Installs `next-vite-router` and `react-router-dom@latest`
|
|
49
|
-
- Configures the Vite plugin in `vite.config.ts`
|
|
50
|
-
- Sets up path aliases (`@/*`) in `tsconfig.json` and Vite config
|
|
51
|
-
- Creates TypeScript declarations for the virtual module (`virtual:next-vite-router`)
|
|
52
|
-
- Generates example pages (`app/page.tsx`, `app/layout.tsx`, `app/example/page.tsx`)
|
|
53
|
-
- Optionally configures Tailwind CSS with `@tailwindcss/vite` and creates `global.css`
|
|
51
|
+
Use the generated router inside a normal React Router provider:
|
|
54
52
|
|
|
55
|
-
|
|
53
|
+
```tsx
|
|
54
|
+
// src/App.tsx
|
|
55
|
+
import { Router } from "virtual:next-vite-router";
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
export default function App() {
|
|
58
|
+
return <Router />;
|
|
59
|
+
}
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
```tsx
|
|
63
|
+
// src/main.tsx
|
|
64
|
+
import { StrictMode } from "react";
|
|
65
|
+
import { createRoot } from "react-dom/client";
|
|
66
|
+
import { BrowserRouter } from "react-router-dom";
|
|
67
|
+
import App from "./App";
|
|
67
68
|
|
|
68
|
-
|
|
69
|
+
createRoot(document.getElementById("root")!).render(
|
|
70
|
+
<StrictMode>
|
|
71
|
+
<BrowserRouter>
|
|
72
|
+
<App />
|
|
73
|
+
</BrowserRouter>
|
|
74
|
+
</StrictMode>,
|
|
75
|
+
);
|
|
76
|
+
```
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
import { defineConfig } from 'vite';
|
|
72
|
-
import react from '@vitejs/plugin-react';
|
|
73
|
-
import { nextViteRouter } from 'next-vite-router';
|
|
78
|
+
That is the complete setup. Run:
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
react(),
|
|
78
|
-
nextViteRouter({ pagesDir: 'src/pages' })
|
|
79
|
-
]
|
|
80
|
-
});
|
|
80
|
+
```bash
|
|
81
|
+
npm run dev
|
|
81
82
|
```
|
|
82
83
|
|
|
83
|
-
|
|
84
|
+
## Use React Router directly
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
`Router` is only a convenience wrapper around
|
|
87
|
+
`useRoutes(generateRoutes())`. You can keep using React Router APIs:
|
|
86
88
|
|
|
87
89
|
```tsx
|
|
88
|
-
import {
|
|
89
|
-
|
|
90
|
+
import {
|
|
91
|
+
Link,
|
|
92
|
+
generateRoutes,
|
|
93
|
+
useRoutes,
|
|
94
|
+
} from "virtual:next-vite-router";
|
|
95
|
+
import { useNavigate, useParams } from "react-router-dom";
|
|
90
96
|
|
|
91
97
|
const routes = generateRoutes();
|
|
92
98
|
|
|
93
99
|
export default function App() {
|
|
94
100
|
const element = useRoutes(routes);
|
|
95
|
-
return
|
|
101
|
+
return (
|
|
102
|
+
<>
|
|
103
|
+
<Link to="/users">Users</Link>
|
|
104
|
+
{element}
|
|
105
|
+
</>
|
|
106
|
+
);
|
|
96
107
|
}
|
|
97
108
|
```
|
|
98
109
|
|
|
99
|
-
|
|
110
|
+
Use `useNavigate`, `useParams`, loaders, actions, and other React Router APIs
|
|
111
|
+
from `react-router-dom`. The package intentionally does not create competing
|
|
112
|
+
navigation or data-loading APIs.
|
|
113
|
+
|
|
114
|
+
## File conventions
|
|
115
|
+
|
|
116
|
+
| File or folder | Result |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| `page.tsx` | Route page |
|
|
119
|
+
| `layout.tsx` | Nested layout rendered with React Router's `Outlet` |
|
|
120
|
+
| `not-found.tsx` | `*` route for that subtree |
|
|
121
|
+
| `[id]` | Dynamic segment `:id` |
|
|
122
|
+
| `[...slug]` | Catch-all `*` segment |
|
|
123
|
+
| `[[...slug]]` | Optional catch-all `*` segment |
|
|
124
|
+
| `(admin)` | Route group omitted from the URL |
|
|
125
|
+
|
|
126
|
+
Layouts are the recommended way to add route-scoped navigation, providers, or
|
|
127
|
+
authorization:
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
src/app/
|
|
131
|
+
├── layout.tsx
|
|
132
|
+
└── dashboard/
|
|
133
|
+
├── layout.tsx
|
|
134
|
+
└── page.tsx
|
|
135
|
+
```
|
|
100
136
|
|
|
101
137
|
```tsx
|
|
102
|
-
import {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
</BrowserRouter>
|
|
112
|
-
</StrictMode>
|
|
113
|
-
);
|
|
138
|
+
import { Outlet } from "react-router-dom";
|
|
139
|
+
|
|
140
|
+
export default function DashboardLayout() {
|
|
141
|
+
return (
|
|
142
|
+
<AuthGuard>
|
|
143
|
+
<Outlet />
|
|
144
|
+
</AuthGuard>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
114
147
|
```
|
|
115
148
|
|
|
116
|
-
|
|
149
|
+
## Type-safe paths
|
|
117
150
|
|
|
118
|
-
|
|
119
|
-
- Wrap your app with `BrowserRouter` at the entry point (`main.tsx`), not inside `App`.
|
|
120
|
-
- `pagesDir` (default: `src/app`) is the directory where you organize your **route files** (`page.tsx`, `layout.tsx`, `not-found.tsx`). It has nothing to do with the `App.tsx` component.
|
|
121
|
-
- The virtual module is `virtual:next-vite-router` (the plugin resolves it internally).
|
|
151
|
+
The Vite plugin generates `virtual-next-vite-router.d.ts` automatically:
|
|
122
152
|
|
|
123
|
-
|
|
153
|
+
```tsx
|
|
154
|
+
import type {
|
|
155
|
+
RouteParams,
|
|
156
|
+
RoutePath,
|
|
157
|
+
} from "virtual:next-vite-router";
|
|
124
158
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
├── App.tsx ← Your main app component
|
|
128
|
-
├── main.tsx ← Entry point (with BrowserRouter)
|
|
129
|
-
└── app/ ← pagesDir (routes are organized here)
|
|
130
|
-
├── page.tsx ← Home page
|
|
131
|
-
├── layout.tsx ← Root layout
|
|
132
|
-
└── dashboard/
|
|
133
|
-
├── page.tsx ← /dashboard page
|
|
134
|
-
└── layout.tsx ← Dashboard layout
|
|
159
|
+
const path = "/users/:id" satisfies RoutePath;
|
|
160
|
+
const params: RouteParams<typeof path> = { id: "123" };
|
|
135
161
|
```
|
|
136
162
|
|
|
137
|
-
TypeScript
|
|
163
|
+
Invalid paths and missing dynamic parameters are reported by TypeScript.
|
|
164
|
+
No manual declaration for the virtual module is required.
|
|
138
165
|
|
|
139
|
-
|
|
166
|
+
## Lazy loading
|
|
140
167
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
168
|
+
Pages and `not-found.tsx` files use Vite's non-eager `import.meta.glob`, so
|
|
169
|
+
Vite can emit separate chunks for pages. Layouts are eager because they wrap
|
|
170
|
+
the generated route tree. Lazy loading is enabled by default:
|
|
144
171
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
This ensures TypeScript knows the shape of the virtual module provided by the Vite plugin and avoids `Cannot find module 'virtual:next-vite-router'` errors in editors and builds.
|
|
172
|
+
```tsx
|
|
173
|
+
import { configureRouter } from "next-vite-router";
|
|
151
174
|
|
|
152
|
-
|
|
175
|
+
configureRouter({
|
|
176
|
+
loadingFallback: () => <div>Loading route...</div>,
|
|
177
|
+
});
|
|
178
|
+
```
|
|
153
179
|
|
|
154
|
-
|
|
180
|
+
`enableLazyLoading: false` is available for compatibility and testing. It does
|
|
181
|
+
not turn Vite's asynchronous imports into synchronous imports.
|
|
155
182
|
|
|
156
|
-
|
|
183
|
+
## Optional middleware
|
|
157
184
|
|
|
158
|
-
|
|
159
|
-
|
|
185
|
+
Prefer layouts for route-scoped behavior. `registerMiddleware` is an optional
|
|
186
|
+
escape hatch for cross-cutting wrappers:
|
|
160
187
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const layouts = import.meta.glob('../../pages/**/layout.tsx', { eager: true });
|
|
164
|
-
const notFounds = import.meta.glob('../../pages/**/not-found.tsx');
|
|
188
|
+
```tsx
|
|
189
|
+
import { registerMiddleware } from "next-vite-router";
|
|
165
190
|
|
|
166
|
-
|
|
167
|
-
|
|
191
|
+
registerMiddleware(/^\/dashboard/, (element) => (
|
|
192
|
+
<AuthGuard>{element}</AuthGuard>
|
|
193
|
+
));
|
|
168
194
|
```
|
|
169
195
|
|
|
170
|
-
|
|
196
|
+
Middleware wraps generated route elements; it does not create routes or
|
|
197
|
+
replace React Router.
|
|
198
|
+
|
|
199
|
+
## CLI
|
|
171
200
|
|
|
172
|
-
|
|
201
|
+
For an interactive setup:
|
|
173
202
|
|
|
174
|
-
|
|
203
|
+
```bash
|
|
204
|
+
npx create-next-vite-router init
|
|
205
|
+
```
|
|
175
206
|
|
|
176
|
-
|
|
177
|
-
-
|
|
178
|
-
|
|
179
|
-
- `registerMiddleware`, `clearMiddlewares` middleware helpers to manage registered middlewares.
|
|
180
|
-
- `configureRouter` configure router-level options.
|
|
181
|
-
- `nextViteRouter(options)` Vite plugin factory. Options:
|
|
182
|
-
- `pagesDir?: string` (default: `src/app`)
|
|
183
|
-
- `pageFile?: string` (default: `page.tsx`)
|
|
184
|
-
- `layoutFile?: string` (default: `layout.tsx`)
|
|
185
|
-
- `notFoundFile?: string` (default: `not-found.tsx`)
|
|
186
|
-
- Types exported: `RouterConfig`, `RouteNode`, `RouteMiddleware`, `NextViteRouterPluginOptions`.
|
|
207
|
+
The CLI creates a Vite React project, installs the package and
|
|
208
|
+
`react-router-dom@^7.0.0`, configures the plugin, and adds an example route
|
|
209
|
+
tree.
|
|
187
210
|
|
|
188
|
-
|
|
211
|
+
## Compatibility
|
|
189
212
|
|
|
190
|
-
|
|
213
|
+
| Package | Supported versions |
|
|
214
|
+
| --- | --- |
|
|
215
|
+
| React / React DOM | `>=18 <20` |
|
|
216
|
+
| React Router DOM | `>=6 <8` |
|
|
217
|
+
| Vite | `>=5 <9` |
|
|
191
218
|
|
|
192
|
-
|
|
219
|
+
The compatibility workflow tests React 18 and 19 with React Router 6 and 7
|
|
220
|
+
across Vite 5, 6, 7, and 8.
|
|
193
221
|
|
|
194
|
-
|
|
195
|
-
- `pagesDir?: string` path used by the generator to resolve pages (useful if you need to override defaults at runtime).
|
|
196
|
-
- `enableLazyLoading?: boolean` when true, pages are wrapped to load lazily.
|
|
222
|
+
## Advanced API
|
|
197
223
|
|
|
198
|
-
|
|
224
|
+
For custom glob layouts, the package exports:
|
|
199
225
|
|
|
200
226
|
```ts
|
|
201
|
-
import {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
});
|
|
227
|
+
import {
|
|
228
|
+
buildRouteTree,
|
|
229
|
+
createRouteGenerator,
|
|
230
|
+
treeToRoutes,
|
|
231
|
+
} from "next-vite-router";
|
|
207
232
|
```
|
|
208
233
|
|
|
209
|
-
|
|
234
|
+
The normal pipeline is:
|
|
210
235
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
236
|
+
```text
|
|
237
|
+
filesystem -> buildRouteTree() -> treeToRoutes() -> RouteObject[] -> React Router
|
|
238
|
+
```
|
|
214
239
|
|
|
215
|
-
|
|
240
|
+
## Examples
|
|
216
241
|
|
|
217
|
-
|
|
218
|
-
- To remove all registered middlewares, use `clearMiddlewares()`.
|
|
219
|
-
- The internal helper `applyMiddlewares(path, element)` is used when constructing the final route element.
|
|
242
|
+
The repository includes a runnable showcase in [`examples/`](./examples/):
|
|
220
243
|
|
|
221
|
-
|
|
244
|
+
- `basic`
|
|
245
|
+
- `layouts`
|
|
246
|
+
- `dynamic-routes`
|
|
247
|
+
- `middleware`
|
|
248
|
+
- `typed-routes`
|
|
222
249
|
|
|
223
|
-
|
|
224
|
-
import { registerMiddleware } from 'next-vite-router';
|
|
250
|
+
Run it from the examples directory:
|
|
225
251
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
252
|
+
```bash
|
|
253
|
+
cd examples
|
|
254
|
+
pnpm install
|
|
255
|
+
pnpm dev
|
|
229
256
|
```
|
|
230
257
|
|
|
231
|
-
|
|
258
|
+
The app opens a small navigation menu so each example can be tested
|
|
259
|
+
immediately. The `predev` script builds the local package automatically.
|
|
232
260
|
|
|
233
|
-
|
|
261
|
+
## Development
|
|
234
262
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
263
|
+
From this repository:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
pnpm install
|
|
267
|
+
pnpm run build
|
|
268
|
+
pnpm run test:generator
|
|
269
|
+
pnpm run test:routes
|
|
270
|
+
pnpm run test:compatibility
|
|
271
|
+
pnpm exec tsc -p test/fixture/tsconfig.json --noEmit
|
|
272
|
+
pnpm run test:local
|
|
242
273
|
```
|
|
243
274
|
|
|
244
|
-
|
|
275
|
+
The route matrix lives in [`test/routes.test.js`](./test/routes.test.js).
|
|
245
276
|
|
|
246
277
|
## License
|
|
247
278
|
|
|
248
|
-
MIT
|
|
279
|
+
MIT
|
package/dist/cli.cjs
CHANGED
|
@@ -200,10 +200,18 @@ function createVirtualDTS(projectDir, useSrc) {
|
|
|
200
200
|
}
|
|
201
201
|
const filePath = path.join(targetDir, "virtual-next-vite-router.d.ts");
|
|
202
202
|
const content = `declare module 'virtual:next-vite-router' {
|
|
203
|
+
import type { ReactElement } from 'react';
|
|
203
204
|
import type { RouteObject } from 'react-router-dom';
|
|
204
205
|
|
|
206
|
+
export type RoutePath = string;
|
|
207
|
+
export type RoutePathParams = Record<string, Record<string, string>>;
|
|
208
|
+
export type RouteParams<P extends RoutePath> = P extends keyof RoutePathParams
|
|
209
|
+
? RoutePathParams[P]
|
|
210
|
+
: never;
|
|
211
|
+
|
|
205
212
|
export const generateRoutes: () => RouteObject[];
|
|
206
|
-
export
|
|
213
|
+
export function Router(): ReactElement | null;
|
|
214
|
+
export { Link, useRoutes } from 'react-router-dom';
|
|
207
215
|
}
|
|
208
216
|
`;
|
|
209
217
|
fs.writeFileSync(filePath, content, "utf-8");
|
|
@@ -221,7 +229,7 @@ import { generateRoutes, useRoutes } from 'virtual:next-vite-router';
|
|
|
221
229
|
|
|
222
230
|
const routes = generateRoutes();
|
|
223
231
|
|
|
224
|
-
function App() {
|
|
232
|
+
export default function App() {
|
|
225
233
|
const element = useRoutes(routes);
|
|
226
234
|
return element;
|
|
227
235
|
}
|
|
@@ -518,7 +526,7 @@ const init = new commander.Command().name("init").description(
|
|
|
518
526
|
);
|
|
519
527
|
const addDepsCmd = pm.addDepsCommand([
|
|
520
528
|
"next-vite-router",
|
|
521
|
-
"react-router-dom
|
|
529
|
+
"react-router-dom@^7.0.0"
|
|
522
530
|
]);
|
|
523
531
|
child_process.execSync(addDepsCmd, { stdio: "inherit", cwd: projectName });
|
|
524
532
|
logger.info("Configuring next-vite-router in the project...");
|
|
@@ -531,7 +539,7 @@ const init = new commander.Command().name("init").description(
|
|
|
531
539
|
Project "${projectName}" is ready!
|
|
532
540
|
`);
|
|
533
541
|
});
|
|
534
|
-
const version = "1.0
|
|
542
|
+
const version = "1.1.0";
|
|
535
543
|
const pkg = {
|
|
536
544
|
version
|
|
537
545
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,86 +1,84 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
function k(e) {
|
|
11
|
-
m = { ...m, ...e };
|
|
1
|
+
import { e as C, n as f } from "./index.plugin--ecyiAem.js";
|
|
2
|
+
import { a as G } from "./index.plugin--ecyiAem.js";
|
|
3
|
+
import i, { Suspense as y, lazy as F } from "react";
|
|
4
|
+
const L = {
|
|
5
|
+
enableLazyLoading: !0
|
|
6
|
+
};
|
|
7
|
+
let d = { ...L };
|
|
8
|
+
function x(e) {
|
|
9
|
+
d = { ...d, ...e };
|
|
12
10
|
}
|
|
13
|
-
function
|
|
14
|
-
return
|
|
11
|
+
function $() {
|
|
12
|
+
return d;
|
|
15
13
|
}
|
|
16
|
-
let
|
|
17
|
-
function
|
|
18
|
-
|
|
14
|
+
let E = [];
|
|
15
|
+
function T(e, r) {
|
|
16
|
+
E.push({ pattern: e, middleware: r });
|
|
19
17
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
18
|
+
function j() {
|
|
19
|
+
E = [];
|
|
22
20
|
}
|
|
23
|
-
function
|
|
24
|
-
let
|
|
25
|
-
for (const
|
|
26
|
-
|
|
27
|
-
return
|
|
21
|
+
function z(e, r) {
|
|
22
|
+
let n = r;
|
|
23
|
+
for (const t of E)
|
|
24
|
+
t.pattern.test(e) && (n = t.middleware(n));
|
|
25
|
+
return n;
|
|
28
26
|
}
|
|
29
|
-
const
|
|
30
|
-
function R(e,
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
33
|
-
const
|
|
34
|
-
|
|
27
|
+
const M = () => i.createElement("div"), b = /* @__PURE__ */ new Map();
|
|
28
|
+
function R(e, r, n) {
|
|
29
|
+
const t = $();
|
|
30
|
+
if (t.enableLazyLoading === !1) {
|
|
31
|
+
const c = i.lazy(e), u = i.createElement(
|
|
32
|
+
y,
|
|
35
33
|
{ fallback: null },
|
|
36
34
|
// No loading fallback when disabled
|
|
37
|
-
i.createElement(
|
|
35
|
+
i.createElement(c)
|
|
38
36
|
);
|
|
39
|
-
return
|
|
37
|
+
return n ? z(n, u) : u;
|
|
40
38
|
}
|
|
41
|
-
let
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
{ fallback: i.createElement(
|
|
46
|
-
i.createElement(
|
|
39
|
+
let l = b.get(r);
|
|
40
|
+
l || (l = F(e), b.set(r, l));
|
|
41
|
+
const o = t.loadingFallback || M, a = i.createElement(
|
|
42
|
+
y,
|
|
43
|
+
{ fallback: i.createElement(o) },
|
|
44
|
+
i.createElement(l)
|
|
47
45
|
);
|
|
48
|
-
return
|
|
46
|
+
return n ? z(n, a) : a;
|
|
49
47
|
}
|
|
50
|
-
function p(e,
|
|
51
|
-
const
|
|
52
|
-
let
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
segment:
|
|
56
|
-
fullPath:
|
|
48
|
+
function p(e, r, n, t) {
|
|
49
|
+
const l = C(r), o = l ? l.split("/") : [];
|
|
50
|
+
let a = e, c = "";
|
|
51
|
+
o.forEach((u, h) => {
|
|
52
|
+
c = c ? `${c}/${u}` : u, a.children.has(u) || a.children.set(u, {
|
|
53
|
+
segment: u,
|
|
54
|
+
fullPath: c,
|
|
57
55
|
children: /* @__PURE__ */ new Map()
|
|
58
|
-
}),
|
|
59
|
-
}),
|
|
56
|
+
}), a = a.children.get(u), h === o.length - 1 && (a[t] = n);
|
|
57
|
+
}), o.length === 0 && (e[t] = n);
|
|
60
58
|
}
|
|
61
|
-
function
|
|
62
|
-
const
|
|
59
|
+
function S(e, r, n) {
|
|
60
|
+
const t = {
|
|
63
61
|
segment: "",
|
|
64
62
|
fullPath: "",
|
|
65
63
|
children: /* @__PURE__ */ new Map()
|
|
66
64
|
};
|
|
67
|
-
return Object.entries(
|
|
68
|
-
p(
|
|
69
|
-
}), Object.entries(e).forEach(([
|
|
70
|
-
p(
|
|
71
|
-
}), Object.entries(
|
|
72
|
-
p(
|
|
73
|
-
}),
|
|
65
|
+
return Object.entries(r).forEach(([l, o]) => {
|
|
66
|
+
p(t, l, o.default, "layout");
|
|
67
|
+
}), Object.entries(e).forEach(([l, o]) => {
|
|
68
|
+
p(t, l, o, "page");
|
|
69
|
+
}), Object.entries(n).forEach(([l, o]) => {
|
|
70
|
+
p(t, l, o, "notFound");
|
|
71
|
+
}), t;
|
|
74
72
|
}
|
|
75
|
-
function
|
|
76
|
-
const
|
|
73
|
+
function m(e, r, n = !1) {
|
|
74
|
+
const t = R(
|
|
77
75
|
async () => ({ default: (await e.page()).default }),
|
|
78
|
-
`page:${e.fullPath ||
|
|
79
|
-
|
|
76
|
+
`page:${e.fullPath || r}`,
|
|
77
|
+
r
|
|
80
78
|
);
|
|
81
|
-
return
|
|
79
|
+
return n ? { index: !0, element: t } : { path: f(e.segment), element: t };
|
|
82
80
|
}
|
|
83
|
-
function
|
|
81
|
+
function g(e) {
|
|
84
82
|
return {
|
|
85
83
|
path: "*",
|
|
86
84
|
element: R(
|
|
@@ -89,62 +87,70 @@ function $(e) {
|
|
|
89
87
|
)
|
|
90
88
|
};
|
|
91
89
|
}
|
|
92
|
-
function s(e,
|
|
93
|
-
const r = [];
|
|
94
|
-
return e.children.forEach((n, t) => {
|
|
95
|
-
const l = f(t), o = l ? a ? `${a}/${l}` : `/${l}` : a;
|
|
96
|
-
r.push(...b(n, !1, o));
|
|
97
|
-
}), r;
|
|
98
|
-
}
|
|
99
|
-
function b(e, a = !1, r = "") {
|
|
90
|
+
function s(e, r) {
|
|
100
91
|
const n = [];
|
|
101
|
-
|
|
102
|
-
const t =
|
|
103
|
-
|
|
92
|
+
return [...e.children.entries()].sort(([t], [l]) => t.localeCompare(l)).forEach(([t, l]) => {
|
|
93
|
+
const o = f(t), a = o ? r ? `${r}/${o}` : `/${o}` : r;
|
|
94
|
+
n.push(...w(l, !1, a));
|
|
95
|
+
}), n;
|
|
96
|
+
}
|
|
97
|
+
function w(e, r = !1, n = "") {
|
|
98
|
+
const t = [];
|
|
99
|
+
if (r && e.layout) {
|
|
100
|
+
const a = [];
|
|
101
|
+
return e.page && a.push(m(e, "/", !0)), a.push(...s(e, "")), e.notFound && a.push(g(e)), t.push({
|
|
104
102
|
path: "/",
|
|
105
103
|
element: i.createElement(e.layout),
|
|
106
|
-
children:
|
|
107
|
-
}),
|
|
104
|
+
children: a
|
|
105
|
+
}), t;
|
|
108
106
|
}
|
|
109
107
|
if (e.layout) {
|
|
110
|
-
const
|
|
111
|
-
if (!
|
|
112
|
-
return s(e,
|
|
113
|
-
const
|
|
114
|
-
return e.page &&
|
|
115
|
-
path:
|
|
108
|
+
const a = f(e.segment);
|
|
109
|
+
if (!a)
|
|
110
|
+
return s(e, n);
|
|
111
|
+
const c = n + "/" + a, u = [];
|
|
112
|
+
return e.page && u.push(m(e, c, !0)), u.push(...s(e, c)), e.notFound && u.push(g(e)), t.push({
|
|
113
|
+
path: a,
|
|
116
114
|
element: i.createElement(e.layout),
|
|
117
|
-
children:
|
|
118
|
-
}),
|
|
115
|
+
children: u.length > 0 ? u : void 0
|
|
116
|
+
}), t;
|
|
119
117
|
}
|
|
120
118
|
if (e.page) {
|
|
121
|
-
const
|
|
122
|
-
if (!
|
|
123
|
-
return
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
119
|
+
const a = f(e.segment);
|
|
120
|
+
if (!a)
|
|
121
|
+
return r ? (t.push({
|
|
122
|
+
path: "/",
|
|
123
|
+
element: m(e, "/", !0).element,
|
|
124
|
+
children: s(e, n).length > 0 ? s(e, n) : void 0
|
|
125
|
+
}), e.notFound && t.push(g(e)), t) : s(e, n);
|
|
126
|
+
const c = n + "/" + a, u = s(e, c), h = m(e, c, !1);
|
|
127
|
+
return t.push({
|
|
128
|
+
path: h.path,
|
|
129
|
+
element: h.element,
|
|
130
|
+
children: u.length > 0 ? u : void 0
|
|
131
|
+
}), t;
|
|
130
132
|
}
|
|
131
|
-
|
|
133
|
+
const l = f(e.segment), o = s(e, n);
|
|
134
|
+
return l ? [{
|
|
135
|
+
path: l,
|
|
136
|
+
children: o.length > 0 ? o : void 0
|
|
137
|
+
}] : o;
|
|
132
138
|
}
|
|
133
|
-
function
|
|
139
|
+
function O(e, r, n) {
|
|
134
140
|
return () => {
|
|
135
|
-
const
|
|
136
|
-
return
|
|
141
|
+
const t = S(e, r, n);
|
|
142
|
+
return w(t, !0);
|
|
137
143
|
};
|
|
138
144
|
}
|
|
139
145
|
export {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
S as buildRouteTree,
|
|
147
|
+
j as clearMiddlewares,
|
|
148
|
+
x as configureRouter,
|
|
143
149
|
R as createLazyElement,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
O as createRouteGenerator,
|
|
151
|
+
C as extractRoutePath,
|
|
152
|
+
G as nextViteRouter,
|
|
147
153
|
f as normalizeSegment,
|
|
148
|
-
|
|
149
|
-
|
|
154
|
+
T as registerMiddleware,
|
|
155
|
+
w as treeToRoutes
|
|
150
156
|
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import p from "node:fs";
|
|
2
|
+
import i from "node:path";
|
|
3
|
+
function y(e) {
|
|
4
|
+
return /^\([^)]+\)$/.test(e) ? "" : /^\[\[\.\.\.(.+)\]\]$/.test(e) || /^\[\.\.\.(.+)\]$/.test(e) ? "*" : /^\[([^\]]+)\]$/.test(e) ? e.replace(/^\[([^\]]+)\]$/, ":$1") : e;
|
|
5
|
+
}
|
|
6
|
+
function b(e) {
|
|
7
|
+
return e.replace(/\\/g, "/").replace("../../app/", "").replace(/\/?(page|layout|not-found)\.tsx$/, "");
|
|
8
|
+
}
|
|
9
|
+
function R(e) {
|
|
10
|
+
const t = e.split(i.sep).filter(Boolean).map(y).filter(Boolean);
|
|
11
|
+
return t.length > 0 ? `/${t.join("/")}` : "/";
|
|
12
|
+
}
|
|
13
|
+
function h(e, t) {
|
|
14
|
+
const s = /* @__PURE__ */ new Set();
|
|
15
|
+
function n(a) {
|
|
16
|
+
for (const u of p.readdirSync(a, { withFileTypes: !0 })) {
|
|
17
|
+
const r = i.join(a, u.name);
|
|
18
|
+
u.isDirectory() ? n(r) : u.isFile() && u.name === t && s.add(R(i.relative(e, a)));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return p.existsSync(e) && n(e), [...s].sort();
|
|
22
|
+
}
|
|
23
|
+
function x(e) {
|
|
24
|
+
const t = e.match(/^\/(?:\[\.\.\.|:)([^/\]]+)\]?$/);
|
|
25
|
+
return t == null ? void 0 : t[1];
|
|
26
|
+
}
|
|
27
|
+
function $(e) {
|
|
28
|
+
const t = e.map((n) => ` | "${n}"`).join(`
|
|
29
|
+
`), s = e.map((n) => {
|
|
30
|
+
const a = n.split("/").map((r) => x(`/${r}`)).filter((r) => !!r), u = a.length > 0 ? a.map((r) => ` ${r}: string;`).join(`
|
|
31
|
+
`) : " [key: string]: never;";
|
|
32
|
+
return ` "${n}": {
|
|
33
|
+
${u}
|
|
34
|
+
};`;
|
|
35
|
+
}).join(`
|
|
36
|
+
`);
|
|
37
|
+
return `declare module 'virtual:next-vite-router' {
|
|
38
|
+
import type { ReactElement } from 'react';
|
|
39
|
+
import type { RouteObject } from 'react-router-dom';
|
|
40
|
+
|
|
41
|
+
export type RoutePath =
|
|
42
|
+
${t || ' | "/"'};
|
|
43
|
+
|
|
44
|
+
export type RouteParams<P extends RoutePath> = P extends keyof RoutePathParams
|
|
45
|
+
? RoutePathParams[P]
|
|
46
|
+
: never;
|
|
47
|
+
|
|
48
|
+
export interface RoutePathParams {
|
|
49
|
+
${s}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const generateRoutes: () => RouteObject[];
|
|
53
|
+
export function Router(): ReactElement | null;
|
|
54
|
+
export { Link, useRoutes } from 'react-router-dom';
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
}
|
|
58
|
+
function g(e = {}) {
|
|
59
|
+
const {
|
|
60
|
+
pagesDir: t = "src/app",
|
|
61
|
+
pageFile: s = "page.tsx",
|
|
62
|
+
layoutFile: n = "layout.tsx",
|
|
63
|
+
notFoundFile: a = "not-found.tsx"
|
|
64
|
+
} = e, u = "virtual:next-vite-router", r = "\0" + u;
|
|
65
|
+
let l = "", m = "";
|
|
66
|
+
function f() {
|
|
67
|
+
const o = $(h(l, s));
|
|
68
|
+
p.writeFileSync(m, o, "utf-8");
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
name: "next-vite-router",
|
|
72
|
+
configResolved(o) {
|
|
73
|
+
l = i.resolve(o.root, t), m = i.join(i.dirname(l), "virtual-next-vite-router.d.ts"), f();
|
|
74
|
+
},
|
|
75
|
+
resolveId(o) {
|
|
76
|
+
if (o === u)
|
|
77
|
+
return r;
|
|
78
|
+
},
|
|
79
|
+
load(o) {
|
|
80
|
+
if (o === r)
|
|
81
|
+
return `
|
|
82
|
+
import { buildRouteTree, treeToRoutes, normalizeSegment, createLazyElement } from 'next-vite-router';
|
|
83
|
+
import { Link, useRoutes } from 'react-router-dom';
|
|
84
|
+
|
|
85
|
+
const pagesGlob = import.meta.glob('/${t}/**/${s}');
|
|
86
|
+
const layoutsGlob = import.meta.glob('/${t}/**/${n}', { eager: true });
|
|
87
|
+
const notFoundsGlob = import.meta.glob('/${t}/**/${a}');
|
|
88
|
+
|
|
89
|
+
const transformPath = (path) => path.replace('/${t}/', '');
|
|
90
|
+
|
|
91
|
+
const pages = Object.fromEntries(
|
|
92
|
+
Object.entries(pagesGlob).map(([key, value]) => [transformPath(key), value])
|
|
93
|
+
);
|
|
94
|
+
const layouts = Object.fromEntries(
|
|
95
|
+
Object.entries(layoutsGlob).map(([key, value]) => [transformPath(key), value])
|
|
96
|
+
);
|
|
97
|
+
const notFounds = Object.fromEntries(
|
|
98
|
+
Object.entries(notFoundsGlob).map(([key, value]) => [transformPath(key), value])
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
export function generateRoutes() {
|
|
102
|
+
const tree = buildRouteTree(pages, layouts, notFounds);
|
|
103
|
+
const routes = treeToRoutes(tree, true);
|
|
104
|
+
return routes;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function Router() {
|
|
108
|
+
return useRoutes(generateRoutes());
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { Link, useRoutes };
|
|
112
|
+
`;
|
|
113
|
+
},
|
|
114
|
+
handleHotUpdate({ file: o, server: c }) {
|
|
115
|
+
if (o.includes(t) && (o.endsWith(s) || o.endsWith(n) || o.endsWith(a))) {
|
|
116
|
+
f();
|
|
117
|
+
const d = c.moduleGraph.getModuleById(
|
|
118
|
+
r
|
|
119
|
+
);
|
|
120
|
+
d && (c.moduleGraph.invalidateModule(d), c.ws.send({
|
|
121
|
+
type: "full-reload",
|
|
122
|
+
path: "*"
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
export {
|
|
129
|
+
g as a,
|
|
130
|
+
b as e,
|
|
131
|
+
y as n
|
|
132
|
+
};
|
package/dist/plugin.js
CHANGED
|
@@ -1,59 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
pageFile: n = "page.tsx",
|
|
5
|
-
layoutFile: a = "layout.tsx",
|
|
6
|
-
notFoundFile: u = "not-found.tsx"
|
|
7
|
-
} = i, s = "virtual:next-vite-router", o = "\0" + s;
|
|
8
|
-
return {
|
|
9
|
-
name: "next-vite-router",
|
|
10
|
-
resolveId(e) {
|
|
11
|
-
if (e === s)
|
|
12
|
-
return o;
|
|
13
|
-
},
|
|
14
|
-
load(e) {
|
|
15
|
-
if (e === o)
|
|
16
|
-
return `
|
|
17
|
-
import { buildRouteTree, treeToRoutes, normalizeSegment, createLazyElement } from 'next-vite-router';
|
|
18
|
-
|
|
19
|
-
const pagesGlob = import.meta.glob('/${t}/**/${n}');
|
|
20
|
-
const layoutsGlob = import.meta.glob('/${t}/**/${a}', { eager: true });
|
|
21
|
-
const notFoundsGlob = import.meta.glob('/${t}/**/${u}');
|
|
22
|
-
|
|
23
|
-
const transformPath = (path) => path.replace('/${t}/', '');
|
|
24
|
-
|
|
25
|
-
const pages = Object.fromEntries(
|
|
26
|
-
Object.entries(pagesGlob).map(([key, value]) => [transformPath(key), value])
|
|
27
|
-
);
|
|
28
|
-
const layouts = Object.fromEntries(
|
|
29
|
-
Object.entries(layoutsGlob).map(([key, value]) => [transformPath(key), value])
|
|
30
|
-
);
|
|
31
|
-
const notFounds = Object.fromEntries(
|
|
32
|
-
Object.entries(notFoundsGlob).map(([key, value]) => [transformPath(key), value])
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
export function generateRoutes() {
|
|
36
|
-
const tree = buildRouteTree(pages, layouts, notFounds);
|
|
37
|
-
const routes = treeToRoutes(tree, true);
|
|
38
|
-
return routes;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export { useRoutes } from 'react-router-dom';
|
|
42
|
-
`;
|
|
43
|
-
},
|
|
44
|
-
handleHotUpdate({ file: e, server: r }) {
|
|
45
|
-
if (e.includes(t) && (e.endsWith(n) || e.endsWith(a) || e.endsWith(u))) {
|
|
46
|
-
const l = r.moduleGraph.getModuleById(
|
|
47
|
-
o
|
|
48
|
-
);
|
|
49
|
-
l && (r.moduleGraph.invalidateModule(l), r.ws.send({
|
|
50
|
-
type: "full-reload",
|
|
51
|
-
path: "*"
|
|
52
|
-
}));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
}
|
|
1
|
+
import "node:fs";
|
|
2
|
+
import "node:path";
|
|
3
|
+
import { a as i } from "./index.plugin--ecyiAem.js";
|
|
57
4
|
export {
|
|
58
|
-
|
|
5
|
+
i as nextViteRouter
|
|
59
6
|
};
|
package/package.json
CHANGED
|
@@ -1,70 +1,72 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "next-vite-router",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "Next.js-like file-based routing for React + Vite",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"create-next-vite-router": "./dist/cli.cjs"
|
|
10
|
-
},
|
|
11
|
-
"exports": {
|
|
12
|
-
".": {
|
|
13
|
-
"import": "./dist/index.js",
|
|
14
|
-
"types": "./dist/index.d.ts"
|
|
15
|
-
},
|
|
16
|
-
"./plugin": {
|
|
17
|
-
"import": "./dist/plugin.js",
|
|
18
|
-
"types": "./dist/plugin.d.ts"
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"dist",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE"
|
|
25
|
-
],
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
},
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"react": "^18.0.0",
|
|
52
|
-
"react-dom": "^18.0.0",
|
|
53
|
-
"
|
|
54
|
-
"vite": "^5.0.0"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "next-vite-router",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Next.js-like file-based routing for React + Vite",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"create-next-vite-router": "./dist/cli.cjs"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./plugin": {
|
|
17
|
+
"import": "./dist/plugin.js",
|
|
18
|
+
"types": "./dist/plugin.d.ts"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"react",
|
|
28
|
+
"vite",
|
|
29
|
+
"router",
|
|
30
|
+
"nextjs",
|
|
31
|
+
"file-based-routing",
|
|
32
|
+
"filesystem-router",
|
|
33
|
+
"react-router"
|
|
34
|
+
],
|
|
35
|
+
"author": "Rlzee",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://github.com/Rlzee/next-vite-router"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://github.com/Rlzee/next-vite-router#readme",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"react": ">=18 <20",
|
|
44
|
+
"react-dom": ">=18 <20",
|
|
45
|
+
"react-router-dom": ">=6 <8",
|
|
46
|
+
"vite": ">=5 <9"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^24.10.1",
|
|
50
|
+
"@types/prompts": "^2.4.9",
|
|
51
|
+
"@types/react": "^18.0.0",
|
|
52
|
+
"@types/react-dom": "^18.0.0",
|
|
53
|
+
"typescript": "^5.0.0",
|
|
54
|
+
"vite": "^5.0.0",
|
|
55
|
+
"vite-plugin-dts": "^3.0.0"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"commander": "^14.0.2",
|
|
59
|
+
"kleur": "^4.1.5",
|
|
60
|
+
"prompts": "^2.4.2"
|
|
61
|
+
},
|
|
62
|
+
"scripts": {
|
|
63
|
+
"dev": "vite build --watch",
|
|
64
|
+
"build": "vite build && vite build -c vite.config.cli.ts",
|
|
65
|
+
"test:local": "node test/test-package.js",
|
|
66
|
+
"test:routes": "node test/test-route-types.js",
|
|
67
|
+
"test:generator": "node --test test/routes.test.js",
|
|
68
|
+
"test:compatibility": "node test/test-compatibility.js",
|
|
69
|
+
"preview": "pnpm pack --dry-run",
|
|
70
|
+
"cli": "cd test && node ../dist/cli.cjs"
|
|
71
|
+
}
|
|
72
|
+
}
|