Типизаторы декораторов неожиданного поведения - PullRequest
0 голосов
/ 12 октября 2019

У меня определен декоратор для создания маршрутов с экспрессом

export const Get = (path: string) => {
  return (
    target: any,
    property: string,
    descriptor: PropertyDescriptor
  ): PropertyDescriptor => {
    console.log(`Creating router for get request, path ${path}`);
    if (!Reflect.hasMetadata("routes", target.constructor)) {
      Reflect.defineMetadata("routes", [], target.constructor);
    }
    const routes = Reflect.getMetadata("routes", target.constructor);
    routes.push({
      method: "get",
      path,
      handler: target[property]
    });
    Reflect.defineMetadata("routes", routes, target.constructor);
    return descriptor;
  };
};

И декоратор для защиты маршрутов

export const protect = function(type: authenticatorType = "JWT") {
  const authFactory = AuthFactory.getInstance();
  const authenticator: IAuthenticator = authFactory.getAuthenticator(type);
  return (
    target: any,
    property: string,
    descriptor: PropertyDescriptor
  ): PropertyDescriptor => {
    const method = descriptor.value;
    descriptor.value = function(...args: any[]) {
      const req: Request = args[0];
      const token = <string>req.headers.token;
      if (!token) {
        throw new HTTP401Error();
      }
      const payload = authenticator.verify(token);
      const result = method.apply(this, [...args, payload]);
      return result;
    };
    //Object.defineProperty(target, property, descriptor);
    return descriptor;
  };
};

Когда я пытаюсь использовать protect с Get, это не работает. Чтобы это работало, я должен раскомментировать //Object.defineProperty(target, property, descriptor);. Без этого блок кода оформления вообще не выполняется. Однако, если я использую его без Get, он прекрасно работает даже без использования Object.defineProperty().

@Controller("/users/:uuid/connections")
export default class ConnectionController {
  constructor() {
    console.debug("Creating network controller");
  }
  @Get("/")
  @protect()
  getConnections(req: Request, res: Response, meta?: any) {
    const s: Social = new Social();
    const result = s.getConnection();
    return res.json(result);
  }
  @Post("/")
  createConnection(req: Request, res: Response) {
    return res.json({ method: "POST" });
  }
  @Put("/:connectionId/status")
  updateConnectionStatus(req: Request, res: Response) {
    const connectionId = req.params.connectionId;
    return res.json({ connectionId });
  }
}

Я не могу понять, почему поведение отличается.

...