vinext 0.0.53 → 0.0.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/dist/build/inline-css.d.ts +7 -0
  2. package/dist/build/inline-css.js +50 -0
  3. package/dist/build/inline-css.js.map +1 -0
  4. package/dist/build/prerender.js +2 -1
  5. package/dist/build/prerender.js.map +1 -1
  6. package/dist/check.js +4 -0
  7. package/dist/check.js.map +1 -1
  8. package/dist/client/navigation-runtime.d.ts +2 -1
  9. package/dist/client/navigation-runtime.js.map +1 -1
  10. package/dist/client/window-next.d.ts +7 -0
  11. package/dist/client/window-next.js.map +1 -1
  12. package/dist/config/next-config.d.ts +83 -1
  13. package/dist/config/next-config.js +131 -2
  14. package/dist/config/next-config.js.map +1 -1
  15. package/dist/deploy.js +13 -0
  16. package/dist/deploy.js.map +1 -1
  17. package/dist/entries/app-browser-entry.d.ts +11 -1
  18. package/dist/entries/app-browser-entry.js +16 -6
  19. package/dist/entries/app-browser-entry.js.map +1 -1
  20. package/dist/entries/app-rsc-entry.d.ts +8 -1
  21. package/dist/entries/app-rsc-entry.js +18 -5
  22. package/dist/entries/app-rsc-entry.js.map +1 -1
  23. package/dist/entries/app-rsc-manifest.d.ts +21 -1
  24. package/dist/entries/app-rsc-manifest.js +6 -4
  25. package/dist/entries/app-rsc-manifest.js.map +1 -1
  26. package/dist/entries/pages-client-entry.d.ts +4 -1
  27. package/dist/entries/pages-client-entry.js +18 -2
  28. package/dist/entries/pages-client-entry.js.map +1 -1
  29. package/dist/entries/pages-server-entry.js +82 -4
  30. package/dist/entries/pages-server-entry.js.map +1 -1
  31. package/dist/entries/runtime-entry-module.d.ts +1 -10
  32. package/dist/entries/runtime-entry-module.js +2 -12
  33. package/dist/entries/runtime-entry-module.js.map +1 -1
  34. package/dist/index.js +63 -5
  35. package/dist/index.js.map +1 -1
  36. package/dist/plugins/remove-console.d.ts +16 -0
  37. package/dist/plugins/remove-console.js +176 -0
  38. package/dist/plugins/remove-console.js.map +1 -0
  39. package/dist/routing/app-route-graph.d.ts +24 -1
  40. package/dist/routing/app-route-graph.js +52 -4
  41. package/dist/routing/app-route-graph.js.map +1 -1
  42. package/dist/routing/app-router.d.ts +2 -2
  43. package/dist/routing/app-router.js +2 -2
  44. package/dist/routing/app-router.js.map +1 -1
  45. package/dist/routing/file-matcher.d.ts +21 -1
  46. package/dist/routing/file-matcher.js +39 -1
  47. package/dist/routing/file-matcher.js.map +1 -1
  48. package/dist/routing/pages-router.d.ts +1 -1
  49. package/dist/routing/pages-router.js +10 -3
  50. package/dist/routing/pages-router.js.map +1 -1
  51. package/dist/server/api-handler.js +1 -1
  52. package/dist/server/app-browser-entry.js +25 -16
  53. package/dist/server/app-browser-entry.js.map +1 -1
  54. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  55. package/dist/server/app-browser-navigation-controller.js +4 -0
  56. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  57. package/dist/server/app-elements-wire.d.ts +13 -4
  58. package/dist/server/app-elements-wire.js +10 -1
  59. package/dist/server/app-elements-wire.js.map +1 -1
  60. package/dist/server/app-elements.d.ts +2 -2
  61. package/dist/server/app-elements.js +2 -2
  62. package/dist/server/app-elements.js.map +1 -1
  63. package/dist/server/app-fallback-renderer.d.ts +15 -5
  64. package/dist/server/app-fallback-renderer.js +10 -4
  65. package/dist/server/app-fallback-renderer.js.map +1 -1
  66. package/dist/server/app-inline-css-client.d.ts +7 -0
  67. package/dist/server/app-inline-css-client.js +37 -0
  68. package/dist/server/app-inline-css-client.js.map +1 -0
  69. package/dist/server/app-page-boundary.d.ts +21 -1
  70. package/dist/server/app-page-boundary.js +28 -3
  71. package/dist/server/app-page-boundary.js.map +1 -1
  72. package/dist/server/app-page-cache.d.ts +7 -3
  73. package/dist/server/app-page-cache.js +7 -7
  74. package/dist/server/app-page-cache.js.map +1 -1
  75. package/dist/server/app-page-dispatch.d.ts +10 -1
  76. package/dist/server/app-page-dispatch.js +126 -79
  77. package/dist/server/app-page-dispatch.js.map +1 -1
  78. package/dist/server/app-page-element-builder.js +12 -28
  79. package/dist/server/app-page-element-builder.js.map +1 -1
  80. package/dist/server/app-page-render-identity.d.ts +22 -0
  81. package/dist/server/app-page-render-identity.js +42 -0
  82. package/dist/server/app-page-render-identity.js.map +1 -0
  83. package/dist/server/app-page-render.d.ts +8 -1
  84. package/dist/server/app-page-render.js +4 -1
  85. package/dist/server/app-page-render.js.map +1 -1
  86. package/dist/server/app-page-request.d.ts +6 -3
  87. package/dist/server/app-page-request.js +5 -2
  88. package/dist/server/app-page-request.js.map +1 -1
  89. package/dist/server/app-page-response.js +2 -2
  90. package/dist/server/app-page-response.js.map +1 -1
  91. package/dist/server/app-page-route-wiring.d.ts +15 -0
  92. package/dist/server/app-page-route-wiring.js +7 -5
  93. package/dist/server/app-page-route-wiring.js.map +1 -1
  94. package/dist/server/app-page-stream.d.ts +11 -0
  95. package/dist/server/app-page-stream.js +1 -0
  96. package/dist/server/app-page-stream.js.map +1 -1
  97. package/dist/server/app-route-handler-response.js +37 -5
  98. package/dist/server/app-route-handler-response.js.map +1 -1
  99. package/dist/server/app-rsc-handler.d.ts +14 -3
  100. package/dist/server/app-rsc-handler.js +45 -5
  101. package/dist/server/app-rsc-handler.js.map +1 -1
  102. package/dist/server/app-rsc-request-normalization.d.ts +2 -1
  103. package/dist/server/app-rsc-request-normalization.js +3 -2
  104. package/dist/server/app-rsc-request-normalization.js.map +1 -1
  105. package/dist/server/app-server-action-execution.d.ts +21 -3
  106. package/dist/server/app-server-action-execution.js +42 -7
  107. package/dist/server/app-server-action-execution.js.map +1 -1
  108. package/dist/server/app-ssr-entry.d.ts +6 -0
  109. package/dist/server/app-ssr-entry.js +22 -7
  110. package/dist/server/app-ssr-entry.js.map +1 -1
  111. package/dist/server/app-ssr-error-meta.js +3 -3
  112. package/dist/server/app-ssr-error-meta.js.map +1 -1
  113. package/dist/server/app-ssr-stream.d.ts +2 -1
  114. package/dist/server/app-ssr-stream.js +176 -31
  115. package/dist/server/app-ssr-stream.js.map +1 -1
  116. package/dist/server/client-trace-metadata.d.ts +31 -0
  117. package/dist/server/client-trace-metadata.js +83 -0
  118. package/dist/server/client-trace-metadata.js.map +1 -0
  119. package/dist/server/cookie-utils.d.ts +13 -0
  120. package/dist/server/cookie-utils.js +20 -0
  121. package/dist/server/cookie-utils.js.map +1 -0
  122. package/dist/server/dev-server.d.ts +8 -1
  123. package/dist/server/dev-server.js +34 -5
  124. package/dist/server/dev-server.js.map +1 -1
  125. package/dist/server/html.d.ts +2 -1
  126. package/dist/server/html.js +6 -1
  127. package/dist/server/html.js.map +1 -1
  128. package/dist/server/isr-cache.d.ts +7 -5
  129. package/dist/server/isr-cache.js +17 -6
  130. package/dist/server/isr-cache.js.map +1 -1
  131. package/dist/server/middleware-runtime.js +1 -2
  132. package/dist/server/middleware-runtime.js.map +1 -1
  133. package/dist/server/pages-document-initial-props.d.ts +7 -0
  134. package/dist/server/pages-document-initial-props.js +14 -0
  135. package/dist/server/pages-document-initial-props.js.map +1 -0
  136. package/dist/server/pages-page-data.js +3 -0
  137. package/dist/server/pages-page-data.js.map +1 -1
  138. package/dist/server/pages-page-method.d.ts +48 -0
  139. package/dist/server/pages-page-method.js +19 -0
  140. package/dist/server/pages-page-method.js.map +1 -0
  141. package/dist/server/pages-page-response.d.ts +6 -0
  142. package/dist/server/pages-page-response.js +10 -3
  143. package/dist/server/pages-page-response.js.map +1 -1
  144. package/dist/server/pages-serializable-props.d.ts +25 -0
  145. package/dist/server/pages-serializable-props.js +69 -0
  146. package/dist/server/pages-serializable-props.js.map +1 -0
  147. package/dist/server/prod-server.js +3 -0
  148. package/dist/server/prod-server.js.map +1 -1
  149. package/dist/server/server-action-not-found.js +3 -2
  150. package/dist/server/server-action-not-found.js.map +1 -1
  151. package/dist/server/static-file-cache.js +2 -1
  152. package/dist/server/static-file-cache.js.map +1 -1
  153. package/dist/shims/app-router-scroll-state.d.ts +4 -2
  154. package/dist/shims/app-router-scroll-state.js +16 -3
  155. package/dist/shims/app-router-scroll-state.js.map +1 -1
  156. package/dist/shims/app-router-scroll.d.ts +16 -2
  157. package/dist/shims/app-router-scroll.js +18 -3
  158. package/dist/shims/app-router-scroll.js.map +1 -1
  159. package/dist/shims/cache.d.ts +6 -0
  160. package/dist/shims/cache.js +7 -0
  161. package/dist/shims/cache.js.map +1 -1
  162. package/dist/shims/error.js +3 -0
  163. package/dist/shims/error.js.map +1 -1
  164. package/dist/shims/headers.d.ts +7 -0
  165. package/dist/shims/headers.js +9 -1
  166. package/dist/shims/headers.js.map +1 -1
  167. package/dist/shims/internal/app-route-detection.d.ts +37 -0
  168. package/dist/shims/internal/app-route-detection.js +69 -0
  169. package/dist/shims/internal/app-route-detection.js.map +1 -0
  170. package/dist/shims/link.d.ts +18 -2
  171. package/dist/shims/link.js +70 -6
  172. package/dist/shims/link.js.map +1 -1
  173. package/dist/shims/metadata.d.ts +7 -6
  174. package/dist/shims/metadata.js +9 -5
  175. package/dist/shims/metadata.js.map +1 -1
  176. package/dist/shims/navigation.d.ts +1 -2
  177. package/dist/shims/navigation.js +63 -12
  178. package/dist/shims/navigation.js.map +1 -1
  179. package/dist/shims/router.d.ts +5 -0
  180. package/dist/shims/router.js +14 -4
  181. package/dist/shims/router.js.map +1 -1
  182. package/dist/shims/script.d.ts +11 -1
  183. package/dist/shims/script.js +75 -6
  184. package/dist/shims/script.js.map +1 -1
  185. package/dist/utils/path.d.ts +13 -0
  186. package/dist/utils/path.js +16 -0
  187. package/dist/utils/path.js.map +1 -0
  188. package/package.json +1 -1
