cloudflare-next-intl 0.9.47 → 0.9.49
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/README.md +15 -7
- package/bin/check_locale_params.mjs +26 -0
- package/dist/src/dynamic_pages_check/check_dynamic_pages.js +7 -2
- package/dist/src/dynamic_pages_check/detect_dynamic_usage.js +7 -0
- package/dist/src/dynamic_pages_check/find_page_files.js +1 -1
- package/dist/src/image_optimizer/plugin.js +6 -1
- package/dist/src/locale_params_check/check_locale_params.d.ts +24 -0
- package/dist/src/locale_params_check/check_locale_params.js +104 -0
- package/dist/src/locale_params_check/detect_locale_params.d.ts +10 -0
- package/dist/src/locale_params_check/detect_locale_params.js +96 -0
- package/dist/src/locale_params_check/find_locale_scoped_files.d.ts +1 -0
- package/dist/src/locale_params_check/find_locale_scoped_files.js +14 -0
- package/dist/src/locale_params_check/index.d.ts +4 -0
- package/dist/src/locale_params_check/index.js +4 -0
- package/dist/src/locale_params_check/insert_locale_params.d.ts +5 -0
- package/dist/src/locale_params_check/insert_locale_params.js +117 -0
- package/dist/src/vite/auto_dynamic_pages_plugin.js +2 -24
- package/dist/src/vite/auto_locale_params_plugin.d.ts +18 -0
- package/dist/src/vite/auto_locale_params_plugin.js +71 -0
- package/dist/src/vite/build_write_restore_stack.d.ts +1 -0
- package/dist/src/vite/build_write_restore_stack.js +43 -0
- package/dist/src/vite/index.d.ts +2 -0
- package/dist/src/vite/index.js +2 -0
- package/dist/src/vite/lucide_optimizer_plugin.d.ts +21 -0
- package/dist/src/vite/lucide_optimizer_plugin.js +190 -0
- package/dist/src/vite/plugin.d.ts +4 -0
- package/dist/src/vite/plugin.js +12 -0
- package/dist/src/vite/vinext_route_wiring_fix.js +71 -24
- package/llms.txt +3 -1
- package/package.json +7 -2
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { checkLocaleParams } from "../locale_params_check/check_locale_params.js";
|
|
4
|
+
import { registerBuildWriteRestore } from "./build_write_restore_stack.js";
|
|
5
|
+
const RESTORABLE_ACTIONS = new Set(['added-locale-params']);
|
|
6
|
+
export function autoLocaleParamsPlugin(options = {}) {
|
|
7
|
+
let ran = false;
|
|
8
|
+
return {
|
|
9
|
+
name: "cloudflare-next-intl-auto-locale-params",
|
|
10
|
+
enforce: "pre",
|
|
11
|
+
async configResolved(config) {
|
|
12
|
+
if (ran)
|
|
13
|
+
return;
|
|
14
|
+
const isBuild = config.command === "build";
|
|
15
|
+
const isDev = config.command === "serve";
|
|
16
|
+
if (!isBuild && !(isDev && options.runOnDev))
|
|
17
|
+
return;
|
|
18
|
+
ran = true;
|
|
19
|
+
const root = config.root || process.cwd();
|
|
20
|
+
let appDir = options.appDir;
|
|
21
|
+
if (!appDir) {
|
|
22
|
+
if (existsSync(resolve(root, "src/app"))) {
|
|
23
|
+
appDir = resolve(root, "src/app");
|
|
24
|
+
}
|
|
25
|
+
else if (existsSync(resolve(root, "app"))) {
|
|
26
|
+
appDir = resolve(root, "app");
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (!appDir || !existsSync(appDir))
|
|
30
|
+
return;
|
|
31
|
+
const restoreAfterBuild = isBuild && (options.restoreAfterBuild ?? true);
|
|
32
|
+
const originals = new Map();
|
|
33
|
+
try {
|
|
34
|
+
const reports = await checkLocaleParams({
|
|
35
|
+
appDir,
|
|
36
|
+
mode: options.mode ?? "fix",
|
|
37
|
+
localeParam: options.localeParam,
|
|
38
|
+
skip: options.skip,
|
|
39
|
+
overrides: options.overrides,
|
|
40
|
+
verbose: options.verbose ?? false,
|
|
41
|
+
}, restoreAfterBuild
|
|
42
|
+
? {
|
|
43
|
+
writeFile: (file, contents) => {
|
|
44
|
+
if (!originals.has(file)) {
|
|
45
|
+
try {
|
|
46
|
+
originals.set(file, readFileSync(file, "utf8"));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
writeFileSync(file, contents, "utf8");
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
: undefined);
|
|
55
|
+
if (!restoreAfterBuild)
|
|
56
|
+
return;
|
|
57
|
+
const restorable = new Set(reports
|
|
58
|
+
.filter((report) => RESTORABLE_ACTIONS.has(report.action))
|
|
59
|
+
.map((report) => report.file));
|
|
60
|
+
for (const file of [...originals.keys()]) {
|
|
61
|
+
if (!restorable.has(file))
|
|
62
|
+
originals.delete(file);
|
|
63
|
+
}
|
|
64
|
+
registerBuildWriteRestore(originals);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.warn("[cloudflare-next-intl] autoLocaleParams check error:", err);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerBuildWriteRestore(originals: ReadonlyMap<string, string>): void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { writeFileSync } from "node:fs";
|
|
2
|
+
const restoreStack = [];
|
|
3
|
+
let registered = false;
|
|
4
|
+
export function registerBuildWriteRestore(originals) {
|
|
5
|
+
if (originals.size === 0)
|
|
6
|
+
return;
|
|
7
|
+
restoreStack.push(() => {
|
|
8
|
+
for (const [file, contents] of originals) {
|
|
9
|
+
try {
|
|
10
|
+
writeFileSync(file, contents, "utf8");
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
if (registered)
|
|
17
|
+
return;
|
|
18
|
+
registered = true;
|
|
19
|
+
armProcessRestoreHandlers();
|
|
20
|
+
}
|
|
21
|
+
function runAllRestores() {
|
|
22
|
+
while (restoreStack.length > 0) {
|
|
23
|
+
const restore = restoreStack.pop();
|
|
24
|
+
restore();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function armProcessRestoreHandlers() {
|
|
28
|
+
process.once("exit", runAllRestores);
|
|
29
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
30
|
+
process.once(signal, () => {
|
|
31
|
+
runAllRestores();
|
|
32
|
+
process.kill(process.pid, signal);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
process.once("uncaughtException", (err) => {
|
|
36
|
+
runAllRestores();
|
|
37
|
+
throw err;
|
|
38
|
+
});
|
|
39
|
+
process.once("unhandledRejection", (reason) => {
|
|
40
|
+
runAllRestores();
|
|
41
|
+
throw reason;
|
|
42
|
+
});
|
|
43
|
+
}
|
package/dist/src/vite/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export { autoDynamicPagesPlugin, type AutoDynamicPagesPluginOptions } from "./auto_dynamic_pages_plugin.js";
|
|
2
|
+
export { autoLocaleParamsPlugin, type AutoLocaleParamsPluginOptions } from "./auto_locale_params_plugin.js";
|
|
2
3
|
export { buildIdAsset } from "./build_id_asset.js";
|
|
3
4
|
export { userAgentStubPlugin, USER_AGENT_STUB_ID, USER_AGENT_STUB_CODE } from "./user_agent_stub.js";
|
|
4
5
|
export { cfWorkersClientStubPlugin, CF_WORKERS_CLIENT_STUB_ID, CF_WORKERS_CLIENT_STUB_CODE } from "./cf_workers_client_stub.js";
|
|
5
6
|
export { vinextRouteWiringFixPlugin, patchAppPageRouteWiring, isAppPageRouteWiringFile, isAppPageRouteWiringAlreadyFixed, type VinextRouteWiringFixPluginOptions } from "./vinext_route_wiring_fix.js";
|
|
6
7
|
export { localeFilePlugin, resolveDefaultIntlConfigPath, type LocaleFilePluginOptions } from "./locale_file_plugin.js";
|
|
8
|
+
export { lucideOptimizerPlugin, detectLucideReact, resolveLucideEsmEntry, parseLucideIconMap, transformLucideImports, transformNextJsImports, type LucideOptimizerPluginOptions, } from "./lucide_optimizer_plugin.js";
|
|
7
9
|
export { cloudflareNextIntl, cloudflareNextIntlPlugin, type CloudflareNextIntlOptions, default } from "./plugin.js";
|
|
8
10
|
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";
|
package/dist/src/vite/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export { autoDynamicPagesPlugin } from "./auto_dynamic_pages_plugin.js";
|
|
2
|
+
export { autoLocaleParamsPlugin } from "./auto_locale_params_plugin.js";
|
|
2
3
|
export { buildIdAsset } from "./build_id_asset.js";
|
|
3
4
|
export { userAgentStubPlugin, USER_AGENT_STUB_ID, USER_AGENT_STUB_CODE } from "./user_agent_stub.js";
|
|
4
5
|
export { cfWorkersClientStubPlugin, CF_WORKERS_CLIENT_STUB_ID, CF_WORKERS_CLIENT_STUB_CODE } from "./cf_workers_client_stub.js";
|
|
5
6
|
export { vinextRouteWiringFixPlugin, patchAppPageRouteWiring, isAppPageRouteWiringFile, isAppPageRouteWiringAlreadyFixed } from "./vinext_route_wiring_fix.js";
|
|
6
7
|
export { localeFilePlugin, resolveDefaultIntlConfigPath } from "./locale_file_plugin.js";
|
|
8
|
+
export { lucideOptimizerPlugin, detectLucideReact, resolveLucideEsmEntry, parseLucideIconMap, transformLucideImports, transformNextJsImports, } from "./lucide_optimizer_plugin.js";
|
|
7
9
|
export { cloudflareNextIntl, cloudflareNextIntlPlugin, default } from "./plugin.js";
|
|
8
10
|
export { imageOptimizer, imageOptimizerPlugin, VIRTUAL_IMAGE_SHIM_ID, } from "../image_optimizer/index.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
export interface LucideOptimizerPluginOptions {
|
|
3
|
+
root?: string;
|
|
4
|
+
normalizeNextJsImports?: boolean;
|
|
5
|
+
lucideEntryPath?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const JS_EXT_RE: RegExp;
|
|
8
|
+
export declare const LUCIDE_IMPORT_RE: RegExp;
|
|
9
|
+
export declare const NEXT_JS_IMPORT_RE: RegExp;
|
|
10
|
+
export declare function detectLucideReact(root: string): boolean;
|
|
11
|
+
export declare function resolveLucideEsmEntry(root: string): string | null;
|
|
12
|
+
export declare function parseLucideIconMap(esmEntryPath: string): Map<string, string>;
|
|
13
|
+
export declare function transformLucideImports(code: string, iconMap: Map<string, string>): {
|
|
14
|
+
code: string;
|
|
15
|
+
changed: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare function transformNextJsImports(code: string): {
|
|
18
|
+
code: string;
|
|
19
|
+
changed: boolean;
|
|
20
|
+
};
|
|
21
|
+
export declare function lucideOptimizerPlugin(options?: LucideOptimizerPluginOptions): Plugin;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
export const JS_EXT_RE = /\.[cm]?[jt]sx?$/;
|
|
5
|
+
export const LUCIDE_IMPORT_RE = /import\s+(?:type\s+)?\{([^}]+)\}\s+from\s*['"]lucide-react['"];?/g;
|
|
6
|
+
export const NEXT_JS_IMPORT_RE = /(['"])next\/([a-zA-Z0-9_-]+)\.js\1/g;
|
|
7
|
+
export function detectLucideReact(root) {
|
|
8
|
+
try {
|
|
9
|
+
const req = createRequire(path.join(root, "package.json"));
|
|
10
|
+
req.resolve("lucide-react");
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return fs.existsSync(path.join(root, "node_modules", "lucide-react"));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function resolveLucideEsmEntry(root) {
|
|
18
|
+
try {
|
|
19
|
+
const req = createRequire(path.join(root, "package.json"));
|
|
20
|
+
const pkgJsonPath = req.resolve("lucide-react/package.json");
|
|
21
|
+
const dir = path.dirname(pkgJsonPath);
|
|
22
|
+
const esm = path.join(dir, "dist", "esm", "lucide-react.mjs");
|
|
23
|
+
if (fs.existsSync(esm))
|
|
24
|
+
return esm;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
const fallback = path.join(root, "node_modules", "lucide-react", "dist", "esm", "lucide-react.mjs");
|
|
28
|
+
if (fs.existsSync(fallback))
|
|
29
|
+
return fallback;
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
export function parseLucideIconMap(esmEntryPath) {
|
|
34
|
+
const iconMap = new Map();
|
|
35
|
+
try {
|
|
36
|
+
const content = fs.readFileSync(esmEntryPath, "utf8");
|
|
37
|
+
const exportRegex = /export\s*\{\s*([^}]+)\s*\}\s*from\s*['"](\.\/icons\/[^'"]+)['"];/g;
|
|
38
|
+
let match;
|
|
39
|
+
while ((match = exportRegex.exec(content)) !== null) {
|
|
40
|
+
const [, specifiers, file] = match;
|
|
41
|
+
const normalizedFile = file.replace(/^\.\//, "lucide-react/dist/esm/");
|
|
42
|
+
for (const part of specifiers.split(",")) {
|
|
43
|
+
const m = part.trim().match(/(?:(\w+)\s+as\s+)?(\w+)$/);
|
|
44
|
+
if (m)
|
|
45
|
+
iconMap.set(m[2], normalizedFile);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
iconMap.set("LucideProvider", "lucide-react/dist/esm/context.mjs");
|
|
49
|
+
iconMap.set("useLucideContext", "lucide-react/dist/esm/context.mjs");
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
}
|
|
53
|
+
return iconMap;
|
|
54
|
+
}
|
|
55
|
+
export function transformLucideImports(code, iconMap) {
|
|
56
|
+
if (!code.includes("lucide-react") || iconMap.size === 0) {
|
|
57
|
+
return { code, changed: false };
|
|
58
|
+
}
|
|
59
|
+
let changed = false;
|
|
60
|
+
const replaced = code.replace(new RegExp(LUCIDE_IMPORT_RE), (_match, specifiersStr) => {
|
|
61
|
+
const clean = specifiersStr
|
|
62
|
+
.replace(/\/\/[^\n]*/g, "")
|
|
63
|
+
.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
64
|
+
const parts = clean
|
|
65
|
+
.split(",")
|
|
66
|
+
.map((s) => s.trim())
|
|
67
|
+
.filter(Boolean);
|
|
68
|
+
const newImports = [];
|
|
69
|
+
const remaining = [];
|
|
70
|
+
for (const part of parts) {
|
|
71
|
+
if (part.startsWith("type ")) {
|
|
72
|
+
remaining.push(part);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const m = part.match(/^(\w+)(?:\s+as\s+(\w+))?$/);
|
|
76
|
+
if (m) {
|
|
77
|
+
const [, imported, local] = m;
|
|
78
|
+
const iconPath = iconMap.get(imported);
|
|
79
|
+
if (iconPath) {
|
|
80
|
+
newImports.push(`import ${local || imported} from "${iconPath}";`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
remaining.push(part);
|
|
85
|
+
}
|
|
86
|
+
if (remaining.length > 0) {
|
|
87
|
+
newImports.push(`import { ${remaining.join(", ")} } from "lucide-react";`);
|
|
88
|
+
}
|
|
89
|
+
return newImports.join("\n");
|
|
90
|
+
});
|
|
91
|
+
if (replaced !== code) {
|
|
92
|
+
changed = true;
|
|
93
|
+
}
|
|
94
|
+
return { code: replaced, changed };
|
|
95
|
+
}
|
|
96
|
+
export function transformNextJsImports(code) {
|
|
97
|
+
if (!code.includes("next/") || !code.includes(".js")) {
|
|
98
|
+
return { code, changed: false };
|
|
99
|
+
}
|
|
100
|
+
const replaced = code.replace(new RegExp(NEXT_JS_IMPORT_RE), "$1next/$2$1");
|
|
101
|
+
return { code: replaced, changed: replaced !== code };
|
|
102
|
+
}
|
|
103
|
+
export function lucideOptimizerPlugin(options = {}) {
|
|
104
|
+
let resolvedRoot = options.root ?? process.cwd();
|
|
105
|
+
let isLucidePresent = false;
|
|
106
|
+
let iconMap = new Map();
|
|
107
|
+
const normalizeNext = options.normalizeNextJsImports ?? true;
|
|
108
|
+
return {
|
|
109
|
+
name: "cloudflare-next-intl-lucide-optimizer",
|
|
110
|
+
enforce: "pre",
|
|
111
|
+
config(config) {
|
|
112
|
+
const root = config.root || resolvedRoot;
|
|
113
|
+
resolvedRoot = root;
|
|
114
|
+
isLucidePresent = detectLucideReact(root);
|
|
115
|
+
if (isLucidePresent) {
|
|
116
|
+
const entry = options.lucideEntryPath ?? resolveLucideEsmEntry(root);
|
|
117
|
+
if (entry) {
|
|
118
|
+
iconMap = parseLucideIconMap(entry);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const vinextHeadersShim = path.join(root, "node_modules", "vinext", "dist", "shims", "headers.js");
|
|
122
|
+
const hasVinextHeaders = fs.existsSync(vinextHeadersShim);
|
|
123
|
+
const aliasEntries = [];
|
|
124
|
+
if (hasVinextHeaders) {
|
|
125
|
+
aliasEntries.push({
|
|
126
|
+
find: /^next\/headers(\.js)?$/,
|
|
127
|
+
replacement: vinextHeadersShim,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
if (normalizeNext) {
|
|
131
|
+
aliasEntries.push({
|
|
132
|
+
find: /^next\/(.+)\.js$/,
|
|
133
|
+
replacement: "next/$1",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
resolve: {
|
|
138
|
+
alias: aliasEntries,
|
|
139
|
+
},
|
|
140
|
+
optimizeDeps: {
|
|
141
|
+
include: [
|
|
142
|
+
"next/dynamic",
|
|
143
|
+
"next/link",
|
|
144
|
+
"next/navigation",
|
|
145
|
+
"next/image",
|
|
146
|
+
],
|
|
147
|
+
exclude: [
|
|
148
|
+
"next/server",
|
|
149
|
+
"next/headers",
|
|
150
|
+
...(isLucidePresent ? ["lucide-react"] : []),
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
},
|
|
155
|
+
configResolved(config) {
|
|
156
|
+
if (config.root) {
|
|
157
|
+
resolvedRoot = config.root;
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
transform(code, id) {
|
|
161
|
+
const cleanId = id.split("?")[0];
|
|
162
|
+
if (!JS_EXT_RE.test(cleanId) || cleanId.includes("node_modules/lucide-react")) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
if (cleanId.includes("node_modules") && !cleanId.includes("cloudflare-next-intl")) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
let transformed = code;
|
|
169
|
+
let hasChange = false;
|
|
170
|
+
if (isLucidePresent && iconMap.size > 0) {
|
|
171
|
+
const res = transformLucideImports(transformed, iconMap);
|
|
172
|
+
if (res.changed) {
|
|
173
|
+
transformed = res.code;
|
|
174
|
+
hasChange = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (normalizeNext) {
|
|
178
|
+
const res = transformNextJsImports(transformed);
|
|
179
|
+
if (res.changed) {
|
|
180
|
+
transformed = res.code;
|
|
181
|
+
hasChange = true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (!hasChange) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
return { code: transformed, map: null };
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
@@ -2,8 +2,11 @@ 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 AutoLocaleParamsPluginOptions } from "./auto_locale_params_plugin.js";
|
|
5
6
|
import { type VinextRouteWiringFixPluginOptions } from "./vinext_route_wiring_fix.js";
|
|
7
|
+
import { type LucideOptimizerPluginOptions } from "./lucide_optimizer_plugin.js";
|
|
6
8
|
export interface CloudflareNextIntlOptions extends LocaleFilePluginOptions {
|
|
9
|
+
lucideOptimizer?: boolean | LucideOptimizerPluginOptions;
|
|
7
10
|
autoDynamicPages?: boolean | AutoDynamicPagesPluginOptions;
|
|
8
11
|
buildIdAsset?: boolean | string;
|
|
9
12
|
localeFiles?: boolean;
|
|
@@ -11,6 +14,7 @@ export interface CloudflareNextIntlOptions extends LocaleFilePluginOptions {
|
|
|
11
14
|
cfWorkersClientStub?: boolean;
|
|
12
15
|
imageOptimizer?: boolean | ImageOptimizerPluginOptions;
|
|
13
16
|
vinextRouteWiringFix?: boolean | VinextRouteWiringFixPluginOptions;
|
|
17
|
+
autoLocaleParams?: boolean | AutoLocaleParamsPluginOptions;
|
|
14
18
|
}
|
|
15
19
|
export declare function cloudflareNextIntl(options?: CloudflareNextIntlOptions): Plugin[];
|
|
16
20
|
export declare const cloudflareNextIntlPlugin: typeof cloudflareNextIntl;
|
package/dist/src/vite/plugin.js
CHANGED
|
@@ -4,9 +4,21 @@ 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 { autoLocaleParamsPlugin } from "./auto_locale_params_plugin.js";
|
|
7
8
|
import { vinextRouteWiringFixPlugin } from "./vinext_route_wiring_fix.js";
|
|
9
|
+
import { lucideOptimizerPlugin } from "./lucide_optimizer_plugin.js";
|
|
8
10
|
export function cloudflareNextIntl(options = {}) {
|
|
9
11
|
const plugins = [];
|
|
12
|
+
if (options.lucideOptimizer !== false) {
|
|
13
|
+
plugins.push(lucideOptimizerPlugin(typeof options.lucideOptimizer === "object"
|
|
14
|
+
? options.lucideOptimizer
|
|
15
|
+
: { root: options.root }));
|
|
16
|
+
}
|
|
17
|
+
if (options.autoLocaleParams !== false) {
|
|
18
|
+
plugins.push(autoLocaleParamsPlugin(typeof options.autoLocaleParams === "object"
|
|
19
|
+
? options.autoLocaleParams
|
|
20
|
+
: undefined));
|
|
21
|
+
}
|
|
10
22
|
if (options.autoDynamicPages !== false) {
|
|
11
23
|
plugins.push(autoDynamicPagesPlugin(typeof options.autoDynamicPages === "object"
|
|
12
24
|
? options.autoDynamicPages
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync, rmSync } from "node:fs";
|
|
2
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*\}/;
|
|
3
|
+
const PREFETCH_LOADING_FN_RE = /function\s+getPrefetchLoadingEntry\s*\(\s*route\s*\)\s*\{[\s\S]*?firstNestedEntry[\s\S]*?route\.loadings[\s\S]*?return\s+getDefaultExport\s*\(\s*route\.loading\s*\)\s*\?[\s\S]*?:\s*null\s*;\s*\}/;
|
|
4
4
|
const FIXED_PREFETCH_LOADING_FN = `function getPrefetchLoadingEntry(route) {
|
|
5
5
|
let rootEntry = null;
|
|
6
6
|
let deepestNestedEntry = null;
|
|
@@ -29,7 +29,8 @@ const FIXED_PREFETCH_LOADING_FN = `function getPrefetchLoadingEntry(route) {
|
|
|
29
29
|
const ROUTE_LOADING_GUARD_RE = /if\s*\(\s*!isPrefetchLoadingShell\s*&&\s*treePosition\s*<\s*routeSegments\.length\s*\)\s*\{/g;
|
|
30
30
|
const FIXED_ROUTE_LOADING_GUARD = "if (!isPrefetchLoadingShell && treePosition < routeSegments.length && !routeLoadingComponent) {";
|
|
31
31
|
export function isAppPageRouteWiringAlreadyFixed(code) {
|
|
32
|
-
const hasBuggyPrefetch = code.includes("firstNestedEntry") &&
|
|
32
|
+
const hasBuggyPrefetch = code.includes("firstNestedEntry") &&
|
|
33
|
+
PREFETCH_LOADING_FN_RE.test(code);
|
|
33
34
|
const hasBuggySuspense = !code.includes("!routeLoadingComponent") && ROUTE_LOADING_GUARD_RE.test(code);
|
|
34
35
|
return !hasBuggyPrefetch && !hasBuggySuspense;
|
|
35
36
|
}
|
|
@@ -38,8 +39,10 @@ export function patchAppPageRouteWiring(code) {
|
|
|
38
39
|
return code;
|
|
39
40
|
}
|
|
40
41
|
let result = code;
|
|
41
|
-
const hasBuggyPrefetch = code.includes("firstNestedEntry") &&
|
|
42
|
-
|
|
42
|
+
const hasBuggyPrefetch = code.includes("firstNestedEntry") &&
|
|
43
|
+
!result.includes("deepestNestedEntry") &&
|
|
44
|
+
PREFETCH_LOADING_FN_RE.test(result);
|
|
45
|
+
if (hasBuggyPrefetch) {
|
|
43
46
|
result = result.replace(PREFETCH_LOADING_FN_RE, FIXED_PREFETCH_LOADING_FN);
|
|
44
47
|
}
|
|
45
48
|
const hasBuggySuspense = !result.includes("!routeLoadingComponent") && ROUTE_LOADING_GUARD_RE.test(result);
|
|
@@ -53,13 +56,20 @@ export function isRouteMatchingFile(id) {
|
|
|
53
56
|
return cleanId.endsWith("/routing/route-matching.js") || cleanId.endsWith("/routing/route-matching.ts");
|
|
54
57
|
}
|
|
55
58
|
export function isRouteMatchingAlreadyFixed(code) {
|
|
56
|
-
|
|
59
|
+
if (code.includes("hasLeadingLocaleParam")) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
const hasUpstreamLocaleMatch = code.includes(":locale") &&
|
|
63
|
+
(code.includes("activeLocale") || code.includes("getActiveRouteLocale") || code.includes("matchWithLocale") || code.includes("localeMatch")) &&
|
|
64
|
+
/function\s+matchRouteWithTrie[\s\S]*?:locale/.test(code);
|
|
65
|
+
return Boolean(hasUpstreamLocaleMatch);
|
|
57
66
|
}
|
|
58
|
-
const
|
|
59
|
-
const FIXED_MATCH_ROUTE_WITH_TRIE = `function getActiveRouteLocale() {
|
|
67
|
+
const GET_ACTIVE_ROUTE_LOCALE_FN = `function getActiveRouteLocale() {
|
|
60
68
|
return (typeof document !== "undefined" && (document.documentElement?.lang || document.cookie.match(/__user_locale_key__=([^;]+)/)?.[1])) || (typeof window !== "undefined" && window.__VINEXT_LOCALE__) || "en";
|
|
61
69
|
}
|
|
62
|
-
|
|
70
|
+
`;
|
|
71
|
+
const MATCH_ROUTE_WITH_TRIE_RE = /function\s+matchRouteWithTrie\s*\(\s*url\s*,\s*routes\s*,\s*cache\s*\)\s*\{[\s\S]*?normalizePathnameForRouteMatch[\s\S]*?getOrBuildTrie\(\s*cache\s*,\s*routes\s*\)\s*;?\s*\n\s*return\s+trieMatch\(\s*trie\s*,\s*urlParts\s*\)\s*;?\s*\}/;
|
|
72
|
+
const FIXED_MATCH_ROUTE_WITH_TRIE_BODY = `function matchRouteWithTrie(url, routes, cache) {
|
|
63
73
|
const pathname = url.split("?")[0];
|
|
64
74
|
let normalizedUrl = pathname === "/" ? "/" : pathname.replace(/\\/$/, "");
|
|
65
75
|
normalizedUrl = normalizePathnameForRouteMatch(normalizedUrl);
|
|
@@ -75,7 +85,7 @@ function matchRouteWithTrie(url, routes, cache) {
|
|
|
75
85
|
}
|
|
76
86
|
return trieMatch(trie, urlParts);
|
|
77
87
|
}`;
|
|
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\(
|
|
88
|
+
const MATCH_ROUTE_WITH_TRIE_RAW_RE = /function\s+matchRouteWithTrieRawPathname\s*\(\s*url\s*,\s*routes\s*,\s*cache\s*\)\s*\{[\s\S]*?urlParts\s*=[\s\S]*?return\s+trieMatch\(\s*(?:trie|getOrBuildTrie\(\s*cache\s*,\s*routes\s*\))\s*,\s*urlParts\s*\)\s*;?\s*\}/;
|
|
79
89
|
const FIXED_MATCH_ROUTE_WITH_TRIE_RAW = `function matchRouteWithTrieRawPathname(url, routes, cache) {
|
|
80
90
|
const pathname = url.split("?")[0];
|
|
81
91
|
const urlParts = (pathname === "/" ? "/" : pathname.replace(/\\/$/, "")).split("/").filter(Boolean);
|
|
@@ -95,11 +105,17 @@ export function patchRouteMatching(code) {
|
|
|
95
105
|
return code;
|
|
96
106
|
}
|
|
97
107
|
let result = code;
|
|
98
|
-
if (MATCH_ROUTE_WITH_TRIE_RE.test(result)) {
|
|
99
|
-
|
|
108
|
+
if (!result.includes("hasLeadingLocaleParam") && MATCH_ROUTE_WITH_TRIE_RE.test(result)) {
|
|
109
|
+
const replacement = result.includes("function getActiveRouteLocale")
|
|
110
|
+
? FIXED_MATCH_ROUTE_WITH_TRIE_BODY
|
|
111
|
+
: `${GET_ACTIVE_ROUTE_LOCALE_FN}${FIXED_MATCH_ROUTE_WITH_TRIE_BODY}`;
|
|
112
|
+
result = result.replace(MATCH_ROUTE_WITH_TRIE_RE, replacement);
|
|
100
113
|
}
|
|
101
|
-
if (MATCH_ROUTE_WITH_TRIE_RAW_RE.test(result)) {
|
|
102
|
-
|
|
114
|
+
if (!result.includes("hasLeadingLocaleParam") && MATCH_ROUTE_WITH_TRIE_RAW_RE.test(result)) {
|
|
115
|
+
const replacement = result.includes("function getActiveRouteLocale")
|
|
116
|
+
? FIXED_MATCH_ROUTE_WITH_TRIE_RAW
|
|
117
|
+
: `${GET_ACTIVE_ROUTE_LOCALE_FN}${FIXED_MATCH_ROUTE_WITH_TRIE_RAW}`;
|
|
118
|
+
result = result.replace(MATCH_ROUTE_WITH_TRIE_RAW_RE, replacement);
|
|
103
119
|
}
|
|
104
120
|
return result;
|
|
105
121
|
}
|
|
@@ -111,13 +127,17 @@ export function isOptimisticRoutingAlreadyFixed(code) {
|
|
|
111
127
|
const hasLocalePrefixFirst = code.includes("hasLeadingLocaleParam") &&
|
|
112
128
|
code.indexOf("hasLeadingLocaleParam") < code.indexOf("const match = matchNode(trie, urlParts.normalized");
|
|
113
129
|
const hasRawPartsFix = code.includes("options.rawUrlParts[0] !== options.match.params.locale");
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
130
|
+
if (hasLocalePrefixFirst && hasRawPartsFix) {
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
const hasUpstreamLocaleMatch = code.includes(":locale") &&
|
|
134
|
+
(code.includes("activeLocale") || code.includes("getActiveRouteLocale") || code.includes("localeMatch")) &&
|
|
135
|
+
/function\s+matchOptimisticRouteManifestRoute[\s\S]*?:locale/.test(code);
|
|
136
|
+
const hasUpstreamRawPartsFix = /function\s+resolveOptimisticNavigationParams[\s\S]*?:locale/.test(code);
|
|
137
|
+
return Boolean(hasUpstreamLocaleMatch && hasUpstreamRawPartsFix);
|
|
119
138
|
}
|
|
120
|
-
function
|
|
139
|
+
const MATCH_OPTIMISTIC_ROUTE_RE = /function\s+matchOptimisticRouteManifestRoute\s*\(\s*options\s*\)\s*\{[\s\S]*?hrefToRouteParts\(\s*options\.href\s*,\s*options\.basePath\s*\)[\s\S]*?matchNode\([\s\S]*?urlParts\.normalized\s*,\s*0\s*,\s*\[\]\)[\s\S]*?decodeMatchedParams\(\s*match\.params\s*\)[\s\S]*?\n\}/;
|
|
140
|
+
const FIXED_MATCH_OPTIMISTIC_ROUTE_BODY = `function matchOptimisticRouteManifestRoute(options) {
|
|
121
141
|
const urlParts = hrefToRouteParts(options.href, options.basePath);
|
|
122
142
|
if (urlParts === null) return null;
|
|
123
143
|
const trie = getRouteTrie(options.routeManifest);
|
|
@@ -151,7 +171,10 @@ export function patchOptimisticRouting(code) {
|
|
|
151
171
|
}
|
|
152
172
|
let result = code;
|
|
153
173
|
if (!result.includes("hasLeadingLocaleParam") && MATCH_OPTIMISTIC_ROUTE_RE.test(result)) {
|
|
154
|
-
|
|
174
|
+
const replacement = result.includes("function getActiveRouteLocale")
|
|
175
|
+
? FIXED_MATCH_OPTIMISTIC_ROUTE_BODY
|
|
176
|
+
: `${GET_ACTIVE_ROUTE_LOCALE_FN}${FIXED_MATCH_OPTIMISTIC_ROUTE_BODY}`;
|
|
177
|
+
result = result.replace(MATCH_OPTIMISTIC_ROUTE_RE, replacement);
|
|
155
178
|
}
|
|
156
179
|
if (!result.includes("options.rawUrlParts[0] !== options.match.params.locale") && RESOLVE_OPTIMISTIC_NAV_PARAMS_RE.test(result)) {
|
|
157
180
|
result = result.replace(RESOLVE_OPTIMISTIC_NAV_PARAMS_RE, FIXED_RESOLVE_OPTIMISTIC_NAV_PARAMS);
|
|
@@ -165,9 +188,16 @@ export function isPrefetchLearningFile(id) {
|
|
|
165
188
|
export function isPrefetchLearningAlreadyFixed(code) {
|
|
166
189
|
const hasFixedFunction = code.includes("stripRsc(parsePrefetchCacheKey(cacheKey).rscUrl)") && code.includes("hasOptimisticTemplate");
|
|
167
190
|
const hasFixedCallSite = code.includes("targetHref: currentHref,") && code.includes("targetRscUrl: rscUrl,") && !LEARN_TEMPLATES_CALL_RE.test(code);
|
|
168
|
-
|
|
191
|
+
if (hasFixedFunction && hasFixedCallSite) {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
const hasBuggySkip = /if\s*\(\s*!isSettledPrefetchCacheEntry\(\s*entry\s*\)\s*\)\s*continue\s*;/.test(code);
|
|
195
|
+
if (!hasBuggySkip && code.includes("learnOptimisticRouteTemplatesFromPrefetchCache")) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
169
199
|
}
|
|
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*\)
|
|
200
|
+
const LEARN_TEMPLATES_FN_RE = /async\s+function\s+learnOptimisticRouteTemplatesFromPrefetchCache\s*\(\s*options\s*\)\s*\{[\s\S]*?getPrefetchCache\(\)[\s\S]*?if\s*\(\s*!isSettledPrefetchCacheEntry\(\s*entry\s*\)\s*\)\s*continue\s*;[\s\S]*?learnOptimisticRouteTemplateFromPrefetch[\s\S]*?await\s+Promise\.allSettled\(\s*learning\s*\)\s*;?\s*\}/;
|
|
171
201
|
const FIXED_LEARN_TEMPLATES_FN = `async function learnOptimisticRouteTemplatesFromPrefetchCache(options) {
|
|
172
202
|
if (options.routeManifest === null) return;
|
|
173
203
|
const hasOptimisticTemplate = options.targetHref !== void 0 && resolveOptimisticNavigationPayload({
|
|
@@ -241,10 +271,15 @@ export function patchPrefetchLearning(code) {
|
|
|
241
271
|
return code;
|
|
242
272
|
}
|
|
243
273
|
let result = code;
|
|
244
|
-
|
|
274
|
+
const hasBuggyFn = !result.includes("hasOptimisticTemplate") &&
|
|
275
|
+
!result.includes("isPendingNavigationTarget") &&
|
|
276
|
+
LEARN_TEMPLATES_FN_RE.test(result);
|
|
277
|
+
const hasFixedFunction = result.includes("stripRsc(parsePrefetchCacheKey(cacheKey).rscUrl)") &&
|
|
278
|
+
result.includes("hasOptimisticTemplate");
|
|
279
|
+
if (hasBuggyFn) {
|
|
245
280
|
result = result.replace(LEARN_TEMPLATES_FN_RE, FIXED_LEARN_TEMPLATES_FN);
|
|
246
281
|
}
|
|
247
|
-
if (LEARN_TEMPLATES_CALL_RE.test(result)) {
|
|
282
|
+
if ((hasBuggyFn || hasFixedFunction) && LEARN_TEMPLATES_CALL_RE.test(result)) {
|
|
248
283
|
result = result.replace(LEARN_TEMPLATES_CALL_RE, FIXED_LEARN_TEMPLATES_CALL);
|
|
249
284
|
}
|
|
250
285
|
return result;
|
|
@@ -386,6 +421,9 @@ export function vinextRouteWiringFixPlugin(options = {}) {
|
|
|
386
421
|
return;
|
|
387
422
|
}
|
|
388
423
|
const patched = patchAppPageRouteWiring(code);
|
|
424
|
+
if (patched === code) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
389
427
|
return {
|
|
390
428
|
code: patched,
|
|
391
429
|
map: null,
|
|
@@ -396,6 +434,9 @@ export function vinextRouteWiringFixPlugin(options = {}) {
|
|
|
396
434
|
return;
|
|
397
435
|
}
|
|
398
436
|
const patched = patchRouteMatching(code);
|
|
437
|
+
if (patched === code) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
399
440
|
return {
|
|
400
441
|
code: patched,
|
|
401
442
|
map: null,
|
|
@@ -406,6 +447,9 @@ export function vinextRouteWiringFixPlugin(options = {}) {
|
|
|
406
447
|
return;
|
|
407
448
|
}
|
|
408
449
|
const patched = patchPrefetchLearning(code);
|
|
450
|
+
if (patched === code) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
409
453
|
return {
|
|
410
454
|
code: patched,
|
|
411
455
|
map: null,
|
|
@@ -416,6 +460,9 @@ export function vinextRouteWiringFixPlugin(options = {}) {
|
|
|
416
460
|
return;
|
|
417
461
|
}
|
|
418
462
|
const patched = patchOptimisticRouting(code);
|
|
463
|
+
if (patched === code) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
419
466
|
return {
|
|
420
467
|
code: patched,
|
|
421
468
|
map: null,
|
package/llms.txt
CHANGED
|
@@ -27,7 +27,9 @@ other subpath can be used.
|
|
|
27
27
|
- `./db` — `withPublicDb(fn)` / `withUserDb(fn, uid?)` server-side Postgres/Drizzle context helpers (require `db` set on your `RoutingConfig`; direct Postgres or Supabase Data API with automatic PostgREST REST translation and `cfni_exec` fallback, see below).
|
|
28
28
|
- `./dbEslint` — flat-config ESLint fragment banning direct `@supabase/supabase-js`, `pg`, `postgres`, and deep `dist/` imports in application code.
|
|
29
29
|
- `./dbHelpers` — generic Drizzle SQL helper functions (`excluded`, `onConflictSet`, `ago`, `currentDate`, `windowCount`, `unnestLateral`, `ascNullsLast`, `alwaysTrue`, `lateral`, `aliasColumn`, `minOf`, `maxOf`, `roundReal`, `multiply`, `scalarFromCte`) for use with `./db`.
|
|
30
|
-
- `./vite` — `cloudflareNextIntl(options?)` / `cloudflareNextIntlPlugin`, `imageOptimizerPlugin(options?)` / `imageOptimizer`, `buildIdAsset(fileName?)`, `localeFilePlugin(options?)`, `userAgentStubPlugin()`, `cfWorkersClientStubPlugin()`, `vinextRouteWiringFixPlugin(options?)`: All-in-one Vite plugin required for Vinext/Cloudflare Workers environments (bundles `@locale-file/*` via eager glob, resolves `@intl-config`, stubs Node.js `user-agent` to prevent runtime `node:fs` errors, stubs `cloudflare:workers` for client builds, emits client `BUILD_ID`, runs build-time/dev Image Optimizer with Next.js blur placeholder shimming,
|
|
30
|
+
- `./vite` — `cloudflareNextIntl(options?)` / `cloudflareNextIntlPlugin`, `imageOptimizerPlugin(options?)` / `imageOptimizer`, `autoLocaleParamsPlugin(options?)`, `buildIdAsset(fileName?)`, `localeFilePlugin(options?)`, `userAgentStubPlugin()`, `cfWorkersClientStubPlugin()`, `vinextRouteWiringFixPlugin(options?)`, `lucideOptimizerPlugin(options?)`: All-in-one Vite plugin required for Vinext/Cloudflare Workers environments (bundles `@locale-file/*` via eager glob, resolves `@intl-config`, stubs Node.js `user-agent` to prevent runtime `node:fs` errors, stubs `cloudflare:workers` for client builds, emits client `BUILD_ID`, runs build-time/dev Image Optimizer with Next.js blur placeholder shimming, fixes vinext route wiring/matching/non-blocking optimistic prefetch learning, auto-inserts locale params for pages reading locale from cookies, and rewrites `lucide-react` imports to deep icon paths). Also wraps `checkDynamicPages`/`checkLocaleParams` (see `./checkDynamicPages` / `./checkLocaleParams`), running `autoLocaleParams` before `autoDynamicPages` so a page whose locale param this fixes no longer trips the cookie-derived-locale dynamic signal.
|
|
31
|
+
- `./checkDynamicPages` — `checkDynamicPages(options, io?)`: standalone SSG-eligibility scanner/fixer for `page`/`route` files (text-heuristic, transitive local-import following, capped/cycle-safe). Modes `"off" | "report" | "fix"`. Also usable as the `cfni-check-dynamic-pages` CLI bin.
|
|
32
|
+
- `./checkLocaleParams` — `checkLocaleParams(options, io?)`: standalone scanner/fixer for `page`/`layout`/`loading` files under a `[locale]`-scoped route that call `getTranslations()`/`useTranslations()` without a `locale` param or `setLocale()` call (the source of a hidden cookie-derived-locale dependency). Modes `"off" | "report" | "fix"`; options include `appDir`, `localeParam` (default `"locale"`), `skip`, `overrides`. Also usable as the `cfni-check-locale-params` CLI bin.
|
|
31
33
|
- `./image-optimizer` / `./imageOptimizer` — image optimization suite: `imageOptimizerPlugin`, `imageOptimizer`, `resolveOptions`, `resolveImageConfig`, `resolveBlurOptions`, `processImage`, `makeBlurDataURL`, `getImageBlurSvg`, `renderManifest`, `writeManifest`, `isFresh`, `loadCache`, `saveCache`, `collectImages`, `run`.
|
|
32
34
|
- `./errorHandling` — error reporting & stale deploy recovery barrel: `reportError`, `withErrorHandling`, `installConsoleErrorOverride`, `installGlobalErrorOverride`, `stringifyUnknown`, `formatErrorMessage`, `defaultIgnoredConsoleErrors`, `createServerErrorAction`, `isStaleDeployError`, `defaultStaleDeployPatterns`, `setStaleDeployPatterns`, `getStaleDeployPatterns`, `clearClientCache`, `useStaleDeployRecovery`, `shouldRecoverFromStaleDeploy`, `isRecentBuild`.
|
|
33
35
|
- `./isStaleDeployError` — `isStaleDeployError(error, patterns?)`, `setStaleDeployPatterns(patterns)`, `getStaleDeployPatterns()`: detector returning `true` for version skew / chunk load / dynamic import / server action 404 / hydration errors (ChunkLoadError, UnrecognizedActionError, server action not found, failed to fetch, dynamically imported module failure, loading CSS chunk, connection closed, RSC payload failure, minified error #412, or missing stream error `undefined`) with fast pre-lowercased pattern cache and intl-config integration (`errorHandling.staleDeployPatterns`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloudflare-next-intl",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.49",
|
|
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",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"cfni-db-install-exec": "bin/db_install_exec.mjs",
|
|
12
12
|
"cfni-image-optimizer": "bin/image_optimizer.mjs",
|
|
13
13
|
"optimize-images": "bin/image_optimizer.mjs",
|
|
14
|
-
"cfni-check-dynamic-pages": "bin/check_dynamic_pages.mjs"
|
|
14
|
+
"cfni-check-dynamic-pages": "bin/check_dynamic_pages.mjs",
|
|
15
|
+
"cfni-check-locale-params": "bin/check_locale_params.mjs"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"dist",
|
|
@@ -238,6 +239,10 @@
|
|
|
238
239
|
"types": "./dist/src/dynamic_pages_check/index.d.ts",
|
|
239
240
|
"import": "./dist/src/dynamic_pages_check/index.js"
|
|
240
241
|
},
|
|
242
|
+
"./checkLocaleParams": {
|
|
243
|
+
"types": "./dist/src/locale_params_check/index.d.ts",
|
|
244
|
+
"import": "./dist/src/locale_params_check/index.js"
|
|
245
|
+
},
|
|
241
246
|
"./db": {
|
|
242
247
|
"types": "./dist/src/db/index.d.ts",
|
|
243
248
|
"import": "./dist/src/db/index.js"
|