Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: rename draft mode enabled to isEnabled #49096

Merged
merged 9 commits into from May 2, 2023
28 changes: 28 additions & 0 deletions packages/next/src/client/components/draft-mode.ts
@@ -0,0 +1,28 @@
import { DraftModeProvider } from '../../server/async-storage/draft-mode-provider'
import { staticGenerationBailout } from './static-generation-bailout'

export class DraftMode {
/**
* @internal - this declaration is stripped via `tsc --stripInternal`
*/
private readonly _provider: DraftModeProvider

constructor(provider: DraftModeProvider) {
this._provider = provider
}
get isEnabled() {
return this._provider.isEnabled
}
public enable() {
if (staticGenerationBailout('draftMode().enable()')) {
return
}
return this._provider.enable()
}
public disable() {
if (staticGenerationBailout('draftMode().disable()')) {
return
}
return this._provider.disable()
}
}
22 changes: 3 additions & 19 deletions packages/next/src/client/components/headers.ts
Expand Up @@ -7,7 +7,7 @@ import { RequestCookies } from '../../server/web/spec-extension/cookies'
import { requestAsyncStorage } from './request-async-storage'
import { actionAsyncStorage } from './action-async-storage'
import { staticGenerationBailout } from './static-generation-bailout'
import { DraftMode } from '../../../types'
import { DraftMode } from './draft-mode'