@@ -0,0 +1,16 @@
1
+ //#region src/plugins/remove-console.d.ts
2
+ type RemoveConsoleConfig = boolean | {
3
+ exclude: string[];
4
+ };
5
+ /**
6
+ * Walk the AST body looking for expression statements whose expression is a
7
+ * CallExpression with a callee of `console.<identifier>`. When found, check
8
+ * that the name is not in the excluded set and that `console` is not shadowed
9
+ * at this scope. If all conditions pass, replace the entire statement with `;`.
10
+ *
11
+ * Returns `null` if no console calls are removed.
12
+ */
13
+ declare function removeConsoleCalls(code: string, config: RemoveConsoleConfig): string | null;
14
+ //#endregion
15
+ export { removeConsoleCalls };
16
+ //# sourceMappingURL=remove-console.d.ts.map
@@ -0,0 +1,176 @@
1
+ import { parseAst } from "vite";
2
+ import MagicString from "magic-string";
3
+ //#region src/plugins/remove-console.ts
4
+ /**
5
+ * Strip `console.*` calls from client bundle code.
6
+ *
7
+ * Mirrors Next.js's SWC `remove_console` transform:
8
+ * - Strips all `console.<method>()` calls regardless of context (top-level,
9
+ * JSX expressions, function arguments, return values, ternary branches)
10
+ * - Replaces removed calls with `void 0` to keep the AST valid in every
11
+ * position a CallExpression can appear
12
+ * - Respects `exclude: ["error"]` to preserve certain methods (case-insensitive)
13
+ * - Preserves calls when `console` is shadowed (local variable, function
14
+ * parameter, or destructured binding)
15
+ * - Preserves computed property access `console[prop]()`
16
+ *
17
+ * Uses Vite's `parseAst` (OXC/acorn) for parsing and `MagicString` for
18
+ * surgical source replacement. Returns `null` when no changes are made.
19
+ */
20
+ const SCOPE_ENTERING_TYPES = new Set([
21
+ "FunctionDeclaration",
22
+ "FunctionExpression",
23
+ "ArrowFunctionExpression"
24
+ ]);
25
+ /**
26
+ * Walk the AST body looking for expression statements whose expression is a
27
+ * CallExpression with a callee of `console.<identifier>`. When found, check
28
+ * that the name is not in the excluded set and that `console` is not shadowed
29
+ * at this scope. If all conditions pass, replace the entire statement with `;`.
30
+ *
31
+ * Returns `null` if no console calls are removed.
32
+ */
33
+ function removeConsoleCalls(code, config) {
34
+ if (config === false) return null;
35
+ const excluded = typeof config === "object" ? new Set(config.exclude.map((s) => s.toLowerCase())) : /* @__PURE__ */ new Set();
36
+ if (!code.match(/\bconsole\b/)) return null;
37
+ let ast;
38
+ try {
39
+ ast = parseAst(code);
40
+ } catch {
41
+ return null;
42
+ }
43
+ const scopeStack = [{ shadowed: false }];
44
+ function currentScope() {
45
+ return scopeStack[scopeStack.length - 1];
46
+ }
47
+ function pushScope() {
48
+ scopeStack.push({ shadowed: currentScope().shadowed });
49
+ }
50
+ function popScope() {
51
+ scopeStack.pop();
52
+ }
53
+ const s = new MagicString(code);
54
+ let changed = false;
55
+ /**
56
+ * Check if a node introduces a binding named "console" and mark scope.
57
+ * Recurses into all binding-pattern node types (destructuring shapes,
58
+ * defaults, rest elements).
59
+ */
60
+ function checkBinding(node) {
61
+ if (!node) return;
62
+ switch (node.type) {
63
+ case "Identifier":
64
+ if (node.name === "console") currentScope().shadowed = true;
65
+ break;
66
+ case "ObjectPattern":
67
+ for (const prop of node.properties) checkBinding(prop);
68
+ break;
69
+ case "Property": {
70
+ const propertyNode = node;
71
+ if (propertyNode.value) checkBinding(propertyNode.value);
72
+ break;
73
+ }
74
+ case "ArrayPattern": {
75
+ const elements = node.elements;
76
+ if (elements) for (const el of elements) checkBinding(el);
77
+ break;
78
+ }
79
+ case "AssignmentPattern": {
80
+ const left = node.left;
81
+ checkBinding(left);
82
+ break;
83
+ }
84
+ case "RestElement": {
85
+ const argument = node.argument;
86
+ checkBinding(argument);
87
+ break;
88
+ }
89
+ default: break;
90
+ }
91
+ }
92
+ /**
93
+ * Check if an identifier refers to the *global* console.
94
+ * It's global only when:
95
+ * 1. Its name is "console"
96
+ * 2. No local binding of that name shadows it at this point
97
+ */
98
+ function isGlobalConsole(node) {
99
+ return node.type === "Identifier" && node.name === "console" && !currentScope().shadowed;
100
+ }
101
+ /**
102
+ * Determine if a call expression is a `console.<method>()` that should be
103
+ * removed. The callee must be a MemberExpression with:
104
+ * - object: Identifier "console" (global, not shadowed)
105
+ * - property: Identifier (NOT computed — computed access like
106
+ * `console[prop]()` is preserved per Next.js behavior)
107
+ * The method name must NOT be in the excluded set.
108
+ */
109
+ function shouldRemove(node) {
110
+ if (node.type !== "CallExpression") return false;
111
+ const callee = node.callee;
112
+ if (callee.type !== "MemberExpression") return false;
113
+ if (callee.computed) return false;
114
+ if (!isGlobalConsole(callee.object)) return false;
115
+ const prop = callee.property;
116
+ if (prop.type !== "Identifier") return false;
117
+ const method = prop.name.toLowerCase();
118
+ if (excluded.has(method)) return false;
119
+ return true;
120
+ }
121
+ /**
122
+ * Recursively walk a node tree, managing scope for shadow detection.
123
+ * When a CallExpression matches `console.<method>()`, replace it with
124
+ * `void 0`. If the call is the sole expression of an ExpressionStatement,
125
+ * replace the entire statement with `;` for cleaner output.
126
+ */
127
+ function walk(node, parent) {
128
+ if (!node) return;
129
+ if (node.type === "CallExpression" && shouldRemove(node)) {
130
+ if (parent?.type === "ExpressionStatement") s.overwrite(parent.start, parent.end, ";");
131
+ else s.overwrite(node.start, node.end, "void 0");
132
+ changed = true;
133
+ return;
134
+ }
135
+ if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") {
136
+ const id = node.id;
137
+ checkBinding(id);
138
+ }
139
+ const isScopeEntering = SCOPE_ENTERING_TYPES.has(node.type);
140
+ if (isScopeEntering) {
141
+ pushScope();
142
+ if (node.type === "FunctionExpression") {
143
+ const id = node.id;
144
+ checkBinding(id);
145
+ }
146
+ const params = node.params;
147
+ if (params) for (const param of params) checkBinding(param);
148
+ }
149
+ const isCatchScope = node.type === "CatchClause";
150
+ if (isCatchScope) {
151
+ pushScope();
152
+ const param = node.param;
153
+ if (param) checkBinding(param);
154
+ }
155
+ const isBlockScope = node.type === "BlockStatement" || node.type === "Program" || node.type === "SwitchCase";
156
+ if (isBlockScope && !isScopeEntering) pushScope();
157
+ if (node.type === "VariableDeclaration") for (const decl of node.declarations ?? []) checkBinding(decl.id);
158
+ for (const key of Object.keys(node)) {
159
+ if (key === "parent" || key === "start" || key === "end") continue;
160
+ const child = node[key];
161
+ if (child && typeof child === "object") {
162
+ if (Array.isArray(child)) {
163
+ for (const item of child) if (item && typeof item === "object" && "type" in item) walk(item, node);
164
+ } else if ("type" in child) walk(child, node);
165
+ }
166
+ }
167
+ if (isScopeEntering || isBlockScope || isCatchScope) popScope();
168
+ }
169
+ for (const node of ast.body) walk(node);
170
+ if (!changed) return null;
171
+ return s.toString();
172
+ }
173
+ //#endregion
174
+ export { removeConsoleCalls };
175
+
176
+ //# sourceMappingURL=remove-console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-console.js","names":[],"sources":["../../src/plugins/remove-console.ts"],"sourcesContent":["/**\n * Strip `console.*` calls from client bundle code.\n *\n * Mirrors Next.js's SWC `remove_console` transform:\n * - Strips all `console.<method>()` calls regardless of context (top-level,\n * JSX expressions, function arguments, return values, ternary branches)\n * - Replaces removed calls with `void 0` to keep the AST valid in every\n * position a CallExpression can appear\n * - Respects `exclude: [\"error\"]` to preserve certain methods (case-insensitive)\n * - Preserves calls when `console` is shadowed (local variable, function\n * parameter, or destructured binding)\n * - Preserves computed property access `console[prop]()`\n *\n * Uses Vite's `parseAst` (OXC/acorn) for parsing and `MagicString` for\n * surgical source replacement. Returns `null` when no changes are made.\n */\nimport { parseAst } from \"vite\";\nimport MagicString from \"magic-string\";\n\ntype ASTNode = ReturnType<typeof parseAst>[\"body\"][number][\"parent\"];\ntype BindingNode = Extract<ASTNode, { type: string }>;\n\ntype RemoveConsoleConfig = boolean | { exclude: string[] };\n\n// Node types that introduce a new function-style scope. Hoisted to a module-\n// level Set so the membership check in walk() is O(1) and doesn't allocate\n// per recursive call.\nconst SCOPE_ENTERING_TYPES = new Set([\n \"FunctionDeclaration\",\n \"FunctionExpression\",\n \"ArrowFunctionExpression\",\n]);\n\n/**\n * Walk the AST body looking for expression statements whose expression is a\n * CallExpression with a callee of `console.<identifier>`. When found, check\n * that the name is not in the excluded set and that `console` is not shadowed\n * at this scope. If all conditions pass, replace the entire statement with `;`.\n *\n * Returns `null` if no console calls are removed.\n */\nexport function removeConsoleCalls(code: string, config: RemoveConsoleConfig): string | null {\n if (config === false) return null;\n\n const excluded =\n typeof config === \"object\"\n ? new Set(config.exclude.map((s) => s.toLowerCase()))\n : new Set<string>();\n\n // Fast path: if there's no bare \"console\" reference, skip parsing.\n // This avoids the parse cost for the vast majority of modules.\n const consoleMatch = code.match(/\\bconsole\\b/);\n if (!consoleMatch) return null;\n\n let ast: ReturnType<typeof parseAst>;\n try {\n ast = parseAst(code);\n } catch {\n // If parsing fails (shouldn't happen post-transform), bail out\n return null;\n }\n\n // Collect shadowing scopes: tracks whether there's a local binding named\n // \"console\" in the current or any parent scope. We do a simple top-down\n // walk maintaining a stack of scope frames. Each function/arrow/block\n // introduces a new frame. When we see a declaration/parameter of name\n // \"console\", that frame (and its descendants) are shadowed.\n type Scope = { shadowed: boolean };\n const scopeStack: Scope[] = [{ shadowed: false }];\n\n function currentScope(): Scope {\n return scopeStack[scopeStack.length - 1]!;\n }\n\n function pushScope(): void {\n // Child inherits parent shadowed status\n scopeStack.push({ shadowed: currentScope().shadowed });\n }\n\n function popScope(): void {\n scopeStack.pop();\n }\n\n const s = new MagicString(code);\n let changed = false;\n\n /**\n * Check if a node introduces a binding named \"console\" and mark scope.\n * Recurses into all binding-pattern node types (destructuring shapes,\n * defaults, rest elements).\n */\n function checkBinding(node: BindingNode | null | undefined): void {\n if (!node) return;\n // oxlint-disable-next-line typescript/switch-exhaustiveness-check\n switch (node.type) {\n case \"Identifier\": {\n if (node.name === \"console\") {\n currentScope().shadowed = true;\n }\n break;\n }\n case \"ObjectPattern\": {\n for (const prop of node.properties) {\n checkBinding(prop as BindingNode);\n }\n break;\n }\n case \"Property\": {\n // For `{ key: value }` and `{ console }` (shorthand) — the binding name\n // is in `value`, not `key`. Recurse so AssignmentPattern defaults,\n // nested patterns, etc. are all handled.\n const propertyNode = node as unknown as { value?: BindingNode };\n if (propertyNode.value) checkBinding(propertyNode.value);\n break;\n }\n case \"ArrayPattern\": {\n // oxlint-disable-next-line typescript/no-explicit-any\n const elements = (node as any).elements as Array<BindingNode | null> | undefined;\n if (elements) {\n for (const el of elements) {\n checkBinding(el);\n }\n }\n break;\n }\n case \"AssignmentPattern\": {\n // `x = default` — the binding is `left`, the default value is `right`.\n // oxlint-disable-next-line typescript/no-explicit-any\n const left = (node as any).left as BindingNode | undefined;\n checkBinding(left);\n break;\n }\n case \"RestElement\": {\n // `...x` — the binding is `argument`.\n // oxlint-disable-next-line typescript/no-explicit-any\n const argument = (node as any).argument as BindingNode | undefined;\n checkBinding(argument);\n break;\n }\n default:\n break;\n }\n }\n\n /**\n * Check if an identifier refers to the *global* console.\n * It's global only when:\n * 1. Its name is \"console\"\n * 2. No local binding of that name shadows it at this point\n */\n function isGlobalConsole(node: BindingNode): boolean {\n return node.type === \"Identifier\" && node.name === \"console\" && !currentScope().shadowed;\n }\n\n /**\n * Determine if a call expression is a `console.<method>()` that should be\n * removed. The callee must be a MemberExpression with:\n * - object: Identifier \"console\" (global, not shadowed)\n * - property: Identifier (NOT computed — computed access like\n * `console[prop]()` is preserved per Next.js behavior)\n * The method name must NOT be in the excluded set.\n */\n function shouldRemove(node: BindingNode): boolean {\n if (node.type !== \"CallExpression\") return false;\n const callee = node.callee;\n if (callee.type !== \"MemberExpression\") return false;\n\n // Only handle dot access: console.log() — skip computed: console[prop]()\n if (callee.computed) return false;\n\n // The object must be the global console identifier\n if (!isGlobalConsole(callee.object)) return false;\n\n // Property must be an identifier (e.g., \"log\", \"warn\")\n const prop = callee.property;\n if (prop.type !== \"Identifier\") return false;\n\n const method = prop.name.toLowerCase();\n if (excluded.has(method)) return false;\n\n return true;\n }\n\n /**\n * Recursively walk a node tree, managing scope for shadow detection.\n * When a CallExpression matches `console.<method>()`, replace it with\n * `void 0`. If the call is the sole expression of an ExpressionStatement,\n * replace the entire statement with `;` for cleaner output.\n */\n function walk(node: ASTNode, parent?: ASTNode): void {\n if (!node) return;\n\n if (node.type === \"CallExpression\" && shouldRemove(node)) {\n if (parent?.type === \"ExpressionStatement\") {\n // Replace the whole statement so we don't leave `void 0;` litter\n s.overwrite(parent.start, parent.end, \";\");\n } else {\n s.overwrite(node.start, node.end, \"void 0\");\n }\n changed = true;\n return; // don't recurse into children of a removed call\n }\n\n // `function console() {}` and `class console {}` bind `console` in the\n // *enclosing* scope (function declarations are hoisted to function/module\n // scope, class declarations are block-scoped). Check `id` against the\n // current scope BEFORE pushing the function's own scope, so the binding\n // is visible both outside and inside the function (via scope inheritance).\n if (node.type === \"FunctionDeclaration\" || node.type === \"ClassDeclaration\") {\n // oxlint-disable-next-line typescript/no-explicit-any\n const id = (node as any).id as BindingNode | undefined;\n checkBinding(id);\n }\n\n const isScopeEntering = SCOPE_ENTERING_TYPES.has(node.type);\n if (isScopeEntering) {\n pushScope();\n\n // Named FunctionExpressions (`const x = function console() {}`) bind\n // their name only in their *own* scope — not the enclosing one — so\n // mark after pushing.\n if (node.type === \"FunctionExpression\") {\n // oxlint-disable-next-line typescript/no-explicit-any\n const id = (node as any).id as BindingNode | undefined;\n checkBinding(id);\n }\n\n // Mark params/destructured params\n // oxlint-disable-next-line typescript/no-explicit-any\n const params = (node as any).params as ASTNode[] | undefined;\n if (params) {\n for (const param of params) {\n checkBinding(param as BindingNode);\n }\n }\n }\n\n // CatchClause introduces a binding for its param (`catch (e) { ... }`).\n // If the param shadows \"console\", the catch block must treat console as\n // local. We push a scope just for the param binding; the BlockStatement\n // body below will push its own scope on top, which inherits the shadow.\n const isCatchScope = node.type === \"CatchClause\";\n if (isCatchScope) {\n pushScope();\n // oxlint-disable-next-line typescript/no-explicit-any\n const param = (node as any).param as BindingNode | undefined;\n if (param) {\n checkBinding(param);\n }\n }\n\n // Also enter a new scope for BlockStatement / Program bodies so that\n // variable declarations are checked in the right frame.\n //\n // KNOWN LIMITATION: `var` is function-scoped, not block-scoped. A `var\n // console = ...` inside a nested block (if/for/etc.) is hoisted to the\n // enclosing function, but we treat it as block-scoped here, so console\n // references after the block exits its scope frame will be incorrectly\n // stripped. `let`/`const` are block-scoped so this only affects `var`.\n // In real-world code, shadowing `console` with `var` is exceedingly rare.\n const isBlockScope =\n node.type === \"BlockStatement\" || node.type === \"Program\" || node.type === \"SwitchCase\";\n if (isBlockScope && !isScopeEntering) {\n pushScope();\n }\n\n // Check for local variable declarations of \"console\"\n if (node.type === \"VariableDeclaration\") {\n // oxlint-disable-next-line typescript/no-explicit-any\n for (const decl of (node as any).declarations ?? []) {\n checkBinding(decl.id as BindingNode);\n }\n }\n\n // Recurse into child nodes, passing current node as parent\n for (const key of Object.keys(node)) {\n if (key === \"parent\" || key === \"start\" || key === \"end\") continue;\n // oxlint-disable-next-line typescript/no-explicit-any\n const child = (node as any)[key];\n if (child && typeof child === \"object\") {\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === \"object\" && \"type\" in item) {\n walk(item as BindingNode, node);\n }\n }\n } else if (\"type\" in child) {\n walk(child as BindingNode, node);\n }\n }\n }\n\n if (isScopeEntering || isBlockScope || isCatchScope) {\n popScope();\n }\n }\n\n for (const node of ast.body) {\n walk(node);\n }\n\n if (!changed) return null;\n return s.toString();\n}\n"],"mappings":"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"}
@@ -281,6 +281,29 @@ declare function convertSegmentsToRouteParts(segments: readonly string[]): {
281
281
  params: string[];
282
282
  isDynamic: boolean;
283
283
  } | null;
