Skip to content

Commit

Permalink
Merge branch 'canary' into polish-error-overlay-diff-style
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Mar 16, 2024
2 parents d0c5c59 + dc2be64 commit 1d6b9b8
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 7 deletions.
79 changes: 79 additions & 0 deletions packages/next/src/lib/find-config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { mkdtemp, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { tmpdir } from 'node:os'
import { findConfig } from './find-config'

describe('findConfig()', () => {
const exampleConfig = {
basePath: '/docs',
}
const configCode = {
mjs: `
const config = ${JSON.stringify(exampleConfig)}
export default config;
`,
cjs: `
const config = ${JSON.stringify(exampleConfig)}
module.exports = config;
`,
}
type TestPatterns = {
pkgConfigTypes: ('module' | 'commonjs')[]
exts: ('js' | 'mjs' | 'cjs')[]
}
const testPatterns: TestPatterns = {
pkgConfigTypes: ['module', 'commonjs'],
exts: ['js', 'mjs', 'cjs'],
}

for (const pkgConfigType of testPatterns.pkgConfigTypes) {
for (const ext of testPatterns.exts) {
it(`should load config properly from *.config.* file (type: "${pkgConfigType}", config: awsome.config.${ext})`, async () => {
// Create fixtures
const tmpDir = await mkdtemp(join(tmpdir(), 'nextjs-test-'))

await writeFile(
join(tmpDir, 'package.json'),
JSON.stringify({
name: 'nextjs-test',
type: pkgConfigType,
})
)

let configCodeType = ext
if (configCodeType === 'js') {
configCodeType = pkgConfigType === 'module' ? 'mjs' : 'cjs'
}
await writeFile(
join(tmpDir, `awsome.config.${ext}`),
configCode[configCodeType]
)

// Test
const actualConfig = await findConfig(tmpDir, 'awsome')
expect(actualConfig).toStrictEqual(exampleConfig)
})
}
}

it(`should load config properly from the config in package.json)`, async () => {
// Create fixtures
const tmpDir = await mkdtemp(join(tmpdir(), 'nextjs-test-'))

await writeFile(
join(tmpDir, 'package.json'),
JSON.stringify({
name: 'nextjs-test',
awsome: {
basePath: '/docs',
},
})
)

// Test
const actualConfig = await findConfig(tmpDir, 'awsome')
expect(actualConfig).toStrictEqual(exampleConfig)
})
})
35 changes: 29 additions & 6 deletions packages/next/src/lib/find-config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import findUp from 'next/dist/compiled/find-up'
import fs from 'fs'
import { readFile } from 'fs/promises'
import JSON5 from 'next/dist/compiled/json5'

type RecursivePartial<T> = {
Expand All @@ -18,6 +18,7 @@ export function findConfigPath(
`${key}.config.json`,
`.${key}rc.js`,
`${key}.config.js`,
`${key}.config.mjs`,
`${key}.config.cjs`,
],
{
Expand All @@ -36,23 +37,45 @@ export async function findConfig<T>(
): Promise<RecursivePartial<T> | null> {
// `package.json` configuration always wins. Let's check that first.
const packageJsonPath = await findUp('package.json', { cwd: directory })
let isESM = false

if (packageJsonPath) {
const packageJson = require(packageJsonPath)
if (packageJson[key] != null && typeof packageJson[key] === 'object') {
return packageJson[key]
try {
const packageJsonStr = await readFile(packageJsonPath, 'utf8')
const packageJson = JSON.parse(packageJsonStr) as {
[key: string]: string
}

if (typeof packageJson !== 'object') {
throw new Error() // Stop processing and continue
}

if (packageJson.type === 'module') {
isESM = true
}

if (packageJson[key] != null && typeof packageJson[key] === 'object') {
return packageJson[key]
}
} catch {
// Ignore error and continue
}
}

const filePath = await findConfigPath(directory, key)

if (filePath) {
if (filePath.endsWith('.js') || filePath.endsWith('.cjs')) {
if (filePath.endsWith('.js')) {
return isESM ? (await import(filePath)).default : require(filePath)
} else if (filePath.endsWith('.mjs')) {
return (await import(filePath)).default
} else if (filePath.endsWith('.cjs')) {
return require(filePath)
}

// We load JSON contents with JSON5 to allow users to comment in their
// configuration file. This pattern was popularized by TypeScript.
const fileContents = fs.readFileSync(filePath, 'utf8')
const fileContents = await readFile(filePath, 'utf8')
return JSON5.parse(fileContents)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ export class AppRouteRouteModule extends RouteModule<
// We should never be in this case but since it can happen based on the way our build/execution is structured
// We defend against it for the time being
throw new Error(
'Invariant: `dynamic-error` during static generation not expected for app routes. This is a bug in Next.js'
'Invariant: `force-dynamic` during static generation not expected for app routes. This is a bug in Next.js'
)
break
case 'force-static':
Expand Down

0 comments on commit 1d6b9b8

Please sign in to comment.