@wular/pnext 0.0.1
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 +153 -0
- package/bin/pnext +67 -0
- package/config/lint/base.js +48 -0
- package/config/ts/base.json +26 -0
- package/config/ts/react.json +13 -0
- package/package.json +70 -0
- package/reference/compat.md +63 -0
- package/reference/config.md +120 -0
- package/reference/css.md +58 -0
- package/reference/dev.md +69 -0
- package/reference/env.md +40 -0
- package/reference/metadata.md +86 -0
- package/reference/navigation.md +149 -0
- package/reference/overview.md +35 -0
- package/reference/performance.md +97 -0
- package/reference/rendering.md +127 -0
- package/reference/routing.md +167 -0
- package/reference/typegen.md +64 -0
- package/src/api/cache.ts +80 -0
- package/src/api/client-cache.ts +9 -0
- package/src/api/client-navigation.ts +279 -0
- package/src/api/dynamic.tsx +102 -0
- package/src/api/link.tsx +119 -0
- package/src/api/navigation.ts +198 -0
- package/src/api/router/events.ts +53 -0
- package/src/api/router/history.ts +70 -0
- package/src/api/router/hub.ts +194 -0
- package/src/api/router/policies.ts +107 -0
- package/src/api/router/runtime.ts +5238 -0
- package/src/api/router/types.ts +299 -0
- package/src/api/router.ts +167 -0
- package/src/api/server.ts +323 -0
- package/src/api/suspense.ts +16 -0
- package/src/cache/context.ts +61 -0
- package/src/cli/adapters/vercel-warm.ts +375 -0
- package/src/cli/adapters/vercel.ts +1310 -0
- package/src/cli/analyze-print.ts +181 -0
- package/src/cli/analyze.ts +328 -0
- package/src/cli/boot-trace.ts +29 -0
- package/src/cli/build.ts +3114 -0
- package/src/cli/dev.ts +276 -0
- package/src/cli/index.ts +196 -0
- package/src/cli/named-bin.ts +119 -0
- package/src/cli/serve-ui.ts +160 -0
- package/src/cli/start.ts +1425 -0
- package/src/client/build.ts +2136 -0
- package/src/client/chunk-fold.ts +526 -0
- package/src/client/entry.ts +1525 -0
- package/src/client/paths.ts +22 -0
- package/src/client/prebuilt.ts +621 -0
- package/src/client/profile.ts +75 -0
- package/src/client/react-compiler.ts +94 -0
- package/src/client/reference-stub.ts +145 -0
- package/src/client/reference.ts +47 -0
- package/src/compat/actions/action-client.ts +531 -0
- package/src/compat/actions/action-dispatch.ts +676 -0
- package/src/compat/actions/action-router.ts +40 -0
- package/src/compat/actions/action-shared.ts +95 -0
- package/src/compat/actions/client-plugin.ts +135 -0
- package/src/compat/actions/client-stub.ts +65 -0
- package/src/compat/actions/config.ts +164 -0
- package/src/compat/actions/detect.ts +208 -0
- package/src/compat/actions/discovery.ts +244 -0
- package/src/compat/actions/early-submit.ts +40 -0
- package/src/compat/actions/endpoint.ts +602 -0
- package/src/compat/actions/flight.ts +52 -0
- package/src/compat/actions/form-state.ts +73 -0
- package/src/compat/actions/hoist.ts +485 -0
- package/src/compat/actions/ids.ts +39 -0
- package/src/compat/actions/index.ts +41 -0
- package/src/compat/actions/instances.ts +144 -0
- package/src/compat/actions/origin.ts +109 -0
- package/src/compat/actions/protocol.ts +125 -0
- package/src/compat/actions/registry.ts +74 -0
- package/src/compat/actions/rewrite.ts +282 -0
- package/src/compat/actions/serve.ts +414 -0
- package/src/compat/actions/server-tag.ts +21 -0
- package/src/compat/actions/unrecognized-error.ts +30 -0
- package/src/compat/adapter/build-complete.ts +257 -0
- package/src/compat/bundler/bun-externals.ts +53 -0
- package/src/compat/bundler/cjs-exports.ts +542 -0
- package/src/compat/bundler/config.ts +363 -0
- package/src/compat/bundler/externals.ts +34 -0
- package/src/compat/bundler/import-meta-url.ts +60 -0
- package/src/compat/bundler/modularize-imports.ts +119 -0
- package/src/compat/bundler/new-url-asset.ts +87 -0
- package/src/compat/bundler/optimize-package-imports.ts +273 -0
- package/src/compat/bundler/polyfill.ts +88 -0
- package/src/compat/bundler/react-compiler.ts +61 -0
- package/src/compat/bundler/react-profiler.tsx +25 -0
- package/src/compat/bundler/relay-transform.ts +116 -0
- package/src/compat/bundler/require-context.ts +281 -0
- package/src/compat/bundler/resolve-extensions.ts +75 -0
- package/src/compat/bundler/source-cache.ts +61 -0
- package/src/compat/bundler/static-imports.ts +25 -0
- package/src/compat/bundler/symlink-imports.ts +119 -0
- package/src/compat/bundler/tsconfig-paths.ts +50 -0
- package/src/compat/bundler/wasm.ts +153 -0
- package/src/compat/bundler/webpack-loaders.ts +685 -0
- package/src/compat/bundler/worker.ts +278 -0
- package/src/compat/cache/build-flags.ts +81 -0
- package/src/compat/cache/build-prerender-errors.ts +163 -0
- package/src/compat/cache/custom-handler.ts +159 -0
- package/src/compat/cache/fetch-patch.ts +745 -0
- package/src/compat/cache/handler.ts +100 -0
- package/src/compat/cache/modern-handler.ts +275 -0
- package/src/compat/cache/resume-data-cache.ts +143 -0
- package/src/compat/cache/revalidate.ts +759 -0
- package/src/compat/cache/runtime-error.ts +124 -0
- package/src/compat/cache/use-cache-transform.ts +961 -0
- package/src/compat/cache/use-cache.ts +1695 -0
- package/src/compat/cache-control.ts +269 -0
- package/src/compat/client/base-path.ts +64 -0
- package/src/compat/client/css-order.ts +36 -0
- package/src/compat/client/errors/control-flow.ts +92 -0
- package/src/compat/client/errors/error-boundary.ts +222 -0
- package/src/compat/client/errors/global-error.ts +238 -0
- package/src/compat/client/errors/install.ts +217 -0
- package/src/compat/client/errors/lazy.ts +53 -0
- package/src/compat/client/errors/primitive-throw.ts +126 -0
- package/src/compat/client/errors/soft-refresh.ts +14 -0
- package/src/compat/client/link-status.ts +86 -0
- package/src/compat/client/nav-compat-runtime.ts +57 -0
- package/src/compat/client/nav-compat.ts +42 -0
- package/src/compat/client/navigation-scroll.ts +154 -0
- package/src/compat/client/optimistic-routing.ts +206 -0
- package/src/compat/client/prefetch-cache.ts +111 -0
- package/src/compat/client/route-announcer.ts +72 -0
- package/src/compat/client/segment-cache-policy.ts +159 -0
- package/src/compat/client/segment-cache.ts +1077 -0
- package/src/compat/client/segment-prefetch.ts +375 -0
- package/src/compat/client/trailing-slash.ts +24 -0
- package/src/compat/css/chunking.ts +254 -0
- package/src/compat/css/inline-css.ts +73 -0
- package/src/compat/css/lightningcss.ts +90 -0
- package/src/compat/css/modules.ts +373 -0
- package/src/compat/css/nonce.ts +30 -0
- package/src/compat/css/sass-plugin.ts +65 -0
- package/src/compat/css/sass.ts +392 -0
- package/src/compat/css/styled-jsx-runtime.ts +80 -0
- package/src/compat/css/styled-jsx.ts +49 -0
- package/src/compat/edge-runtime.ts +71 -0
- package/src/compat/export/client.ts +112 -0
- package/src/compat/export/index.ts +272 -0
- package/src/compat/export/standalone.ts +207 -0
- package/src/compat/image-optimizer/cache.ts +119 -0
- package/src/compat/image-optimizer/detect.ts +143 -0
- package/src/compat/image-optimizer/index.ts +601 -0
- package/src/compat/image-optimizer/source.ts +243 -0
- package/src/compat/index.ts +458 -0
- package/src/compat/lifecycle/after-scope.ts +86 -0
- package/src/compat/lifecycle/after.ts +173 -0
- package/src/compat/lifecycle/error-funnel.ts +306 -0
- package/src/compat/lifecycle/error-serialize.ts +87 -0
- package/src/compat/lifecycle/error-ui.ts +167 -0
- package/src/compat/lifecycle/instrumentation-client.ts +138 -0
- package/src/compat/lifecycle/instrumentation.ts +277 -0
- package/src/compat/lifecycle/node-console.ts +19 -0
- package/src/compat/lifecycle/testmode.ts +263 -0
- package/src/compat/mdx/compile.ts +219 -0
- package/src/compat/mdx/next-mdx-stub.ts +46 -0
- package/src/compat/mdx/plugin.ts +37 -0
- package/src/compat/metadata-route-artifacts.ts +458 -0
- package/src/compat/metadata.ts +295 -0
- package/src/compat/middleware/manifest.ts +210 -0
- package/src/compat/misc/action-return.ts +173 -0
- package/src/compat/next/cache.ts +211 -0
- package/src/compat/next/canonical-url.ts +35 -0
- package/src/compat/next/client-cache.ts +57 -0
- package/src/compat/next/client-navigation.ts +313 -0
- package/src/compat/next/client-only.ts +3 -0
- package/src/compat/next/client-script.tsx +215 -0
- package/src/compat/next/client-server.ts +39 -0
- package/src/compat/next/config-loader.ts +569 -0
- package/src/compat/next/config.ts +29 -0
- package/src/compat/next/constants.cjs +6 -0
- package/src/compat/next/constants.ts +6 -0
- package/src/compat/next/custom-server.ts +236 -0
- package/src/compat/next/dist/client/components/app-router-headers.ts +32 -0
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +38 -0
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -0
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -0
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -0
- package/src/compat/next/dynamic.tsx +46 -0
- package/src/compat/next/error.tsx +148 -0
- package/src/compat/next/font/cache.ts +171 -0
- package/src/compat/next/font/google.ts +2 -0
- package/src/compat/next/font/index.ts +8 -0
- package/src/compat/next/font/local.ts +5 -0
- package/src/compat/next/font/runtime-client.ts +71 -0
- package/src/compat/next/font/runtime.ts +974 -0
- package/src/compat/next/font/shared.ts +281 -0
- package/src/compat/next/form.tsx +156 -0
- package/src/compat/next/head.tsx +10 -0
- package/src/compat/next/headers.ts +247 -0
- package/src/compat/next/image/config.ts +196 -0
- package/src/compat/next/image/optimizer.ts +96 -0
- package/src/compat/next/image/patterns.ts +103 -0
- package/src/compat/next/image/shared.ts +141 -0
- package/src/compat/next/image/static-metadata.ts +283 -0
- package/src/compat/next/image/validate.ts +269 -0
- package/src/compat/next/image-client.tsx +215 -0
- package/src/compat/next/image-props.ts +575 -0
- package/src/compat/next/image-usage.ts +102 -0
- package/src/compat/next/image.tsx +56 -0
- package/src/compat/next/index.ts +1 -0
- package/src/compat/next/legacy-image.tsx +97 -0
- package/src/compat/next/link-usage.ts +29 -0
- package/src/compat/next/link-validation-transform.ts +200 -0
- package/src/compat/next/link.tsx +466 -0
- package/src/compat/next/navigation.cjs +21 -0
- package/src/compat/next/navigation.ts +188 -0
- package/src/compat/next/offline.ts +51 -0
- package/src/compat/next/og.ts +324 -0
- package/src/compat/next/optimistic-route-state.ts +188 -0
- package/src/compat/next/preferred-region.ts +39 -0
- package/src/compat/next/redirects.ts +131 -0
- package/src/compat/next/resource-hints.ts +136 -0
- package/src/compat/next/rewrites.ts +350 -0
- package/src/compat/next/root-params.ts +142 -0
- package/src/compat/next/router.cjs +49 -0
- package/src/compat/next/router.ts +143 -0
- package/src/compat/next/script.tsx +355 -0
- package/src/compat/next/server-only.ts +3 -0
- package/src/compat/next/server.ts +28 -0
- package/src/compat/next/svgr.ts +58 -0
- package/src/compat/next/telemetry.ts +77 -0
- package/src/compat/next/user-agent.ts +100 -0
- package/src/compat/next/web-vitals.ts +56 -0
- package/src/compat/otel/api.ts +95 -0
- package/src/compat/otel/client-trace-metadata.ts +71 -0
- package/src/compat/otel/fetch-span.ts +77 -0
- package/src/compat/otel/tracer.ts +944 -0
- package/src/compat/pages/client-plugin.ts +108 -0
- package/src/compat/pages/index.ts +527 -0
- package/src/compat/pages/router-state.ts +94 -0
- package/src/compat/ppr/io.ts +38 -0
- package/src/compat/ppr/missing-root-params.ts +105 -0
- package/src/compat/ppr/root-params-scan.ts +164 -0
- package/src/compat/ppr/root-params-transform.ts +75 -0
- package/src/compat/ppr/root-params.ts +129 -0
- package/src/compat/ppr/segment-config-incompat.ts +34 -0
- package/src/compat/protocol.ts +202 -0
- package/src/compat/react/client.ts +59 -0
- package/src/compat/react/compiler-runtime.ts +60 -0
- package/src/compat/react/dom-client.ts +115 -0
- package/src/compat/react/dom-react-server.ts +20 -0
- package/src/compat/react/dom-server.ts +40 -0
- package/src/compat/react/dom.ts +154 -0
- package/src/compat/react/preact.ts +522 -0
- package/src/compat/react/react-server.ts +84 -0
- package/src/compat/react/router-shim.ts +26 -0
- package/src/compat/react/server-component-use.ts +48 -0
- package/src/compat/react/server-inserted-html.ts +87 -0
- package/src/compat/react/server.ts +156 -0
- package/src/compat/react/view-transition.ts +60 -0
- package/src/compat/register/actions.ts +875 -0
- package/src/compat/register/boot.ts +141 -0
- package/src/compat/register/build-tier.ts +11 -0
- package/src/compat/register/build.ts +182 -0
- package/src/compat/register/bundler.ts +587 -0
- package/src/compat/register/cache.ts +85 -0
- package/src/compat/register/client-errors.ts +18 -0
- package/src/compat/register/config.ts +17 -0
- package/src/compat/register/css-extras.ts +120 -0
- package/src/compat/register/edge-runtime.ts +6 -0
- package/src/compat/register/errors.ts +46 -0
- package/src/compat/register/export.ts +23 -0
- package/src/compat/register/font.ts +36 -0
- package/src/compat/register/hooks.ts +34 -0
- package/src/compat/register/image.ts +133 -0
- package/src/compat/register/index.ts +111 -0
- package/src/compat/register/instrumentation-client.ts +35 -0
- package/src/compat/register/lifecycle.ts +86 -0
- package/src/compat/register/mdx.ts +48 -0
- package/src/compat/register/middleware.ts +36 -0
- package/src/compat/register/misc.ts +44 -0
- package/src/compat/register/otel.ts +288 -0
- package/src/compat/register/pages-api.ts +473 -0
- package/src/compat/register/ppr.ts +56 -0
- package/src/compat/register/protocol.ts +57 -0
- package/src/compat/register/proxy.ts +127 -0
- package/src/compat/register/render.ts +268 -0
- package/src/compat/register/routing.ts +410 -0
- package/src/compat/register/segment.ts +1903 -0
- package/src/compat/register/static-image.ts +21 -0
- package/src/compat/register/typed-routes.ts +35 -0
- package/src/compat/register/usecache.ts +131 -0
- package/src/compat/register/validation.ts +56 -0
- package/src/compat/segment/loading-boundary.ts +113 -0
- package/src/compat/segment/page-slot.ts +200 -0
- package/src/compat/segment/tree.ts +481 -0
- package/src/compat/segment/vary-key.ts +102 -0
- package/src/compat/segment/vary-params.ts +551 -0
- package/src/compat/static-params.ts +33 -0
- package/src/compat/tsconfig-defaults.ts +301 -0
- package/src/compat/typecheck/index.ts +1481 -0
- package/src/compat/typecheck/worker.ts +26 -0
- package/src/compat/typed-routes/index.ts +92 -0
- package/src/compat/typed-routes/manifest.ts +356 -0
- package/src/compat/typed-routes/typegen.ts +566 -0
- package/src/compat/validation/errors.ts +159 -0
- package/src/compat/validation/index.ts +1770 -0
- package/src/compat/validation/prerender-diagnostics.ts +1508 -0
- package/src/compat-bootstrap.ts +67 -0
- package/src/config.ts +218 -0
- package/src/css/build.ts +697 -0
- package/src/css/index.ts +2 -0
- package/src/css/postcss.ts +236 -0
- package/src/css/worker.ts +34 -0
- package/src/dev/client-actions.ts +35 -0
- package/src/dev/client-chunk-store.ts +92 -0
- package/src/dev/client-key-cache.ts +178 -0
- package/src/dev/global-css-cache.ts +212 -0
- package/src/dev/imports.ts +2430 -0
- package/src/dev/module-cache.ts +721 -0
- package/src/dev/module-generations.ts +38 -0
- package/src/dev/module-transform.ts +188 -0
- package/src/dev/node-module-bundle-cache.ts +63 -0
- package/src/dev/restart-cache.ts +10 -0
- package/src/dev/route-bundle-key-cache.ts +154 -0
- package/src/dev/route-facts-cache.ts +223 -0
- package/src/dev/server.ts +1710 -0
- package/src/dynamic/source.ts +307 -0
- package/src/dynamic/tree-shake.ts +262 -0
- package/src/env.ts +92 -0
- package/src/extensions.ts +1898 -0
- package/src/index.ts +34 -0
- package/src/internal.ts +43 -0
- package/src/islands/boundary-error.ts +8 -0
- package/src/islands/static-children.ts +37 -0
- package/src/islands/static-slots.ts +106 -0
- package/src/ppr-postpone.ts +24 -0
- package/src/ppr.ts +784 -0
- package/src/proxy.ts +752 -0
- package/src/render/hooks.ts +384 -0
- package/src/render/index.ts +1 -0
- package/src/render/island-context.ts +47 -0
- package/src/render/metadata.ts +857 -0
- package/src/render/renderer.ts +7391 -0
- package/src/render/resource-hints.ts +44 -0
- package/src/render/slots.tsx +679 -0
- package/src/request/context.ts +396 -0
- package/src/resolve/engine.ts +219 -0
- package/src/resolve/imports.ts +1104 -0
- package/src/resolve/scan-facts.ts +474 -0
- package/src/resolve/source-text.ts +86 -0
- package/src/routing/forwarded.ts +41 -0
- package/src/routing/handler.ts +271 -0
- package/src/routing/href.ts +203 -0
- package/src/routing/metadata.ts +1018 -0
- package/src/routing/request-runtime.ts +43 -0
- package/src/routing/routes.ts +2560 -0
- package/src/routing/slots.ts +432 -0
- package/src/runtime/server.ts +3453 -0
- package/src/runtime/vendor.ts +1160 -0
- package/src/style-modules.d.ts +9 -0
- package/src/typegen.ts +151 -0
- package/src/types.ts +725 -0
- package/src/utils/ansi.ts +9 -0
- package/src/utils/content-type.ts +31 -0
- package/src/utils/decode.ts +7 -0
- package/src/utils/dev-profile.ts +31 -0
- package/src/utils/error-log.ts +29 -0
- package/src/utils/fs-cache.ts +31 -0
- package/src/utils/fs.ts +119 -0
- package/src/utils/html.ts +46 -0
- package/src/utils/serialize.ts +378 -0
- package/src/utils/source.ts +35 -0
- package/src/utils/verbose.ts +39 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// The typecheck, run on its own thread, so `typescript`'s multi-megabyte import lands off the build
|
|
2
|
+
// thread and runs alongside client bundling and prerendering.
|
|
3
|
+
//
|
|
4
|
+
// The thread gets the two config fields the checker reads plus a serializable projection of
|
|
5
|
+
// next.config, so it never re-loads the app's config.
|
|
6
|
+
|
|
7
|
+
import { parentPort, workerData } from 'node:worker_threads';
|
|
8
|
+
import type { ResolvedConfig } from '../../config';
|
|
9
|
+
import { setNextConfig } from '../next/config-loader';
|
|
10
|
+
import { PnextTypecheckError, validateTypes } from './index';
|
|
11
|
+
import type { TypecheckWorkerInput, TypecheckWorkerResult } from './index';
|
|
12
|
+
|
|
13
|
+
const input = workerData as TypecheckWorkerInput;
|
|
14
|
+
setNextConfig(input.nextConfig);
|
|
15
|
+
|
|
16
|
+
let result: TypecheckWorkerResult;
|
|
17
|
+
try {
|
|
18
|
+
await validateTypes({ root: input.root, outPath: input.outPath } as ResolvedConfig);
|
|
19
|
+
result = { ok: true };
|
|
20
|
+
} catch (error) {
|
|
21
|
+
result =
|
|
22
|
+
error instanceof PnextTypecheckError
|
|
23
|
+
? { ok: false, messages: error.message.split('\n\n') }
|
|
24
|
+
: { ok: false, failure: error instanceof Error ? error.stack || error.message : String(error) };
|
|
25
|
+
}
|
|
26
|
+
parentPort?.postMessage(result);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Writes `.next/types/{routes.d.ts,link.d.ts,validator.ts}` from a Next-shaped
|
|
2
|
+
// route-types manifest so the typed-routes / typed-routes-validator suites (which
|
|
3
|
+
// read `<distDir>/types/*` and run `tsc --noEmit`) pass. Compat-only.
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import type { ResolvedConfig } from '../../config';
|
|
8
|
+
import type { RouteManifestEntry } from '../../types';
|
|
9
|
+
import { ensureDir, toPosixPath } from '../../utils/fs';
|
|
10
|
+
import { getNextConfig } from '../next/config-loader';
|
|
11
|
+
import { scanRootParamTypes, type RootParamValueType } from '../ppr/root-params-scan';
|
|
12
|
+
import { buildRouteTypesManifest } from './manifest';
|
|
13
|
+
import { generateLinkTypesFile, generateRouteTypesFile, generateValidatorFile } from './typegen';
|
|
14
|
+
|
|
15
|
+
async function writeIfChanged(file: string, source: string): Promise<void> {
|
|
16
|
+
if (existsSync(file) && (await readFile(file, 'utf8')) === source) return;
|
|
17
|
+
await ensureDir(path.dirname(file));
|
|
18
|
+
await writeFile(file, source);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function generateTypedRoutes(
|
|
22
|
+
config: ResolvedConfig,
|
|
23
|
+
routes: RouteManifestEntry[],
|
|
24
|
+
): Promise<void> {
|
|
25
|
+
const nextConfig = getNextConfig();
|
|
26
|
+
const typedRoutes = nextConfig.typedRoutes === true;
|
|
27
|
+
|
|
28
|
+
const manifest = await buildRouteTypesManifest({ config, routes, nextConfig });
|
|
29
|
+
|
|
30
|
+
// Next writes generated types into `<distDir>/types`; the harness maps
|
|
31
|
+
// distDir to `.next`, and the fixtures read `<distDir>/types/*` + include
|
|
32
|
+
// them via tsconfig's `**/*.ts` glob.
|
|
33
|
+
const typesDir = path.join(config.root, '.next', 'types');
|
|
34
|
+
|
|
35
|
+
await writeIfChanged(path.join(typesDir, 'routes.d.ts'), generateRouteTypesFile(manifest));
|
|
36
|
+
|
|
37
|
+
// Import specifiers in validator.ts are relative to the validator file's dir.
|
|
38
|
+
const toImportSpecifier = (rootRelativePath: string): string => {
|
|
39
|
+
const abs = path.join(config.root, rootRelativePath);
|
|
40
|
+
const rel = toPosixPath(path.relative(typesDir, abs));
|
|
41
|
+
return rel.startsWith('.') ? rel : `./${rel}`;
|
|
42
|
+
};
|
|
43
|
+
await writeIfChanged(
|
|
44
|
+
path.join(typesDir, 'validator.ts'),
|
|
45
|
+
generateValidatorFile(manifest, toImportSpecifier),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
if (typedRoutes) {
|
|
49
|
+
await writeIfChanged(path.join(typesDir, 'link.d.ts'), generateLinkTypesFile(manifest));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Next generates `<distDir>/types/root-params.d.ts` — a `declare module
|
|
53
|
+
// 'next/root-params'` with one async getter per root param — and imports it
|
|
54
|
+
// from next-env.d.ts (typecheck suite runs the app's own `tsc --noEmit`).
|
|
55
|
+
await writeIfChanged(
|
|
56
|
+
path.join(typesDir, 'root-params.d.ts'),
|
|
57
|
+
rootParamsTypesFile(scanRootParamTypes(path.join(config.root, 'app'))),
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
// Next writes `next-env.d.ts` with reference imports so tsc - which does NOT traverse the dotfolder
|
|
61
|
+
// `.next/` via the tsconfig glob - pulls the generated types, and thus the global
|
|
62
|
+
// PageProps/LayoutProps/RouteContext and the next/link href augmentation, into the program. Without it a
|
|
63
|
+
// plain `tsc --noEmit` in the app never sees the generated files.
|
|
64
|
+
await writeNextEnv(config.root, typedRoutes);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Match Next's generated file byte-for-byte (ordering + comment banner): the
|
|
68
|
+
// getters sort by name, and value types print string, string[], undefined.
|
|
69
|
+
function rootParamsTypesFile(rootParams: Map<string, Set<RootParamValueType>>): string {
|
|
70
|
+
if (rootParams.size === 0) {
|
|
71
|
+
return `// Type definitions for Next.js root params (next/root-params)\n// No root params detected.\nexport {}\n`;
|
|
72
|
+
}
|
|
73
|
+
const order: RootParamValueType[] = ['string', 'string[]', 'undefined'];
|
|
74
|
+
const getters = [...rootParams.entries()]
|
|
75
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
76
|
+
.map(([name, types]) => {
|
|
77
|
+
const union = order.filter(type => types.has(type)).join(' | ');
|
|
78
|
+
return ` export function ${name}(): Promise<${union}>`;
|
|
79
|
+
});
|
|
80
|
+
return `// Type definitions for Next.js root params (next/root-params)\n\ndeclare module 'next/root-params' {\n${getters.join('\n')}\n}\n`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function writeNextEnv(root: string, typedRoutes: boolean): Promise<void> {
|
|
84
|
+
const lines = [
|
|
85
|
+
'/// <reference types="next" />',
|
|
86
|
+
'import "./.next/types/routes.d.ts";',
|
|
87
|
+
'import "./.next/types/root-params.d.ts";',
|
|
88
|
+
];
|
|
89
|
+
if (typedRoutes) lines.push('import "./.next/types/link.d.ts";');
|
|
90
|
+
lines.push('', '// NOTE: This file should not be edited', '');
|
|
91
|
+
await writeIfChanged(path.join(root, 'next-env.d.ts'), lines.join('\n'));
|
|
92
|
+
}
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
// Builds a Next-shaped route-types manifest from pnext's route entries, an
|
|
2
|
+
// independent scan of app-dir layouts/slots and the pages/ directory, plus the
|
|
3
|
+
// redirects/rewrites from next.config. Feeds the Next-identical codegen in
|
|
4
|
+
// ./typegen.ts. Compat-only.
|
|
5
|
+
import { existsSync } from 'node:fs';
|
|
6
|
+
import { readdir } from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import type { ResolvedConfig } from '../../config';
|
|
9
|
+
import type { RouteManifestEntry } from '../../types';
|
|
10
|
+
import { toPosixPath } from '../../utils/fs';
|
|
11
|
+
|
|
12
|
+
/** path-to-regexp group info, mirroring Next's `getRouteRegex().groups`. */
|
|
13
|
+
export interface Group {
|
|
14
|
+
pos: number;
|
|
15
|
+
repeat: boolean;
|
|
16
|
+
optional: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ManifestRouteInfo {
|
|
20
|
+
path: string;
|
|
21
|
+
groups: Record<string, Group>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RouteTypesManifest {
|
|
25
|
+
appRoutes: Record<string, ManifestRouteInfo>;
|
|
26
|
+
pageRoutes: Record<string, ManifestRouteInfo>;
|
|
27
|
+
layoutRoutes: Record<string, ManifestRouteInfo & { slots: string[] }>;
|
|
28
|
+
appRouteHandlerRoutes: Record<string, ManifestRouteInfo>;
|
|
29
|
+
redirectRoutes: Record<string, ManifestRouteInfo>;
|
|
30
|
+
rewriteRoutes: Record<string, ManifestRouteInfo>;
|
|
31
|
+
appPagePaths: Set<string>;
|
|
32
|
+
pagesRouterPagePaths: Set<string>;
|
|
33
|
+
layoutPaths: Set<string>;
|
|
34
|
+
appRouteHandlers: Set<string>;
|
|
35
|
+
pageApiRoutes: Set<string>;
|
|
36
|
+
filePathToRoute: Map<string, string>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const PAGE_EXTENSIONS = ['tsx', 'ts', 'jsx', 'js', 'mdx', 'md'];
|
|
40
|
+
const LAYOUT_NAMES = new Set(PAGE_EXTENSIONS.map(ext => `layout.${ext}`));
|
|
41
|
+
|
|
42
|
+
function isGroupSegment(name: string): boolean {
|
|
43
|
+
return name.startsWith('(') && name.endsWith(')');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isSlotSegment(name: string): boolean {
|
|
47
|
+
return name.startsWith('@');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function decodeLiteral(segment: string): string {
|
|
51
|
+
return segment.replace(/%5[Ff]/g, '_');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Extract groups (param name -> shape) from a bracket-syntax route. */
|
|
55
|
+
function groupsFromBracketRoute(route: string): Record<string, Group> {
|
|
56
|
+
const groups: Record<string, Group> = {};
|
|
57
|
+
let pos = 1;
|
|
58
|
+
for (const segment of route.split('/').filter(Boolean)) {
|
|
59
|
+
const optionalCatchAll = /^\[\[\.\.\.(.+)\]\]$/.exec(segment);
|
|
60
|
+
if (optionalCatchAll?.[1]) {
|
|
61
|
+
groups[optionalCatchAll[1]] = { pos: pos++, repeat: true, optional: true };
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const catchAll = /^\[\.\.\.(.+)\]$/.exec(segment);
|
|
65
|
+
if (catchAll?.[1]) {
|
|
66
|
+
groups[catchAll[1]] = { pos: pos++, repeat: true, optional: false };
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const param = /^\[(.+)\]$/.exec(segment);
|
|
70
|
+
if (param?.[1]) {
|
|
71
|
+
groups[param[1]] = { pos: pos++, repeat: false, optional: false };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return groups;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Turn a pnext `route` (`:param` / `:param*` form, groups already stripped and
|
|
79
|
+
* `%5F` decoded) plus its catch-all flags into Next bracket syntax.
|
|
80
|
+
*/
|
|
81
|
+
function bracketRouteFromEntry(entry: RouteManifestEntry): string {
|
|
82
|
+
const segments = entry.route.split('/').filter(Boolean).map(segment => {
|
|
83
|
+
const catchAll = /^:(.+)\*$/.exec(segment);
|
|
84
|
+
if (catchAll?.[1]) {
|
|
85
|
+
const name = catchAll[1];
|
|
86
|
+
return name === entry.catchAll && entry.catchAllOptional
|
|
87
|
+
? `[[...${name}]]`
|
|
88
|
+
: `[...${name}]`;
|
|
89
|
+
}
|
|
90
|
+
const param = /^:(.+)$/.exec(segment);
|
|
91
|
+
if (param?.[1]) return `[${param[1]}]`;
|
|
92
|
+
return segment;
|
|
93
|
+
});
|
|
94
|
+
return `/${segments.join('/')}`.replace(/\/$/, '') || '/';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Bracket route derived from a directory path relative to app/ (for layouts). */
|
|
98
|
+
function bracketRouteFromDir(relativeDir: string): string {
|
|
99
|
+
const segments: string[] = [];
|
|
100
|
+
for (const segment of relativeDir.split('/').filter(Boolean)) {
|
|
101
|
+
if (isGroupSegment(segment) || isSlotSegment(segment)) continue;
|
|
102
|
+
if (/^\[\[?\.\.\..+\]\]?$/.test(segment) || /^\[.+\]$/.test(segment)) {
|
|
103
|
+
segments.push(segment);
|
|
104
|
+
} else {
|
|
105
|
+
segments.push(decodeLiteral(segment));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return `/${segments.join('/')}`.replace(/\/$/, '') || '/';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function pagesRouteFromRelative(relative: string): string {
|
|
112
|
+
const withoutExt = relative.replace(/\.[^.]+$/, '');
|
|
113
|
+
const trimmed = withoutExt.replace(/\/index$/, '').replace(/^index$/, '');
|
|
114
|
+
const route = `/${trimmed}`.replace(/\/$/, '') || '/';
|
|
115
|
+
return route;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function walkFiles(dir: string): Promise<string[]> {
|
|
119
|
+
if (!existsSync(dir)) return [];
|
|
120
|
+
const out: string[] = [];
|
|
121
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
122
|
+
for (const entry of entries) {
|
|
123
|
+
const full = path.join(dir, entry.name);
|
|
124
|
+
if (entry.isDirectory()) out.push(...(await walkFiles(full)));
|
|
125
|
+
else out.push(full);
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A private app segment (`_foo`, but not `%5F`-encoded or a group/slot) makes
|
|
132
|
+
* the whole route non-routable.
|
|
133
|
+
*/
|
|
134
|
+
function isPrivate(relativeDir: string): boolean {
|
|
135
|
+
return relativeDir
|
|
136
|
+
.split('/')
|
|
137
|
+
.some(seg => seg.startsWith('_') && !isGroupSegment(seg) && !isSlotSegment(seg));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// path-to-regexp custom-route source -> bracket routes. The fixture only uses
|
|
141
|
+
// `:name`, `:name+`, `:name*`; other modifiers/patterns are skipped like Next.
|
|
142
|
+
function convertCustomRouteSource(source: string): string[] {
|
|
143
|
+
const normalized = source.startsWith('/') ? source : `/${source}`;
|
|
144
|
+
const converted = normalized
|
|
145
|
+
.split('/')
|
|
146
|
+
.map(segment => {
|
|
147
|
+
const optional = /^:(.+)\*$/.exec(segment);
|
|
148
|
+
if (optional?.[1]) return `[[...${optional[1]}]]`;
|
|
149
|
+
const catchAll = /^:(.+)\+$/.exec(segment);
|
|
150
|
+
if (catchAll?.[1]) return `[...${catchAll[1]}]`;
|
|
151
|
+
const param = /^:([A-Za-z0-9_]+)$/.exec(segment);
|
|
152
|
+
if (param?.[1]) return `[${param[1]}]`;
|
|
153
|
+
return segment;
|
|
154
|
+
})
|
|
155
|
+
.join('/');
|
|
156
|
+
return [converted.replace(/\/$/, '') || '/'];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
interface CustomRoute {
|
|
160
|
+
source: string;
|
|
161
|
+
}
|
|
162
|
+
type RedirectsFn = () => Promise<CustomRoute[]> | CustomRoute[];
|
|
163
|
+
type RewritesFn = () =>
|
|
164
|
+
| Promise<CustomRoute[] | { beforeFiles?: CustomRoute[]; afterFiles?: CustomRoute[]; fallback?: CustomRoute[] }>
|
|
165
|
+
| CustomRoute[]
|
|
166
|
+
| { beforeFiles?: CustomRoute[]; afterFiles?: CustomRoute[]; fallback?: CustomRoute[] };
|
|
167
|
+
|
|
168
|
+
export interface BuildManifestInput {
|
|
169
|
+
config: ResolvedConfig;
|
|
170
|
+
routes: RouteManifestEntry[];
|
|
171
|
+
nextConfig: { redirects?: unknown; rewrites?: unknown };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export async function buildRouteTypesManifest({
|
|
175
|
+
config,
|
|
176
|
+
routes,
|
|
177
|
+
nextConfig,
|
|
178
|
+
}: BuildManifestInput): Promise<RouteTypesManifest> {
|
|
179
|
+
const relApp = (file: string) => toPosixPath(path.relative(config.root, file));
|
|
180
|
+
const isHybrid = config.appPath.includes('pnext-pages-compat');
|
|
181
|
+
const sourceAppPath = (entry: RouteManifestEntry): string | undefined => {
|
|
182
|
+
if (!isHybrid) return entry.file;
|
|
183
|
+
const basename = entry.kind === 'page' ? /^page\.(?:tsx?|jsx?|mdx?)$/ : /^route\.(?:tsx?|jsx?)$/;
|
|
184
|
+
const source = entry.sourceFiles.find(file => {
|
|
185
|
+
const normalized = toPosixPath(file);
|
|
186
|
+
return normalized.includes('/source-app/') && basename.test(path.basename(normalized));
|
|
187
|
+
});
|
|
188
|
+
if (!source) return undefined;
|
|
189
|
+
const relative = toPosixPath(source).split('/source-app/')[1];
|
|
190
|
+
return relative ? path.join(config.root, 'app', relative) : undefined;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const manifest: RouteTypesManifest = {
|
|
194
|
+
appRoutes: {},
|
|
195
|
+
pageRoutes: {},
|
|
196
|
+
layoutRoutes: {},
|
|
197
|
+
appRouteHandlerRoutes: {},
|
|
198
|
+
redirectRoutes: {},
|
|
199
|
+
rewriteRoutes: {},
|
|
200
|
+
appPagePaths: new Set(),
|
|
201
|
+
pagesRouterPagePaths: new Set(),
|
|
202
|
+
layoutPaths: new Set(),
|
|
203
|
+
appRouteHandlers: new Set(),
|
|
204
|
+
pageApiRoutes: new Set(),
|
|
205
|
+
filePathToRoute: new Map(),
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// App pages + route handlers from pnext's scanned entries. Skip synthetic /
|
|
209
|
+
// interception entries (typegen resolves interceptors to their canonical page
|
|
210
|
+
// which is already scanned). When in hybrid mode (app + pages), config.appPath
|
|
211
|
+
// points at a generated compat directory containing wrappers for both app and
|
|
212
|
+
// pages. For typegen we only want original app routes in AppRoutes, not pages
|
|
213
|
+
// wrappers which belong in PageRoutes.
|
|
214
|
+
const hybridFilteredRoutes = isHybrid
|
|
215
|
+
? routes.filter(entry => {
|
|
216
|
+
const file = entry.file;
|
|
217
|
+
if (!file.includes('pnext-pages-compat')) return true;
|
|
218
|
+
const sourceFiles = (entry as { sourceFiles?: string[] }).sourceFiles ?? [];
|
|
219
|
+
const isPagesWrapper = sourceFiles.some(sf => sf.includes('source-pages'));
|
|
220
|
+
if (isPagesWrapper) return false;
|
|
221
|
+
return true;
|
|
222
|
+
})
|
|
223
|
+
: routes;
|
|
224
|
+
|
|
225
|
+
for (const entry of hybridFilteredRoutes) {
|
|
226
|
+
if (entry.synthetic || entry.interception || entry.metadataRoute) continue;
|
|
227
|
+
const source = sourceAppPath(entry);
|
|
228
|
+
if (!source) continue;
|
|
229
|
+
const bracket = bracketRouteFromEntry(entry);
|
|
230
|
+
const rel = relApp(source);
|
|
231
|
+
const info: ManifestRouteInfo = { path: rel, groups: groupsFromBracketRoute(bracket) };
|
|
232
|
+
if (entry.kind === 'page') {
|
|
233
|
+
if (!manifest.appRoutes[bracket]) manifest.appRoutes[bracket] = info;
|
|
234
|
+
// appPagePaths/filePathToRoute (the validator inputs) are populated by an independent filesystem scan
|
|
235
|
+
// below, NOT from runtime entries: pnext's scanner collapses parallel-route slot pages onto a single
|
|
236
|
+
// representative route entry, which mis-maps a slot page's route and drops its siblings, breaking the
|
|
237
|
+
// generated validator's tsc.
|
|
238
|
+
} else {
|
|
239
|
+
if (!manifest.appRouteHandlerRoutes[bracket]) manifest.appRouteHandlerRoutes[bracket] = info;
|
|
240
|
+
manifest.appRouteHandlers.add(rel);
|
|
241
|
+
manifest.filePathToRoute.set(rel, bracket);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Layouts + slots: independent app-dir scan (pnext entries don't carry them).
|
|
246
|
+
const appFiles = await walkFiles(isHybrid ? path.join(config.root, 'app') : config.appPath);
|
|
247
|
+
const appPath = isHybrid ? path.join(config.root, 'app') : config.appPath;
|
|
248
|
+
for (const file of appFiles) {
|
|
249
|
+
const relative = toPosixPath(path.relative(appPath, file));
|
|
250
|
+
const base = path.basename(relative);
|
|
251
|
+
if (!LAYOUT_NAMES.has(base)) continue;
|
|
252
|
+
const dir = path.dirname(relative) === '.' ? '' : path.dirname(relative);
|
|
253
|
+
if (isPrivate(dir)) continue;
|
|
254
|
+
const bracket = bracketRouteFromDir(dir);
|
|
255
|
+
const rel = relApp(file);
|
|
256
|
+
if (!manifest.layoutRoutes[bracket]) {
|
|
257
|
+
manifest.layoutRoutes[bracket] = {
|
|
258
|
+
path: rel,
|
|
259
|
+
groups: groupsFromBracketRoute(bracket),
|
|
260
|
+
slots: [],
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
manifest.layoutPaths.add(rel);
|
|
264
|
+
manifest.filePathToRoute.set(rel, bracket);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Slots: `@name` dirs whose nearest ancestor layout owns them. A path can
|
|
268
|
+
// pass through multiple slot dirs (e.g. `@modal/(.)test-nested/@sidebar`);
|
|
269
|
+
// the slot that owns a given file is the deepest (last) one on the path,
|
|
270
|
+
// not the first, since the layout receiving the prop lives directly under it.
|
|
271
|
+
for (const file of appFiles) {
|
|
272
|
+
const relative = toPosixPath(path.relative(appPath, file));
|
|
273
|
+
const segments = relative.split('/');
|
|
274
|
+
let slotIndex = -1;
|
|
275
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
276
|
+
if (isSlotSegment(segments[i]!)) {
|
|
277
|
+
slotIndex = i;
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (slotIndex === -1) continue;
|
|
282
|
+
const slotName = segments[slotIndex]!.slice(1);
|
|
283
|
+
const ownerDir = segments.slice(0, slotIndex).join('/');
|
|
284
|
+
if (isPrivate(ownerDir)) continue;
|
|
285
|
+
const ownerRoute = bracketRouteFromDir(ownerDir);
|
|
286
|
+
const layout = manifest.layoutRoutes[ownerRoute];
|
|
287
|
+
if (layout && !layout.slots.includes(slotName)) layout.slots.push(slotName);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// App pages for the validator: an independent filesystem scan of every `page.{ext}` (including
|
|
291
|
+
// parallel-route slot pages), each mapped to its dir-derived route with group/slot segments stripped.
|
|
292
|
+
// Next validates each page file's `default` export against `AppPageConfig<its-route>`; a slot page like
|
|
293
|
+
// `dashboard/@analytics/page.tsx` renders at `/dashboard`, so it must validate against `/dashboard`.
|
|
294
|
+
// Guarded to routes that are actually routable, so private and interception pages are excluded - the
|
|
295
|
+
// AppPageConfig<Route> constraint requires `Route extends AppRoutes`.
|
|
296
|
+
const PAGE_BASENAMES = new Set(PAGE_EXTENSIONS.map(ext => `page.${ext}`));
|
|
297
|
+
for (const file of appFiles) {
|
|
298
|
+
const relative = toPosixPath(path.relative(appPath, file));
|
|
299
|
+
if (!PAGE_BASENAMES.has(path.basename(relative))) continue;
|
|
300
|
+
const dir = path.dirname(relative) === '.' ? '' : path.dirname(relative);
|
|
301
|
+
if (isPrivate(dir)) continue;
|
|
302
|
+
const route = bracketRouteFromDir(dir);
|
|
303
|
+
if (!manifest.appRoutes[route]) continue;
|
|
304
|
+
const rel = relApp(file);
|
|
305
|
+
manifest.appPagePaths.add(rel);
|
|
306
|
+
manifest.filePathToRoute.set(rel, route);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Pages Router: pages/*.{ext} (non-api) -> pageRoutes; pages/api/** -> pageApiRoutes.
|
|
310
|
+
const pagesDir = path.join(config.root, 'pages');
|
|
311
|
+
for (const file of await walkFiles(pagesDir)) {
|
|
312
|
+
const relative = toPosixPath(path.relative(pagesDir, file));
|
|
313
|
+
if (!PAGE_EXTENSIONS.some(ext => relative.endsWith(`.${ext}`))) continue;
|
|
314
|
+
const base = path.basename(relative);
|
|
315
|
+
if (base.startsWith('_app.') || base.startsWith('_document.') || base.startsWith('_error.')) {
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
const rel = relApp(file);
|
|
319
|
+
const isApi = relative === 'api' || relative.startsWith('api/');
|
|
320
|
+
const route = pagesRouteFromRelative(relative);
|
|
321
|
+
if (isApi) {
|
|
322
|
+
manifest.pageApiRoutes.add(rel);
|
|
323
|
+
manifest.filePathToRoute.set(rel, route);
|
|
324
|
+
} else {
|
|
325
|
+
manifest.pageRoutes[route] = { path: rel, groups: groupsFromBracketRoute(route) };
|
|
326
|
+
manifest.pagesRouterPagePaths.add(rel);
|
|
327
|
+
manifest.filePathToRoute.set(rel, route);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// redirects / rewrites from next.config.
|
|
332
|
+
const redirects = nextConfig.redirects;
|
|
333
|
+
if (typeof redirects === 'function') {
|
|
334
|
+
const list = await (redirects as RedirectsFn)();
|
|
335
|
+
for (const item of list ?? []) {
|
|
336
|
+
for (const route of convertCustomRouteSource(item.source)) {
|
|
337
|
+
manifest.redirectRoutes[route] = { path: route, groups: groupsFromBracketRoute(route) };
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const rewrites = nextConfig.rewrites;
|
|
343
|
+
if (typeof rewrites === 'function') {
|
|
344
|
+
const result = await (rewrites as RewritesFn)();
|
|
345
|
+
const sources = Array.isArray(result)
|
|
346
|
+
? result
|
|
347
|
+
: [...(result?.beforeFiles ?? []), ...(result?.afterFiles ?? []), ...(result?.fallback ?? [])];
|
|
348
|
+
for (const item of sources) {
|
|
349
|
+
for (const route of convertCustomRouteSource(item.source)) {
|
|
350
|
+
manifest.rewriteRoutes[route] = { path: route, groups: groupsFromBracketRoute(route) };
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return manifest;
|
|
356
|
+
}
|