| import type { NextServer, RequestHandler, UpgradeHandler } from '../next' |
| import type { DevBundlerService } from './dev-bundler-service' |
| import type { PropagateToWorkersField } from './router-utils/types' |
|
|
| import next from '../next' |
| import type { Span } from '../../trace' |
| import type { ServerResponse } from 'http' |
| import type { OnCacheEntryHandler } from '../request-meta' |
| import { interopDefault } from '../../lib/interop-default' |
| import { formatDynamicImportPath } from '../../lib/format-dynamic-import-path' |
| import type { ConfiguredExperimentalFeature } from '../config' |
|
|
| export type ServerInitResult = { |
| requestHandler: RequestHandler |
| upgradeHandler: UpgradeHandler |
| server: NextServer |
| |
| closeUpgraded: () => void |
| |
| distDir: string |
| |
| experimentalFeatures: ConfiguredExperimentalFeature[] |
| |
| cacheComponents: boolean |
| } |
|
|
| let initializations: Record<string, Promise<ServerInitResult> | undefined> = {} |
|
|
| let sandboxContext: undefined | typeof import('../web/sandbox/context') |
|
|
| if (process.env.NODE_ENV !== 'production') { |
| sandboxContext = |
| require('../web/sandbox/context') as typeof import('../web/sandbox/context') |
| } |
|
|
| export function clearAllModuleContexts() { |
| return sandboxContext?.clearAllModuleContexts() |
| } |
|
|
| export function clearModuleContext(target: string) { |
| return sandboxContext?.clearModuleContext(target) |
| } |
|
|
| export async function getServerField( |
| dir: string, |
| field: PropagateToWorkersField |
| ) { |
| const initialization = await initializations[dir] |
| if (!initialization) { |
| throw new Error('Invariant cant propagate server field, no app initialized') |
| } |
| const { server } = initialization |
| let wrappedServer = server['server']! |
| return wrappedServer[field as keyof typeof wrappedServer] |
| } |
|
|
| export async function propagateServerField( |
| dir: string, |
| field: PropagateToWorkersField, |
| value: any |
| ) { |
| const initialization = await initializations[dir] |
| if (!initialization) { |
| throw new Error('Invariant cant propagate server field, no app initialized') |
| } |
| const { server } = initialization |
| let wrappedServer = server['server'] |
| const _field = field as keyof NonNullable<typeof wrappedServer> |
|
|
| if (wrappedServer) { |
| if (typeof wrappedServer[_field] === 'function') { |
| |
| await wrappedServer[_field].apply( |
| wrappedServer, |
| Array.isArray(value) ? value : [] |
| ) |
| } else { |
| |
| wrappedServer[_field] = value |
| } |
| } |
| } |
|
|
| async function initializeImpl(opts: { |
| dir: string |
| port: number |
| dev: boolean |
| minimalMode?: boolean |
| hostname?: string |
| keepAliveTimeout?: number |
| serverFields?: any |
| server?: any |
| experimentalTestProxy: boolean |
| experimentalHttpsServer: boolean |
| _ipcPort?: string |
| _ipcKey?: string |
| bundlerService: DevBundlerService | undefined |
| startServerSpan: Span | undefined |
| quiet?: boolean |
| onDevServerCleanup: ((listener: () => Promise<void>) => void) | undefined |
| distDir: string |
| experimentalFeatures: ConfiguredExperimentalFeature[] |
| cacheComponents: boolean |
| }): Promise<ServerInitResult> { |
| const type = process.env.__NEXT_PRIVATE_RENDER_WORKER |
| if (type) { |
| process.title = 'next-render-worker-' + type |
| } |
|
|
| let requestHandler: RequestHandler |
| let upgradeHandler: UpgradeHandler |
|
|
| const server = next({ |
| ...opts, |
| hostname: opts.hostname || 'localhost', |
| customServer: false, |
| httpServer: opts.server, |
| port: opts.port, |
| }) as NextServer |
|
|
| |
| |
| if ( |
| process.env.__NEXT_TEST_MODE && |
| process.env.NEXT_PRIVATE_DEBUG_CACHE_ENTRY_HANDLERS |
| ) { |
| |
| |
| const createOnCacheEntryHandlers = interopDefault( |
| await import( |
| formatDynamicImportPath( |
| opts.dir, |
| process.env.NEXT_PRIVATE_DEBUG_CACHE_ENTRY_HANDLERS |
| ) |
| ) |
| ) as (res: ServerResponse) => { |
| |
| onCacheEntry: OnCacheEntryHandler |
| onCacheEntryV2: OnCacheEntryHandler |
| } |
|
|
| |
| |
| requestHandler = async (req, res, parsedUrl) => { |
| |
| |
| const { |
| |
| onCacheEntry, |
| onCacheEntryV2, |
| } = createOnCacheEntryHandlers(res) |
|
|
| |
| |
| const handler = server.getRequestHandlerWithMetadata({ |
| |
| onCacheEntry, |
| onCacheEntryV2, |
| }) |
|
|
| return handler(req, res, parsedUrl) |
| } |
|
|
| upgradeHandler = server.getUpgradeHandler() |
| } else { |
| requestHandler = server.getRequestHandler() |
| upgradeHandler = server.getUpgradeHandler() |
| } |
|
|
| await server.prepare(opts.serverFields) |
|
|
| return { |
| requestHandler, |
| upgradeHandler, |
| server, |
| closeUpgraded() { |
| opts.bundlerService?.close() |
| }, |
| distDir: opts.distDir, |
| experimentalFeatures: opts.experimentalFeatures, |
| cacheComponents: opts.cacheComponents, |
| } |
| } |
|
|
| export async function initialize( |
| opts: Parameters<typeof initializeImpl>[0] |
| ): Promise<ServerInitResult> { |
| |
| |
| if (initializations[opts.dir]) { |
| return initializations[opts.dir]! |
| } |
| return (initializations[opts.dir] = initializeImpl(opts)) |
| } |
|
|