@rebask/core 0.2.1 → 0.4.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.
Files changed (210) hide show
  1. package/dist/components/head.d.ts +2 -11
  2. package/dist/components/head.d.ts.map +1 -1
  3. package/dist/components/head.js +12 -24
  4. package/dist/components/image.d.ts +16 -3
  5. package/dist/components/image.d.ts.map +1 -1
  6. package/dist/components/image.js +50 -68
  7. package/dist/components/link.d.ts.map +1 -1
  8. package/dist/components/link.js +6 -2
  9. package/dist/entry.browser.js +2 -2
  10. package/dist/entry.ssr.d.ts.map +1 -1
  11. package/dist/entry.ssr.js +12 -7
  12. package/dist/handlers/rsc/background-render.js +2 -2
  13. package/dist/handlers/rsc/render-request.js +2 -2
  14. package/dist/handlers/rsc/render-to-response.js +2 -2
  15. package/dist/handlers/rsc/state.d.ts.map +1 -1
  16. package/dist/handlers/rsc/state.js +11 -5
  17. package/dist/lib/client-route-prediction.d.ts +1 -1
  18. package/dist/lib/client-route-prediction.d.ts.map +1 -1
  19. package/dist/lib/client-route-prediction.js +2 -7
  20. package/dist/lib/head/head-manager.d.ts +9 -0
  21. package/dist/lib/head/head-manager.d.ts.map +1 -0
  22. package/dist/lib/head/head-manager.js +98 -0
  23. package/dist/lib/head/head-script.js +8 -13
  24. package/dist/lib/image-optimization/fetch-remote-image.d.ts +17 -0
  25. package/dist/lib/image-optimization/fetch-remote-image.d.ts.map +1 -0
  26. package/dist/lib/image-optimization/fetch-remote-image.js +157 -0
  27. package/dist/lib/image-optimization/get-img-props.d.ts +3 -5
  28. package/dist/lib/image-optimization/get-img-props.d.ts.map +1 -1
  29. package/dist/lib/image-optimization/get-img-props.js +66 -40
  30. package/dist/lib/image-optimization/handler.d.ts +0 -3
  31. package/dist/lib/image-optimization/handler.d.ts.map +1 -1
  32. package/dist/lib/image-optimization/handler.js +339 -124
  33. package/dist/lib/image-optimization/image-config.d.ts +31 -4
  34. package/dist/lib/image-optimization/image-config.d.ts.map +1 -1
  35. package/dist/lib/image-optimization/image-config.js +6 -0
  36. package/dist/lib/image-optimization/image-error.d.ts +8 -0
  37. package/dist/lib/image-optimization/image-error.d.ts.map +1 -0
  38. package/dist/lib/image-optimization/image-error.js +10 -0
  39. package/dist/lib/image-optimization/image-plugin.d.ts +2 -0
  40. package/dist/lib/image-optimization/image-plugin.d.ts.map +1 -1
  41. package/dist/lib/image-optimization/image-plugin.js +36 -16
  42. package/dist/lib/image-optimization/is-private-ip.d.ts +2 -0
  43. package/dist/lib/image-optimization/is-private-ip.d.ts.map +1 -0
  44. package/dist/lib/image-optimization/is-private-ip.js +43 -0
  45. package/dist/lib/image-optimization/match-patterns.d.ts +4 -0
  46. package/dist/lib/image-optimization/match-patterns.d.ts.map +1 -0
  47. package/dist/lib/image-optimization/match-patterns.js +39 -0
  48. package/dist/lib/image-optimization/read-body.d.ts +2 -0
  49. package/dist/lib/image-optimization/read-body.d.ts.map +1 -0
  50. package/dist/lib/image-optimization/read-body.js +27 -0
  51. package/dist/lib/image-optimization/static-image-loader.d.ts +2 -0
  52. package/dist/lib/image-optimization/static-image-loader.d.ts.map +1 -0
  53. package/dist/lib/image-optimization/static-image-loader.js +60 -0
  54. package/dist/lib/plugin-names.d.ts +3 -0
  55. package/dist/lib/plugin-names.d.ts.map +1 -0
  56. package/dist/lib/plugin-names.js +2 -0
  57. package/dist/lib/proxy/build-proxy.d.ts +1 -1
  58. package/dist/lib/proxy/build-proxy.d.ts.map +1 -1
  59. package/dist/lib/proxy/build-proxy.js +4 -11
  60. package/dist/lib/proxy/pattern.d.ts +7 -0
  61. package/dist/lib/proxy/pattern.d.ts.map +1 -0
  62. package/dist/lib/proxy/pattern.js +18 -0
  63. package/dist/lib/proxy/types.d.ts +3 -1
  64. package/dist/lib/proxy/types.d.ts.map +1 -1
  65. package/dist/lib/route-prediction.d.ts.map +1 -1
  66. package/dist/lib/rsc-request.d.ts.map +1 -1
  67. package/dist/lib/rsc-request.js +6 -4
  68. package/dist/lib/server-router/build-entries.d.ts +76 -0
  69. package/dist/lib/server-router/build-entries.d.ts.map +1 -0
  70. package/dist/lib/server-router/build-entries.js +74 -0
  71. package/dist/lib/server-router/get-router.d.ts.map +1 -1
  72. package/dist/lib/server-router/get-router.js +55 -105
  73. package/dist/lib/server-router/rou3.d.ts +20 -0
  74. package/dist/lib/server-router/rou3.d.ts.map +1 -0
  75. package/dist/lib/server-router/rou3.js +55 -0
  76. package/dist/lib/server-router/route-entries.d.ts +16 -0
  77. package/dist/lib/server-router/route-entries.d.ts.map +1 -0
  78. package/dist/lib/server-router/route-entries.js +67 -0
  79. package/dist/lib/server-router/types.d.ts +24 -33
  80. package/dist/lib/server-router/types.d.ts.map +1 -1
  81. package/dist/lib/server-router/types.js +1 -6
  82. package/dist/lib/types.d.ts +2 -2
  83. package/dist/lib/types.d.ts.map +1 -1
  84. package/dist/plugins/prerender.d.ts +3 -4
  85. package/dist/plugins/prerender.d.ts.map +1 -1
  86. package/dist/plugins/prerender.js +31 -0
  87. package/dist/plugins/proxy.d.ts.map +1 -1
  88. package/dist/plugins/proxy.js +7 -1
  89. package/dist/plugins/router/rou3-compiled.d.ts +9 -0
  90. package/dist/plugins/router/rou3-compiled.d.ts.map +1 -0
  91. package/dist/plugins/router/rou3-compiled.js +14 -0
  92. package/dist/plugins/router/rou3-router.d.ts +3 -0
  93. package/dist/plugins/router/rou3-router.d.ts.map +1 -0
  94. package/dist/plugins/router/rou3-router.js +16 -0
  95. package/dist/plugins/router/router-plugin.d.ts +6 -16
  96. package/dist/plugins/router/router-plugin.d.ts.map +1 -1
  97. package/dist/plugins/router/router-plugin.js +43 -22
  98. package/dist/proxy.d.ts +1 -0
  99. package/dist/proxy.d.ts.map +1 -1
  100. package/dist/proxy.js +1 -0
  101. package/dist/request-context.d.ts +0 -2
  102. package/dist/request-context.d.ts.map +1 -1
  103. package/dist/request-context.js +0 -4
  104. package/dist/router.d.ts +1 -1
  105. package/dist/router.d.ts.map +1 -1
  106. package/dist/router.js +4 -4
  107. package/dist/server-router.d.ts +3 -3
  108. package/dist/server-router.d.ts.map +1 -1
  109. package/dist/server-router.js +2 -2
  110. package/dist/vite.d.ts +8 -3
  111. package/dist/vite.d.ts.map +1 -1
  112. package/dist/vite.js +72 -33
  113. package/package.json +6 -4
  114. package/dist/components/error-boundary-client.d.ts +0 -49
  115. package/dist/components/error-boundary-client.d.ts.map +0 -1
  116. package/dist/components/error-boundary-client.js +0 -71
  117. package/dist/components/error-boundary.browser.d.ts +0 -8
  118. package/dist/components/error-boundary.browser.d.ts.map +0 -1
  119. package/dist/components/error-boundary.browser.js +0 -6
  120. package/dist/components/error.d.ts +0 -2
  121. package/dist/components/error.d.ts.map +0 -1
  122. package/dist/components/error.js +0 -5
  123. package/dist/components/not-found-activator.d.ts +0 -11
  124. package/dist/components/not-found-activator.d.ts.map +0 -1
  125. package/dist/components/not-found-activator.js +0 -26
  126. package/dist/components/not-found-boundary-client.d.ts +0 -3
  127. package/dist/components/not-found-boundary-client.d.ts.map +0 -1
  128. package/dist/components/not-found-boundary-client.js +0 -20
  129. package/dist/components/not-found-boundary.browser.d.ts +0 -8
  130. package/dist/components/not-found-boundary.browser.d.ts.map +0 -1
  131. package/dist/components/not-found-boundary.browser.js +0 -4
  132. package/dist/components/not-found-boundary.d.ts +0 -8
  133. package/dist/components/not-found-boundary.d.ts.map +0 -1
  134. package/dist/components/not-found-boundary.js +0 -9
  135. package/dist/components/not-found-thrower.d.ts +0 -2
  136. package/dist/components/not-found-thrower.d.ts.map +0 -1
  137. package/dist/components/not-found-thrower.js +0 -7
  138. package/dist/components/not-found.d.ts +0 -2
  139. package/dist/components/not-found.d.ts.map +0 -1
  140. package/dist/components/not-found.js +0 -5
  141. package/dist/components/status-page.d.ts +0 -6
  142. package/dist/components/status-page.d.ts.map +0 -1
  143. package/dist/components/status-page.js +0 -61
  144. package/dist/handler.d.ts +0 -12
  145. package/dist/handler.d.ts.map +0 -1
  146. package/dist/handler.js +0 -21
  147. package/dist/handlers/rsc/constants.d.ts +0 -3
  148. package/dist/handlers/rsc/constants.d.ts.map +0 -1
  149. package/dist/handlers/rsc/constants.js +0 -2
  150. package/dist/handlers/rsc/create-response.d.ts +0 -3
  151. package/dist/handlers/rsc/create-response.d.ts.map +0 -1
  152. package/dist/handlers/rsc/create-response.js +0 -378
  153. package/dist/handlers/rsc/render-with-retries.d.ts +0 -4
  154. package/dist/handlers/rsc/render-with-retries.d.ts.map +0 -1
  155. package/dist/handlers/rsc/render-with-retries.js +0 -154
  156. package/dist/handlers/rsc/retry-loop.d.ts +0 -3
  157. package/dist/handlers/rsc/retry-loop.d.ts.map +0 -1
  158. package/dist/handlers/rsc/retry-loop.js +0 -145
  159. package/dist/handlers/rsc/stream-rsc-payload.d.ts +0 -9
  160. package/dist/handlers/rsc/stream-rsc-payload.d.ts.map +0 -1
  161. package/dist/handlers/rsc/stream-rsc-payload.js +0 -20
  162. package/dist/handlers/rsc/types.d.ts +0 -26
  163. package/dist/handlers/rsc/types.d.ts.map +0 -1
  164. package/dist/handlers/rsc/types.js +0 -7
  165. package/dist/handlers/rsc.d.ts +0 -20
  166. package/dist/handlers/rsc.d.ts.map +0 -1
  167. package/dist/handlers/rsc.js +0 -872
  168. package/dist/integration.d.ts +0 -14
  169. package/dist/integration.d.ts.map +0 -1
  170. package/dist/integration.js +0 -9
  171. package/dist/lib/dev-module-load-race.d.ts +0 -8
  172. package/dist/lib/dev-module-load-race.d.ts.map +0 -1
  173. package/dist/lib/dev-module-load-race.js +0 -31
  174. package/dist/lib/dev-page-exports.d.ts +0 -5
  175. package/dist/lib/dev-page-exports.d.ts.map +0 -1
  176. package/dist/lib/dev-page-exports.js +0 -14
  177. package/dist/lib/environment-names.d.ts +0 -11
  178. package/dist/lib/environment-names.d.ts.map +0 -1
  179. package/dist/lib/environment-names.js +0 -10
  180. package/dist/lib/initial-hash-scroll.d.ts.map +0 -1
  181. package/dist/lib/not-found.d.ts +0 -5
  182. package/dist/lib/not-found.d.ts.map +0 -1
  183. package/dist/lib/not-found.js +0 -7
  184. package/dist/lib/page-exports.d.ts +0 -9
  185. package/dist/lib/page-exports.d.ts.map +0 -1
  186. package/dist/lib/page-exports.js +0 -47
  187. package/dist/lib/pattern-segments.d.ts +0 -8
  188. package/dist/lib/pattern-segments.d.ts.map +0 -1
  189. package/dist/lib/pattern-segments.js +0 -22
  190. package/dist/lib/ppr/cache-status.d.ts +0 -3
  191. package/dist/lib/ppr/cache-status.d.ts.map +0 -1
  192. package/dist/lib/ppr/cache-status.js +0 -5
  193. package/dist/lib/server-router-contract.d.ts +0 -42
  194. package/dist/lib/server-router-contract.d.ts.map +0 -1
  195. package/dist/lib/server-router-contract.js +0 -6
  196. package/dist/lib/server-router-loader.d.ts +0 -10
  197. package/dist/lib/server-router-loader.d.ts.map +0 -1
  198. package/dist/lib/server-router-loader.js +0 -180
  199. package/dist/lib/server-router.d.ts +0 -8
  200. package/dist/lib/server-router.d.ts.map +0 -1
  201. package/dist/lib/server-router.js +0 -173
  202. package/dist/plugins/ppr-upgrade.d.ts +0 -36
  203. package/dist/plugins/ppr-upgrade.d.ts.map +0 -1
  204. package/dist/plugins/ppr-upgrade.js +0 -32
  205. package/dist/plugins/server-router-fallback.d.ts +0 -15
  206. package/dist/plugins/server-router-fallback.d.ts.map +0 -1
  207. package/dist/plugins/server-router-fallback.js +0 -30
  208. package/dist/server.d.ts +0 -10
  209. package/dist/server.d.ts.map +0 -1
  210. package/dist/server.js +0 -57
