Skip to content

Commit

Permalink
Merge pull request #2441 from nestjs/chore/drop-support-for-old-types…
Browse files Browse the repository at this point in the history
…cript

chore: drop support for typescript < 4.8
  • Loading branch information
kamilmysliwiec authored Jun 12, 2023
2 parents 9682d79 + 0693fba commit 23bbc5d
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 181 deletions.
25 changes: 10 additions & 15 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,23 @@ version: 2
aliases:
- &restore-cache
restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
key: dependency-cache-{{ checksum "package.json" }}
- &install-deps
run:
name: Install dependencies
command: npm ci
name: Install dependencies
command: npm ci
- &build-packages
run:
name: Build
command: npm run build
name: Build
command: npm run build
- &run-unit-tests
run:
name: Test
command: npm run test -- --runInBand
- &run-unit-tests
run:
name: Test (TypeScript < v4.8)
command: npm i --no-save -D typescript@4.7.2 && npm run test -- --runInBand
name: Test
command: npm run test -- --runInBand
- &run-e2e-tests
run:
name: E2E test
command: npm run test:e2e
name: E2E test
command: npm run test:e2e

jobs:
build:
Expand All @@ -46,7 +42,7 @@ jobs:
- ./node_modules
- run:
name: Build
command: npm run build
command: npm run build

unit_tests:
working_directory: ~/nest
Expand Down Expand Up @@ -81,4 +77,3 @@ workflows:
- e2e_tests:
requires:
- build

