写一个简易的 Nest.js (1)

105 阅读1分钟

先看最终的代码

启动服务

image.png

模块化

image.png

控制层

image.png

截图摘自于 github.com/chelizichen… 中的 test 目录下


联系方式:1347290221@qq.com

微信:13476973442 备注(掘金)


作者并没有看过 Nest 的源码,一开始也没有想做一个 Nest-Like 的意思,只是觉得好玩就模仿了几个常用的Api。而后在暑期实习的时候在公司拓展了一下整个代码,在8月底决定做一个富含装饰器并且使用了DI 设计思想的库,询问英语专业的同学如何起名,最后起名为 Ado-Node。


第一章 参数装饰器

@Body @Query 和实现方式

image.png

Nest 底层是由 Express 构建的,我们可以将 @Body 和 @Query 看作为

@Body = request.body

@Query = request.query

@Params = request.params

我们需要使用到 Reflect-Metadata 这个库 和 TypeScript 自带的装饰器函数

实现代码

我定义了一个元数据

function Query(): ParameterDecorator {
  return function (
    target: Object,
    propertyKey: string | symbol,
    parameterIndex: number
  ) {
    ref.def(
      propertyKey as string,
      parameterIndex,
      target.constructor.prototype,
      ":query"
    );
  };
}

并且修改了函数的参数

function useArgs(
  propertyKey: string,
  target: Object,
  req: Request,
  res: Response
): any[] {
  const hasQuery = ref.get(
    propertyKey as string,
    target.constructor.prototype,
    ":query"
  );
  const hasBody = ref.get(...);
  const hasHeaders = ref.get(...);
  const hasRequest = ref.get(...);
  const hasResponse = ref.get(...);
  let arg = [];
  if (
    typeof hasQuery === "number" ||
    typeof hasBody === "number" ||
    typeof hasHeaders === "number" ||
    typeof hasRequest == "number" ||
    typeof hasResponse == "number"
  ) {
    arg[hasQuery] = req.query;
    arg[hasBody] = req.body;
    arg[hasHeaders] = req.headers;
    arg[hasRequest] = req;
    arg[hasResponse] = res;
    return arg;
  }
  return [req, res];
}

// 而后在 MethodDecorator 里面使用了如下的代码
// 修改了运行时的参数
// 根据条件语句 args 只可能为 原生的 req,res 或者带有装饰器的 @Query @Body
Method (url) : MethodDecorator =>

const fn = descriptor.value;
ref.def(propertyKey as string, URL, target.constructor.prototype, ":url");

descriptor.value = async function (req: Request, res: Response) {
    const args = useArgs(propertyKey as string, target, req, res);
    target.constructor.prototype[propertyKey](...args);
}