获取导入模块的文件路径

时间:2018-08-20 21:18:13

标签: node.js typescript annotations node-modules

我正在为我的控制器编写一个类装饰器。看起来像:

export function Controller<T extends { new(...args: any[]): {} }> (ctor: T) {
    return class extends ctor {
        public readonly name = name;
    }
}

ctor是用@Controller装饰的类的构造函数。

控制器文件的完整路径为src/modules/{module}/controllers/{ctrl}Controller.ts。我需要将花括号的部分连接起来,并将它们连接成{module}.{ctrl}

为此,我需要从中导入ctor的模块的文件路径。我如何获得它?

1 个答案:

答案 0 :(得分:1)

无法从ctor参数获取文件路径信息。这只是在某处定义的函数。

基本上,modulectrl最好在注册时提供给控制器类,因为此时路径是已知的,即:

  for (const filename of filenames) {
    const Ctrl = require(filename).default;
    const [moduleName, ctrlName] = parseCtrlFilename(filename);
    Ctrl._module = moduleName;
    Ctrl._name = ctrlName;
  }

唯一且棘手的工作方式是获取调用Controller的位置的文件路径。这是通过获取stacktrace来实现的,例如:

const caller = require('caller-callsite');

export function Controller<T extends { new(...args: any[]): {} }> (ctor: T) {
    const fullPath = caller().getFileName();
    ...
}

问题在于,这是Controller的调用路径:

... / foo.ts

@Controller
export class Foo {...}

... / bar.ts

import { Foo } from '.../foo.ts';

// fullPath is still .../foo.ts
export class Bar extends Foo {}

一种不太可靠和更可靠的方法是从可用的模块中显式提供文件路径:

@Controller(__filename)
export class Foo {...}

import.meta proposal,即supported by TypeScript。它取决于Node项目的配置,因为它可以与esnext目标一起使用:

@Controller(import.meta)
export class Foo {...}
传递给import.meta

@Controller可以作为meta.__dirname使用。