284
+ /**
285
+ * Returns the unique static sibling segment names at each dynamic URL level
286
+ * of the matched route. Mirrors Next.js's `getStaticSiblingSegments` from
287
+ * the next-app-loader: for `/products/[id]` with a sibling route at
288
+ * `/products/sale`, the dynamic `[id]` segment has `staticSiblings: ['sale']`.
289
+ *
290
+ * The returned list flattens siblings across all dynamic positions and is
291
+ * intended for the RSC payload — the client router uses it to determine if
292
+ * a cached dynamic-route prefetch can be reused when navigating to a static
293
+ * sibling URL.
294
+ *
295
+ * Ported from Next.js: packages/next/src/build/webpack/loaders/next-app-loader/index.ts
296
+ * (getStaticSiblingSegments).
297
+ *
298
+ * Route group segments and parallel-route slot segments are part of the
299
+ * filesystem tree but not the URL namespace — sibling computation is done on
300
+ * the URL-level `patternParts`, so they are correctly transparent here.
301
+ */
302
+ declare function computeAppRouteStaticSiblings(allRoutes: readonly {
303
+ patternParts?: readonly string[] | null;
304
+ }[], matchedRoute: {
305
+ patternParts?: readonly string[] | null;
306
+ }): string[];
284
307
  //#endregion
