Skip to content

Commit 0ee492c

Browse files
LekoArtspieh
andauthored
fix(gatsby): Panic on gatsby-node.jsx/gatsby-node.tsx (#36308)
Co-authored-by: Michal Piechowiak <[email protected]>
1 parent 0d649a8 commit 0ee492c

File tree

10 files changed

+253
-27
lines changed

10 files changed

+253
-27
lines changed

packages/gatsby-cli/src/structured-errors/error-map.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,9 @@ const errors = {
358358
},
359359
"10124": {
360360
text: (context): string =>
361-
`It looks like you were trying to add the config file? Please rename "${context.nearMatch}" to "${context.configName}.js"`,
361+
`It looks like you were trying to add the config file? Please rename "${
362+
context.nearMatch
363+
}" to "${context.configName}.${context.isTSX ? `ts` : `js`}"`,
362364
type: Type.CONFIG,
363365
level: Level.ERROR,
364366
category: ErrorCategory.USER,
@@ -388,6 +390,15 @@ const errors = {
388390
level: Level.ERROR,
389391
category: ErrorCategory.USER,
390392
},
393+
"10128": {
394+
text: (context): string =>
395+
`It looks like you were trying to add the gatsby-node file? Please rename "${
396+
context.nearMatch
397+
}" to "${context.configName}.${context.isTSX ? `ts` : `js`}"`,
398+
type: Type.CONFIG,
399+
level: Level.ERROR,
400+
category: ErrorCategory.USER,
401+
},
391402
"10226": {
392403
text: (context): string =>
393404
[
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// `gatsby-confi.tsx` name is intentional. This is used for testing misspelled `gatsby-config` errors
2+
3+
import type { GatsbyConfig } from "gatsby"
4+
5+
const config: GatsbyConfig = {
6+
siteMetadata: {
7+
title: `ts`,
8+
siteUrl: `https://www.yourdomain.tld`,
9+
},
10+
plugins: [],
11+
}
12+
13+
export default config

packages/gatsby/src/bootstrap/__tests__/get-config-file.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import path from "path"
2-
import { isNearMatch, getConfigFile } from "../get-config-file"
2+
import { getConfigFile } from "../get-config-file"
33
import { testRequireError } from "../../utils/test-require-error"
44
import reporter from "gatsby-cli/lib/reporter"
55

@@ -41,25 +41,12 @@ const reporterPanicMock = reporter.panic as jest.MockedFunction<
4141
typeof reporter.panic
4242
>
4343

44-
describe(`isNearMatch`, () => {
45-
it(`should NOT find a near match if file name is undefined`, () => {
46-
const nearMatchA = isNearMatch(undefined, `gatsby-config`, 1)
47-
expect(nearMatchA).toBeFalse()
48-
})
49-
50-
it(`should calculate near matches based on distance`, () => {
51-
const nearMatchA = isNearMatch(`gatsby-config`, `gatsby-conf`, 2)
52-
const nearMatchB = isNearMatch(`gatsby-config`, `gatsby-configur`, 2)
53-
expect(nearMatchA).toBeTrue()
54-
expect(nearMatchB).toBeTrue()
55-
})
56-
})
57-
5844
// Separate config directories so cases can be tested separately
5945
const dir = path.resolve(__dirname, `../__mocks__/get-config`)
6046
const compiledDir = `${dir}/compiled-dir`
6147
const userRequireDir = `${dir}/user-require-dir`
6248
const tsDir = `${dir}/ts-dir`
49+
const tsxDir = `${dir}/tsx-dir`
6350
const nearMatchDir = `${dir}/near-match-dir`
6451
const srcDir = `${dir}/src-dir`
6552

@@ -144,11 +131,28 @@ describe(`getConfigFile`, () => {
144131
error: expect.toBeObject(),
145132
context: {
146133
configName: `gatsby-config`,
134+
isTSX: false,
147135
nearMatch: `gatsby-confi.js`,
148136
},
149137
})
150138
})
151139

140+
it(`should handle .tsx extension`, async () => {
141+
testRequireErrorMock.mockImplementationOnce(() => true)
142+
143+
await getConfigFile(tsxDir, `gatsby-config`)
144+
145+
expect(reporterPanicMock).toBeCalledWith({
146+
id: `10124`,
147+
error: expect.toBeObject(),
148+
context: {
149+
configName: `gatsby-config`,
150+
isTSX: true,
151+
nearMatch: `gatsby-confi.tsx`,
152+
},
153+
})
154+
})
155+
152156
it(`should handle gatsby config incorrectly located in src dir`, async () => {
153157
testRequireErrorMock.mockImplementationOnce(() => true)
154158

packages/gatsby/src/bootstrap/get-config-file.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,10 @@
1-
import { distance as levenshtein } from "fastest-levenshtein"
21
import fs from "fs-extra"
32
import { testRequireError } from "../utils/test-require-error"
43
import report from "gatsby-cli/lib/reporter"
54
import path from "path"
65
import { sync as existsSync } from "fs-exists-cached"
76
import { COMPILED_CACHE_DIR } from "../utils/parcel/compile-gatsby-files"
8-
9-
export function isNearMatch(
10-
fileName: string | undefined,
11-
configName: string,
12-
distance: number
13-
): boolean {
14-
if (!fileName) return false
15-
return levenshtein(fileName, configName) <= distance
16-
}
7+
import { isNearMatch } from "../utils/is-near-match"
178

189
export async function getConfigFile(
1910
siteDirectory: string,
@@ -108,12 +99,14 @@ export async function getConfigFile(
10899

109100
// gatsby-config is misnamed
110101
if (nearMatch) {
102+
const isTSX = nearMatch.endsWith(`.tsx`)
111103
report.panic({
112104
id: `10124`,
113105
error: innerError,
114106
context: {
115107
configName,
116108
nearMatch,
109+
isTSX,
117110
},
118111
})
119112
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { isNearMatch } from "../is-near-match"
2+
3+
describe(`isNearMatch`, () => {
4+
it(`should NOT find a near match if file name is undefined`, () => {
5+
const nearMatchA = isNearMatch(undefined, `gatsby-config`, 1)
6+
expect(nearMatchA).toBeFalse()
7+
})
8+
9+
it(`should calculate near matches based on distance`, () => {
10+
const nearMatchA = isNearMatch(`gatsby-config`, `gatsby-conf`, 2)
11+
const nearMatchB = isNearMatch(`gatsby-config`, `gatsby-configur`, 2)
12+
expect(nearMatchA).toBeTrue()
13+
expect(nearMatchB).toBeTrue()
14+
})
15+
})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { distance as levenshtein } from "fastest-levenshtein"
2+
3+
export function isNearMatch(
4+
fileName: string | undefined,
5+
configName: string,
6+
distance: number
7+
): boolean {
8+
if (!fileName) return false
9+
return levenshtein(fileName, configName) <= distance
10+
}

packages/gatsby/src/utils/parcel/__tests__/compile-gatsby-files.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ import {
99
import { siteMetadata } from "./fixtures/utils/site-metadata"
1010
import { moreDataConfig } from "./fixtures/utils/more-data-config"
1111
import { readFile, remove, pathExists } from "fs-extra"
12+
import reporter from "gatsby-cli/lib/reporter"
1213

1314
const dir = {
1415
js: `${__dirname}/fixtures/js`,
1516
ts: `${__dirname}/fixtures/ts`,
1617
tsOnlyInLocal: `${__dirname}/fixtures/ts-only-in-local-plugin`,
18+
misnamedJS: `${__dirname}/fixtures/misnamed-js`,
19+
misnamedTS: `${__dirname}/fixtures/misnamed-ts`,
1720
}
1821

1922
jest.setTimeout(15000)
@@ -36,6 +39,16 @@ jest.mock(`@parcel/core`, () => {
3639
}
3740
})
3841

42+
jest.mock(`gatsby-cli/lib/reporter`, () => {
43+
return {
44+
panic: jest.fn(),
45+
}
46+
})
47+
48+
const reporterPanicMock = reporter.panic as jest.MockedFunction<
49+
typeof reporter.panic
50+
>
51+
3952
interface IMockedParcel extends Parcel {
4053
options: unknown
4154
}
@@ -77,18 +90,24 @@ describe(`gatsby file compilation`, () => {
7790
await compileGatsbyFiles(dir.js)
7891
})
7992

93+
beforeEach(() => {
94+
reporterPanicMock.mockClear()
95+
})
96+
8097
it(`should not compile gatsby-config.js`, async () => {
8198
const isCompiled = await pathExists(
8299
`${dir.js}/.cache/compiled/gatsby-config.js`
83100
)
84101
expect(isCompiled).toEqual(false)
102+
expect(reporterPanicMock).not.toHaveBeenCalled()
85103
})
86104

87105
it(`should not compile gatsby-node.js`, async () => {
88106
const isCompiled = await pathExists(
89107
`${dir.js}/.cache/compiled/gatsby-node.js`
90108
)
91109
expect(isCompiled).toEqual(false)
110+
expect(reporterPanicMock).not.toHaveBeenCalled()
92111
})
93112
})
94113

@@ -99,6 +118,10 @@ describe(`gatsby file compilation`, () => {
99118
await compileGatsbyFiles(dir.ts)
100119
})
101120

121+
beforeEach(() => {
122+
reporterPanicMock.mockClear()
123+
})
124+
102125
it(`should compile gatsby-config.ts`, async () => {
103126
const compiledGatsbyConfig = await readFile(
104127
`${dir.ts}/.cache/compiled/gatsby-config.js`,
@@ -108,6 +131,7 @@ describe(`gatsby file compilation`, () => {
108131
expect(compiledGatsbyConfig).toContain(siteMetadata.title)
109132
expect(compiledGatsbyConfig).toContain(siteMetadata.siteUrl)
110133
expect(compiledGatsbyConfig).toContain(moreDataConfig.options.name)
134+
expect(reporterPanicMock).not.toHaveBeenCalled()
111135
})
112136

113137
it(`should compile gatsby-node.ts`, async () => {
@@ -117,6 +141,7 @@ describe(`gatsby file compilation`, () => {
117141
)
118142

119143
expect(compiledGatsbyNode).toContain(`I am working!`)
144+
expect(reporterPanicMock).not.toHaveBeenCalled()
120145
})
121146
})
122147

@@ -147,3 +172,37 @@ describe(`gatsby file compilation`, () => {
147172
})
148173
})
149174
})
175+
176+
describe(`misnamed gatsby-node files`, () => {
177+
beforeEach(() => {
178+
reporterPanicMock.mockClear()
179+
})
180+
it(`should panic on gatsby-node.jsx`, async () => {
181+
process.chdir(dir.misnamedJS)
182+
await remove(`${dir.misnamedJS}/.cache`)
183+
await compileGatsbyFiles(dir.misnamedJS)
184+
185+
expect(reporterPanicMock).toBeCalledWith({
186+
id: `10128`,
187+
context: {
188+
configName: `gatsby-node`,
189+
isTSX: false,
190+
nearMatch: `gatsby-node.jsx`,
191+
},
192+
})
193+
})
194+
it(`should panic on gatsby-node.tsx`, async () => {
195+
process.chdir(dir.misnamedTS)
196+
await remove(`${dir.misnamedTS}/.cache`)
197+
await compileGatsbyFiles(dir.misnamedTS)
198+
199+
expect(reporterPanicMock).toBeCalledWith({
200+
id: `10128`,
201+
context: {
202+
configName: `gatsby-node`,
203+
isTSX: true,
204+
nearMatch: `gatsby-node.tsx`,
205+
},
206+
})
207+
})
208+
})
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { working } from "../utils/say-what"
2+
import { createPages } from "../utils/create-pages"
3+
4+
export const onPreInit = ({ reporter }) => {
5+
reporter.info(working)
6+
}
7+
8+
export const sourceNodes = async ({ actions, createNodeId, createContentDigest }) => {
9+
const { createNode } = actions
10+
11+
let characters = [
12+
{
13+
id: `0`,
14+
name: `A`
15+
},
16+
{
17+
id: `1`,
18+
name: `B`
19+
}
20+
]
21+
22+
characters.forEach((character) => {
23+
const node = {
24+
...character,
25+
id: createNodeId(`characters-${character.id}`),
26+
parent: null,
27+
children: [],
28+
internal: {
29+
type: 'Character',
30+
content: JSON.stringify(character),
31+
contentDigest: createContentDigest(character),
32+
},
33+
}
34+
35+
createNode(node)
36+
})
37+
}
38+
39+
export { createPages }
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { GatsbyNode } from "gatsby"
2+
import { working } from "../utils/say-what-ts"
3+
import { createPages } from "../utils/create-pages-ts"
4+
5+
export const onPreInit: GatsbyNode["onPreInit"] = ({ reporter }) => {
6+
reporter.info(working)
7+
}
8+
9+
type Character = {
10+
id: string
11+
name: string
12+
}
13+
14+
export const sourceNodes: GatsbyNode["sourceNodes"] = async ({ actions, createNodeId, createContentDigest }) => {
15+
const { createNode } = actions
16+
17+
let characters: Array<Character> = [
18+
{
19+
id: `0`,
20+
name: `A`
21+
},
22+
{
23+
id: `1`,
24+
name: `B`
25+
}
26+
]
27+
28+
characters.forEach((character: Character) => {
29+
const node = {
30+
...character,
31+
id: createNodeId(`characters-${character.id}`),
32+
parent: null,
33+
children: [],
34+
internal: {
35+
type: 'Character',
36+
content: JSON.stringify(character),
37+
contentDigest: createContentDigest(character),
38+
},
39+
}
40+
41+
createNode(node)
42+
})
43+
}
44+
45+
export { createPages }

0 commit comments

Comments
 (0)