获取导入模块的文件路径

Posted

技术标签:

【中文标题】获取导入模块的文件路径【英文标题】:Get file path of imported module 【发布时间】:2019-01-27 01:08:54 【问题描述】:

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

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

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

控制器文件的完整路径是src/modules/module/controllers/ctrlController.ts。我需要将部分放在花括号中并将它们连接到module.ctrl

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

【问题讨论】:

【参考方案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 的位置的文件路径。这是通过获取堆栈跟踪来实现的,例如:

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 ...

传递给@Controllerimport.meta可以作为meta.__dirname使用。

【讨论】:

感谢您详细而彻底的回答。我会采纳你的建议并提供关于导入模块的模块+ctrl 信息。

以上是关于获取导入模块的文件路径的主要内容,如果未能解决你的问题,请参考以下文章

查找导入模块的绝对路径

跨目录导入模块

模块的搜索路径

在Python中以绝对路径或者相对路径导入文件(或模块)的方法

python pathlib模块(面向对象的文件系统路径)

Python Importlib.import_module动态导入模块