@react-router/dev 7.2.0-pre.0 → 7.2.0-pre.2
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/CHANGELOG.md +49 -0
- package/dist/cli/index.js +126 -61
- package/dist/config.js +1 -1
- package/dist/routes.js +1 -1
- package/dist/vite/cloudflare.js +1 -1
- package/dist/vite.js +120 -59
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# `@react-router/dev`
|
|
2
2
|
|
|
3
|
+
## 7.2.0-pre.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies:
|
|
8
|
+
- `react-router@7.2.0-pre.2`
|
|
9
|
+
- `@react-router/node@7.2.0-pre.2`
|
|
10
|
+
- `@react-router/serve@7.2.0-pre.2`
|
|
11
|
+
|
|
12
|
+
## 7.2.0-pre.1
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- New type-safe `href` utility that guarantees links point to actual paths in your app ([#13012](https://github.com/remix-run/react-router/pull/13012))
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { href } from "react-router";
|
|
20
|
+
|
|
21
|
+
export default function Component() {
|
|
22
|
+
const link = href("/blog/:slug", { slug: "my-first-post" });
|
|
23
|
+
return (
|
|
24
|
+
<main>
|
|
25
|
+
<Link to={href("/products/:id", { id: "asdf" })} />
|
|
26
|
+
<NavLink to={href("/:lang?/about", { lang: "en" })} />
|
|
27
|
+
</main>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- Fix typegen for repeated params ([#13012](https://github.com/remix-run/react-router/pull/13012))
|
|
35
|
+
|
|
36
|
+
In React Router, path parameters are keyed by their name.
|
|
37
|
+
So for a path pattern like `/a/:id/b/:id?/c/:id`, the last `:id` will set the value for `id` in `useParams` and the `params` prop.
|
|
38
|
+
For example, `/a/1/b/2/c/3` will result in the value `{ id: 3 }` at runtime.
|
|
39
|
+
|
|
40
|
+
Previously, generated types for params incorrectly modeled repeated params with an array.
|
|
41
|
+
So `/a/1/b/2/c/3` generated a type like `{ id: [1,2,3] }`.
|
|
42
|
+
|
|
43
|
+
To be consistent with runtime behavior, the generated types now correctly model the "last one wins" semantics of path parameters.
|
|
44
|
+
So `/a/1/b/2/c/3` now generates a type like `{ id: 3 }`.
|
|
45
|
+
|
|
46
|
+
- Fix `ArgError: unknown or unexpected option: --version` when running `react-router --version` ([#13012](https://github.com/remix-run/react-router/pull/13012))
|
|
47
|
+
- Updated dependencies:
|
|
48
|
+
- `react-router@7.2.0-pre.1`
|
|
49
|
+
- `@react-router/node@7.2.0-pre.1`
|
|
50
|
+
- `@react-router/serve@7.2.0-pre.1`
|
|
51
|
+
|
|
3
52
|
## 7.2.0-pre.0
|
|
4
53
|
|
|
5
54
|
### Minor Changes
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* @react-router/dev v7.2.0-pre.
|
|
3
|
+
* @react-router/dev v7.2.0-pre.2
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) Remix Software Inc.
|
|
6
6
|
*
|
|
@@ -636,6 +636,25 @@ var init_profiler = __esm({
|
|
|
636
636
|
}
|
|
637
637
|
});
|
|
638
638
|
|
|
639
|
+
// vite/babel.ts
|
|
640
|
+
var babel_exports = {};
|
|
641
|
+
__export(babel_exports, {
|
|
642
|
+
generate: () => generate,
|
|
643
|
+
parse: () => import_parser.parse,
|
|
644
|
+
t: () => t,
|
|
645
|
+
traverse: () => traverse
|
|
646
|
+
});
|
|
647
|
+
var import_parser, t, traverse, generate;
|
|
648
|
+
var init_babel = __esm({
|
|
649
|
+
"vite/babel.ts"() {
|
|
650
|
+
"use strict";
|
|
651
|
+
import_parser = require("@babel/parser");
|
|
652
|
+
t = __toESM(require("@babel/types"));
|
|
653
|
+
traverse = require("@babel/traverse").default;
|
|
654
|
+
generate = require("@babel/generator").default;
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
|
|
639
658
|
// typegen/paths.ts
|
|
640
659
|
function getTypesDir(ctx) {
|
|
641
660
|
return Path2.join(ctx.rootDirectory, ".react-router/types");
|
|
@@ -657,12 +676,55 @@ var init_paths = __esm({
|
|
|
657
676
|
}
|
|
658
677
|
});
|
|
659
678
|
|
|
679
|
+
// typegen/params.ts
|
|
680
|
+
function parse2(fullpath2) {
|
|
681
|
+
const result = {};
|
|
682
|
+
let segments = fullpath2.split("/");
|
|
683
|
+
segments.forEach((segment) => {
|
|
684
|
+
const match = segment.match(/^:([\w-]+)(\?)?/);
|
|
685
|
+
if (!match) return;
|
|
686
|
+
const param = match[1];
|
|
687
|
+
const isRequired = match[2] === void 0;
|
|
688
|
+
result[param] ||= isRequired;
|
|
689
|
+
return;
|
|
690
|
+
});
|
|
691
|
+
const hasSplat = segments.at(-1) === "*";
|
|
692
|
+
if (hasSplat) result["*"] = true;
|
|
693
|
+
return result;
|
|
694
|
+
}
|
|
695
|
+
var init_params = __esm({
|
|
696
|
+
"typegen/params.ts"() {
|
|
697
|
+
"use strict";
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
// typegen/route.ts
|
|
702
|
+
function lineage(routes2, route) {
|
|
703
|
+
const result = [];
|
|
704
|
+
while (route) {
|
|
705
|
+
result.push(route);
|
|
706
|
+
if (!route.parentId) break;
|
|
707
|
+
route = routes2[route.parentId];
|
|
708
|
+
}
|
|
709
|
+
result.reverse();
|
|
710
|
+
return result;
|
|
711
|
+
}
|
|
712
|
+
function fullpath(lineage2) {
|
|
713
|
+
if (lineage2.length === 1 && lineage2[0].id === "root") return "/";
|
|
714
|
+
return "/" + lineage2.map((route) => route.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path9) => path9 !== void 0 && path9 !== "").join("/");
|
|
715
|
+
}
|
|
716
|
+
var init_route = __esm({
|
|
717
|
+
"typegen/route.ts"() {
|
|
718
|
+
"use strict";
|
|
719
|
+
}
|
|
720
|
+
});
|
|
721
|
+
|
|
660
722
|
// typegen/generate.ts
|
|
661
|
-
function
|
|
662
|
-
const
|
|
663
|
-
const
|
|
723
|
+
function generate2(ctx, route) {
|
|
724
|
+
const lineage2 = lineage(ctx.config.routes, route);
|
|
725
|
+
const fullpath2 = fullpath(lineage2);
|
|
664
726
|
const typesPath = getTypesPath(ctx, route);
|
|
665
|
-
const parents =
|
|
727
|
+
const parents = lineage2.slice(0, -1);
|
|
666
728
|
const parentTypeImports = parents.map((parent, i) => {
|
|
667
729
|
const rel = Path3.relative(
|
|
668
730
|
Path3.dirname(typesPath),
|
|
@@ -689,7 +751,7 @@ function generate(ctx, route) {
|
|
|
689
751
|
file: "${route.file}"
|
|
690
752
|
path: "${route.path}"
|
|
691
753
|
params: {${formatParamProperties(
|
|
692
|
-
|
|
754
|
+
fullpath2
|
|
693
755
|
)}} & { [key: string]: string | undefined }
|
|
694
756
|
module: Module
|
|
695
757
|
loaderData: T.CreateLoaderData<Module>
|
|
@@ -718,46 +780,13 @@ function generate(ctx, route) {
|
|
|
718
780
|
}
|
|
719
781
|
`;
|
|
720
782
|
}
|
|
721
|
-
function
|
|
722
|
-
const
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
route = routes2[route.parentId];
|
|
727
|
-
}
|
|
728
|
-
result.reverse();
|
|
729
|
-
return result;
|
|
730
|
-
}
|
|
731
|
-
function formatParamProperties(urlpath) {
|
|
732
|
-
const params = parseParams(urlpath);
|
|
733
|
-
const properties = Object.entries(params).map(([name, values]) => {
|
|
734
|
-
if (values.length === 1) {
|
|
735
|
-
const isOptional = values[0];
|
|
736
|
-
return isOptional ? `"${name}"?: string` : `"${name}": string`;
|
|
737
|
-
}
|
|
738
|
-
const items = values.map(
|
|
739
|
-
(isOptional) => isOptional ? "string | undefined" : "string"
|
|
740
|
-
);
|
|
741
|
-
return `"${name}": [${items.join(", ")}]`;
|
|
742
|
-
});
|
|
783
|
+
function formatParamProperties(fullpath2) {
|
|
784
|
+
const params = parse2(fullpath2);
|
|
785
|
+
const properties = Object.entries(params).map(
|
|
786
|
+
([name, isRequired]) => isRequired ? `"${name}": string` : `"${name}"?: string`
|
|
787
|
+
);
|
|
743
788
|
return properties.join("; ");
|
|
744
789
|
}
|
|
745
|
-
function parseParams(urlpath) {
|
|
746
|
-
const result = {};
|
|
747
|
-
let segments = urlpath.split("/");
|
|
748
|
-
segments.forEach((segment) => {
|
|
749
|
-
const match = segment.match(/^:([\w-]+)(\?)?/);
|
|
750
|
-
if (!match) return;
|
|
751
|
-
const param = match[1];
|
|
752
|
-
const isOptional = match[2] !== void 0;
|
|
753
|
-
result[param] ??= [];
|
|
754
|
-
result[param].push(isOptional);
|
|
755
|
-
return;
|
|
756
|
-
});
|
|
757
|
-
const hasSplat = segments.at(-1) === "*";
|
|
758
|
-
if (hasSplat) result["*"] = [false];
|
|
759
|
-
return result;
|
|
760
|
-
}
|
|
761
790
|
var import_dedent, Path3, Pathe2, noExtension;
|
|
762
791
|
var init_generate = __esm({
|
|
763
792
|
"typegen/generate.ts"() {
|
|
@@ -766,6 +795,8 @@ var init_generate = __esm({
|
|
|
766
795
|
Path3 = __toESM(require("pathe"));
|
|
767
796
|
Pathe2 = __toESM(require("pathe/utils"));
|
|
768
797
|
init_paths();
|
|
798
|
+
init_params();
|
|
799
|
+
init_route();
|
|
769
800
|
noExtension = (path9) => Path3.join(Path3.dirname(path9), Pathe2.filename(path9));
|
|
770
801
|
}
|
|
771
802
|
});
|
|
@@ -818,33 +849,67 @@ async function writeAll(ctx) {
|
|
|
818
849
|
import_node_fs3.default.rmSync(typegenDir, { recursive: true, force: true });
|
|
819
850
|
Object.values(ctx.config.routes).forEach((route) => {
|
|
820
851
|
const typesPath = getTypesPath(ctx, route);
|
|
821
|
-
const content =
|
|
852
|
+
const content = generate2(ctx, route);
|
|
822
853
|
import_node_fs3.default.mkdirSync(Path4.dirname(typesPath), { recursive: true });
|
|
823
854
|
import_node_fs3.default.writeFileSync(typesPath, content);
|
|
824
855
|
});
|
|
856
|
+
const registerPath = Path4.join(typegenDir, "+register.ts");
|
|
857
|
+
import_node_fs3.default.writeFileSync(registerPath, register(ctx));
|
|
825
858
|
}
|
|
826
|
-
|
|
859
|
+
function register(ctx) {
|
|
860
|
+
const register2 = import_dedent2.default`
|
|
861
|
+
import "react-router";
|
|
862
|
+
|
|
863
|
+
declare module "react-router" {
|
|
864
|
+
interface Register {
|
|
865
|
+
params: Params;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
`;
|
|
869
|
+
const { t: t2 } = babel_exports;
|
|
870
|
+
const typeParams = t2.tsTypeAliasDeclaration(
|
|
871
|
+
t2.identifier("Params"),
|
|
872
|
+
null,
|
|
873
|
+
t2.tsTypeLiteral(
|
|
874
|
+
Object.values(ctx.config.routes).map((route) => {
|
|
875
|
+
if (route.id !== "root" && !route.path) return void 0;
|
|
876
|
+
const lineage2 = lineage(ctx.config.routes, route);
|
|
877
|
+
const fullpath2 = fullpath(lineage2);
|
|
878
|
+
const params = parse2(fullpath2);
|
|
879
|
+
return t2.tsPropertySignature(
|
|
880
|
+
t2.stringLiteral(fullpath2),
|
|
881
|
+
t2.tsTypeAnnotation(
|
|
882
|
+
t2.tsTypeLiteral(
|
|
883
|
+
Object.entries(params).map(([param, isRequired]) => {
|
|
884
|
+
const property = t2.tsPropertySignature(
|
|
885
|
+
t2.stringLiteral(param),
|
|
886
|
+
t2.tsTypeAnnotation(t2.tsStringKeyword())
|
|
887
|
+
);
|
|
888
|
+
property.optional = !isRequired;
|
|
889
|
+
return property;
|
|
890
|
+
})
|
|
891
|
+
)
|
|
892
|
+
)
|
|
893
|
+
);
|
|
894
|
+
}).filter((x) => x !== void 0)
|
|
895
|
+
)
|
|
896
|
+
);
|
|
897
|
+
return [register2, generate(typeParams).code].join("\n\n");
|
|
898
|
+
}
|
|
899
|
+
var import_node_fs3, import_dedent2, Path4, import_picocolors3;
|
|
827
900
|
var init_typegen = __esm({
|
|
828
901
|
"typegen/index.ts"() {
|
|
829
902
|
"use strict";
|
|
830
903
|
import_node_fs3 = __toESM(require("fs"));
|
|
904
|
+
import_dedent2 = __toESM(require("dedent"));
|
|
831
905
|
Path4 = __toESM(require("pathe"));
|
|
832
906
|
import_picocolors3 = __toESM(require("picocolors"));
|
|
833
907
|
init_config();
|
|
908
|
+
init_babel();
|
|
834
909
|
init_generate();
|
|
835
910
|
init_paths();
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
// vite/babel.ts
|
|
840
|
-
var import_parser, t, traverse, generate2;
|
|
841
|
-
var init_babel = __esm({
|
|
842
|
-
"vite/babel.ts"() {
|
|
843
|
-
"use strict";
|
|
844
|
-
import_parser = require("@babel/parser");
|
|
845
|
-
t = __toESM(require("@babel/types"));
|
|
846
|
-
traverse = require("@babel/traverse").default;
|
|
847
|
-
generate2 = require("@babel/generator").default;
|
|
911
|
+
init_params();
|
|
912
|
+
init_route();
|
|
848
913
|
}
|
|
849
914
|
});
|
|
850
915
|
|
|
@@ -971,11 +1036,11 @@ var init_route_chunks = __esm({
|
|
|
971
1036
|
});
|
|
972
1037
|
|
|
973
1038
|
// vite/with-props.ts
|
|
974
|
-
var
|
|
1039
|
+
var import_dedent3, vmod;
|
|
975
1040
|
var init_with_props = __esm({
|
|
976
1041
|
"vite/with-props.ts"() {
|
|
977
1042
|
"use strict";
|
|
978
|
-
|
|
1043
|
+
import_dedent3 = __toESM(require("dedent"));
|
|
979
1044
|
init_babel();
|
|
980
1045
|
init_virtual_module();
|
|
981
1046
|
vmod = create("with-props");
|
|
@@ -1993,7 +2058,7 @@ async function run2(argv = process.argv.slice(2)) {
|
|
|
1993
2058
|
return;
|
|
1994
2059
|
}
|
|
1995
2060
|
if (flags.version) {
|
|
1996
|
-
let version = require("
|
|
2061
|
+
let version = require("../../package.json").version;
|
|
1997
2062
|
console.log(version);
|
|
1998
2063
|
return;
|
|
1999
2064
|
}
|
package/dist/config.js
CHANGED
package/dist/routes.js
CHANGED
package/dist/vite/cloudflare.js
CHANGED
package/dist/vite.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @react-router/dev v7.2.0-pre.
|
|
2
|
+
* @react-router/dev v7.2.0-pre.2
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -59,6 +59,7 @@ var import_kebabCase = __toESM(require("lodash/kebabCase"));
|
|
|
59
59
|
|
|
60
60
|
// typegen/index.ts
|
|
61
61
|
var import_node_fs2 = __toESM(require("fs"));
|
|
62
|
+
var import_dedent2 = __toESM(require("dedent"));
|
|
62
63
|
var Path4 = __toESM(require("pathe"));
|
|
63
64
|
var import_picocolors2 = __toESM(require("picocolors"));
|
|
64
65
|
|
|
@@ -633,6 +634,19 @@ function findEntry(dir, basename2, options) {
|
|
|
633
634
|
return void 0;
|
|
634
635
|
}
|
|
635
636
|
|
|
637
|
+
// vite/babel.ts
|
|
638
|
+
var babel_exports = {};
|
|
639
|
+
__export(babel_exports, {
|
|
640
|
+
generate: () => generate,
|
|
641
|
+
parse: () => import_parser.parse,
|
|
642
|
+
t: () => t,
|
|
643
|
+
traverse: () => traverse
|
|
644
|
+
});
|
|
645
|
+
var import_parser = require("@babel/parser");
|
|
646
|
+
var t = __toESM(require("@babel/types"));
|
|
647
|
+
var traverse = require("@babel/traverse").default;
|
|
648
|
+
var generate = require("@babel/generator").default;
|
|
649
|
+
|
|
636
650
|
// typegen/generate.ts
|
|
637
651
|
var import_dedent = __toESM(require("dedent"));
|
|
638
652
|
var Path3 = __toESM(require("pathe"));
|
|
@@ -653,12 +667,45 @@ function getTypesPath(ctx, route) {
|
|
|
653
667
|
);
|
|
654
668
|
}
|
|
655
669
|
|
|
670
|
+
// typegen/params.ts
|
|
671
|
+
function parse2(fullpath2) {
|
|
672
|
+
const result = {};
|
|
673
|
+
let segments = fullpath2.split("/");
|
|
674
|
+
segments.forEach((segment) => {
|
|
675
|
+
const match = segment.match(/^:([\w-]+)(\?)?/);
|
|
676
|
+
if (!match) return;
|
|
677
|
+
const param = match[1];
|
|
678
|
+
const isRequired = match[2] === void 0;
|
|
679
|
+
result[param] ||= isRequired;
|
|
680
|
+
return;
|
|
681
|
+
});
|
|
682
|
+
const hasSplat = segments.at(-1) === "*";
|
|
683
|
+
if (hasSplat) result["*"] = true;
|
|
684
|
+
return result;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// typegen/route.ts
|
|
688
|
+
function lineage(routes, route) {
|
|
689
|
+
const result = [];
|
|
690
|
+
while (route) {
|
|
691
|
+
result.push(route);
|
|
692
|
+
if (!route.parentId) break;
|
|
693
|
+
route = routes[route.parentId];
|
|
694
|
+
}
|
|
695
|
+
result.reverse();
|
|
696
|
+
return result;
|
|
697
|
+
}
|
|
698
|
+
function fullpath(lineage2) {
|
|
699
|
+
if (lineage2.length === 1 && lineage2[0].id === "root") return "/";
|
|
700
|
+
return "/" + lineage2.map((route) => route.path?.replace(/^\//, "")?.replace(/\/$/, "")).filter((path7) => path7 !== void 0 && path7 !== "").join("/");
|
|
701
|
+
}
|
|
702
|
+
|
|
656
703
|
// typegen/generate.ts
|
|
657
|
-
function
|
|
658
|
-
const
|
|
659
|
-
const
|
|
704
|
+
function generate2(ctx, route) {
|
|
705
|
+
const lineage2 = lineage(ctx.config.routes, route);
|
|
706
|
+
const fullpath2 = fullpath(lineage2);
|
|
660
707
|
const typesPath = getTypesPath(ctx, route);
|
|
661
|
-
const parents =
|
|
708
|
+
const parents = lineage2.slice(0, -1);
|
|
662
709
|
const parentTypeImports = parents.map((parent, i) => {
|
|
663
710
|
const rel = Path3.relative(
|
|
664
711
|
Path3.dirname(typesPath),
|
|
@@ -685,7 +732,7 @@ function generate(ctx, route) {
|
|
|
685
732
|
file: "${route.file}"
|
|
686
733
|
path: "${route.path}"
|
|
687
734
|
params: {${formatParamProperties(
|
|
688
|
-
|
|
735
|
+
fullpath2
|
|
689
736
|
)}} & { [key: string]: string | undefined }
|
|
690
737
|
module: Module
|
|
691
738
|
loaderData: T.CreateLoaderData<Module>
|
|
@@ -715,46 +762,13 @@ function generate(ctx, route) {
|
|
|
715
762
|
`;
|
|
716
763
|
}
|
|
717
764
|
var noExtension = (path7) => Path3.join(Path3.dirname(path7), Pathe2.filename(path7));
|
|
718
|
-
function
|
|
719
|
-
const
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
route = routes[route.parentId];
|
|
724
|
-
}
|
|
725
|
-
result.reverse();
|
|
726
|
-
return result;
|
|
727
|
-
}
|
|
728
|
-
function formatParamProperties(urlpath) {
|
|
729
|
-
const params = parseParams(urlpath);
|
|
730
|
-
const properties = Object.entries(params).map(([name, values]) => {
|
|
731
|
-
if (values.length === 1) {
|
|
732
|
-
const isOptional = values[0];
|
|
733
|
-
return isOptional ? `"${name}"?: string` : `"${name}": string`;
|
|
734
|
-
}
|
|
735
|
-
const items = values.map(
|
|
736
|
-
(isOptional) => isOptional ? "string | undefined" : "string"
|
|
737
|
-
);
|
|
738
|
-
return `"${name}": [${items.join(", ")}]`;
|
|
739
|
-
});
|
|
765
|
+
function formatParamProperties(fullpath2) {
|
|
766
|
+
const params = parse2(fullpath2);
|
|
767
|
+
const properties = Object.entries(params).map(
|
|
768
|
+
([name, isRequired]) => isRequired ? `"${name}": string` : `"${name}"?: string`
|
|
769
|
+
);
|
|
740
770
|
return properties.join("; ");
|
|
741
771
|
}
|
|
742
|
-
function parseParams(urlpath) {
|
|
743
|
-
const result = {};
|
|
744
|
-
let segments = urlpath.split("/");
|
|
745
|
-
segments.forEach((segment) => {
|
|
746
|
-
const match = segment.match(/^:([\w-]+)(\?)?/);
|
|
747
|
-
if (!match) return;
|
|
748
|
-
const param = match[1];
|
|
749
|
-
const isOptional = match[2] !== void 0;
|
|
750
|
-
result[param] ??= [];
|
|
751
|
-
result[param].push(isOptional);
|
|
752
|
-
return;
|
|
753
|
-
});
|
|
754
|
-
const hasSplat = segments.at(-1) === "*";
|
|
755
|
-
if (hasSplat) result["*"] = [false];
|
|
756
|
-
return result;
|
|
757
|
-
}
|
|
758
772
|
|
|
759
773
|
// typegen/index.ts
|
|
760
774
|
async function watch(rootDirectory, { logger } = {}) {
|
|
@@ -800,17 +814,53 @@ async function writeAll(ctx) {
|
|
|
800
814
|
import_node_fs2.default.rmSync(typegenDir, { recursive: true, force: true });
|
|
801
815
|
Object.values(ctx.config.routes).forEach((route) => {
|
|
802
816
|
const typesPath = getTypesPath(ctx, route);
|
|
803
|
-
const content =
|
|
817
|
+
const content = generate2(ctx, route);
|
|
804
818
|
import_node_fs2.default.mkdirSync(Path4.dirname(typesPath), { recursive: true });
|
|
805
819
|
import_node_fs2.default.writeFileSync(typesPath, content);
|
|
806
820
|
});
|
|
821
|
+
const registerPath = Path4.join(typegenDir, "+register.ts");
|
|
822
|
+
import_node_fs2.default.writeFileSync(registerPath, register(ctx));
|
|
807
823
|
}
|
|
824
|
+
function register(ctx) {
|
|
825
|
+
const register2 = import_dedent2.default`
|
|
826
|
+
import "react-router";
|
|
808
827
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
828
|
+
declare module "react-router" {
|
|
829
|
+
interface Register {
|
|
830
|
+
params: Params;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
`;
|
|
834
|
+
const { t: t2 } = babel_exports;
|
|
835
|
+
const typeParams = t2.tsTypeAliasDeclaration(
|
|
836
|
+
t2.identifier("Params"),
|
|
837
|
+
null,
|
|
838
|
+
t2.tsTypeLiteral(
|
|
839
|
+
Object.values(ctx.config.routes).map((route) => {
|
|
840
|
+
if (route.id !== "root" && !route.path) return void 0;
|
|
841
|
+
const lineage2 = lineage(ctx.config.routes, route);
|
|
842
|
+
const fullpath2 = fullpath(lineage2);
|
|
843
|
+
const params = parse2(fullpath2);
|
|
844
|
+
return t2.tsPropertySignature(
|
|
845
|
+
t2.stringLiteral(fullpath2),
|
|
846
|
+
t2.tsTypeAnnotation(
|
|
847
|
+
t2.tsTypeLiteral(
|
|
848
|
+
Object.entries(params).map(([param, isRequired]) => {
|
|
849
|
+
const property = t2.tsPropertySignature(
|
|
850
|
+
t2.stringLiteral(param),
|
|
851
|
+
t2.tsTypeAnnotation(t2.tsStringKeyword())
|
|
852
|
+
);
|
|
853
|
+
property.optional = !isRequired;
|
|
854
|
+
return property;
|
|
855
|
+
})
|
|
856
|
+
)
|
|
857
|
+
)
|
|
858
|
+
);
|
|
859
|
+
}).filter((x) => x !== void 0)
|
|
860
|
+
)
|
|
861
|
+
);
|
|
862
|
+
return [register2, generate(typeParams).code].join("\n\n");
|
|
863
|
+
}
|
|
814
864
|
|
|
815
865
|
// vite/node-adapter.ts
|
|
816
866
|
var import_node_events = require("events");
|
|
@@ -1598,7 +1648,7 @@ function getChunkedExport(code, exportName, generateOptions = {}, cache, cacheKe
|
|
|
1598
1648
|
}
|
|
1599
1649
|
throw new Error(`Unknown export node type: ${node.type}`);
|
|
1600
1650
|
}).filter((node) => node !== null);
|
|
1601
|
-
return
|
|
1651
|
+
return generate(ast, generateOptions);
|
|
1602
1652
|
}
|
|
1603
1653
|
);
|
|
1604
1654
|
}
|
|
@@ -1714,7 +1764,7 @@ function omitChunkedExports(code, exportNames, generateOptions = {}, cache, cach
|
|
|
1714
1764
|
if (ast.program.body.length === 0) {
|
|
1715
1765
|
return void 0;
|
|
1716
1766
|
}
|
|
1717
|
-
return
|
|
1767
|
+
return generate(ast, generateOptions);
|
|
1718
1768
|
}
|
|
1719
1769
|
);
|
|
1720
1770
|
}
|
|
@@ -1776,7 +1826,7 @@ function getRouteChunkNameFromModuleId(id) {
|
|
|
1776
1826
|
}
|
|
1777
1827
|
|
|
1778
1828
|
// vite/with-props.ts
|
|
1779
|
-
var
|
|
1829
|
+
var import_dedent3 = __toESM(require("dedent"));
|
|
1780
1830
|
var vmod = create("with-props");
|
|
1781
1831
|
var NAMED_COMPONENT_EXPORTS = ["HydrateFallback", "ErrorBoundary"];
|
|
1782
1832
|
var plugin = {
|
|
@@ -1787,7 +1837,7 @@ var plugin = {
|
|
|
1787
1837
|
},
|
|
1788
1838
|
async load(id) {
|
|
1789
1839
|
if (id !== vmod.resolvedId) return;
|
|
1790
|
-
return
|
|
1840
|
+
return import_dedent3.default`
|
|
1791
1841
|
import { createElement as h } from "react";
|
|
1792
1842
|
import { useActionData, useLoaderData, useMatches, useParams, useRouteError } from "react-router";
|
|
1793
1843
|
|
|
@@ -3086,7 +3136,7 @@ var reactRouterVitePlugin = () => {
|
|
|
3086
3136
|
removeExports(ast, SERVER_ONLY_ROUTE_EXPORTS);
|
|
3087
3137
|
}
|
|
3088
3138
|
transform(ast);
|
|
3089
|
-
return
|
|
3139
|
+
return generate(ast, {
|
|
3090
3140
|
sourceMaps: true,
|
|
3091
3141
|
filename: id,
|
|
3092
3142
|
sourceFileName: filepath
|
|
@@ -3694,10 +3744,21 @@ async function validateSsrFalsePrerenderExports(viteConfig, ctx, manifest, viteC
|
|
|
3694
3744
|
`Prerender: ${invalidApis.length} invalid route export(s) in \`${route.id}\` when prerendering with \`ssr:false\`: ${invalidApis.join(", ")}. See https://reactrouter.com/how-to/pre-rendering for more information.`
|
|
3695
3745
|
);
|
|
3696
3746
|
}
|
|
3697
|
-
if (
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3747
|
+
if (!prerenderedRoutes.has(routeId)) {
|
|
3748
|
+
if (exports2.includes("loader")) {
|
|
3749
|
+
errors.push(
|
|
3750
|
+
`Prerender: 1 invalid route export in \`${route.id}\` when using \`ssr:false\` with \`prerender\` because the route is never prerendered so the loader will never be called. See https://reactrouter.com/how-to/pre-rendering for more information.`
|
|
3751
|
+
);
|
|
3752
|
+
}
|
|
3753
|
+
let parentRoute = route.parentId ? manifest.routes[route.parentId] : null;
|
|
3754
|
+
while (parentRoute && parentRoute.id !== "root") {
|
|
3755
|
+
if (parentRoute.hasLoader && !parentRoute.hasClientLoader) {
|
|
3756
|
+
errors.push(
|
|
3757
|
+
`Prerender: 1 invalid route export in \`${parentRoute.id}\` when using \`ssr:false\` with \`prerender\`: \`loader\`. This is because the route has non-pre-rendered children paths and does not have it's own \`clientLoader\` to be used when those paths are hydrated as a SPA. You can fix this error by adding a \`clientLoader\` to the route or by pre-rendering the children paths. See https://reactrouter.com/how-to/pre-rendering for more information.`
|
|
3758
|
+
);
|
|
3759
|
+
}
|
|
3760
|
+
parentRoute = parentRoute.parentId && parentRoute.parentId !== "root" ? manifest.routes[parentRoute.parentId] : null;
|
|
3761
|
+
}
|
|
3701
3762
|
}
|
|
3702
3763
|
}
|
|
3703
3764
|
if (errors.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-router/dev",
|
|
3
|
-
"version": "7.2.0-pre.
|
|
3
|
+
"version": "7.2.0-pre.2",
|
|
4
4
|
"description": "Dev tools and CLI for React Router",
|
|
5
5
|
"homepage": "https://reactrouter.com",
|
|
6
6
|
"bugs": {
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"set-cookie-parser": "^2.6.0",
|
|
89
89
|
"valibot": "^0.41.0",
|
|
90
90
|
"vite-node": "3.0.0-beta.2",
|
|
91
|
-
"@react-router/node": "7.2.0-pre.
|
|
91
|
+
"@react-router/node": "7.2.0-pre.2"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@types/babel__core": "^7.20.5",
|
|
@@ -117,15 +117,15 @@
|
|
|
117
117
|
"vite": "^6.0.0",
|
|
118
118
|
"wireit": "0.14.9",
|
|
119
119
|
"wrangler": "^3.28.2",
|
|
120
|
-
"@react-router/serve": "7.2.0-pre.
|
|
121
|
-
"react-router": "^7.2.0-pre.
|
|
120
|
+
"@react-router/serve": "7.2.0-pre.2",
|
|
121
|
+
"react-router": "^7.2.0-pre.2"
|
|
122
122
|
},
|
|
123
123
|
"peerDependencies": {
|
|
124
124
|
"typescript": "^5.1.0",
|
|
125
125
|
"vite": "^5.1.0 || ^6.0.0",
|
|
126
126
|
"wrangler": "^3.28.2",
|
|
127
|
-
"@react-router/serve": "^7.2.0-pre.
|
|
128
|
-
"react-router": "^7.2.0-pre.
|
|
127
|
+
"@react-router/serve": "^7.2.0-pre.2",
|
|
128
|
+
"react-router": "^7.2.0-pre.2"
|
|
129
129
|
},
|
|
130
130
|
"peerDependenciesMeta": {
|
|
131
131
|
"@react-router/serve": {
|