Skip to content

Commit

Permalink
fix: resolve file path in require
Browse files Browse the repository at this point in the history
  • Loading branch information
jbl428 committed May 7, 2023
1 parent b95a530 commit 7e73515
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 14 deletions.
70 changes: 70 additions & 0 deletions lib/plugin/utils/plugin-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* c8 ignore start */
/**
* codes are from '@nestjs/swagger' package
*/

import { isAbsolute, posix } from 'path';

export function replaceImportPath(
typeReference: string,
fileName: string,
): string | undefined {
if (!typeReference.includes('import')) {
return typeReference;
}
let importPath = /\("([^)]).+(")/.exec(typeReference)?.[0];
if (importPath == null) {
return undefined;
}
importPath = convertPath(importPath);
importPath = importPath.slice(2, importPath.length - 1);

try {
if (isAbsolute(importPath)) {
throw new Error();
}
require.resolve(importPath);
return typeReference.replace('import', 'require');
} catch (_error) {
let relativePath = posix.relative(posix.dirname(fileName), importPath);
relativePath = relativePath[0] !== '.' ? './' + relativePath : relativePath;

const nodeModulesText = 'node_modules';
const nodeModulePos = relativePath.indexOf(nodeModulesText);
if (nodeModulePos >= 0) {
relativePath = relativePath.slice(
nodeModulePos + nodeModulesText.length + 1, // slash
);

const typesText = '@types';
const typesPos = relativePath.indexOf(typesText);
if (typesPos >= 0) {
relativePath = relativePath.slice(
typesPos + typesText.length + 1, // slash
);
}

const indexText = '/index';
const indexPos = relativePath.indexOf(indexText);
if (indexPos >= 0) {
relativePath = relativePath.slice(0, indexPos);
}
}

typeReference = typeReference.replace(importPath, relativePath);
return typeReference.replace('import', 'require');
}
}

/**
* Converts Windows specific file paths to posix
* @param windowsPath
*/
function convertPath(windowsPath: string): string {
return windowsPath
.replace(/^\\\\\?\\/, '')
.replace(/\\/g, '/')
.replace(/\/\/+/g, '/');
}

/* c8 ignore end */
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`HttpInterfaceVisitor > should handle array return type 1`] = `
"\\"use strict\\";
Object.defineProperty(exports, \\"__esModule\\", { value: true });
const eager_module_1 = require(\\"@r2don/nest-http-interface\\");
const r2don_http_module_1 = require(\\"@r2don/nest-http-interface\\");
const nest_http_interface_1 = require(\\"@r2don/nest-http-interface\\");
class ResponseClass {
}
Expand All @@ -20,15 +20,15 @@ let UserService = class UserService {
};
__decorate([
(0, nest_http_interface_1.GetExchange)(),
eager_module_1.ResponseBody(ResponseClass)
r2don_http_module_1.ResponseBody(ResponseClass)
], UserService.prototype, \\"getUsers\\", null);
__decorate([
(0, nest_http_interface_1.GetExchange)(),
eager_module_1.ResponseBody(ResponseClass)
r2don_http_module_1.ResponseBody(ResponseClass)
], UserService.prototype, \\"getUserList\\", null);
__decorate([
(0, nest_http_interface_1.GetExchange)(),
eager_module_1.ResponseBody(ResponseClass)
r2don_http_module_1.ResponseBody(ResponseClass)
], UserService.prototype, \\"getUsersReadonly\\", null);
UserService = __decorate([
(0, nest_http_interface_1.HttpInterface)()
Expand Down Expand Up @@ -116,7 +116,7 @@ TextService = __decorate([
exports[`HttpInterfaceVisitor > should override plugin suffix option 1`] = `
"\\"use strict\\";
Object.defineProperty(exports, \\"__esModule\\", { value: true });
const eager_module_1 = require(\\"@r2don/nest-http-interface\\");
const r2don_http_module_1 = require(\\"@r2don/nest-http-interface\\");
const nest_http_interface_1 = require(\\"@r2don/nest-http-interface\\");
class ResponseClass {
}
Expand All @@ -127,7 +127,7 @@ let UserService = class UserService {
};
__decorate([
(0, nest_http_interface_1.GraphQLExchange)(),
eager_module_1.ResponseBody(ResponseClass)
r2don_http_module_1.ResponseBody(ResponseClass)
], UserService.prototype, \\"getUser\\", null);
UserService = __decorate([
(0, nest_http_interface_1.HttpInterface)()
Expand Down
35 changes: 27 additions & 8 deletions lib/plugin/visitors/http-interface.visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
GraphQLExchange,
ResponseBody,
} from '../../decorators';
import { replaceImportPath } from '../utils/plugin-utils';

export class HttpInterfaceVisitor {
HTTP_INTERFACE_DECORATOR = HttpInterface.name;
Expand All @@ -26,7 +27,7 @@ export class HttpInterfaceVisitor {
GraphQLExchange.name,
];

libModuleAlias = 'eager_module_1';
libModuleAlias = 'r2don_http_module_1';
libName = '@r2don/nest-http-interface';
importSet = new Set<string>();
typeFormatFlag =
Expand All @@ -45,7 +46,12 @@ export class HttpInterfaceVisitor {
const typeChecker = program.getTypeChecker();
const visitNode = (node: ts.Node): ts.Node => {
if (this.isHttpInterfaceClass(node)) {
return this.visitMethods(node, factory, typeChecker);
return this.visitMethods(
node,
factory,
typeChecker,
sourceFile.fileName,
);
}

if (ts.isSourceFile(node)) {
Expand Down Expand Up @@ -91,13 +97,19 @@ export class HttpInterfaceVisitor {
node: ts.ClassDeclaration,
factory: ts.NodeFactory,
typeChecker: ts.TypeChecker,
hostFilename: string,
): ts.ClassDeclaration {
const updatedMembers = node.members.map((member) => {
if (!this.isExchangeMethod(member)) {
return member;
}

return this.appendResponseBodyDecorator(member, factory, typeChecker);
return this.appendResponseBodyDecorator(
member,
factory,
typeChecker,
hostFilename,
);
});

return factory.updateClassDeclaration(
Expand All @@ -121,8 +133,13 @@ export class HttpInterfaceVisitor {
node: ts.MethodDeclaration,
factory: ts.NodeFactory,
typeChecker: ts.TypeChecker,
hostFilename: string,
): ts.MethodDeclaration {
const returnType = this.getReturnTypeAsText(node, typeChecker);
const returnType = this.getReturnTypeAsText(
node,
typeChecker,
hostFilename,
);

if (returnType == null) {
return node;
Expand Down Expand Up @@ -157,6 +174,7 @@ export class HttpInterfaceVisitor {
private getReturnTypeAsText(
node: ts.MethodDeclaration,
typeChecker: ts.TypeChecker,
hostFilename: string,
): string | undefined {
if (
node.type == null ||
Expand All @@ -176,13 +194,14 @@ export class HttpInterfaceVisitor {
return undefined;
}

return typeChecker
.typeToString(
return replaceImportPath(
typeChecker.typeToString(
typeChecker.getTypeAtLocation(innerType),
undefined,
this.typeFormatFlag,
)
.replace('import', 'require');
),
hostFilename,
);
}

private getInnerType(node?: ts.TypeNode): ts.TypeNode | undefined {
Expand Down

0 comments on commit 7e73515

Please sign in to comment.