Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: drop support for typescript < 4.8 #2441

Merged
merged 2 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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