diff --git a/.changeset/modern-now-configuration.md b/.changeset/modern-now-configuration.md new file mode 100644 index 00000000..b6a32378 --- /dev/null +++ b/.changeset/modern-now-configuration.md @@ -0,0 +1,5 @@ +--- +'serve': patch +--- + +Ignore now.json without legacy static-serving configuration instead of crashing at startup. diff --git a/readme.md b/readme.md index 241a3fbe..7165f1cc 100644 --- a/readme.md +++ b/readme.md @@ -58,6 +58,9 @@ Now you understand how the package works! :tada: ## Configuration +A `now.json` file without a legacy `now.static` section is ignored when +looking for static-serving configuration. + To customize `serve`'s behavior, create a `serve.json` file in the public folder and insert any of [these properties](https://github.com/vercel/serve-handler#options). ## API diff --git a/source/utilities/config.ts b/source/utilities/config.ts index db2e3c85..aa328487 100644 --- a/source/utilities/config.ts +++ b/source/utilities/config.ts @@ -61,7 +61,7 @@ export const loadConfiguration = async ( static?: Partial; } interface NowConfigurationFile { - now: { static?: Partial }; + now?: { static?: Partial }; } type ParseableConfiguration = | ServeConfigurationFile @@ -87,7 +87,7 @@ export const loadConfiguration = async ( // Check if any of these files have a serve specific section. if (file === 'now.json') { parsedJson = parsedJson as NowConfigurationFile; - parsedJson = parsedJson.now.static; + parsedJson = parsedJson.now?.static; } else if (file === 'package.json') { parsedJson = parsedJson as ManifestConfigurationFile; parsedJson = parsedJson.static; diff --git a/tests/config-legacy.test.ts b/tests/config-legacy.test.ts new file mode 100644 index 00000000..98b2873d --- /dev/null +++ b/tests/config-legacy.test.ts @@ -0,0 +1,51 @@ +import { mkdtemp, writeFile, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { expect, test } from 'vitest'; +import { loadConfiguration } from '../source/utilities/config.js'; + +test('a modern now.json without a legacy static section does not break static serving', async () => { + const directory = await mkdtemp(join(tmpdir(), 'serve-now-')); + try { + await writeFile( + join(directory, 'now.json'), + JSON.stringify({ version: 2 }), + ); + const config = await loadConfiguration(directory, directory, {}); + expect(config.public).toBe(''); + expect(config.etag).toBe(true); + } finally { + await rm(directory, { recursive: true, force: true }); + } +}); +test('a legacy now.static section is still loaded', async () => { + const directory = await mkdtemp(join(tmpdir(), 'serve-now-')); + try { + await writeFile( + join(directory, 'now.json'), + JSON.stringify({ now: { static: { cleanUrls: false } } }), + ); + const config = await loadConfiguration(directory, directory, {}); + expect(config.cleanUrls).toBe(false); + } finally { + await rm(directory, { recursive: true, force: true }); + } +}); + +test('a modern now.json falls through to package.json static settings', async () => { + const directory = await mkdtemp(join(tmpdir(), 'serve-now-')); + try { + await writeFile( + join(directory, 'now.json'), + JSON.stringify({ version: 2 }), + ); + await writeFile( + join(directory, 'package.json'), + JSON.stringify({ static: { cleanUrls: false } }), + ); + const config = await loadConfiguration(directory, directory, {}); + expect(config.cleanUrls).toBe(false); + } finally { + await rm(directory, { recursive: true, force: true }); + } +});