cloudflare-next-intl 0.9.44 → 0.9.46

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.
@@ -22,8 +22,6 @@ function bindingsFromClause(clause) {
22
22
  const namespaceMatch = /^\*\s*as\s+(\w+)$/.exec(clause.trim());
23
23
  if (namespaceMatch)
24
24
  return [namespaceMatch[1]];
25
- if (clause.trim() === '*')
26
- return [];
27
25
  const braceMatch = /\{([^}]*)\}/.exec(clause);
28
26
  if (braceMatch) {
29
27
  for (const rawItem of braceMatch[1].split(',')) {
@@ -2,6 +2,7 @@ export { autoDynamicPagesPlugin, type AutoDynamicPagesPluginOptions } from "./au
2
2
  export { buildIdAsset } from "./build_id_asset.js";
3
3
  export { userAgentStubPlugin, USER_AGENT_STUB_ID, USER_AGENT_STUB_CODE } from "./user_agent_stub.js";
4
4
  export { cfWorkersClientStubPlugin, CF_WORKERS_CLIENT_STUB_ID, CF_WORKERS_CLIENT_STUB_CODE } from "./cf_workers_client_stub.js";
5
+ export { vinextRouteWiringFixPlugin, patchAppPageRouteWiring, isAppPageRouteWiringFile, isAppPageRouteWiringAlreadyFixed, type VinextRouteWiringFixPluginOptions } from "./vinext_route_wiring_fix.js";
5
6
  export { localeFilePlugin, resolveDefaultIntlConfigPath, type LocaleFilePluginOptions } from "./locale_file_plugin.js";
6
7
  export { cloudflareNextIntl, cloudflareNextIntlPlugin, type CloudflareNextIntlOptions, default } from "./plugin.js";
7
8
  export { imageOptimizer, imageOptimizerPlugin, VIRTUAL_IMAGE_SHIM_ID, type ImageFormat, type ImageBlurOptions, type ImageOverrideOptions, type ImageOptimizerPluginOptions, type ResolvedBlurOptions, type ResolvedOptions, type ResolvedImageConfig, type OptimizedImage, type ManifestData, type ManifestEntry, } from "../image_optimizer/index.js";
@@ -2,6 +2,7 @@ export { autoDynamicPagesPlugin } from "./auto_dynamic_pages_plugin.js";
2
2
  export { buildIdAsset } from "./build_id_asset.js";
3
3
  export { userAgentStubPlugin, USER_AGENT_STUB_ID, USER_AGENT_STUB_CODE } from "./user_agent_stub.js";
4
4
  export { cfWorkersClientStubPlugin, CF_WORKERS_CLIENT_STUB_ID, CF_WORKERS_CLIENT_STUB_CODE } from "./cf_workers_client_stub.js";
5
+ export { vinextRouteWiringFixPlugin, patchAppPageRouteWiring, isAppPageRouteWiringFile, isAppPageRouteWiringAlreadyFixed } from "./vinext_route_wiring_fix.js";
5
6
  export { localeFilePlugin, resolveDefaultIntlConfigPath } from "./locale_file_plugin.js";
6
7
  export { cloudflareNextIntl, cloudflareNextIntlPlugin, default } from "./plugin.js";
7
8
  export { imageOptimizer, imageOptimizerPlugin, VIRTUAL_IMAGE_SHIM_ID, } from "../image_optimizer/index.js";
@@ -2,6 +2,7 @@ import type { Plugin } from "vite";
2
2
  import { type LocaleFilePluginOptions } from "./locale_file_plugin.js";
3
3
  import { type ImageOptimizerPluginOptions } from "../image_optimizer/index.js";
4
4
  import { type AutoDynamicPagesPluginOptions } from "./auto_dynamic_pages_plugin.js";
5
+ import { type VinextRouteWiringFixPluginOptions } from "./vinext_route_wiring_fix.js";
5
6
  export interface CloudflareNextIntlOptions extends LocaleFilePluginOptions {
6
7
  autoDynamicPages?: boolean | AutoDynamicPagesPluginOptions;
7
8
  buildIdAsset?: boolean | string;
@@ -9,6 +10,7 @@ export interface CloudflareNextIntlOptions extends LocaleFilePluginOptions {
9
10
  userAgentStub?: boolean;
10
11
  cfWorkersClientStub?: boolean;
11
12
  imageOptimizer?: boolean | ImageOptimizerPluginOptions;
13
+ vinextRouteWiringFix?: boolean | VinextRouteWiringFixPluginOptions;
12
14
  }
13
15
  export declare function cloudflareNextIntl(options?: CloudflareNextIntlOptions): Plugin[];
14
16
  export declare const cloudflareNextIntlPlugin: typeof cloudflareNextIntl;
@@ -4,6 +4,7 @@ import { cfWorkersClientStubPlugin } from "./cf_workers_client_stub.js";
4
4
  import { localeFilePlugin } from "./locale_file_plugin.js";
5
5
  import { imageOptimizerPlugin } from "../image_optimizer/index.js";
6
6
  import { autoDynamicPagesPlugin } from "./auto_dynamic_pages_plugin.js";
7
+ import { vinextRouteWiringFixPlugin } from "./vinext_route_wiring_fix.js";
7
8
  export function cloudflareNextIntl(options = {}) {
8
9
  const plugins = [];
9
10
  if (options.autoDynamicPages !== false) {
@@ -26,6 +27,9 @@ export function cloudflareNextIntl(options = {}) {
26
27
  if (options.userAgentStub !== false) {
27
28
  plugins.push(userAgentStubPlugin());
28
29
  }
30
+ if (options.vinextRouteWiringFix !== false) {
31
+ plugins.push(vinextRouteWiringFixPlugin(typeof options.vinextRouteWiringFix === "object" ? options.vinextRouteWiringFix : {}));
32
+ }
29
33
  if (options.localeFiles !== false) {
30
34
  plugins.push(localeFilePlugin({
31
35
  messagesDir: options.messagesDir,
@@ -0,0 +1,32 @@
1
+ import type { Plugin } from "vite";
2
+ export declare function isAppPageRouteWiringAlreadyFixed(code: string): boolean;
3
+ export declare function patchAppPageRouteWiring(code: string): string;
4
+ export declare function isRouteMatchingFile(id: string): boolean;
5
+ export declare function isRouteMatchingAlreadyFixed(code: string): boolean;
6
+ export declare function patchRouteMatching(code: string): string;
7
+ export declare function isOptimisticRoutingFile(id: string): boolean;
8
+ export declare function isOptimisticRoutingAlreadyFixed(code: string): boolean;
9
+ export declare function patchOptimisticRouting(code: string): string;
10
+ export declare function isPrefetchLearningFile(id: string): boolean;
11
+ export declare function isPrefetchLearningAlreadyFixed(code: string): boolean;
12
+ export declare function patchPrefetchLearning(code: string): string;
13
+ export declare function resolveVinextBrowserEntryPath(root?: string): string | null;
14
+ export declare function isAppPageRouteWiringFile(id: string): boolean;
15
+ export declare function resolveVinextAppPageRouteWiringPath(root?: string): string | null;
16
+ export declare function resolveVinextRouteMatchingPath(root?: string): string | null;
17
+ export declare function resolveVinextOptimisticRoutingPath(root?: string): string | null;
18
+ export interface SyncPatchVinextOnDiskOptions {
19
+ routeWiring?: boolean;
20
+ routeMatching?: boolean;
21
+ optimisticRouting?: boolean;
22
+ prefetchLearning?: boolean;
23
+ }
24
+ export declare function syncPatchVinextOnDisk(root?: string, options?: SyncPatchVinextOnDiskOptions): boolean;
25
+ export declare function bustVinextOptimizeDepsCache(cacheDir: string): boolean;
26
+ export interface VinextRouteWiringFixPluginOptions {
27
+ routeWiring?: boolean;
28
+ routeMatching?: boolean;
29
+ optimisticRouting?: boolean;
30
+ prefetchLearning?: boolean;
31
+ }
32
+ export declare function vinextRouteWiringFixPlugin(options?: VinextRouteWiringFixPluginOptions): Plugin;
@@ -0,0 +1,402 @@
1
+ import { existsSync, readFileSync, writeFileSync, rmSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ const PREFETCH_LOADING_FN_RE = /function\s+getPrefetchLoadingEntry\s*\(\s*route\s*\)\s*\{[\s\S]*?return\s+getDefaultExport\s*\(\s*route\.loading\s*\)\s*\?[\s\S]*?:\s*null\s*;\s*\}/;
4
+ const FIXED_PREFETCH_LOADING_FN = `function getPrefetchLoadingEntry(route) {
5
+ let rootEntry = null;
6
+ let deepestNestedEntry = null;
7
+ for (const [index, loadingModule] of (route.loadings ?? []).entries()) {
8
+ if (!getDefaultExport(loadingModule)) continue;
9
+ const treePosition = route.loadingTreePositions?.[index];
10
+ if (treePosition === void 0) continue;
11
+ if (treePosition === 0) rootEntry ??= {
12
+ loadingModule,
13
+ treePosition
14
+ };
15
+ else if (deepestNestedEntry === null || treePosition > deepestNestedEntry.treePosition) deepestNestedEntry = {
16
+ loadingModule,
17
+ treePosition
18
+ };
19
+ }
20
+ const leafEntry = getDefaultExport(route.loading) ? {
21
+ loadingModule: route.loading,
22
+ treePosition: route.routeSegments?.length ?? 0
23
+ } : null;
24
+ if (leafEntry && (!deepestNestedEntry || leafEntry.treePosition >= deepestNestedEntry.treePosition)) return leafEntry;
25
+ if (deepestNestedEntry) return deepestNestedEntry;
26
+ if (rootEntry) return rootEntry;
27
+ return null;
28
+ }`;
29
+ const ROUTE_LOADING_GUARD_RE = /if\s*\(\s*!isPrefetchLoadingShell\s*&&\s*treePosition\s*<\s*routeSegments\.length\s*\)\s*\{/g;
30
+ const FIXED_ROUTE_LOADING_GUARD = "if (!isPrefetchLoadingShell && treePosition < routeSegments.length && !routeLoadingComponent) {";
31
+ export function isAppPageRouteWiringAlreadyFixed(code) {
32
+ const hasBuggyPrefetch = code.includes("firstNestedEntry") && PREFETCH_LOADING_FN_RE.test(code);
33
+ const hasBuggySuspense = !code.includes("!routeLoadingComponent") && ROUTE_LOADING_GUARD_RE.test(code);
34
+ return !hasBuggyPrefetch && !hasBuggySuspense;
35
+ }
36
+ export function patchAppPageRouteWiring(code) {
37
+ if (isAppPageRouteWiringAlreadyFixed(code)) {
38
+ return code;
39
+ }
40
+ let result = code;
41
+ const hasBuggyPrefetch = code.includes("firstNestedEntry") && PREFETCH_LOADING_FN_RE.test(code);
42
+ if (hasBuggyPrefetch && !result.includes("deepestNestedEntry")) {
43
+ result = result.replace(PREFETCH_LOADING_FN_RE, FIXED_PREFETCH_LOADING_FN);
44
+ }
45
+ const hasBuggySuspense = !result.includes("!routeLoadingComponent") && ROUTE_LOADING_GUARD_RE.test(result);
46
+ if (hasBuggySuspense) {
47
+ result = result.replace(ROUTE_LOADING_GUARD_RE, FIXED_ROUTE_LOADING_GUARD);
48
+ }
49
+ return result;
50
+ }
51
+ export function isRouteMatchingFile(id) {
52
+ const cleanId = id.split("?")[0].replace(/\\/g, "/");
53
+ return cleanId.endsWith("/routing/route-matching.js") || cleanId.endsWith("/routing/route-matching.ts");
54
+ }
55
+ export function isRouteMatchingAlreadyFixed(code) {
56
+ return code.includes("hasLeadingLocaleParam");
57
+ }
58
+ const MATCH_ROUTE_WITH_TRIE_RE = /function\s+matchRouteWithTrie\s*\(\s*url\s*,\s*routes\s*,\s*cache\s*\)\s*\{[\s\S]*?return\s+trieMatch\([\s\S]*?\);\s*\}/;
59
+ const FIXED_MATCH_ROUTE_WITH_TRIE = `function getActiveRouteLocale() {
60
+ return (typeof document !== "undefined" && (document.documentElement?.lang || document.cookie.match(/__user_locale_key__=([^;]+)/)?.[1])) || (typeof window !== "undefined" && window.__VINEXT_LOCALE__) || "en";
61
+ }
62
+ function matchRouteWithTrie(url, routes, cache) {
63
+ const pathname = url.split("?")[0];
64
+ let normalizedUrl = pathname === "/" ? "/" : pathname.replace(/\\/$/, "");
65
+ normalizedUrl = normalizePathnameForRouteMatch(normalizedUrl);
66
+ const urlParts = normalizedUrl.split("/").filter(Boolean);
67
+ const trie = getOrBuildTrie(cache, routes);
68
+ const hasLeadingLocaleParam = routes.some((r) => r.patternParts?.[0] === ":locale");
69
+ if (hasLeadingLocaleParam) {
70
+ const activeLocale = getActiveRouteLocale();
71
+ if (urlParts[0] !== activeLocale) {
72
+ const matchWithLocale = trieMatch(trie, [activeLocale, ...urlParts]);
73
+ if (matchWithLocale) return matchWithLocale;
74
+ }
75
+ }
76
+ return trieMatch(trie, urlParts);
77
+ }`;
78
+ const MATCH_ROUTE_WITH_TRIE_RAW_RE = /function\s+matchRouteWithTrieRawPathname\s*\(\s*url\s*,\s*routes\s*,\s*cache\s*\)\s*\{[\s\S]*?return\s+trieMatch\([\s\S]*?\);\s*\}/;
79
+ const FIXED_MATCH_ROUTE_WITH_TRIE_RAW = `function matchRouteWithTrieRawPathname(url, routes, cache) {
80
+ const pathname = url.split("?")[0];
81
+ const urlParts = (pathname === "/" ? "/" : pathname.replace(/\\/$/, "")).split("/").filter(Boolean);
82
+ const trie = getOrBuildTrie(cache, routes);
83
+ const hasLeadingLocaleParam = routes.some((r) => r.patternParts?.[0] === ":locale");
84
+ if (hasLeadingLocaleParam) {
85
+ const activeLocale = getActiveRouteLocale();
86
+ if (urlParts[0] !== activeLocale) {
87
+ const matchWithLocale = trieMatch(trie, [activeLocale, ...urlParts]);
88
+ if (matchWithLocale) return matchWithLocale;
89
+ }
90
+ }
91
+ return trieMatch(trie, urlParts);
92
+ }`;
93
+ export function patchRouteMatching(code) {
94
+ if (isRouteMatchingAlreadyFixed(code)) {
95
+ return code;
96
+ }
97
+ let result = code;
98
+ if (MATCH_ROUTE_WITH_TRIE_RE.test(result)) {
99
+ result = result.replace(MATCH_ROUTE_WITH_TRIE_RE, FIXED_MATCH_ROUTE_WITH_TRIE);
100
+ }
101
+ if (MATCH_ROUTE_WITH_TRIE_RAW_RE.test(result)) {
102
+ result = result.replace(MATCH_ROUTE_WITH_TRIE_RAW_RE, FIXED_MATCH_ROUTE_WITH_TRIE_RAW);
103
+ }
104
+ return result;
105
+ }
106
+ export function isOptimisticRoutingFile(id) {
107
+ const cleanId = id.split("?")[0].replace(/\\/g, "/");
108
+ return cleanId.endsWith("/app-optimistic-routing.js") || cleanId.endsWith("/app-optimistic-routing.ts");
109
+ }
110
+ export function isOptimisticRoutingAlreadyFixed(code) {
111
+ const hasLocalePrefixFirst = code.includes("hasLeadingLocaleParam") &&
112
+ code.indexOf("hasLeadingLocaleParam") < code.indexOf("const match = matchNode(trie, urlParts.normalized");
113
+ const hasRawPartsFix = code.includes("options.rawUrlParts[0] !== options.match.params.locale");
114
+ return hasLocalePrefixFirst && hasRawPartsFix;
115
+ }
116
+ const MATCH_OPTIMISTIC_ROUTE_RE = /function\s+matchOptimisticRouteManifestRoute\s*\(\s*options\s*\)\s*\{[\s\S]*?getRouteTrie\([\s\S]*?\)[\s\S]*?\n\}/;
117
+ const FIXED_MATCH_OPTIMISTIC_ROUTE = `function getActiveRouteLocale() {
118
+ return (typeof document !== "undefined" && (document.documentElement?.lang || document.cookie.match(/__user_locale_key__=([^;]+)/)?.[1])) || (typeof window !== "undefined" && window.__VINEXT_LOCALE__) || "en";
119
+ }
120
+ function matchOptimisticRouteManifestRoute(options) {
121
+ const urlParts = hrefToRouteParts(options.href, options.basePath);
122
+ if (urlParts === null) return null;
123
+ const trie = getRouteTrie(options.routeManifest);
124
+ const hasLeadingLocaleParam = Array.from(options.routeManifest?.segmentGraph?.routes?.values() ?? []).some((r) => r.patternParts?.[0] === ":locale");
125
+ if (hasLeadingLocaleParam) {
126
+ const activeLocale = getActiveRouteLocale();
127
+ if (urlParts.normalized[0] !== activeLocale) {
128
+ const localeMatch = matchNode(trie, [activeLocale, ...urlParts.normalized], 0, []);
129
+ if (localeMatch !== null) {
130
+ decodeMatchedParams(localeMatch.params);
131
+ return localeMatch;
132
+ }
133
+ }
134
+ }
135
+ const match = matchNode(trie, urlParts.normalized, 0, []);
136
+ if (match !== null) {
137
+ decodeMatchedParams(match.params);
138
+ return match;
139
+ }
140
+ return null;
141
+ }`;
142
+ const RESOLVE_OPTIMISTIC_NAV_PARAMS_RE = /function\s+resolveOptimisticNavigationParams\s*\(\s*options\s*\)\s*\{[\s\S]*?const\s+routeParams\s*=\s*extractRawRoutePatternParams\s*\(\s*options\.match\.route\.patternParts\s*,\s*options\.rawUrlParts\s*\);/;
143
+ const FIXED_RESOLVE_OPTIMISTIC_NAV_PARAMS = `function resolveOptimisticNavigationParams(options) {
144
+ const rawParts = (options.match.route.patternParts?.[0] === ":locale" && options.rawUrlParts[0] !== options.match.params.locale)
145
+ ? [options.match.params.locale, ...options.rawUrlParts]
146
+ : options.rawUrlParts;
147
+ const routeParams = extractRawRoutePatternParams(options.match.route.patternParts, rawParts);`;
148
+ export function patchOptimisticRouting(code) {
149
+ if (isOptimisticRoutingAlreadyFixed(code)) {
150
+ return code;
151
+ }
152
+ let result = code;
153
+ if (!result.includes("hasLeadingLocaleParam") && MATCH_OPTIMISTIC_ROUTE_RE.test(result)) {
154
+ result = result.replace(MATCH_OPTIMISTIC_ROUTE_RE, FIXED_MATCH_OPTIMISTIC_ROUTE);
155
+ }
156
+ if (!result.includes("options.rawUrlParts[0] !== options.match.params.locale") && RESOLVE_OPTIMISTIC_NAV_PARAMS_RE.test(result)) {
157
+ result = result.replace(RESOLVE_OPTIMISTIC_NAV_PARAMS_RE, FIXED_RESOLVE_OPTIMISTIC_NAV_PARAMS);
158
+ }
159
+ return result;
160
+ }
161
+ export function isPrefetchLearningFile(id) {
162
+ const cleanId = id.split("?")[0].replace(/\\/g, "/");
163
+ return cleanId.endsWith("/app-browser-entry.js") || cleanId.endsWith("/app-browser-entry.ts");
164
+ }
165
+ export function isPrefetchLearningAlreadyFixed(code) {
166
+ const hasFixedFunction = code.includes("isPendingNavigationTarget");
167
+ const hasFixedCallSite = code.includes("targetRscUrl: rscUrl,");
168
+ return hasFixedFunction && hasFixedCallSite;
169
+ }
170
+ const LEARN_TEMPLATES_FN_RE = /async\s+function\s+learnOptimisticRouteTemplatesFromPrefetchCache\s*\(\s*options\s*\)\s*\{[\s\S]*?await\s+Promise\.allSettled\(\s*learning\s*\);\s*\}/;
171
+ const FIXED_LEARN_TEMPLATES_FN = `async function learnOptimisticRouteTemplatesFromPrefetchCache(options) {
172
+ if (options.routeManifest === null) return;
173
+ const learning = [...optimisticRouteTemplateLearning.values()];
174
+ for (const [cacheKey, entry] of getPrefetchCache()) {
175
+ const sourceKey = getOptimisticPrefetchSourceKey({
176
+ cacheKey,
177
+ interceptionContext: options.interceptionContext,
178
+ mountedSlotsHeader: options.mountedSlotsHeader
179
+ });
180
+ if (optimisticRouteTemplateSources.has(sourceKey)) continue;
181
+ if (optimisticRouteTemplateLearning.has(sourceKey)) continue;
182
+ if (entry.prefetchKind === "route-tree") continue;
183
+ const isPendingNavigationTarget = !isSettledPrefetchCacheEntry(entry) && entry.pending !== void 0 && options.targetRscUrl !== void 0 && parsePrefetchCacheKey(cacheKey).rscUrl === options.targetRscUrl;
184
+ if (!isSettledPrefetchCacheEntry(entry) && !isPendingNavigationTarget) continue;
185
+ const promise = (async () => {
186
+ let settledEntry = entry;
187
+ if (!isSettledPrefetchCacheEntry(settledEntry)) {
188
+ await Promise.race([
189
+ settledEntry.pending?.catch(() => {}),
190
+ new Promise((resolve) => setTimeout(resolve, 3000))
191
+ ]);
192
+ settledEntry = getPrefetchCache().get(cacheKey) ?? settledEntry;
193
+ if (!isSettledPrefetchCacheEntry(settledEntry)) return;
194
+ }
195
+ return learnOptimisticRouteTemplateFromPrefetch({
196
+ cacheKey,
197
+ entry: settledEntry,
198
+ interceptionContext: options.interceptionContext,
199
+ mountedSlotsHeader: options.mountedSlotsHeader,
200
+ routeManifest: options.routeManifest
201
+ });
202
+ })().then((learned) => {
203
+ if (learned) optimisticRouteTemplateSources.add(sourceKey);
204
+ }).finally(() => {
205
+ optimisticRouteTemplateLearning.delete(sourceKey);
206
+ });
207
+ optimisticRouteTemplateLearning.set(sourceKey, promise);
208
+ learning.push(promise);
209
+ }
210
+ if (learning.length === 0) return;
211
+ await Promise.allSettled(learning);
212
+ }`;
213
+ const LEARN_TEMPLATES_CALL_RE = /(await\s+learnOptimisticRouteTemplatesFromPrefetchCache\(\s*\{\s*)interceptionContext:\s*requestInterceptionContext,/;
214
+ const FIXED_LEARN_TEMPLATES_CALL = "$1interceptionContext: requestInterceptionContext,\n\t\t\t\t\t\t\ttargetRscUrl: rscUrl,";
215
+ export function patchPrefetchLearning(code) {
216
+ if (isPrefetchLearningAlreadyFixed(code)) {
217
+ return code;
218
+ }
219
+ let result = code;
220
+ if (!result.includes("isPendingNavigationTarget") && LEARN_TEMPLATES_FN_RE.test(result)) {
221
+ result = result.replace(LEARN_TEMPLATES_FN_RE, FIXED_LEARN_TEMPLATES_FN);
222
+ }
223
+ if (!result.includes("targetRscUrl: rscUrl,") && LEARN_TEMPLATES_CALL_RE.test(result)) {
224
+ result = result.replace(LEARN_TEMPLATES_CALL_RE, FIXED_LEARN_TEMPLATES_CALL);
225
+ }
226
+ return result;
227
+ }
228
+ export function resolveVinextBrowserEntryPath(root = process.cwd()) {
229
+ const directPath = resolve(root, "node_modules/vinext/dist/server/app-browser-entry.js");
230
+ return existsSync(directPath) ? directPath : null;
231
+ }
232
+ export function isAppPageRouteWiringFile(id) {
233
+ const cleanId = id.split("?")[0].replace(/\\/g, "/");
234
+ return cleanId.endsWith("/app-page-route-wiring.js") || cleanId.endsWith("/app-page-route-wiring.tsx") || cleanId.endsWith("/app-page-route-wiring.ts");
235
+ }
236
+ export function resolveVinextAppPageRouteWiringPath(root = process.cwd()) {
237
+ const directPath = resolve(root, "node_modules/vinext/dist/server/app-page-route-wiring.js");
238
+ return existsSync(directPath) ? directPath : null;
239
+ }
240
+ export function resolveVinextRouteMatchingPath(root = process.cwd()) {
241
+ const directPath = resolve(root, "node_modules/vinext/dist/routing/route-matching.js");
242
+ return existsSync(directPath) ? directPath : null;
243
+ }
244
+ export function resolveVinextOptimisticRoutingPath(root = process.cwd()) {
245
+ const directPath = resolve(root, "node_modules/vinext/dist/server/app-optimistic-routing.js");
246
+ return existsSync(directPath) ? directPath : null;
247
+ }
248
+ export function syncPatchVinextOnDisk(root = process.cwd(), options = {}) {
249
+ const { routeWiring = true, routeMatching = true, optimisticRouting = true, prefetchLearning = true } = options;
250
+ let changed = false;
251
+ const wiringPath = routeWiring ? resolveVinextAppPageRouteWiringPath(root) : null;
252
+ if (wiringPath) {
253
+ try {
254
+ const content = readFileSync(wiringPath, "utf8");
255
+ if (!isAppPageRouteWiringAlreadyFixed(content)) {
256
+ const patched = patchAppPageRouteWiring(content);
257
+ if (patched !== content) {
258
+ writeFileSync(wiringPath, patched, "utf8");
259
+ changed = true;
260
+ }
261
+ else {
262
+ console.warn(`[cfni:vinext-route-wiring-fix] ${wiringPath} does not match the expected shape for patchAppPageRouteWiring — this vinext version may have changed; the route-wiring fix was NOT applied.`);
263
+ }
264
+ }
265
+ }
266
+ catch {
267
+ }
268
+ }
269
+ const matchingPath = routeMatching ? resolveVinextRouteMatchingPath(root) : null;
270
+ if (matchingPath) {
271
+ try {
272
+ const content = readFileSync(matchingPath, "utf8");
273
+ if (!isRouteMatchingAlreadyFixed(content)) {
274
+ const patched = patchRouteMatching(content);
275
+ if (patched !== content) {
276
+ writeFileSync(matchingPath, patched, "utf8");
277
+ changed = true;
278
+ }
279
+ else {
280
+ console.warn(`[cfni:vinext-route-wiring-fix] ${matchingPath} does not match the expected shape for patchRouteMatching — this vinext version may have changed; the route-matching fix was NOT applied.`);
281
+ }
282
+ }
283
+ }
284
+ catch {
285
+ }
286
+ }
287
+ const optimisticPath = optimisticRouting ? resolveVinextOptimisticRoutingPath(root) : null;
288
+ if (optimisticPath) {
289
+ try {
290
+ const content = readFileSync(optimisticPath, "utf8");
291
+ if (!isOptimisticRoutingAlreadyFixed(content)) {
292
+ const patched = patchOptimisticRouting(content);
293
+ if (patched !== content) {
294
+ writeFileSync(optimisticPath, patched, "utf8");
295
+ changed = true;
296
+ }
297
+ else {
298
+ console.warn(`[cfni:vinext-route-wiring-fix] ${optimisticPath} does not match the expected shape for patchOptimisticRouting — this vinext version may have changed; the optimistic-routing fix was NOT applied.`);
299
+ }
300
+ }
301
+ }
302
+ catch {
303
+ }
304
+ }
305
+ const browserEntryPath = prefetchLearning ? resolveVinextBrowserEntryPath(root) : null;
306
+ if (browserEntryPath) {
307
+ try {
308
+ const content = readFileSync(browserEntryPath, "utf8");
309
+ if (!isPrefetchLearningAlreadyFixed(content)) {
310
+ const patched = patchPrefetchLearning(content);
311
+ if (patched !== content) {
312
+ writeFileSync(browserEntryPath, patched, "utf8");
313
+ changed = true;
314
+ }
315
+ else {
316
+ console.warn(`[cfni:vinext-route-wiring-fix] ${browserEntryPath} does not match the expected shape for patchPrefetchLearning — this vinext version may have changed; the prefetch-learning fix was NOT applied.`);
317
+ }
318
+ }
319
+ }
320
+ catch {
321
+ }
322
+ }
323
+ return changed;
324
+ }
325
+ export function bustVinextOptimizeDepsCache(cacheDir) {
326
+ let removed = false;
327
+ for (const sub of ["deps", "deps_ssr", "deps_rsc"]) {
328
+ const dir = resolve(cacheDir, sub);
329
+ if (!existsSync(dir))
330
+ continue;
331
+ try {
332
+ rmSync(dir, { recursive: true, force: true });
333
+ removed = true;
334
+ }
335
+ catch {
336
+ }
337
+ }
338
+ return removed;
339
+ }
340
+ export function vinextRouteWiringFixPlugin(options = {}) {
341
+ const routeWiring = options.routeWiring !== false;
342
+ const routeMatching = options.routeMatching !== false;
343
+ const optimisticRouting = options.optimisticRouting !== false;
344
+ const prefetchLearning = options.prefetchLearning !== false;
345
+ return {
346
+ name: "cfni:vinext-route-wiring-fix",
347
+ enforce: "pre",
348
+ configResolved(config) {
349
+ const root = config.root || process.cwd();
350
+ const changed = syncPatchVinextOnDisk(root, { routeWiring, routeMatching, optimisticRouting, prefetchLearning });
351
+ if (changed) {
352
+ const cacheDir = config.cacheDir || resolve(root, "node_modules/.vite");
353
+ const busted = bustVinextOptimizeDepsCache(cacheDir);
354
+ if (busted) {
355
+ console.log("[cfni:vinext-route-wiring-fix] patched vinext on disk and cleared its stale Vite optimizeDeps cache — dependencies will re-bundle on next request.");
356
+ }
357
+ }
358
+ },
359
+ transform(code, id) {
360
+ if (routeWiring && isAppPageRouteWiringFile(id)) {
361
+ if (isAppPageRouteWiringAlreadyFixed(code)) {
362
+ return;
363
+ }
364
+ const patched = patchAppPageRouteWiring(code);
365
+ return {
366
+ code: patched,
367
+ map: null,
368
+ };
369
+ }
370
+ if (routeMatching && isRouteMatchingFile(id)) {
371
+ if (isRouteMatchingAlreadyFixed(code)) {
372
+ return;
373
+ }
374
+ const patched = patchRouteMatching(code);
375
+ return {
376
+ code: patched,
377
+ map: null,
378
+ };
379
+ }
380
+ if (prefetchLearning && isPrefetchLearningFile(id)) {
381
+ if (isPrefetchLearningAlreadyFixed(code)) {
382
+ return;
383
+ }
384
+ const patched = patchPrefetchLearning(code);
385
+ return {
386
+ code: patched,
387
+ map: null,
388
+ };
389
+ }
390
+ if (optimisticRouting && isOptimisticRoutingFile(id)) {
391
+ if (isOptimisticRoutingAlreadyFixed(code)) {
392
+ return;
393
+ }
394
+ const patched = patchOptimisticRouting(code);
395
+ return {
396
+ code: patched,
397
+ map: null,
398
+ };
399
+ }
400
+ },
401
+ };
402
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.9.44",
3
+ "version": "0.9.46",
4
4
  "description": "Optimized Next Intl Package Special for App Router and Cloudflare",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",