vinext 0.0.54 → 0.0.55
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 +1 -0
- package/dist/check.js +15 -3
- package/dist/check.js.map +1 -1
- package/dist/client/navigation-runtime.d.ts +1 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/client/navigation-runtime.js.map +1 -1
- package/dist/config/next-config.d.ts +14 -1
- package/dist/config/next-config.js +24 -4
- package/dist/config/next-config.js.map +1 -1
- package/dist/config/tsconfig-paths.d.ts +12 -3
- package/dist/config/tsconfig-paths.js +55 -24
- package/dist/config/tsconfig-paths.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts +2 -1
- package/dist/entries/app-rsc-entry.js +12 -0
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-rsc-manifest.js +22 -5
- package/dist/entries/app-rsc-manifest.js.map +1 -1
- package/dist/entries/pages-server-entry.js +41 -4
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/index.js +81 -39
- package/dist/index.js.map +1 -1
- package/dist/plugins/import-meta-url.d.ts +16 -0
- package/dist/plugins/import-meta-url.js +193 -0
- package/dist/plugins/import-meta-url.js.map +1 -0
- package/dist/server/app-browser-action-result.d.ts +9 -16
- package/dist/server/app-browser-action-result.js +25 -14
- package/dist/server/app-browser-action-result.js.map +1 -1
- package/dist/server/app-browser-entry.js +171 -45
- package/dist/server/app-browser-entry.js.map +1 -1
- package/dist/server/app-browser-mpa-navigation.d.ts +16 -0
- package/dist/server/app-browser-mpa-navigation.js +36 -0
- package/dist/server/app-browser-mpa-navigation.js.map +1 -0
- package/dist/server/app-browser-popstate.d.ts +3 -1
- package/dist/server/app-browser-popstate.js +15 -1
- package/dist/server/app-browser-popstate.js.map +1 -1
- package/dist/server/app-browser-state.js +2 -1
- package/dist/server/app-browser-state.js.map +1 -1
- package/dist/server/app-layout-param-observation.d.ts +30 -0
- package/dist/server/app-layout-param-observation.js +130 -0
- package/dist/server/app-layout-param-observation.js.map +1 -0
- package/dist/server/app-page-boundary-render.js +2 -2
- package/dist/server/app-page-boundary-render.js.map +1 -1
- package/dist/server/app-page-dispatch.js +1 -1
- package/dist/server/app-page-params.d.ts +2 -1
- package/dist/server/app-page-params.js +14 -1
- package/dist/server/app-page-params.js.map +1 -1
- package/dist/server/app-page-probe.d.ts +12 -1
- package/dist/server/app-page-probe.js +116 -1
- package/dist/server/app-page-probe.js.map +1 -1
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-response.js.map +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +3 -2
- package/dist/server/app-rsc-cache-busting.js +9 -7
- package/dist/server/app-rsc-cache-busting.js.map +1 -1
- package/dist/server/app-rsc-handler.js +11 -1
- package/dist/server/app-rsc-handler.js.map +1 -1
- package/dist/server/app-segment-config.d.ts +1 -1
- package/dist/server/app-segment-config.js +4 -1
- package/dist/server/app-segment-config.js.map +1 -1
- package/dist/server/app-server-action-execution.d.ts +5 -0
- package/dist/server/app-server-action-execution.js +198 -22
- package/dist/server/app-server-action-execution.js.map +1 -1
- package/dist/server/artifact-compatibility.d.ts +2 -1
- package/dist/server/artifact-compatibility.js +10 -1
- package/dist/server/artifact-compatibility.js.map +1 -1
- package/dist/server/client-reuse-manifest.d.ts +9 -4
- package/dist/server/client-reuse-manifest.js +2 -1
- package/dist/server/client-reuse-manifest.js.map +1 -1
- package/dist/server/dev-server.js +52 -10
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/document-initial-head.d.ts +7 -0
- package/dist/server/document-initial-head.js +35 -0
- package/dist/server/document-initial-head.js.map +1 -0
- package/dist/server/pages-document-initial-props.d.ts +84 -2
- package/dist/server/pages-document-initial-props.js +127 -1
- package/dist/server/pages-document-initial-props.js.map +1 -1
- package/dist/server/pages-node-compat.js +1 -1
- package/dist/server/pages-page-response.d.ts +14 -0
- package/dist/server/pages-page-response.js +31 -8
- package/dist/server/pages-page-response.js.map +1 -1
- package/dist/server/prod-server.js +13 -6
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/skip-cache-proof.d.ts +23 -2
- package/dist/server/skip-cache-proof.js +81 -12
- package/dist/server/skip-cache-proof.js.map +1 -1
- package/dist/server/static-layout-client-reuse-proof.d.ts +16 -0
- package/dist/server/static-layout-client-reuse-proof.js +35 -0
- package/dist/server/static-layout-client-reuse-proof.js.map +1 -0
- package/dist/shims/cache.d.ts +21 -1
- package/dist/shims/cache.js +101 -6
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/document.d.ts +6 -0
- package/dist/shims/document.js +7 -8
- package/dist/shims/document.js.map +1 -1
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error-boundary.js +27 -28
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +16 -5
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/hash-scroll.d.ts +4 -1
- package/dist/shims/hash-scroll.js +13 -1
- package/dist/shims/hash-scroll.js.map +1 -1
- package/dist/shims/head-state.d.ts +1 -0
- package/dist/shims/head-state.js +18 -3
- package/dist/shims/head-state.js.map +1 -1
- package/dist/shims/head.d.ts +35 -1
- package/dist/shims/head.js +113 -14
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +56 -0
- package/dist/shims/internal/pages-data-fetch-dedup.js +70 -0
- package/dist/shims/internal/pages-data-fetch-dedup.js.map +1 -0
- package/dist/shims/link.js +28 -2
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/navigation.d.ts +39 -1
- package/dist/shims/navigation.js +61 -13
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/router.js +37 -17
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/thenable-params.d.ts +5 -2
- package/dist/shims/thenable-params.js +25 -1
- package/dist/shims/thenable-params.js.map +1 -1
- package/dist/shims/unified-request-context.js +3 -0
- package/dist/shims/unified-request-context.js.map +1 -1
- package/dist/utils/client-build-manifest.d.ts +15 -0
- package/dist/utils/client-build-manifest.js +54 -0
- package/dist/utils/client-build-manifest.js.map +1 -0
- package/dist/utils/hash.js +1 -1
- package/dist/utils/hash.js.map +1 -1
- package/dist/utils/lazy-chunks.d.ts +1 -1
- package/dist/utils/lazy-chunks.js.map +1 -1
- package/dist/utils/vite-version.d.ts +11 -0
- package/dist/utils/vite-version.js +36 -0
- package/dist/utils/vite-version.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Plugin } from "vite";
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
|
|
4
|
+
//#region src/plugins/import-meta-url.d.ts
|
|
5
|
+
type ImportMetaUrlEnvironment = "client" | "server";
|
|
6
|
+
type RewriteResult = {
|
|
7
|
+
code: string;
|
|
8
|
+
map: ReturnType<MagicString["generateMap"]>;
|
|
9
|
+
};
|
|
10
|
+
declare function createImportMetaUrlPlugin(options: {
|
|
11
|
+
getRoot: () => string | undefined;
|
|
12
|
+
}): Plugin;
|
|
13
|
+
declare function rewriteImportMetaUrl(code: string, id: string, root: string, environment: ImportMetaUrlEnvironment): RewriteResult | null;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { createImportMetaUrlPlugin, rewriteImportMetaUrl };
|
|
16
|
+
//# sourceMappingURL=import-meta-url.d.ts.map
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { normalizePath, parseAst } from "vite";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import MagicString from "magic-string";
|
|
6
|
+
//#region src/plugins/import-meta-url.ts
|
|
7
|
+
const TRANSFORMABLE_SCRIPT_EXTENSIONS = new Set([
|
|
8
|
+
".cjs",
|
|
9
|
+
".cts",
|
|
10
|
+
".js",
|
|
11
|
+
".jsx",
|
|
12
|
+
".mjs",
|
|
13
|
+
".mts",
|
|
14
|
+
".ts",
|
|
15
|
+
".tsx"
|
|
16
|
+
]);
|
|
17
|
+
function createImportMetaUrlPlugin(options) {
|
|
18
|
+
let rootPaths;
|
|
19
|
+
let outputDirs = [];
|
|
20
|
+
function getRootPaths() {
|
|
21
|
+
const root = options.getRoot();
|
|
22
|
+
if (!root) return rootPaths;
|
|
23
|
+
if (!rootPaths || rootPaths.root !== root) rootPaths = createRootPaths(root, { outputDirs });
|
|
24
|
+
return rootPaths;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
name: "vinext:import-meta-url",
|
|
28
|
+
enforce: "post",
|
|
29
|
+
configResolved(config) {
|
|
30
|
+
const root = options.getRoot() ?? config.root;
|
|
31
|
+
outputDirs = [config.build.outDir];
|
|
32
|
+
rootPaths = createRootPaths(root, { outputDirs });
|
|
33
|
+
},
|
|
34
|
+
transform(code, id) {
|
|
35
|
+
if (!mayContainImportMetaUrl(code)) return null;
|
|
36
|
+
const paths = getRootPaths();
|
|
37
|
+
if (!paths) return null;
|
|
38
|
+
const canonicalId = transformableModuleCanonicalId(cleanModuleId(id), paths);
|
|
39
|
+
if (!canonicalId) return null;
|
|
40
|
+
const rewritten = rewriteCanonicalImportMetaUrl(code, canonicalId, paths, this.environment?.name === "client" ? "client" : "server");
|
|
41
|
+
if (!rewritten) return null;
|
|
42
|
+
return {
|
|
43
|
+
code: rewritten.code,
|
|
44
|
+
map: rewritten.map
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function rewriteImportMetaUrl(code, id, root, environment) {
|
|
50
|
+
if (!mayContainImportMetaUrl(code)) return null;
|
|
51
|
+
return rewriteCanonicalImportMetaUrl(code, canonicalizePath(id), createRootPaths(root), environment);
|
|
52
|
+
}
|
|
53
|
+
function rewriteCanonicalImportMetaUrl(code, canonicalId, rootPaths, environment) {
|
|
54
|
+
let ast;
|
|
55
|
+
try {
|
|
56
|
+
ast = parseAst(code);
|
|
57
|
+
} catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const ranges = collectImportMetaUrlRanges(ast);
|
|
61
|
+
if (ranges.length === 0) return null;
|
|
62
|
+
const replacement = JSON.stringify(importMetaUrlValue(canonicalId, rootPaths, environment));
|
|
63
|
+
const output = new MagicString(code);
|
|
64
|
+
for (const range of ranges) output.overwrite(range.start, range.end, replacement);
|
|
65
|
+
return {
|
|
66
|
+
code: output.toString(),
|
|
67
|
+
map: output.generateMap({ hires: "boundary" })
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function cleanModuleId(id) {
|
|
71
|
+
return id.split("?", 1)[0];
|
|
72
|
+
}
|
|
73
|
+
function createRootPaths(root, options = {}) {
|
|
74
|
+
const canonicalRoot = canonicalizePath(root);
|
|
75
|
+
const normalizedRoot = normalizePath(canonicalRoot);
|
|
76
|
+
return {
|
|
77
|
+
root,
|
|
78
|
+
canonicalRoot,
|
|
79
|
+
normalizedRoot,
|
|
80
|
+
excludedRelativePrefixes: excludedRelativePrefixes(canonicalRoot, normalizedRoot, options)
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function transformableModuleCanonicalId(id, rootPaths) {
|
|
84
|
+
if (!id || id.startsWith("\0")) return null;
|
|
85
|
+
if (!path.isAbsolute(id)) return null;
|
|
86
|
+
const normalizedInputId = normalizePath(id);
|
|
87
|
+
if (normalizedInputId.includes("/node_modules/")) return null;
|
|
88
|
+
if (!TRANSFORMABLE_SCRIPT_EXTENSIONS.has(path.extname(normalizedInputId))) return null;
|
|
89
|
+
const canonicalId = canonicalizePath(id);
|
|
90
|
+
if (!isPathWithin(normalizePath(canonicalId), rootPaths.normalizedRoot)) return null;
|
|
91
|
+
if (isExcludedRelativePath(normalizePath(path.relative(rootPaths.canonicalRoot, canonicalId)), rootPaths.excludedRelativePrefixes)) return null;
|
|
92
|
+
return canonicalId;
|
|
93
|
+
}
|
|
94
|
+
function mayContainImportMetaUrl(code) {
|
|
95
|
+
return code.includes("import.meta.url") || code.includes("import.meta?.url");
|
|
96
|
+
}
|
|
97
|
+
function excludedRelativePrefixes(canonicalRoot, normalizedRoot, options) {
|
|
98
|
+
const prefixes = new Set([
|
|
99
|
+
".next",
|
|
100
|
+
".vinext",
|
|
101
|
+
".vinext-local-package",
|
|
102
|
+
"dist",
|
|
103
|
+
"out"
|
|
104
|
+
]);
|
|
105
|
+
for (const outputDir of options.outputDirs ?? []) {
|
|
106
|
+
const canonicalOutputDir = canonicalizePath(path.isAbsolute(outputDir) ? outputDir : path.resolve(canonicalRoot, outputDir));
|
|
107
|
+
if (!isPathWithin(normalizePath(canonicalOutputDir), normalizedRoot)) continue;
|
|
108
|
+
const relativePath = normalizePath(path.relative(canonicalRoot, canonicalOutputDir));
|
|
109
|
+
if (relativePath && relativePath !== ".") prefixes.add(relativePath);
|
|
110
|
+
}
|
|
111
|
+
return [...prefixes];
|
|
112
|
+
}
|
|
113
|
+
function isExcludedRelativePath(relativePath, prefixes) {
|
|
114
|
+
return prefixes.some((prefix) => relativePath === prefix || relativePath.startsWith(`${prefix}/`));
|
|
115
|
+
}
|
|
116
|
+
function isPathWithin(candidate, root) {
|
|
117
|
+
return candidate === root || candidate.startsWith(root.endsWith("/") ? root : `${root}/`);
|
|
118
|
+
}
|
|
119
|
+
function importMetaUrlValue(canonicalId, rootPaths, environment) {
|
|
120
|
+
if (environment === "client") return `file:///ROOT/${normalizePath(path.relative(rootPaths.canonicalRoot, canonicalId))}`;
|
|
121
|
+
return pathToFileURL(canonicalId).href;
|
|
122
|
+
}
|
|
123
|
+
function canonicalizePath(value) {
|
|
124
|
+
try {
|
|
125
|
+
return fs.realpathSync.native(value);
|
|
126
|
+
} catch {
|
|
127
|
+
return path.resolve(value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function collectImportMetaUrlRanges(ast) {
|
|
131
|
+
const ranges = [];
|
|
132
|
+
function visit(value) {
|
|
133
|
+
if (!isNodeLike(value)) return;
|
|
134
|
+
if (isImportMetaUrlNode(value)) {
|
|
135
|
+
ranges.push({
|
|
136
|
+
start: value.start,
|
|
137
|
+
end: value.end
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (isChainExpressionWrappingImportMetaUrl(value)) {
|
|
142
|
+
ranges.push({
|
|
143
|
+
start: value.start,
|
|
144
|
+
end: value.end
|
|
145
|
+
});
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (isNewUrlExpression(value)) {
|
|
149
|
+
const args = nodeArray(value.arguments);
|
|
150
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
151
|
+
if (index === 1 && isImportMetaUrlOrChainedNode(args[index])) continue;
|
|
152
|
+
visit(args[index]);
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
for (const [key, child] of Object.entries(value)) {
|
|
157
|
+
if (key === "type" || key === "start" || key === "end" || key === "loc") continue;
|
|
158
|
+
if (Array.isArray(child)) for (const item of child) visit(item);
|
|
159
|
+
else visit(child);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
visit(ast);
|
|
163
|
+
return ranges;
|
|
164
|
+
}
|
|
165
|
+
function isNodeLike(value) {
|
|
166
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
167
|
+
}
|
|
168
|
+
function isIdentifierNamed(value, name) {
|
|
169
|
+
return isNodeLike(value) && value.type === "Identifier" && value.name === name;
|
|
170
|
+
}
|
|
171
|
+
function isImportMetaNode(value) {
|
|
172
|
+
return isNodeLike(value) && value.type === "MetaProperty" && isIdentifierNamed(value.meta, "import") && isIdentifierNamed(value.property, "meta");
|
|
173
|
+
}
|
|
174
|
+
function isImportMetaUrlNode(value) {
|
|
175
|
+
return isNodeLike(value) && value.type === "MemberExpression" && typeof value.start === "number" && typeof value.end === "number" && isImportMetaNode(value.object) && isIdentifierNamed(value.property, "url");
|
|
176
|
+
}
|
|
177
|
+
function isImportMetaUrlOrChainedNode(value) {
|
|
178
|
+
if (isImportMetaUrlNode(value)) return true;
|
|
179
|
+
return isNodeLike(value) && value.type === "ChainExpression" && isImportMetaUrlNode(value.expression);
|
|
180
|
+
}
|
|
181
|
+
function isChainExpressionWrappingImportMetaUrl(value) {
|
|
182
|
+
return isNodeLike(value) && value.type === "ChainExpression" && typeof value.start === "number" && typeof value.end === "number" && isImportMetaUrlNode(value.expression);
|
|
183
|
+
}
|
|
184
|
+
function isNewUrlExpression(value) {
|
|
185
|
+
return value.type === "NewExpression" && isIdentifierNamed(value.callee, "URL");
|
|
186
|
+
}
|
|
187
|
+
function nodeArray(value) {
|
|
188
|
+
return Array.isArray(value) ? value : [];
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
export { createImportMetaUrlPlugin, rewriteImportMetaUrl };
|
|
192
|
+
|
|
193
|
+
//# sourceMappingURL=import-meta-url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-meta-url.js","names":[],"sources":["../../src/plugins/import-meta-url.ts"],"sourcesContent":["// Rewrites direct `import.meta.url` reads in user modules to the source-module\n// URL (a real file URL on the server, a Turbopack-style `file:///ROOT/...` URL\n// on the client) so module identity survives bundling, matching Next.js.\n//\n// Two known limitations, both matching Vite's own `import.meta.url` handling:\n// 1. Destructured access — `const { url } = import.meta;` — is not detected\n// and will leak the bundled chunk URL.\n// 2. An aliased `import.meta.url` used as a `new URL()` base — e.g.\n// `const u = import.meta.url; new URL(\"./file\", u);` — is rewritten,\n// breaking Vite's asset detection for that expression. Only the direct\n// `new URL(\"./file\", import.meta.url)` form is preserved.\n// Both are edge cases that are unlikely in real Next.js apps.\nimport { normalizePath, parseAst, type Plugin } from \"vite\";\nimport MagicString from \"magic-string\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\ntype NodeLike = {\n type?: string;\n start?: number;\n end?: number;\n [key: string]: unknown;\n};\n\ntype ImportMetaUrlEnvironment = \"client\" | \"server\";\n\ntype RewriteResult = {\n code: string;\n map: ReturnType<MagicString[\"generateMap\"]>;\n};\n\ntype RootPaths = {\n root: string;\n canonicalRoot: string;\n normalizedRoot: string;\n excludedRelativePrefixes: string[];\n};\n\nconst TRANSFORMABLE_SCRIPT_EXTENSIONS = new Set([\n \".cjs\",\n \".cts\",\n \".js\",\n \".jsx\",\n \".mjs\",\n \".mts\",\n \".ts\",\n \".tsx\",\n]);\n\nexport function createImportMetaUrlPlugin(options: { getRoot: () => string | undefined }): Plugin {\n let rootPaths: RootPaths | undefined;\n let outputDirs: string[] = [];\n\n function getRootPaths(): RootPaths | undefined {\n const root = options.getRoot();\n if (!root) return rootPaths;\n if (!rootPaths || rootPaths.root !== root) {\n rootPaths = createRootPaths(root, { outputDirs });\n }\n return rootPaths;\n }\n\n return {\n name: \"vinext:import-meta-url\",\n enforce: \"post\",\n configResolved(config) {\n const root = options.getRoot() ?? config.root;\n outputDirs = [config.build.outDir];\n rootPaths = createRootPaths(root, { outputDirs });\n },\n transform(code, id) {\n if (!mayContainImportMetaUrl(code)) return null;\n const paths = getRootPaths();\n if (!paths) return null;\n const cleanId = cleanModuleId(id);\n const canonicalId = transformableModuleCanonicalId(cleanId, paths);\n if (!canonicalId) return null;\n\n const environment: ImportMetaUrlEnvironment =\n this.environment?.name === \"client\" ? \"client\" : \"server\";\n const rewritten = rewriteCanonicalImportMetaUrl(code, canonicalId, paths, environment);\n if (!rewritten) return null;\n return {\n code: rewritten.code,\n map: rewritten.map,\n };\n },\n };\n}\n\nexport function rewriteImportMetaUrl(\n code: string,\n id: string,\n root: string,\n environment: ImportMetaUrlEnvironment,\n): RewriteResult | null {\n if (!mayContainImportMetaUrl(code)) return null;\n return rewriteCanonicalImportMetaUrl(\n code,\n canonicalizePath(id),\n createRootPaths(root),\n environment,\n );\n}\n\nfunction rewriteCanonicalImportMetaUrl(\n code: string,\n canonicalId: string,\n rootPaths: RootPaths,\n environment: ImportMetaUrlEnvironment,\n): RewriteResult | null {\n let ast: unknown;\n try {\n ast = parseAst(code);\n } catch {\n return null;\n }\n\n const ranges = collectImportMetaUrlRanges(ast);\n if (ranges.length === 0) return null;\n\n const replacement = JSON.stringify(importMetaUrlValue(canonicalId, rootPaths, environment));\n const output = new MagicString(code);\n for (const range of ranges) {\n output.overwrite(range.start, range.end, replacement);\n }\n\n return {\n code: output.toString(),\n map: output.generateMap({ hires: \"boundary\" }),\n };\n}\n\nfunction cleanModuleId(id: string): string {\n return id.split(\"?\", 1)[0];\n}\n\nfunction createRootPaths(root: string, options: { outputDirs?: string[] } = {}): RootPaths {\n const canonicalRoot = canonicalizePath(root);\n const normalizedRoot = normalizePath(canonicalRoot);\n return {\n root,\n canonicalRoot,\n normalizedRoot,\n excludedRelativePrefixes: excludedRelativePrefixes(canonicalRoot, normalizedRoot, options),\n };\n}\n\n// Returns the canonical module id when the module is eligible for rewriting,\n// or null otherwise. Threading the canonical id back to the caller avoids a\n// second realpathSync when computing the replacement value.\nfunction transformableModuleCanonicalId(id: string, rootPaths: RootPaths): string | null {\n if (!id || id.startsWith(\"\\0\")) return null;\n if (!path.isAbsolute(id)) return null;\n const normalizedInputId = normalizePath(id);\n // Early-exit optimization: skip the realpathSync below for node_modules\n // paths, which are the majority of modules in a typical project. The\n // isPathWithin check at line 150 provides a second safety net in case a\n // symlink causes the canonical path to land outside node_modules.\n if (normalizedInputId.includes(\"/node_modules/\")) return null;\n if (!TRANSFORMABLE_SCRIPT_EXTENSIONS.has(path.extname(normalizedInputId))) return null;\n\n const canonicalId = canonicalizePath(id);\n const normalizedId = normalizePath(canonicalId);\n if (!isPathWithin(normalizedId, rootPaths.normalizedRoot)) return null;\n\n const relativePath = normalizePath(path.relative(rootPaths.canonicalRoot, canonicalId));\n if (isExcludedRelativePath(relativePath, rootPaths.excludedRelativePrefixes)) return null;\n return canonicalId;\n}\n\nfunction mayContainImportMetaUrl(code: string): boolean {\n return code.includes(\"import.meta.url\") || code.includes(\"import.meta?.url\");\n}\n\nfunction excludedRelativePrefixes(\n canonicalRoot: string,\n normalizedRoot: string,\n options: { outputDirs?: string[] },\n): string[] {\n // Static list of known output/build directories whose modules must\n // never have import.meta.url rewritten (they are build artifacts, not\n // user source). Custom output directories are added dynamically from\n // config.build.outDir in configResolved. Using .gitignore was considered\n // but adds unnecessary filesystem overhead for this narrow use case.\n const prefixes = new Set([\".next\", \".vinext\", \".vinext-local-package\", \"dist\", \"out\"]);\n\n for (const outputDir of options.outputDirs ?? []) {\n const absoluteOutputDir = path.isAbsolute(outputDir)\n ? outputDir\n : path.resolve(canonicalRoot, outputDir);\n const canonicalOutputDir = canonicalizePath(absoluteOutputDir);\n const normalizedOutputDir = normalizePath(canonicalOutputDir);\n if (!isPathWithin(normalizedOutputDir, normalizedRoot)) continue;\n\n const relativePath = normalizePath(path.relative(canonicalRoot, canonicalOutputDir));\n if (relativePath && relativePath !== \".\") prefixes.add(relativePath);\n }\n\n return [...prefixes];\n}\n\nfunction isExcludedRelativePath(relativePath: string, prefixes: string[]): boolean {\n return prefixes.some(\n (prefix) => relativePath === prefix || relativePath.startsWith(`${prefix}/`),\n );\n}\n\nfunction isPathWithin(candidate: string, root: string): boolean {\n return candidate === root || candidate.startsWith(root.endsWith(\"/\") ? root : `${root}/`);\n}\n\nfunction importMetaUrlValue(\n canonicalId: string,\n rootPaths: RootPaths,\n environment: ImportMetaUrlEnvironment,\n): string {\n if (environment === \"client\") {\n const relativePath = normalizePath(path.relative(rootPaths.canonicalRoot, canonicalId));\n return `file:///ROOT/${relativePath}`;\n }\n\n return pathToFileURL(canonicalId).href;\n}\n\nfunction canonicalizePath(value: string): string {\n try {\n return fs.realpathSync.native(value);\n } catch {\n return path.resolve(value);\n }\n}\n\nfunction collectImportMetaUrlRanges(ast: unknown): Array<{ start: number; end: number }> {\n const ranges: Array<{ start: number; end: number }> = [];\n\n function visit(value: unknown): void {\n if (!isNodeLike(value)) return;\n\n if (isImportMetaUrlNode(value)) {\n ranges.push({ start: value.start, end: value.end });\n return;\n }\n\n if (isChainExpressionWrappingImportMetaUrl(value)) {\n ranges.push({ start: value.start, end: value.end });\n return;\n }\n\n if (isNewUrlExpression(value)) {\n const args = nodeArray(value.arguments);\n for (let index = 0; index < args.length; index += 1) {\n if (index === 1 && isImportMetaUrlOrChainedNode(args[index])) continue;\n visit(args[index]);\n }\n // The callee is always the bare `URL` identifier (see isNewUrlExpression),\n // so it can never contain an import.meta.url read — no need to visit it.\n return;\n }\n\n for (const [key, child] of Object.entries(value)) {\n if (key === \"type\" || key === \"start\" || key === \"end\" || key === \"loc\") continue;\n if (Array.isArray(child)) {\n for (const item of child) visit(item);\n } else {\n visit(child);\n }\n }\n }\n\n visit(ast);\n return ranges;\n}\n\nfunction isNodeLike(value: unknown): value is NodeLike {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isIdentifierNamed(value: unknown, name: string): boolean {\n return isNodeLike(value) && value.type === \"Identifier\" && value.name === name;\n}\n\nfunction isImportMetaNode(value: unknown): boolean {\n return (\n isNodeLike(value) &&\n value.type === \"MetaProperty\" &&\n isIdentifierNamed(value.meta, \"import\") &&\n isIdentifierNamed(value.property, \"meta\")\n );\n}\n\nfunction isImportMetaUrlNode(value: unknown): value is NodeLike & { start: number; end: number } {\n return (\n isNodeLike(value) &&\n value.type === \"MemberExpression\" &&\n typeof value.start === \"number\" &&\n typeof value.end === \"number\" &&\n isImportMetaNode(value.object) &&\n isIdentifierNamed(value.property, \"url\")\n );\n}\n\n// Accepts both import.meta.url (MemberExpression) and import.meta?.url\n// (ChainExpression wrapping a MemberExpression) so that the new URL() skip\n// correctly handles optional-chained base arguments.\nfunction isImportMetaUrlOrChainedNode(\n value: unknown,\n): value is NodeLike & { start: number; end: number } {\n if (isImportMetaUrlNode(value)) return true;\n return (\n isNodeLike(value) && value.type === \"ChainExpression\" && isImportMetaUrlNode(value.expression)\n );\n}\n\n// Catches the ChainExpression wrapper so we record the outer node range\n// and avoid descending into the inner MemberExpression (which happens\n// to share the same start/end, but this is more explicit).\nfunction isChainExpressionWrappingImportMetaUrl(\n value: unknown,\n): value is NodeLike & { start: number; end: number } {\n return (\n isNodeLike(value) &&\n value.type === \"ChainExpression\" &&\n typeof value.start === \"number\" &&\n typeof value.end === \"number\" &&\n isImportMetaUrlNode(value.expression)\n );\n}\n\n// Only matches bare `new URL(...)`, not `new globalThis.URL(...)` or\n// `new window.URL(...)`. Matches Vite's own asset-detection scope.\nfunction isNewUrlExpression(value: NodeLike): boolean {\n return value.type === \"NewExpression\" && isIdentifierNamed(value.callee, \"URL\");\n}\n\nfunction nodeArray(value: unknown): unknown[] {\n return Array.isArray(value) ? value : [];\n}\n"],"mappings":"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"}
|
|
@@ -22,21 +22,14 @@ type ServerActionInitiationSnapshot<TRouterState> = {
|
|
|
22
22
|
declare function isServerActionResult<TRoot>(value: unknown): value is AppBrowserServerActionResult<TRoot>;
|
|
23
23
|
declare function shouldClearClientNavigationCachesForServerActionResult<TRoot>(result: AppBrowserServerActionResult<TRoot> | TRoot, revalidation?: ServerActionRevalidationKind): boolean;
|
|
24
24
|
declare function parseServerActionRevalidationHeader(headers: Pick<Headers, "get">): ServerActionRevalidationKind;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* `./subpage` from `/subdir` lands on `/subdir/subpage`, not `/subpage`.
|
|
34
|
-
*/
|
|
35
|
-
declare function resolveServerActionRedirectLocation(options: {
|
|
36
|
-
currentHref: string;
|
|
37
|
-
location: string;
|
|
38
|
-
origin: string;
|
|
39
|
-
}): ServerActionRedirectLocation;
|
|
25
|
+
declare function normalizeServerActionThrownValue(data: unknown, responseStatus: number): unknown;
|
|
26
|
+
declare function readInvalidServerActionResponseError(response: Pick<Response, "headers" | "status" | "text">, hasRedirectLocation: boolean): Promise<Error | null>;
|
|
27
|
+
declare function shouldCheckRscCompatibilityForServerActionResponse(response: Pick<Response, "headers">): boolean;
|
|
28
|
+
declare function resolveServerActionRedirectCompatibilityHardNavigationTarget(options: {
|
|
29
|
+
actionRedirectHref: string | null;
|
|
30
|
+
clientCompatibilityId: string | null | undefined;
|
|
31
|
+
response: Pick<Response, "headers">;
|
|
32
|
+
}): string | null;
|
|
40
33
|
declare function shouldScheduleRefreshForDiscardedServerAction(revalidation: ServerActionRevalidationKind): boolean;
|
|
41
34
|
declare function createServerActionInitiationSnapshot<TRouterState>(options: {
|
|
42
35
|
href: string;
|
|
@@ -55,5 +48,5 @@ type DiscardedServerActionRefreshSchedulerOptions = {
|
|
|
55
48
|
};
|
|
56
49
|
declare function createDiscardedServerActionRefreshScheduler(options: DiscardedServerActionRefreshSchedulerOptions): DiscardedServerActionRefreshScheduler;
|
|
57
50
|
//#endregion
|
|
58
|
-
export { AppBrowserServerActionResult, ServerActionRevalidationKind, createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, isServerActionResult, parseServerActionRevalidationHeader,
|
|
51
|
+
export { AppBrowserServerActionResult, ServerActionRevalidationKind, createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, resolveServerActionRedirectCompatibilityHardNavigationTarget, shouldCheckRscCompatibilityForServerActionResponse, shouldClearClientNavigationCachesForServerActionResult, shouldScheduleRefreshForDiscardedServerAction };
|
|
59
52
|
//# sourceMappingURL=app-browser-action-result.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ACTION_REVALIDATED_HEADER } from "./headers.js";
|
|
2
|
+
import { VINEXT_RSC_CONTENT_TYPE, isRscCompatibilityIdCompatible } from "./app-rsc-cache-busting.js";
|
|
2
3
|
//#region src/server/app-browser-action-result.ts
|
|
3
4
|
const ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1;
|
|
4
5
|
const ACTION_DID_REVALIDATE_DYNAMIC_ONLY = 2;
|
|
@@ -31,19 +32,29 @@ function parseServerActionRevalidationHeader(headers) {
|
|
|
31
32
|
default: return "none";
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
function createServerActionHttpFallbackError(status) {
|
|
36
|
+
if (status < 400 || status > 599) return null;
|
|
37
|
+
const digest = status === 404 ? "NEXT_HTTP_ERROR_FALLBACK;404" : `NEXT_HTTP_ERROR_FALLBACK;${status}`;
|
|
38
|
+
const error = /* @__PURE__ */ new Error(status === 404 ? "NEXT_NOT_FOUND" : `NEXT_HTTP_ERROR_FALLBACK;${status}`);
|
|
39
|
+
return Object.assign(error, { digest });
|
|
40
|
+
}
|
|
41
|
+
function normalizeServerActionThrownValue(data, responseStatus) {
|
|
42
|
+
return createServerActionHttpFallbackError(responseStatus) ?? data;
|
|
43
|
+
}
|
|
44
|
+
async function readInvalidServerActionResponseError(response, hasRedirectLocation) {
|
|
45
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
46
|
+
if (contentType.startsWith("text/x-component") || hasRedirectLocation) return null;
|
|
47
|
+
const message = response.status >= 400 && contentType.toLowerCase().startsWith("text/plain") ? await response.text() : "An unexpected response was received from the server.";
|
|
48
|
+
return new Error(message || "An unexpected response was received from the server.");
|
|
49
|
+
}
|
|
50
|
+
function shouldCheckRscCompatibilityForServerActionResponse(response) {
|
|
51
|
+
return (response.headers.get("content-type") ?? "").startsWith(VINEXT_RSC_CONTENT_TYPE);
|
|
52
|
+
}
|
|
53
|
+
function resolveServerActionRedirectCompatibilityHardNavigationTarget(options) {
|
|
54
|
+
if (!options.actionRedirectHref) return null;
|
|
55
|
+
if (!shouldCheckRscCompatibilityForServerActionResponse(options.response)) return null;
|
|
56
|
+
if (isRscCompatibilityIdCompatible(options.response.headers.get("X-Vinext-RSC-Compatibility-Id"), options.clientCompatibilityId)) return null;
|
|
57
|
+
return options.actionRedirectHref;
|
|
47
58
|
}
|
|
48
59
|
function shouldScheduleRefreshForDiscardedServerAction(revalidation) {
|
|
49
60
|
return revalidation !== "none";
|
|
@@ -88,6 +99,6 @@ function createDiscardedServerActionRefreshScheduler(options) {
|
|
|
88
99
|
};
|
|
89
100
|
}
|
|
90
101
|
//#endregion
|
|
91
|
-
export { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, isServerActionResult, parseServerActionRevalidationHeader,
|
|
102
|
+
export { createDiscardedServerActionRefreshScheduler, createServerActionInitiationSnapshot, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, resolveServerActionRedirectCompatibilityHardNavigationTarget, shouldCheckRscCompatibilityForServerActionResponse, shouldClearClientNavigationCachesForServerActionResult, shouldScheduleRefreshForDiscardedServerAction };
|
|
92
103
|
|
|
93
104
|
//# sourceMappingURL=app-browser-action-result.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-browser-action-result.js","names":[],"sources":["../../src/server/app-browser-action-result.ts"],"sourcesContent":["import { ACTION_REVALIDATED_HEADER } from \"./headers.js\";\n\nexport type AppBrowserServerActionResult<TRoot> = {\n root?: TRoot;\n returnValue?: {\n ok: boolean;\n data: unknown;\n };\n};\n\nexport type ServerActionRevalidationKind = \"dynamicOnly\" | \"none\" | \"staticAndDynamic\";\n\nconst ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1;\nconst ACTION_DID_REVALIDATE_DYNAMIC_ONLY = 2;\n\ntype ServerActionInitiationSnapshot<TRouterState> = {\n href: string;\n navigationId: number;\n path: string;\n routerState: TRouterState;\n};\n\n/**\n * Structural discriminator: matches on `\"returnValue\"` or `\"root\"` keys.\n * This is safe because {@link AppWireElements} keys are prefixed (`route:`,\n * `slot:`, `__route`, etc.) and will never collide with these property names.\n * If the wire format ever adds a `\"root\"` key, this guard must be updated.\n */\nexport function isServerActionResult<TRoot>(\n value: unknown,\n): value is AppBrowserServerActionResult<TRoot> {\n return !!value && typeof value === \"object\" && (\"returnValue\" in value || \"root\" in value);\n}\n\nexport function shouldClearClientNavigationCachesForServerActionResult<TRoot>(\n result: AppBrowserServerActionResult<TRoot> | TRoot,\n revalidation: ServerActionRevalidationKind = \"none\",\n): boolean {\n if (revalidation !== \"none\") {\n return true;\n }\n\n if (!isServerActionResult<TRoot>(result)) {\n return true;\n }\n\n return result.root !== undefined;\n}\n\nexport function parseServerActionRevalidationHeader(\n headers: Pick<Headers, \"get\">,\n): ServerActionRevalidationKind {\n const value = headers.get(ACTION_REVALIDATED_HEADER);\n if (!value) return \"none\";\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch {\n return \"none\";\n }\n\n switch (parsed) {\n case ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC:\n return \"staticAndDynamic\";\n case ACTION_DID_REVALIDATE_DYNAMIC_ONLY:\n return \"dynamicOnly\";\n default:\n return \"none\";\n }\n}\n\
|
|
1
|
+
{"version":3,"file":"app-browser-action-result.js","names":[],"sources":["../../src/server/app-browser-action-result.ts"],"sourcesContent":["import { ACTION_REVALIDATED_HEADER } from \"./headers.js\";\nimport {\n isRscCompatibilityIdCompatible,\n VINEXT_RSC_COMPATIBILITY_ID_HEADER,\n VINEXT_RSC_CONTENT_TYPE,\n} from \"./app-rsc-cache-busting.js\";\n\nexport type AppBrowserServerActionResult<TRoot> = {\n root?: TRoot;\n returnValue?: {\n ok: boolean;\n data: unknown;\n };\n};\n\nexport type ServerActionRevalidationKind = \"dynamicOnly\" | \"none\" | \"staticAndDynamic\";\n\nconst ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1;\nconst ACTION_DID_REVALIDATE_DYNAMIC_ONLY = 2;\n\ntype ServerActionInitiationSnapshot<TRouterState> = {\n href: string;\n navigationId: number;\n path: string;\n routerState: TRouterState;\n};\n\n/**\n * Structural discriminator: matches on `\"returnValue\"` or `\"root\"` keys.\n * This is safe because {@link AppWireElements} keys are prefixed (`route:`,\n * `slot:`, `__route`, etc.) and will never collide with these property names.\n * If the wire format ever adds a `\"root\"` key, this guard must be updated.\n */\nexport function isServerActionResult<TRoot>(\n value: unknown,\n): value is AppBrowserServerActionResult<TRoot> {\n return !!value && typeof value === \"object\" && (\"returnValue\" in value || \"root\" in value);\n}\n\nexport function shouldClearClientNavigationCachesForServerActionResult<TRoot>(\n result: AppBrowserServerActionResult<TRoot> | TRoot,\n revalidation: ServerActionRevalidationKind = \"none\",\n): boolean {\n if (revalidation !== \"none\") {\n return true;\n }\n\n if (!isServerActionResult<TRoot>(result)) {\n return true;\n }\n\n return result.root !== undefined;\n}\n\nexport function parseServerActionRevalidationHeader(\n headers: Pick<Headers, \"get\">,\n): ServerActionRevalidationKind {\n const value = headers.get(ACTION_REVALIDATED_HEADER);\n if (!value) return \"none\";\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch {\n return \"none\";\n }\n\n switch (parsed) {\n case ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC:\n return \"staticAndDynamic\";\n case ACTION_DID_REVALIDATE_DYNAMIC_ONLY:\n return \"dynamicOnly\";\n default:\n return \"none\";\n }\n}\n\nfunction createServerActionHttpFallbackError(status: number): (Error & { digest: string }) | null {\n if (status < 400 || status > 599) return null;\n\n const digest =\n status === 404 ? \"NEXT_HTTP_ERROR_FALLBACK;404\" : `NEXT_HTTP_ERROR_FALLBACK;${status}`;\n const error = new Error(status === 404 ? \"NEXT_NOT_FOUND\" : `NEXT_HTTP_ERROR_FALLBACK;${status}`);\n return Object.assign(error, { digest });\n}\n\nexport function normalizeServerActionThrownValue(data: unknown, responseStatus: number): unknown {\n return createServerActionHttpFallbackError(responseStatus) ?? data;\n}\n\nexport async function readInvalidServerActionResponseError(\n response: Pick<Response, \"headers\" | \"status\" | \"text\">,\n hasRedirectLocation: boolean,\n): Promise<Error | null> {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n const isRscResponse = contentType.startsWith(VINEXT_RSC_CONTENT_TYPE);\n if (isRscResponse || hasRedirectLocation) return null;\n\n // Parity with Next.js' server-action reducer: any non-RSC action response,\n // including a 2xx, is surfaced to the action caller. Plain text 4xx/5xx\n // bodies are preserved when available; other responses use a stable generic\n // message.\n const message =\n response.status >= 400 && contentType.toLowerCase().startsWith(\"text/plain\")\n ? await response.text()\n : \"An unexpected response was received from the server.\";\n\n return new Error(message || \"An unexpected response was received from the server.\");\n}\n\nexport function shouldCheckRscCompatibilityForServerActionResponse(\n response: Pick<Response, \"headers\">,\n): boolean {\n return (response.headers.get(\"content-type\") ?? \"\").startsWith(VINEXT_RSC_CONTENT_TYPE);\n}\n\nexport function resolveServerActionRedirectCompatibilityHardNavigationTarget(options: {\n actionRedirectHref: string | null;\n clientCompatibilityId: string | null | undefined;\n response: Pick<Response, \"headers\">;\n}): string | null {\n if (!options.actionRedirectHref) return null;\n if (!shouldCheckRscCompatibilityForServerActionResponse(options.response)) return null;\n if (\n isRscCompatibilityIdCompatible(\n options.response.headers.get(VINEXT_RSC_COMPATIBILITY_ID_HEADER),\n options.clientCompatibilityId,\n )\n ) {\n return null;\n }\n return options.actionRedirectHref;\n}\n\nexport function shouldScheduleRefreshForDiscardedServerAction(\n revalidation: ServerActionRevalidationKind,\n): boolean {\n return revalidation !== \"none\";\n}\n\nexport function createServerActionInitiationSnapshot<TRouterState>(options: {\n href: string;\n navigationId: number;\n origin?: string;\n routerState: TRouterState;\n}): ServerActionInitiationSnapshot<TRouterState> {\n const url =\n options.origin === undefined ? new URL(options.href) : new URL(options.href, options.origin);\n return {\n href: url.href,\n navigationId: options.navigationId,\n path: url.pathname + url.search,\n routerState: options.routerState,\n };\n}\n\ntype DiscardedServerActionRefreshScheduler = {\n markNavigationSettled(): void;\n markNavigationStart(): void;\n schedule(): void;\n};\n\ntype DiscardedServerActionRefreshSchedulerOptions = {\n queueTask?: (callback: () => void) => void;\n runRefresh: () => void;\n};\n\nexport function createDiscardedServerActionRefreshScheduler(\n options: DiscardedServerActionRefreshSchedulerOptions,\n): DiscardedServerActionRefreshScheduler {\n const queueTask = options.queueTask ?? queueMicrotask;\n let activeNavigationCount = 0;\n let flushQueued = false;\n let refreshPending = false;\n\n function flush(): void {\n flushQueued = false;\n if (!refreshPending || activeNavigationCount > 0) return;\n\n refreshPending = false;\n options.runRefresh();\n }\n\n function queueFlush(): void {\n if (flushQueued) return;\n flushQueued = true;\n queueTask(flush);\n }\n\n return {\n markNavigationSettled() {\n if (activeNavigationCount > 0) {\n activeNavigationCount -= 1;\n }\n queueFlush();\n },\n markNavigationStart() {\n activeNavigationCount += 1;\n },\n schedule() {\n refreshPending = true;\n queueFlush();\n },\n };\n}\n"],"mappings":";;;AAiBA,MAAM,2CAA2C;AACjD,MAAM,qCAAqC;;;;;;;AAe3C,SAAgB,qBACd,OAC8C;CAC9C,OAAO,CAAC,CAAC,SAAS,OAAO,UAAU,aAAa,iBAAiB,SAAS,UAAU;;AAGtF,SAAgB,uDACd,QACA,eAA6C,QACpC;CACT,IAAI,iBAAiB,QACnB,OAAO;CAGT,IAAI,CAAC,qBAA4B,OAAO,EACtC,OAAO;CAGT,OAAO,OAAO,SAAS,KAAA;;AAGzB,SAAgB,oCACd,SAC8B;CAC9B,MAAM,QAAQ,QAAQ,IAAI,0BAA0B;CACpD,IAAI,CAAC,OAAO,OAAO;CAEnB,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,MAAM;SACpB;EACN,OAAO;;CAGT,QAAQ,QAAR;EACE,KAAK,0CACH,OAAO;EACT,KAAK,oCACH,OAAO;EACT,SACE,OAAO;;;AAIb,SAAS,oCAAoC,QAAqD;CAChG,IAAI,SAAS,OAAO,SAAS,KAAK,OAAO;CAEzC,MAAM,SACJ,WAAW,MAAM,iCAAiC,4BAA4B;CAChF,MAAM,wBAAQ,IAAI,MAAM,WAAW,MAAM,mBAAmB,4BAA4B,SAAS;CACjG,OAAO,OAAO,OAAO,OAAO,EAAE,QAAQ,CAAC;;AAGzC,SAAgB,iCAAiC,MAAe,gBAAiC;CAC/F,OAAO,oCAAoC,eAAe,IAAI;;AAGhE,eAAsB,qCACpB,UACA,qBACuB;CACvB,MAAM,cAAc,SAAS,QAAQ,IAAI,eAAe,IAAI;CAE5D,IADsB,YAAY,WAAA,mBACjB,IAAI,qBAAqB,OAAO;CAMjD,MAAM,UACJ,SAAS,UAAU,OAAO,YAAY,aAAa,CAAC,WAAW,aAAa,GACxE,MAAM,SAAS,MAAM,GACrB;CAEN,OAAO,IAAI,MAAM,WAAW,uDAAuD;;AAGrF,SAAgB,mDACd,UACS;CACT,QAAQ,SAAS,QAAQ,IAAI,eAAe,IAAI,IAAI,WAAW,wBAAwB;;AAGzF,SAAgB,6DAA6D,SAI3D;CAChB,IAAI,CAAC,QAAQ,oBAAoB,OAAO;CACxC,IAAI,CAAC,mDAAmD,QAAQ,SAAS,EAAE,OAAO;CAClF,IACE,+BACE,QAAQ,SAAS,QAAQ,IAAA,gCAAuC,EAChE,QAAQ,sBACT,EAED,OAAO;CAET,OAAO,QAAQ;;AAGjB,SAAgB,8CACd,cACS;CACT,OAAO,iBAAiB;;AAG1B,SAAgB,qCAAmD,SAKlB;CAC/C,MAAM,MACJ,QAAQ,WAAW,KAAA,IAAY,IAAI,IAAI,QAAQ,KAAK,GAAG,IAAI,IAAI,QAAQ,MAAM,QAAQ,OAAO;CAC9F,OAAO;EACL,MAAM,IAAI;EACV,cAAc,QAAQ;EACtB,MAAM,IAAI,WAAW,IAAI;EACzB,aAAa,QAAQ;EACtB;;AAcH,SAAgB,4CACd,SACuC;CACvC,MAAM,YAAY,QAAQ,aAAa;CACvC,IAAI,wBAAwB;CAC5B,IAAI,cAAc;CAClB,IAAI,iBAAiB;CAErB,SAAS,QAAc;EACrB,cAAc;EACd,IAAI,CAAC,kBAAkB,wBAAwB,GAAG;EAElD,iBAAiB;EACjB,QAAQ,YAAY;;CAGtB,SAAS,aAAmB;EAC1B,IAAI,aAAa;EACjB,cAAc;EACd,UAAU,MAAM;;CAGlB,OAAO;EACL,wBAAwB;GACtB,IAAI,wBAAwB,GAC1B,yBAAyB;GAE3B,YAAY;;EAEd,sBAAsB;GACpB,yBAAyB;;EAE3B,WAAW;GACT,iBAAiB;GACjB,YAAY;;EAEf"}
|