获取导入模块的文件路径 [英] Get file path of imported module
问题描述
我正在为我的控制器编写一个类装饰器.它看起来像:
I'm writing a class decorator for my controllers. It looks like:
export function Controller<T extends { new(...args: any[]): {} }> (ctor: T) {
return class extends ctor {
public readonly name = name;
}
}
ctor
是用 @Controller
修饰的类的构造函数.
ctor
is a constructor of a class decorated with @Controller
.
控制器文件的完整路径是 src/modules/{module}/controllers/{ctrl}Controller.ts
.我需要获取花括号中的部分并将它们连接到 {module}.{ctrl}
.
Full path to the controller's file is src/modules/{module}/controllers/{ctrl}Controller.ts
. I need to get parts in curly braces and concatenate them into {module}.{ctrl}
.
为此,我需要导入 ctor
的模块的文件路径.我如何获得它?
To do so I need a filepath of module from which ctor
is imported. How can I obtain it?
推荐答案
无法从 ctor
参数中获取文件路径信息.它只是一个在某处定义的函数.
There is no way to get file path information from ctor
parameter. It's just a function that was defined somewhere.
基本上,module
和 ctrl
最好在注册时提供给控制器类,因为此时路径是已知的,即:
Basically, module
and ctrl
preferably have to be provided to controller class on registration, since the path is known at this moment, i.e.:
for (const filename of filenames) {
const Ctrl = require(filename).default;
const [moduleName, ctrlName] = parseCtrlFilename(filename);
Ctrl._module = moduleName;
Ctrl._name = ctrlName;
}
唯一可行的解决方法是获取调用 Controller
的位置的文件路径.这是通过获取堆栈跟踪来实现的,例如:
The only and hacky workarount is to get file path of a place where Controller
was called. This is achieved by getting stacktrace, e.g:
const caller = require('caller-callsite');
export function Controller<T extends { new(...args: any[]): {} }> (ctor: T) {
const fullPath = caller().getFileName();
...
}
问题在于它是Controller
被调用的路径:
The problem is that it's the path where Controller
is called:
.../foo.ts
@Controller
export class Foo {...}
.../bar.ts
import { Foo } from '.../foo.ts';
// fullPath is still .../foo.ts
export class Bar extends Foo {}
一种不那么笨拙且更可靠的方法是从可用的模块中明确提供文件路径:
A less hacky and more reliable way is to provide file path explicitly from the module where it is available:
@Controller(__filename)
export class Foo {...}
有 import.meta
提案,它是受 TypeScript 支持.这取决于 Node 项目配置,因为它适用于 esnext
目标:
There is import.meta
proposal which is supported by TypeScript. It depends on Node project configuration because it works with esnext
target:
@Controller(import.meta)
export class Foo {...}
传递给 @Controller
的
import.meta
可以作为 meta.__dirname
使用.
import.meta
that was passed to @Controller
can be consumed as meta.__dirname
.
这篇关于获取导入模块的文件路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!