@@ -17,117 +17,67 @@ import { buildProxy } from "../proxy/build-proxy.js";
17
17
  import { proxyExternal } from "../proxy/proxy-external.js";
18
18
  import { REWRITE_HEADER, rewriteHeaders } from "../proxy/rewrite.js";
19
19
  import { assertNoPageRouteHandlerConflicts, buildLayoutRoutes, buildRouteHandlerRoutes, buildRoutes, } from "../route-builder.js";
20
- import { HTTP_METHODS, } from "../route-matcher.js";
21
- import { RouteType } from "./types.js";
22
- function buildEntries(pageRoutes, routeHandlerRoutes, layoutRoutes) {
23
- const appEntries = [];
24
- const layoutEntries = [];
25
- const markdownEntries = [];
26
- const hasMarkdownRoutes = pageRoutes.some((route) => route.markdownFilePath);
27
- // Image optimization route
28
- if (imageConfig !== null && loadImageHandler !== undefined) {
29
- const imageEntry = {
30
- type: RouteType.IMAGE,
31
- methods: ["GET"],
32
- pattern: imageConfig.path,
33
- handler: handleImageRequest,
34
- };
35
- appEntries.push(imageEntry);
36
- if (hasMarkdownRoutes)
37
- markdownEntries.push(imageEntry);
38
- }
39
- // Page routes — registered for GET and POST:
40
- // - GET: page loads, RSC requests, segment requests
41
- // - POST: server functions, form submissions, PPR resume
42
- for (const route of pageRoutes) {
43
- if (route.hasPage !== false) {
44
- appEntries.push({
45
- type: RouteType.APP,
46
- methods: ["GET", "POST"],
47
- route,
48
- handler: (req, params) => handlePageRoute(req, route, params),
49
- });
50
- }
51
- if (!hasMarkdownRoutes)
52
- continue;
53
- if (route.markdownFilePath) {
54
- markdownEntries.push({
55
- type: RouteType.APP,
56
- methods: ["GET", "HEAD"],
57
- route,
58
- handler: (req, params) => handleMarkdownRoute(req, route, params),
59
- });
60
- }
61
- else if (route.hasPage !== false) {
62
- // A specific page without Markdown still wins negotiation over a Markdown catch-all.
63
- markdownEntries.push({
64
- type: RouteType.APP,
65
- methods: ["GET"],
66
- route,
67
- handler: (req, params) => handlePageRoute(req, route, params),
68
- });
69
- }
70
- }
71
- // Route handlers — registered for all methods so they can return 405 when the path exists but a
72
- // specific method is not implemented.
73
- for (const route of routeHandlerRoutes) {
74
- const entry = {
75
- type: RouteType.APP,
76
- methods: [...HTTP_METHODS],
77
- route,
78
- handler: (req, params) => handleRouteHandler(req, route, params),
79
- };
80
- appEntries.push(entry);
81
- if (hasMarkdownRoutes)
82
- markdownEntries.push(entry);
83
- }
84
- // Layout routes — registered under /_rebask/1/{path}
85
- for (const route of layoutRoutes) {
86
- const segments = [
87
- { type: "static", value: "_rebask" },
88
- { type: "static", value: "1" },
89
- ...route.segments,
90
- ];
91
- layoutEntries.push({
92
- type: RouteType.APP,
93
- methods: ["GET"],
94
- route: { ...route, segments },
95
- handler: (req, params) => handleLayoutRouteRequest(req, route, params),
96
- });
97
- }
98
- return { appEntries, layoutEntries, markdownEntries };
99
- }
20
+ import { extractAppParams } from "./rou3.js";
21
+ import { buildRouteEntries } from "./route-entries.js";
100
22
  function createRouter(pageRoutes, routeHandlerRoutes, layoutRoutes, resolvedProxyRouter = proxyRouter) {
101
- const { appEntries, layoutEntries, markdownEntries } = buildEntries(pageRoutes, routeHandlerRoutes, layoutRoutes);
102
- const appMatcher = createMatcher(appEntries);
103
- const markdownMatcher = markdownEntries.length > 0 ? createMatcher(markdownEntries) : null;
104
- const layoutMatcher = layoutEntries.length > 0 ? createMatcher(layoutEntries) : null;
23
+ const imageEntry = imageConfig !== null && loadImageHandler !== undefined
24
+ ? { pattern: imageConfig.path, handler: handleImageRequest }
25
+ : null;
26
+ const { entries, markdownEnabled } = buildRouteEntries(pageRoutes, routeHandlerRoutes, layoutRoutes, imageEntry, {
27
+ page: (route) => (request, params) => handlePageRoute(request, route, params),
28
+ markdown: (route) => (request, params) => handleMarkdownRoute(request, route, params),
29
+ routeHandler: (route) => (request, params) => handleRouteHandler(request, route, params),
30
+ layout: (route) => (request, params) => handleLayoutRouteRequest(request, route, params),
31
+ });
32
+ const appMatcher = createMatcher(entries);
105
33
  const app = async (request) => {
106
34
  const method = request.method;
107
35
  const accept = request.headers.get("accept");
108
36
  const isRscRequest = accept?.startsWith("text/x-component");
109
- const isMarkdownMethod = method === "GET" || method === "HEAD";
110
- if (!isRscRequest && isMarkdownMethod && markdownMatcher) {
111
- const url = new URL(request.url);
112
- const markdownPathname = __REBASK_MARKDOWN_URLS ? getMarkdownPathname(url.pathname) : null;
113
- if (markdownPathname !== null) {
37
+ const isMarkdownRequest = markdownEnabled && !isRscRequest && (method === "GET" || method === "HEAD");
38
+ const url = new URL(request.url);
39
+ let markdownPathname = null;
40
+ if (isMarkdownRequest) {
41
+ markdownPathname = __REBASK_MARKDOWN_URLS ? getMarkdownPathname(url.pathname) : null;
42
+ if (markdownPathname !== null)
114
43
  url.pathname = markdownPathname;
115
- const markdownHandler = markdownMatcher.find(method, url.href);
116
- if (markdownHandler?.route?.type === "page" && markdownHandler.route.markdownFilePath) {
117
- return (await markdownHandler(request));
44
+ }
45
+ const match = appMatcher.find(method, url.href);
46
+ const matched = match?.params ?? {};
47
+ if (markdownPathname !== null) {
48
+ if (match?.entry.type === "app") {
49
+ const variant = match.entry.markdown;
50
+ if (variant?.route.type === "page" && variant.route.markdownFilePath) {
51
+ return variant.handler(request, extractAppParams(variant.params, matched));
118
52
  }
119
- return markdownNotFound(request);
120
- }
121
- if (prefersMarkdown(accept)) {
122
- const handler = markdownMatcher.find(method, request.url);
123
- return handler ? handler(request) : markdownNotFound(request);
124
53
  }
54
+ return markdownNotFound(request);
55
+ }
56
+ const wantsMarkdown = isMarkdownRequest && prefersMarkdown(accept);
57
+ if (!match) {
58
+ return wantsMarkdown
59
+ ? markdownNotFound(request)
60
+ : handlePageRoute(request, buildDefaultNotFoundRoute(), {});
61
+ }
62
+ const entry = match.entry;
63
+ if (wantsMarkdown && entry.type === "app") {
64
+ const variant = entry.markdown;
65
+ return variant
66
+ ? variant.handler(request, extractAppParams(variant.params, matched))
67
+ : markdownNotFound(request);
68
+ }
69
+ if (isRscRequest) {
70
+ const layout = entry.layout;
71
+ if (layout)
72
+ return layout.handler(request, extractAppParams(layout.params, matched));
73
+ }
74
+ if (entry.type === "app") {
75
+ const variant = entry.app;
76
+ return variant
77
+ ? variant.handler(request, extractAppParams(variant.params, matched))
78
+ : handlePageRoute(request, buildDefaultNotFoundRoute(), {});
125
79
  }
126
- const layoutHandler = isRscRequest
127
- ? layoutMatcher?.find(request.method, request.url)
128
- : undefined;
129
- const handler = layoutHandler ?? appMatcher.find(request.method, request.url);
130
- return handler ? handler(request) : handlePageRoute(request, buildDefaultNotFoundRoute(), {});
80
+ return entry.app(request, matched);
131
81
  };
132
82
  const mainRouter = { handle: app, app, proxy: async () => null };
133
83
  if (!resolvedProxyRouter)
@@ -140,10 +90,10 @@ function createRouter(pageRoutes, routeHandlerRoutes, layoutRoutes, resolvedProx
140
90
  const rewriteUrl = result.headers.get(REWRITE_HEADER);
141
91
  if (!rewriteUrl)
142
92
  return applyCookies(result);
143
- const rewrittenUrl = new URL(rewriteUrl, req.url);
144
- const reqOrigin = new URL(req.url).origin;
93
+ const reqUrl = new URL(req.url);
94
+ const rewrittenUrl = new URL(rewriteUrl, reqUrl);
145
95
  let response;
146
- if (rewrittenUrl.origin !== reqOrigin) {
96
+ if (rewrittenUrl.origin !== reqUrl.origin) {
147
97
  response = await proxyExternal(rewrittenUrl, req, result, stashed);
148
98
  }
149
99
  else {
@@ -0,0 +1,20 @@
1
+ import type { RouteParams, RouteSegment } from "../route-matcher.js";
2
+ export type EntryParams = {
3
+ pattern: string;
4
+ segments: RouteSegment[];
5
+ };
6
+ /**
7
+ * Converts filesystem route segments into a rou3 pattern. Static text is escaped, and dynamic
8
+ * segments use generated `pN` keys because filesystem names are not always valid rou3 param names
9
+ * (e.g `[foo-bar]`).
10
+ */
11
+ export declare function appPattern(segments: RouteSegment[], includeGroups: boolean): {
12
+ pattern: string;
13
+ segments: RouteSegment[];
14
+ };
15
+ /**
16
+ * Converts the raw params from an `appPattern` match into the route's original params, decoding
17
+ * dynamic values and splitting catch-all matches into decoded segment arrays.
18
+ */
19
+ export declare function extractAppParams(params: EntryParams, matched: Record<string, string>): RouteParams;
20
+ //# sourceMappingURL=rou3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rou3.d.ts","sourceRoot":"","sources":["../../../src/lib/server-router/rou3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAKpE,MAAM,MAAM,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAAA;AAEvE;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,aAAa,EAAE,OAAO;;;EAmB1E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,WAAW,CAsBb"}
@@ -0,0 +1,55 @@
1
+ const ROU3_SYNTAX = /[:*?+(){}]/g;
2
+ const escapeStatic = (value) => value.replace(ROU3_SYNTAX, "\\$&");
3
+ /**
4
+ * Converts filesystem route segments into a rou3 pattern. Static text is escaped, and dynamic
5
+ * segments use generated `pN` keys because filesystem names are not always valid rou3 param names
6
+ * (e.g `[foo-bar]`).
7
+ */
8
+ export function appPattern(segments, includeGroups) {
9
+ const parts = [];
10
+ let index = 0;
11
+ for (const segment of segments) {
12
+ if (segment.type === "static") {
13
+ parts.push(escapeStatic(segment.value));
14
+ }
15
+ else if (segment.type === "group") {
16
+ if (includeGroups)
17
+ parts.push(escapeStatic(segment.value));
18
+ }
19
+ else {
20
+ const name = `p${index++}`;
21
+ if (segment.type === "dynamic")
22
+ parts.push(`:${name}`);
23
+ else if (segment.type === "catch-all")
24
+ parts.push(`:${name}+`);
25
+ else
26
+ parts.push(`:${name}*`);
27
+ }
28
+ }
29
+ return { pattern: "/" + parts.join("/"), segments };
30
+ }
31
+ /**
32
+ * Converts the raw params from an `appPattern` match into the route's original params, decoding
33
+ * dynamic values and splitting catch-all matches into decoded segment arrays.
34
+ */
35
+ export function extractAppParams(params, matched) {
36
+ const result = {};
37
+ let index = 0;
38
+ for (const segment of params.segments) {
39
+ if (segment.type === "dynamic") {
40
+ result[segment.name] = decodeURIComponent(matched[`p${index++}`]);
41
+ }
42
+ else if (segment.type === "catch-all" || segment.type === "optional-catch-all") {
43
+ const value = matched[`p${index++}`];
44
+ const parts = [];
45
+ if (value) {
46
+ for (const part of value.split("/")) {
47
+ if (part)
48
+ parts.push(decodeURIComponent(part));
49
+ }
50
+ }
51
+ result[segment.name] = parts;
52
+ }
53
+ }
54
+ return result;
55
+ }
@@ -0,0 +1,16 @@
1
+ import { type LayoutRoute, type PageRoute, type RouteHandlerRoute } from "../route-matcher.js";
2
+ import type { AppEntry, AppHandler } from "./types.js";
3
+ export interface EntryHandlers {
4
+ page: (route: PageRoute) => AppHandler;
5
+ markdown: (route: PageRoute) => AppHandler;
6
+ routeHandler: (route: RouteHandlerRoute) => AppHandler;
7
+ layout: (route: LayoutRoute) => AppHandler;
8
+ }
9
+ export declare function buildRouteEntries(pageRoutes: PageRoute[], routeHandlerRoutes: RouteHandlerRoute[], layoutRoutes: LayoutRoute[], imageEntry: {
10
+ pattern: string;
11
+ handler: AppHandler;
12
+ } | null, handlers: EntryHandlers): {
13
+ entries: AppEntry[];
14
+ markdownEnabled: boolean;
15
+ };
16
+ //# sourceMappingURL=route-entries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-entries.d.ts","sourceRoot":"","sources":["../../../src/lib/server-router/route-entries.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,WAAW,EAChB,KAAK,SAAS,EAEd,KAAK,iBAAiB,EAEtB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEtD,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,UAAU,CAAA;IACtC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,UAAU,CAAA;IAC1C,YAAY,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,UAAU,CAAA;IACtD,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,UAAU,CAAA;CAC1C;AAED,wBAAgB,iBAAiB,CAChC,UAAU,EAAE,SAAS,EAAE,EACvB,kBAAkB,EAAE,iBAAiB,EAAE,EACvC,YAAY,EAAE,WAAW,EAAE,EAC3B,UAAU,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,EAC3D,QAAQ,EAAE,aAAa,GACrB;IAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CA2EnD"}
@@ -0,0 +1,67 @@
1
+ import { HTTP_METHODS, } from "../route-matcher.js";
2
+ import { appPattern } from "./rou3.js";
3
+ export function buildRouteEntries(pageRoutes, routeHandlerRoutes, layoutRoutes, imageEntry, handlers) {
4
+ const entries = new Map();
5
+ const hasMarkdownRoutes = pageRoutes.some((route) => route.markdownFilePath);
6
+ const entryKey = (pattern, method) => `${pattern}\n${method}`;
7
+ function ensureEntry(pattern, method) {
8
+ const key = entryKey(pattern, method);
9
+ let entry = entries.get(key);
10
+ if (!entry) {
11
+ entry = { type: "app", methods: [method], pattern };
12
+ entries.set(key, entry);
13
+ }
14
+ return entry;
15
+ }
16
+ function addApp(route, methods, handler, variant) {
17
+ const params = appPattern(route.segments, route.type === "layout");
18
+ const handlerEntry = { handler, route, params };
19
+ for (const method of methods) {
20
+ const entry = ensureEntry(params.pattern, method);
21
+ if (entry.type === "image") {
22
+ // An image route can collide with a layout route. RSC still gives layout precedence.
23
+ if (variant === "layout" && !entry.layout)
24
+ entry.layout = handlerEntry;
25
+ continue;
26
+ }
27
+ if (!entry[variant])
28
+ entry[variant] = handlerEntry;
29
+ }
30
+ }
31
+ if (imageEntry) {
32
+ entries.set(entryKey(imageEntry.pattern, "GET"), {
33
+ type: "image",
34
+ methods: ["GET", "HEAD"],
35
+ pattern: imageEntry.pattern,
36
+ app: imageEntry.handler,
37
+ });
38
+ }
39
+ for (const route of pageRoutes) {
40
+ if (route.hasPage !== false) {
41
+ addApp(route, ["GET", "POST"], handlers.page(route), "app");
42
+ }
43
+ if (!hasMarkdownRoutes)
44
+ continue;
45
+ if (route.markdownFilePath) {
46
+ addApp(route, ["GET", "HEAD"], handlers.markdown(route), "markdown");
47
+ }
48
+ else if (route.hasPage !== false) {
49
+ addApp(route, ["GET"], handlers.page(route), "markdown");
50
+ }
51
+ }
52
+ for (const route of routeHandlerRoutes) {
53
+ const handler = handlers.routeHandler(route);
54
+ addApp(route, HTTP_METHODS, handler, "app");
55
+ if (hasMarkdownRoutes)
56
+ addApp(route, HTTP_METHODS, handler, "markdown");
57
+ }
58
+ for (const route of layoutRoutes) {
59
+ const segments = [
60
+ { type: "static", value: "_rebask" },
61
+ { type: "static", value: "1" },
62
+ ...route.segments,
63
+ ];
64
+ addApp({ ...route, segments }, ["GET"], handlers.layout(route), "layout");
65
+ }
66
+ return { entries: [...entries.values()], markdownEnabled: hasMarkdownRoutes };
67
+ }
@@ -1,48 +1,39 @@
1
- import type { ProxyHandler } from "../proxy/types.js";
2
1
  import type { HttpMethod, LayoutRoute, Route, RouteHandlerRoute, RouteParams } from "../route-matcher.js";
3
- export declare enum RouteType {
4
- APP = 0,
5
- PROXY = 1,
6
- IMAGE = 2
7
- }
8
- type Handler = (request: Request, params: RouteParams) => Promise<Response>;
9
- type AppEntry<T> = {
10
- methods: HttpMethod[];
11
- type: RouteType.APP;
12
- route: T;
13
- handler: Handler;
2
+ import type { EntryParams } from "./rou3.js";
3
+ export type AppHandler = (request: Request, params: RouteParams) => Promise<Response>;
4
+ type AppHandlerVariant = {
5
+ handler: AppHandler;
6
+ route: Route | RouteHandlerRoute | LayoutRoute;
7
+ params: EntryParams;
14
8
  };
15
- type PageRouteEntry = AppEntry<Route>;
16
- type RouteHandlerEntry = AppEntry<RouteHandlerRoute>;
17
- type LayoutRSCEntry = AppEntry<LayoutRoute>;
18
- export type ProxyEntry = {
19
- type: RouteType.PROXY;
9
+ export type MatcherEntry = {
20
10
  methods: HttpMethod[];
21
11
  pattern: string;
22
- handler: ProxyHandler;
23
12
  };
24
- type ImageEntry = {
25
- type: RouteType.IMAGE;
26
- methods: HttpMethod[];
27
- pattern: string;
28
- handler: Handler;
13
+ type AppRouteEntry = MatcherEntry & {
14
+ type: "app";
15
+ app?: AppHandlerVariant;
16
+ markdown?: AppHandlerVariant;
17
+ layout?: AppHandlerVariant;
29
18
  };
30
- export type RouteEntry = PageRouteEntry | RouteHandlerEntry | LayoutRSCEntry | ProxyEntry | ImageEntry;
31
- type FindHandler<E extends RouteEntry> = ProxyEntry extends E ? (request: Request) => ReturnType<ProxyHandler> : (request: Request) => Promise<Response>;
32
- export type MatchedHandler<E extends RouteEntry = RouteEntry> = FindHandler<E> & {
33
- route?: Route | RouteHandlerRoute | LayoutRoute;
19
+ type ImageRouteEntry = MatcherEntry & {
20
+ type: "image";
21
+ app: AppHandler;
22
+ layout?: AppHandlerVariant;
34
23
  };
35
- /** A compiled route matcher that finds the best matching route for a given method + URL. */
36
- export interface RouteMatcher<E extends RouteEntry = RouteEntry> {
37
- find(method: string, url: string): MatchedHandler<E> | null;
24
+ export type AppEntry = AppRouteEntry | ImageRouteEntry;
25
+ /** A route matcher that finds the best matching route for a given method + URL. */
26
+ export interface RouteMatcher<T> {
27
+ find(method: string, url: string): {
28
+ entry: T;
29
+ params?: Record<string, string>;
30
+ } | null;
38
31
  }
39
32
  /**
40
33
  * A router plugin provides an implementation of this function via the
41
34
  * `virtual:rebask/server-router` virtual module.
42
- *
43
- * Matched handlers must receive decoded params, splitting catch-all components before decoding.
44
35
  */
45
- export type CreateMatcherFn = <E extends RouteEntry>(entries: E[]) => RouteMatcher<E>;
36
+ export type CreateMatcherFn = <T extends MatcherEntry>(entries: T[]) => RouteMatcher<T>;
46
37
  export interface RebaskRouter {
47
38
  /** Handles a request through the full router: proxy routes first, then app routes. */
48
39
  handle: (request: Request) => Promise<Response>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/server-router/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EACX,UAAU,EACV,WAAW,EACX,KAAK,EACL,iBAAiB,EACjB,WAAW,EACX,MAAM,qBAAqB,CAAA;AAE5B,oBAAY,SAAS;IACpB,GAAG,IAAA;IACH,KAAK,IAAA;IACL,KAAK,IAAA;CACL;AAED,KAAK,OAAO,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE3E,KAAK,QAAQ,CAAC,CAAC,IAAI;IAClB,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,IAAI,EAAE,SAAS,CAAC,GAAG,CAAA;IACnB,KAAK,EAAE,CAAC,CAAA;IACR,OAAO,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,KAAK,cAAc,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;AACrC,KAAK,iBAAiB,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAA;AACpD,KAAK,cAAc,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAA;AAE3C,MAAM,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,SAAS,CAAC,KAAK,CAAA;IACrB,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,YAAY,CAAA;CACrB,CAAA;AAED,KAAK,UAAU,GAAG;IACjB,IAAI,EAAE,SAAS,CAAC,KAAK,CAAA;IACrB,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,UAAU,GACnB,cAAc,GACd,iBAAiB,GACjB,cAAc,GACd,UAAU,GACV,UAAU,CAAA;AAEb,KAAK,WAAW,CAAC,CAAC,SAAS,UAAU,IAAI,UAAU,SAAS,CAAC,GAC1D,CAAC,OAAO,EAAE,OAAO,KAAK,UAAU,CAAC,YAAY,CAAC,GAC9C,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE1C,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IAChF,KAAK,CAAC,EAAE,KAAK,GAAG,iBAAiB,GAAG,WAAW,CAAA;CAC/C,CAAA;AAED,4FAA4F;AAC5F,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU;IAC9D,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;CAC3D;AAED;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,CAAA;AAErF,MAAM,WAAW,YAAY;IAC5B,sFAAsF;IACtF,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC/C,uEAAuE;IACvE,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC5C,qFAAqF;IACrF,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;CACrD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/server-router/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,WAAW,EACX,KAAK,EACL,iBAAiB,EACjB,WAAW,EACX,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAErF,KAAK,iBAAiB,GAAG;IACxB,OAAO,EAAE,UAAU,CAAA;IACnB,KAAK,EAAE,KAAK,GAAG,iBAAiB,GAAG,WAAW,CAAA;IAC9C,MAAM,EAAE,WAAW,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CACf,CAAA;AAED,KAAK,aAAa,GAAG,YAAY,GAAG;IACnC,IAAI,EAAE,KAAK,CAAA;IACX,GAAG,CAAC,EAAE,iBAAiB,CAAA;IACvB,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAC1B,CAAA;AAED,KAAK,eAAe,GAAG,YAAY,GAAG;IACrC,IAAI,EAAE,OAAO,CAAA;IACb,GAAG,EAAE,UAAU,CAAA;IACf,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,aAAa,GAAG,eAAe,CAAA;AAEtD,mFAAmF;AACnF,MAAM,WAAW,YAAY,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI,CAAA;CACvF;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,SAAS,YAAY,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC,CAAC,CAAA;AAEvF,MAAM,WAAW,YAAY;IAC5B,sFAAsF;IACtF,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC/C,uEAAuE;IACvE,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC5C,qFAAqF;IACrF,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;CACrD"}
@@ -1,6 +1 @@
1
- export var RouteType;
2
- (function (RouteType) {
3
- RouteType[RouteType["APP"] = 0] = "APP";
4
- RouteType[RouteType["PROXY"] = 1] = "PROXY";
5
- RouteType[RouteType["IMAGE"] = 2] = "IMAGE";
6
- })(RouteType || (RouteType = {}));
1
+ export {};
@@ -48,8 +48,8 @@ export type SegmentRscPayload = PageRscPayload | LayoutRscPayload;
48
48
  export type RouteRscPayload = PageRscPayload & {
49
49
  /** Form state in case of a document form submission. */
50
50
  formState?: ReactFormState;
51
- /** Proxy route patterns, read once at bootstrap to gate route prediction. */
52
- proxyPatterns?: string[];
51
+ /** Regex sources the browser tests to skip route prediction for paths a proxy may answer. */
52
+ proxyRegexps?: string[];
53
53
  /**
54
54
  * Set when this document is the built-in error route rendered after a failed shell. The
55
55
  * browser hydrates it as-is and then refreshes the URL to render the real route content.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAElE,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,iDAAiD;IACjD,eAAe,CAAC,EAAE,qBAAqB,CAAA;CACvC;AAED,MAAM,WAAW,qBAAqB;IACrC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAA;IAChC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,kDAAkD;AAClD,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,EAAE,eAAe,CAAC,CAAA;AAEnF,MAAM,MAAM,cAAc,GAAG;IAC5B,QAAQ,EAAE,cAAc,CAAA;IACxB,eAAe,CAAC,EAAE,eAAe,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,EAAE,cAAc,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,gBAAgB,CAAA;AAEjE,6DAA6D;AAC7D,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG;IAC9C,wDAAwD;IACxD,SAAS,CAAC,EAAE,cAAc,CAAA;IAC1B,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAEzD,MAAM,MAAM,gBAAgB,GACzB;IAAE,WAAW,EAAE,YAAY,CAAC;IAAC,SAAS,CAAC,EAAE,KAAK,CAAA;CAAE,GAChD;IAAE,WAAW,CAAC,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,CAAA;AAErD,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAElE,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,iDAAiD;IACjD,eAAe,CAAC,EAAE,qBAAqB,CAAA;CACvC;AAED,MAAM,WAAW,qBAAqB;IACrC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IACzB;;;;;;OAMG;IACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAA;IAChC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,kDAAkD;AAClD,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,EAAE,eAAe,CAAC,CAAA;AAEnF,MAAM,MAAM,cAAc,GAAG;IAC5B,QAAQ,EAAE,cAAc,CAAA;IACxB,eAAe,CAAC,EAAE,eAAe,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,EAAE,cAAc,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,gBAAgB,CAAA;AAEjE,6DAA6D;AAC7D,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG;IAC9C,wDAAwD;IACxD,SAAS,CAAC,EAAE,cAAc,CAAA;IAC1B,6FAA6F;IAC7F,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAEzD,MAAM,MAAM,gBAAgB,GACzB;IAAE,WAAW,EAAE,YAAY,CAAC;IAAC,SAAS,CAAC,EAAE,KAAK,CAAA;CAAE,GAChD;IAAE,WAAW,CAAC,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,cAAc,CAAA;CAAE,CAAA;AAErD,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,CAAA"}
@@ -4,10 +4,7 @@ import { type HasDynamicIO } from "../lib/route-prediction.js";
4
4
  import type { RebaskPluginApi } from "../vite.js";
5
5
  type CacheControl = NonNullable<BuildPrerenderMeta["cacheLife"]>;
6
6
  type PrerenderManifestPaths = {
7
- /**
8
- * Concrete pathnames of a file with `allowExtraParams: false`. The field's presence is the
9
- * static-only signal.
10
- */
7
+ /** Concrete pathnames of a file with `allowExtraParams = false`, used for static-only 404s. */
11
8
  static?: string[];
12
9
  /** Ordered `predictPaths` pathnames with their request-IO bits. */
13
10
  predict?: Array<[pathname: string, hasDynamicIO: HasDynamicIO]>;
@@ -41,5 +38,7 @@ interface PrerenderPluginOptions {
41
38
  failOnDynamic?: boolean;
42
39
  }
43
40
  export declare function prerenderPlugin(api: RebaskPluginApi, options?: PrerenderPluginOptions): Plugin;
41
+ /** Collects the route metadata needed at runtime when prerendering is disabled. */
42
+ export declare function routeMetadataPlugin(api: RebaskPluginApi): Plugin;
44
43
  export {};
45
44
  //# sourceMappingURL=prerender.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/plugins/prerender.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAQlC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AASlE,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAOjD,KAAK,YAAY,GAAG,WAAW,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAA;AAEhE,KAAK,sBAAsB,GAAG;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAA;IAC/D,2DAA2D;IAC3D,EAAE,CAAC,EAAE,MAAM,EAAE,CAAA;CACb,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;IAC9C,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IAClG;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC,CAAA;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CAChD,CAAA;AA2CD,UAAU,sBAAsB;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,eAAe,CAC9B,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,sBAA2B,GAClC,MAAM,CA2ZR"}
1
+ {"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/plugins/prerender.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAQlC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AASlE,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACtF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAOjD,KAAK,YAAY,GAAG,WAAW,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAA;AAEhE,KAAK,sBAAsB,GAAG;IAC7B,+FAA+F;IAC/F,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAA;IAC/D,2DAA2D;IAC3D,EAAE,CAAC,EAAE,MAAM,EAAE,CAAA;CACb,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAA;IAC9C,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IAClG;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC,CAAA;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CAChD,CAAA;AA2CD,UAAU,sBAAsB;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,eAAe,CAC9B,GAAG,EAAE,eAAe,EACpB,OAAO,GAAE,sBAA2B,GAClC,MAAM,CA4ZR;AAED,mFAAmF;AACnF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAoChE"}
@@ -70,6 +70,9 @@ export function prerenderPlugin(api, options = {}) {
70
70
  const resolvedParams = paramsResult && paramsResult.params.length > 0 ? paramsResult.params : null;
71
71
  const allowExtraParams = isDynamic ? (paramsResult?.allowExtraParams ?? true) : true;
72
72
  const { filePath, shellParams } = route;
73
+ if (allowExtraParams === false) {
74
+ staticRoutePaths[filePath] ??= [];
75
+ }
73
76
  if (allowExtraParams !== false &&
74
77
  typeof paramsResult?.predictPaths === "number" &&
75
78
  paramsResult.predictPaths > 0) {
@@ -358,3 +361,31 @@ export function prerenderPlugin(api, options = {}) {
358
361
  },
359
362
  };
360
363
  }
364
+ /** Collects the route metadata needed at runtime when prerendering is disabled. */
365
+ export function routeMetadataPlugin(api) {
366
+ return {
367
+ name: "rebask:route-metadata",
368
+ buildApp: {
369
+ async handler() {
370
+ const pageRoutes = api
371
+ .getRoutes()
372
+ .filter((route) => route.type === "page");
373
+ const entryModule = (await import(`file://${api.getRscEntry()}`));
374
+ const paths = {};
375
+ await Promise.all(pageRoutes.map(async (route) => {
376
+ if (!route.segments.some(isDynamicSegment))
377
+ return;
378
+ const result = await entryModule.getPrerenderParams(route);
379
+ if (result?.allowExtraParams !== false)
380
+ return;
381
+ paths[route.filePath] = {
382
+ static: result.params.map((params) => getRouteParamsPathname(route, params)),
383
+ };
384
+ }));
385
+ const dir = join(process.cwd(), "dist", ".rebask");
386
+ await mkdir(dir, { recursive: true });
387
+ await writeFile(join(dir, "prerendered-paths.json"), JSON.stringify({ noShellRoutes: [], paths }));
388
+ },
389
+ },
390
+ };
391
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/plugins/proxy.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAIX,MAAM,EAEN,MAAM,MAAM,CAAA;AAQb,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,qCAAqC;AACrC,eAAO,MAAM,wBAAwB,iBAAiB,CAAA;AAEtD,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,kGAAkG;IAClG,WAAW,EAAE,MAAM,MAAM,EAAE,GAAG,IAAI,CAAA;CAClC;AAyDD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CA8J5D"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/plugins/proxy.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAIX,MAAM,EAEN,MAAM,MAAM,CAAA;AAQb,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,qCAAqC;AACrC,eAAO,MAAM,wBAAwB,iBAAiB,CAAA;AAEtD,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,kGAAkG;IAClG,WAAW,EAAE,MAAM,MAAM,EAAE,GAAG,IAAI,CAAA;CAClC;AAyDD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAoK5D"}
@@ -60,6 +60,7 @@ export function proxyPlugin(coreApi) {
60
60
  let takenOver = false;
61
61
  let projectRoot = process.cwd();
62
62
  let takenOverPatterns = null;
63
+ let takenOverRegexps = null;
63
64
  const api = {
64
65
  takeover() {
65
66
  takenOver = true;
@@ -145,6 +146,7 @@ export function proxyPlugin(coreApi) {
145
146
  return;
146
147
  const bundle = (await import(pathToFileURL(join(projectRoot, REBASK_PROXY_BUNDLE_PATH)).href));
147
148
  takenOverPatterns = bundle.proxyPatterns;
149
+ takenOverRegexps = bundle.proxyRegexps;
148
150
  },
149
151
  },
150
152
  async hotUpdate({ file, server }) {
@@ -171,14 +173,18 @@ export function proxyPlugin(coreApi) {
171
173
  // proxy file, both are `null`.
172
174
  if (!resolvedProxyPath || (takenOver && this.environment?.name !== "proxy")) {
173
175
  const patterns = resolvedProxyPath ? JSON.stringify(takenOverPatterns) : "null";
174
- return `export const proxyPatterns = ${patterns};\nexport const proxyRouter = null;`;
176
+ const regexps = resolvedProxyPath ? JSON.stringify(takenOverRegexps) : "null";
177
+ return `export const proxyPatterns = ${patterns};\nexport const proxyRegexps = ${regexps};\nexport const proxyRouter = null;`;
175
178
  }
176
179
  const buildProxyPath = new URL("../lib/proxy/build-proxy.js", import.meta.url).pathname;
180
+ const patternPath = new URL("../lib/proxy/pattern.js", import.meta.url).pathname;
177
181
  return [
178
182
  `import proxy from ${JSON.stringify(resolvedProxyPath)};`,
179
183
  `import { buildProxy } from ${JSON.stringify(buildProxyPath)};`,
184
+ `import { proxyPatternToClientSource } from ${JSON.stringify(patternPath)};`,
180
185
  `const routes = proxy.default || proxy;`,
181
186
  `export const proxyPatterns = Object.keys(routes);`,
187
+ `export const proxyRegexps = proxyPatterns.map(proxyPatternToClientSource);`,
182
188
  `export const proxyRouter = buildProxy(routes);`,
183
189
  ].join("\n");
184
190
  },
@@ -0,0 +1,9 @@
1
+ import type { MatcherEntry, RouteMatcher } from "../../lib/server-router/types.js";
2
+ /** A compiled `find` function returning an index into the matcher entries. */
3
+ export type CompiledFind = (method: string, path: string) => {
4
+ data: number;
5
+ params?: Record<string, string>;
6
+ } | undefined;
7
+ /** Wraps a compiled `find` function and resolves its entry indexes. */
8
+ export declare function createCompiledMatcher<T extends MatcherEntry>(find: CompiledFind, entries: T[]): RouteMatcher<T>;
9
+ //# sourceMappingURL=rou3-compiled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rou3-compiled.d.ts","sourceRoot":"","sources":["../../../src/plugins/router/rou3-compiled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAElF,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GAAG,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,KACR;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,SAAS,CAAA;AAElE,uEAAuE;AACvE,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,YAAY,EAC3D,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,CAAC,EAAE,GACV,YAAY,CAAC,CAAC,CAAC,CAYjB"}
@@ -0,0 +1,14 @@
1
+ /** Wraps a compiled `find` function and resolves its entry indexes. */
2
+ export function createCompiledMatcher(find, entries) {
3
+ return {
4
+ find(method, url) {
5
+ const match = find(method, new URL(url, "http://localhost").pathname);
6
+ if (!match)
7
+ return null;
8
+ const entry = entries[match.data];
9
+ if (!entry)
10
+ return null;
11
+ return { entry, params: match.params };
12
+ },
13
+ };
14
+ }
@@ -0,0 +1,3 @@
1
+ import type { MatcherEntry, RouteMatcher } from "../../lib/server-router/types.js";
2
+ export declare function createMatcher<T extends MatcherEntry>(entries: T[]): RouteMatcher<T>;
3
+ //# sourceMappingURL=rou3-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rou3-router.d.ts","sourceRoot":"","sources":["../../../src/plugins/router/rou3-router.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAElF,wBAAgB,aAAa,CAAC,CAAC,SAAS,YAAY,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAgBnF"}