export function headers() {
if (staticGenerationBailout('headers')) {
Expand Down Expand Up @@ -49,28 +49,12 @@ export function cookies() {
return requestStore.cookies
}

export function draftMode(): DraftMode {
export function draftMode() {
const requestStore = requestAsyncStorage.getStore()
if (!requestStore) {
throw new Error(
`Invariant: Method expects to have requestAsyncStorage, none available`
)
}
return {
get enabled() {
return requestStore.draftMode.enabled
},
enable() {
if (staticGenerationBailout('draftMode().enable()')) {
return
}
return requestStore.draftMode.enable()
},
disable() {
if (staticGenerationBailout('draftMode().disable()')) {
return
}
return requestStore.draftMode.disable()
},
}
return new DraftMode(requestStore.draftMode)
}
@@ -1,6 +1,6 @@
import type { AsyncLocalStorage } from 'async_hooks'
import type { DraftModeProvider } from '../../server/async-storage/draft-mode-provider'
import type { ResponseCookies } from '../../server/web/spec-extension/cookies'
import type { DraftMode } from '../../../types'
import type { ReadonlyHeaders } from '../../server/web/spec-extension/adapters/headers'
import type { ReadonlyRequestCookies } from '../../server/web/spec-extension/adapters/request-cookies'

Expand All @@ -10,7 +10,7 @@ export interface RequestStore {
readonly headers: ReadonlyHeaders
readonly cookies: ReadonlyRequestCookies
readonly mutableCookies: ResponseCookies
readonly draftMode: DraftMode
readonly draftMode: DraftModeProvider
}

export type RequestAsyncStorage = AsyncLocalStorage<RequestStore>
Expand Down
Expand Up @@ -10,45 +10,54 @@ import {
__ApiPreviewProps,
} from '../api-utils'

export class DraftMode {
public readonly enabled: boolean
export class DraftModeProvider {
public readonly isEnabled: boolean

private readonly previewModeId: string | undefined
/**
* @internal - this declaration is stripped via `tsc --stripInternal`
*/
private readonly _previewModeId: string | undefined

/**
* @internal - this declaration is stripped via `tsc --stripInternal`
*/
private readonly _mutableCookies: ResponseCookies

constructor(
previewProps: __ApiPreviewProps | undefined,
req: IncomingMessage | BaseNextRequest<unknown> | NextRequest,
private readonly cookies: ReadonlyRequestCookies,
private readonly mutableCookies: ResponseCookies
cookies: ReadonlyRequestCookies,
mutableCookies: ResponseCookies
) {
// The logic for draftMode() is very similar to tryGetPreviewData()
// but Draft Mode does not have any data associated with it.
const isOnDemandRevalidate =
previewProps &&
checkIsOnDemandRevalidate(req, previewProps).isOnDemandRevalidate

const cookieValue = this.cookies.get(COOKIE_NAME_PRERENDER_BYPASS)?.value
const cookieValue = cookies.get(COOKIE_NAME_PRERENDER_BYPASS)?.value

this.enabled = Boolean(
this.isEnabled = Boolean(
!isOnDemandRevalidate &&
cookieValue &&
previewProps &&
cookieValue === previewProps.previewModeId
)

this.previewModeId = previewProps?.previewModeId
this._previewModeId = previewProps?.previewModeId
this._mutableCookies = mutableCookies
}

enable() {
if (!this.previewModeId) {
if (!this._previewModeId) {
throw new Error(
'Invariant: previewProps missing previewModeId this should not be hit'
'Invariant: previewProps missing previewModeId this should never happen'
)
}

this.mutableCookies.set({
this._mutableCookies.set({
name: COOKIE_NAME_PRERENDER_BYPASS,
value: this.previewModeId,
value: this._previewModeId,
httpOnly: true,
sameSite: process.env.NODE_ENV !== 'development' ? 'none' : 'lax',
secure: process.env.NODE_ENV !== 'development',
Expand All @@ -60,7 +69,7 @@ export class DraftMode {
// To delete a cookie, set `expires` to a date in the past:
// https://tools.ietf.org/html/rfc6265#section-4.1.1
// `Max-Age: 0` is not valid, thus ignored, and the cookie is persisted.
this.mutableCookies.set({
this._mutableCookies.set({
name: COOKIE_NAME_PRERENDER_BYPASS,
value: '',
httpOnly: true,
Expand Down
Expand Up @@ -18,7 +18,7 @@ import {
} from '../web/spec-extension/adapters/request-cookies'
import { RequestCookies, ResponseCookies } from '../web/spec-extension/cookies'
import { __ApiPreviewProps } from '../api-utils'
import { DraftMode } from './draft-mode'
import { DraftModeProvider } from './draft-mode-provider'

function getHeaders(headers: Headers | IncomingHttpHeaders): ReadonlyHeaders {
const cleaned = HeadersAdapter.from(headers)
Expand Down Expand Up @@ -79,7 +79,7 @@ export const RequestAsyncStorageWrapper: AsyncStorageWrapper<
headers?: ReadonlyHeaders
cookies?: ReadonlyRequestCookies
mutableCookies?: ResponseCookies
draftMode?: DraftMode
draftMode?: DraftModeProvider
} = {}

const store: RequestStore = {
Expand Down Expand Up @@ -109,7 +109,7 @@ export const RequestAsyncStorageWrapper: AsyncStorageWrapper<
},
get draftMode() {
if (!cache.draftMode) {
cache.draftMode = new DraftMode(
cache.draftMode = new DraftModeProvider(
previewProps,
req,
this.cookies,
Expand Down
16 changes: 0 additions & 16 deletions packages/next/types/index.d.ts
Expand Up @@ -141,22 +141,6 @@ export {

export type PreviewData = string | false | object | undefined

export type DraftMode = {
/**
* Get the current value of Draft Mode.
* True when enabled, false when disabled.
*/
enabled: boolean
/**
* Set the value of Draft Mode to true.
*/
enable: () => void
/**
* Set the value of Draft Mode to false.
*/
disable: () => void
}

/**
* Context object passed into `getStaticProps`.
* @link https://nextjs.org/docs/api-reference/data-fetching/get-static-props#context-parameter
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/app-dir/app-static/app-static.test.ts
Expand Up @@ -1356,7 +1356,7 @@ createNextDescribe(
.elementByCss('#draft-mode')
.text()

expect(content).toBe('{"result":{"enabled":false}}')
expect(content).toBe('{"isEnabled":false}')
})

it('should force SSR correctly for headers usage', async () => {
Expand Down
@@ -1,11 +1,11 @@
import { draftMode } from 'next/headers'

export default function Page() {
const result = draftMode()
const { isEnabled } = draftMode()

return (
<main>
<pre id="draft-mode">{JSON.stringify({ result })}</pre>
<pre id="draft-mode">{JSON.stringify({ isEnabled })}</pre>
</main>
)
}
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/app-dir/draft-mode/app/page.tsx
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import { draftMode } from 'next/headers'

export default function Page() {
const { enabled } = draftMode()
const { isEnabled } = draftMode()

return (
<>
Expand All @@ -11,7 +11,7 @@ export default function Page() {
Random: <em id="rand">{Math.random()}</em>
</p>
<p>
State: <strong id="mode">{enabled ? 'ENABLED' : 'DISABLED'}</strong>
State: <strong id="mode">{isEnabled ? 'ENABLED' : 'DISABLED'}</strong>
</p>
</>
)
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/app-dir/draft-mode/app/state/route.ts
@@ -1,6 +1,6 @@
import { draftMode } from 'next/headers'

export function GET() {
const { enabled } = draftMode()
return new Response(enabled ? 'ENABLED' : 'DISABLED')
const { isEnabled } = draftMode()
return new Response(isEnabled ? 'ENABLED' : 'DISABLED')
}
4 changes: 2 additions & 2 deletions test/e2e/app-dir/draft-mode/app/with-edge/page.tsx
Expand Up @@ -4,7 +4,7 @@ import { draftMode } from 'next/headers'
export const runtime = 'experimental-edge'

export default function Page() {
const { enabled } = draftMode()
const { isEnabled } = draftMode()

return (
<>
Expand All @@ -13,7 +13,7 @@ export default function Page() {
Random: <em id="rand">{Math.random()}</em>
</p>
<p>
State: <strong id="mode">{enabled ? 'ENABLED' : 'DISABLED'}</strong>
State: <strong id="mode">{isEnabled ? 'ENABLED' : 'DISABLED'}</strong>
</p>
</>
)
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/app-dir/draft-mode/app/with-edge/state/route.ts
Expand Up @@ -3,6 +3,6 @@ import { draftMode } from 'next/headers'
export const runtime = 'edge'

export function GET() {
const { enabled } = draftMode()
return new Response(enabled ? 'ENABLED' : 'DISABLED')
const { isEnabled } = draftMode()
return new Response(isEnabled ? 'ENABLED' : 'DISABLED')
}
4 changes: 2 additions & 2 deletions test/e2e/app-dir/hooks/app/hooks/use-draft-mode/page.js
@@ -1,15 +1,15 @@
import { draftMode } from 'next/headers'

export default function Page() {
const { enabled } = draftMode()
const { isEnabled } = draftMode()

return (
<>
<h1>hello from /hooks/use-draft-mode</h1>
<p>
Rand: <em id="rand">{Math.random()}</em>
</p>
<h2 id="draft-mode-val">{enabled ? 'ENABLED' : 'DISABLED'}</h2>
<h2 id="draft-mode-val">{isEnabled ? 'ENABLED' : 'DISABLED'}</h2>
</>
)
}