Я пишу декоратор классов для своих контроллеров. Это выглядит как:
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. Как я могу его получить?





Невозможно получить информацию о пути к файлу из параметра ctor. Это просто функция, которая где-то была определена.
В принципе, module и ctrl предпочтительно должны быть предоставлены классу контроллера при регистрации, поскольку путь известен в данный момент, то есть:
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, который является поддерживается TypeScript. Это зависит от конфигурации проекта узла, потому что он работает с целью esnext:
@Controller(import.meta)
export class Foo {...}
import.meta, который был передан @Controller, может потребляться как meta.__dirname.
Спасибо за подробный и обстоятельный ответ. Я воспользуюсь вашим советом и предоставлю информацию о модуле + ctrl при импорте модуля.