@@ -11,7 +11,20 @@ let getAndPost = (path, handler) =>
1111 ] ,
1212 );
1313
14- let rscRouting = (basePath, handler) => {
14+ let splitListAt = (n, list) => {
15+ let rec aux = (i, acc, remaining_list) =>
16+ if (i == 0 ) {
17+ (List . rev(acc), remaining_list == [] ? [ "" ] : remaining_list);
18+ } else {
19+ switch (remaining_list) {
20+ | [] => (List . rev(acc), [] )
21+ | [ h , ... t ] => aux(i - 1 , [ h, ... acc] , t)
22+ };
23+ };
24+ aux(n, [] , list);
25+ };
26+
27+ let rscRoutes = (basePath, handler) => {
1528 RouteDefinitions . generated_routes_paths
1629 |> List . map(path => {
1730 let path = path == "/" ? "" : path;
@@ -22,7 +35,8 @@ let rscRouting = (basePath, handler) => {
2235 request => {
2336 // Redirect when the route is accessed with a trailing slash
2437 Dream . log("Redirecting to /demo% s " , path);
25- Dream . redirect(request, basePath ++ path);
38+ let query = Dream . target(request) |> Dream . split_target |> snd;
39+ Dream . redirect(request, basePath ++ path ++ "?" ++ query);
2640 },
2741 ),
2842 getAndPost(
@@ -40,24 +54,76 @@ let rscRouting = (basePath, handler) => {
4054 };
4155
4256 let routeSegments = String . split_on_char('/' , path);
57+ let params = {
58+ let params = Supersonic . Params . create() ;
59+ routeSegments
60+ |> List . iter(segment =>
61+ if (String . starts_with(segment, ~prefix= ":" )) {
62+ let key =
63+ segment-> String . sub(1 , String . length(segment) - 1 );
64+ Supersonic . Params . add(
65+ params,
66+ key,
67+ Dream . param(request, key),
68+ );
69+ } else {
70+ () ;
71+ }
72+ );
73+
74+ params;
75+ };
76+
77+ /**
78+ * If the rsc query param is present, we need to render the specific route
79+ * based on the rsc path.
80+ */
4381 let rscParam = Dream . query(request, "rsc" );
82+
4483 let element =
4584 switch (rscParam) {
4685 | Some (rscPath ) =>
47- let rscRouteSegments = rscPath |> String . split_on_char('/' );
86+ let rscSegmentLevel =
87+ (routeSegments |> List . length)
88+ - (rscPath |> String . split_on_char('/' ) |> List . length);
89+
90+ /**
91+ * To get the dynamic segments (/:id) we cannot get them from the rsc path
92+ * but from the route path segments.
93+ * We then split the route path into 2 lists:
94+ * - the first list is the parent segments that aren't required but used to find the correct component
95+ * - the second list is the rsc segments
96+ * The list is split based on the number of segments in the rsc query param
97+ */
98+ let (parentSegments , rscSegments ) =
99+ splitListAt(rscSegmentLevel, routeSegments);
100+
48101 RouteDefinitions . (
49- routes |> renderComponent(routeSegments, rscRouteSegments)
102+ routes
103+ |> renderComponent(
104+ request,
105+ parentSegments,
106+ rscSegments,
107+ basePath,
108+ )
50109 )
51110 |> Option . value(~default= React . null);
52111 | None =>
53- <Supersonic . RouterContext . Provider url= {URL . makeExn(url)}>
112+ let routeData : Supersonic . RouterContext . routeData = {
113+ params,
114+ url: URL . makeExn(url),
115+ };
116+ <Supersonic . RouterContext . Provider routeData>
54117 {switch (
55- RouteDefinitions . (routes |> renderByPath(routeSegments))
118+ RouteDefinitions . (
119+ routes
120+ |> renderByPath(request, routeSegments, ~basePath)
121+ )
56122 ) {
57123 | Some (element ) => element
58124 | None => React . null
59125 }}
60- </Supersonic . RouterContext . Provider >
126+ </Supersonic . RouterContext . Provider >;
61127 };
62128
63129 handler(~element, request);
@@ -103,7 +169,7 @@ let server =
103169 getAndPost(Routes . singlePageRSC, Pages . SinglePageRSC . handler),
104170 getAndPost(Routes . dummyRouterRSC, Pages . DummyRouterRSC . handler),
105171 getAndPost(Routes . serverOnlyRSC, Pages . ServerOnlyRSC . handler),
106- ... rscRouting (Routes . router, Pages . Router . handler),
172+ ... rscRoutes (Routes . router, Pages . Router . handler),
107173 ] ),
108174 );
109175
0 commit comments