npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@k3000/fastify

v0.5.2

Published

一个基于 Fastify 的轻量封装,提供类式路由抽象、统一钩子绑定、动态注册以及函数装饰器,帮助你更少样板代码地构建 API。

Downloads

404

Readme

@k3000/fastify

一个基于 Fastify 的轻量封装,提供类式路由抽象、统一钩子绑定、动态注册以及函数装饰器,帮助你更少样板代码地构建 API。

安装

npm i @k3000/fastify

快速开始

可以参照demo.mjs

import { Base, register, listen, fastify } from '@k3000/fastify'

class Test extends Base {
  url = '/test'

  GET(request, reply) {
    console.log('GET', request.query)
    reply.raw.setHeader('content-type', 'application/json; charset=utf-8')
    return { code: 0, msg: 'success' }
  }
}

register(Test)
listen(8080)

路由类与钩子

  • 路由路径:通过 url 指定基础路径,如 '/users'
  • HTTP 方法:以方法名为动词(GET/POST/...)的函数作为对应路由处理器
  • Schema:在类实例字段上设置 body/querystring/params/response 即可生效
  • 钩子:以 $ 前缀的方法映射到 Fastify 钩子,如 $onRequest/$preHandler/$onSend/...

示例:

class Users extends Base {
  url = '/users'

  // 校验 querystring 与响应
  querystring = { type: 'object', properties: { q: { type: 'string' } } }
  response = { 200: { type: 'object', properties: { code: { type: 'number' }, data: { type: 'array' } } } }

  $onRequest(req, reply, done) { /* auth */ done() }
  $preHandler(req, reply, done) { /* rate limit */ done() }

  GET(req, reply) { return { code: 0, data: [] } }
  POST(req, reply) { return { code: 0 } }
}

函数装饰器 f

使用 f(method, [url], fn) 为普通函数标注 HTTP 方法和子路径:

import { f } from '@k3000/fastify'

class Files extends Base {
  url = '/files'

  // 普通函数会自动成为子路由:/files/upload
  upload = f('POST', '/upload', function (req, reply) {
    return { code: 0 }
  })
}

动态注册 register

register(key) 支持多种输入:

  • 类:register(YourClass)
  • 实例:register(new YourClass())
  • 模块:register(import('./routes.mjs'))
  • 路径:register('./apps/example')(非构建态下会递归扫描 .mjs 文件)

注意:路径解析以 process.cwd() 向上三级作为根目录;为避免路径耦合,推荐使用“类或模块”方式注册。

构建态支持

当运行环境设置 global.$BUILT = true 时,路径注册走构建态逻辑,依赖外部提供的 $readdirSync/$import

  • 仅处理当前目录的 .mjs 文件,不递归子目录
  • 需要构建产物提供 index.mjs 作为入口代理

错误处理与校验/序列化

  • 路由级错误处理:实现 $errorHandler(error, request, reply) 覆盖默认处理
  • 链路错误钩子:$onError(request, reply, error, done)
  • 校验编译器:$validatorCompiler({ schema, method, url, httpPart })
  • 序列化编译器:$serializerCompiler({ schema, method, url, httpStatus, contentType })

示例:

class Health extends Base {
  url = '/health'

  $errorHandler(err, request, reply) {
    reply.status(400).send({ code: -1, msg: err.message })
  }

  GET() { return { code: 0, msg: 'ok' } }
}

日志

  • 内置启用 Fastify 的 logger: true(pino),自动记录请求/响应/错误
  • 路由注册时会打印已注册的方法与路径,便于排查

常见问题

  • 路径注册失败:确认当前工作目录(process.cwd())与目录结构匹配;建议改用类或模块注册
  • 响应头设置:示例使用 reply.raw.setHeader,亦可使用 reply.header('content-type', 'application/json; charset=utf-8')
  • 方法命名:普通函数会自动成为子路由;如需设定为主路由或指定方法,请使用装饰器 f

许可证

未指定许可证;如需开源或商用,请补充相应 LICENSE。