From e4f99f063676359de6bb5638384656ae68a0335d Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Wed, 1 Mar 2023 12:42:10 -0800 Subject: [PATCH] Ensure default config passes schema checks --- packages/next/src/server/config-schema.ts | 35 +++++++++++++------ packages/next/src/server/config-shared.ts | 4 +-- packages/next/taskfile.js | 4 +-- .../config-schema-check/next.config.js | 3 ++ .../config-schema-check/pages/index.js | 3 ++ .../config-schema-check/test/index.test.js | 20 +++++++++++ 6 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 test/integration/config-schema-check/next.config.js create mode 100644 test/integration/config-schema-check/pages/index.js create mode 100644 test/integration/config-schema-check/test/index.test.js diff --git a/packages/next/src/server/config-schema.ts b/packages/next/src/server/config-schema.ts index 4584a68331474..904ec224a1316 100644 --- a/packages/next/src/server/config-schema.ts +++ b/packages/next/src/server/config-schema.ts @@ -11,7 +11,7 @@ const configSchema = { additionalProperties: false, properties: { canonicalBase: { - minLength: 1, + nullable: true, type: 'string', }, }, @@ -21,7 +21,7 @@ const configSchema = { type: 'string', }, assetPrefix: { - minLength: 1, + nullable: true, type: 'string', }, basePath: { @@ -170,6 +170,9 @@ const configSchema = { compress: { type: 'boolean', }, + configOrigin: { + type: 'string', + }, crossOrigin: { oneOf: [ false, @@ -342,7 +345,7 @@ const configSchema = { type: 'boolean', }, outputFileTracingRoot: { - minLength: 1, + nullable: true, type: 'string', }, outputFileTracingExcludes: { @@ -521,6 +524,7 @@ const configSchema = { }, i18n: { additionalProperties: false, + nullable: true, properties: { defaultLocale: { minLength: 1, @@ -568,17 +572,17 @@ const configSchema = { }, images: { additionalProperties: false, + nullable: true, properties: { remotePatterns: { + nullable: true, items: { additionalProperties: false, properties: { hostname: { - minLength: 1, type: 'string', }, pathname: { - minLength: 1, type: 'string', }, port: { @@ -601,15 +605,17 @@ const configSchema = { type: 'boolean', }, contentSecurityPolicy: { - minLength: 1, type: 'string', + nullable: true, }, contentDispositionType: { enum: ['inline', 'attachment'] as any, // automatic typing does not like enum type: 'string', + nullable: true, }, dangerouslyAllowSVG: { type: 'boolean', + nullable: true, }, deviceSizes: { items: { @@ -617,12 +623,13 @@ const configSchema = { minimum: 1, maximum: 10000, }, - minItems: 1, maxItems: 25, type: 'array', + nullable: true, }, disableStaticImages: { type: 'boolean', + nullable: true, }, domains: { items: { @@ -630,6 +637,7 @@ const configSchema = { }, maxItems: 50, type: 'array', + nullable: true, }, formats: { items: { @@ -638,6 +646,7 @@ const configSchema = { } as any, maxItems: 4, type: 'array', + nullable: true, }, imageSizes: { items: { @@ -648,23 +657,26 @@ const configSchema = { minItems: 0, maxItems: 25, type: 'array', + nullable: true, }, loader: { // automatic typing does not like enum enum: VALID_LOADERS as any, type: 'string', + nullable: true, }, loaderFile: { - minLength: 1, type: 'string', + nullable: true, }, minimumCacheTTL: { type: 'integer', minimum: 0, + nullable: true, }, path: { - minLength: 1, type: 'string', + nullable: true, }, }, type: 'object', @@ -737,6 +749,9 @@ const configSchema = { swcMinify: { type: 'boolean', }, + target: { + type: 'string', + }, trailingSlash: { type: 'boolean', }, @@ -768,7 +783,7 @@ const configSchema = { 'must be a function that returns a webpack configuration object', } as any, }, -} as JSONSchemaType +} as JSONSchemaType // module.exports is used to get around an export bug with TypeScript // and the Ajv automatic typing diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index d4f88d468040e..aa005fa0d8726 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -16,6 +16,7 @@ export type NextConfigComplete = Required & { configOrigin?: string configFile?: string configFileName: string + target?: string } export interface I18NConfig { @@ -569,7 +570,6 @@ export interface NextConfig extends Record { export const defaultConfig: NextConfig = { env: {}, webpack: null, - webpackDevMiddleware: null, eslint: { ignoreDuringBuilds: false, }, @@ -610,7 +610,7 @@ export const defaultConfig: NextConfig = { excludeDefaultMomentLocales: true, serverRuntimeConfig: {}, publicRuntimeConfig: {}, - reactStrictMode: null, + reactStrictMode: false, httpAgentOptions: { keepAlive: true, }, diff --git a/packages/next/taskfile.js b/packages/next/taskfile.js index eddc3370e3f36..9fb3cc54ba5d8 100644 --- a/packages/next/taskfile.js +++ b/packages/next/taskfile.js @@ -304,11 +304,11 @@ export async function compile_config_schema(task, opts) { keyword: 'isFunction', schemaType: 'boolean', compile() { - return (data) => data instanceof Function + return (data) => data == null || data instanceof Function }, code(ctx) { const { data } = ctx - ctx.fail(Ajv._`!(${data} instanceof Function)`) + ctx.fail(Ajv._`!(${data} == null || ${data} instanceof Function)`) }, metaSchema: { anyOf: [{ type: 'boolean' }], diff --git a/test/integration/config-schema-check/next.config.js b/test/integration/config-schema-check/next.config.js new file mode 100644 index 0000000000000..0b6018655b065 --- /dev/null +++ b/test/integration/config-schema-check/next.config.js @@ -0,0 +1,3 @@ +module.exports = (phase, { defaultConfig }) => { + return defaultConfig +} diff --git a/test/integration/config-schema-check/pages/index.js b/test/integration/config-schema-check/pages/index.js new file mode 100644 index 0000000000000..ff7159d9149fe --- /dev/null +++ b/test/integration/config-schema-check/pages/index.js @@ -0,0 +1,3 @@ +export default function Page() { + return

hello world

+} diff --git a/test/integration/config-schema-check/test/index.test.js b/test/integration/config-schema-check/test/index.test.js new file mode 100644 index 0000000000000..7eec26e428de9 --- /dev/null +++ b/test/integration/config-schema-check/test/index.test.js @@ -0,0 +1,20 @@ +/* eslint-env jest */ + +import { join } from 'path' +import { nextBuild } from 'next-test-utils' +import stripAnsi from 'strip-ansi' + +const appDir = join(__dirname, '../') + +describe('next.config.js schema validating', () => { + it('should validate against defaultConfig', async () => { + const result = await nextBuild(appDir, undefined, { + stderr: true, + stdout: true, + }) + const output = stripAnsi(result.stderr + result.stdout) + + expect(output).not.toContain('Invalid next.config.js options detected') + expect(result.code).toBe(0) + }) +})