Skip to content

Commit ef5ee17

Browse files
author
Jason Kuhrt
authored
feat(tsconfig): enforce noEmit: true (#1039)
1 parent 50b5c38 commit ef5ee17

File tree

2 files changed

+83
-41
lines changed

2 files changed

+83
-41
lines changed

src/lib/layout/index.spec.ts

+55-25
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,22 @@ process.stdout.columns = 300
4545
* Helpers
4646
*/
4747

48-
/**
49-
* Create tsconfig content. Defaults to minimum valid tsconfig needed by Nexus. Passed config will override and merge using lodash deep defaults.
50-
*/
51-
function tsconfigSource(input?: TsConfigJson): string {
52-
const defaultTsConfigContent = {
48+
function tsconfig(input?: TsConfigJson): TsConfigJson {
49+
const defaultTsConfigContent: TsConfigJson = {
5350
compilerOptions: {
51+
noEmit: true,
5452
rootDir: '.',
5553
plugins: [{ name: NEXUS_TS_LSP_IMPORT_ID }],
5654
},
5755
include: ['.'],
5856
}
59-
return JSON.stringify(defaultsDeep(input, defaultTsConfigContent))
57+
return defaultsDeep(input, defaultTsConfigContent)
58+
}
59+
/**
60+
* Create tsconfig content. Defaults to minimum valid tsconfig needed by Nexus. Passed config will override and merge using lodash deep defaults.
61+
*/
62+
function tsconfigSource(input?: TsConfigJson): string {
63+
return JSON.stringify(tsconfig(input))
6064
}
6165

6266
const ctx = TC.create(
@@ -172,6 +176,7 @@ describe('tsconfig', () => {
172176
"esnext",
173177
],
174178
"module": "commonjs",
179+
"noEmit": true,
175180
"plugins": Array [
176181
Object {
177182
"name": "nexus/typescript-language-service",
@@ -189,6 +194,29 @@ describe('tsconfig', () => {
189194
})
190195

191196
describe('linting', () => {
197+
it('enforces noEmit is true (explicit false)', async () => {
198+
ctx.setup({
199+
'tsconfig.json': tsconfigSource({ compilerOptions: { noEmit: false } }),
200+
})
201+
await ctx.createLayoutThrow()
202+
expect(mockedStdoutBuffer).toMatchInlineSnapshot(`
203+
"▲ nexus:tsconfig Please set \`compilerOptions.noEmit\` to true. This will ensure you do not accidentally emit using \`$ tsc\`. Use \`$ nexus build\` to build your app and emit JavaScript.
204+
"
205+
`)
206+
})
207+
it('enforces noEmit is true (undefined)', async () => {
208+
const tscfg = tsconfig()
209+
delete tscfg.compilerOptions?.noEmit
210+
211+
ctx.setup({
212+
'tsconfig.json': JSON.stringify(tscfg),
213+
})
214+
await ctx.createLayoutThrow()
215+
expect(mockedStdoutBuffer).toMatchInlineSnapshot(`
216+
"▲ nexus:tsconfig Please set \`compilerOptions.noEmit\` to true. This will ensure you do not accidentally emit using \`$ tsc\`. Use \`$ nexus build\` to build your app and emit JavaScript.
217+
"
218+
`)
219+
})
192220
it('warns if reserved settings are in use', async () => {
193221
ctx.setup({
194222
'tsconfig.json': tsconfigSource({
@@ -200,23 +228,23 @@ describe('tsconfig', () => {
200228
})
201229
await ctx.createLayoutThrow()
202230
expect(mockedStdoutBuffer).toMatchInlineSnapshot(`
203-
"▲ nexus:tsconfig You have set [93m\`compilerOptions.tsBuildInfoFile\`[39m in your tsconfig.json but it will be ignored by Nexus. Nexus manages this value internally.
204-
▲ nexus:tsconfig You have set [93m\`compilerOptions.incremental\`[39m in your tsconfig.json but it will be ignored by Nexus. Nexus manages this value internally.
231+
"▲ nexus:tsconfig You have set [93m\`compilerOptions.tsBuildInfoFile\`[39m but it will be ignored by Nexus. Nexus manages this value internally.
232+
▲ nexus:tsconfig You have set [93m\`compilerOptions.incremental\`[39m but it will be ignored by Nexus. Nexus manages this value internally.
205233
"
206234
`)
207235
})
208236
it('warns if rootDir or include not set and sets them in memory', async () => {
237+
const tscfg = tsconfig()
238+
delete tscfg.compilerOptions?.rootDir
239+
delete tscfg.include
240+
209241
ctx.setup({
210-
'tsconfig.json': '',
242+
'tsconfig.json': JSON.stringify(tscfg),
211243
})
212244
const layout = await ctx.createLayoutThrow()
213245
expect(mockedStdoutBuffer).toMatchInlineSnapshot(`
214-
"▲ nexus:tsconfig You have not setup the Nexus TypeScript Language Service Plugin. Add this to your tsconfig compiler options:
215-
216-
\\"plugins\\": [{ \\"name\\": \\"nexus/typescript-language-service\\" }]
217-
218-
▲ nexus:tsconfig Please set your tsconfig.json \`compilerOptions.rootDir\` to \\".\\"
219-
▲ nexus:tsconfig Please set your tsconfig.json \`include\` to have \\".\\"
246+
"▲ nexus:tsconfig Please set \`compilerOptions.rootDir\` to \\".\\"
247+
▲ nexus:tsconfig Please set \`include\` to have \\".\\"
220248
"
221249
`)
222250
expect(layout.tsConfig.content.raw.compilerOptions.rootDir).toEqual('.')
@@ -231,7 +259,7 @@ describe('tsconfig', () => {
231259

232260
await ctx.createLayoutThrow()
233261
expect(mockedStdoutBuffer).toMatchInlineSnapshot(`
234-
"▲ nexus:tsconfig You have not added the Nexus TypeScript Language Service Plugin to your configured TypeScript plugins. Add this to your tsconfig compiler options:
262+
"▲ nexus:tsconfig You have not added the Nexus TypeScript Language Service Plugin to your configured TypeScript plugins. Add this to your compilerOptions:
235263
236264
\\"plugins\\": [{\\"name\\":\\"foobar\\"},{\\"name\\":\\"nexus/typescript-language-service\\"}]
237265
@@ -244,7 +272,7 @@ describe('tsconfig', () => {
244272
})
245273
await ctx.createLayoutThrow()
246274
expect(mockedStdoutBuffer).toMatchInlineSnapshot(`
247-
"■ nexus:tsconfig You have set [93m\`compilerOptions.types\`[39m in your tsconfig.json but Nexus does not support it. If you do not remove your customization you may/will (e.g. VSCode) see inconsistent results between your IDE and what Nexus tells you at build time. If you would like to see Nexus support this setting please chime in at https://github.com/graphql-nexus/nexus/issues/1036.
275+
"■ nexus:tsconfig You have set [93m\`compilerOptions.types\`[39m but Nexus does not support it. If you do not remove your customization you may/will (e.g. VSCode) see inconsistent results between your IDE and what Nexus tells you at build time. If you would like to see Nexus support this setting please chime in at https://github.com/graphql-nexus/nexus/issues/1036.
248276
"
249277
`)
250278
})
@@ -254,7 +282,7 @@ describe('tsconfig', () => {
254282
})
255283
await ctx.createLayoutThrow()
256284
expect(mockedStdoutBuffer).toMatchInlineSnapshot(`
257-
"■ nexus:tsconfig You have set [93m\`compilerOptions.typeRoots\`[39m in your tsconfig.json but Nexus does not support it. If you do not remove your customization you may/will (e.g. VSCode) see inconsistent results between your IDE and what Nexus tells you at build time. If you would like to see Nexus support this setting please chime in at https://github.com/graphql-nexus/nexus/issues/1036.
285+
"■ nexus:tsconfig You have set [93m\`compilerOptions.typeRoots\`[39m but Nexus does not support it. If you do not remove your customization you may/will (e.g. VSCode) see inconsistent results between your IDE and what Nexus tells you at build time. If you would like to see Nexus support this setting please chime in at https://github.com/graphql-nexus/nexus/issues/1036.
258286
"
259287
`)
260288
})
@@ -264,7 +292,7 @@ describe('tsconfig', () => {
264292
})
265293
await ctx.createLayoutThrow()
266294
expect(mockedStdoutBuffer).toMatchInlineSnapshot(`
267-
"■ nexus:tsconfig You have set [93m\`compilerOptions.typeRoots\`[39m and [93m\`compilerOptions.types\`[39m in your tsconfig.json but Nexus does not support them. If you do not remove your customization you may/will (e.g. VSCode) see inconsistent results between your IDE and what Nexus tells you at build time. If you would like to see Nexus support these settings please chime in at https://github.com/graphql-nexus/nexus/issues/1036.
295+
"■ nexus:tsconfig You have set [93m\`compilerOptions.typeRoots\`[39m and [93m\`compilerOptions.types\`[39m but Nexus does not support them. If you do not remove your customization you may/will (e.g. VSCode) see inconsistent results between your IDE and what Nexus tells you at build time. If you would like to see Nexus support these settings please chime in at https://github.com/graphql-nexus/nexus/issues/1036.
268296
"
269297
`)
270298
})
@@ -287,12 +315,13 @@ describe('tsconfig', () => {
287315
288316
--- process.exit(1) ---
289317
290-
▲ nexus:tsconfig You have not setup the Nexus TypeScript Language Service Plugin. Add this to your tsconfig compiler options:
318+
▲ nexus:tsconfig You have not setup the Nexus TypeScript Language Service Plugin. Add this to your compiler options:
291319
292320
\\"plugins\\": [{ \\"name\\": \\"nexus/typescript-language-service\\" }]
293321
294-
▲ nexus:tsconfig Please set your tsconfig.json \`compilerOptions.rootDir\` to \\".\\"
295-
▲ nexus:tsconfig Please set your tsconfig.json \`include\` to have \\".\\"
322+
▲ nexus:tsconfig Please set \`compilerOptions.rootDir\` to \\".\\"
323+
▲ nexus:tsconfig Please set \`include\` to have \\".\\"
324+
▲ nexus:tsconfig Please set \`compilerOptions.noEmit\` to true. This will ensure you do not accidentally emit using \`$ tsc\`. Use \`$ nexus build\` to build your app and emit JavaScript.
296325
"
297326
`)
298327
})
@@ -303,12 +332,13 @@ describe('tsconfig', () => {
303332
})
304333
await ctx.createLayoutThrow()
305334
expect(stripAnsi(mockedStdoutBuffer)).toMatchInlineSnapshot(`
306-
"▲ nexus:tsconfig You have not setup the Nexus TypeScript Language Service Plugin. Add this to your tsconfig compiler options:
335+
"▲ nexus:tsconfig You have not setup the Nexus TypeScript Language Service Plugin. Add this to your compiler options:
307336
308337
\\"plugins\\": [{ \\"name\\": \\"nexus/typescript-language-service\\" }]
309338
310-
▲ nexus:tsconfig Please set your tsconfig.json \`compilerOptions.rootDir\` to \\".\\"
311-
▲ nexus:tsconfig Please set your tsconfig.json \`include\` to have \\".\\"
339+
▲ nexus:tsconfig Please set \`compilerOptions.rootDir\` to \\".\\"
340+
▲ nexus:tsconfig Please set \`include\` to have \\".\\"
341+
▲ nexus:tsconfig Please set \`compilerOptions.noEmit\` to true. This will ensure you do not accidentally emit using \`$ tsc\`. Use \`$ nexus build\` to build your app and emit JavaScript.
312342
✕ nexus:tsconfig Your tsconfig.json is invalid
313343
314344
error TS5024: Compiler option 'exclude' requires a value of type Array.

src/lib/layout/tsconfig.ts

+28-16
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export async function readOrScaffoldTsconfig(input: {
7171
const pluginsFixed = tscfg.compilerOptions.plugins.concat([{ name: NEXUS_TS_LSP_IMPORT_ID }])
7272
log.warn(
7373
stripIndent`
74-
You have not added the Nexus TypeScript Language Service Plugin to your configured TypeScript plugins. Add this to your tsconfig compiler options:
74+
You have not added the Nexus TypeScript Language Service Plugin to your configured TypeScript plugins. Add this to your compilerOptions:
7575
7676
${chalk.yellowBright(`"plugins": ${JSON.stringify(pluginsFixed)}`)}
7777
` + EOL
@@ -80,7 +80,7 @@ export async function readOrScaffoldTsconfig(input: {
8080
} else {
8181
log.warn(
8282
stripIndent`
83-
You have not setup the Nexus TypeScript Language Service Plugin. Add this to your tsconfig compiler options:
83+
You have not setup the Nexus TypeScript Language Service Plugin. Add this to your compiler options:
8484
8585
"plugins": [{ "name": "${NEXUS_TS_LSP_IMPORT_ID}" }]
8686
` + EOL
@@ -90,17 +90,13 @@ export async function readOrScaffoldTsconfig(input: {
9090
if (tscfg.compilerOptions.tsBuildInfoFile) {
9191
delete tscfg.compilerOptions.tsBuildInfoFile
9292
const setting = renderSetting(`compilerOptions.tsBuildInfoFile`)
93-
log.warn(
94-
`You have set ${setting} in your tsconfig.json but it will be ignored by Nexus. Nexus manages this value internally.`
95-
)
93+
log.warn(`You have set ${setting} but it will be ignored by Nexus. Nexus manages this value internally.`)
9694
}
9795

9896
if (tscfg.compilerOptions.incremental) {
9997
delete tscfg.compilerOptions.incremental
10098
const setting = renderSetting('compilerOptions.incremental')
101-
log.warn(
102-
`You have set ${setting} in your tsconfig.json but it will be ignored by Nexus. Nexus manages this value internally.`
103-
)
99+
log.warn(`You have set ${setting} but it will be ignored by Nexus. Nexus manages this value internally.`)
104100
}
105101

106102
const { typeRoots, types } = tscfg.compilerOptions
@@ -117,39 +113,54 @@ export async function readOrScaffoldTsconfig(input: {
117113
const thisThese = typeRoots && types ? 'these' : 'this'
118114
const s = typeRoots && types ? 's' : ''
119115
log.error(
120-
`You have set ${settingsSet} in your tsconfig.json but Nexus does not support ${itThem}. If you do not remove your customization you may/will (e.g. VSCode) see inconsistent results between your IDE and what Nexus tells you at build time. If you would like to see Nexus support ${thisThese} setting${s} please chime in at https://github.com/graphql-nexus/nexus/issues/1036.`
116+
`You have set ${settingsSet} but Nexus does not support ${itThem}. If you do not remove your customization you may/will (e.g. VSCode) see inconsistent results between your IDE and what Nexus tells you at build time. If you would like to see Nexus support ${thisThese} setting${s} please chime in at https://github.com/graphql-nexus/nexus/issues/1036.`
121117
)
122118
}
123119

120+
/**
121+
* Setup source root (aka. rootDir)
122+
*/
123+
124124
if (!tscfg.compilerOptions!.rootDir) {
125-
// setup source root
126125
tscfg.compilerOptions!.rootDir = '.'
127126
const setting = renderSetting('compilerOptions.rootDir')
128-
log.warn(`Please set your tsconfig.json ${setting} to "${tscfg.compilerOptions!.rootDir}"`)
127+
log.warn(`Please set ${setting} to "${tscfg.compilerOptions!.rootDir}"`)
129128
}
130129

131130
if (!tscfg.include.includes(tscfg.compilerOptions!.rootDir!)) {
132131
tscfg.include.push(tscfg.compilerOptions!.rootDir!)
133132
const setting = renderSetting('include')
134-
log.warn(`Please set your tsconfig.json ${setting} to have "${tscfg.compilerOptions!.rootDir}"`)
133+
log.warn(`Please set ${setting} to have "${tscfg.compilerOptions!.rootDir}"`)
135134
}
136135

137-
if (tscfg.compilerOptions.noEmit === true) {
136+
if (tscfg.compilerOptions.noEmit !== true) {
138137
const setting = renderSetting('compilerOptions.noEmit')
139138
log.warn(
140-
`You have set ${setting} in your tsconfig.json. This will prevent \`$ nexus build\` from emitting code.`
139+
`Please set ${setting} to true. This will ensure you do not accidentally emit using ${chalk.yellowBright(
140+
`\`$ tsc\``
141+
)}. Use ${chalk.yellowBright(`\`$ nexus build\``)} to build your app and emit JavaScript.`
141142
)
142143
}
143144

144-
// setup out root
145+
/**
146+
* Setup noEmit. Internally we always want emit to be on.
147+
*/
148+
149+
tscfg.compilerOptions.noEmit = false
150+
151+
/**
152+
* Setup out root (aka. outDir)
153+
*/
145154

146155
if (input.overrides?.outRoot !== undefined) {
147156
tscfg.compilerOptions.outDir = input.overrides.outRoot
148157
} else if (!tscfg.compilerOptions.outDir) {
149158
tscfg.compilerOptions.outDir = DEFAULT_BUILD_DIR_PATH_RELATIVE_TO_PROJECT_ROOT
150159
}
151160

152-
// check it
161+
/**
162+
* Validate the tsconfig
163+
*/
153164

154165
const tsconfig = ts.parseJsonConfigFileContent(tscfg, ts.sys, projectRoot, undefined, tsconfigPath)
155166

@@ -181,6 +192,7 @@ export function tsconfigTemplate(input: { sourceRootRelative: string; outRootRel
181192
lib: ['esnext'],
182193
strict: true,
183194
rootDir: sourceRelative,
195+
noEmit: true,
184196
plugins: [{ name: 'nexus/typescript-language-service' }],
185197
},
186198
include: [sourceRelative],

0 commit comments

Comments
 (0)