2022-02-17 19:21:40 +01:00
import type { HtmlProps } from './html-context'
2021-07-21 18:12:33 +02:00
import type { ComponentType } from 'react'
import type { DomainLocale } from '../../server/config'
import type { Env } from '@next/env'
import type { IncomingMessage , ServerResponse } from 'http'
import type { NextRouter } from './router/router'
import type { ParsedUrlQuery } from 'querystring'
import type { PreviewData } from 'next/types'
2022-08-12 15:01:19 +02:00
import { COMPILER_NAMES } from './constants'
2019-04-22 19:55:03 +02:00
2019-05-23 21:31:22 +02:00
export type NextComponentType <
C extends BaseContext = NextPageContext ,
IP = { } ,
P = { }
> = ComponentType < P > & {
2019-12-03 19:35:20 +01:00
/ * *
* Used for initial page load data population . Data returned from ` getInitialProps ` is serialized when server rendered .
* Make sure to return plain ` Object ` without using ` Date ` , ` Map ` , ` Set ` .
* @param ctx Context of ` page `
* /
2019-07-07 20:52:59 +02:00
getInitialProps ? ( context : C ) : IP | Promise < IP >
2019-04-22 19:55:03 +02:00
}
2019-05-23 21:31:22 +02:00
export type DocumentType = NextComponentType <
DocumentContext ,
DocumentInitialProps ,
DocumentProps
2021-08-13 05:36:54 +02:00
>
2019-04-22 19:55:03 +02:00
2019-05-23 21:31:22 +02:00
export type AppType = NextComponentType <
AppContextType ,
AppInitialProps ,
AppPropsType
>
2019-04-22 19:55:03 +02:00
2019-09-09 18:23:34 +02:00
export type AppTreeType = ComponentType <
AppInitialProps & { [ name : string ] : any }
>
2020-07-03 05:36:13 +02:00
/ * *
* Web vitals provided to _app . reportWebVitals by Core Web Vitals plugin developed by Google Chrome team .
* https : //nextjs.org/blog/next-9-4#integrated-web-vitals-reporting
* /
export type NextWebVitalsMetric = {
id : string
startTime : number
value : number
2021-07-20 03:39:24 +02:00
} & (
| {
label : 'web-vital'
2022-06-07 20:28:58 +02:00
name : 'FCP' | 'LCP' | 'CLS' | 'FID' | 'TTFB' | 'INP'
2021-07-20 03:39:24 +02:00
}
| {
label : 'custom'
name :
| 'Next.js-hydration'
| 'Next.js-route-change-to-render'
| 'Next.js-render'
}
)
2020-07-03 05:36:13 +02:00
2019-04-22 19:55:03 +02:00
export type Enhancer < C > = ( Component : C ) = > C
export type ComponentsEnhancer =
2019-05-23 21:31:22 +02:00
| {
enhanceApp? : Enhancer < AppType >
2019-05-29 13:57:26 +02:00
enhanceComponent? : Enhancer < NextComponentType >
2019-05-23 21:31:22 +02:00
}
2019-04-22 19:55:03 +02:00
| Enhancer < NextComponentType >
2019-05-23 21:31:22 +02:00
export type RenderPageResult = {
html : string
head? : Array < JSX.Element | null >
}
2019-04-22 19:55:03 +02:00
2019-05-23 21:31:22 +02:00
export type RenderPage = (
2019-05-29 13:57:26 +02:00
options? : ComponentsEnhancer
2021-09-09 10:13:50 +02:00
) = > DocumentInitialProps | Promise < DocumentInitialProps >
2019-04-22 19:55:03 +02:00
2019-04-26 09:37:57 +02:00
export type BaseContext = {
2019-04-22 19:55:03 +02:00
res? : ServerResponse
2019-05-29 13:57:26 +02:00
[ k : string ] : any
2019-04-22 19:55:03 +02:00
}
2019-05-06 23:42:04 +02:00
export type NEXT_DATA = {
2020-08-14 00:19:06 +02:00
props : Record < string , any >
2019-04-22 19:55:03 +02:00
page : string
query : ParsedUrlQuery
buildId : string
assetPrefix? : string
runtimeConfig ? : { [ key : string ] : any }
nextExport? : boolean
2019-09-15 20:35:14 +02:00
autoExport? : boolean
2020-02-07 14:09:06 +01:00
isFallback? : boolean
2021-04-21 13:18:05 +02:00
dynamicIds ? : ( string | number ) [ ]
2022-08-12 15:01:19 +02:00
err? : Error & {
statusCode? : number
source? : typeof COMPILER_NAMES . server | typeof COMPILER_NAMES . edgeServer
}
2020-03-03 19:39:08 +01:00
gsp? : boolean
gssp? : boolean
2020-03-06 17:14:39 +01:00
customServer? : boolean
2020-04-13 11:59:49 +02:00
gip? : boolean
appGip? : boolean
2020-10-07 23:11:01 +02:00
locale? : string
locales? : string [ ]
2020-10-08 13:12:17 +02:00
defaultLocale? : string
2021-07-21 18:12:33 +02:00
domainLocales? : DomainLocale [ ]
2021-03-02 20:17:33 +01:00
scriptLoader? : any [ ]
2021-02-18 19:34:33 +01:00
isPreview? : boolean
2022-02-16 19:53:48 +01:00
notFoundSrcPage? : string
2021-10-26 18:50:56 +02:00
rsc? : boolean
2019-04-22 19:55:03 +02:00
}
2019-05-23 21:31:22 +02:00
/ * *
* ` Next ` context
* /
2019-05-06 23:42:04 +02:00
export interface NextPageContext {
2019-05-23 21:31:22 +02:00
/ * *
* Error object if encountered during rendering
* /
2019-11-11 04:24:53 +01:00
err ? : ( Error & { statusCode? : number } ) | null
2019-05-23 21:31:22 +02:00
/ * *
* ` HTTP ` request object .
* /
2019-04-22 19:55:03 +02:00
req? : IncomingMessage
2019-05-23 21:31:22 +02:00
/ * *
* ` HTTP ` response object .
* /
2019-04-22 19:55:03 +02:00
res? : ServerResponse
2019-05-23 21:31:22 +02:00
/ * *
* Path section of ` URL ` .
* /
2019-04-22 19:55:03 +02:00
pathname : string
2019-05-23 21:31:22 +02:00
/ * *
* Query string section of ` URL ` parsed as an object .
* /
2019-04-22 19:55:03 +02:00
query : ParsedUrlQuery
2019-05-23 21:31:22 +02:00
/ * *
* ` String ` of the actual path including query .
* /
2019-04-22 19:55:03 +02:00
asPath? : string
2021-05-22 18:35:57 +02:00
/ * *
* The currently active locale
* /
locale? : string
/ * *
* All configured locales
* /
locales? : string [ ]
/ * *
* The configured default locale
* /
defaultLocale? : string
2019-08-13 11:33:48 +02:00
/ * *
* ` Component ` the tree of the App to use if needing to render separately
* /
2019-09-09 18:23:34 +02:00
AppTree : AppTreeType
2019-04-22 19:55:03 +02:00
}
2019-07-11 19:35:39 +02:00
export type AppContextType < R extends NextRouter = NextRouter > = {
2019-05-06 23:42:04 +02:00
Component : NextComponentType < NextPageContext >
2019-09-09 18:23:34 +02:00
AppTree : AppTreeType
2019-05-29 13:57:26 +02:00
ctx : NextPageContext
2019-07-30 20:00:19 +02:00
router : R
2019-04-22 19:55:03 +02:00
}
2022-08-26 03:10:11 +02:00
export type AppInitialProps < P = any > = {
pageProps : P
2019-04-22 19:55:03 +02:00
}
2019-05-23 21:31:22 +02:00
export type AppPropsType <
2019-07-11 19:35:39 +02:00
R extends NextRouter = NextRouter ,
2019-05-23 21:31:22 +02:00
P = { }
2022-08-26 03:10:11 +02:00
> = AppInitialProps < P > & {
Component : NextComponentType < NextPageContext , any , any >
2019-05-29 13:57:26 +02:00
router : R
2020-03-06 05:15:10 +01:00
__N_SSG? : boolean
__N_SSP? : boolean
2021-10-26 18:50:56 +02:00
__N_RSC? : boolean
2019-04-22 19:55:03 +02:00
}
2019-05-06 23:42:04 +02:00
export type DocumentContext = NextPageContext & {
2019-05-29 13:57:26 +02:00
renderPage : RenderPage
2022-04-19 14:37:57 +02:00
defaultGetInitialProps (
ctx : DocumentContext ,
options ? : { nonce? : string }
) : Promise < DocumentInitialProps >
2019-04-22 19:55:03 +02:00
}
2019-04-26 09:37:57 +02:00
export type DocumentInitialProps = RenderPageResult & {
2022-05-23 06:00:36 +02:00
styles? : React.ReactElement [ ] | React . ReactFragment | JSX . Element
2019-04-22 19:55:03 +02:00
}
2021-08-13 05:36:54 +02:00
export type DocumentProps = DocumentInitialProps & HtmlProps
2019-04-22 19:55:03 +02:00
/ * *
2019-06-05 13:22:09 +02:00
* Next ` API ` route request
* /
2020-05-07 00:04:24 +02:00
export interface NextApiRequest extends IncomingMessage {
2019-06-05 13:22:09 +02:00
/ * *
* Object of ` query ` values from url
* /
fix NextApiRequestCookies and NextApiRequestQuery types (#25532)
Hello! Thanks for making next.js so great.
## Bug
Right now, these types give false confidence. These `key`s are treated as though [a value is defined for _every_ string](https://dev.to/sarioglu/avoiding-unintended-undefined-values-while-using-typescript-record-4igo). However, given an arbitrary request, a particular cookie or query param could be `undefined`.
For example, when building an `/api` endpoint, the code might look like this:
```ts
import type { NextApiRequest, NextApiResponse } from "next"
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// According to the old types, `value` is a string
const value = req.cookies.value
// Type-checking passes but leads to a runtime error when no `value` cookie is provided in the request
// Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
value.toLowerCause()
// ...
}
```
By using `Partial`, TypeScript now knows that these objects don't have values defined for every `key` and accessing a given `key` might resolve to `undefined`.
---
The only obvious error this caused within this repo was on line 333 of the same file. For better or worse, I ended up casting that cookie value to a `string`. There's a series of `if` statements before it that, I guess, are guaranteeing that it's truly a string. Potentially, that stretch could be refactored such that TypeScript _knows_ it's a string.
Also, I tried to follow the contributing guidelines. However, running `yarn types` kicked out a bunch of errors about overwriting files:
```
$ yarn types
yarn run v1.22.10
$ lerna run types --stream
lerna notice cli v4.0.0
lerna info Executing command in 2 packages: "yarn run types"
@next/env: $ tsc index.ts --declaration --emitDeclarationOnly --declarationDir types --esModuleInterop
next: $ tsc --declaration --emitDeclarationOnly --declarationDir dist
next: error TS5055: Cannot write file '/Users/mbrandly/code/next.js/packages/next/dist/build/index.d.ts' because it would overwrite input file.
next: error TS5055: Cannot write file '/Users/mbrandly/code/next.js/packages/next/dist/build/webpack/plugins/build-manifest-plugin.d.ts' because it would overwrite input file.
...
...
...
```
Let me know if there's anything I can improve here! Thanks again.
2022-05-23 02:48:26 +02:00
query : Partial < {
2019-06-05 13:22:09 +02:00
[ key : string ] : string | string [ ]
fix NextApiRequestCookies and NextApiRequestQuery types (#25532)
Hello! Thanks for making next.js so great.
## Bug
Right now, these types give false confidence. These `key`s are treated as though [a value is defined for _every_ string](https://dev.to/sarioglu/avoiding-unintended-undefined-values-while-using-typescript-record-4igo). However, given an arbitrary request, a particular cookie or query param could be `undefined`.
For example, when building an `/api` endpoint, the code might look like this:
```ts
import type { NextApiRequest, NextApiResponse } from "next"
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// According to the old types, `value` is a string
const value = req.cookies.value
// Type-checking passes but leads to a runtime error when no `value` cookie is provided in the request
// Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
value.toLowerCause()
// ...
}
```
By using `Partial`, TypeScript now knows that these objects don't have values defined for every `key` and accessing a given `key` might resolve to `undefined`.
---
The only obvious error this caused within this repo was on line 333 of the same file. For better or worse, I ended up casting that cookie value to a `string`. There's a series of `if` statements before it that, I guess, are guaranteeing that it's truly a string. Potentially, that stretch could be refactored such that TypeScript _knows_ it's a string.
Also, I tried to follow the contributing guidelines. However, running `yarn types` kicked out a bunch of errors about overwriting files:
```
$ yarn types
yarn run v1.22.10
$ lerna run types --stream
lerna notice cli v4.0.0
lerna info Executing command in 2 packages: "yarn run types"
@next/env: $ tsc index.ts --declaration --emitDeclarationOnly --declarationDir types --esModuleInterop
next: $ tsc --declaration --emitDeclarationOnly --declarationDir dist
next: error TS5055: Cannot write file '/Users/mbrandly/code/next.js/packages/next/dist/build/index.d.ts' because it would overwrite input file.
next: error TS5055: Cannot write file '/Users/mbrandly/code/next.js/packages/next/dist/build/webpack/plugins/build-manifest-plugin.d.ts' because it would overwrite input file.
...
...
...
```
Let me know if there's anything I can improve here! Thanks again.
2022-05-23 02:48:26 +02:00
} >
2019-06-05 13:22:09 +02:00
/ * *
* Object of ` cookies ` from header
* /
fix NextApiRequestCookies and NextApiRequestQuery types (#25532)
Hello! Thanks for making next.js so great.
## Bug
Right now, these types give false confidence. These `key`s are treated as though [a value is defined for _every_ string](https://dev.to/sarioglu/avoiding-unintended-undefined-values-while-using-typescript-record-4igo). However, given an arbitrary request, a particular cookie or query param could be `undefined`.
For example, when building an `/api` endpoint, the code might look like this:
```ts
import type { NextApiRequest, NextApiResponse } from "next"
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// According to the old types, `value` is a string
const value = req.cookies.value
// Type-checking passes but leads to a runtime error when no `value` cookie is provided in the request
// Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
value.toLowerCause()
// ...
}
```
By using `Partial`, TypeScript now knows that these objects don't have values defined for every `key` and accessing a given `key` might resolve to `undefined`.
---
The only obvious error this caused within this repo was on line 333 of the same file. For better or worse, I ended up casting that cookie value to a `string`. There's a series of `if` statements before it that, I guess, are guaranteeing that it's truly a string. Potentially, that stretch could be refactored such that TypeScript _knows_ it's a string.
Also, I tried to follow the contributing guidelines. However, running `yarn types` kicked out a bunch of errors about overwriting files:
```
$ yarn types
yarn run v1.22.10
$ lerna run types --stream
lerna notice cli v4.0.0
lerna info Executing command in 2 packages: "yarn run types"
@next/env: $ tsc index.ts --declaration --emitDeclarationOnly --declarationDir types --esModuleInterop
next: $ tsc --declaration --emitDeclarationOnly --declarationDir dist
next: error TS5055: Cannot write file '/Users/mbrandly/code/next.js/packages/next/dist/build/index.d.ts' because it would overwrite input file.
next: error TS5055: Cannot write file '/Users/mbrandly/code/next.js/packages/next/dist/build/webpack/plugins/build-manifest-plugin.d.ts' because it would overwrite input file.
...
...
...
```
Let me know if there's anything I can improve here! Thanks again.
2022-05-23 02:48:26 +02:00
cookies : Partial < {
2019-06-05 13:22:09 +02:00
[ key : string ] : string
fix NextApiRequestCookies and NextApiRequestQuery types (#25532)
Hello! Thanks for making next.js so great.
## Bug
Right now, these types give false confidence. These `key`s are treated as though [a value is defined for _every_ string](https://dev.to/sarioglu/avoiding-unintended-undefined-values-while-using-typescript-record-4igo). However, given an arbitrary request, a particular cookie or query param could be `undefined`.
For example, when building an `/api` endpoint, the code might look like this:
```ts
import type { NextApiRequest, NextApiResponse } from "next"
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// According to the old types, `value` is a string
const value = req.cookies.value
// Type-checking passes but leads to a runtime error when no `value` cookie is provided in the request
// Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
value.toLowerCause()
// ...
}
```
By using `Partial`, TypeScript now knows that these objects don't have values defined for every `key` and accessing a given `key` might resolve to `undefined`.
---
The only obvious error this caused within this repo was on line 333 of the same file. For better or worse, I ended up casting that cookie value to a `string`. There's a series of `if` statements before it that, I guess, are guaranteeing that it's truly a string. Potentially, that stretch could be refactored such that TypeScript _knows_ it's a string.
Also, I tried to follow the contributing guidelines. However, running `yarn types` kicked out a bunch of errors about overwriting files:
```
$ yarn types
yarn run v1.22.10
$ lerna run types --stream
lerna notice cli v4.0.0
lerna info Executing command in 2 packages: "yarn run types"
@next/env: $ tsc index.ts --declaration --emitDeclarationOnly --declarationDir types --esModuleInterop
next: $ tsc --declaration --emitDeclarationOnly --declarationDir dist
next: error TS5055: Cannot write file '/Users/mbrandly/code/next.js/packages/next/dist/build/index.d.ts' because it would overwrite input file.
next: error TS5055: Cannot write file '/Users/mbrandly/code/next.js/packages/next/dist/build/webpack/plugins/build-manifest-plugin.d.ts' because it would overwrite input file.
...
...
...
```
Let me know if there's anything I can improve here! Thanks again.
2022-05-23 02:48:26 +02:00
} >
2019-06-05 13:22:09 +02:00
body : any
2020-03-26 13:32:41 +01:00
env : Env
2020-07-07 05:41:16 +02:00
preview? : boolean
/ * *
* Preview data set on the request , if any
* * /
2021-04-20 20:13:48 +02:00
previewData? : PreviewData
2019-06-05 13:22:09 +02:00
}
/ * *
* Send body of response
2019-04-22 19:55:03 +02:00
* /
2019-07-09 19:02:46 +02:00
type Send < T > = ( body : T ) = > void
2019-04-22 19:55:03 +02:00
2019-06-05 13:22:09 +02:00
/ * *
* Next ` API ` route response
* /
2019-07-09 19:02:46 +02:00
export type NextApiResponse < T = any > = ServerResponse & {
2019-06-05 13:22:09 +02:00
/ * *
2019-07-10 16:43:04 +02:00
* Send data ` any ` data in response
2019-06-05 13:22:09 +02:00
* /
2019-07-09 19:02:46 +02:00
send : Send < T >
2019-06-05 13:22:09 +02:00
/ * *
2019-07-10 16:43:04 +02:00
* Send data ` json ` data in response
2019-06-05 13:22:09 +02:00
* /
2019-07-09 19:02:46 +02:00
json : Send < T >
status : ( statusCode : number ) = > NextApiResponse < T >
2020-07-29 09:01:21 +02:00
redirect ( url : string ) : NextApiResponse < T >
redirect ( status : number , url : string ) : NextApiResponse < T >
2020-02-12 02:16:42 +01:00
/ * *
* Set preview data for Next . js ' prerender mode
* /
setPreviewData : (
data : object | string ,
options ? : {
/ * *
* Specifies the number ( in seconds ) for the preview session to last for .
* The given number will be converted to an integer by rounding down .
* By default , no maximum age is set and the preview session finishes
* when the client shuts down ( browser is closed ) .
* /
maxAge? : number
2022-08-08 03:45:30 +02:00
/ * *
* Specifies the path for the preview session to work under . By default ,
* the path is considered the "default path" , i . e . , any pages under "/" .
* /
path? : string
2020-02-12 02:16:42 +01:00
}
) = > NextApiResponse < T >
2022-09-05 22:37:08 +02:00
/ * *
* Clear preview data for Next . js ' prerender mode
* /
clearPreviewData : ( options ? : { path? : string } ) = > NextApiResponse < T >
2022-02-08 04:50:23 +01:00
2022-06-27 21:28:41 +02:00
/ * *
* @deprecated ` unstable_revalidate ` has been renamed to ` revalidate `
* /
unstable_revalidate : ( ) = > void
2022-06-24 23:59:23 +02:00
revalidate : (
2022-04-13 18:56:58 +02:00
urlPath : string ,
opts ? : {
unstable_onlyGenerated? : boolean
}
) = > Promise < void >
2019-06-05 13:22:09 +02:00
}
2020-02-19 04:57:31 +01:00
/ * *
* Next ` API ` route handler
* /
export type NextApiHandler < T = any > = (
req : NextApiRequest ,
res : NextApiResponse < T >
2022-04-16 06:00:52 +02:00
) = > unknown | Promise < unknown >
2020-02-19 04:57:31 +01:00
2019-06-05 13:22:09 +02:00
/ * *
* Utils
* /
2020-04-06 17:59:44 +02:00
export function execOnce < T extends ( ...args : any [ ] ) = > ReturnType < T > > (
fn : T
) : T {
2019-04-22 19:55:03 +02:00
let used = false
2020-04-06 17:59:44 +02:00
let result : ReturnType < T >
2019-11-01 20:13:13 +01:00
2020-04-06 17:59:44 +02:00
return ( ( . . . args : any [ ] ) = > {
2019-04-22 19:55:03 +02:00
if ( ! used ) {
used = true
2020-04-06 17:59:44 +02:00
result = fn ( . . . args )
2019-04-22 19:55:03 +02:00
}
2019-11-01 20:13:13 +01:00
return result
2020-04-06 17:59:44 +02:00
} ) as T
2019-04-22 19:55:03 +02:00
}
2022-05-22 18:43:48 +02:00
// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
const ABSOLUTE_URL_REGEX = /^[a-zA-Z][a-zA-Z\d+\-.]*?:/
export const isAbsoluteUrl = ( url : string ) = > ABSOLUTE_URL_REGEX . test ( url )
2019-04-22 19:55:03 +02:00
export function getLocationOrigin() {
const { protocol , hostname , port } = window . location
return ` ${ protocol } // ${ hostname } ${ port ? ':' + port : '' } `
}
export function getURL() {
const { href } = window . location
const origin = getLocationOrigin ( )
return href . substring ( origin . length )
}
2020-04-06 17:59:44 +02:00
export function getDisplayName < P > ( Component : ComponentType < P > ) {
2019-05-23 21:31:22 +02:00
return typeof Component === 'string'
? Component
: Component . displayName || Component . name || 'Unknown'
2019-04-22 19:55:03 +02:00
}
export function isResSent ( res : ServerResponse ) {
return res . finished || res . headersSent
}
2021-08-03 17:06:26 +02:00
export function normalizeRepeatedSlashes ( url : string ) {
const urlParts = url . split ( '?' )
const urlNoQuery = urlParts [ 0 ]
return (
urlNoQuery
// first we replace any non-encoded backslashes with forward
// then normalize repeated forward slashes
. replace ( /\\/g , '/' )
. replace ( /\/\/+/g , '/' ) +
( urlParts [ 1 ] ? ` ? ${ urlParts . slice ( 1 ) . join ( '?' ) } ` : '' )
)
}
2019-05-23 21:31:22 +02:00
export async function loadGetInitialProps <
C extends BaseContext ,
IP = { } ,
P = { }
2019-11-02 16:00:55 +01:00
> ( App : NextComponentType < C , IP , P > , ctx : C ) : Promise < IP > {
2019-04-22 19:55:03 +02:00
if ( process . env . NODE_ENV !== 'production' ) {
2020-01-08 17:30:53 +01:00
if ( App . prototype ? . getInitialProps ) {
2019-05-23 21:31:22 +02:00
const message = ` " ${ getDisplayName (
2019-11-02 16:00:55 +01:00
App
2021-03-29 10:25:00 +02:00
) } . getInitialProps ( ) " is defined as an instance method - visit https : //nextjs.org/docs/messages/get-initial-props-as-an-instance-method for more information.`
2019-04-22 19:55:03 +02:00
throw new Error ( message )
}
}
2019-04-30 23:28:25 +02:00
// when called from _app `ctx` is nested in `ctx`
const res = ctx . res || ( ctx . ctx && ctx . ctx . res )
2019-04-22 19:55:03 +02:00
2019-11-02 16:00:55 +01:00
if ( ! App . getInitialProps ) {
if ( ctx . ctx && ctx . Component ) {
// @ts-ignore pageProps default
return {
pageProps : await loadGetInitialProps ( ctx . Component , ctx . ctx ) ,
}
}
2020-04-06 17:59:44 +02:00
return { } as IP
2019-04-25 10:11:05 +02:00
}
2019-04-22 19:55:03 +02:00
2019-11-02 16:00:55 +01:00
const props = await App . getInitialProps ( ctx )
2019-04-22 19:55:03 +02:00
2019-04-30 23:28:25 +02:00
if ( res && isResSent ( res ) ) {
2019-04-22 19:55:03 +02:00
return props
}
if ( ! props ) {
2019-05-23 21:31:22 +02:00
const message = ` " ${ getDisplayName (
2019-11-02 16:00:55 +01:00
App
2019-05-23 21:31:22 +02:00
) } . getInitialProps ( ) " should resolve to an object. But found " $ { props } " instead . `
2019-04-22 19:55:03 +02:00
throw new Error ( message )
}
2019-08-22 19:06:30 +02:00
if ( process . env . NODE_ENV !== 'production' ) {
if ( Object . keys ( props ) . length === 0 && ! ctx . ctx ) {
console . warn (
` ${ getDisplayName (
2019-11-02 16:00:55 +01:00
App
2021-03-29 10:25:00 +02:00
) } returned an empty object from \ ` getInitialProps \` . This de-optimizes and prevents automatic static optimization. https://nextjs.org/docs/messages/empty-object-getInitialProps `
2019-08-22 19:06:30 +02:00
)
}
}
2019-04-22 19:55:03 +02:00
return props
}
2022-02-28 23:39:51 +01:00
let warnOnce = ( _ : string ) = > { }
if ( process . env . NODE_ENV !== 'production' ) {
const warnings = new Set < string > ( )
warnOnce = ( msg : string ) = > {
if ( ! warnings . has ( msg ) ) {
console . warn ( msg )
}
warnings . add ( msg )
}
}
export { warnOnce }
2020-01-04 21:53:33 +01:00
export const SP = typeof performance !== 'undefined'
export const ST =
SP &&
2022-06-30 18:06:53 +02:00
( [ 'mark' , 'measure' , 'getEntriesByName' ] as const ) . every (
( method ) = > typeof performance [ method ] === 'function'
)
2021-07-05 18:31:32 +02:00
export class DecodeError extends Error { }
2022-05-01 11:23:06 +02:00
export class NormalizeError extends Error { }
2022-06-06 20:35:26 +02:00
export class PageNotFoundError extends Error {
code : string
constructor ( page : string ) {
super ( )
this . code = 'ENOENT'
this . message = ` Cannot find module for page: ${ page } `
}
}
2021-08-13 05:36:54 +02:00
2022-06-27 21:15:09 +02:00
export class MissingStaticPage extends Error {
constructor ( page : string , message : string ) {
super ( )
this . message = ` Failed to load static file for page: ${ page } ${ message } `
}
}
2022-06-24 20:50:49 +02:00
export class MiddlewareNotFoundError extends Error {
code : string
constructor ( ) {
super ( )
this . code = 'ENOENT'
this . message = ` Cannot find the middleware module `
}
}
2021-12-17 23:56:26 +01:00
export interface CacheFs {
readFile ( f : string ) : Promise < string >
readFileSync ( f : string ) : string
writeFile ( f : string , d : any ) : Promise < void >
2022-01-04 16:35:32 +01:00
mkdir ( dir : string ) : Promise < void | string >
2021-12-17 23:56:26 +01:00
stat ( f : string ) : Promise < { mtime : Date } >
}