feat(nest): Add strict option (#16371)
This commit is contained in:
parent
a4ef9596d9
commit
ce4a76a975
@ -68,6 +68,11 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"strict": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Adds strictNullChecks, noImplicitAny, strictBindCallApply, forceConsistentCasingInFileNames and noFallthroughCasesInSwitch to tsconfig.",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|||||||
@ -110,7 +110,7 @@
|
|||||||
"strict": {
|
"strict": {
|
||||||
"description": "Whether to enable tsconfig strict mode or not.",
|
"description": "Whether to enable tsconfig strict mode or not.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": true
|
||||||
},
|
},
|
||||||
"standaloneConfig": {
|
"standaloneConfig": {
|
||||||
"description": "Split the project configuration into <projectRoot>/project.json rather than including it inside workspace.json",
|
"description": "Split the project configuration into <projectRoot>/project.json rather than including it inside workspace.json",
|
||||||
|
|||||||
@ -511,8 +511,8 @@ describe('nest libraries', function () {
|
|||||||
`libs/${nestlib}/src/lib/foo.model.ts`,
|
`libs/${nestlib}/src/lib/foo.model.ts`,
|
||||||
`
|
`
|
||||||
export class FooModel {
|
export class FooModel {
|
||||||
foo: string;
|
foo?: string;
|
||||||
bar: number;
|
bar?: number;
|
||||||
}`
|
}`
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -527,7 +527,7 @@ exports.FooModel = void 0;
|
|||||||
const openapi = require("@nestjs/swagger");
|
const openapi = require("@nestjs/swagger");
|
||||||
class FooModel {
|
class FooModel {
|
||||||
static _OPENAPI_METADATA_FACTORY() {
|
static _OPENAPI_METADATA_FACTORY() {
|
||||||
return { foo: { required: true, type: () => String }, bar: { required: true, type: () => Number } };
|
return { foo: { required: false, type: () => String }, bar: { required: false, type: () => Number } };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.FooModel = FooModel;
|
exports.FooModel = FooModel;
|
||||||
|
|||||||
@ -59,6 +59,22 @@ describe('application generator', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should add strict checks with --strict', async () => {
|
||||||
|
await applicationGenerator(tree, { name: appName, strict: true });
|
||||||
|
const tsConfig = devkit.readJson(
|
||||||
|
tree,
|
||||||
|
`apps/${appDirectory}/tsconfig.app.json`
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tsConfig.compilerOptions.strictNullChecks).toBeTruthy();
|
||||||
|
expect(tsConfig.compilerOptions.noImplicitAny).toBeTruthy();
|
||||||
|
expect(tsConfig.compilerOptions.strictBindCallApply).toBeTruthy();
|
||||||
|
expect(
|
||||||
|
tsConfig.compilerOptions.forceConsistentCasingInFileNames
|
||||||
|
).toBeTruthy();
|
||||||
|
expect(tsConfig.compilerOptions.noFallthroughCasesInSwitch).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
describe('--skipFormat', () => {
|
describe('--skipFormat', () => {
|
||||||
it('should format files', async () => {
|
it('should format files', async () => {
|
||||||
jest.spyOn(devkit, 'formatFiles');
|
jest.spyOn(devkit, 'formatFiles');
|
||||||
|
|||||||
@ -25,6 +25,7 @@ export function normalizeOptions(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
|
strict: options.strict ?? false,
|
||||||
appProjectRoot,
|
appProjectRoot,
|
||||||
linter: options.linter ?? Linter.EsLint,
|
linter: options.linter ?? Linter.EsLint,
|
||||||
unitTestRunner: options.unitTestRunner ?? 'jest',
|
unitTestRunner: options.unitTestRunner ?? 'jest',
|
||||||
|
|||||||
@ -9,6 +9,16 @@ export function updateTsConfig(tree: Tree, options: NormalizedOptions): void {
|
|||||||
(json) => {
|
(json) => {
|
||||||
json.compilerOptions.emitDecoratorMetadata = true;
|
json.compilerOptions.emitDecoratorMetadata = true;
|
||||||
json.compilerOptions.target = 'es2015';
|
json.compilerOptions.target = 'es2015';
|
||||||
|
if (options.strict) {
|
||||||
|
json.compilerOptions = {
|
||||||
|
...json.compilerOptions,
|
||||||
|
strictNullChecks: true,
|
||||||
|
noImplicitAny: true,
|
||||||
|
strictBindCallApply: true,
|
||||||
|
forceConsistentCasingInFileNames: true,
|
||||||
|
noFallthroughCasesInSwitch: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -13,6 +13,7 @@ export interface ApplicationGeneratorOptions {
|
|||||||
e2eTestRunner?: 'jest' | 'none';
|
e2eTestRunner?: 'jest' | 'none';
|
||||||
setParserOptionsProject?: boolean;
|
setParserOptionsProject?: boolean;
|
||||||
rootProject?: boolean;
|
rootProject?: boolean;
|
||||||
|
strict?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NormalizedOptions extends ApplicationGeneratorOptions {
|
interface NormalizedOptions extends ApplicationGeneratorOptions {
|
||||||
|
|||||||
@ -68,6 +68,11 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
"description": "Whether or not to configure the ESLint `parserOptions.project` option. We do not do this by default for lint performance reasons.",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"strict": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Adds strictNullChecks, noImplicitAny, strictBindCallApply, forceConsistentCasingInFileNames and noFallthroughCasesInSwitch to tsconfig.",
|
||||||
|
"default": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|||||||
@ -32,7 +32,13 @@ export default {
|
|||||||
exports[`lib --unit-test-runner none should not generate test configuration 1`] = `
|
exports[`lib --unit-test-runner none should not generate test configuration 1`] = `
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"strict": true,
|
||||||
},
|
},
|
||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../tsconfig.base.json",
|
||||||
"files": [],
|
"files": [],
|
||||||
@ -62,7 +68,13 @@ exports[`lib --unit-test-runner none should not generate test configuration 2`]
|
|||||||
exports[`lib nested should create a local tsconfig.json 1`] = `
|
exports[`lib nested should create a local tsconfig.json 1`] = `
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"strict": true,
|
||||||
},
|
},
|
||||||
"extends": "../../../tsconfig.base.json",
|
"extends": "../../../tsconfig.base.json",
|
||||||
"files": [],
|
"files": [],
|
||||||
@ -94,7 +106,13 @@ export class MyLibModule {}
|
|||||||
exports[`lib not nested should create a local tsconfig.json 1`] = `
|
exports[`lib not nested should create a local tsconfig.json 1`] = `
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitOverride": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noPropertyAccessFromIndexSignature": true,
|
||||||
|
"strict": true,
|
||||||
},
|
},
|
||||||
"extends": "../../tsconfig.base.json",
|
"extends": "../../tsconfig.base.json",
|
||||||
"files": [],
|
"files": [],
|
||||||
|
|||||||
@ -28,6 +28,7 @@ export function normalizeOptions(
|
|||||||
|
|
||||||
const normalized: NormalizedOptions = {
|
const normalized: NormalizedOptions = {
|
||||||
...options,
|
...options,
|
||||||
|
strict: options.strict ?? true,
|
||||||
controller: options.controller ?? false,
|
controller: options.controller ?? false,
|
||||||
fileName,
|
fileName,
|
||||||
global: options.global ?? false,
|
global: options.global ?? false,
|
||||||
|
|||||||
@ -10,9 +10,10 @@ export function updateTsConfig(tree: Tree, options: NormalizedOptions): void {
|
|||||||
if (options.strict) {
|
if (options.strict) {
|
||||||
json.compilerOptions = {
|
json.compilerOptions = {
|
||||||
...json.compilerOptions,
|
...json.compilerOptions,
|
||||||
|
strictNullChecks: true,
|
||||||
|
noImplicitAny: true,
|
||||||
|
strictBindCallApply: true,
|
||||||
forceConsistentCasingInFileNames: true,
|
forceConsistentCasingInFileNames: true,
|
||||||
strict: true,
|
|
||||||
noImplicitReturns: true,
|
|
||||||
noFallthroughCasesInSwitch: true,
|
noFallthroughCasesInSwitch: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -247,35 +247,14 @@ describe('lib', () => {
|
|||||||
it('should update the projects tsconfig with strict true', async () => {
|
it('should update the projects tsconfig with strict true', async () => {
|
||||||
await libraryGenerator(tree, { name: libName, strict: true });
|
await libraryGenerator(tree, { name: libName, strict: true });
|
||||||
|
|
||||||
const tsconfigJson = readJson(
|
const tsConfig = readJson(tree, `/libs/${libFileName}/tsconfig.lib.json`);
|
||||||
tree,
|
expect(tsConfig.compilerOptions.strictNullChecks).toBeTruthy();
|
||||||
`/libs/${libFileName}/tsconfig.lib.json`
|
expect(tsConfig.compilerOptions.noImplicitAny).toBeTruthy();
|
||||||
);
|
expect(tsConfig.compilerOptions.strictBindCallApply).toBeTruthy();
|
||||||
expect(tsconfigJson.compilerOptions.strict).toBe(true);
|
|
||||||
expect(
|
expect(
|
||||||
tsconfigJson.compilerOptions.forceConsistentCasingInFileNames
|
tsConfig.compilerOptions.forceConsistentCasingInFileNames
|
||||||
).toBe(true);
|
).toBeTruthy();
|
||||||
expect(tsconfigJson.compilerOptions.noImplicitReturns).toBe(true);
|
expect(tsConfig.compilerOptions.noFallthroughCasesInSwitch).toBeTruthy();
|
||||||
expect(tsconfigJson.compilerOptions.noFallthroughCasesInSwitch).toBe(
|
|
||||||
true
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should default to strict false', async () => {
|
|
||||||
await libraryGenerator(tree, { name: libName });
|
|
||||||
|
|
||||||
const tsconfigJson = readJson(
|
|
||||||
tree,
|
|
||||||
`/libs/${libFileName}/tsconfig.lib.json`
|
|
||||||
);
|
|
||||||
expect(tsconfigJson.compilerOptions.strict).not.toBeDefined();
|
|
||||||
expect(
|
|
||||||
tsconfigJson.compilerOptions.forceConsistentCasingInFileNames
|
|
||||||
).not.toBeDefined();
|
|
||||||
expect(tsconfigJson.compilerOptions.noImplicitReturns).not.toBeDefined();
|
|
||||||
expect(
|
|
||||||
tsconfigJson.compilerOptions.noFallthroughCasesInSwitch
|
|
||||||
).not.toBeDefined();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -110,7 +110,7 @@
|
|||||||
"strict": {
|
"strict": {
|
||||||
"description": "Whether to enable tsconfig strict mode or not.",
|
"description": "Whether to enable tsconfig strict mode or not.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": true
|
||||||
},
|
},
|
||||||
"standaloneConfig": {
|
"standaloneConfig": {
|
||||||
"description": "Split the project configuration into <projectRoot>/project.json rather than including it inside workspace.json",
|
"description": "Split the project configuration into <projectRoot>/project.json rather than including it inside workspace.json",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user