285
- export { AppRoute, AppRouteGraphParallelSlot, AppRouteGraphRoute, AppRouteSemanticIds, GraphVersion, InterceptingRoute, ParallelSlot, RootBoundaryId, RouteManifest, RouteManifestBoundary, RouteManifestBoundaryOutcome, RouteManifestDefault, RouteManifestInterception, RouteManifestLayout, RouteManifestPage, RouteManifestRootBoundary, RouteManifestRoute, RouteManifestRouteHandler, RouteManifestSlot, RouteManifestSlotBinding, RouteManifestSlotBindingState, RouteManifestTemplate, StaticSegmentGraph, buildAppRouteGraph, computeRootParamNames, convertSegmentsToRouteParts, isInvisibleSegment };
308
+ export { AppRoute, AppRouteGraphParallelSlot, AppRouteGraphRoute, AppRouteSemanticIds, GraphVersion, InterceptingRoute, ParallelSlot, RootBoundaryId, RouteManifest, RouteManifestBoundary, RouteManifestBoundaryOutcome, RouteManifestDefault, RouteManifestInterception, RouteManifestLayout, RouteManifestPage, RouteManifestRootBoundary, RouteManifestRoute, RouteManifestRouteHandler, RouteManifestSlot, RouteManifestSlotBinding, RouteManifestSlotBindingState, RouteManifestTemplate, StaticSegmentGraph, buildAppRouteGraph, computeAppRouteStaticSiblings, computeRootParamNames, convertSegmentsToRouteParts, isInvisibleSegment };
286
309
  //# sourceMappingURL=app-route-graph.d.ts.map
