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 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. Register middleware with
99
- `registerMiddleware` *before* calling `generateRoutes()`, because route elements
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
- ## Optional middleware
232
+ ## Auth guards
234
233
 
235
- Prefer layouts for route-scoped behavior. `registerMiddleware` is an optional
236
- escape hatch for cross-cutting wrappers:
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
- import { registerMiddleware } from "next-vite-router";
238
+ // src/app/(protected)/layout.tsx
239
+ import { Navigate, Outlet } from "react-router-dom";
240
240
 
241
- registerMiddleware(/^\/dashboard/, (element) => (
242
- <AuthGuard>{element}</AuthGuard>
243
- ));
241
+ export default function ProtectedLayout() {
242
+ const isAuthed = useAuth();
243
+ return isAuthed ? <Outlet /> : <Navigate to="/login" replace />;
244
+ }
244
245
  ```
245
246
 
246
- Middleware wraps generated route elements; it does not create routes or
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 init
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
- - `middleware`
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 pm2 = p;
34
- if (!candidates.includes(pm2)) candidates.push(pm2);
35
+ const pm = p;
36
+ if (!candidates.includes(pm)) candidates.push(pm);
35
37
  });
36
38
  let chosen = null;
37
- for (const pm2 of candidates) {
38
- if (isAvailable(pm2)) {
39
- chosen = pm2;
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$1(x, y) {
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$1(31, 39);
99
- const green = init$1(32, 39);
100
- const yellow = init$1(33, 39);
101
- const cyan = init$1(36, 39);
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 (fs.existsSync(srcPath)) {
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 addDevDepsCmd = pm$1.addDevDepsCommand([
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 pm = detectPackageManager();
455
- const init = new commander.Command().name("init").description(
456
- "Initialize a new Vite project with next-vite-router configuration"
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 = "1.3.0";
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("create-next-vite-router").version(pkg.version).addCommand(init);
558
- program.parse(process.argv);
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"),l=require("react"),S=require("react-router-dom"),C={enableLazyLoading:!0};let f={...C};function v(e){f={...f,...e}}function F(){f={...C}}function T(){return f}let g=[];function x(e,t){g.push({pattern:e,middleware:t})}function A(){g=[]}function y(e,t){let r=t;for(const n of g)n.pattern.lastIndex=0,n.pattern.test(e)&&(r=n.middleware(r)),n.pattern.lastIndex=0;return r}const M=()=>l.createElement("div"),h=new Map;function N(){const e=T();if(e.enableLazyLoading===!1)return null;const t=e.loadingFallback||M;return l.createElement(t)}function $(){h.clear()}function p(e,t,r){let n=h.get(t);n||(n=l.lazy(e),h.set(t,n));const a=l.createElement(l.Suspense,{fallback:l.createElement(N)},l.createElement(n));return r?y(r,a):a}const P=l.createContext(void 0);function w({name:e,children:t}){return l.createElement(P.Provider,{value:e},t)}function k(){return l.useContext(P)}function E(e,t){return y(e,l.createElement(t))}function D(e){const t=c.parseRouteSegments(e)[0];return(t==null?void 0:t.kind)==="catchAll"&&t.optional}function d(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,r=!1){const n=e.page;if(!n)throw new Error(`Route node "${e.fullPath}" has no page loader`);const a=p(async()=>({default:(await n()).default}),`page:${e.fullPath||t}`,t),o=c.parseRouteSegments(e.segment)[0],u=(o==null?void 0:o.kind)==="catchAll"?l.createElement(w,{name:o.name,children:a}):a;return r?{index:!0,element:u}:{path:d(e.segment),element:u}}function q(e){const t=e.notFound;if(!t)throw new Error(`Route node "${e.fullPath}" has no not-found loader`);const r=e.fullPath?`/${e.fullPath}`:"/";return{path:"*",element:p(async()=>({default:(await t()).default}),`notfound:${e.fullPath}`,r)}}function L(e){return e.notFound?[q(e)]:[]}function I(e,t,r,n){return{...t?{path:t}:{},element:E(e,r),children:n.length>0?n:void 0}}function b(e,t){const r=[];return[...e.children.entries()].sort(([n],[a])=>n.localeCompare(a)).forEach(([n,a])=>{const o=d(n),u=o?t?`${t}/${o}`:`/${o}`:t;r.push(...R(a,!1,u))}),r}function z(e,t){const r=[];return e.page&&r.push(s(e,t||"/")),r.push(...b(e,t)),r.push(...L(e)),r}function G(e,t,r,n,a,o){if(D(e.segment)){const u=[...a,...o];return[s(e,t),{path:n,element:m(e,r).element,children:u.length>0?u:void 0}]}return a.length>0||o.length>0?[{path:n,children:[s(e,r),...a,...o]}]:[{path:n,element:m(e,r).element}]}function O(e,t,r,n){const a=[...e.page?[s(e,t)]:[],...r,...n];return[{children:a.length>0?a:void 0}]}function j(e){const t=z(e,"");return e.layout?[{path:"/",element:E("/",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,r=""){if(t)return j(e);const n=d(e.segment),a=!n,o=a?r:r+"/"+n,u=b(e,o),i=L(e);return e.layout?[I(o,a?"":n,e.layout,z(e,o))]:e.page&&!a?G(e,r,o,n,u,i):e.page||e.notFound||!a?a?O(e,o,u,i):[{path:n,children:[...e.page?[s(e,o)]:[],...u,...i]}]:u}function B(e,t,r,n){return()=>{const a=c.buildRouteTree(e,t,r,n);return R(a,!0)}}function H(){const e=S.useParams(),t=k();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=w;exports.clearLazyCache=$;exports.clearMiddlewares=A;exports.configureRouter=v;exports.createLazyElement=p;exports.createRouteGenerator=B;exports.registerMiddleware=x;exports.resetRouterConfig=F;exports.treeToRoutes=R;exports.useParams=H;
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
- * `clearMiddlewares` for the middleware registry.
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 and apply middlewares
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, routePath?: string): default_2.ReactElement;
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 `clearMiddlewares`.
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
- * `clearMiddlewares` for the middleware registry.
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 and apply middlewares
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, routePath?: string): default_2.ReactElement;
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 `clearMiddlewares`.
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 et, c as nt, e as rt, n as at } from "./tree-DfnssFxU.js";
3
- import u, { lazy as v, Suspense as z, createContext as $, useContext as A } from "react";
4
- import { useParams as k } from "react-router-dom";
5
- const d = {
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 = { ...d };
9
- function U(t) {
8
+ let i = { ...g };
9
+ function H(t) {
10
10
  i = { ...i, ...t };
11
11
  }
12
- function V() {
13
- i = { ...d };
12
+ function J() {
13
+ i = { ...g };
14
14
  }
15
- function N() {
15
+ function $() {
16
16
  return i;
17
17
  }
18
- let p = [];
19
- function W(t, e) {
20
- p.push({ pattern: t, middleware: e });
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 || M;
37
- return u.createElement(e);
23
+ const e = t.loadingFallback || k;
24
+ return l.createElement(e);
38
25
  }
39
- function Y() {
26
+ function Q() {
40
27
  m.clear();
41
28
  }
42
- function C(t, e, r) {
29
+ function R(t, e) {
43
30
  let n = m.get(e);
44
- n || (n = v(t), m.set(e, n));
45
- const a = u.createElement(
46
- z,
47
- { fallback: u.createElement(T) },
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 y = $(void 0);
53
- function I({
37
+ const C = z(void 0);
38
+ function N({
54
39
  name: t,
55
40
  children: e
56
41
  }) {
57
- return u.createElement(
58
- y.Provider,
42
+ return l.createElement(
43
+ C.Provider,
59
44
  { value: t },
60
45
  e
61
46
  );
62
47
  }
63
- function S() {
64
- return A(y);
65
- }
66
- function P(t, e) {
67
- return R(t, u.createElement(e));
48
+ function T() {
49
+ return x(C);
68
50
  }
69
- function D(t) {
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 g(t) {
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, r = !1) {
81
- const n = t.page;
82
- if (!n)
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 a = C(
85
- async () => ({ default: (await n()).default }),
86
- `page:${t.fullPath || e}`,
87
- e
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: a
91
- }) : a;
92
- return r ? { index: !0, element: l } : { path: g(t.segment), element: l };
71
+ children: r
72
+ }) : r;
73
+ return n ? { index: !0, element: u } : { path: p(t.segment), element: u };
93
74
  }
94
- function G(t) {
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: C(
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 E(t) {
109
- return t.notFound ? [G(t)] : [];
87
+ function d(t) {
88
+ return t.notFound ? [D(t)] : [];
110
89
  }
111
- function O(t, e, r, n) {
90
+ function G(t, e, n) {
112
91
  return {
113
- ...e ? { path: e } : {},
114
- element: P(t, r),
92
+ ...t ? { path: t } : {},
93
+ element: l.createElement(e),
115
94
  children: n.length > 0 ? n : void 0
116
95
  };
117
96
  }
118
- function w(t, e) {
119
- const r = [];
120
- return [...t.children.entries()].sort(([n], [a]) => n.localeCompare(a)).forEach(([n, a]) => {
121
- const o = g(n), l = o ? e ? `${e}/${o}` : `/${o}` : e;
122
- r.push(...x(a, !1, l));
123
- }), r;
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 L(t, e) {
126
- const r = [];
127
- return t.page && r.push(c(t, e || "/")), r.push(...w(t, e)), r.push(...E(t)), r;
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 j(t, e, r, n, a, o) {
130
- if (D(t.segment)) {
131
- const l = [...a, ...o];
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: n,
136
- element: f(t, r).element,
137
- children: l.length > 0 ? l : void 0
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 a.length > 0 || o.length > 0 ? [{
142
- path: n,
120
+ return r.length > 0 || o.length > 0 ? [{
121
+ path: a,
143
122
  children: [
144
- c(t, r),
145
- ...a,
123
+ c(t, n),
124
+ ...r,
146
125
  ...o
147
126
  ]
148
127
  }] : [{
149
- path: n,
150
- element: f(t, r).element
128
+ path: a,
129
+ element: f(t, n).element
151
130
  }];
152
131
  }
153
- function q(t, e, r, n) {
154
- const a = [
132
+ function M(t, e, n, a) {
133
+ const r = [
155
134
  ...t.page ? [c(t, e)] : [],
156
- ...r,
157
- ...n
135
+ ...n,
136
+ ...a
158
137
  ];
159
138
  return [{
160
- children: a.length > 0 ? a : void 0
139
+ children: r.length > 0 ? r : void 0
161
140
  }];
162
141
  }
163
- function B(t) {
164
- const e = L(t, "");
142
+ function O(t) {
143
+ const e = E(t, "");
165
144
  return t.layout ? [{
166
145
  path: "/",
167
- element: P("/", t.layout),
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 x(t, e = !1, r = "") {
153
+ function P(t, e = !1, n = "") {
175
154
  if (e)
176
- return B(t);
177
- const n = g(t.segment), a = !n, o = a ? r : r + "/" + n, l = w(t, o), s = E(t);
178
- return t.layout ? [O(
179
- o,
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
- L(t, o)
183
- )] : t.page && !a ? j(
160
+ E(t, o)
161
+ )] : t.page && !r ? I(
184
162
  t,
185
- r,
186
- o,
187
163
  n,
188
- l,
164
+ o,
165
+ a,
166
+ u,
189
167
  s
190
- ) : t.page || t.notFound || !a ? a ? q(t, o, l, s) : [{
191
- path: n,
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
- ...l,
172
+ ...u,
195
173
  ...s
196
174
  ]
197
- }] : l;
175
+ }] : u;
198
176
  }
199
- function Z(t, e, r, n) {
177
+ function U(t, e, n, a) {
200
178
  return () => {
201
- const a = b(t, e, r, n);
202
- return x(a, !0);
179
+ const r = L(t, e, n, a);
180
+ return P(r, !0);
203
181
  };
204
182
  }
205
- function _() {
206
- const t = k(), e = S();
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
- I as CatchAllParamProvider,
211
- et as assertNoDuplicateRoutes,
212
- nt as assertNoRouteConflicts,
213
- b as buildRouteTree,
214
- Y as clearLazyCache,
215
- X as clearMiddlewares,
216
- U as configureRouter,
217
- C as createLazyElement,
218
- Z as createRouteGenerator,
219
- rt as extractRoutePath,
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
- W as registerMiddleware,
223
- V as resetRouterConfig,
199
+ J as resetRouterConfig,
224
200
  F as routeSegmentToPath,
225
- x as treeToRoutes,
226
- _ as useParams
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"),m=require("node:path"),x=require("./tree-hc1dSMdb.cjs");function w(n){const a=n.map(x.routeSegmentToPath).filter(Boolean);return a.length>0?`/${a.join("/")}`:"/"}function S(n){const a=[["pagesDir",n.pagesDir],["pageFile",n.pageFile],["layoutFile",n.layoutFile],["notFoundFile",n.notFoundFile]];for(const[t,e]of a)if(!e.trim())throw new Error(`nextViteRouter option "${t}" must not be empty.`);const s=a.slice(1),i=s.find(([,t],e)=>s.slice(e+1).some(([,r])=>r===t));if(i)throw new Error(`nextViteRouter file options must be distinct; "${i[0]}" is duplicated.`)}function T(n){return n.replace(/\\/g,"/").replace(/^\.\//,"").replace(/^\/|\/$/g,"")}function k(n,a,s){const i=a.pageFile??"page.tsx",t=new Map;for(const e of R(n,i,s)){const r=x.extractRoutePath(e,a),l=x.parseRouteSegments(r),d=l.filter(u=>u.kind==="dynamic"||u.kind==="catchAll").map(u=>({name:u.name,optional:u.kind==="catchAll"&&u.optional})),c=w(l);t.set(c,{path:c,params:d});const f=l[l.length-1];if((f==null?void 0:f.kind)==="catchAll"&&f.optional){const u=w(l.slice(0,-1));t.has(u)||t.set(u,{path:u,params:[]})}}return[...t.values()].sort((e,r)=>e.path.localeCompare(r.path))}function R(n,a,s){const i=[];function t(e){for(const r of b.readdirSync(e,{withFileTypes:!0})){const l=m.join(e,r.name);if(r.isDirectory())t(l);else if(r.isFile()&&r.name===a){const d=m.relative(n,l).replace(/\\/g,"/");i.push(`/${s}/${d}`)}}}return b.existsSync(n)&&t(n),i}function G(n){const a=n.map(({path:i})=>` | ${JSON.stringify(i)}`).join(`
2
- `),s=n.map(({path:i,params:t})=>{const e=t.length>0?[...t.map(({name:r,optional:l})=>` ${r}${l?"?":""}: string;`)].join(`
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 O(n={}){const{pagesDir:a="src/app",pageFile:s="page.tsx",layoutFile:i="layout.tsx",notFoundFile:t="not-found.tsx"}=n;S({pagesDir:a,pageFile:s,layoutFile:i,notFoundFile:t});const e=T(a),r={pagesDir:e,pageFile:s,layoutFile:i,notFoundFile:t},l="virtual:next-vite-router",d="\0"+l;let c="",f="",u,h;function F(){const o=G(k(c,r,e));b.writeFileSync(f,o,"utf-8")}return{name:"next-vite-router",configResolved(o){c=m.resolve(o.root,a),f=m.join(m.dirname(c),"virtual-next-vite-router.d.ts"),x.assertNoRouteConflicts(R(c,s,e),R(c,t,e),r),F()},configureServer(o){if(u===o)return;h==null||h(),u=o;const g=$=>{if(m.relative(c,$).startsWith("..")||![s,i,t].includes(m.basename($)))return;try{x.assertNoRouteConflicts(R(c,s,e),R(c,t,e),r)}catch(P){o.config.logger.error(P instanceof Error?P.message:String(P));return}F();const v=o.moduleGraph.getModuleById(d);v&&(o.moduleGraph.invalidateModule(v),p&&clearTimeout(p),p=setTimeout(()=>{p=void 0,o.ws.send({type:"full-reload",path:"*"})},0))};let p;const y=()=>{p&&(clearTimeout(p),p=void 0),o.watcher.off("add",g),o.watcher.off("unlink",g),o.watcher.off("close",y),u===o&&(u=void 0,h=void 0)};o.watcher.on("add",g),o.watcher.on("unlink",g),o.watcher.once("close",y),h=y},resolveId(o){if(o===l)return d},load(o){if(o===d){const g=`/${e}/**/${s}`,p=`/${e}/**/${i}`,y=`/${e}/**/${t}`;return`
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(g)});
31
- const layoutsGlob = import.meta.glob(${JSON.stringify(p)}, { eager: true });
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(r)});
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=O;
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 v, e as S, p as T, r as k } from "./tree-DfnssFxU.js";
4
- function w(n) {
5
- const a = n.map(k).filter(Boolean);
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 G(n) {
8
+ function O(r) {
9
9
  const a = [
10
- ["pagesDir", n.pagesDir],
11
- ["pageFile", n.pageFile],
12
- ["layoutFile", n.layoutFile],
13
- ["notFoundFile", n.notFoundFile]
10
+ ["pagesDir", r.pagesDir],
11
+ ["pageFile", r.pageFile],
12
+ ["layoutFile", r.layoutFile],
13
+ ["notFoundFile", r.notFoundFile]
14
14
  ];
15
- for (const [e, t] of a)
16
- if (!t.trim())
17
- throw new Error(`nextViteRouter option "${e}" must not be empty.`);
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
- ([, e], t) => s.slice(t + 1).some(([, r]) => r === e)
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 O(n) {
27
- return n.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/|\/$/g, "");
26
+ function j(r) {
27
+ return r.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/|\/$/g, "");
28
28
  }
29
- function j(n, a, s) {
30
- const i = a.pageFile ?? "page.tsx", e = /* @__PURE__ */ new Map();
31
- for (const t of R(n, i, s)) {
32
- const r = S(t, a), l = T(r), d = l.filter(
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
- })), c = w(l);
38
- e.set(c, { path: c, params: d });
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 = w(l.slice(0, -1));
42
- e.has(u) || e.set(u, { path: u, params: [] });
41
+ const u = S(l.slice(0, -1));
42
+ o.has(u) || o.set(u, { path: u, params: [] });
43
43
  }
44
44
  }
45
- return [...e.values()].sort((t, r) => t.path.localeCompare(r.path));
45
+ return [...o.values()].sort((e, n) => e.path.localeCompare(n.path));
46
46
  }
47
- function R(n, a, s) {
47
+ function R(r, a, s) {
48
48
  const i = [];
49
- function e(t) {
50
- for (const r of P.readdirSync(t, { withFileTypes: !0 })) {
51
- const l = f.join(t, r.name);
52
- if (r.isDirectory())
53
- e(l);
54
- else if (r.isFile() && r.name === a) {
55
- const d = f.relative(n, l).replace(/\\/g, "/");
56
- i.push(`/${s}/${d}`);
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(n) && e(n), i;
60
+ return P.existsSync(r) && o(r), i;
61
61
  }
62
- function D(n) {
63
- const a = n.map(({ path: i }) => ` | ${JSON.stringify(i)}`).join(`
64
- `), s = n.map(({ path: i, params: e }) => {
65
- const t = e.length > 0 ? [
66
- ...e.map(({ name: r, optional: l }) => ` ${r}${l ? "?" : ""}: string;`)
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
- ${t}
70
+ ${e}
71
71
  };`;
72
72
  }).join(`
73
73
  `);
@@ -93,73 +93,78 @@ ${s}
93
93
  }
94
94
  `;
95
95
  }
96
- function z(n = {}) {
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: e = "not-found.tsx"
102
- } = n;
103
- G({ pagesDir: a, pageFile: s, layoutFile: i, notFoundFile: e });
104
- const t = O(a), r = { pagesDir: t, pageFile: s, layoutFile: i, notFoundFile: e }, l = "virtual:next-vite-router", d = "\0" + l;
105
- let c = "", m = "", u, h;
106
- function F() {
107
- const o = D(j(c, r, t));
108
- P.writeFileSync(m, o, "utf-8");
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(o) {
113
- c = f.resolve(o.root, a), m = f.join(f.dirname(c), "virtual-next-vite-router.d.ts"), v(
114
- R(c, s, t),
115
- R(c, e, t),
116
- r
117
- ), F();
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(o) {
120
- if (u === o)
124
+ configureServer(t) {
125
+ if (x === t)
121
126
  return;
122
- h == null || h(), u = o;
123
- const g = (b) => {
124
- if (f.relative(c, b).startsWith("..") || ![s, i, e].includes(f.basename(b)))
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
- v(
128
- R(c, s, t),
129
- R(c, e, t),
130
- r
132
+ w(
133
+ R(p, s, e),
134
+ R(p, o, e),
135
+ n
131
136
  );
132
- } catch (x) {
133
- o.config.logger.error(
134
- x instanceof Error ? x.message : String(x)
137
+ } catch (F) {
138
+ t.config.logger.error(
139
+ F instanceof Error ? F.message : String(F)
135
140
  );
136
141
  return;
137
142
  }
138
- F();
139
- const $ = o.moduleGraph.getModuleById(d);
140
- $ && (o.moduleGraph.invalidateModule($), p && clearTimeout(p), p = setTimeout(() => {
141
- p = void 0, o.ws.send({ type: "full-reload", path: "*" });
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 p;
149
+ let c;
145
150
  const y = () => {
146
- p && (clearTimeout(p), p = void 0), o.watcher.off("add", g), o.watcher.off("unlink", g), o.watcher.off("close", y), u === o && (u = void 0, h = void 0);
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
- o.watcher.on("add", g), o.watcher.on("unlink", g), o.watcher.once("close", y), h = y;
153
+ t.watcher.on("add", d), t.watcher.on("unlink", d), t.watcher.once("close", y), h = y;
149
154
  },
150
- resolveId(o) {
151
- if (o === l)
152
- return d;
155
+ resolveId(t) {
156
+ if (t === l)
157
+ return g;
153
158
  },
154
- load(o) {
155
- if (o === d) {
156
- const g = `/${t}/**/${s}`, p = `/${t}/**/${i}`, y = `/${t}/**/${e}`;
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(g)});
162
- const layoutsGlob = import.meta.glob(${JSON.stringify(p)}, { eager: true });
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(r)});
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
- z as nextViteRouter
205
+ L as nextViteRouter
201
206
  };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "next-vite-router",
3
- "version": "1.3.0",
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
- "create-next-vite-router": "./dist/cli.cjs"
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 \"import fs from 'node:fs'; for (const f of ['index','plugin']) fs.copyFileSync('dist/'+f+'.d.ts','dist/'+f+'.d.cts')\"",
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",