next-vite-router 1.3.0 → 2.0.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 +14 -14
- package/dist/cli.cjs +66 -26
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +5 -12
- package/dist/index.d.ts +5 -12
- package/dist/index.js +108 -132
- package/dist/plugin.cjs +7 -7
- package/dist/plugin.js +88 -83
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -95,9 +95,8 @@ npm run dev
|
|
|
95
95
|
`Router` is only a convenience wrapper around `useRoutes(routes)`. The
|
|
96
96
|
lazy-loading behavior and `loadingFallback` configured through `configureRouter`
|
|
97
97
|
are read at render time, so they take effect even when `generateRoutes()` runs
|
|
98
|
-
at module scope before application setup finishes.
|
|
99
|
-
|
|
100
|
-
are wrapped while the tree is built. You can keep using React Router APIs:
|
|
98
|
+
at module scope before application setup finishes. You can keep using React
|
|
99
|
+
Router APIs:
|
|
101
100
|
|
|
102
101
|
```tsx
|
|
103
102
|
import {
|
|
@@ -230,28 +229,29 @@ The fallback is resolved when a route suspends during render, so the order of
|
|
|
230
229
|
`enableLazyLoading: false` is available for compatibility and testing. It does
|
|
231
230
|
not turn Vite's asynchronous imports into synchronous imports.
|
|
232
231
|
|
|
233
|
-
##
|
|
232
|
+
## Auth guards
|
|
234
233
|
|
|
235
|
-
|
|
236
|
-
|
|
234
|
+
Protect a subtree with a layout inside a route group: the group name stays out
|
|
235
|
+
of the URL, and the layout decides whether to render its `Outlet`:
|
|
237
236
|
|
|
238
237
|
```tsx
|
|
239
|
-
|
|
238
|
+
// src/app/(protected)/layout.tsx
|
|
239
|
+
import { Navigate, Outlet } from "react-router-dom";
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
241
|
+
export default function ProtectedLayout() {
|
|
242
|
+
const isAuthed = useAuth();
|
|
243
|
+
return isAuthed ? <Outlet /> : <Navigate to="/login" replace />;
|
|
244
|
+
}
|
|
244
245
|
```
|
|
245
246
|
|
|
246
|
-
|
|
247
|
-
replace React Router.
|
|
247
|
+
Every page under `src/app/(protected)/` is then guarded by `useAuth()`.
|
|
248
248
|
|
|
249
249
|
## CLI
|
|
250
250
|
|
|
251
251
|
For an interactive setup:
|
|
252
252
|
|
|
253
253
|
```bash
|
|
254
|
-
npx next-vite-router
|
|
254
|
+
npx next-vite-router create
|
|
255
255
|
```
|
|
256
256
|
|
|
257
257
|
The CLI creates a Vite React project, installs the package and
|
|
@@ -295,7 +295,7 @@ The repository includes a runnable showcase in [`examples/`](./examples/):
|
|
|
295
295
|
- `basic`
|
|
296
296
|
- `layouts`
|
|
297
297
|
- `dynamic-routes`
|
|
298
|
-
- `
|
|
298
|
+
- `(protected)`
|
|
299
299
|
- `typed-routes`
|
|
300
300
|
|
|
301
301
|
Run it from the examples directory:
|
package/dist/cli.cjs
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
const commander = require("commander");
|
|
4
4
|
const node_child_process = require("node:child_process");
|
|
5
5
|
const child_process = require("child_process");
|
|
6
|
+
const fs$1 = require("node:fs");
|
|
7
|
+
const path$1 = require("node:path");
|
|
6
8
|
const prompts = require("prompts");
|
|
7
9
|
const fs = require("fs");
|
|
8
10
|
const path = require("path");
|
|
@@ -30,13 +32,13 @@ function detectPackageManager() {
|
|
|
30
32
|
if (fromUA) candidates.push(fromUA);
|
|
31
33
|
if (preferred && !candidates.includes(preferred)) candidates.push(preferred);
|
|
32
34
|
["pnpm", "bun", "yarn", "npm"].forEach((p) => {
|
|
33
|
-
const
|
|
34
|
-
if (!candidates.includes(
|
|
35
|
+
const pm = p;
|
|
36
|
+
if (!candidates.includes(pm)) candidates.push(pm);
|
|
35
37
|
});
|
|
36
38
|
let chosen = null;
|
|
37
|
-
for (const
|
|
38
|
-
if (isAvailable(
|
|
39
|
-
chosen =
|
|
39
|
+
for (const pm of candidates) {
|
|
40
|
+
if (isAvailable(pm)) {
|
|
41
|
+
chosen = pm;
|
|
40
42
|
break;
|
|
41
43
|
}
|
|
42
44
|
}
|
|
@@ -87,7 +89,7 @@ if (typeof process !== "undefined") {
|
|
|
87
89
|
const $ = {
|
|
88
90
|
enabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== "dumb" && (FORCE_COLOR != null && FORCE_COLOR !== "0" || isTTY)
|
|
89
91
|
};
|
|
90
|
-
function init
|
|
92
|
+
function init(x, y) {
|
|
91
93
|
let rgx = new RegExp(`\\x1b\\[${y}m`, "g");
|
|
92
94
|
let open = `\x1B[${x}m`, close = `\x1B[${y}m`;
|
|
93
95
|
return function(txt) {
|
|
@@ -95,10 +97,10 @@ function init$1(x, y) {
|
|
|
95
97
|
return open + (!!~("" + txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;
|
|
96
98
|
};
|
|
97
99
|
}
|
|
98
|
-
const red = init
|
|
99
|
-
const green = init
|
|
100
|
-
const yellow = init
|
|
101
|
-
const cyan = init
|
|
100
|
+
const red = init(31, 39);
|
|
101
|
+
const green = init(32, 39);
|
|
102
|
+
const yellow = init(33, 39);
|
|
103
|
+
const cyan = init(36, 39);
|
|
102
104
|
const highlighter = {
|
|
103
105
|
error: red,
|
|
104
106
|
warn: yellow,
|
|
@@ -164,7 +166,6 @@ function updateAppTsConfig(projectDir, src) {
|
|
|
164
166
|
const aliasPath = src ? "./src/*" : "./*";
|
|
165
167
|
tsConfigApp.compilerOptions = {
|
|
166
168
|
...tsConfigApp.compilerOptions,
|
|
167
|
-
baseUrl: ".",
|
|
168
169
|
paths: {
|
|
169
170
|
...tsConfigApp.compilerOptions?.paths,
|
|
170
171
|
"@/*": [aliasPath]
|
|
@@ -194,12 +195,24 @@ function updateTsConfigJson(projectDir, src) {
|
|
|
194
195
|
if (!tsConfig.compilerOptions) {
|
|
195
196
|
tsConfig.compilerOptions = {};
|
|
196
197
|
}
|
|
197
|
-
tsConfig.compilerOptions.baseUrl = ".";
|
|
198
198
|
tsConfig.compilerOptions.paths = {
|
|
199
199
|
"@/*": [src ? "./src/*" : "./*"]
|
|
200
200
|
};
|
|
201
201
|
fs.writeFileSync(tsConfigPath, JSON.stringify(tsConfig, null, 2), "utf-8");
|
|
202
202
|
}
|
|
203
|
+
function updateIndexHtml(projectDir, src) {
|
|
204
|
+
if (src) return;
|
|
205
|
+
const indexPath = path.join(projectDir, "index.html");
|
|
206
|
+
if (!fs.existsSync(indexPath)) return;
|
|
207
|
+
const content = fs.readFileSync(indexPath, "utf-8");
|
|
208
|
+
const updated = content.replace(
|
|
209
|
+
/(src\s*=\s*["'])\/src\/main\.tsx(["'])/,
|
|
210
|
+
"$1/main.tsx$2"
|
|
211
|
+
);
|
|
212
|
+
if (updated !== content) {
|
|
213
|
+
fs.writeFileSync(indexPath, updated, "utf-8");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
203
216
|
function createVirtualDTS(projectDir, useSrc) {
|
|
204
217
|
const targetDir = useSrc ? path.join(projectDir, "src") : projectDir;
|
|
205
218
|
if (useSrc && !fs.existsSync(targetDir)) {
|
|
@@ -374,7 +387,6 @@ function addTailwindToViteConfig(projectDir) {
|
|
|
374
387
|
}
|
|
375
388
|
writeViteConfig(projectDir, updatedContent);
|
|
376
389
|
}
|
|
377
|
-
const pm$1 = detectPackageManager();
|
|
378
390
|
function startNextViteRouterConfig({
|
|
379
391
|
projectDir = process.cwd(),
|
|
380
392
|
src,
|
|
@@ -382,16 +394,31 @@ function startNextViteRouterConfig({
|
|
|
382
394
|
}) {
|
|
383
395
|
startViteConfig(projectDir, src);
|
|
384
396
|
const srcPath = path.join(projectDir, "src");
|
|
385
|
-
if (
|
|
397
|
+
if (src) {
|
|
398
|
+
for (const entry of [
|
|
399
|
+
"App.tsx",
|
|
400
|
+
"App.css",
|
|
401
|
+
"index.css",
|
|
402
|
+
"main.tsx",
|
|
403
|
+
"assets"
|
|
404
|
+
]) {
|
|
405
|
+
const entryPath = path.join(srcPath, entry);
|
|
406
|
+
if (fs.existsSync(entryPath)) {
|
|
407
|
+
fs.rmSync(entryPath, { recursive: true, force: true });
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
} else if (fs.existsSync(srcPath)) {
|
|
386
411
|
fs.rmSync(srcPath, { recursive: true, force: true });
|
|
387
412
|
}
|
|
388
413
|
updateTsConfigJson(projectDir, src);
|
|
389
414
|
updateAppTsConfig(projectDir, src);
|
|
390
415
|
createVirtualDTS(projectDir, src);
|
|
391
416
|
createMainTSX(projectDir, src);
|
|
417
|
+
updateIndexHtml(projectDir, src);
|
|
392
418
|
if (tailwindcss) {
|
|
393
419
|
logger.info("Setting up Tailwind CSS...");
|
|
394
|
-
const
|
|
420
|
+
const pm = detectPackageManager();
|
|
421
|
+
const addDevDepsCmd = pm.addDevDepsCommand([
|
|
395
422
|
"tailwindcss",
|
|
396
423
|
"@tailwindcss/vite"
|
|
397
424
|
]);
|
|
@@ -434,7 +461,7 @@ ${resolveConfig}
|
|
|
434
461
|
}
|
|
435
462
|
const pluginsRegex = /plugins\s*:\s*\[(.*?)\]/s;
|
|
436
463
|
const match = viteConfigContent.match(pluginsRegex);
|
|
437
|
-
const pluginString = "nextViteRouter()";
|
|
464
|
+
const pluginString = src ? "nextViteRouter()" : 'nextViteRouter({ pagesDir: "app" })';
|
|
438
465
|
if (match) {
|
|
439
466
|
const existing = match[1].trim();
|
|
440
467
|
const newPlugins = existing ? `${existing}, ${pluginString}` : pluginString;
|
|
@@ -451,9 +478,9 @@ ${resolveConfig}
|
|
|
451
478
|
}
|
|
452
479
|
writeViteConfig(projectDir, viteConfigContent);
|
|
453
480
|
}
|
|
454
|
-
const
|
|
455
|
-
const
|
|
456
|
-
"
|
|
481
|
+
const PROJECT_NAME_RE = /^[a-z0-9][a-z0-9._-]*$/i;
|
|
482
|
+
const create = new commander.Command().name("create").description(
|
|
483
|
+
"Create a new Vite project with next-vite-router configuration"
|
|
457
484
|
).action(async () => {
|
|
458
485
|
const projectNameResponse = await prompts(
|
|
459
486
|
{
|
|
@@ -470,6 +497,16 @@ const init = new commander.Command().name("init").description(
|
|
|
470
497
|
}
|
|
471
498
|
);
|
|
472
499
|
const projectName = projectNameResponse.projectName;
|
|
500
|
+
if (!PROJECT_NAME_RE.test(projectName)) {
|
|
501
|
+
logger.error(
|
|
502
|
+
"Invalid project name (letters, digits, '.', '_' and '-' only)."
|
|
503
|
+
);
|
|
504
|
+
process.exit(1);
|
|
505
|
+
}
|
|
506
|
+
if (fs$1.existsSync(path$1.resolve(projectName))) {
|
|
507
|
+
logger.error(`Directory "${projectName}" already exists.`);
|
|
508
|
+
process.exit(1);
|
|
509
|
+
}
|
|
473
510
|
const variantResponse = await prompts(
|
|
474
511
|
{
|
|
475
512
|
type: "select",
|
|
@@ -522,12 +559,10 @@ const init = new commander.Command().name("init").description(
|
|
|
522
559
|
}
|
|
523
560
|
);
|
|
524
561
|
const useTailwind = tailwindResponse.useTailwind;
|
|
562
|
+
const pm = detectPackageManager();
|
|
525
563
|
const createCommand = pm.createProjectCommand(projectName, variant);
|
|
526
564
|
logger.info(`Creating project "${projectName}" using ${pm.name}...`);
|
|
527
|
-
child_process.execSync(createCommand, {
|
|
528
|
-
stdio: ["pipe", "inherit", "inherit"],
|
|
529
|
-
input: "n\n"
|
|
530
|
-
});
|
|
565
|
+
child_process.execSync(createCommand, { stdio: "inherit" });
|
|
531
566
|
logger.info("Installing dependencies...");
|
|
532
567
|
child_process.execSync(pm.installCommand, { stdio: "inherit", cwd: projectName });
|
|
533
568
|
logger.info(
|
|
@@ -548,13 +583,18 @@ const init = new commander.Command().name("init").description(
|
|
|
548
583
|
Project "${projectName}" is ready!
|
|
549
584
|
`);
|
|
550
585
|
});
|
|
551
|
-
const version = "
|
|
586
|
+
const version = "2.0.0";
|
|
552
587
|
const pkg = {
|
|
553
588
|
version
|
|
554
589
|
};
|
|
555
590
|
async function main() {
|
|
556
591
|
const program = new commander.Command();
|
|
557
|
-
program.name("
|
|
558
|
-
|
|
592
|
+
program.name("next-vite-router").version(pkg.version).addCommand(create);
|
|
593
|
+
try {
|
|
594
|
+
await program.parseAsync(process.argv);
|
|
595
|
+
} catch (e) {
|
|
596
|
+
logger.error(e instanceof Error ? e.message : String(e));
|
|
597
|
+
process.exit(1);
|
|
598
|
+
}
|
|
559
599
|
}
|
|
560
600
|
main();
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("./tree-hc1dSMdb.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("./tree-hc1dSMdb.cjs"),u=require("react"),z=require("react-router-dom"),C={enableLazyLoading:!0};let f={...C};function L(e){f={...f,...e}}function S(){f={...C}}function v(){return f}const F=()=>u.createElement("div"),h=new Map;function T(){const e=v();if(e.enableLazyLoading===!1)return null;const t=e.loadingFallback||F;return u.createElement(t)}function A(){h.clear()}function g(e,t){let n=h.get(t);return n||(n=u.lazy(e),h.set(t,n)),u.createElement(u.Suspense,{fallback:u.createElement(T)},u.createElement(n))}const d=u.createContext(void 0);function P({name:e,children:t}){return u.createElement(d.Provider,{value:e},t)}function N(){return u.useContext(d)}function k(e){const t=c.parseRouteSegments(e)[0];return(t==null?void 0:t.kind)==="catchAll"&&t.optional}function p(e){const t=c.parseRouteSegments(e)[0];return t?c.routeSegmentToPath(t):""}function s(e,t){return m(e,t,!0)}function m(e,t,n=!1){const a=e.page;if(!a)throw new Error(`Route node "${e.fullPath}" has no page loader`);const r=g(async()=>({default:(await a()).default}),`page:${e.fullPath||t}`),o=c.parseRouteSegments(e.segment)[0],l=(o==null?void 0:o.kind)==="catchAll"?u.createElement(P,{name:o.name,children:r}):r;return n?{index:!0,element:l}:{path:p(e.segment),element:l}}function w(e){const t=e.notFound;if(!t)throw new Error(`Route node "${e.fullPath}" has no not-found loader`);return{path:"*",element:g(async()=>({default:(await t()).default}),`notfound:${e.fullPath}`)}}function y(e){return e.notFound?[w(e)]:[]}function x(e,t,n){return{...e?{path:e}:{},element:u.createElement(t),children:n.length>0?n:void 0}}function E(e,t){const n=[];return[...e.children.entries()].sort(([a],[r])=>a.localeCompare(r)).forEach(([a,r])=>{const o=p(a),l=o?t?`${t}/${o}`:`/${o}`:t;n.push(...R(r,!1,l))}),n}function b(e,t){const n=[];return e.page&&n.push(s(e,t||"/")),n.push(...E(e,t)),n.push(...y(e)),n}function $(e,t,n,a,r,o){if(k(e.segment)){const l=[...r,...o];return[s(e,t),{path:a,element:m(e,n).element,children:l.length>0?l:void 0}]}return r.length>0||o.length>0?[{path:a,children:[s(e,n),...r,...o]}]:[{path:a,element:m(e,n).element}]}function D(e,t,n,a){const r=[...e.page?[s(e,t)]:[],...n,...a];return[{children:r.length>0?r:void 0}]}function q(e){const t=b(e,"");return e.layout?[{path:"/",element:u.createElement(e.layout),children:t}]:e.page?t.length>1?[{path:"/",children:t}]:[{path:"/",element:m(e,"/",!1).element}]:e.notFound?[{path:"/",children:t}]:t}function R(e,t=!1,n=""){if(t)return q(e);const a=p(e.segment),r=!a,o=r?n:n+"/"+a,l=E(e,o),i=y(e);return e.layout?[x(r?"":a,e.layout,b(e,o))]:e.page&&!r?$(e,n,o,a,l,i):e.page||e.notFound||!r?r?D(e,o,l,i):[{path:a,children:[...e.page?[s(e,o)]:[],...l,...i]}]:l}function G(e,t,n,a){return()=>{const r=c.buildRouteTree(e,t,n,a);return R(r,!0)}}function M(){const e=z.useParams(),t=N();return typeof t=="string"&&e["*"]!==void 0?{...e,[t]:e["*"]}:e}exports.assertNoDuplicateRoutes=c.assertNoDuplicateRoutes;exports.assertNoRouteConflicts=c.assertNoRouteConflicts;exports.buildRouteTree=c.buildRouteTree;exports.extractRoutePath=c.extractRoutePath;exports.normalizeSegment=c.normalizeSegment;exports.parseRouteSegments=c.parseRouteSegments;exports.routeSegmentToPath=c.routeSegmentToPath;exports.CatchAllParamProvider=P;exports.clearLazyCache=A;exports.configureRouter=L;exports.createLazyElement=g;exports.createRouteGenerator=G;exports.resetRouterConfig=S;exports.treeToRoutes=R;exports.useParams=M;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ComponentType } from 'react';
|
|
2
2
|
import { default as default_2 } from 'react';
|
|
3
|
-
import { ReactElement } from 'react';
|
|
4
3
|
import { RouteObject } from 'react-router-dom';
|
|
5
4
|
|
|
6
5
|
export declare function assertNoDuplicateRoutes(filePaths: string[], fileOptions?: RouteFileOptions): void;
|
|
@@ -21,21 +20,18 @@ export declare function CatchAllParamProvider({ name, children, }: {
|
|
|
21
20
|
* `React.lazy` component created in one context (for example a previous test)
|
|
22
21
|
* is reused whenever another context requests the same key with a different
|
|
23
22
|
* loader. Exposing an explicit reset keeps that state from leaking, mirroring
|
|
24
|
-
* `
|
|
23
|
+
* `resetRouterConfig` for the router configuration.
|
|
25
24
|
*/
|
|
26
25
|
export declare function clearLazyCache(): void;
|
|
27
26
|
|
|
28
|
-
export declare function clearMiddlewares(): void;
|
|
29
|
-
|
|
30
27
|
export declare function configureRouter(config: RouterConfig): void;
|
|
31
28
|
|
|
32
29
|
/**
|
|
33
|
-
* Create a lazy element wrapped with Suspense
|
|
30
|
+
* Create a lazy element wrapped with Suspense
|
|
34
31
|
* @param loader - Function that loads the component
|
|
35
32
|
* @param cacheKey - Unique key for the cache
|
|
36
|
-
* @param routePath - Route path for middlewares
|
|
37
33
|
*/
|
|
38
|
-
export declare function createLazyElement(loader: () => Promise<any>, cacheKey: string
|
|
34
|
+
export declare function createLazyElement(loader: () => Promise<any>, cacheKey: string): default_2.ReactElement;
|
|
39
35
|
|
|
40
36
|
/**
|
|
41
37
|
* Create a custom route generator function using your own files
|
|
@@ -81,15 +77,14 @@ export declare function normalizeSegment(segment: string): string;
|
|
|
81
77
|
|
|
82
78
|
export declare function parseRouteSegments(routePath: string): RouteSegment[];
|
|
83
79
|
|
|
84
|
-
export declare function registerMiddleware(pattern: RegExp, middleware: RouteMiddleware): void;
|
|
85
|
-
|
|
86
80
|
/**
|
|
87
81
|
* Restore the module-level router configuration to its defaults.
|
|
88
82
|
*
|
|
89
83
|
* `configureRouter` merges, so it can never drop keys back to their initial
|
|
90
84
|
* state. A dedicated reset lets isolated contexts (for example tests) start
|
|
91
85
|
* from a known configuration instead of inheriting whatever was set globally
|
|
92
|
-
* before, matching the explicit reset offered by `
|
|
86
|
+
* before, matching the explicit reset offered by `clearLazyCache` for the lazy
|
|
87
|
+
* component cache.
|
|
93
88
|
*/
|
|
94
89
|
export declare function resetRouterConfig(): void;
|
|
95
90
|
|
|
@@ -100,8 +95,6 @@ export declare type RouteFileOptions = {
|
|
|
100
95
|
notFoundFile?: string;
|
|
101
96
|
};
|
|
102
97
|
|
|
103
|
-
export declare type RouteMiddleware = (element: ReactElement) => ReactElement;
|
|
104
|
-
|
|
105
98
|
export declare type RouteModuleLoader = () => Promise<{
|
|
106
99
|
default: ComponentType;
|
|
107
100
|
}>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ComponentType } from 'react';
|
|
2
2
|
import { default as default_2 } from 'react';
|
|
3
|
-
import { ReactElement } from 'react';
|
|
4
3
|
import { RouteObject } from 'react-router-dom';
|
|
5
4
|
|
|
6
5
|
export declare function assertNoDuplicateRoutes(filePaths: string[], fileOptions?: RouteFileOptions): void;
|
|
@@ -21,21 +20,18 @@ export declare function CatchAllParamProvider({ name, children, }: {
|
|
|
21
20
|
* `React.lazy` component created in one context (for example a previous test)
|
|
22
21
|
* is reused whenever another context requests the same key with a different
|
|
23
22
|
* loader. Exposing an explicit reset keeps that state from leaking, mirroring
|
|
24
|
-
* `
|
|
23
|
+
* `resetRouterConfig` for the router configuration.
|
|
25
24
|
*/
|
|
26
25
|
export declare function clearLazyCache(): void;
|
|
27
26
|
|
|
28
|
-
export declare function clearMiddlewares(): void;
|
|
29
|
-
|
|
30
27
|
export declare function configureRouter(config: RouterConfig): void;
|
|
31
28
|
|
|
32
29
|
/**
|
|
33
|
-
* Create a lazy element wrapped with Suspense
|
|
30
|
+
* Create a lazy element wrapped with Suspense
|
|
34
31
|
* @param loader - Function that loads the component
|
|
35
32
|
* @param cacheKey - Unique key for the cache
|
|
36
|
-
* @param routePath - Route path for middlewares
|
|
37
33
|
*/
|
|
38
|
-
export declare function createLazyElement(loader: () => Promise<any>, cacheKey: string
|
|
34
|
+
export declare function createLazyElement(loader: () => Promise<any>, cacheKey: string): default_2.ReactElement;
|
|
39
35
|
|
|
40
36
|
/**
|
|
41
37
|
* Create a custom route generator function using your own files
|
|
@@ -81,15 +77,14 @@ export declare function normalizeSegment(segment: string): string;
|
|
|
81
77
|
|
|
82
78
|
export declare function parseRouteSegments(routePath: string): RouteSegment[];
|
|
83
79
|
|
|
84
|
-
export declare function registerMiddleware(pattern: RegExp, middleware: RouteMiddleware): void;
|
|
85
|
-
|
|
86
80
|
/**
|
|
87
81
|
* Restore the module-level router configuration to its defaults.
|
|
88
82
|
*
|
|
89
83
|
* `configureRouter` merges, so it can never drop keys back to their initial
|
|
90
84
|
* state. A dedicated reset lets isolated contexts (for example tests) start
|
|
91
85
|
* from a known configuration instead of inheriting whatever was set globally
|
|
92
|
-
* before, matching the explicit reset offered by `
|
|
86
|
+
* before, matching the explicit reset offered by `clearLazyCache` for the lazy
|
|
87
|
+
* component cache.
|
|
93
88
|
*/
|
|
94
89
|
export declare function resetRouterConfig(): void;
|
|
95
90
|
|
|
@@ -100,8 +95,6 @@ export declare type RouteFileOptions = {
|
|
|
100
95
|
notFoundFile?: string;
|
|
101
96
|
};
|
|
102
97
|
|
|
103
|
-
export declare type RouteMiddleware = (element: ReactElement) => ReactElement;
|
|
104
|
-
|
|
105
98
|
export declare type RouteModuleLoader = () => Promise<{
|
|
106
99
|
default: ComponentType;
|
|
107
100
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -1,227 +1,203 @@
|
|
|
1
|
-
import { p as h, r as F, b } from "./tree-DfnssFxU.js";
|
|
2
|
-
import { a as
|
|
3
|
-
import
|
|
4
|
-
import { useParams as
|
|
5
|
-
const
|
|
1
|
+
import { p as h, r as F, b as L } from "./tree-DfnssFxU.js";
|
|
2
|
+
import { a as Y, c as Z, e as _, n as K } from "./tree-DfnssFxU.js";
|
|
3
|
+
import l, { lazy as b, Suspense as v, createContext as z, useContext as x } from "react";
|
|
4
|
+
import { useParams as A } from "react-router-dom";
|
|
5
|
+
const g = {
|
|
6
6
|
enableLazyLoading: !0
|
|
7
7
|
};
|
|
8
|
-
let i = { ...
|
|
9
|
-
function
|
|
8
|
+
let i = { ...g };
|
|
9
|
+
function H(t) {
|
|
10
10
|
i = { ...i, ...t };
|
|
11
11
|
}
|
|
12
|
-
function
|
|
13
|
-
i = { ...
|
|
12
|
+
function J() {
|
|
13
|
+
i = { ...g };
|
|
14
14
|
}
|
|
15
|
-
function
|
|
15
|
+
function $() {
|
|
16
16
|
return i;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
function X() {
|
|
23
|
-
p = [];
|
|
24
|
-
}
|
|
25
|
-
function R(t, e) {
|
|
26
|
-
let r = e;
|
|
27
|
-
for (const n of p)
|
|
28
|
-
n.pattern.lastIndex = 0, n.pattern.test(t) && (r = n.middleware(r)), n.pattern.lastIndex = 0;
|
|
29
|
-
return r;
|
|
30
|
-
}
|
|
31
|
-
const M = () => u.createElement("div"), m = /* @__PURE__ */ new Map();
|
|
32
|
-
function T() {
|
|
33
|
-
const t = N();
|
|
18
|
+
const k = () => l.createElement("div"), m = /* @__PURE__ */ new Map();
|
|
19
|
+
function w() {
|
|
20
|
+
const t = $();
|
|
34
21
|
if (t.enableLazyLoading === !1)
|
|
35
22
|
return null;
|
|
36
|
-
const e = t.loadingFallback ||
|
|
37
|
-
return
|
|
23
|
+
const e = t.loadingFallback || k;
|
|
24
|
+
return l.createElement(e);
|
|
38
25
|
}
|
|
39
|
-
function
|
|
26
|
+
function Q() {
|
|
40
27
|
m.clear();
|
|
41
28
|
}
|
|
42
|
-
function
|
|
29
|
+
function R(t, e) {
|
|
43
30
|
let n = m.get(e);
|
|
44
|
-
n || (n =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
u.createElement(n)
|
|
31
|
+
return n || (n = b(t), m.set(e, n)), l.createElement(
|
|
32
|
+
v,
|
|
33
|
+
{ fallback: l.createElement(w) },
|
|
34
|
+
l.createElement(n)
|
|
49
35
|
);
|
|
50
|
-
return r ? R(r, a) : a;
|
|
51
36
|
}
|
|
52
|
-
const
|
|
53
|
-
function
|
|
37
|
+
const C = z(void 0);
|
|
38
|
+
function N({
|
|
54
39
|
name: t,
|
|
55
40
|
children: e
|
|
56
41
|
}) {
|
|
57
|
-
return
|
|
58
|
-
|
|
42
|
+
return l.createElement(
|
|
43
|
+
C.Provider,
|
|
59
44
|
{ value: t },
|
|
60
45
|
e
|
|
61
46
|
);
|
|
62
47
|
}
|
|
63
|
-
function
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
function P(t, e) {
|
|
67
|
-
return R(t, u.createElement(e));
|
|
48
|
+
function T() {
|
|
49
|
+
return x(C);
|
|
68
50
|
}
|
|
69
|
-
function
|
|
51
|
+
function S(t) {
|
|
70
52
|
const e = h(t)[0];
|
|
71
53
|
return (e == null ? void 0 : e.kind) === "catchAll" && e.optional;
|
|
72
54
|
}
|
|
73
|
-
function
|
|
55
|
+
function p(t) {
|
|
74
56
|
const e = h(t)[0];
|
|
75
57
|
return e ? F(e) : "";
|
|
76
58
|
}
|
|
77
59
|
function c(t, e) {
|
|
78
60
|
return f(t, e, !0);
|
|
79
61
|
}
|
|
80
|
-
function f(t, e,
|
|
81
|
-
const
|
|
82
|
-
if (!
|
|
62
|
+
function f(t, e, n = !1) {
|
|
63
|
+
const a = t.page;
|
|
64
|
+
if (!a)
|
|
83
65
|
throw new Error(`Route node "${t.fullPath}" has no page loader`);
|
|
84
|
-
const
|
|
85
|
-
async () => ({ default: (await
|
|
86
|
-
`page:${t.fullPath || e}
|
|
87
|
-
|
|
88
|
-
), o = h(t.segment)[0], l = (o == null ? void 0 : o.kind) === "catchAll" ? u.createElement(I, {
|
|
66
|
+
const r = R(
|
|
67
|
+
async () => ({ default: (await a()).default }),
|
|
68
|
+
`page:${t.fullPath || e}`
|
|
69
|
+
), o = h(t.segment)[0], u = (o == null ? void 0 : o.kind) === "catchAll" ? l.createElement(N, {
|
|
89
70
|
name: o.name,
|
|
90
|
-
children:
|
|
91
|
-
}) :
|
|
92
|
-
return
|
|
71
|
+
children: r
|
|
72
|
+
}) : r;
|
|
73
|
+
return n ? { index: !0, element: u } : { path: p(t.segment), element: u };
|
|
93
74
|
}
|
|
94
|
-
function
|
|
75
|
+
function D(t) {
|
|
95
76
|
const e = t.notFound;
|
|
96
77
|
if (!e)
|
|
97
78
|
throw new Error(`Route node "${t.fullPath}" has no not-found loader`);
|
|
98
|
-
const r = t.fullPath ? `/${t.fullPath}` : "/";
|
|
99
79
|
return {
|
|
100
80
|
path: "*",
|
|
101
|
-
element:
|
|
81
|
+
element: R(
|
|
102
82
|
async () => ({ default: (await e()).default }),
|
|
103
|
-
`notfound:${t.fullPath}
|
|
104
|
-
r
|
|
83
|
+
`notfound:${t.fullPath}`
|
|
105
84
|
)
|
|
106
85
|
};
|
|
107
86
|
}
|
|
108
|
-
function
|
|
109
|
-
return t.notFound ? [
|
|
87
|
+
function d(t) {
|
|
88
|
+
return t.notFound ? [D(t)] : [];
|
|
110
89
|
}
|
|
111
|
-
function
|
|
90
|
+
function G(t, e, n) {
|
|
112
91
|
return {
|
|
113
|
-
...
|
|
114
|
-
element:
|
|
92
|
+
...t ? { path: t } : {},
|
|
93
|
+
element: l.createElement(e),
|
|
115
94
|
children: n.length > 0 ? n : void 0
|
|
116
95
|
};
|
|
117
96
|
}
|
|
118
|
-
function
|
|
119
|
-
const
|
|
120
|
-
return [...t.children.entries()].sort(([
|
|
121
|
-
const o =
|
|
122
|
-
|
|
123
|
-
}),
|
|
97
|
+
function y(t, e) {
|
|
98
|
+
const n = [];
|
|
99
|
+
return [...t.children.entries()].sort(([a], [r]) => a.localeCompare(r)).forEach(([a, r]) => {
|
|
100
|
+
const o = p(a), u = o ? e ? `${e}/${o}` : `/${o}` : e;
|
|
101
|
+
n.push(...P(r, !1, u));
|
|
102
|
+
}), n;
|
|
124
103
|
}
|
|
125
|
-
function
|
|
126
|
-
const
|
|
127
|
-
return t.page &&
|
|
104
|
+
function E(t, e) {
|
|
105
|
+
const n = [];
|
|
106
|
+
return t.page && n.push(c(t, e || "/")), n.push(...y(t, e)), n.push(...d(t)), n;
|
|
128
107
|
}
|
|
129
|
-
function
|
|
130
|
-
if (
|
|
131
|
-
const
|
|
108
|
+
function I(t, e, n, a, r, o) {
|
|
109
|
+
if (S(t.segment)) {
|
|
110
|
+
const u = [...r, ...o];
|
|
132
111
|
return [
|
|
133
112
|
c(t, e),
|
|
134
113
|
{
|
|
135
|
-
path:
|
|
136
|
-
element: f(t,
|
|
137
|
-
children:
|
|
114
|
+
path: a,
|
|
115
|
+
element: f(t, n).element,
|
|
116
|
+
children: u.length > 0 ? u : void 0
|
|
138
117
|
}
|
|
139
118
|
];
|
|
140
119
|
}
|
|
141
|
-
return
|
|
142
|
-
path:
|
|
120
|
+
return r.length > 0 || o.length > 0 ? [{
|
|
121
|
+
path: a,
|
|
143
122
|
children: [
|
|
144
|
-
c(t,
|
|
145
|
-
...
|
|
123
|
+
c(t, n),
|
|
124
|
+
...r,
|
|
146
125
|
...o
|
|
147
126
|
]
|
|
148
127
|
}] : [{
|
|
149
|
-
path:
|
|
150
|
-
element: f(t,
|
|
128
|
+
path: a,
|
|
129
|
+
element: f(t, n).element
|
|
151
130
|
}];
|
|
152
131
|
}
|
|
153
|
-
function
|
|
154
|
-
const
|
|
132
|
+
function M(t, e, n, a) {
|
|
133
|
+
const r = [
|
|
155
134
|
...t.page ? [c(t, e)] : [],
|
|
156
|
-
...
|
|
157
|
-
...
|
|
135
|
+
...n,
|
|
136
|
+
...a
|
|
158
137
|
];
|
|
159
138
|
return [{
|
|
160
|
-
children:
|
|
139
|
+
children: r.length > 0 ? r : void 0
|
|
161
140
|
}];
|
|
162
141
|
}
|
|
163
|
-
function
|
|
164
|
-
const e =
|
|
142
|
+
function O(t) {
|
|
143
|
+
const e = E(t, "");
|
|
165
144
|
return t.layout ? [{
|
|
166
145
|
path: "/",
|
|
167
|
-
element:
|
|
146
|
+
element: l.createElement(t.layout),
|
|
168
147
|
children: e
|
|
169
148
|
}] : t.page ? e.length > 1 ? [{ path: "/", children: e }] : [{
|
|
170
149
|
path: "/",
|
|
171
150
|
element: f(t, "/", !1).element
|
|
172
151
|
}] : t.notFound ? [{ path: "/", children: e }] : e;
|
|
173
152
|
}
|
|
174
|
-
function
|
|
153
|
+
function P(t, e = !1, n = "") {
|
|
175
154
|
if (e)
|
|
176
|
-
return
|
|
177
|
-
const
|
|
178
|
-
return t.layout ? [
|
|
179
|
-
|
|
180
|
-
a ? "" : n,
|
|
155
|
+
return O(t);
|
|
156
|
+
const a = p(t.segment), r = !a, o = r ? n : n + "/" + a, u = y(t, o), s = d(t);
|
|
157
|
+
return t.layout ? [G(
|
|
158
|
+
r ? "" : a,
|
|
181
159
|
t.layout,
|
|
182
|
-
|
|
183
|
-
)] : t.page && !
|
|
160
|
+
E(t, o)
|
|
161
|
+
)] : t.page && !r ? I(
|
|
184
162
|
t,
|
|
185
|
-
r,
|
|
186
|
-
o,
|
|
187
163
|
n,
|
|
188
|
-
|
|
164
|
+
o,
|
|
165
|
+
a,
|
|
166
|
+
u,
|
|
189
167
|
s
|
|
190
|
-
) : t.page || t.notFound || !
|
|
191
|
-
path:
|
|
168
|
+
) : t.page || t.notFound || !r ? r ? M(t, o, u, s) : [{
|
|
169
|
+
path: a,
|
|
192
170
|
children: [
|
|
193
171
|
...t.page ? [c(t, o)] : [],
|
|
194
|
-
...
|
|
172
|
+
...u,
|
|
195
173
|
...s
|
|
196
174
|
]
|
|
197
|
-
}] :
|
|
175
|
+
}] : u;
|
|
198
176
|
}
|
|
199
|
-
function
|
|
177
|
+
function U(t, e, n, a) {
|
|
200
178
|
return () => {
|
|
201
|
-
const
|
|
202
|
-
return
|
|
179
|
+
const r = L(t, e, n, a);
|
|
180
|
+
return P(r, !0);
|
|
203
181
|
};
|
|
204
182
|
}
|
|
205
|
-
function
|
|
206
|
-
const t =
|
|
183
|
+
function V() {
|
|
184
|
+
const t = A(), e = T();
|
|
207
185
|
return typeof e == "string" && t["*"] !== void 0 ? { ...t, [e]: t["*"] } : t;
|
|
208
186
|
}
|
|
209
187
|
export {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
at as normalizeSegment,
|
|
188
|
+
N as CatchAllParamProvider,
|
|
189
|
+
Y as assertNoDuplicateRoutes,
|
|
190
|
+
Z as assertNoRouteConflicts,
|
|
191
|
+
L as buildRouteTree,
|
|
192
|
+
Q as clearLazyCache,
|
|
193
|
+
H as configureRouter,
|
|
194
|
+
R as createLazyElement,
|
|
195
|
+
U as createRouteGenerator,
|
|
196
|
+
_ as extractRoutePath,
|
|
197
|
+
K as normalizeSegment,
|
|
221
198
|
h as parseRouteSegments,
|
|
222
|
-
|
|
223
|
-
V as resetRouterConfig,
|
|
199
|
+
J as resetRouterConfig,
|
|
224
200
|
F as routeSegmentToPath,
|
|
225
|
-
|
|
226
|
-
|
|
201
|
+
P as treeToRoutes,
|
|
202
|
+
V as useParams
|
|
227
203
|
};
|
package/dist/plugin.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("node:fs"),
|
|
2
|
-
`),s=
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("node:fs"),f=require("node:path"),x=require("./tree-hc1dSMdb.cjs");function S(r){const a=r.map(x.routeSegmentToPath).filter(Boolean);return a.length>0?`/${a.join("/")}`:"/"}function T(r){const a=[["pagesDir",r.pagesDir],["pageFile",r.pageFile],["layoutFile",r.layoutFile],["notFoundFile",r.notFoundFile]];for(const[o,e]of a)if(!e.trim())throw new Error(`nextViteRouter option "${o}" must not be empty.`);const s=a.slice(1),i=s.find(([,o],e)=>s.slice(e+1).some(([,n])=>n===o));if(i)throw new Error(`nextViteRouter file options must be distinct; "${i[0]}" is duplicated.`)}function k(r){return r.replace(/\\/g,"/").replace(/^\.\//,"").replace(/^\/|\/$/g,"")}function G(r,a,s){const i=a.pageFile??"page.tsx",o=new Map;for(const e of R(r,i,s)){const n=x.extractRoutePath(e,a),l=x.parseRouteSegments(n),g=l.filter(u=>u.kind==="dynamic"||u.kind==="catchAll").map(u=>({name:u.name,optional:u.kind==="catchAll"&&u.optional})),p=S(l);o.set(p,{path:p,params:g});const m=l[l.length-1];if((m==null?void 0:m.kind)==="catchAll"&&m.optional){const u=S(l.slice(0,-1));o.has(u)||o.set(u,{path:u,params:[]})}}return[...o.values()].sort((e,n)=>e.path.localeCompare(n.path))}function R(r,a,s){const i=[];function o(e){for(const n of b.readdirSync(e,{withFileTypes:!0})){const l=f.join(e,n.name);if(n.isDirectory())o(l);else if(n.isFile()&&n.name===a){const g=f.relative(r,l).replace(/\\/g,"/");i.push(`/${s}/${g}`)}}}return b.existsSync(r)&&o(r),i}function O(r){const a=r.map(({path:i})=>` | ${JSON.stringify(i)}`).join(`
|
|
2
|
+
`),s=r.map(({path:i,params:o})=>{const e=o.length>0?[...o.map(({name:n,optional:l})=>` ${n}${l?"?":""}: string;`)].join(`
|
|
3
3
|
`):" [key: string]: never;";return` ${JSON.stringify(i)}: {
|
|
4
4
|
${e}
|
|
5
5
|
};`}).join(`
|
|
@@ -23,12 +23,12 @@ ${s}
|
|
|
23
23
|
export function useParams<T extends Record<string, string | undefined> = Record<string, string | undefined>>(): T;
|
|
24
24
|
export { Link, useRoutes } from 'react-router-dom';
|
|
25
25
|
}
|
|
26
|
-
`}function
|
|
26
|
+
`}function j(r={}){const{pagesDir:a="src/app",pageFile:s="page.tsx",layoutFile:i="layout.tsx",notFoundFile:o="not-found.tsx"}=r;T({pagesDir:a,pageFile:s,layoutFile:i,notFoundFile:o});const e=k(a),n={pagesDir:e,pageFile:s,layoutFile:i,notFoundFile:o},l="virtual:next-vite-router",g="\0"+l;let p="",m="",u,P,h;function v(){const t=O(G(p,n,e));try{b.mkdirSync(f.dirname(m),{recursive:!0}),b.writeFileSync(m,t,"utf-8")}catch(d){const c=`next-vite-router could not write route types to ${m}: ${d instanceof Error?d.message:String(d)}`;u?u.warn(c):console.warn(c)}}return{name:"next-vite-router",configResolved(t){p=f.resolve(t.root,a),m=f.join(f.dirname(p),"virtual-next-vite-router.d.ts"),u=t.logger,x.assertNoRouteConflicts(R(p,s,e),R(p,o,e),n),v()},configureServer(t){if(P===t)return;h==null||h(),P=t;const d=$=>{if(f.relative(p,$).startsWith("..")||![s,i,o].includes(f.basename($)))return;try{x.assertNoRouteConflicts(R(p,s,e),R(p,o,e),n)}catch(F){t.config.logger.error(F instanceof Error?F.message:String(F));return}v();const w=t.moduleGraph.getModuleById(g);w&&(t.moduleGraph.invalidateModule(w),c&&clearTimeout(c),c=setTimeout(()=>{c=void 0,t.ws.send({type:"full-reload",path:"*"})},0))};let c;const y=()=>{c&&(clearTimeout(c),c=void 0),t.watcher.off("add",d),t.watcher.off("unlink",d),t.watcher.off("close",y),P===t&&(P=void 0,h=void 0)};t.watcher.on("add",d),t.watcher.on("unlink",d),t.watcher.once("close",y),h=y},resolveId(t){if(t===l)return g},load(t){if(t===g){const d=`/${e}/**/${s}`,c=`/${e}/**/${i}`,y=`/${e}/**/${o}`;return`
|
|
27
27
|
import { buildRouteTree, treeToRoutes, normalizeSegment, createLazyElement, useParams } from 'next-vite-router';
|
|
28
28
|
import { Link, useRoutes } from 'react-router-dom';
|
|
29
29
|
|
|
30
|
-
const pagesGlob = import.meta.glob(${JSON.stringify(
|
|
31
|
-
const layoutsGlob = import.meta.glob(${JSON.stringify(
|
|
30
|
+
const pagesGlob = import.meta.glob(${JSON.stringify(d)});
|
|
31
|
+
const layoutsGlob = import.meta.glob(${JSON.stringify(c)}, { eager: true });
|
|
32
32
|
const notFoundsGlob = import.meta.glob(${JSON.stringify(y)});
|
|
33
33
|
|
|
34
34
|
// Keep the raw root-relative glob keys. extractRoutePath (via buildRouteTree)
|
|
@@ -40,7 +40,7 @@ const layouts = layoutsGlob;
|
|
|
40
40
|
const notFounds = notFoundsGlob;
|
|
41
41
|
|
|
42
42
|
export function generateRoutes() {
|
|
43
|
-
const tree = buildRouteTree(pages, layouts, notFounds, ${JSON.stringify(
|
|
43
|
+
const tree = buildRouteTree(pages, layouts, notFounds, ${JSON.stringify(n)});
|
|
44
44
|
const routes = treeToRoutes(tree, true);
|
|
45
45
|
return routes;
|
|
46
46
|
}
|
|
@@ -60,4 +60,4 @@ if (import.meta.hot) {
|
|
|
60
60
|
|
|
61
61
|
export { Link, useRoutes };
|
|
62
62
|
export { useParams };
|
|
63
|
-
`}}}}exports.nextViteRouter=
|
|
63
|
+
`}}}}exports.nextViteRouter=j;
|
package/dist/plugin.js
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
1
|
import P from "node:fs";
|
|
2
2
|
import f from "node:path";
|
|
3
|
-
import { c as
|
|
4
|
-
function
|
|
5
|
-
const a =
|
|
3
|
+
import { c as w, e as T, p as k, r as G } from "./tree-DfnssFxU.js";
|
|
4
|
+
function S(r) {
|
|
5
|
+
const a = r.map(G).filter(Boolean);
|
|
6
6
|
return a.length > 0 ? `/${a.join("/")}` : "/";
|
|
7
7
|
}
|
|
8
|
-
function
|
|
8
|
+
function O(r) {
|
|
9
9
|
const a = [
|
|
10
|
-
["pagesDir",
|
|
11
|
-
["pageFile",
|
|
12
|
-
["layoutFile",
|
|
13
|
-
["notFoundFile",
|
|
10
|
+
["pagesDir", r.pagesDir],
|
|
11
|
+
["pageFile", r.pageFile],
|
|
12
|
+
["layoutFile", r.layoutFile],
|
|
13
|
+
["notFoundFile", r.notFoundFile]
|
|
14
14
|
];
|
|
15
|
-
for (const [
|
|
16
|
-
if (!
|
|
17
|
-
throw new Error(`nextViteRouter option "${
|
|
15
|
+
for (const [o, e] of a)
|
|
16
|
+
if (!e.trim())
|
|
17
|
+
throw new Error(`nextViteRouter option "${o}" must not be empty.`);
|
|
18
18
|
const s = a.slice(1), i = s.find(
|
|
19
|
-
([,
|
|
19
|
+
([, o], e) => s.slice(e + 1).some(([, n]) => n === o)
|
|
20
20
|
);
|
|
21
21
|
if (i)
|
|
22
22
|
throw new Error(
|
|
23
23
|
`nextViteRouter file options must be distinct; "${i[0]}" is duplicated.`
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
|
-
function
|
|
27
|
-
return
|
|
26
|
+
function j(r) {
|
|
27
|
+
return r.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/|\/$/g, "");
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
const i = a.pageFile ?? "page.tsx",
|
|
31
|
-
for (const
|
|
32
|
-
const
|
|
29
|
+
function D(r, a, s) {
|
|
30
|
+
const i = a.pageFile ?? "page.tsx", o = /* @__PURE__ */ new Map();
|
|
31
|
+
for (const e of R(r, i, s)) {
|
|
32
|
+
const n = T(e, a), l = k(n), g = l.filter(
|
|
33
33
|
(u) => u.kind === "dynamic" || u.kind === "catchAll"
|
|
34
34
|
).map((u) => ({
|
|
35
35
|
name: u.name,
|
|
36
36
|
optional: u.kind === "catchAll" && u.optional
|
|
37
|
-
})),
|
|
38
|
-
|
|
37
|
+
})), p = S(l);
|
|
38
|
+
o.set(p, { path: p, params: g });
|
|
39
39
|
const m = l[l.length - 1];
|
|
40
40
|
if ((m == null ? void 0 : m.kind) === "catchAll" && m.optional) {
|
|
41
|
-
const u =
|
|
42
|
-
|
|
41
|
+
const u = S(l.slice(0, -1));
|
|
42
|
+
o.has(u) || o.set(u, { path: u, params: [] });
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
return [...
|
|
45
|
+
return [...o.values()].sort((e, n) => e.path.localeCompare(n.path));
|
|
46
46
|
}
|
|
47
|
-
function R(
|
|
47
|
+
function R(r, a, s) {
|
|
48
48
|
const i = [];
|
|
49
|
-
function e
|
|
50
|
-
for (const
|
|
51
|
-
const l = f.join(
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
else if (
|
|
55
|
-
const
|
|
56
|
-
i.push(`/${s}/${
|
|
49
|
+
function o(e) {
|
|
50
|
+
for (const n of P.readdirSync(e, { withFileTypes: !0 })) {
|
|
51
|
+
const l = f.join(e, n.name);
|
|
52
|
+
if (n.isDirectory())
|
|
53
|
+
o(l);
|
|
54
|
+
else if (n.isFile() && n.name === a) {
|
|
55
|
+
const g = f.relative(r, l).replace(/\\/g, "/");
|
|
56
|
+
i.push(`/${s}/${g}`);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
-
return P.existsSync(
|
|
60
|
+
return P.existsSync(r) && o(r), i;
|
|
61
61
|
}
|
|
62
|
-
function
|
|
63
|
-
const a =
|
|
64
|
-
`), s =
|
|
65
|
-
const
|
|
66
|
-
...
|
|
62
|
+
function N(r) {
|
|
63
|
+
const a = r.map(({ path: i }) => ` | ${JSON.stringify(i)}`).join(`
|
|
64
|
+
`), s = r.map(({ path: i, params: o }) => {
|
|
65
|
+
const e = o.length > 0 ? [
|
|
66
|
+
...o.map(({ name: n, optional: l }) => ` ${n}${l ? "?" : ""}: string;`)
|
|
67
67
|
].join(`
|
|
68
68
|
`) : " [key: string]: never;";
|
|
69
69
|
return ` ${JSON.stringify(i)}: {
|
|
70
|
-
${
|
|
70
|
+
${e}
|
|
71
71
|
};`;
|
|
72
72
|
}).join(`
|
|
73
73
|
`);
|
|
@@ -93,73 +93,78 @@ ${s}
|
|
|
93
93
|
}
|
|
94
94
|
`;
|
|
95
95
|
}
|
|
96
|
-
function
|
|
96
|
+
function L(r = {}) {
|
|
97
97
|
const {
|
|
98
98
|
pagesDir: a = "src/app",
|
|
99
99
|
pageFile: s = "page.tsx",
|
|
100
100
|
layoutFile: i = "layout.tsx",
|
|
101
|
-
notFoundFile:
|
|
102
|
-
} =
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
let
|
|
106
|
-
function
|
|
107
|
-
const
|
|
108
|
-
|
|
101
|
+
notFoundFile: o = "not-found.tsx"
|
|
102
|
+
} = r;
|
|
103
|
+
O({ pagesDir: a, pageFile: s, layoutFile: i, notFoundFile: o });
|
|
104
|
+
const e = j(a), n = { pagesDir: e, pageFile: s, layoutFile: i, notFoundFile: o }, l = "virtual:next-vite-router", g = "\0" + l;
|
|
105
|
+
let p = "", m = "", u, x, h;
|
|
106
|
+
function $() {
|
|
107
|
+
const t = N(D(p, n, e));
|
|
108
|
+
try {
|
|
109
|
+
P.mkdirSync(f.dirname(m), { recursive: !0 }), P.writeFileSync(m, t, "utf-8");
|
|
110
|
+
} catch (d) {
|
|
111
|
+
const c = `next-vite-router could not write route types to ${m}: ${d instanceof Error ? d.message : String(d)}`;
|
|
112
|
+
u ? u.warn(c) : console.warn(c);
|
|
113
|
+
}
|
|
109
114
|
}
|
|
110
115
|
return {
|
|
111
116
|
name: "next-vite-router",
|
|
112
|
-
configResolved(
|
|
113
|
-
|
|
114
|
-
R(
|
|
115
|
-
R(
|
|
116
|
-
|
|
117
|
-
),
|
|
117
|
+
configResolved(t) {
|
|
118
|
+
p = f.resolve(t.root, a), m = f.join(f.dirname(p), "virtual-next-vite-router.d.ts"), u = t.logger, w(
|
|
119
|
+
R(p, s, e),
|
|
120
|
+
R(p, o, e),
|
|
121
|
+
n
|
|
122
|
+
), $();
|
|
118
123
|
},
|
|
119
|
-
configureServer(
|
|
120
|
-
if (
|
|
124
|
+
configureServer(t) {
|
|
125
|
+
if (x === t)
|
|
121
126
|
return;
|
|
122
|
-
h == null || h(),
|
|
123
|
-
const
|
|
124
|
-
if (f.relative(
|
|
127
|
+
h == null || h(), x = t;
|
|
128
|
+
const d = (b) => {
|
|
129
|
+
if (f.relative(p, b).startsWith("..") || ![s, i, o].includes(f.basename(b)))
|
|
125
130
|
return;
|
|
126
131
|
try {
|
|
127
|
-
|
|
128
|
-
R(
|
|
129
|
-
R(
|
|
130
|
-
|
|
132
|
+
w(
|
|
133
|
+
R(p, s, e),
|
|
134
|
+
R(p, o, e),
|
|
135
|
+
n
|
|
131
136
|
);
|
|
132
|
-
} catch (
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
} catch (F) {
|
|
138
|
+
t.config.logger.error(
|
|
139
|
+
F instanceof Error ? F.message : String(F)
|
|
135
140
|
);
|
|
136
141
|
return;
|
|
137
142
|
}
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
$();
|
|
144
|
+
const v = t.moduleGraph.getModuleById(g);
|
|
145
|
+
v && (t.moduleGraph.invalidateModule(v), c && clearTimeout(c), c = setTimeout(() => {
|
|
146
|
+
c = void 0, t.ws.send({ type: "full-reload", path: "*" });
|
|
142
147
|
}, 0));
|
|
143
148
|
};
|
|
144
|
-
let
|
|
149
|
+
let c;
|
|
145
150
|
const y = () => {
|
|
146
|
-
|
|
151
|
+
c && (clearTimeout(c), c = void 0), t.watcher.off("add", d), t.watcher.off("unlink", d), t.watcher.off("close", y), x === t && (x = void 0, h = void 0);
|
|
147
152
|
};
|
|
148
|
-
|
|
153
|
+
t.watcher.on("add", d), t.watcher.on("unlink", d), t.watcher.once("close", y), h = y;
|
|
149
154
|
},
|
|
150
|
-
resolveId(
|
|
151
|
-
if (
|
|
152
|
-
return
|
|
155
|
+
resolveId(t) {
|
|
156
|
+
if (t === l)
|
|
157
|
+
return g;
|
|
153
158
|
},
|
|
154
|
-
load(
|
|
155
|
-
if (
|
|
156
|
-
const
|
|
159
|
+
load(t) {
|
|
160
|
+
if (t === g) {
|
|
161
|
+
const d = `/${e}/**/${s}`, c = `/${e}/**/${i}`, y = `/${e}/**/${o}`;
|
|
157
162
|
return `
|
|
158
163
|
import { buildRouteTree, treeToRoutes, normalizeSegment, createLazyElement, useParams } from 'next-vite-router';
|
|
159
164
|
import { Link, useRoutes } from 'react-router-dom';
|
|
160
165
|
|
|
161
|
-
const pagesGlob = import.meta.glob(${JSON.stringify(
|
|
162
|
-
const layoutsGlob = import.meta.glob(${JSON.stringify(
|
|
166
|
+
const pagesGlob = import.meta.glob(${JSON.stringify(d)});
|
|
167
|
+
const layoutsGlob = import.meta.glob(${JSON.stringify(c)}, { eager: true });
|
|
163
168
|
const notFoundsGlob = import.meta.glob(${JSON.stringify(y)});
|
|
164
169
|
|
|
165
170
|
// Keep the raw root-relative glob keys. extractRoutePath (via buildRouteTree)
|
|
@@ -171,7 +176,7 @@ const layouts = layoutsGlob;
|
|
|
171
176
|
const notFounds = notFoundsGlob;
|
|
172
177
|
|
|
173
178
|
export function generateRoutes() {
|
|
174
|
-
const tree = buildRouteTree(pages, layouts, notFounds, ${JSON.stringify(
|
|
179
|
+
const tree = buildRouteTree(pages, layouts, notFounds, ${JSON.stringify(n)});
|
|
175
180
|
const routes = treeToRoutes(tree, true);
|
|
176
181
|
return routes;
|
|
177
182
|
}
|
|
@@ -197,5 +202,5 @@ export { useParams };
|
|
|
197
202
|
};
|
|
198
203
|
}
|
|
199
204
|
export {
|
|
200
|
-
|
|
205
|
+
L as nextViteRouter
|
|
201
206
|
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-vite-router",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Next.js-like file-based routing for React + Vite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"bin": {
|
|
10
|
-
"
|
|
10
|
+
"next-vite-router": "./dist/cli.cjs"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
@@ -29,13 +29,17 @@
|
|
|
29
29
|
"types": "./dist/plugin.d.cts",
|
|
30
30
|
"default": "./dist/plugin.cjs"
|
|
31
31
|
}
|
|
32
|
-
}
|
|
32
|
+
},
|
|
33
|
+
"./package.json": "./package.json"
|
|
33
34
|
},
|
|
34
35
|
"files": [
|
|
35
36
|
"dist",
|
|
36
37
|
"README.md",
|
|
37
38
|
"LICENSE"
|
|
38
39
|
],
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18"
|
|
42
|
+
},
|
|
39
43
|
"keywords": [
|
|
40
44
|
"react",
|
|
41
45
|
"vite",
|
|
@@ -74,7 +78,7 @@
|
|
|
74
78
|
},
|
|
75
79
|
"scripts": {
|
|
76
80
|
"dev": "vite build --watch",
|
|
77
|
-
"build": "vite build && vite build -c vite.config.cli.ts && node -e \"
|
|
81
|
+
"build": "vite build && vite build -c vite.config.cli.ts && node --input-type=commonjs -e \"const fs = require('node:fs'); for (const f of ['index','plugin']) fs.copyFileSync('dist/'+f+'.d.ts','dist/'+f+'.d.cts')\"",
|
|
78
82
|
"test": "pnpm run test:params && pnpm run test:generator && pnpm run test:routes && pnpm run test:local && pnpm run test:compatibility",
|
|
79
83
|
"test:local": "node test/test-package.js",
|
|
80
84
|
"test:routes": "node test/test-route-types.js",
|