@rangojs/router 0.0.0-experimental.1b930379 → 0.0.0-experimental.1fa245e2
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/AGENTS.md +4 -0
- package/README.md +76 -18
- package/dist/bin/rango.js +138 -50
- package/dist/vite/index.js +558 -319
- package/package.json +16 -15
- package/skills/cache-guide/SKILL.md +32 -0
- package/skills/caching/SKILL.md +45 -4
- package/skills/links/SKILL.md +3 -1
- package/skills/loader/SKILL.md +53 -43
- package/skills/middleware/SKILL.md +2 -0
- package/skills/parallel/SKILL.md +126 -0
- package/skills/prerender/SKILL.md +110 -68
- package/skills/route/SKILL.md +31 -0
- package/skills/router-setup/SKILL.md +87 -2
- package/skills/typesafety/SKILL.md +10 -0
- package/src/__internal.ts +1 -1
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +5 -0
- package/src/browser/navigation-bridge.ts +19 -13
- package/src/browser/navigation-client.ts +115 -58
- package/src/browser/navigation-store.ts +43 -8
- package/src/browser/navigation-transaction.ts +11 -9
- package/src/browser/partial-update.ts +80 -15
- package/src/browser/prefetch/cache.ts +57 -5
- package/src/browser/prefetch/fetch.ts +38 -23
- package/src/browser/prefetch/queue.ts +92 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/react/Link.tsx +53 -9
- package/src/browser/react/NavigationProvider.tsx +40 -4
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/use-handle.ts +9 -58
- package/src/browser/react/use-router.ts +21 -8
- package/src/browser/rsc-router.tsx +134 -59
- package/src/browser/scroll-restoration.ts +41 -42
- package/src/browser/segment-reconciler.ts +6 -1
- package/src/browser/server-action-bridge.ts +8 -6
- package/src/browser/types.ts +36 -5
- package/src/build/generate-manifest.ts +6 -6
- package/src/build/generate-route-types.ts +3 -0
- package/src/build/route-types/include-resolution.ts +8 -1
- package/src/build/route-types/router-processing.ts +223 -74
- package/src/build/route-types/scan-filter.ts +8 -1
- package/src/cache/cache-runtime.ts +15 -11
- package/src/cache/cache-scope.ts +48 -7
- package/src/cache/cf/cf-cache-store.ts +453 -11
- package/src/cache/cf/index.ts +5 -1
- package/src/cache/document-cache.ts +17 -7
- package/src/cache/index.ts +1 -0
- package/src/cache/taint.ts +55 -0
- package/src/client.tsx +2 -56
- package/src/context-var.ts +72 -2
- package/src/debug.ts +2 -2
- package/src/handle.ts +40 -0
- package/src/index.rsc.ts +3 -1
- package/src/index.ts +8 -0
- package/src/prerender/store.ts +5 -4
- package/src/prerender.ts +138 -77
- package/src/reverse.ts +22 -1
- package/src/route-definition/dsl-helpers.ts +73 -25
- package/src/route-definition/helpers-types.ts +10 -6
- package/src/route-definition/index.ts +3 -0
- package/src/route-definition/redirect.ts +11 -3
- package/src/route-definition/resolve-handler-use.ts +149 -0
- package/src/route-map-builder.ts +7 -1
- package/src/route-types.ts +11 -0
- package/src/router/content-negotiation.ts +100 -1
- package/src/router/find-match.ts +4 -2
- package/src/router/handler-context.ts +79 -23
- package/src/router/intercept-resolution.ts +11 -4
- package/src/router/lazy-includes.ts +4 -1
- package/src/router/loader-resolution.ts +122 -10
- package/src/router/logging.ts +5 -2
- package/src/router/manifest.ts +9 -3
- package/src/router/match-api.ts +124 -189
- package/src/router/match-middleware/background-revalidation.ts +30 -2
- package/src/router/match-middleware/cache-lookup.ts +88 -16
- package/src/router/match-middleware/cache-store.ts +53 -10
- package/src/router/match-middleware/intercept-resolution.ts +9 -7
- package/src/router/match-middleware/segment-resolution.ts +61 -5
- package/src/router/match-result.ts +22 -6
- package/src/router/metrics.ts +6 -1
- package/src/router/middleware-types.ts +6 -8
- package/src/router/middleware.ts +4 -6
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/prerender-match.ts +110 -10
- package/src/router/preview-match.ts +30 -102
- package/src/router/request-classification.ts +310 -0
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +6 -1
- package/src/router/router-interfaces.ts +36 -4
- package/src/router/router-options.ts +37 -11
- package/src/router/segment-resolution/fresh.ts +183 -20
- package/src/router/segment-resolution/helpers.ts +29 -24
- package/src/router/segment-resolution/loader-cache.ts +1 -0
- package/src/router/segment-resolution/revalidation.ts +412 -297
- package/src/router/segment-wrappers.ts +2 -0
- package/src/router/types.ts +1 -0
- package/src/router.ts +59 -6
- package/src/rsc/handler.ts +460 -368
- package/src/rsc/manifest-init.ts +5 -1
- package/src/rsc/progressive-enhancement.ts +4 -0
- package/src/rsc/rsc-rendering.ts +5 -0
- package/src/rsc/server-action.ts +2 -0
- package/src/rsc/ssr-setup.ts +2 -2
- package/src/rsc/types.ts +8 -1
- package/src/segment-system.tsx +140 -4
- package/src/server/context.ts +140 -14
- package/src/server/loader-registry.ts +9 -8
- package/src/server/request-context.ts +144 -18
- package/src/ssr/index.tsx +4 -0
- package/src/static-handler.ts +18 -6
- package/src/types/cache-types.ts +4 -4
- package/src/types/handler-context.ts +137 -33
- package/src/types/loader-types.ts +36 -9
- package/src/types/route-entry.ts +8 -1
- package/src/types/segments.ts +2 -0
- package/src/urls/path-helper-types.ts +9 -2
- package/src/urls/path-helper.ts +48 -13
- package/src/urls/pattern-types.ts +12 -0
- package/src/urls/response-types.ts +16 -6
- package/src/use-loader.tsx +73 -4
- package/src/vite/discovery/bundle-postprocess.ts +30 -33
- package/src/vite/discovery/discover-routers.ts +5 -1
- package/src/vite/discovery/prerender-collection.ts +14 -1
- package/src/vite/discovery/state.ts +13 -6
- package/src/vite/index.ts +4 -0
- package/src/vite/plugin-types.ts +51 -79
- package/src/vite/plugins/expose-action-id.ts +1 -3
- package/src/vite/plugins/performance-tracks.ts +88 -0
- package/src/vite/plugins/refresh-cmd.ts +88 -26
- package/src/vite/plugins/version-plugin.ts +13 -1
- package/src/vite/rango.ts +163 -211
- package/src/vite/router-discovery.ts +153 -42
- package/src/vite/utils/banner.ts +3 -3
- package/src/vite/utils/prerender-utils.ts +18 -0
- package/src/vite/utils/shared-utils.ts +3 -2
|
@@ -10,11 +10,12 @@ import type { Plugin } from "vite";
|
|
|
10
10
|
import { createServer as createViteServer } from "vite";
|
|
11
11
|
import { resolve } from "node:path";
|
|
12
12
|
import { readFileSync } from "node:fs";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
import { pathToFileURL } from "node:url";
|
|
13
15
|
import {
|
|
14
16
|
formatNestedRouterConflictError,
|
|
15
17
|
findNestedRouterConflict,
|
|
16
18
|
findRouterFiles,
|
|
17
|
-
createScanFilter,
|
|
18
19
|
} from "../build/generate-route-types.js";
|
|
19
20
|
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
20
21
|
import { createVirtualStubPlugin } from "./plugins/virtual-stub-plugin.js";
|
|
@@ -95,6 +96,105 @@ async function createTempRscServer(
|
|
|
95
96
|
});
|
|
96
97
|
}
|
|
97
98
|
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Build-Time Env Resolution
|
|
101
|
+
// ============================================================================
|
|
102
|
+
|
|
103
|
+
import type {
|
|
104
|
+
BuildEnvOption,
|
|
105
|
+
BuildEnvFactoryContext,
|
|
106
|
+
BuildEnvResult,
|
|
107
|
+
} from "./plugin-types.js";
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Resolve the buildEnv option into a concrete { env, dispose? } result.
|
|
111
|
+
* Handles all four input shapes: false, "auto", factory, plain object.
|
|
112
|
+
*/
|
|
113
|
+
async function resolveBuildEnv(
|
|
114
|
+
option: BuildEnvOption | undefined,
|
|
115
|
+
factoryCtx: BuildEnvFactoryContext,
|
|
116
|
+
): Promise<BuildEnvResult | null> {
|
|
117
|
+
if (!option) return null;
|
|
118
|
+
|
|
119
|
+
if (option === "auto") {
|
|
120
|
+
if (factoryCtx.preset !== "cloudflare") {
|
|
121
|
+
throw new Error(
|
|
122
|
+
'[rsc-router] buildEnv: "auto" is only supported with preset: "cloudflare". ' +
|
|
123
|
+
"Use a factory function or plain object for other presets.",
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
// Resolve wrangler from the user's project root (not the router package)
|
|
128
|
+
const userRequire = createRequire(
|
|
129
|
+
resolve(factoryCtx.root, "package.json"),
|
|
130
|
+
);
|
|
131
|
+
const wranglerPath = userRequire.resolve("wrangler");
|
|
132
|
+
const { getPlatformProxy } = (await import(
|
|
133
|
+
pathToFileURL(wranglerPath).href
|
|
134
|
+
)) as {
|
|
135
|
+
getPlatformProxy: (opts?: any) => Promise<any>;
|
|
136
|
+
};
|
|
137
|
+
const proxy = await getPlatformProxy();
|
|
138
|
+
return {
|
|
139
|
+
env: proxy.env as Record<string, unknown>,
|
|
140
|
+
dispose: proxy.dispose,
|
|
141
|
+
};
|
|
142
|
+
} catch (err: any) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
'[rsc-router] buildEnv: "auto" requires wrangler to be installed.\n' +
|
|
145
|
+
`Install it with: pnpm add -D wrangler\n${err.message}`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (typeof option === "function") {
|
|
151
|
+
return await option(factoryCtx);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Plain object
|
|
155
|
+
return { env: option };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Acquire build-time env bindings and store on discovery state.
|
|
160
|
+
* Returns true if env was acquired, false if buildEnv is disabled.
|
|
161
|
+
*/
|
|
162
|
+
async function acquireBuildEnv(
|
|
163
|
+
s: DiscoveryState,
|
|
164
|
+
command: "serve" | "build",
|
|
165
|
+
mode: string,
|
|
166
|
+
): Promise<boolean> {
|
|
167
|
+
const option = s.opts?.buildEnv;
|
|
168
|
+
if (!option) return false;
|
|
169
|
+
|
|
170
|
+
const result = await resolveBuildEnv(option, {
|
|
171
|
+
root: s.projectRoot,
|
|
172
|
+
mode,
|
|
173
|
+
command,
|
|
174
|
+
preset: s.opts?.preset ?? "node",
|
|
175
|
+
});
|
|
176
|
+
if (!result) return false;
|
|
177
|
+
|
|
178
|
+
s.resolvedBuildEnv = result.env;
|
|
179
|
+
s.buildEnvDispose = result.dispose ?? null;
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Release build-time env resources and clear state.
|
|
185
|
+
*/
|
|
186
|
+
async function releaseBuildEnv(s: DiscoveryState): Promise<void> {
|
|
187
|
+
if (s.buildEnvDispose) {
|
|
188
|
+
try {
|
|
189
|
+
await s.buildEnvDispose();
|
|
190
|
+
} catch (err: any) {
|
|
191
|
+
console.warn(`[rsc-router] buildEnv dispose failed: ${err.message}`);
|
|
192
|
+
}
|
|
193
|
+
s.buildEnvDispose = null;
|
|
194
|
+
}
|
|
195
|
+
s.resolvedBuildEnv = undefined;
|
|
196
|
+
}
|
|
197
|
+
|
|
98
198
|
/**
|
|
99
199
|
* Plugin that discovers router instances at dev/build time via the RSC environment.
|
|
100
200
|
*
|
|
@@ -112,6 +212,8 @@ export function createRouterDiscoveryPlugin(
|
|
|
112
212
|
opts?: PluginOptions,
|
|
113
213
|
): Plugin {
|
|
114
214
|
const s = createDiscoveryState(entryPath, opts);
|
|
215
|
+
let viteCommand: "serve" | "build" = "build";
|
|
216
|
+
let viteMode = "production";
|
|
115
217
|
|
|
116
218
|
return {
|
|
117
219
|
name: "@rangojs/router:discovery",
|
|
@@ -122,32 +224,20 @@ export function createRouterDiscoveryPlugin(
|
|
|
122
224
|
__RANGO_DEBUG__: JSON.stringify(!!process.env.INTERNAL_RANGO_DEBUG),
|
|
123
225
|
},
|
|
124
226
|
};
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
manualChunks(id: string) {
|
|
132
|
-
if (s.resolvedPrerenderModules?.has(id)) {
|
|
133
|
-
return "__prerender-handlers";
|
|
134
|
-
}
|
|
135
|
-
if (s.resolvedStaticModules?.has(id)) {
|
|
136
|
-
return "__static-handlers";
|
|
137
|
-
}
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
}
|
|
227
|
+
// Prerender/static handler modules are bundled naturally with the
|
|
228
|
+
// rest of the RSC entry. A previous design forced them into dedicated
|
|
229
|
+
// __prerender-handlers / __static-handlers chunks via manualChunks,
|
|
230
|
+
// but Rollup hoisted all shared dependencies into those chunks,
|
|
231
|
+
// inflating them to ~1 MB with active runtime code. Handler code is
|
|
232
|
+
// evicted in closeBundle regardless of which chunk it lands in.
|
|
145
233
|
return config;
|
|
146
234
|
},
|
|
147
235
|
|
|
148
236
|
configResolved(config) {
|
|
149
237
|
s.projectRoot = config.root;
|
|
150
238
|
s.isBuildMode = config.command === "build";
|
|
239
|
+
viteCommand = config.command as "serve" | "build";
|
|
240
|
+
viteMode = config.mode;
|
|
151
241
|
// Capture user's resolve aliases for the temp server
|
|
152
242
|
s.userResolveAlias = config.resolve.alias;
|
|
153
243
|
// Node preset: pick up auto-discovered router path from the config() hook.
|
|
@@ -168,13 +258,6 @@ export function createRouterDiscoveryPlugin(
|
|
|
168
258
|
s.resolvedEntryPath = entries[0];
|
|
169
259
|
}
|
|
170
260
|
}
|
|
171
|
-
// Compile include/exclude patterns into a scan filter
|
|
172
|
-
if (opts?.include || opts?.exclude) {
|
|
173
|
-
s.scanFilter = createScanFilter(s.projectRoot, {
|
|
174
|
-
include: opts.include,
|
|
175
|
-
exclude: opts.exclude,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
261
|
// Generate combined named-routes.gen.ts from static source parsing.
|
|
179
262
|
// Runs before the dev server starts so the gen file exists immediately for IDE.
|
|
180
263
|
// In build mode, the runtime discovery in buildStart produces the definitive
|
|
@@ -225,12 +308,13 @@ export function createRouterDiscoveryPlugin(
|
|
|
225
308
|
let prerenderTempServer: any = null;
|
|
226
309
|
let prerenderNodeRegistry: Map<string, any> | null = null;
|
|
227
310
|
|
|
228
|
-
// Clean up the temporary server when the dev server shuts down
|
|
311
|
+
// Clean up the temporary server and build env when the dev server shuts down
|
|
229
312
|
server.httpServer?.on("close", () => {
|
|
230
313
|
if (prerenderTempServer) {
|
|
231
314
|
prerenderTempServer.close().catch(() => {});
|
|
232
315
|
prerenderTempServer = null;
|
|
233
316
|
}
|
|
317
|
+
releaseBuildEnv(s).catch(() => {});
|
|
234
318
|
});
|
|
235
319
|
|
|
236
320
|
async function getOrCreateTempServer(): Promise<any | null> {
|
|
@@ -270,6 +354,9 @@ export function createRouterDiscoveryPlugin(
|
|
|
270
354
|
// Create a temp Node.js server to run runtime discovery and generate
|
|
271
355
|
// named route types (static parser can't resolve factory calls).
|
|
272
356
|
try {
|
|
357
|
+
// Acquire build-time env bindings for dev prerender
|
|
358
|
+
await acquireBuildEnv(s, viteCommand, viteMode);
|
|
359
|
+
|
|
273
360
|
const tempRscEnv = await getOrCreateTempServer();
|
|
274
361
|
if (tempRscEnv) {
|
|
275
362
|
await discoverRouters(s, tempRscEnv);
|
|
@@ -286,6 +373,9 @@ export function createRouterDiscoveryPlugin(
|
|
|
286
373
|
}
|
|
287
374
|
|
|
288
375
|
try {
|
|
376
|
+
// Acquire build-time env bindings for dev prerender (Node.js path)
|
|
377
|
+
await acquireBuildEnv(s, viteCommand, viteMode);
|
|
378
|
+
|
|
289
379
|
// Set the readiness gate BEFORE discovery so early requests
|
|
290
380
|
// block until manifest is populated
|
|
291
381
|
const serverMod = await rscEnv.runner.import(
|
|
@@ -421,6 +511,8 @@ export function createRouterDiscoveryPlugin(
|
|
|
421
511
|
{},
|
|
422
512
|
undefined,
|
|
423
513
|
wantPassthrough,
|
|
514
|
+
s.resolvedBuildEnv,
|
|
515
|
+
true, // devMode: check getParams for passthrough routes
|
|
424
516
|
);
|
|
425
517
|
if (!result) continue;
|
|
426
518
|
if (result.passthrough) continue;
|
|
@@ -609,6 +701,9 @@ export function createRouterDiscoveryPlugin(
|
|
|
609
701
|
s.prerenderManifestEntries = null;
|
|
610
702
|
s.staticManifestEntries = null;
|
|
611
703
|
|
|
704
|
+
// Acquire build-time env bindings if configured
|
|
705
|
+
await acquireBuildEnv(s, viteCommand, viteMode);
|
|
706
|
+
|
|
612
707
|
let tempServer: any = null;
|
|
613
708
|
// Signal to user-space code (e.g. reverse.ts) that build-time discovery
|
|
614
709
|
// is active. Uses globalThis because the temp server's module runner
|
|
@@ -667,6 +762,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
667
762
|
if (tempServer) {
|
|
668
763
|
await tempServer.close();
|
|
669
764
|
}
|
|
765
|
+
await releaseBuildEnv(s);
|
|
670
766
|
}
|
|
671
767
|
},
|
|
672
768
|
|
|
@@ -727,33 +823,40 @@ export function createRouterDiscoveryPlugin(
|
|
|
727
823
|
if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size)
|
|
728
824
|
return;
|
|
729
825
|
|
|
826
|
+
// Clear maps at the start of each RSC generateBundle pass.
|
|
827
|
+
// Vite 6 multi-environment builds run RSC twice (analysis + production);
|
|
828
|
+
// clearing prevents stale/duplicate records from the analysis pass.
|
|
829
|
+
s.handlerChunkInfoMap.clear();
|
|
830
|
+
s.staticHandlerChunkInfoMap.clear();
|
|
831
|
+
|
|
730
832
|
for (const [fileName, chunk] of Object.entries(bundle) as [
|
|
731
833
|
string,
|
|
732
834
|
any,
|
|
733
835
|
][]) {
|
|
734
836
|
if (chunk.type !== "chunk") continue;
|
|
735
837
|
|
|
736
|
-
//
|
|
737
|
-
if (
|
|
738
|
-
fileName.includes("__prerender-handlers") &&
|
|
739
|
-
s.resolvedPrerenderModules?.size
|
|
740
|
-
) {
|
|
838
|
+
// Scan all chunks for handler exports (handlers may land in any chunk)
|
|
839
|
+
if (s.resolvedPrerenderModules?.size) {
|
|
741
840
|
const handlers = extractHandlerExportsFromChunk(
|
|
742
841
|
chunk.code,
|
|
743
842
|
s.resolvedPrerenderModules,
|
|
744
843
|
"Prerender",
|
|
745
|
-
|
|
844
|
+
false,
|
|
746
845
|
);
|
|
747
846
|
if (handlers.length > 0) {
|
|
748
|
-
|
|
847
|
+
const existing = s.handlerChunkInfoMap.get(fileName);
|
|
848
|
+
if (existing) {
|
|
849
|
+
existing.exports.push(...handlers);
|
|
850
|
+
} else {
|
|
851
|
+
s.handlerChunkInfoMap.set(fileName, {
|
|
852
|
+
fileName,
|
|
853
|
+
exports: handlers,
|
|
854
|
+
});
|
|
855
|
+
}
|
|
749
856
|
}
|
|
750
857
|
}
|
|
751
858
|
|
|
752
|
-
|
|
753
|
-
if (
|
|
754
|
-
fileName.includes("__static-handlers") &&
|
|
755
|
-
s.resolvedStaticModules?.size
|
|
756
|
-
) {
|
|
859
|
+
if (s.resolvedStaticModules?.size) {
|
|
757
860
|
const handlers = extractHandlerExportsFromChunk(
|
|
758
861
|
chunk.code,
|
|
759
862
|
s.resolvedStaticModules,
|
|
@@ -761,7 +864,15 @@ export function createRouterDiscoveryPlugin(
|
|
|
761
864
|
false,
|
|
762
865
|
);
|
|
763
866
|
if (handlers.length > 0) {
|
|
764
|
-
|
|
867
|
+
const existing = s.staticHandlerChunkInfoMap.get(fileName);
|
|
868
|
+
if (existing) {
|
|
869
|
+
existing.exports.push(...handlers);
|
|
870
|
+
} else {
|
|
871
|
+
s.staticHandlerChunkInfoMap.set(fileName, {
|
|
872
|
+
fileName,
|
|
873
|
+
exports: handlers,
|
|
874
|
+
});
|
|
875
|
+
}
|
|
765
876
|
}
|
|
766
877
|
}
|
|
767
878
|
}
|
package/src/vite/utils/banner.ts
CHANGED
|
@@ -23,11 +23,11 @@ ${dim} ╱${reset} ${bold}╔═╗${reset}${dim} * ╱
|
|
|
23
23
|
${dim} ${reset}${bold}║ ║${reset} ${bold}╔═╗${reset}${dim} * ✧. ╱${reset}
|
|
24
24
|
${dim} ${reset}${bold}╔╗ ║ ║ ║ ║${reset}${dim} * ╱${reset}
|
|
25
25
|
${dim} ${reset}${bold}║║ ║ ║ ║ ║ ╦═╗╔═╗╔╗╔╔═╗╔═╗${reset}${dim} ✧ ✦${reset}
|
|
26
|
-
${dim}
|
|
26
|
+
${dim} ${reset}${bold}║║ ║ ╠═╝ ║ ╠╦╝╠═╣║║║║ ╦║ ║${reset}${dim} * ✧${reset}
|
|
27
27
|
${dim} ${reset}${bold}║╚═╝ ╔═══╝ ╩╚═╩ ╩╝╚╝╚═╝╚═╝${reset}${dim} ✦ . *${reset}
|
|
28
28
|
${dim} ${reset}${bold}╚══╗ ║${reset}${dim} * RSC Wrangler ✧ ✦${reset}
|
|
29
|
-
${dim} * ${reset}${bold}║
|
|
30
|
-
${bold}
|
|
29
|
+
${dim} * ${reset}${bold}║ ║${reset}${dim} * ✧. ╱${reset}
|
|
30
|
+
${dim} ${reset}${bold}═══╝ ╚════${reset}${dim} ✦ *${reset}
|
|
31
31
|
|
|
32
32
|
v${version} · ${preset} · ${mode}
|
|
33
33
|
`;
|
|
@@ -31,6 +31,7 @@ export function encodePathParam(value: unknown): string {
|
|
|
31
31
|
/**
|
|
32
32
|
* Substitute route params into a pattern, stripping constraint and optional
|
|
33
33
|
* syntax (:param(a|b)? -> value). Also handles wildcard params (*key).
|
|
34
|
+
* Optional params not present in `params` are removed from the output.
|
|
34
35
|
*/
|
|
35
36
|
export function substituteRouteParams(
|
|
36
37
|
pattern: string,
|
|
@@ -38,6 +39,9 @@ export function substituteRouteParams(
|
|
|
38
39
|
encode: (value: string) => string = encodeURIComponent,
|
|
39
40
|
): string {
|
|
40
41
|
let result = pattern;
|
|
42
|
+
let hadOmittedOptional = false;
|
|
43
|
+
|
|
44
|
+
// First pass: substitute provided params
|
|
41
45
|
for (const [key, value] of Object.entries(params)) {
|
|
42
46
|
const escaped = escapeRegExp(key);
|
|
43
47
|
result = result.replace(
|
|
@@ -46,6 +50,20 @@ export function substituteRouteParams(
|
|
|
46
50
|
);
|
|
47
51
|
result = result.replace(`*${key}`, encode(value));
|
|
48
52
|
}
|
|
53
|
+
|
|
54
|
+
// Second pass: strip remaining optional param placeholders not in params
|
|
55
|
+
result = result.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?\?/g, () => {
|
|
56
|
+
hadOmittedOptional = true;
|
|
57
|
+
return "";
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Clean up slashes from omitted optional segments
|
|
61
|
+
if (hadOmittedOptional) {
|
|
62
|
+
const hadTrailingSlash = pattern.length > 1 && pattern.endsWith("/");
|
|
63
|
+
result = result.replace(/\/\/+/g, "/").replace(/\/+$/, "") || "/";
|
|
64
|
+
if (hadTrailingSlash && !result.endsWith("/")) result += "/";
|
|
65
|
+
}
|
|
66
|
+
|
|
49
67
|
return result;
|
|
50
68
|
}
|
|
51
69
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
2
|
import * as Vite from "vite";
|
|
3
3
|
import { getPublishedPackageName } from "./package-resolution.js";
|
|
4
|
+
import { performanceTracksOptimizeDepsPlugin } from "../plugins/performance-tracks.js";
|
|
4
5
|
import {
|
|
5
6
|
VIRTUAL_ENTRY_BROWSER,
|
|
6
7
|
VIRTUAL_ENTRY_SSR,
|
|
@@ -35,9 +36,9 @@ const versionEsbuildPlugin = {
|
|
|
35
36
|
* Includes the version stub plugin for all environments.
|
|
36
37
|
*/
|
|
37
38
|
export const sharedEsbuildOptions: {
|
|
38
|
-
plugins:
|
|
39
|
+
plugins: any[];
|
|
39
40
|
} = {
|
|
40
|
-
plugins: [versionEsbuildPlugin],
|
|
41
|
+
plugins: [versionEsbuildPlugin, performanceTracksOptimizeDepsPlugin()],
|
|
41
42
|
};
|
|
42
43
|
|
|
43
44
|
/**
|