next-vite-router 1.2.3 → 1.3.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 +39 -13
- package/dist/cli.cjs +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +144 -0
- package/dist/index.d.ts +50 -1
- package/dist/index.js +201 -167
- package/dist/plugin.cjs +63 -0
- package/dist/plugin.d.cts +12 -0
- package/dist/plugin.js +118 -97
- package/dist/tree-DfnssFxU.js +143 -0
- package/dist/tree-hc1dSMdb.cjs +10 -0
- package/package.json +20 -7
- package/dist/tree-HwBRWJNI.js +0 -64
package/dist/plugin.js
CHANGED
|
@@ -1,60 +1,73 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
function
|
|
5
|
-
const
|
|
6
|
-
return
|
|
1
|
+
import P from "node:fs";
|
|
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);
|
|
6
|
+
return a.length > 0 ? `/${a.join("/")}` : "/";
|
|
7
7
|
}
|
|
8
|
-
function
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
8
|
+
function G(n) {
|
|
9
|
+
const a = [
|
|
10
|
+
["pagesDir", n.pagesDir],
|
|
11
|
+
["pageFile", n.pageFile],
|
|
12
|
+
["layoutFile", n.layoutFile],
|
|
13
|
+
["notFoundFile", n.notFoundFile]
|
|
14
|
+
];
|
|
15
|
+
for (const [e, t] of a)
|
|
16
|
+
if (!t.trim())
|
|
17
|
+
throw new Error(`nextViteRouter option "${e}" must not be empty.`);
|
|
18
|
+
const s = a.slice(1), i = s.find(
|
|
19
|
+
([, e], t) => s.slice(t + 1).some(([, r]) => r === e)
|
|
20
|
+
);
|
|
21
|
+
if (i)
|
|
22
|
+
throw new Error(
|
|
23
|
+
`nextViteRouter file options must be distinct; "${i[0]}" is duplicated.`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
function O(n) {
|
|
27
|
+
return n.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/|\/$/g, "");
|
|
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(
|
|
33
|
+
(u) => u.kind === "dynamic" || u.kind === "catchAll"
|
|
34
|
+
).map((u) => ({
|
|
35
|
+
name: u.name,
|
|
36
|
+
optional: u.kind === "catchAll" && u.optional
|
|
37
|
+
})), c = w(l);
|
|
38
|
+
e.set(c, { path: c, params: d });
|
|
39
|
+
const m = l[l.length - 1];
|
|
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: [] });
|
|
30
43
|
}
|
|
31
44
|
}
|
|
32
|
-
return
|
|
45
|
+
return [...e.values()].sort((t, r) => t.path.localeCompare(r.path));
|
|
33
46
|
}
|
|
34
|
-
function
|
|
35
|
-
const
|
|
36
|
-
function
|
|
37
|
-
for (const
|
|
38
|
-
const
|
|
39
|
-
|
|
47
|
+
function R(n, a, s) {
|
|
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}`);
|
|
57
|
+
}
|
|
40
58
|
}
|
|
41
59
|
}
|
|
42
|
-
return
|
|
60
|
+
return P.existsSync(n) && e(n), i;
|
|
43
61
|
}
|
|
44
|
-
function
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const e = n.map(({ path: i }) => ` | "${i}"`).join(`
|
|
50
|
-
`), r = n.map(({ path: i, params: a }) => {
|
|
51
|
-
const o = i.split("/").map((s) => k(`/${s}`)).filter((s) => !!s), p = o.length > 0 || a.length > 0 ? [
|
|
52
|
-
...o.map((s) => ` ${s}: string;`),
|
|
53
|
-
...a.map(({ name: s, optional: u }) => ` ${s}${u ? "?" : ""}: string;`)
|
|
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;`)
|
|
54
67
|
].join(`
|
|
55
68
|
`) : " [key: string]: never;";
|
|
56
|
-
return `
|
|
57
|
-
${
|
|
69
|
+
return ` ${JSON.stringify(i)}: {
|
|
70
|
+
${t}
|
|
58
71
|
};`;
|
|
59
72
|
}).join(`
|
|
60
73
|
`);
|
|
@@ -63,14 +76,14 @@ ${p}
|
|
|
63
76
|
import type { RouteObject } from 'react-router-dom';
|
|
64
77
|
|
|
65
78
|
export type RoutePath =
|
|
66
|
-
${
|
|
79
|
+
${a || ' | "/"'};
|
|
67
80
|
|
|
68
81
|
export type RouteParams<P extends RoutePath> = P extends keyof RoutePathParams
|
|
69
82
|
? RoutePathParams[P]
|
|
70
83
|
: never;
|
|
71
84
|
|
|
72
85
|
export interface RoutePathParams {
|
|
73
|
-
${
|
|
86
|
+
${s}
|
|
74
87
|
}
|
|
75
88
|
|
|
76
89
|
export const generateRoutes: () => RouteObject[];
|
|
@@ -80,78 +93,85 @@ ${r}
|
|
|
80
93
|
}
|
|
81
94
|
`;
|
|
82
95
|
}
|
|
83
|
-
function
|
|
96
|
+
function z(n = {}) {
|
|
84
97
|
const {
|
|
85
|
-
pagesDir:
|
|
86
|
-
pageFile:
|
|
98
|
+
pagesDir: a = "src/app",
|
|
99
|
+
pageFile: s = "page.tsx",
|
|
87
100
|
layoutFile: i = "layout.tsx",
|
|
88
|
-
notFoundFile:
|
|
89
|
-
} = n
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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");
|
|
94
109
|
}
|
|
95
110
|
return {
|
|
96
111
|
name: "next-vite-router",
|
|
97
|
-
configResolved(
|
|
98
|
-
|
|
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();
|
|
99
118
|
},
|
|
100
|
-
configureServer(
|
|
101
|
-
if (
|
|
119
|
+
configureServer(o) {
|
|
120
|
+
if (u === o)
|
|
102
121
|
return;
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
122
|
+
h == null || h(), u = o;
|
|
123
|
+
const g = (b) => {
|
|
124
|
+
if (f.relative(c, b).startsWith("..") || ![s, i, e].includes(f.basename(b)))
|
|
106
125
|
return;
|
|
107
126
|
try {
|
|
108
|
-
|
|
127
|
+
v(
|
|
128
|
+
R(c, s, t),
|
|
129
|
+
R(c, e, t),
|
|
130
|
+
r
|
|
131
|
+
);
|
|
109
132
|
} catch (x) {
|
|
110
|
-
|
|
133
|
+
o.config.logger.error(
|
|
111
134
|
x instanceof Error ? x.message : String(x)
|
|
112
135
|
);
|
|
113
136
|
return;
|
|
114
137
|
}
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
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: "*" });
|
|
119
142
|
}, 0));
|
|
120
143
|
};
|
|
121
|
-
let
|
|
122
|
-
const
|
|
123
|
-
|
|
144
|
+
let p;
|
|
145
|
+
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);
|
|
124
147
|
};
|
|
125
|
-
|
|
148
|
+
o.watcher.on("add", g), o.watcher.on("unlink", g), o.watcher.once("close", y), h = y;
|
|
126
149
|
},
|
|
127
|
-
resolveId(
|
|
128
|
-
if (
|
|
129
|
-
return
|
|
150
|
+
resolveId(o) {
|
|
151
|
+
if (o === l)
|
|
152
|
+
return d;
|
|
130
153
|
},
|
|
131
|
-
load(
|
|
132
|
-
if (
|
|
154
|
+
load(o) {
|
|
155
|
+
if (o === d) {
|
|
156
|
+
const g = `/${t}/**/${s}`, p = `/${t}/**/${i}`, y = `/${t}/**/${e}`;
|
|
133
157
|
return `
|
|
134
158
|
import { buildRouteTree, treeToRoutes, normalizeSegment, createLazyElement, useParams } from 'next-vite-router';
|
|
135
159
|
import { Link, useRoutes } from 'react-router-dom';
|
|
136
160
|
|
|
137
|
-
const pagesGlob = import.meta.glob(
|
|
138
|
-
const layoutsGlob = import.meta.glob(
|
|
139
|
-
const notFoundsGlob = import.meta.glob(
|
|
161
|
+
const pagesGlob = import.meta.glob(${JSON.stringify(g)});
|
|
162
|
+
const layoutsGlob = import.meta.glob(${JSON.stringify(p)}, { eager: true });
|
|
163
|
+
const notFoundsGlob = import.meta.glob(${JSON.stringify(y)});
|
|
140
164
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
const layouts =
|
|
147
|
-
|
|
148
|
-
);
|
|
149
|
-
const notFounds = Object.fromEntries(
|
|
150
|
-
Object.entries(notFoundsGlob).map(([key, value]) => [transformPath(key), value])
|
|
151
|
-
);
|
|
165
|
+
// Keep the raw root-relative glob keys. extractRoutePath (via buildRouteTree)
|
|
166
|
+
// is the single place that strips the pagesDir prefix; stripping it here as
|
|
167
|
+
// well would double-remove it and let the prefix regex match a same-named
|
|
168
|
+
// nested folder (e.g. pagesDir "app" turning "app/docs/app" into "/").
|
|
169
|
+
const pages = pagesGlob;
|
|
170
|
+
const layouts = layoutsGlob;
|
|
171
|
+
const notFounds = notFoundsGlob;
|
|
152
172
|
|
|
153
173
|
export function generateRoutes() {
|
|
154
|
-
const tree = buildRouteTree(pages, layouts, notFounds, ${JSON.stringify(
|
|
174
|
+
const tree = buildRouteTree(pages, layouts, notFounds, ${JSON.stringify(r)});
|
|
155
175
|
const routes = treeToRoutes(tree, true);
|
|
156
176
|
return routes;
|
|
157
177
|
}
|
|
@@ -172,9 +192,10 @@ if (import.meta.hot) {
|
|
|
172
192
|
export { Link, useRoutes };
|
|
173
193
|
export { useParams };
|
|
174
194
|
`;
|
|
195
|
+
}
|
|
175
196
|
}
|
|
176
197
|
};
|
|
177
198
|
}
|
|
178
199
|
export {
|
|
179
|
-
|
|
200
|
+
z as nextViteRouter
|
|
180
201
|
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
function R(t) {
|
|
2
|
+
return /^\([^)]+\)$/.test(t) ? "" : /^\[\[\.\.\.(.+)\]\]$/.test(t) || /^\[\.\.\.(.+)\]$/.test(t) ? "*" : /^\[([^\]]+)\]$/.test(t) ? t.replace(/^\[([^\]]+)\]$/, ":$1") : t;
|
|
3
|
+
}
|
|
4
|
+
const P = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
5
|
+
function A(t) {
|
|
6
|
+
return t.kind === "group" ? "" : t.kind === "dynamic" ? `:${t.name}` : t.kind === "catchAll" ? "*" : t.name;
|
|
7
|
+
}
|
|
8
|
+
function m(t) {
|
|
9
|
+
const s = t ? t.split("/").filter(Boolean) : [], o = [], c = /* @__PURE__ */ new Set();
|
|
10
|
+
for (const a of s) {
|
|
11
|
+
const n = a.match(/^\(([^)]+)\)$/), e = a.match(/^\[\[\.\.\.(.+)\]\]$/), r = a.match(/^\[\.\.\.(.+)\]$/), i = a.match(/^\[([^\]]+)\]$/), l = e ? { name: e[1], optional: !0, kind: "catchAll" } : r ? { name: r[1], optional: !1, kind: "catchAll" } : i ? { name: i[1], optional: !1, kind: "dynamic" } : void 0;
|
|
12
|
+
if (n)
|
|
13
|
+
o.push({ kind: "group", name: n[1] });
|
|
14
|
+
else if (l) {
|
|
15
|
+
if (!P.test(l.name))
|
|
16
|
+
throw new Error(
|
|
17
|
+
`Invalid route parameter name "${l.name}" in segment "${a}". Parameter names must start with a letter or underscore and contain only letters, numbers, and underscores.`
|
|
18
|
+
);
|
|
19
|
+
if (c.has(l.name))
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Duplicate route parameter "${l.name}" in route "${t || "/"}".`
|
|
22
|
+
);
|
|
23
|
+
c.add(l.name), o.push(l);
|
|
24
|
+
} else
|
|
25
|
+
o.push({ kind: "static", name: a });
|
|
26
|
+
}
|
|
27
|
+
return o;
|
|
28
|
+
}
|
|
29
|
+
function f(t, { pagesDir: s, pageFile: o = "page.tsx", layoutFile: c = "layout.tsx", notFoundFile: a = "not-found.tsx" } = {}) {
|
|
30
|
+
const n = t.replace(/\\/g, "/"), e = s == null ? void 0 : s.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\/|\/$/g, ""), r = e == null ? void 0 : e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), i = [o, c, a].map((l) => l.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
31
|
+
return n.replace(
|
|
32
|
+
e ? new RegExp(`^.*?(?:^|/)${r}/`) : /^.*?(?:^|\/)(?:app|pages)\//,
|
|
33
|
+
""
|
|
34
|
+
).replace(/\\/g, "/").replace(new RegExp(`/?(?:${i})$`), "");
|
|
35
|
+
}
|
|
36
|
+
function $(t) {
|
|
37
|
+
return t.kind === "group" ? "" : t.kind === "catchAll" ? "*" : t.kind === "dynamic" ? ":param" : A(t);
|
|
38
|
+
}
|
|
39
|
+
function g(t, s) {
|
|
40
|
+
const o = f(t, s), c = m(o), a = c.map($).filter(Boolean), n = [
|
|
41
|
+
a.length > 0 ? `/${a.join("/")}` : "/"
|
|
42
|
+
], e = c[c.length - 1];
|
|
43
|
+
if ((e == null ? void 0 : e.kind) === "catchAll" && e.optional) {
|
|
44
|
+
const r = a.slice(0, -1);
|
|
45
|
+
n.push(r.length > 0 ? `/${r.join("/")}` : "/");
|
|
46
|
+
}
|
|
47
|
+
return n;
|
|
48
|
+
}
|
|
49
|
+
function w(t) {
|
|
50
|
+
return /(^|\/)(:param|\*)($|\/)/.test(t) ? "pattern" : "literal";
|
|
51
|
+
}
|
|
52
|
+
function j(t, s, o) {
|
|
53
|
+
const c = t.flatMap((n) => {
|
|
54
|
+
const e = f(n, o), r = m(e), i = r[r.length - 1];
|
|
55
|
+
if ((i == null ? void 0 : i.kind) !== "catchAll")
|
|
56
|
+
return [];
|
|
57
|
+
const l = r.map($).filter(Boolean), u = l.length > 0 ? `/${l.join("/")}` : "/", p = l.slice(0, -1), k = p.length > 0 ? `/${p.join("/")}` : "/";
|
|
58
|
+
return [{ filePath: n, paths: /* @__PURE__ */ new Set([u, k]) }];
|
|
59
|
+
}), a = /* @__PURE__ */ new Map();
|
|
60
|
+
for (const n of s)
|
|
61
|
+
for (const e of g(n, o))
|
|
62
|
+
for (const r of c)
|
|
63
|
+
if (r.paths.has(e)) {
|
|
64
|
+
const i = `${e}\0${r.filePath}\0${n}`;
|
|
65
|
+
a.set(i, {
|
|
66
|
+
routePath: e,
|
|
67
|
+
pageFile: r.filePath,
|
|
68
|
+
notFoundFile: n
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (a.size > 0)
|
|
72
|
+
throw new Error(
|
|
73
|
+
[...a.values()].sort((n, e) => n.routePath.localeCompare(e.routePath)).map(
|
|
74
|
+
({ routePath: n, pageFile: e, notFoundFile: r }) => `Conflicting fallback routes "${n}" detected:
|
|
75
|
+
catch-all page: ${e}
|
|
76
|
+
not-found file: ${r}
|
|
77
|
+
A not-found route and a catch-all page cannot coexist at the same route level.`
|
|
78
|
+
).join(`
|
|
79
|
+
|
|
80
|
+
`)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
function d(t, s) {
|
|
84
|
+
const o = /* @__PURE__ */ new Map();
|
|
85
|
+
for (const a of t)
|
|
86
|
+
for (const n of g(a, s)) {
|
|
87
|
+
const e = o.get(n) ?? [];
|
|
88
|
+
e.push({ kind: w(n), filePath: a }), o.set(n, e);
|
|
89
|
+
}
|
|
90
|
+
const c = [...o.entries()].filter(([, a]) => a.length > 1).sort(([a], [n]) => a.localeCompare(n));
|
|
91
|
+
if (c.length > 0)
|
|
92
|
+
throw new Error(
|
|
93
|
+
c.map(
|
|
94
|
+
([a, n]) => `${n[0].kind === "pattern" ? "Ambiguous route pattern" : "Duplicate route"} "${a}" detected:
|
|
95
|
+
${n.sort((e, r) => e.filePath.localeCompare(r.filePath)).map((e) => ` ${e.filePath}`).join(`
|
|
96
|
+
`)}`
|
|
97
|
+
).join(`
|
|
98
|
+
|
|
99
|
+
`)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
function E(t, s, o) {
|
|
103
|
+
d(t, o), d(s, o), j(t, s, o);
|
|
104
|
+
}
|
|
105
|
+
function h(t, s, o, c, a) {
|
|
106
|
+
const n = f(s, a), e = n ? n.split("/") : [];
|
|
107
|
+
let r = t, i = "";
|
|
108
|
+
e.forEach((l, u) => {
|
|
109
|
+
i = i ? `${i}/${l}` : l, r.children.has(l) || r.children.set(l, {
|
|
110
|
+
segment: l,
|
|
111
|
+
fullPath: i,
|
|
112
|
+
children: /* @__PURE__ */ new Map()
|
|
113
|
+
}), r = r.children.get(l), u === e.length - 1 && (r[c] = o);
|
|
114
|
+
}), e.length === 0 && (t[c] = o);
|
|
115
|
+
}
|
|
116
|
+
function b(t, s, o, c) {
|
|
117
|
+
E(
|
|
118
|
+
Object.keys(t),
|
|
119
|
+
Object.keys(o),
|
|
120
|
+
c
|
|
121
|
+
);
|
|
122
|
+
const a = {
|
|
123
|
+
segment: "",
|
|
124
|
+
fullPath: "",
|
|
125
|
+
children: /* @__PURE__ */ new Map()
|
|
126
|
+
};
|
|
127
|
+
return Object.entries(s).forEach(([n, e]) => {
|
|
128
|
+
h(a, n, e.default, "layout", c);
|
|
129
|
+
}), Object.entries(t).forEach(([n, e]) => {
|
|
130
|
+
h(a, n, e, "page", c);
|
|
131
|
+
}), Object.entries(o).forEach(([n, e]) => {
|
|
132
|
+
h(a, n, e, "notFound", c);
|
|
133
|
+
}), a;
|
|
134
|
+
}
|
|
135
|
+
export {
|
|
136
|
+
d as a,
|
|
137
|
+
b,
|
|
138
|
+
E as c,
|
|
139
|
+
f as e,
|
|
140
|
+
R as n,
|
|
141
|
+
m as p,
|
|
142
|
+
A as r
|
|
143
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";function w(t){return/^\([^)]+\)$/.test(t)?"":/^\[\[\.\.\.(.+)\]\]$/.test(t)||/^\[\.\.\.(.+)\]$/.test(t)?"*":/^\[([^\]]+)\]$/.test(t)?t.replace(/^\[([^\]]+)\]$/,":$1"):t}const R=/^[A-Za-z_][A-Za-z0-9_]*$/;function $(t){return t.kind==="group"?"":t.kind==="dynamic"?`:${t.name}`:t.kind==="catchAll"?"*":t.name}function d(t){const s=t?t.split("/").filter(Boolean):[],o=[],c=new Set;for(const a of s){const n=a.match(/^\(([^)]+)\)$/),e=a.match(/^\[\[\.\.\.(.+)\]\]$/),r=a.match(/^\[\.\.\.(.+)\]$/),i=a.match(/^\[([^\]]+)\]$/),l=e?{name:e[1],optional:!0,kind:"catchAll"}:r?{name:r[1],optional:!1,kind:"catchAll"}:i?{name:i[1],optional:!1,kind:"dynamic"}:void 0;if(n)o.push({kind:"group",name:n[1]});else if(l){if(!R.test(l.name))throw new Error(`Invalid route parameter name "${l.name}" in segment "${a}". Parameter names must start with a letter or underscore and contain only letters, numbers, and underscores.`);if(c.has(l.name))throw new Error(`Duplicate route parameter "${l.name}" in route "${t||"/"}".`);c.add(l.name),o.push(l)}else o.push({kind:"static",name:a})}return o}function u(t,{pagesDir:s,pageFile:o="page.tsx",layoutFile:c="layout.tsx",notFoundFile:a="not-found.tsx"}={}){const n=t.replace(/\\/g,"/"),e=s==null?void 0:s.replace(/\\/g,"/").replace(/^\.\//,"").replace(/^\/|\/$/g,""),r=e==null?void 0:e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),i=[o,c,a].map(l=>l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|");return n.replace(e?new RegExp(`^.*?(?:^|/)${r}/`):/^.*?(?:^|\/)(?:app|pages)\//,"").replace(/\\/g,"/").replace(new RegExp(`/?(?:${i})$`),"")}function g(t){return t.kind==="group"?"":t.kind==="catchAll"?"*":t.kind==="dynamic"?":param":$(t)}function P(t,s){const o=u(t,s),c=d(o),a=c.map(g).filter(Boolean),n=[a.length>0?`/${a.join("/")}`:"/"],e=c[c.length-1];if((e==null?void 0:e.kind)==="catchAll"&&e.optional){const r=a.slice(0,-1);n.push(r.length>0?`/${r.join("/")}`:"/")}return n}function j(t){return/(^|\/)(:param|\*)($|\/)/.test(t)?"pattern":"literal"}function E(t,s,o){const c=t.flatMap(n=>{const e=u(n,o),r=d(e),i=r[r.length-1];if((i==null?void 0:i.kind)!=="catchAll")return[];const l=r.map(g).filter(Boolean),h=l.length>0?`/${l.join("/")}`:"/",m=l.slice(0,-1),A=m.length>0?`/${m.join("/")}`:"/";return[{filePath:n,paths:new Set([h,A])}]}),a=new Map;for(const n of s)for(const e of P(n,o))for(const r of c)if(r.paths.has(e)){const i=`${e}\0${r.filePath}\0${n}`;a.set(i,{routePath:e,pageFile:r.filePath,notFoundFile:n})}if(a.size>0)throw new Error([...a.values()].sort((n,e)=>n.routePath.localeCompare(e.routePath)).map(({routePath:n,pageFile:e,notFoundFile:r})=>`Conflicting fallback routes "${n}" detected:
|
|
2
|
+
catch-all page: ${e}
|
|
3
|
+
not-found file: ${r}
|
|
4
|
+
A not-found route and a catch-all page cannot coexist at the same route level.`).join(`
|
|
5
|
+
|
|
6
|
+
`))}function p(t,s){const o=new Map;for(const a of t)for(const n of P(a,s)){const e=o.get(n)??[];e.push({kind:j(n),filePath:a}),o.set(n,e)}const c=[...o.entries()].filter(([,a])=>a.length>1).sort(([a],[n])=>a.localeCompare(n));if(c.length>0)throw new Error(c.map(([a,n])=>`${n[0].kind==="pattern"?"Ambiguous route pattern":"Duplicate route"} "${a}" detected:
|
|
7
|
+
${n.sort((e,r)=>e.filePath.localeCompare(r.filePath)).map(e=>` ${e.filePath}`).join(`
|
|
8
|
+
`)}`).join(`
|
|
9
|
+
|
|
10
|
+
`))}function k(t,s,o){p(t,o),p(s,o),E(t,s,o)}function f(t,s,o,c,a){const n=u(s,a),e=n?n.split("/"):[];let r=t,i="";e.forEach((l,h)=>{i=i?`${i}/${l}`:l,r.children.has(l)||r.children.set(l,{segment:l,fullPath:i,children:new Map}),r=r.children.get(l),h===e.length-1&&(r[c]=o)}),e.length===0&&(t[c]=o)}function b(t,s,o,c){k(Object.keys(t),Object.keys(o),c);const a={segment:"",fullPath:"",children:new Map};return Object.entries(s).forEach(([n,e])=>{f(a,n,e.default,"layout",c)}),Object.entries(t).forEach(([n,e])=>{f(a,n,e,"page",c)}),Object.entries(o).forEach(([n,e])=>{f(a,n,e,"notFound",c)}),a}exports.assertNoDuplicateRoutes=p;exports.assertNoRouteConflicts=k;exports.buildRouteTree=b;exports.extractRoutePath=u;exports.normalizeSegment=w;exports.parseRouteSegments=d;exports.routeSegmentToPath=$;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-vite-router",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Next.js-like file-based routing for React + Vite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -11,12 +11,24 @@
|
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
-
"import":
|
|
15
|
-
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"require": {
|
|
19
|
+
"types": "./dist/index.d.cts",
|
|
20
|
+
"default": "./dist/index.cjs"
|
|
21
|
+
}
|
|
16
22
|
},
|
|
17
23
|
"./plugin": {
|
|
18
|
-
"import":
|
|
19
|
-
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/plugin.d.ts",
|
|
26
|
+
"default": "./dist/plugin.js"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/plugin.d.cts",
|
|
30
|
+
"default": "./dist/plugin.cjs"
|
|
31
|
+
}
|
|
20
32
|
}
|
|
21
33
|
},
|
|
22
34
|
"files": [
|
|
@@ -36,7 +48,7 @@
|
|
|
36
48
|
"author": "Rlzee",
|
|
37
49
|
"repository": {
|
|
38
50
|
"type": "git",
|
|
39
|
-
"url": "https://github.com/Rlzee/next-vite-router"
|
|
51
|
+
"url": "git+https://github.com/Rlzee/next-vite-router.git"
|
|
40
52
|
},
|
|
41
53
|
"homepage": "https://github.com/Rlzee/next-vite-router#readme",
|
|
42
54
|
"license": "MIT",
|
|
@@ -62,7 +74,8 @@
|
|
|
62
74
|
},
|
|
63
75
|
"scripts": {
|
|
64
76
|
"dev": "vite build --watch",
|
|
65
|
-
"build": "vite build && vite build -c vite.config.cli.ts",
|
|
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')\"",
|
|
78
|
+
"test": "pnpm run test:params && pnpm run test:generator && pnpm run test:routes && pnpm run test:local && pnpm run test:compatibility",
|
|
66
79
|
"test:local": "node test/test-package.js",
|
|
67
80
|
"test:routes": "node test/test-route-types.js",
|
|
68
81
|
"test:generator": "node --test test/routes.test.js",
|
package/dist/tree-HwBRWJNI.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
function p(t) {
|
|
2
|
-
return /^\([^)]+\)$/.test(t) ? "" : /^\[\[\.\.\.(.+)\]\]$/.test(t) || /^\[\.\.\.(.+)\]$/.test(t) ? "*" : /^\[([^\]]+)\]$/.test(t) ? t.replace(/^\[([^\]]+)\]$/, ":$1") : t;
|
|
3
|
-
}
|
|
4
|
-
function h(t, { pagesDir: c, pageFile: a = "page.tsx", layoutFile: o = "layout.tsx", notFoundFile: r = "not-found.tsx" } = {}) {
|
|
5
|
-
const n = t.replace(/\\/g, "/"), e = c == null ? void 0 : c.replace(/\\/g, "/").replace(/^\/|\/$/g, ""), l = [a, o, r].map((u) => u.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
6
|
-
return n.replace(
|
|
7
|
-
e ? new RegExp(`^.*(?:^|/)${e}/`) : /^.*(?:^|\/)(?:app|pages)\//,
|
|
8
|
-
""
|
|
9
|
-
).replace(/\\/g, "/").replace(new RegExp(`/?(?:${l})$`), "");
|
|
10
|
-
}
|
|
11
|
-
function $(t, c) {
|
|
12
|
-
const a = h(t, c), o = a ? a.split("/").map(p).filter(Boolean) : [];
|
|
13
|
-
return o.length > 0 ? `/${o.join("/")}` : "/";
|
|
14
|
-
}
|
|
15
|
-
function d(t, c) {
|
|
16
|
-
const a = /* @__PURE__ */ new Map();
|
|
17
|
-
for (const r of t) {
|
|
18
|
-
const n = $(r, c), e = a.get(n) ?? [];
|
|
19
|
-
e.push(r), a.set(n, e);
|
|
20
|
-
}
|
|
21
|
-
const o = [...a.entries()].filter(([, r]) => r.length > 1).sort(([r], [n]) => r.localeCompare(n));
|
|
22
|
-
if (o.length > 0)
|
|
23
|
-
throw new Error(
|
|
24
|
-
o.map(
|
|
25
|
-
([r, n]) => `Duplicate route "${r}" detected:
|
|
26
|
-
${n.sort((e, l) => e.localeCompare(l)).map((e) => ` ${e}`).join(`
|
|
27
|
-
`)}`
|
|
28
|
-
).join(`
|
|
29
|
-
|
|
30
|
-
`)
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
function i(t, c, a, o, r) {
|
|
34
|
-
const n = h(c, r), e = n ? n.split("/") : [];
|
|
35
|
-
let l = t, u = "";
|
|
36
|
-
e.forEach((s, f) => {
|
|
37
|
-
u = u ? `${u}/${s}` : s, l.children.has(s) || l.children.set(s, {
|
|
38
|
-
segment: s,
|
|
39
|
-
fullPath: u,
|
|
40
|
-
children: /* @__PURE__ */ new Map()
|
|
41
|
-
}), l = l.children.get(s), f === e.length - 1 && (l[o] = a);
|
|
42
|
-
}), e.length === 0 && (t[o] = a);
|
|
43
|
-
}
|
|
44
|
-
function P(t, c, a, o) {
|
|
45
|
-
d(Object.keys(t), o);
|
|
46
|
-
const r = {
|
|
47
|
-
segment: "",
|
|
48
|
-
fullPath: "",
|
|
49
|
-
children: /* @__PURE__ */ new Map()
|
|
50
|
-
};
|
|
51
|
-
return Object.entries(c).forEach(([n, e]) => {
|
|
52
|
-
i(r, n, e.default, "layout", o);
|
|
53
|
-
}), Object.entries(t).forEach(([n, e]) => {
|
|
54
|
-
i(r, n, e, "page", o);
|
|
55
|
-
}), Object.entries(a).forEach(([n, e]) => {
|
|
56
|
-
i(r, n, e, "notFound", o);
|
|
57
|
-
}), r;
|
|
58
|
-
}
|
|
59
|
-
export {
|
|
60
|
-
d as a,
|
|
61
|
-
P as b,
|
|
62
|
-
h as e,
|
|
63
|
-
p as n
|
|
64
|
-
};
|