@@ -329,7 +329,7 @@ function createRouteManifestGraphVersion(segmentGraph) {
329
329
  }
330
330
  async function buildAppRouteGraph(appDir, matcher) {
331
331
  const routes = [];
332
- const excludeDir = (name) => name.startsWith("@") || name.startsWith("_") || isInterceptionMarkerDir(name);
332
+ const excludeDir = (name) => name.startsWith("@") && name !== "@children" || name.startsWith("_") || isInterceptionMarkerDir(name);
333
333
  for await (const file of scanWithExtensions("**/page", appDir, matcher.extensions, excludeDir)) {
334
334
  const route = fileToAppRoute(file, appDir, "page", matcher);
335
335
  if (route) routes.push(route);
@@ -367,7 +367,7 @@ async function buildAppRouteGraph(appDir, matcher) {
367
367
  }
368
368
  function hasParallelSlotDirectory(dir) {
369
369
  try {
370
- return fs.readdirSync(dir, { withFileTypes: true }).some((entry) => entry.isDirectory() && entry.name.startsWith("@"));
370
+ return fs.readdirSync(dir, { withFileTypes: true }).some((entry) => entry.isDirectory() && entry.name.startsWith("@") && entry.name !== "@children");
371
371
  } catch {
372
372
  return false;
373
373
  }
@@ -555,7 +555,12 @@ function findSlotSubPages(slotDir, matcher) {
555
555
  * Convert a file path relative to app/ into an AppRoute.
556
556
  */
557
557
  function fileToAppRoute(file, appDir, type, matcher) {
558
- return directoryToAppRoute(path.dirname(file), appDir, matcher, type === "page" ? path.join(appDir, file) : null, type === "route" ? path.join(appDir, file) : null);
558
+ let dir = path.dirname(file);
559
+ if (type === "page" && dir !== "." && path.basename(dir) === "@children") {
560
+ const parent = path.dirname(dir);
561
+ dir = parent === "" || parent === "." ? "." : parent;
562
+ }
563
+ return directoryToAppRoute(dir, appDir, matcher, type === "page" ? path.join(appDir, file) : null, type === "route" ? path.join(appDir, file) : null);
559
564
  }
560
565
  function directoryToAppRoute(dir, appDir, matcher, pagePath, routePath) {
561
566
  const segments = dir === "." ? [] : dir.split(path.sep);
@@ -981,6 +986,7 @@ function discoverParallelSlots(dir, appDir, matcher) {
981
986
  const slots = [];
982
987
  for (const entry of entries) {
983
988
  if (!entry.isDirectory() || !entry.name.startsWith("@")) continue;
989
+ if (entry.name === "@children") continue;
984
990
  const slotName = entry.name.slice(1);
985
991
  const slotDir = path.join(dir, entry.name);
986
992
  const pagePath = findFile(slotDir, "page", matcher);
@@ -1284,7 +1290,49 @@ function joinRoutePattern(basePattern, subPath) {
1284
1290
  if (!subPath) return basePattern;
1285
1291
  return basePattern === "/" ? `/${subPath}` : `${basePattern}/${subPath}`;
1286
1292
  }
1293
+ /**
1294
+ * Returns the unique static sibling segment names at each dynamic URL level
1295
+ * of the matched route. Mirrors Next.js's `getStaticSiblingSegments` from
1296
+ * the next-app-loader: for `/products/[id]` with a sibling route at
1297
+ * `/products/sale`, the dynamic `[id]` segment has `staticSiblings: ['sale']`.
1298
+ *
1299
+ * The returned list flattens siblings across all dynamic positions and is
1300
+ * intended for the RSC payload — the client router uses it to determine if
1301
+ * a cached dynamic-route prefetch can be reused when navigating to a static
1302
+ * sibling URL.
1303
+ *
1304
+ * Ported from Next.js: packages/next/src/build/webpack/loaders/next-app-loader/index.ts
1305
+ * (getStaticSiblingSegments).
1306
+ *
1307
+ * Route group segments and parallel-route slot segments are part of the
1308
+ * filesystem tree but not the URL namespace — sibling computation is done on
1309
+ * the URL-level `patternParts`, so they are correctly transparent here.
1310
+ */
1311
+ function computeAppRouteStaticSiblings(allRoutes, matchedRoute) {
1312
+ const siblings = /* @__PURE__ */ new Set();
1313
+ const parts = matchedRoute.patternParts;
1314
+ if (!parts) return [];
1315
+ for (let level = 0; level < parts.length; level++) {
1316
+ const segmentAtLevel = parts[level];
1317
+ if (!segmentAtLevel.startsWith(":")) continue;
1318
+ for (const otherRoute of allRoutes) {
1319
+ const otherParts = otherRoute.patternParts;
1320
+ if (!otherParts || otherParts.length <= level) continue;
1321
+ let prefixMatches = true;
1322
+ for (let i = 0; i < level; i++) if (parts[i] !== otherParts[i]) {
1323
+ prefixMatches = false;
1324
+ break;
1325
+ }
1326
+ if (!prefixMatches) continue;
1327
+ const otherSegmentAtLevel = otherParts[level];
1328
+ if (otherSegmentAtLevel === segmentAtLevel) continue;
1329
+ if (otherSegmentAtLevel.startsWith(":")) continue;
1330
+ siblings.add(otherSegmentAtLevel);
1331
+ }
1332
+ }
1333
+ return Array.from(siblings);
1334
+ }
1287
1335
  //#endregion
1288
- export { buildAppRouteGraph, computeRootParamNames, convertSegmentsToRouteParts, isInvisibleSegment };
1336
+ export { buildAppRouteGraph, computeAppRouteStaticSiblings, computeRootParamNames, convertSegmentsToRouteParts, isInvisibleSegment };
1289
1337
 
1290
1338
  //# sourceMappingURL=app-route-graph.js.map