Repository: vercel/next.js
File: packages/next/src/server/lib/start-server.ts (TypeScript)

Code before:

      // Log basic startup info immediately (before loading config)
      logStartInfo({
        networkUrl,
        appUrl,
        envInfo,
        logBundler: isDev,
      })

      // Calculate and log "Ready in X" before loading config
      // so it reflects actual framework startup time.
      // NEXT_PRIVATE_START_TIME is set by bin/next.ts or cli/next-start.ts.
      const startTime = parseInt(process.env.NEXT_PRIVATE_START_TIME || '0', 10)
      const endTime = Date.now()
      const startServerProcessDurationMs = startTime ? endTime - startTime : 0

      const formattedStartDuration = durationToString(
        startServerProcessDurationMs / 1000
      )

      Log.event(`Ready in ${formattedStartDuration}`)

      try {
        let cleanupStarted = false
        let closeUpgraded: (() => void) | null = null
        const cleanup = (signal: NodeJS.Signals) => {
          if (cleanupStarted) {
            // We can get duplicate signals, e.g. when `ctrl+c` is used in an
            // interactive shell (i.e. bash, zsh), the shell will recursively
            // send SIGINT to children. The parent `next-dev` process will also
            // send us SIGINT.
            return
          }
          cleanupStarted = true
          ;(async () => {
            debug('start-server process cleanup')

            // first, stop accepting new connections and finish pending requests,
            // because they might affect `nextServer.close()` (e.g. by scheduling an `after`)
            await new Promise<void>((res) => {
              server.close((err) => {
                if (err) console.error(err)
                res()
              })
              if (isDev) {
                server.closeAllConnections()
                closeUpgraded?.()
              }
            })

            // now that no new requests can come in, clean up the rest

Review comment (suggestion):
You're typing it like you accept any signal but then you only handle one and let everything else fall into a single exit code bucket. Instead, we should just accept the two handled signals and then use a switch + TS's exhaustiveness check 
```suggestion
        const cleanup = (signal: "SIGINT" | "SIGTERM") => {
```

```js
switch (signal) {
  case "SIGINT":
    process.exit(128 + 2);
    break;
  case "SIGTERM":
    process.exit(128 + 15)
    break;
	default:
		(signal as never);
    // fallback in case of unsound types.
    process.exit(128);
}
```

That's the pattern we use throughout the codebase.

Code after:

      // Log basic startup info immediately (before loading config)
      logStartInfo({
        networkUrl,
        appUrl,
        envInfo,
        logBundler: isDev,
      })

      // Calculate and log "Ready in X" before loading config
      // so it reflects actual framework startup time.
      // NEXT_PRIVATE_START_TIME is set by bin/next.ts or cli/next-start.ts.
      const startTime = parseInt(process.env.NEXT_PRIVATE_START_TIME || '0', 10)
      const endTime = Date.now()
      const startServerProcessDurationMs = startTime ? endTime - startTime : 0

      const formattedStartDuration = durationToString(
        startServerProcessDurationMs / 1000
      )

      Log.event(`Ready in ${formattedStartDuration}`)

      try {
        let cleanupStarted = false
        let closeUpgraded: (() => void) | null = null
        const cleanup = (signal: 'SIGINT' | 'SIGTERM') => {
          if (cleanupStarted) {
            // We can get duplicate signals, e.g. when `ctrl+c` is used in an
            // interactive shell (i.e. bash, zsh), the shell will recursively
            // send SIGINT to children. The parent `next-dev` process will also
            // send us SIGINT.
            return
          }
          cleanupStarted = true
          ;(async () => {
            debug('start-server process cleanup')

            // first, stop accepting new connections and finish pending requests,
            // because they might affect `nextServer.close()` (e.g. by scheduling an `after`)
            await new Promise<void>((res) => {
              server.close((err) => {
                if (err) console.error(err)
                res()
              })
              if (isDev) {
                server.closeAllConnections()
                closeUpgraded?.()
              }
            })

            // now that no new requests can come in, clean up the rest