From 9346c7ca7b016890ea72b19ee3328949344daec0 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 28 Jun 2024 13:53:25 +0200 Subject: [PATCH] fix(nuxt): prompt to set compatibility date with latest nitro (#27893) --- packages/nuxt/package.json | 2 + packages/nuxt/src/core/nuxt.ts | 71 +++++++++++++++++++ playground/nuxt.config.ts | 1 + pnpm-lock.yaml | 6 ++ test/fixtures/basic-types/nuxt.config.ts | 1 + test/fixtures/basic/nuxt.config.ts | 1 + test/fixtures/minimal-types/nuxt.config.ts | 1 + test/fixtures/minimal/nuxt.config.ts | 1 + test/fixtures/runtime-compiler/nuxt.config.ts | 1 + test/fixtures/suspense/nuxt.config.ts | 1 + 10 files changed, 86 insertions(+) diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 2a8125f9f4..8941d334fd 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -72,6 +72,8 @@ "acorn": "8.12.0", "c12": "^1.11.1", "chokidar": "^3.6.0", + "compatx": "^0.1.8", + "consola": "^3.2.3", "cookie-es": "^1.1.0", "defu": "^6.1.4", "destr": "^2.0.3", diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index a14b3c9da9..2cf85f2f9c 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -10,12 +10,18 @@ import type { Nuxt, NuxtHooks, NuxtModule, NuxtOptions } from 'nuxt/schema' import type { PackageJson } from 'pkg-types' import { readPackageJSON, resolvePackageJSON } from 'pkg-types' import { hash } from 'ohash' +import consola from 'consola' +import { colorize } from 'consola/utils' +import { updateConfig } from 'c12/update' +import { formatDate } from 'compatx' +import type { DateString } from 'compatx' import escapeRE from 'escape-string-regexp' import { withTrailingSlash, withoutLeadingSlash } from 'ufo' import defu from 'defu' import { gt, satisfies } from 'semver' +import { hasTTY, isCI } from 'std-env' import pagesModule from '../pages/module' import metaModule from '../head/module' import componentsModule from '../components/module' @@ -60,6 +66,9 @@ export function createNuxt (options: NuxtOptions): Nuxt { return nuxt } +// TODO: update to nitro import +const fallbackCompatibilityDate = '2024-04-03' as DateString + const nightlies = { 'nitropack': 'nitropack-nightly', 'h3': 'h3-nightly', @@ -73,6 +82,8 @@ const keyDependencies = [ '@nuxt/schema', ] +let warnedAboutCompatDate = false + async function initNuxt (nuxt: Nuxt) { // Register user hooks for (const config of nuxt.options._layers.map(layer => layer.config).reverse()) { @@ -81,6 +92,59 @@ async function initNuxt (nuxt: Nuxt) { } } + // Prompt to set compatibility date + if (!nuxt.options.compatibilityDate) { + const todaysDate = formatDate(new Date()) + + if (!warnedAboutCompatDate) { + // Print warning + console.info(`Nuxt now supports pinning the behavior of provider and deployment presets with a compatibility date. We recommend you specify a \`compatibilityDate\` in your \`nuxt.config\` file.`) + } + + // Prompt to update in dev mode + if (!warnedAboutCompatDate && nuxt.options.dev && hasTTY && !isCI) { + const result = await consola.prompt(`Do you want to update your ${colorize('cyan', 'nuxt.config')} to set ${colorize('cyan', `compatibilityDate: '${todaysDate}'`)}?`, { + type: 'confirm', + default: true, + }) + if (result === true) { + const res = await updateConfig({ + configFile: 'nuxt.config', + cwd: nuxt.options.rootDir, + async onCreate ({ configFile }) { + const shallCreate = await consola.prompt(`Do you want to create ${colorize('cyan', relative(nuxt.options.rootDir, configFile))}?`, { + type: 'confirm', + default: true, + }) + if (shallCreate !== true) { + return false + } + return _getDefaultNuxtConfig() + }, + onUpdate (config) { + config.compatibilityDate = todaysDate + }, + }).catch((error) => { + consola.error(`Failed to update config: ${error.message}`) + return null + }) + if (res?.configFile) { + nuxt.options.compatibilityDate = todaysDate + consola.success(`Compatibility date set to \`${todaysDate}\` in \`${relative(nuxt.options.rootDir, res.configFile)}\``) + } + } + } + + if (!nuxt.options.compatibilityDate) { + nuxt.options.compatibilityDate = fallbackCompatibilityDate + if (!warnedAboutCompatDate) { + console.log(`Using \`${fallbackCompatibilityDate}\` as fallback compatibility date.`) + } + } + + warnedAboutCompatDate = true + } + // Restart Nuxt when layer directories are added or removed const layersDir = withTrailingSlash(resolve(nuxt.options.rootDir, 'layers')) nuxt.hook('builder:watch', (event, relativePath) => { @@ -762,3 +826,10 @@ function createPortalProperties (sourceValue: any, options: NuxtOptions, paths: }) } } + +const _getDefaultNuxtConfig = () => /* js */ +`// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + devtools: { enabled: true } +}) +` diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index 9e36a9d496..9b576aa6e5 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -1,3 +1,4 @@ export default defineNuxtConfig({ + compatibilityDate: '2024-06-28', devtools: { enabled: true }, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 352e3fe9ad..0c60547d35 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -288,6 +288,12 @@ importers: chokidar: specifier: ^3.6.0 version: 3.6.0 + compatx: + specifier: ^0.1.8 + version: 0.1.8 + consola: + specifier: ^3.2.3 + version: 3.2.3 cookie-es: specifier: ^1.1.0 version: 1.1.0 diff --git a/test/fixtures/basic-types/nuxt.config.ts b/test/fixtures/basic-types/nuxt.config.ts index 93a409cc04..059a0fca29 100644 --- a/test/fixtures/basic-types/nuxt.config.ts +++ b/test/fixtures/basic-types/nuxt.config.ts @@ -1,6 +1,7 @@ import { addTypeTemplate, installModule } from 'nuxt/kit' export default defineNuxtConfig({ + compatibilityDate: '2024-06-28', experimental: { typedPages: true, appManifest: true, diff --git a/test/fixtures/basic/nuxt.config.ts b/test/fixtures/basic/nuxt.config.ts index 320f957777..40e0582950 100644 --- a/test/fixtures/basic/nuxt.config.ts +++ b/test/fixtures/basic/nuxt.config.ts @@ -13,6 +13,7 @@ declare module 'nitropack' { export default defineNuxtConfig({ future: { compatibilityVersion: process.env.TEST_V4 === 'true' ? 4 : 3 }, + compatibilityDate: '2024-06-28', app: { pageTransition: true, layoutTransition: true, diff --git a/test/fixtures/minimal-types/nuxt.config.ts b/test/fixtures/minimal-types/nuxt.config.ts index c1ae1551ca..51e8532177 100644 --- a/test/fixtures/minimal-types/nuxt.config.ts +++ b/test/fixtures/minimal-types/nuxt.config.ts @@ -1,4 +1,5 @@ export default defineNuxtConfig({ future: { compatibilityVersion: process.env.TEST_V4 === 'true' ? 4 : 3 }, + compatibilityDate: '2024-06-28', experimental: { appManifest: true }, }) diff --git a/test/fixtures/minimal/nuxt.config.ts b/test/fixtures/minimal/nuxt.config.ts index 6a0457d1ed..cebff6569b 100644 --- a/test/fixtures/minimal/nuxt.config.ts +++ b/test/fixtures/minimal/nuxt.config.ts @@ -4,6 +4,7 @@ const testWithInlineVue = process.env.EXTERNAL_VUE === 'false' export default defineNuxtConfig({ future: { compatibilityVersion: process.env.TEST_V4 === 'true' ? 4 : 3 }, + compatibilityDate: '2024-06-28', pages: false, experimental: { externalVue: !testWithInlineVue, diff --git a/test/fixtures/runtime-compiler/nuxt.config.ts b/test/fixtures/runtime-compiler/nuxt.config.ts index 9855b8815c..d8c6e5c6ca 100644 --- a/test/fixtures/runtime-compiler/nuxt.config.ts +++ b/test/fixtures/runtime-compiler/nuxt.config.ts @@ -1,6 +1,7 @@ // https://nuxt.com/docs/api/nuxt-config export default defineNuxtConfig({ future: { compatibilityVersion: process.env.TEST_V4 === 'true' ? 4 : 3 }, + compatibilityDate: '2024-06-28', experimental: { externalVue: false, }, diff --git a/test/fixtures/suspense/nuxt.config.ts b/test/fixtures/suspense/nuxt.config.ts index 02632d5ddb..46587f4851 100644 --- a/test/fixtures/suspense/nuxt.config.ts +++ b/test/fixtures/suspense/nuxt.config.ts @@ -4,6 +4,7 @@ const testWithInlineVue = process.env.EXTERNAL_VUE === 'false' export default defineNuxtConfig({ future: { compatibilityVersion: process.env.TEST_V4 === 'true' ? 4 : 3 }, + compatibilityDate: '2024-06-28', experimental: { externalVue: !testWithInlineVue, },