2 changes: 1 addition & 1 deletion lib/plugin/utils/plugin-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {

export function getDecoratorOrUndefinedByNames(
names: string[],
decorators: ts.NodeArray<ts.Decorator>,
decorators: readonly ts.Decorator[],
factory: ts.NodeFactory
): ts.Decorator | undefined {
return (decorators || factory.createNodeArray()).find((item) => {
Expand Down
81 changes: 23 additions & 58 deletions lib/plugin/visitors/abstract.visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,71 +9,36 @@ export class AbstractFileVisitor {
factory: ts.NodeFactory | undefined,
program: ts.Program
): ts.SourceFile {
if (major <= 4 && minor < 2) {
throw new Error('Nest CLI plugin does not support TypeScript < v4.2');
if (major <= 4 && minor < 8) {
throw new Error('Nest CLI plugin does not support TypeScript < v4.8');
}
const importEqualsDeclaration: ts.ImportDeclaration =
major >= 4 && minor >= 2
? minor >= 8
? (factory.createImportEqualsDeclaration as any)(
undefined,
false,
factory.createIdentifier(OPENAPI_NAMESPACE),
factory.createExternalModuleReference(
factory.createStringLiteral(OPENAPI_PACKAGE_NAME)
)
)
: (factory.createImportEqualsDeclaration as any)(
undefined,
undefined,
false,
OPENAPI_NAMESPACE,
factory.createExternalModuleReference(
factory.createStringLiteral(OPENAPI_PACKAGE_NAME)
)
)
: (factory.createImportEqualsDeclaration as any)(
undefined,
undefined,
OPENAPI_NAMESPACE,
factory.createExternalModuleReference(
factory.createStringLiteral(OPENAPI_PACKAGE_NAME)
)
);
const importEqualsDeclaration: ts.ImportEqualsDeclaration =
factory.createImportEqualsDeclaration(
undefined,
false,
factory.createIdentifier(OPENAPI_NAMESPACE),
factory.createExternalModuleReference(
factory.createStringLiteral(OPENAPI_PACKAGE_NAME)
)
);

const compilerOptions = program.getCompilerOptions();
// Support TS v4.8+
if (
compilerOptions.module >= ts.ModuleKind.ES2015 &&
compilerOptions.module <= ts.ModuleKind.ESNext
) {
const importAsDeclaration =
(minor >= 8 && major >= 4) || major >= 5
? (factory.createImportDeclaration as any)(
undefined,
factory.createImportClause(
false,
undefined,
factory.createNamespaceImport(
factory.createIdentifier(OPENAPI_NAMESPACE)
)
),
factory.createStringLiteral(OPENAPI_PACKAGE_NAME),
undefined
)
: (factory.createImportDeclaration as any)(
undefined,
undefined,
factory.createImportClause(
false,
undefined,
factory.createNamespaceImport(
factory.createIdentifier(OPENAPI_NAMESPACE)
)
),
factory.createStringLiteral(OPENAPI_PACKAGE_NAME),
undefined
);
const importAsDeclaration = (factory.createImportDeclaration as any)(
undefined,
factory.createImportClause(
false,
undefined,
factory.createNamespaceImport(
factory.createIdentifier(OPENAPI_NAMESPACE)
)
),
factory.createStringLiteral(OPENAPI_PACKAGE_NAME),
undefined
);
return factory.updateSourceFile(sourceFile, [
importAsDeclaration,
...sourceFile.statements
Expand Down
62 changes: 17 additions & 45 deletions lib/plugin/visitors/controller-class.visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ import {
} from '../utils/plugin-utils';
import { AbstractFileVisitor } from './abstract.visitor';

const [tsVersionMajor, tsVersionMinor] = ts.versionMajorMinor
?.split('.')
.map((x) => +x);
const isInUpdatedAstContext = tsVersionMinor >= 8 || tsVersionMajor > 4;

export class ControllerClassVisitor extends AbstractFileVisitor {
visit(
sourceFile: ts.SourceFile,
Expand Down Expand Up @@ -61,10 +56,8 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
hostFilename: string,
sourceFile: ts.SourceFile
): ts.MethodDeclaration {
// Support both >= v4.8 and v4.7 and lower
const decorators = (ts as any).canHaveDecorators
? (ts as any).getDecorators(compilerNode)
: (compilerNode as any).decorators;
const decorators =
ts.canHaveDecorators(compilerNode) && ts.getDecorators(compilerNode);
if (!decorators) {
return compilerNode;
}
Expand All @@ -86,12 +79,7 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
)
: decorators;

// Support both >= v4.8 and v4.7 and lower
const modifiers =
(isInUpdatedAstContext
? (ts as any).getModifiers(compilerNode)
: compilerNode.modifiers) ?? [];

const modifiers = ts.getModifiers(compilerNode) ?? [];
const updatedDecorators = [
...apiOperationDecoratorsArray,
...existingDecorators,
Expand All @@ -112,36 +100,23 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
)
];

return isInUpdatedAstContext
? (factory as any).updateMethodDeclaration(
compilerNode,
[...updatedDecorators, ...modifiers],
compilerNode.asteriskToken,
compilerNode.name,
compilerNode.questionToken,
compilerNode.typeParameters,
compilerNode.parameters,
compilerNode.type,
compilerNode.body
)
: (factory as any).updateMethodDeclaration(
compilerNode,
updatedDecorators,
modifiers,
compilerNode.asteriskToken,
compilerNode.name,
compilerNode.questionToken,
compilerNode.typeParameters,
compilerNode.parameters,
compilerNode.type,
compilerNode.body
);
return factory.updateMethodDeclaration(
compilerNode,
[...updatedDecorators, ...modifiers],
compilerNode.asteriskToken,
compilerNode.name,
compilerNode.questionToken,
compilerNode.typeParameters,
compilerNode.parameters,
compilerNode.type,
compilerNode.body
);
}

createApiOperationDecorator(
factory: ts.NodeFactory,
node: ts.MethodDeclaration,
nodeArray: ts.NodeArray<ts.Decorator>,
decorators: readonly ts.Decorator[],
options: PluginOptions,
sourceFile: ts.SourceFile,
typeChecker: ts.TypeChecker
Expand All @@ -152,7 +127,7 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
const keyToGenerate = options.controllerKeyOfComment;
const apiOperationDecorator = getDecoratorOrUndefinedByNames(
[ApiOperation.name],
nodeArray,
decorators,
factory
);
const apiOperationExpr: ts.ObjectLiteralExpression | undefined =
Expand Down Expand Up @@ -279,10 +254,7 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
}

getStatusCodeIdentifier(factory: ts.NodeFactory, node: ts.MethodDeclaration) {
// Support both >= v4.8 and v4.7 and lower
const decorators = (ts as any).canHaveDecorators
? (ts as any).getDecorators(node)
: (node as any).decorators;
const decorators = ts.canHaveDecorators(node) && ts.getDecorators(node);
const httpCodeDecorator = getDecoratorOrUndefinedByNames(
['HttpCode'],
decorators,
Expand Down
86 changes: 24 additions & 62 deletions lib/plugin/visitors/model-class.visitor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { compact, flatten, head } from 'lodash';
import * as ts from 'typescript';
import { factory, PropertyAssignment } from 'typescript';
import { PropertyAssignment, factory } from 'typescript';
import { ApiHideProperty } from '../../decorators';
import { PluginOptions } from '../merge-options';
import { METADATA_FACTORY_NAME } from '../plugin-constants';
Expand All @@ -27,11 +27,6 @@ import { AbstractFileVisitor } from './abstract.visitor';

type ClassMetadata = Record<string, ts.ObjectLiteralExpression>;

const [tsVersionMajor, tsVersionMinor] = ts.versionMajorMinor
?.split('.')
.map((x) => +x);
const isInUpdatedAstContext = tsVersionMinor >= 8 || tsVersionMajor > 4;

export class ModelClassVisitor extends AbstractFileVisitor {
visit(
sourceFile: ts.SourceFile,
Expand All @@ -46,10 +41,8 @@ export class ModelClassVisitor extends AbstractFileVisitor {
(metadata: ClassMetadata) =>
(node: ts.Node): ts.Node => {
if (ts.isPropertyDeclaration(node)) {
// Support both >= v4.8 and v4.7 and lower
const decorators = (ts as any).canHaveDecorators
? (ts as any).getDecorators(node)
: (node as any).decorators;
const decorators =
ts.canHaveDecorators(node) && ts.getDecorators(node);

const hidePropertyDecorator = getDecoratorOrUndefinedByNames(
[ApiHideProperty.name],
Expand Down Expand Up @@ -116,53 +109,25 @@ export class ModelClassVisitor extends AbstractFileVisitor {
)
)
);
const method = isInUpdatedAstContext
? (factory as any).createMethodDeclaration(
[factory.createModifier(ts.SyntaxKind.StaticKeyword)],
undefined,
factory.createIdentifier(METADATA_FACTORY_NAME),
undefined,
undefined,
[],
undefined,
factory.createBlock(
[factory.createReturnStatement(returnValue)],
true
)
)
: (factory as any).createMethodDeclaration(
undefined,
[factory.createModifier(ts.SyntaxKind.StaticKeyword)],
undefined,
factory.createIdentifier(METADATA_FACTORY_NAME),
undefined,
undefined,
[],
undefined,
factory.createBlock(
[factory.createReturnStatement(returnValue)],
true
)
);
const method = factory.createMethodDeclaration(
[factory.createModifier(ts.SyntaxKind.StaticKeyword)],
undefined,
factory.createIdentifier(METADATA_FACTORY_NAME),
undefined,
undefined,
[],
undefined,
factory.createBlock([factory.createReturnStatement(returnValue)], true)
);

return isInUpdatedAstContext
? (factory as any).updateClassDeclaration(
node,
node.modifiers,
node.name,
node.typeParameters,
node.heritageClauses,
[...node.members, method]
)
: (factory as any).updateClassDeclaration(
node,
(node as any).decorators,
node.modifiers as any,
node.name,
node.typeParameters,
node.heritageClauses,
[...node.members, method]
);
return factory.updateClassDeclaration(
node,
node.modifiers,
node.name,
node.typeParameters,
node.heritageClauses,
[...node.members, method]
);
}

inspectPropertyDeclaration(
Expand Down Expand Up @@ -433,10 +398,7 @@ export class ModelClassVisitor extends AbstractFileVisitor {
node: ts.PropertyDeclaration | ts.PropertySignature
): ts.PropertyAssignment[] {
const assignments = [];
// Support both >= v4.8 and v4.7 and lower
const decorators = (ts as any).canHaveDecorators
? (ts as any).getDecorators(node)
: (node as any).decorators;
const decorators = ts.canHaveDecorators(node) && ts.getDecorators(node);

this.addPropertyByValidationDecorator(
factory,
Expand Down Expand Up @@ -549,7 +511,7 @@ export class ModelClassVisitor extends AbstractFileVisitor {
factory: ts.NodeFactory,
decoratorName: string,
propertyKey: string,
decorators: ts.NodeArray<ts.Decorator>,
decorators: readonly ts.Decorator[],
assignments: ts.PropertyAssignment[]
) {
this.addPropertiesByValidationDecorator(
Expand All @@ -572,7 +534,7 @@ export class ModelClassVisitor extends AbstractFileVisitor {
addPropertiesByValidationDecorator(
factory: ts.NodeFactory,
decoratorName: string,
decorators: ts.NodeArray<ts.Decorator>,
decorators: readonly ts.Decorator[],
assignments: ts.PropertyAssignment[],
addPropertyAssignments: (decoratorRef: ts.Decorator) => PropertyAssignment[]
) {
Expand Down

0 comments on commit 23bbc5d

Please sign in to comment.