1
1
import type { Rewrite , Redirect } from '../../../../lib/load-custom-routes'
2
- import type { Token } from 'next/dist/compiled/path-to-regexp'
3
2
4
3
import fs from 'fs/promises'
5
4
import { webpack , sources } from 'next/dist/compiled/webpack/webpack'
6
- import { parse } from 'next/dist/compiled/path-to-regexp'
7
5
import path from 'path'
8
6
9
7
import { WEBPACK_LAYERS } from '../../../../lib/constants'
@@ -15,7 +13,6 @@ import { isDynamicRoute } from '../../../../shared/lib/router/utils'
15
13
import { normalizeAppPath } from '../../../../shared/lib/router/utils/app-paths'
16
14
import { getPageFromPath } from '../../../entries'
17
15
import type { PageExtensions } from '../../../page-extensions-type'
18
- import { devPageFiles } from './shared'
19
16
import { getProxiedPluginState } from '../../../build-context'
20
17
import type { CacheLife } from '../../../../server/use-cache/cache-life'
21
18
@@ -285,266 +282,6 @@ function formatRouteToRouteType(route: string) {
285
282
}
286
283
}
287
284
288
- // Whether redirects and rewrites have been converted into routeTypes or not.
289
- let redirectsRewritesTypesProcessed = false
290
-
291
- // Convert redirects and rewrites into routeTypes.
292
- function addRedirectsRewritesRouteTypes (
293
- rewrites : Rewrites | undefined ,
294
- redirects : Redirect [ ] | undefined
295
- ) {
296
- function addExtraRoute ( source : string ) {
297
- let tokens : Token [ ] | undefined
298
- try {
299
- tokens = parse ( source )
300
- } catch {
301
- // Ignore invalid routes - they will be handled by other checks.
302
- }
303
-
304
- if ( Array . isArray ( tokens ) ) {
305
- const possibleNormalizedRoutes = [ '' ]
306
- let slugCnt = 1
307
-
308
- function append ( suffix : string ) {
309
- for ( let i = 0 ; i < possibleNormalizedRoutes . length ; i ++ ) {
310
- possibleNormalizedRoutes [ i ] += suffix
311
- }
312
- }
313
-
314
- function fork ( suffix : string ) {
315
- const currentLength = possibleNormalizedRoutes . length
316
- for ( let i = 0 ; i < currentLength ; i ++ ) {
317
- possibleNormalizedRoutes . push ( possibleNormalizedRoutes [ i ] + suffix )
318
- }
319
- }
320
-
321
- for ( const token of tokens ) {
322
- if ( typeof token === 'object' ) {
323
- // Make sure the slug is always named.
324
- const slug =
325
- token . name || ( slugCnt ++ === 1 ? 'slug' : `slug${ slugCnt } ` )
326
-
327
- if ( token . modifier === '*' ) {
328
- append ( `${ token . prefix } [[...${ slug } ]]` )
329
- } else if ( token . modifier === '+' ) {
330
- append ( `${ token . prefix } [...${ slug } ]` )
331
- } else if ( token . modifier === '' ) {
332
- if ( token . pattern === '[^\\/#\\?]+?' ) {
333
- // A safe slug
334
- append ( `${ token . prefix } [${ slug } ]` )
335
- } else if ( token . pattern === '.*' ) {
336
- // An optional catch-all slug
337
- append ( `${ token . prefix } [[...${ slug } ]]` )
338
- } else if ( token . pattern === '.+' ) {
339
- // A catch-all slug
340
- append ( `${ token . prefix } [...${ slug } ]` )
341
- } else {
342
- // Other regex patterns are not supported. Skip this route.
343
- return
344
- }
345
- } else if ( token . modifier === '?' ) {
346
- if ( / ^ [ a - z A - Z 0 - 9 _ / ] * $ / . test ( token . pattern ) ) {
347
- // An optional slug with plain text only, fork the route.
348
- append ( token . prefix )
349
- fork ( token . pattern )
350
- } else {
351
- // Optional modifier `?` and regex patterns are not supported.
352
- return
353
- }
354
- }
355
- } else if ( typeof token === 'string' ) {
356
- append ( token )
357
- }
358
- }
359
-
360
- for ( const normalizedRoute of possibleNormalizedRoutes ) {
361
- const { isDynamic, routeType } = formatRouteToRouteType ( normalizedRoute )
362
- pluginState . routeTypes . extra [ isDynamic ? 'dynamic' : 'static' ] . push (
363
- routeType
364
- )
365
- }
366
- }
367
- }
368
-
369
- if ( rewrites ) {
370
- for ( const rewrite of rewrites . beforeFiles ) {
371
- addExtraRoute ( rewrite . source )
372
- }
373
- for ( const rewrite of rewrites . afterFiles ) {
374
- addExtraRoute ( rewrite . source )
375
- }
376
- for ( const rewrite of rewrites . fallback ) {
377
- addExtraRoute ( rewrite . source )
378
- }
379
- }
380
-
381
- if ( redirects ) {
382
- for ( const redirect of redirects ) {
383
- // Skip internal redirects
384
- // https://github.com/vercel/next.js/blob/8ff3d7ff57836c24088474175d595b4d50b3f857/packages/next/src/lib/load-custom-routes.ts#L704-L710
385
- if ( ! ( 'internal' in redirect ) ) {
386
- addExtraRoute ( redirect . source )
387
- }
388
- }
389
- }
390
- }
391
-
392
- function serializeRouteTypes ( routeTypes : string [ ] ) {
393
- // route collection is not deterministic, this makes the output of the file deterministic
394
- return routeTypes
395
- . sort ( )
396
- . map ( ( route ) => `\n | \`${ route } \`` )
397
- . join ( '' )
398
- }
399
-
400
- function createRouteDefinitions ( ) {
401
- let staticRouteTypes = [ ]
402
- let dynamicRouteTypes = [ ]
403
-
404
- for ( const type of [ 'edge' , 'node' , 'extra' ] as const ) {
405
- staticRouteTypes . push ( ...pluginState . routeTypes [ type ] . static )
406
- dynamicRouteTypes . push ( ...pluginState . routeTypes [ type ] . dynamic )
407
- }
408
-
409
- const serializedStaticRouteTypes = serializeRouteTypes ( staticRouteTypes )
410
- const serializedDynamicRouteTypes = serializeRouteTypes ( dynamicRouteTypes )
411
-
412
- // If both StaticRoutes and DynamicRoutes are empty, fallback to type 'string & {}'.
413
- const routeTypesFallback =
414
- ! serializedStaticRouteTypes && ! serializedDynamicRouteTypes
415
- ? 'string & {}'
416
- : ''
417
-
418
- return `// Type definitions for Next.js routes
419
-
420
- /**
421
- * Internal types used by the Next.js router and Link component.
422
- * These types are not meant to be used directly.
423
- * @internal
424
- */
425
- declare namespace __next_route_internal_types__ {
426
- type SearchOrHash = \`?\${string}\` | \`#\${string}\`
427
- type WithProtocol = \`\${string}:\${string}\`
428
-
429
- type Suffix = '' | SearchOrHash
430
-
431
- type SafeSlug<S extends string> = S extends \`\${string}/\${string}\`
432
- ? never
433
- : S extends \`\${string}\${SearchOrHash}\`
434
- ? never
435
- : S extends ''
436
- ? never
437
- : S
438
-
439
- type CatchAllSlug<S extends string> = S extends \`\${string}\${SearchOrHash}\`
440
- ? never
441
- : S extends ''
442
- ? never
443
- : S
444
-
445
- type OptionalCatchAllSlug<S extends string> =
446
- S extends \`\${string}\${SearchOrHash}\` ? never : S
447
-
448
- type StaticRoutes = ${ serializedStaticRouteTypes || 'never' }
449
- type DynamicRoutes<T extends string = string> = ${
450
- serializedDynamicRouteTypes || 'never'
451
- }
452
-
453
- type RouteImpl<T> = ${
454
- routeTypesFallback ||
455
- `
456
- ${
457
- // This keeps autocompletion working for static routes.
458
- '| StaticRoutes'
459
- }
460
- | SearchOrHash
461
- | WithProtocol
462
- | \`\${StaticRoutes}\${SearchOrHash}\`
463
- | (T extends \`\${DynamicRoutes<infer _>}\${Suffix}\` ? T : never)
464
- `
465
- }
466
- }
467
-
468
- declare module 'next' {
469
- export { default } from 'next/types.js'
470
- export * from 'next/types.js'
471
-
472
- export type Route<T extends string = string> =
473
- __next_route_internal_types__.RouteImpl<T>
474
- }
475
-
476
- declare module 'next/link' {
477
- import type { LinkProps as OriginalLinkProps } from 'next/dist/client/link.js'
478
- import type { AnchorHTMLAttributes, DetailedHTMLProps } from 'react'
479
- import type { UrlObject } from 'url'
480
-
481
- type LinkRestProps = Omit<
482
- Omit<
483
- DetailedHTMLProps<
484
- AnchorHTMLAttributes<HTMLAnchorElement>,
485
- HTMLAnchorElement
486
- >,
487
- keyof OriginalLinkProps
488
- > &
489
- OriginalLinkProps,
490
- 'href'
491
- >
492
-
493
- export type LinkProps<RouteInferType> = LinkRestProps & {
494
- /**
495
- * The path or URL to navigate to. This is the only required prop. It can also be an object.
496
- * @see https://nextjs.org/docs/api-reference/next/link
497
- */
498
- href: __next_route_internal_types__.RouteImpl<RouteInferType> | UrlObject
499
- }
500
-
501
- export default function Link<RouteType>(props: LinkProps<RouteType>): JSX.Element
502
- }
503
-
504
- declare module 'next/navigation' {
505
- export * from 'next/dist/client/components/navigation.js'
506
-
507
- import type { NavigateOptions, AppRouterInstance as OriginalAppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime.js'
508
- interface AppRouterInstance extends OriginalAppRouterInstance {
509
- /**
510
- * Navigate to the provided href.
511
- * Pushes a new history entry.
512
- */
513
- push<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>, options?: NavigateOptions): void
514
- /**
515
- * Navigate to the provided href.
516
- * Replaces the current history entry.
517
- */
518
- replace<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>, options?: NavigateOptions): void
519
- /**
520
- * Prefetch the provided href.
521
- */
522
- prefetch<RouteType>(href: __next_route_internal_types__.RouteImpl<RouteType>): void
523
- }
524
-
525
- export function useRouter(): AppRouterInstance;
526
- }
527
-
528
- declare module 'next/form' {
529
- import type { FormProps as OriginalFormProps } from 'next/dist/client/form.js'
530
-
531
- type FormRestProps = Omit<OriginalFormProps, 'action'>
532
-
533
- export type FormProps<RouteInferType> = {
534
- /**
535
- * \`action\` can be either a \`string\` or a function.
536
- * - If \`action\` is a string, it will be interpreted as a path or URL to navigate to when the form is submitted.
537
- * The path will be prefetched when the form becomes visible.
538
- * - If \`action\` is a function, it will be called when the form is submitted. See the [React docs](https://react.dev/reference/react-dom/components/form#props) for more.
539
- */
540
- action: __next_route_internal_types__.RouteImpl<RouteInferType> | ((formData: FormData) => void)
541
- } & FormRestProps
542
-
543
- export default function Form<RouteType>(props: FormProps<RouteType>): JSX.Element
544
- }
545
- `
546
- }
547
-
548
285
function formatTimespan ( seconds : number ) : string {
549
286
if ( seconds > 0 ) {
550
287
if ( seconds === 18748800 ) {
@@ -841,13 +578,6 @@ export class NextTypesPlugin {
841
578
this . typedRoutes = options . typedRoutes
842
579
this . cacheLifeConfig = options . cacheLifeConfig
843
580
this . distDirAbsolutePath = path . join ( this . dir , this . distDir )
844
- if ( this . typedRoutes && ! redirectsRewritesTypesProcessed ) {
845
- redirectsRewritesTypesProcessed = true
846
- addRedirectsRewritesRouteTypes (
847
- options . originalRewrites ,
848
- options . originalRedirects
849
- )
850
- }
851
581
}
852
582
853
583
getRelativePathFromAppTypesDir ( moduleRelativePathToAppDir : string ) {
@@ -1109,23 +839,6 @@ export class NextTypesPlugin {
1109
839
) as unknown as webpack . sources . RawSource
1110
840
)
1111
841
1112
- if ( this . typedRoutes ) {
1113
- if ( this . dev && ! this . isEdgeServer ) {
1114
- devPageFiles . forEach ( ( file ) => {
1115
- this . collectPage ( file )
1116
- } )
1117
- }
1118
-
1119
- const linkAssetPath = path . join ( assetDirRelative , 'types/link.d.ts' )
1120
-
1121
- compilation . emitAsset (
1122
- linkAssetPath ,
1123
- new sources . RawSource (
1124
- createRouteDefinitions ( )
1125
- ) as unknown as webpack . sources . RawSource
1126
- )
1127
- }
1128
-
1129
842
if ( this . cacheLifeConfig ) {
1130
843
const cacheLifeAssetPath = path . join (
1131
844
assetDirRelative ,
0 commit comments