@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,1481 @@
|
|
|
1
|
+
import { existsSync, statSync } from 'node:fs';
|
|
2
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { Worker } from 'node:worker_threads';
|
|
6
|
+
import type * as TS from 'typescript';
|
|
7
|
+
import type { ResolvedConfig } from '../../config';
|
|
8
|
+
import { getNextConfig, type NextConfigObject } from '../next/config-loader';
|
|
9
|
+
import { turbopackLoaderRules } from '../bundler/config';
|
|
10
|
+
import { scanRootParamTypes, type RootParamValueType } from '../ppr/root-params-scan';
|
|
11
|
+
|
|
12
|
+
export class PnextTypecheckError extends Error {
|
|
13
|
+
/** The individual diagnostics, kept so the worker can ship them across intact. */
|
|
14
|
+
readonly messages: string[];
|
|
15
|
+
constructor(messages: string[]) {
|
|
16
|
+
super(messages.join('\n'));
|
|
17
|
+
this.name = 'PnextTypecheckError';
|
|
18
|
+
this.messages = messages;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// `typescript` is 8 MB of JS and is needed ONLY to read the app's tsconfig
|
|
23
|
+
// (extends chains, ambient file lists) and as the fallback checker. Loading it
|
|
24
|
+
// lazily keeps it out of every build that never reaches this step.
|
|
25
|
+
let typescriptModule: typeof TS | undefined;
|
|
26
|
+
async function loadTypescript(): Promise<typeof TS> {
|
|
27
|
+
typescriptModule ??= (await import('typescript')) as unknown as typeof TS;
|
|
28
|
+
return typescriptModule;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* `typescript.ignoreBuildErrors` in next.config disables the production typecheck entirely. Fixtures that
|
|
33
|
+
* ship intentional type errors - a `fetch(..., { next: { revalidate: '1' } })` whose runtime error is what
|
|
34
|
+
* the test asserts - rely on the build completing so the app can start and surface it.
|
|
35
|
+
*/
|
|
36
|
+
export function typecheckDisabled(): boolean {
|
|
37
|
+
const typescript = getNextConfig().typescript as { ignoreBuildErrors?: unknown } | undefined;
|
|
38
|
+
return typescript?.ignoreBuildErrors === true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** What ./worker.ts needs to run the check without re-loading the app config. */
|
|
42
|
+
export interface TypecheckWorkerInput {
|
|
43
|
+
root: string;
|
|
44
|
+
outPath: string;
|
|
45
|
+
nextConfig: NextConfigObject;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type TypecheckWorkerResult =
|
|
49
|
+
| { ok: true }
|
|
50
|
+
| { ok: false; messages?: string[]; failure?: string };
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Run the check on a worker thread, so `typescript`'s large import and the diagnostics pass land
|
|
54
|
+
* off the build thread and overlap client bundling and prerendering.
|
|
55
|
+
*
|
|
56
|
+
* The checker reads only `typescript`, `typedRoutes` and `turbopack.rules` from next.config, so a
|
|
57
|
+
* structured-cloneable projection of those goes across rather than the real object (which can carry
|
|
58
|
+
* functions) or a second config load (which would re-run its telemetry and deprecation warnings).
|
|
59
|
+
* A worker that cannot start at all falls back to the in-process path rather than failing the build.
|
|
60
|
+
*/
|
|
61
|
+
export async function validateTypesOffThread(config: ResolvedConfig): Promise<void> {
|
|
62
|
+
if (typecheckDisabled()) return;
|
|
63
|
+
const next = getNextConfig();
|
|
64
|
+
const input: TypecheckWorkerInput = {
|
|
65
|
+
root: config.root,
|
|
66
|
+
outPath: config.outPath,
|
|
67
|
+
nextConfig: cloneable({
|
|
68
|
+
typescript: next.typescript,
|
|
69
|
+
typedRoutes: next.typedRoutes,
|
|
70
|
+
turbopack: next.turbopack,
|
|
71
|
+
}),
|
|
72
|
+
};
|
|
73
|
+
let worker: Worker;
|
|
74
|
+
try {
|
|
75
|
+
worker = new Worker(new URL('./worker.ts', import.meta.url), { workerData: input });
|
|
76
|
+
} catch {
|
|
77
|
+
return validateTypes(config);
|
|
78
|
+
}
|
|
79
|
+
const result = await new Promise<TypecheckWorkerResult>((resolve, reject) => {
|
|
80
|
+
worker.on('message', resolve);
|
|
81
|
+
worker.on('error', reject);
|
|
82
|
+
// A worker that exits without a message crashed in a way `error` missed;
|
|
83
|
+
// treat it as a clean check rather than failing a build over the harness.
|
|
84
|
+
worker.on('exit', () => resolve({ ok: true }));
|
|
85
|
+
}).finally(() => void worker.terminate());
|
|
86
|
+
if (result.ok) return;
|
|
87
|
+
if (result.messages) throw new PnextTypecheckError(result.messages);
|
|
88
|
+
throw new Error(result.failure ?? 'typecheck worker failed');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Drop anything structured-clone would reject (a `turbopack.rules` function). */
|
|
92
|
+
function cloneable(value: NextConfigObject): NextConfigObject {
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse(JSON.stringify(value)) as NextConfigObject;
|
|
95
|
+
} catch {
|
|
96
|
+
return {};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* TypeScript 7 (`tsgo`) is a separate process, so the check genuinely overlaps bundling instead of
|
|
102
|
+
* blocking the event loop - and it is much faster. It runs as the GATE: a clean TS 7 pass ends the check,
|
|
103
|
+
* which is every successful build.
|
|
104
|
+
*
|
|
105
|
+
* When it does report something, tsc 5.9 re-runs and owns the message text. The two compilers agree on
|
|
106
|
+
* which code is wrong but not always on how they say it - TS 7 collapses a failed generic constraint to
|
|
107
|
+
* the specific cause where 5.9 leads with the constraint itself, and Next's own wording is what the compat
|
|
108
|
+
* suites match. That second pass only ever runs on a build that is already failing.
|
|
109
|
+
*/
|
|
110
|
+
export async function validateTypes(config: ResolvedConfig): Promise<void> {
|
|
111
|
+
if (typecheckDisabled()) return;
|
|
112
|
+
const native = await nativeCheckerBin(config.root);
|
|
113
|
+
const project = await writeTypecheckProject(config, native);
|
|
114
|
+
if (native && (await checkWithNative(native, project, config)).length === 0) return;
|
|
115
|
+
const messages = await checkInProcess(project, config);
|
|
116
|
+
if (messages.length === 0) return;
|
|
117
|
+
throw new PnextTypecheckError(messages);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function checkInProcess(project: string, config: ResolvedConfig): Promise<string[]> {
|
|
121
|
+
const ts = await loadTypescript();
|
|
122
|
+
const parsed = readProject(ts, project);
|
|
123
|
+
const program = ts.createProgram(parsed.fileNames, parsed.options);
|
|
124
|
+
const diagnostics = ts
|
|
125
|
+
.getPreEmitDiagnostics(program)
|
|
126
|
+
.filter(diagnostic => appDiagnostic(diagnostic.file?.fileName, config));
|
|
127
|
+
return formatDiagnostics(ts, diagnostics);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The `tsgo` binary (`@typescript/native-preview`), resolved from the app first so a project pinning its
|
|
132
|
+
* own TS 7 wins. Absent means the in-process fallback. `PNEXT_TYPECHECK=classic` forces the fallback.
|
|
133
|
+
*/
|
|
134
|
+
async function nativeCheckerBin(root: string): Promise<string | undefined> {
|
|
135
|
+
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
136
|
+
if (process.env.PNEXT_TYPECHECK === 'classic') return undefined;
|
|
137
|
+
for (const base of [root, import.meta.dirname]) {
|
|
138
|
+
try {
|
|
139
|
+
const require = createRequire(path.join(base, 'noop.js'));
|
|
140
|
+
const pkg = require.resolve('@typescript/native-preview/package.json');
|
|
141
|
+
// The package exposes the platform binary only through its own resolver
|
|
142
|
+
// (the published `.` export is just a version stub).
|
|
143
|
+
const { default: getExePath } = (await import(
|
|
144
|
+
path.join(path.dirname(pkg), 'lib', 'getExePath.js')
|
|
145
|
+
)) as { default: () => string };
|
|
146
|
+
const bin = getExePath();
|
|
147
|
+
if (bin && existsSync(bin)) return bin;
|
|
148
|
+
} catch {
|
|
149
|
+
// keep looking
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async function checkWithNative(
|
|
156
|
+
bin: string,
|
|
157
|
+
project: string,
|
|
158
|
+
config: ResolvedConfig,
|
|
159
|
+
): Promise<string[]> {
|
|
160
|
+
const proc = Bun.spawn([bin, '--noEmit', '--pretty', 'false', '-p', project], {
|
|
161
|
+
cwd: config.root,
|
|
162
|
+
stdout: 'pipe',
|
|
163
|
+
stderr: 'pipe',
|
|
164
|
+
});
|
|
165
|
+
const [stdout, stderr] = await Promise.all([
|
|
166
|
+
new Response(proc.stdout).text(),
|
|
167
|
+
new Response(proc.stderr).text(),
|
|
168
|
+
]);
|
|
169
|
+
await proc.exited;
|
|
170
|
+
return nativeDiagnostics(`${stdout}${stderr}`, config);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Reshape `tsgo --pretty false` output into the same `<file>:<line>:<col>` plus `Type error: <message>`
|
|
175
|
+
* lines the in-process path produces. A diagnostic is one `file(line,col): error TSxxxx: message` header
|
|
176
|
+
* plus every indented elaboration line under it - the same text `flattenDiagnosticMessageText` builds from
|
|
177
|
+
* a message chain.
|
|
178
|
+
*/
|
|
179
|
+
function nativeDiagnostics(output: string, config: ResolvedConfig): string[] {
|
|
180
|
+
const header = /^(?:(.+)\((\d+),(\d+)\): )?error TS\d+: (.*)$/;
|
|
181
|
+
const messages = new Set<string>();
|
|
182
|
+
const lines = output.split('\n');
|
|
183
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
184
|
+
const match = header.exec(lines[index]!);
|
|
185
|
+
if (!match) continue;
|
|
186
|
+
const [, file, line, column, text] = match;
|
|
187
|
+
const elaborations: string[] = [];
|
|
188
|
+
while (index + 1 < lines.length && /^\s+\S/.test(lines[index + 1]!)) {
|
|
189
|
+
elaborations.push(lines[index + 1]!);
|
|
190
|
+
index += 1;
|
|
191
|
+
}
|
|
192
|
+
const resolved = file ? path.resolve(config.root, file) : undefined;
|
|
193
|
+
if (!appDiagnostic(resolved, config)) continue;
|
|
194
|
+
const raw = [text, ...elaborations].join('\n');
|
|
195
|
+
const location = resolved ? `${resolved}:${line}:${column}\n` : '';
|
|
196
|
+
messages.add(`${location}Type error: ${typedRouteMessage(raw) ?? raw}`);
|
|
197
|
+
}
|
|
198
|
+
return [...messages];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Only diagnostics originating in the app's own sources may fail the build;
|
|
202
|
+
// errors inside node_modules, pnext shims, or generated files are never the
|
|
203
|
+
// app author's fault (Next.js typechecks with the same scoping).
|
|
204
|
+
function appDiagnostic(file: string | undefined, config: ResolvedConfig): boolean {
|
|
205
|
+
if (!file) return true;
|
|
206
|
+
const resolved = path.resolve(file);
|
|
207
|
+
// The generated project is pnext's own; an option error in it (TS5102 and
|
|
208
|
+
// friends) is a framework bug and must never be silently swallowed.
|
|
209
|
+
if (resolved === generatedProjectPath(config)) return true;
|
|
210
|
+
if (!resolved.startsWith(config.root + path.sep)) return false;
|
|
211
|
+
if (resolved.includes(`${path.sep}node_modules${path.sep}`)) return false;
|
|
212
|
+
if (resolved.startsWith(path.resolve(config.outPath) + path.sep)) return false;
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function generatedProjectPath(config: ResolvedConfig): string {
|
|
217
|
+
return path.resolve(config.outPath, 'typecheck', 'tsconfig.json');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* The app's `react` import resolves to pnext's preact compat shim at runtime, whose types cannot satisfy
|
|
222
|
+
* React-typed app code. Point the typechecker at real `@types/react` instead - the app's own copy if
|
|
223
|
+
* installed, otherwise the one visible from pnext. React mappings intentionally override app paths, since
|
|
224
|
+
* they describe pnext's runtime aliases, while unrelated path mappings remain.
|
|
225
|
+
*
|
|
226
|
+
* Written INTO the generated tsconfig rather than patched onto parsed options, so the out-of-process
|
|
227
|
+
* checker sees exactly what the in-process one does.
|
|
228
|
+
*/
|
|
229
|
+
function reactTypePaths(
|
|
230
|
+
root: string,
|
|
231
|
+
basePaths: Record<string, string[]> | undefined,
|
|
232
|
+
compatPreact?: string,
|
|
233
|
+
): Record<string, string[]> | undefined {
|
|
234
|
+
const react = resolveTypesDir('react', root);
|
|
235
|
+
if (!react) return basePaths;
|
|
236
|
+
const reactDom = resolveTypesDir('react-dom', root);
|
|
237
|
+
const paths: Record<string, string[]> = { ...basePaths };
|
|
238
|
+
const mappings: Record<string, string | undefined> = {
|
|
239
|
+
react: path.join(react, 'index.d.ts'),
|
|
240
|
+
'react/*': path.join(react, '*'),
|
|
241
|
+
'react-dom': reactDom && path.join(reactDom, 'index.d.ts'),
|
|
242
|
+
'react-dom/*': reactDom && path.join(reactDom, '*'),
|
|
243
|
+
preact: compatPreact,
|
|
244
|
+
};
|
|
245
|
+
for (const [key, value] of Object.entries(mappings)) {
|
|
246
|
+
if (value) paths[key] = [value];
|
|
247
|
+
}
|
|
248
|
+
return paths;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function resolveTypesDir(name: string, root: string): string | undefined {
|
|
252
|
+
for (const base of [root, import.meta.dirname]) {
|
|
253
|
+
try {
|
|
254
|
+
const require = createRequire(path.join(base, 'noop.js'));
|
|
255
|
+
return path.dirname(require.resolve(`@types/${name}/package.json`));
|
|
256
|
+
} catch {
|
|
257
|
+
// keep looking
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return undefined;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Rebase an app's `paths` onto absolute targets so the generated project (which
|
|
264
|
+
// lives elsewhere and can no longer carry a `baseUrl`) resolves them identically.
|
|
265
|
+
function absolutePaths(
|
|
266
|
+
paths: TS.MapLike<string[]> | undefined,
|
|
267
|
+
basePath: string,
|
|
268
|
+
): Record<string, string[]> | undefined {
|
|
269
|
+
if (!paths) return undefined;
|
|
270
|
+
return Object.fromEntries(
|
|
271
|
+
Object.entries(paths).map(([key, targets]) => [
|
|
272
|
+
key,
|
|
273
|
+
targets.map(target => (path.isAbsolute(target) ? target : path.resolve(basePath, target))),
|
|
274
|
+
]),
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function resolvePackageDir(name: string, root: string): string | undefined {
|
|
279
|
+
for (const base of [root, import.meta.dirname]) {
|
|
280
|
+
try {
|
|
281
|
+
const require = createRequire(path.join(base, 'noop.js'));
|
|
282
|
+
return path.dirname(require.resolve(`${name}/package.json`));
|
|
283
|
+
} catch {
|
|
284
|
+
// keep looking
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
async function writeTypecheckProject(
|
|
291
|
+
config: ResolvedConfig,
|
|
292
|
+
native: string | undefined,
|
|
293
|
+
): Promise<string> {
|
|
294
|
+
const dir = path.join(config.outPath, 'typecheck');
|
|
295
|
+
await mkdir(dir, { recursive: true });
|
|
296
|
+
const reactTypes = resolveTypesDir('react', config.root);
|
|
297
|
+
const hasReactTypes = reactTypes !== undefined;
|
|
298
|
+
const rootParams = scanRootParamTypes(path.join(config.root, 'app'));
|
|
299
|
+
// With `typedRoutes` on, the build generates `.next/types/link.d.ts`, whose next/link, next/navigation
|
|
300
|
+
// and next augmentations layer the RouteImpl type onto the *real* next package. pnext's own permissive
|
|
301
|
+
// `next/*` shims would shadow those and mask the typed-route errors the suite asserts. When the real next
|
|
302
|
+
// package is resolvable from the app, drop the next-module shims and let real next plus the generated
|
|
303
|
+
// files drive the check - exactly what `next build` does.
|
|
304
|
+
const omitNextModuleShims = typedRoutesEnabled() && realNextResolvable(config.root);
|
|
305
|
+
await writeFile(
|
|
306
|
+
path.join(dir, 'next-shims.d.ts'),
|
|
307
|
+
nextShims(hasReactTypes, rootParams, omitNextModuleShims),
|
|
308
|
+
);
|
|
309
|
+
const preact = resolvePackageDir('preact', config.root);
|
|
310
|
+
if (reactTypes && preact) {
|
|
311
|
+
await writeFile(preactTypeShimPath(config), preactTypeShim(preact, reactTypes));
|
|
312
|
+
}
|
|
313
|
+
const base = tsconfigPath(config.root);
|
|
314
|
+
const baseProject = base ? await readBaseProject(base, native) : undefined;
|
|
315
|
+
const baseOptions = baseProject?.options ?? {};
|
|
316
|
+
const preactShim = preactTypeShimPath(config);
|
|
317
|
+
const project = generatedProjectPath(config);
|
|
318
|
+
const paths = reactTypePaths(
|
|
319
|
+
config.root,
|
|
320
|
+
absolutePaths(
|
|
321
|
+
baseOptions.paths,
|
|
322
|
+
baseOptions.baseUrl ?? (base ? path.dirname(base) : config.root),
|
|
323
|
+
),
|
|
324
|
+
existsSync(preactShim) ? preactShim : undefined,
|
|
325
|
+
);
|
|
326
|
+
// App sources (and fixture helpers they import) may use node builtins
|
|
327
|
+
// (`node:fs`, `node:path`). Next resolves them through @types/node; put the
|
|
328
|
+
// app's copy (or pnext's fallback) in the program so `Cannot find module
|
|
329
|
+
// 'node:*'` never fails an app build.
|
|
330
|
+
const nodeTypes = resolveTypesDir('node', config.root);
|
|
331
|
+
await writeFile(
|
|
332
|
+
project,
|
|
333
|
+
JSON.stringify(
|
|
334
|
+
{
|
|
335
|
+
...(base ? { extends: base } : {}),
|
|
336
|
+
compilerOptions: {
|
|
337
|
+
noEmit: true,
|
|
338
|
+
// TS keeps only the buildinfo under noEmit, so a re-check of an
|
|
339
|
+
// unchanged app is near-free. It lives outside outPath, which every
|
|
340
|
+
// build wipes.
|
|
341
|
+
incremental: true,
|
|
342
|
+
tsBuildInfoFile: path.join(
|
|
343
|
+
config.root,
|
|
344
|
+
'node_modules',
|
|
345
|
+
'.cache',
|
|
346
|
+
'pnext',
|
|
347
|
+
'typecheck.tsbuildinfo',
|
|
348
|
+
),
|
|
349
|
+
skipLibCheck: true,
|
|
350
|
+
allowJs: true,
|
|
351
|
+
resolveJsonModule: true,
|
|
352
|
+
isolatedModules: true,
|
|
353
|
+
jsx: 'react-jsx',
|
|
354
|
+
// Runtime JSX targets Preact, but compat typechecking validates the
|
|
355
|
+
// React/Next contract: an inherited `jsxImportSource: 'preact'` would
|
|
356
|
+
// make app components return Preact VNodes, which the React validator
|
|
357
|
+
// rejects. 'react' is TS's own default for react-jsx.
|
|
358
|
+
jsxImportSource: 'react',
|
|
359
|
+
// `paths` only, never `baseUrl` — TS 7 removed it (TS5102). The
|
|
360
|
+
// mappings are absolutized above so they resolve the same from here.
|
|
361
|
+
...(paths ? { paths } : {}),
|
|
362
|
+
// Fallbacks for apps whose tsconfig leaves these unset (the ES3 default rejects modern syntax).
|
|
363
|
+
// The app's own values win - `next build` checks with the app's options, and overriding
|
|
364
|
+
// lib/strict/target changes inference.
|
|
365
|
+
...(baseOptions.strict === undefined ? { strict: false } : {}),
|
|
366
|
+
...(baseOptions.target === undefined ? { target: 'es2022' } : {}),
|
|
367
|
+
...(baseOptions.module === undefined ? { module: 'esnext' } : {}),
|
|
368
|
+
...(baseOptions.moduleResolution === undefined
|
|
369
|
+
? { moduleResolution: 'bundler' }
|
|
370
|
+
: {}),
|
|
371
|
+
...(baseOptions.lib === undefined ? { lib: ['es2022', 'dom', 'dom.iterable'] } : {}),
|
|
372
|
+
},
|
|
373
|
+
include: [
|
|
374
|
+
path.join(dir, 'next-shims.d.ts'),
|
|
375
|
+
...(nodeTypes ? [path.join(nodeTypes, 'index.d.ts')] : []),
|
|
376
|
+
path.join(config.root, 'next-env.d.ts'),
|
|
377
|
+
// The build emits `.next/types/validator.ts` (page/layout/route-handler export validation) just
|
|
378
|
+
// before this typecheck. Next includes it in the program so invalid exports fail the build with a
|
|
379
|
+
// constraint type error; include it here too. It lives outside the `.pnext` outPath, so its
|
|
380
|
+
// diagnostics survive appDiagnostic's scoping.
|
|
381
|
+
...(existsSync(path.join(config.root, '.next/types/validator.ts'))
|
|
382
|
+
? [path.join(config.root, '.next/types/validator.ts')]
|
|
383
|
+
: []),
|
|
384
|
+
path.join(config.root, 'middleware.*'),
|
|
385
|
+
path.join(config.root, 'proxy.*'),
|
|
386
|
+
// Next type-checks the project's next.config.(ts|mts|cts) as part of
|
|
387
|
+
// `next build`; a type error in the config fails the build (the
|
|
388
|
+
// next-config-ts*/type-error suites assert this). JS configs carry no
|
|
389
|
+
// types to check, so only the TS variants are included.
|
|
390
|
+
path.join(config.root, 'next.config.ts'),
|
|
391
|
+
path.join(config.root, 'next.config.mts'),
|
|
392
|
+
path.join(config.root, 'next.config.cts'),
|
|
393
|
+
path.join(config.root, 'app/**/*.ts'),
|
|
394
|
+
path.join(config.root, 'app/**/*.tsx'),
|
|
395
|
+
path.join(config.root, 'pages/**/*.ts'),
|
|
396
|
+
path.join(config.root, 'pages/**/*.tsx'),
|
|
397
|
+
// The app tsconfig's own file list contributes ambient declarations
|
|
398
|
+
// (global .d.ts JSX/module augmentations) nothing imports; merge just
|
|
399
|
+
// those in. Merging its `include` PATTERNS instead would also drag in
|
|
400
|
+
// every stray root-level source (e2e fixtures keep collectors, custom
|
|
401
|
+
// servers and loader inputs there) that no app entry imports, failing
|
|
402
|
+
// builds on helper files the app never bundles.
|
|
403
|
+
...baseAmbientDeclarations(baseProject?.fileNames, config),
|
|
404
|
+
],
|
|
405
|
+
exclude: [
|
|
406
|
+
path.join(config.root, 'node_modules'),
|
|
407
|
+
path.join(config.root, '**/*.test.ts'),
|
|
408
|
+
path.join(config.root, '**/*.test.tsx'),
|
|
409
|
+
],
|
|
410
|
+
},
|
|
411
|
+
null,
|
|
412
|
+
2,
|
|
413
|
+
),
|
|
414
|
+
);
|
|
415
|
+
return project;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function preactTypeShimPath(config: ResolvedConfig): string {
|
|
419
|
+
return path.join(config.outPath, 'typecheck', 'preact-compat.d.ts');
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function preactTypeShim(preact: string, react: string): string {
|
|
423
|
+
const preactTypes = JSON.stringify(path.join(preact, 'src', 'index.d.ts'));
|
|
424
|
+
const types = JSON.stringify(path.join(react, 'index.d.ts'));
|
|
425
|
+
return `import type { ReactNode } from ${types}
|
|
426
|
+
|
|
427
|
+
export * from ${preactTypes}
|
|
428
|
+
export type ComponentChild = ReactNode
|
|
429
|
+
export type ComponentChildren = ReactNode
|
|
430
|
+
`;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function typedRoutesEnabled(): boolean {
|
|
434
|
+
return (getNextConfig() as { typedRoutes?: unknown }).typedRoutes === true;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Whether the real `next` package's type entry resolves from the app root.
|
|
438
|
+
function realNextResolvable(root: string): boolean {
|
|
439
|
+
try {
|
|
440
|
+
createRequire(path.join(root, 'noop.js')).resolve('next/package.json');
|
|
441
|
+
return true;
|
|
442
|
+
} catch {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** Absolute `.d.ts` paths the app's own tsconfig would have put in the program. */
|
|
448
|
+
function baseAmbientDeclarations(fileNames: readonly string[] | undefined, config: ResolvedConfig): string[] {
|
|
449
|
+
if (!fileNames) return [];
|
|
450
|
+
const outPath = path.resolve(config.outPath) + path.sep;
|
|
451
|
+
return fileNames
|
|
452
|
+
.map(name => path.resolve(name))
|
|
453
|
+
.filter(
|
|
454
|
+
name =>
|
|
455
|
+
name.endsWith('.d.ts') &&
|
|
456
|
+
!name.includes(`${path.sep}node_modules${path.sep}`) &&
|
|
457
|
+
!name.startsWith(outPath),
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
interface BaseProject {
|
|
462
|
+
options: {
|
|
463
|
+
paths?: TS.MapLike<string[]>;
|
|
464
|
+
baseUrl?: string;
|
|
465
|
+
strict?: unknown;
|
|
466
|
+
target?: unknown;
|
|
467
|
+
module?: unknown;
|
|
468
|
+
moduleResolution?: unknown;
|
|
469
|
+
lib?: unknown;
|
|
470
|
+
};
|
|
471
|
+
fileNames: string[];
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Resolves the app tsconfig's extends chain and include globs via `tsgo --showConfig` so the native
|
|
476
|
+
* fast path never imports the classic `typescript` package. Any failure falls back to the classic
|
|
477
|
+
* reader.
|
|
478
|
+
*/
|
|
479
|
+
async function readBaseProject(file: string, native: string | undefined): Promise<BaseProject> {
|
|
480
|
+
const shown = native ? await showConfigViaNative(native, file) : undefined;
|
|
481
|
+
if (shown) return shown;
|
|
482
|
+
const ts = await loadTypescript();
|
|
483
|
+
const parsed = readProject(ts, file);
|
|
484
|
+
return { options: parsed.options, fileNames: [...parsed.fileNames] };
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
async function showConfigViaNative(bin: string, file: string): Promise<BaseProject | undefined> {
|
|
488
|
+
try {
|
|
489
|
+
const proc = Bun.spawn([bin, '--showConfig', '-p', file], { stdout: 'pipe', stderr: 'pipe' });
|
|
490
|
+
const stdout = await new Response(proc.stdout).text();
|
|
491
|
+
await proc.exited;
|
|
492
|
+
if (proc.exitCode !== 0) return undefined;
|
|
493
|
+
const shown = JSON.parse(stdout) as { compilerOptions?: BaseProject['options']; files?: string[] };
|
|
494
|
+
const dir = path.dirname(file);
|
|
495
|
+
const options = shown.compilerOptions ?? {};
|
|
496
|
+
if (typeof options.baseUrl === 'string') options.baseUrl = path.resolve(dir, options.baseUrl);
|
|
497
|
+
const fileNames = (shown.files ?? []).map(f => path.resolve(dir, f));
|
|
498
|
+
return { options, fileNames };
|
|
499
|
+
} catch {
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function tsconfigPath(root: string): string | undefined {
|
|
505
|
+
const tsConfig = getNextConfig().typescript as { tsconfigPath?: unknown } | undefined;
|
|
506
|
+
const configured = tsConfig?.tsconfigPath;
|
|
507
|
+
const file =
|
|
508
|
+
typeof configured === 'string' && configured.length > 0
|
|
509
|
+
? path.join(root, configured)
|
|
510
|
+
: path.join(root, 'tsconfig.json');
|
|
511
|
+
return existsSync(file) ? file : undefined;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Memoized per project path: `parseJsonConfigFileContent` walks every `include` glob to build
|
|
516
|
+
* `fileNames`. The cache lives for the process, which for the checker is one build (dev never
|
|
517
|
+
* typechecks).
|
|
518
|
+
*/
|
|
519
|
+
const parsedProjects = new Map<string, { stamp: number; parsed: TS.ParsedCommandLine }>();
|
|
520
|
+
|
|
521
|
+
function readProject(ts: typeof TS, project: string): TS.ParsedCommandLine {
|
|
522
|
+
// The generated project is rewritten before every check, so the cache is
|
|
523
|
+
// keyed on the file's mtime rather than its path alone.
|
|
524
|
+
let stamp = 0;
|
|
525
|
+
try {
|
|
526
|
+
stamp = statSync(project).mtimeMs;
|
|
527
|
+
} catch {
|
|
528
|
+
/* unreadable: parse and let readConfigFile report it */
|
|
529
|
+
}
|
|
530
|
+
const cached = parsedProjects.get(project);
|
|
531
|
+
if (cached?.stamp === stamp) return cached.parsed;
|
|
532
|
+
const read = ts.readConfigFile(project, file => ts.sys.readFile(file));
|
|
533
|
+
if (read.error) throw new PnextTypecheckError(formatDiagnostics(ts, [read.error]));
|
|
534
|
+
const parsed = ts.parseJsonConfigFileContent(read.config, ts.sys, path.dirname(project));
|
|
535
|
+
parsedProjects.set(project, { stamp, parsed });
|
|
536
|
+
return parsed;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
function formatDiagnostics(ts: typeof TS, diagnostics: readonly TS.Diagnostic[]): string[] {
|
|
540
|
+
const messages = new Set<string>();
|
|
541
|
+
for (const diagnostic of diagnostics) {
|
|
542
|
+
const raw = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
|
543
|
+
const typedRoute = typedRouteMessage(raw);
|
|
544
|
+
// Next prints `./relative/file.ts:line:col` on its own line above the
|
|
545
|
+
// message; mirror that so build failures name their source.
|
|
546
|
+
let location = '';
|
|
547
|
+
if (diagnostic.file && diagnostic.start !== undefined) {
|
|
548
|
+
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
549
|
+
location = `${diagnostic.file.fileName}:${line + 1}:${character + 1}\n`;
|
|
550
|
+
}
|
|
551
|
+
messages.add(`${location}Type error: ${typedRoute ?? raw}`);
|
|
552
|
+
}
|
|
553
|
+
return [...messages];
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function typedRouteMessage(message: string): string | undefined {
|
|
557
|
+
const match = /^Type '(".*")' is not assignable to type '.*RouteImpl<\1>/.exec(message);
|
|
558
|
+
if (!match?.[1]) return undefined;
|
|
559
|
+
return `${match[1]} is not an existing route. If it is intentional, please type it explicitly with \`as Route\`.`;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function rootParamsModule(rootParams: Map<string, Set<RootParamValueType>>): string {
|
|
563
|
+
// Real Next generates `next/root-params`'s exports per-build from the app's
|
|
564
|
+
// actual root params (dynamic segments at/above a root layout). Mirror that:
|
|
565
|
+
// one getter per scanned param with its scanned value type (`string` for
|
|
566
|
+
// `[name]`, `string[]` for catch-alls, `| undefined` when optional or absent
|
|
567
|
+
// from some root layout). When the scan finds nothing (no root layout / no
|
|
568
|
+
// dynamic root segments), fall back to the static `lang`/`locale` exports
|
|
569
|
+
// that existing suites rely on.
|
|
570
|
+
const order: RootParamValueType[] = ['string', 'string[]', 'undefined'];
|
|
571
|
+
const entries: [string, string][] =
|
|
572
|
+
rootParams.size > 0
|
|
573
|
+
? [...rootParams.entries()].map(([name, types]) => [
|
|
574
|
+
name,
|
|
575
|
+
order.filter(type => types.has(type)).join(' | '),
|
|
576
|
+
])
|
|
577
|
+
: [
|
|
578
|
+
['lang', 'string | string[] | undefined'],
|
|
579
|
+
['locale', 'string | string[] | undefined'],
|
|
580
|
+
];
|
|
581
|
+
const getters = entries
|
|
582
|
+
.map(([name, union]) => ` export function ${name}(): Promise<${union}>`)
|
|
583
|
+
.join('\n');
|
|
584
|
+
return `declare module 'next/root-params' {
|
|
585
|
+
${getters}
|
|
586
|
+
const rootParams: (...args: any[]) => Promise<any>
|
|
587
|
+
export default rootParams
|
|
588
|
+
}`;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// Remove every top-level `declare module 'next...' { ... }` block from a shim
|
|
592
|
+
// source by brace-counting. Used when the real next package is present and
|
|
593
|
+
// should own the `next/*` type surface (typedRoutes). Non-next ambient
|
|
594
|
+
// declarations (node builtins, asset wildcards, RequestInit augmentation) are
|
|
595
|
+
// left intact.
|
|
596
|
+
function stripNextModuleDeclarations(source: string): string {
|
|
597
|
+
const lines = source.split('\n');
|
|
598
|
+
const out: string[] = [];
|
|
599
|
+
for (let i = 0; i < lines.length; i++) {
|
|
600
|
+
const line = lines[i]!;
|
|
601
|
+
if (/^declare module 'next[^']*' \{/.test(line)) {
|
|
602
|
+
let depth = 0;
|
|
603
|
+
for (; i < lines.length; i++) {
|
|
604
|
+
const current = lines[i]!;
|
|
605
|
+
depth += (current.match(/\{/g)?.length ?? 0) - (current.match(/\}/g)?.length ?? 0);
|
|
606
|
+
if (depth === 0) break;
|
|
607
|
+
}
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
out.push(line);
|
|
611
|
+
}
|
|
612
|
+
return out.join('\n');
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
function nextShims(
|
|
616
|
+
hasReactTypes: boolean,
|
|
617
|
+
rootParams: Map<string, Set<RootParamValueType>>,
|
|
618
|
+
omitNextModuleShims = false,
|
|
619
|
+
): string {
|
|
620
|
+
// Ambient module declarations override real module resolution, so the react
|
|
621
|
+
// fallbacks below must only exist when no real `@types/react` was found —
|
|
622
|
+
// otherwise `import { JSX } from 'react'` etc. fail against the stub.
|
|
623
|
+
const reactShims = hasReactTypes
|
|
624
|
+
? ''
|
|
625
|
+
: `
|
|
626
|
+
declare namespace JSX {
|
|
627
|
+
interface Element {}
|
|
628
|
+
interface IntrinsicElements {
|
|
629
|
+
[name: string]: any
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
declare namespace React {
|
|
634
|
+
type ReactNode = any
|
|
635
|
+
type ComponentType<P = any> = (props: P) => ReactNode
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
declare module 'react' {
|
|
639
|
+
export type ReactNode = any
|
|
640
|
+
export type ComponentType<P = any> = (props: P) => ReactNode
|
|
641
|
+
export type AnchorHTMLAttributes<T> = any
|
|
642
|
+
export type DetailedHTMLProps<E, T> = any
|
|
643
|
+
export const Suspense: ComponentType<any>
|
|
644
|
+
export const ViewTransition: ComponentType<any>
|
|
645
|
+
export function addTransitionType(type: string): void
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
declare module 'react/jsx-runtime' {
|
|
649
|
+
export const jsx: any
|
|
650
|
+
export const jsxs: any
|
|
651
|
+
export const Fragment: any
|
|
652
|
+
}
|
|
653
|
+
`;
|
|
654
|
+
const source = `${reactShims}
|
|
655
|
+
declare const process: {
|
|
656
|
+
env: Record<string, string | undefined>
|
|
657
|
+
emit?: (...args: any[]) => boolean
|
|
658
|
+
cwd(): string
|
|
659
|
+
platform: string
|
|
660
|
+
arch: string
|
|
661
|
+
version: string
|
|
662
|
+
versions: Record<string, string>
|
|
663
|
+
nextTick(callback: (...args: any[]) => void, ...args: any[]): void
|
|
664
|
+
argv: string[]
|
|
665
|
+
pid: number
|
|
666
|
+
exit(code?: number): never
|
|
667
|
+
[key: string]: any
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
declare const EdgeRuntime: string
|
|
671
|
+
|
|
672
|
+
declare const require: (id: string) => any
|
|
673
|
+
|
|
674
|
+
declare class Buffer extends Uint8Array {}
|
|
675
|
+
|
|
676
|
+
declare module 'async_hooks' {
|
|
677
|
+
export class AsyncLocalStorage<T> {
|
|
678
|
+
run<R>(store: T, callback: () => R): R
|
|
679
|
+
getStore(): T | undefined
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
declare module 'timers/promises' {
|
|
684
|
+
export function setTimeout<T = void>(delay?: number, value?: T, options?: any): Promise<T>
|
|
685
|
+
export function setImmediate<T = void>(value?: T, options?: any): Promise<T>
|
|
686
|
+
export function setInterval<T = void>(delay?: number, value?: T, options?: any): AsyncIterable<T>
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
declare module 'node:timers/promises' {
|
|
690
|
+
export * from 'timers/promises'
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
declare module 'node:crypto' {
|
|
694
|
+
interface KeyObject {
|
|
695
|
+
export(...args: any[]): any
|
|
696
|
+
toString(...args: any[]): string
|
|
697
|
+
}
|
|
698
|
+
export function randomInt(...args: any[]): number
|
|
699
|
+
export function randomBytes(...args: any[]): Buffer
|
|
700
|
+
export function randomFillSync<T extends Uint8Array>(buffer: T, ...args: any[]): T
|
|
701
|
+
export function randomUUID(...args: any[]): string
|
|
702
|
+
export function getRandomValues<T extends Uint8Array>(array: T): T
|
|
703
|
+
export function generateKeyPairSync(...args: any[]): { publicKey: any; privateKey: any }
|
|
704
|
+
export function generateKeySync(...args: any[]): KeyObject
|
|
705
|
+
export function generatePrimeSync(...args: any[]): ArrayBuffer | Uint8Array
|
|
706
|
+
const crypto: {
|
|
707
|
+
randomInt: typeof randomInt
|
|
708
|
+
randomBytes: typeof randomBytes
|
|
709
|
+
randomFillSync: typeof randomFillSync
|
|
710
|
+
randomUUID: typeof randomUUID
|
|
711
|
+
getRandomValues: typeof getRandomValues
|
|
712
|
+
generateKeyPairSync: typeof generateKeyPairSync
|
|
713
|
+
generateKeySync: typeof generateKeySync
|
|
714
|
+
generatePrimeSync: typeof generatePrimeSync
|
|
715
|
+
}
|
|
716
|
+
export default crypto
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
declare module 'crypto' {
|
|
720
|
+
export * from 'node:crypto'
|
|
721
|
+
export { default } from 'node:crypto'
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// Next.js augments the fetch RequestInit with a "next" field for its extended
|
|
725
|
+
// fetch semantics (revalidate/tags); mirror that here so app code using
|
|
726
|
+
// fetch(url, next revalidate) typechecks.
|
|
727
|
+
interface RequestInit {
|
|
728
|
+
next?: {
|
|
729
|
+
revalidate?: number | false
|
|
730
|
+
tags?: string[]
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
interface ResponseInit {
|
|
735
|
+
request?: {
|
|
736
|
+
headers?: HeadersInit
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
declare module 'node:buffer' {
|
|
741
|
+
export const Buffer: any
|
|
742
|
+
export const constants: any
|
|
743
|
+
export const kMaxLength: number
|
|
744
|
+
export const kStringMaxLength: number
|
|
745
|
+
export const SlowBuffer: any
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
declare module 'url' {
|
|
749
|
+
export interface UrlObject {
|
|
750
|
+
pathname?: string
|
|
751
|
+
query?: Record<string, string | string[]>
|
|
752
|
+
hash?: string
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
declare module 'next/types.js' {
|
|
757
|
+
export interface NextConfig {
|
|
758
|
+
env?: Record<string, string | number | boolean | undefined>
|
|
759
|
+
typedRoutes?: boolean
|
|
760
|
+
typescript?: { tsconfigPath?: string; ignoreBuildErrors?: boolean }
|
|
761
|
+
eslint?: { ignoreDuringBuilds?: boolean; dirs?: string[] }
|
|
762
|
+
[key: string]: any
|
|
763
|
+
}
|
|
764
|
+
export type Metadata = any
|
|
765
|
+
export type Viewport = any
|
|
766
|
+
export type ResolvingMetadata = Promise<Metadata>
|
|
767
|
+
export type ResolvingViewport = Promise<Viewport>
|
|
768
|
+
export type NextApiHandler<T = any> = (...args: any[]) => any
|
|
769
|
+
export type NextApiRequest = any
|
|
770
|
+
export type NextApiResponse<T = any> = any
|
|
771
|
+
export namespace MetadataRoute {
|
|
772
|
+
type Robots = any
|
|
773
|
+
type Sitemap = any[]
|
|
774
|
+
type Manifest = any
|
|
775
|
+
}
|
|
776
|
+
export type Route<T = string> = string
|
|
777
|
+
export type NextPage<P = {}, IP = P> = ((props: P) => any) & { [key: string]: any }
|
|
778
|
+
export type NextComponentType<C = any, IP = any, P = any> = any
|
|
779
|
+
export type PageProps<P = any> = any
|
|
780
|
+
export type LayoutProps<P = any> = any
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
declare module 'next/types' {
|
|
784
|
+
export * from 'next/types.js'
|
|
785
|
+
export { MetadataRoute } from 'next/types.js'
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
declare module 'next' {
|
|
789
|
+
export type {
|
|
790
|
+
NextConfig,
|
|
791
|
+
Metadata,
|
|
792
|
+
Viewport,
|
|
793
|
+
ResolvingMetadata,
|
|
794
|
+
ResolvingViewport,
|
|
795
|
+
NextApiRequest,
|
|
796
|
+
NextApiResponse,
|
|
797
|
+
NextApiHandler,
|
|
798
|
+
Route,
|
|
799
|
+
NextPage,
|
|
800
|
+
NextComponentType,
|
|
801
|
+
PageProps,
|
|
802
|
+
LayoutProps,
|
|
803
|
+
} from 'next/types.js'
|
|
804
|
+
export { MetadataRoute } from 'next/types.js'
|
|
805
|
+
export type GetServerSideProps<P = any, Q = any> = any
|
|
806
|
+
export type GetStaticProps<P = any, Q = any> = any
|
|
807
|
+
export type GetStaticPaths<Q = any> = any
|
|
808
|
+
export type InferGetServerSidePropsType<T = any> = any
|
|
809
|
+
export type InferGetStaticPropsType<T = any> = any
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
declare module 'next/cache' {
|
|
813
|
+
export function revalidatePath(path: string, type?: 'page' | 'layout'): void
|
|
814
|
+
export function revalidateTag(tag: string, profile: string | { expire?: number }): void
|
|
815
|
+
export function updateTag(tag: string): void
|
|
816
|
+
export function unstable_cache(...args: any[]): any
|
|
817
|
+
export function unstable_noStore(): void
|
|
818
|
+
export function unstable_expirePath(path: string, type?: 'page' | 'layout'): void
|
|
819
|
+
export function unstable_expireTag(...tags: string[]): void
|
|
820
|
+
export function expirePath(path: string, type?: 'page' | 'layout'): void
|
|
821
|
+
export function expireTag(...tags: string[]): void
|
|
822
|
+
export function refresh(): void
|
|
823
|
+
export function unstable_refresh(): void
|
|
824
|
+
export const io: any
|
|
825
|
+
export const cacheTag: (...tags: string[]) => void
|
|
826
|
+
export const cacheLife: (...args: any[]) => void
|
|
827
|
+
export const unstable_cacheTag: (...tags: string[]) => void
|
|
828
|
+
export const unstable_cacheLife: (...args: any[]) => void
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
declare module 'next/headers' {
|
|
832
|
+
interface CookieSetOptions {
|
|
833
|
+
name?: string
|
|
834
|
+
value?: string
|
|
835
|
+
path?: string
|
|
836
|
+
maxAge?: number
|
|
837
|
+
expires?: Date | number
|
|
838
|
+
httpOnly?: boolean
|
|
839
|
+
secure?: boolean
|
|
840
|
+
sameSite?: 'strict' | 'lax' | 'none' | boolean
|
|
841
|
+
domain?: string
|
|
842
|
+
}
|
|
843
|
+
interface CookieStore {
|
|
844
|
+
get(name: string): { name: string; value: string } | undefined
|
|
845
|
+
get(options: { name: string; value?: string }): { name: string; value: string } | undefined
|
|
846
|
+
getAll(name?: string): { name: string; value: string }[]
|
|
847
|
+
getAll(options: { name: string; value?: string }): { name: string; value: string }[]
|
|
848
|
+
has(name: string): boolean
|
|
849
|
+
readonly size: number
|
|
850
|
+
set(name: string, value: string, options?: CookieSetOptions): CookieStore
|
|
851
|
+
set(options: CookieSetOptions): CookieStore
|
|
852
|
+
delete(name: string): boolean
|
|
853
|
+
clear(): CookieStore
|
|
854
|
+
[Symbol.iterator](): IterableIterator<readonly [string, { name?: string; value: string }]>
|
|
855
|
+
}
|
|
856
|
+
export function cookies(): Promise<CookieStore>
|
|
857
|
+
export function headers(): Promise<Headers>
|
|
858
|
+
export function draftMode(): Promise<{
|
|
859
|
+
isEnabled: boolean
|
|
860
|
+
enable(): void
|
|
861
|
+
disable(): void
|
|
862
|
+
}>
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
declare module 'next/server' {
|
|
866
|
+
interface NextURL extends URL {
|
|
867
|
+
clone(): NextURL
|
|
868
|
+
basePath: string
|
|
869
|
+
buildId?: string
|
|
870
|
+
locale: string
|
|
871
|
+
defaultLocale?: string
|
|
872
|
+
}
|
|
873
|
+
interface RequestCookie {
|
|
874
|
+
name: string
|
|
875
|
+
value: string
|
|
876
|
+
}
|
|
877
|
+
interface RequestCookies {
|
|
878
|
+
get(name: string): RequestCookie | undefined
|
|
879
|
+
getAll(name?: string): RequestCookie[]
|
|
880
|
+
has(name: string): boolean
|
|
881
|
+
set(name: string, value: string): RequestCookies
|
|
882
|
+
set(cookie: RequestCookie): RequestCookies
|
|
883
|
+
delete(name: string | string[]): boolean | boolean[]
|
|
884
|
+
clear(): RequestCookies
|
|
885
|
+
readonly size: number
|
|
886
|
+
[Symbol.iterator](): IterableIterator<[string, RequestCookie]>
|
|
887
|
+
}
|
|
888
|
+
interface ResponseCookies {
|
|
889
|
+
get(name: string): (RequestCookie & Record<string, any>) | undefined
|
|
890
|
+
getAll(name?: string): (RequestCookie & Record<string, any>)[]
|
|
891
|
+
has(name: string): boolean
|
|
892
|
+
set(name: string, value: string, options?: any): ResponseCookies
|
|
893
|
+
set(options: { name: string; value: string; [key: string]: any }): ResponseCookies
|
|
894
|
+
delete(name: string, options?: any): ResponseCookies
|
|
895
|
+
[Symbol.iterator](): IterableIterator<[string, RequestCookie & Record<string, any>]>
|
|
896
|
+
}
|
|
897
|
+
export class NextRequest extends Request {
|
|
898
|
+
nextUrl: NextURL
|
|
899
|
+
cookies: RequestCookies
|
|
900
|
+
geo?: any
|
|
901
|
+
ip?: string
|
|
902
|
+
}
|
|
903
|
+
export class NextResponse extends Response {
|
|
904
|
+
cookies: ResponseCookies
|
|
905
|
+
static json(body: any, init?: ResponseInit): NextResponse
|
|
906
|
+
static next(init?: ResponseInit): NextResponse
|
|
907
|
+
static redirect(url: string | URL, init?: number | ResponseInit): NextResponse
|
|
908
|
+
static rewrite(url: string | URL, init?: ResponseInit): NextResponse
|
|
909
|
+
}
|
|
910
|
+
export type NextFetchEvent = any
|
|
911
|
+
export type NextMiddleware = (...args: any[]) => any
|
|
912
|
+
export type NextMiddlewareResult = any
|
|
913
|
+
export interface ProxyConfig {
|
|
914
|
+
matcher?: string | { source: string } | Array<string | { source: string }>
|
|
915
|
+
}
|
|
916
|
+
export class ImageResponse extends Response {
|
|
917
|
+
constructor(element: any, options?: any)
|
|
918
|
+
}
|
|
919
|
+
export const URLPattern: any
|
|
920
|
+
export function userAgent(request: { headers: Headers }): any
|
|
921
|
+
export function userAgentFromString(ua: string | undefined): any
|
|
922
|
+
export function after(task: any): void
|
|
923
|
+
export function connection(): Promise<void>
|
|
924
|
+
export const io: any
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
declare module 'next/server.js' {
|
|
928
|
+
export * from 'next/server'
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
declare module 'next/navigation.js' {
|
|
932
|
+
export * from 'next/navigation'
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
declare module 'next/headers.js' {
|
|
936
|
+
export * from 'next/headers'
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
declare module 'next/cache.js' {
|
|
940
|
+
export * from 'next/cache'
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
declare module 'next/link.js' {
|
|
944
|
+
export * from 'next/link'
|
|
945
|
+
export { default } from 'next/link'
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
declare module 'next/image.js' {
|
|
949
|
+
export * from 'next/image'
|
|
950
|
+
export { default } from 'next/image'
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
declare module 'next/script.js' {
|
|
954
|
+
export * from 'next/script'
|
|
955
|
+
export { default } from 'next/script'
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
declare module 'next/dist/client/link.js' {
|
|
959
|
+
export interface LinkProps {
|
|
960
|
+
href: any
|
|
961
|
+
}
|
|
962
|
+
export function useLinkStatus(): any
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
declare module 'next/link' {
|
|
966
|
+
import type { AnchorHTMLAttributes, ComponentType } from 'react'
|
|
967
|
+
// Mirror Next's public LinkProps: standard anchor attributes plus Link's own
|
|
968
|
+
// props, but NO catch-all index signature. A wildcard string index signature
|
|
969
|
+
// would silently accept non-public props (e.g. unstable_dynamicOnHover),
|
|
970
|
+
// making a fixture's ts-expect-error on such a prop report as unused.
|
|
971
|
+
export interface LinkProps
|
|
972
|
+
extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
|
|
973
|
+
href: any
|
|
974
|
+
// Next 16's public prefetch type. The unstable_forceStale value is
|
|
975
|
+
// runtime-only and Next deliberately keeps it OUT of the public union, so an
|
|
976
|
+
// exhaustive switch over prefetch ending in "prefetch satisfies never"
|
|
977
|
+
// stays valid. Including it here would leave that value in the default
|
|
978
|
+
// branch and break such fixtures under our shim.
|
|
979
|
+
prefetch?: boolean | 'auto' | null
|
|
980
|
+
scroll?: boolean
|
|
981
|
+
replace?: boolean
|
|
982
|
+
as?: any
|
|
983
|
+
shallow?: boolean
|
|
984
|
+
passHref?: boolean
|
|
985
|
+
locale?: string | false
|
|
986
|
+
legacyBehavior?: boolean
|
|
987
|
+
onNavigate?: (event: { preventDefault(): void }) => void
|
|
988
|
+
transitionTypes?: string[]
|
|
989
|
+
children?: any
|
|
990
|
+
}
|
|
991
|
+
const Link: ComponentType<LinkProps>
|
|
992
|
+
export default Link
|
|
993
|
+
export function useLinkStatus(): { pending: boolean }
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
declare module 'next/image' {
|
|
997
|
+
import type { ComponentType } from 'react'
|
|
998
|
+
export interface ImageProps {
|
|
999
|
+
src: any
|
|
1000
|
+
alt: string
|
|
1001
|
+
width?: number | string
|
|
1002
|
+
height?: number | string
|
|
1003
|
+
fill?: boolean
|
|
1004
|
+
priority?: boolean
|
|
1005
|
+
loading?: 'lazy' | 'eager'
|
|
1006
|
+
placeholder?: string
|
|
1007
|
+
blurDataURL?: string
|
|
1008
|
+
unoptimized?: boolean
|
|
1009
|
+
sizes?: string
|
|
1010
|
+
quality?: number | string
|
|
1011
|
+
className?: string
|
|
1012
|
+
[key: string]: any
|
|
1013
|
+
}
|
|
1014
|
+
export interface StaticImageData {
|
|
1015
|
+
src: string
|
|
1016
|
+
height: number
|
|
1017
|
+
width: number
|
|
1018
|
+
blurDataURL?: string
|
|
1019
|
+
blurWidth?: number
|
|
1020
|
+
blurHeight?: number
|
|
1021
|
+
}
|
|
1022
|
+
const Image: ComponentType<ImageProps>
|
|
1023
|
+
export default Image
|
|
1024
|
+
export function getImageProps(props: ImageProps): { props: any }
|
|
1025
|
+
export function unstable_getImgProps(props: ImageProps): { props: any }
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
declare module '@vercel/og' {
|
|
1029
|
+
export class ImageResponse extends Response {
|
|
1030
|
+
constructor(element: any, options?: any)
|
|
1031
|
+
}
|
|
1032
|
+
export type ImageResponseOptions = any
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
declare module 'next/og' {
|
|
1036
|
+
export class ImageResponse extends Response {
|
|
1037
|
+
constructor(element: any, options?: any)
|
|
1038
|
+
static json(...args: any[]): ImageResponse
|
|
1039
|
+
}
|
|
1040
|
+
export interface ImageResponseOptions {
|
|
1041
|
+
width?: number
|
|
1042
|
+
height?: number
|
|
1043
|
+
fonts?: any[]
|
|
1044
|
+
debug?: boolean
|
|
1045
|
+
status?: number
|
|
1046
|
+
statusText?: string
|
|
1047
|
+
headers?: HeadersInit
|
|
1048
|
+
emoji?: string
|
|
1049
|
+
[key: string]: any
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
declare module 'next/dynamic' {
|
|
1054
|
+
import type { ComponentType } from 'react'
|
|
1055
|
+
export interface DynamicOptions {
|
|
1056
|
+
loading?: ComponentType<any>
|
|
1057
|
+
ssr?: boolean
|
|
1058
|
+
loadableGenerated?: any
|
|
1059
|
+
suspense?: boolean
|
|
1060
|
+
[key: string]: any
|
|
1061
|
+
}
|
|
1062
|
+
// Infer P from the loader like real next/dynamic's Loader<P>; a bare
|
|
1063
|
+
// Promise<any> loader would collapse P to any and strip prop types.
|
|
1064
|
+
type LoaderComponent<P> = ComponentType<P> | { default: ComponentType<P> }
|
|
1065
|
+
export default function dynamic<P = {}>(
|
|
1066
|
+
loader: (() => Promise<LoaderComponent<P>>) | Promise<LoaderComponent<P>>,
|
|
1067
|
+
options?: DynamicOptions,
|
|
1068
|
+
): ComponentType<P>
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
declare module 'next/error' {
|
|
1072
|
+
import type { ComponentType, ReactNode } from 'react'
|
|
1073
|
+
export interface ErrorInfo {
|
|
1074
|
+
error: Error
|
|
1075
|
+
reset: () => void
|
|
1076
|
+
unstable_retry: () => void
|
|
1077
|
+
[key: string]: any
|
|
1078
|
+
}
|
|
1079
|
+
export interface ErrorProps {
|
|
1080
|
+
statusCode: number
|
|
1081
|
+
title?: string
|
|
1082
|
+
withDarkMode?: boolean
|
|
1083
|
+
[key: string]: any
|
|
1084
|
+
}
|
|
1085
|
+
const ErrorComponent: ComponentType<ErrorProps>
|
|
1086
|
+
export default ErrorComponent
|
|
1087
|
+
// Wraps a fallback renderer (props, info) => JSX in an error boundary. The
|
|
1088
|
+
// returned component takes the fallback's own props plus children (the
|
|
1089
|
+
// guarded subtree) and an optional clearError reset callback. Mirrors the
|
|
1090
|
+
// runtime in src/compat/next/error.tsx.
|
|
1091
|
+
export function unstable_catchError<P extends Record<string, any> = any>(
|
|
1092
|
+
fallback: (props: P, info: ErrorInfo) => ReactNode,
|
|
1093
|
+
): ComponentType<P & { children?: ReactNode; clearError?: () => void }>
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
declare module 'next/font' {
|
|
1097
|
+
export interface FontModule {
|
|
1098
|
+
className: string
|
|
1099
|
+
style: { fontFamily: string; fontWeight?: number; fontStyle?: string }
|
|
1100
|
+
variable: string
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
declare module 'next/font/local' {
|
|
1105
|
+
import type { FontModule } from 'next/font'
|
|
1106
|
+
export default function localFont(options: any): FontModule
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
declare module 'next/font/google' {
|
|
1110
|
+
import type { FontModule } from 'next/font'
|
|
1111
|
+
type FontLoader = (options?: any) => FontModule
|
|
1112
|
+
const font: FontLoader
|
|
1113
|
+
export default font
|
|
1114
|
+
export const Inter: FontLoader
|
|
1115
|
+
export const Geist: FontLoader
|
|
1116
|
+
export const Geist_Mono: FontLoader
|
|
1117
|
+
export const Roboto: FontLoader
|
|
1118
|
+
export const Roboto_Mono: FontLoader
|
|
1119
|
+
export const Open_Sans: FontLoader
|
|
1120
|
+
export const Lato: FontLoader
|
|
1121
|
+
export const Montserrat: FontLoader
|
|
1122
|
+
export const Poppins: FontLoader
|
|
1123
|
+
export const Noto_Sans: FontLoader
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
declare module 'next/script' {
|
|
1127
|
+
import type { ComponentType } from 'react'
|
|
1128
|
+
export interface ScriptProps {
|
|
1129
|
+
src?: string
|
|
1130
|
+
strategy?: 'afterInteractive' | 'lazyOnload' | 'beforeInteractive' | 'worker'
|
|
1131
|
+
onLoad?: (...args: any[]) => void
|
|
1132
|
+
onReady?: (...args: any[]) => void
|
|
1133
|
+
onError?: (...args: any[]) => void
|
|
1134
|
+
id?: string
|
|
1135
|
+
children?: any
|
|
1136
|
+
[key: string]: any
|
|
1137
|
+
}
|
|
1138
|
+
const Script: ComponentType<ScriptProps>
|
|
1139
|
+
export default Script
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
declare module 'next/legacy/image' {
|
|
1143
|
+
import type { ComponentType } from 'react'
|
|
1144
|
+
export interface ImageProps {
|
|
1145
|
+
src: any
|
|
1146
|
+
alt?: string
|
|
1147
|
+
width?: number | string
|
|
1148
|
+
height?: number | string
|
|
1149
|
+
layout?: 'fixed' | 'intrinsic' | 'responsive' | 'fill'
|
|
1150
|
+
objectFit?: string
|
|
1151
|
+
objectPosition?: string
|
|
1152
|
+
priority?: boolean
|
|
1153
|
+
loading?: 'lazy' | 'eager'
|
|
1154
|
+
placeholder?: string
|
|
1155
|
+
blurDataURL?: string
|
|
1156
|
+
unoptimized?: boolean
|
|
1157
|
+
sizes?: string
|
|
1158
|
+
quality?: number | string
|
|
1159
|
+
[key: string]: any
|
|
1160
|
+
}
|
|
1161
|
+
const Image: ComponentType<ImageProps>
|
|
1162
|
+
export default Image
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
${rootParamsModule(rootParams)}
|
|
1166
|
+
|
|
1167
|
+
declare module 'next/web-vitals' {
|
|
1168
|
+
export interface NextWebVitalsMetric {
|
|
1169
|
+
id: string
|
|
1170
|
+
name: string
|
|
1171
|
+
startTime: number
|
|
1172
|
+
value: number
|
|
1173
|
+
label: 'web-vital' | 'custom'
|
|
1174
|
+
[key: string]: any
|
|
1175
|
+
}
|
|
1176
|
+
export function useReportWebVitals(reportFn: (metric: NextWebVitalsMetric) => void): void
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
declare module 'next/dist/client/components/app-router-headers' {
|
|
1180
|
+
export const NEXT_RSC_UNION_QUERY: string
|
|
1181
|
+
export const RSC_HEADER: string
|
|
1182
|
+
export const NEXT_ROUTER_STATE_TREE_HEADER: string
|
|
1183
|
+
export const NEXT_ROUTER_PREFETCH_HEADER: string
|
|
1184
|
+
export const NEXT_URL: string
|
|
1185
|
+
const headers: Record<string, string>
|
|
1186
|
+
export default headers
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
declare module 'next/dist/server/app-render/work-unit-async-storage.external' {
|
|
1190
|
+
export const workUnitAsyncStorage: {
|
|
1191
|
+
getStore(): any
|
|
1192
|
+
run<R>(store: any, callback: () => R): R
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
declare module 'next/dist/server/web/spec-extension/adapters/headers' {
|
|
1197
|
+
export class ReadonlyHeaders extends Headers {}
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
declare module 'next/dist/server/web/spec-extension/adapters/request-cookies' {
|
|
1201
|
+
export interface ReadonlyRequestCookies {
|
|
1202
|
+
get(name: string): { name: string; value: string } | undefined
|
|
1203
|
+
getAll(name?: string): { name: string; value: string }[]
|
|
1204
|
+
has(name: string): boolean
|
|
1205
|
+
readonly size: number
|
|
1206
|
+
[Symbol.iterator](): IterableIterator<[string, { name: string; value: string }]>
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
declare module 'node-fetch' {
|
|
1211
|
+
export class Headers {
|
|
1212
|
+
get(name: string): string | null
|
|
1213
|
+
has(name: string): boolean
|
|
1214
|
+
set(name: string, value: string): void
|
|
1215
|
+
append(name: string, value: string): void
|
|
1216
|
+
delete(name: string): void
|
|
1217
|
+
forEach(callback: (value: string, name: string) => void): void
|
|
1218
|
+
[Symbol.iterator](): IterableIterator<[string, string]>
|
|
1219
|
+
}
|
|
1220
|
+
const fetch: (...args: any[]) => Promise<any>
|
|
1221
|
+
export default fetch
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
declare module 'next/router' {
|
|
1225
|
+
export interface NextRouter {
|
|
1226
|
+
route: string
|
|
1227
|
+
pathname: string
|
|
1228
|
+
asPath: string
|
|
1229
|
+
query: Record<string, string | string[] | undefined>
|
|
1230
|
+
push(url: any, as?: any, options?: any): Promise<boolean>
|
|
1231
|
+
replace(url: any, as?: any, options?: any): Promise<boolean>
|
|
1232
|
+
prefetch(url: string): Promise<void>
|
|
1233
|
+
back(): void
|
|
1234
|
+
reload(): void
|
|
1235
|
+
beforePopState(callback: (...args: any[]) => boolean): void
|
|
1236
|
+
events: {
|
|
1237
|
+
on(type: string, handler: (...args: any[]) => void): void
|
|
1238
|
+
off(type: string, handler: (...args: any[]) => void): void
|
|
1239
|
+
emit(type: string, ...args: any[]): void
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
export function useRouter(): NextRouter
|
|
1243
|
+
const router: NextRouter
|
|
1244
|
+
export default router
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
declare module 'next/app' {
|
|
1248
|
+
// Pages-router shim: pnext builds the app directory only, but fixtures and
|
|
1249
|
+
// hybrid apps may carry a pages/ tree whose _app imports next/app. The type
|
|
1250
|
+
// program includes pages/**, so this keeps the typecheck from failing a
|
|
1251
|
+
// build over files pnext never bundles.
|
|
1252
|
+
export interface AppProps<P = any> {
|
|
1253
|
+
Component: (props: P) => any
|
|
1254
|
+
pageProps: P
|
|
1255
|
+
router?: any
|
|
1256
|
+
[key: string]: any
|
|
1257
|
+
}
|
|
1258
|
+
export type AppType = (props: AppProps) => any
|
|
1259
|
+
const App: AppType
|
|
1260
|
+
export default App
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
declare module 'next/dist/client/components/navigation.js' {
|
|
1264
|
+
export interface NavigateOptions {
|
|
1265
|
+
scroll?: boolean
|
|
1266
|
+
}
|
|
1267
|
+
export interface PrefetchOptions {
|
|
1268
|
+
kind?: 'auto' | 'full'
|
|
1269
|
+
onInvalidate?: () => void
|
|
1270
|
+
}
|
|
1271
|
+
export interface AppRouterInstance {
|
|
1272
|
+
push(href: string, options?: NavigateOptions): void
|
|
1273
|
+
replace(href: string, options?: NavigateOptions): void
|
|
1274
|
+
prefetch(href: string, options?: PrefetchOptions): void
|
|
1275
|
+
refresh(): void
|
|
1276
|
+
back(): void
|
|
1277
|
+
forward(): void
|
|
1278
|
+
bfcacheId: string
|
|
1279
|
+
}
|
|
1280
|
+
export function useRouter(): AppRouterInstance
|
|
1281
|
+
export function notFound(): never
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
declare module 'next/navigation' {
|
|
1285
|
+
export interface NavigateOptions {
|
|
1286
|
+
scroll?: boolean
|
|
1287
|
+
}
|
|
1288
|
+
export interface PrefetchOptions {
|
|
1289
|
+
kind?: 'auto' | 'full'
|
|
1290
|
+
onInvalidate?: () => void
|
|
1291
|
+
}
|
|
1292
|
+
export interface AppRouterInstance {
|
|
1293
|
+
push(href: string, options?: NavigateOptions): void
|
|
1294
|
+
replace(href: string, options?: NavigateOptions): void
|
|
1295
|
+
prefetch(href: string, options?: PrefetchOptions): void
|
|
1296
|
+
refresh(): void
|
|
1297
|
+
back(): void
|
|
1298
|
+
forward(): void
|
|
1299
|
+
bfcacheId: string
|
|
1300
|
+
}
|
|
1301
|
+
export function useRouter(): AppRouterInstance
|
|
1302
|
+
export function usePathname(): string
|
|
1303
|
+
export class ReadonlyURLSearchParams extends URLSearchParams {
|
|
1304
|
+
append(): never
|
|
1305
|
+
delete(): never
|
|
1306
|
+
set(): never
|
|
1307
|
+
sort(): never
|
|
1308
|
+
}
|
|
1309
|
+
export function useSearchParams(): ReadonlyURLSearchParams
|
|
1310
|
+
export function useParams<T = Record<string, string | string[]>>(): T
|
|
1311
|
+
export function useSelectedLayoutSegment(parallelRoutesKey?: string): string | null
|
|
1312
|
+
export function useSelectedLayoutSegments(parallelRoutesKey?: string): string[]
|
|
1313
|
+
export function useLayoutSegments(parallelRoutesKey?: string): string[]
|
|
1314
|
+
export function useLinkStatus(): { pending: boolean }
|
|
1315
|
+
export function unstable_isUnrecognizedActionError(error: unknown): boolean
|
|
1316
|
+
export const RedirectType: { push: 'push'; replace: 'replace' }
|
|
1317
|
+
export type RedirectType = 'push' | 'replace'
|
|
1318
|
+
export function notFound(): never
|
|
1319
|
+
export function forbidden(): never
|
|
1320
|
+
export function unauthorized(): never
|
|
1321
|
+
export function redirect(url: string, type?: RedirectType): never
|
|
1322
|
+
export function permanentRedirect(url: string, type?: RedirectType): never
|
|
1323
|
+
export function unstable_rethrow(error: unknown): void
|
|
1324
|
+
export function useServerInsertedHTML(callback: () => any): void
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
declare module 'next/dist/shared/lib/app-router-context.shared-runtime.js' {
|
|
1328
|
+
export interface NavigateOptions {
|
|
1329
|
+
scroll?: boolean
|
|
1330
|
+
}
|
|
1331
|
+
export interface PrefetchOptions {
|
|
1332
|
+
kind?: 'auto' | 'full'
|
|
1333
|
+
onInvalidate?: () => void
|
|
1334
|
+
}
|
|
1335
|
+
export interface AppRouterInstance {
|
|
1336
|
+
push(href: string, options?: NavigateOptions): void
|
|
1337
|
+
replace(href: string, options?: NavigateOptions): void
|
|
1338
|
+
prefetch(href: string, options?: PrefetchOptions): void
|
|
1339
|
+
refresh(): void
|
|
1340
|
+
back(): void
|
|
1341
|
+
forward(): void
|
|
1342
|
+
bfcacheId: string
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
declare module 'next/dist/client/components/redirect-error.js' {
|
|
1347
|
+
export type RedirectType = 'replace' | 'push'
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
declare module 'next/dist/client/form.js' {
|
|
1351
|
+
export interface FormProps {
|
|
1352
|
+
action: any
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
declare module 'next/form' {
|
|
1357
|
+
export interface FormProps {
|
|
1358
|
+
action: string | ((formData: FormData) => void | Promise<void>)
|
|
1359
|
+
replace?: boolean
|
|
1360
|
+
scroll?: boolean
|
|
1361
|
+
prefetch?: boolean
|
|
1362
|
+
[key: string]: any
|
|
1363
|
+
}
|
|
1364
|
+
export default function Form(props: FormProps): any
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
declare module '*.module.css' {
|
|
1368
|
+
const classes: Record<string, string>
|
|
1369
|
+
export default classes
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
declare module '*.module.scss' {
|
|
1373
|
+
const classes: Record<string, string>
|
|
1374
|
+
export default classes
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
declare module '*.module.sass' {
|
|
1378
|
+
const classes: Record<string, string>
|
|
1379
|
+
export default classes
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
declare module '*.css' {
|
|
1383
|
+
const href: string | undefined
|
|
1384
|
+
export default href
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
declare module '*.scss' {
|
|
1388
|
+
const href: string | undefined
|
|
1389
|
+
export default href
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
declare module '*.sass' {
|
|
1393
|
+
const href: string | undefined
|
|
1394
|
+
export default href
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
declare module '*.png' {
|
|
1398
|
+
const content: { src: string; height: number; width: number; blurDataURL?: string }
|
|
1399
|
+
export default content
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
declare module '*.jpg' {
|
|
1403
|
+
const content: { src: string; height: number; width: number; blurDataURL?: string }
|
|
1404
|
+
export default content
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
declare module '*.jpeg' {
|
|
1408
|
+
const content: { src: string; height: number; width: number; blurDataURL?: string }
|
|
1409
|
+
export default content
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
declare module '*.gif' {
|
|
1413
|
+
const content: { src: string; height: number; width: number; blurDataURL?: string }
|
|
1414
|
+
export default content
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
declare module '*.svg' {
|
|
1418
|
+
// \`any\` (not the static-image descriptor shape used above) to avoid
|
|
1419
|
+
// conflicts with \`@svgr/webpack\`-style loader rules that import an SVG as
|
|
1420
|
+
// a component, matching Next's own image-types/global.d.ts.
|
|
1421
|
+
const content: any
|
|
1422
|
+
export default content
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
declare module '*.webp' {
|
|
1426
|
+
const content: { src: string; height: number; width: number; blurDataURL?: string }
|
|
1427
|
+
export default content
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
declare module '*.wasm' {
|
|
1431
|
+
const content: any
|
|
1432
|
+
export default content
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
declare module '*.mdx' {
|
|
1436
|
+
const MDXComponent: (props: any) => any
|
|
1437
|
+
export default MDXComponent
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
declare module '*.md' {
|
|
1441
|
+
const MDXComponent: (props: any) => any
|
|
1442
|
+
export default MDXComponent
|
|
1443
|
+
}
|
|
1444
|
+
${loaderRuleAssetDeclarations()}`;
|
|
1445
|
+
return omitNextModuleShims ? stripNextModuleDeclarations(source) : source;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
// Next's generated `next-env.d.ts` carries ambient wildcard module declarations
|
|
1449
|
+
// for every asset extension its loaders/rules handle, so `import x from
|
|
1450
|
+
// './x.data'` typechecks even though tsc has no on-disk `.data` module. pnext's
|
|
1451
|
+
// generated typecheck env ships the standard set above; add one `any`-typed
|
|
1452
|
+
// wildcard per configured `turbopack.rules` extension that the standard set
|
|
1453
|
+
// (and TS's own source/JSON resolution) does not already cover.
|
|
1454
|
+
const STANDARD_ASSET_DECLARATIONS = new Set([
|
|
1455
|
+
'.css', '.scss', '.sass', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp',
|
|
1456
|
+
'.wasm', '.mdx', '.md',
|
|
1457
|
+
]);
|
|
1458
|
+
const TS_RESOLVED_EXTENSIONS = new Set([
|
|
1459
|
+
'.ts', '.tsx', '.mts', '.cts', '.d.ts', '.js', '.jsx', '.mjs', '.cjs', '.json',
|
|
1460
|
+
]);
|
|
1461
|
+
|
|
1462
|
+
function loaderRuleAssetDeclarations(): string {
|
|
1463
|
+
const specs = new Set<string>();
|
|
1464
|
+
for (const rule of turbopackLoaderRules()) {
|
|
1465
|
+
// Only leading-`*` globs form a valid ambient wildcard module ('*.data').
|
|
1466
|
+
if (!rule.glob.startsWith('*')) continue;
|
|
1467
|
+
const ext = rule.glob.slice(1).toLowerCase();
|
|
1468
|
+
if (STANDARD_ASSET_DECLARATIONS.has(ext) || TS_RESOLVED_EXTENSIONS.has(ext)) continue;
|
|
1469
|
+
specs.add(rule.glob);
|
|
1470
|
+
}
|
|
1471
|
+
if (specs.size === 0) return '';
|
|
1472
|
+
return `${[...specs]
|
|
1473
|
+
.map(
|
|
1474
|
+
spec => `
|
|
1475
|
+
declare module '${spec}' {
|
|
1476
|
+
const content: any
|
|
1477
|
+
export default content
|
|
1478
|
+
}`,
|
|
1479
|
+
)
|
|
1480
|
+
.join('')}\n`;
|
|
1481
|
+
}
|