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 🙏

© 2026 – Pkg Stats / Ryan Hefner

dracokite

v1.0.3

Published

dracokite - A multi-process Node.js backend framework with built-in BFF capabilities

Downloads

643

Readme

dracokite 框架实现规格书


1. 框架定位

dracokite 是一个自带 BFF 能力的多进程 Node.js 后端框架

  • 包名:dracokite
  • 语言:TypeScript(严格模式),同时兼容 JavaScript
  • 模块:ESM
  • 依赖:仅 Node.js 内置模块,零第三方依赖
  • 核心理念:文件即路由,BFF 即方法,多进程即默认

2. 架构全景

2.1 进程编制(强制多进程,最低 7 进程)

text

dracokite ×1                         ← 唯一大脑,掌控全局
├── RequestingProcess ×1       ← 管流量,执行 dracokite 调度
│   ├── SyncWorker ×N          ← 同步通道,处理快速请求
│   └── AsyncWorker ×N         ← 异步通道,处理长任务/WebSocket
└── InformationProcess ×1      ← 管后勤,执行 dracokite 调度
    ├── CronProcess ×1         ← 定时任务
    └── LoggerProcess ×1       ← 日志收集
  • dracokite:最高领导,监控、决策、调度
  • RequestingProcess:HTTP 入口,管理同步/异步双队列
  • InformationProcess:管理定时任务和日志
  • SyncWorker:同步 Worker,快速返回
  • AsyncWorker:异步 Worker,处理长连接、文件、流式响应
  • CronProcess:执行定时任务
  • LoggerProcess:收集和写入日志

2.2 每个进程最少 3 个线程

| 进程 | 线程数 | 分工 | | :----------------- | :----- | :---------------------------------------------- | | dracokite | 3 | 主线程(决策)+ 状态收集线程 + 指令下发线程 | | RequestingProcess | 3 | 主线程(事件循环)+ 路由匹配线程 + 队列管理线程 | | SyncWorker | 3 | 主线程(处理请求)+ 辅助线程 + 预留线程 | | AsyncWorker | 3 | 主线程(事件循环)+ 线程池(至少1线程) | | InformationProcess | 3 | 主线程(调度)+ 定时任务触发线程 + 状态收集线程 | | CronProcess | 3 | 主线程(调度器)+ 2 个任务执行线程 | | LoggerProcess | 3 | 收线程 + 写线程 + 缓冲管理线程 |

最低 7 进程 × 3 线程 = 21 个执行单元。

2.3 通信规则

  • 树状单向通信,严禁网状
  • dracokite ↔ RequestingProcess:独立 IPC 通道,最高优先级
  • dracokite ↔ InformationProcess:独立 IPC 通道
  • RequestingProcess → Worker:Worker 主动来队列领取任务
  • 所有进程 → LoggerProcess:单向扔日志,不等回执
  • 心跳:所有下级定期向上级 dracokite 上报

3. 路由系统

3.1 文件系统路由

  • pages/ 目录结构即 URL 路径
  • [param].js 表示动态参数
  • 文件名即路径,函数名即 HTTP 方法

示例:

| 文件 | URL | 方法 | | :--------------------- | :----------- | :-------------- | | pages/users/[id].js | /users/:id | get() → GET | | pages/users/index.js | /users | post() → POST |

3.2 类继承 Router

每个路由文件必须 export default class extends Router

Router 基类提供:

  • this.requestparamsquerybodyheadersfilesmethodpathnameip
  • this.responsestatusbodyheaderscookiessession
  • this.state:钩子间共享数据
  • this.requestId:全局唯一 ID

静态属性:

  • static dataType:定义入参
  • static timeout:路由级超时时间(默认 30000ms)
  • static channel'sync''async',不写默认 sync

3.3 dataType 定义规则

仅定义 paramsquerybody,不包含 headers。

javascript

static dataType = {
  get: {
    params: { id: 'string' },
    query: { page: 'number' }
  },
  post: {
    body: { name: 'string', age: 'number' }
  }
}
  • 定义了就是必填,客户端缺字段返回 400
  • 多传字段不报错
  • 支持的类型:'string''number''int''boolean''email''url''uuid''phone''date''datetime''file''image''base64''buffer''stream''json''xml''csv'
  • 嵌套对象:{ city: 'string', zip: 'number' }
  • 数组:['string'][{ name: 'string' }]
  • 文件类型:'file''file[]''image''image[]'

3.4 路由匹配优先级

固定路由优先于动态路由。例如 pages/users/profile.js 优先于 pages/users/[id].js。启动时检测冲突路径并警告。


4. 请求与响应

4.1 自动解析

  • JSON body、form-urlencoded、multipart/form-data 自动解析
  • 文件放入 this.request.files
  • 默认请求体上限 10MB(非文件上传),通过 bodyMaxSize 配置,单位 MB
  • 文件上传大小限制通过 upload.maxSize 配置

4.2 返回值风格

业务方法直接 return 数据。

  • 返回对象/数组 → 自动 JSON
  • 返回字符串 → text/plain
  • 返回数字 → HTTP 状态码
  • 返回 null → 204
  • 不返回 → 默认 200

特殊返回字段(仅在 return 对象中):

  • __code__:业务码,直接返回,不走错误码文件
  • __header__:设置响应头
  • __cookie__:设置 Cookie
  • __session__:写入 Session

4.3 resError 方法

  • this.resError(code, options?)
  • 走错误码文件 errors.json 查找 message
  • options.isPenetrate:若 truecode 同时作为 HTTP 状态码;否则 HTTP 200
  • 支持多语言,根据请求头 Accept-Language 自动选择

4.4 错误码文件

json

{
  "zh": { "10001": "用户名已存在" },
  "en": { "10001": "Username already exists" }
}

App 构造函数中通过 errors 指定路径。

4.5 自定义错误格式

javascript

const app = new App({
  errorFormat: (code, message, requestId) => ({
    code,
    message,
    requestId,
    timestamp: Date.now()
  })
})

5. 钩子系统

5.1 全局钩子(在 app.js 注册)

| 钩子 | 触发时机 | | :----------------------- | :------------------------------ | | beforeRequest(router) | 请求到达,尚未匹配路由 | | afterRequest(router) | 业务方法执行后,响应前 | | beforeResponse(router) | afterRequest 之后,序列化之前 | | afterResponse(router) | 响应已发送后 |

5.2 路由级钩子(在 Router 子类中重写)

| 钩子 | 触发时机 | | :----------------- | :--------------------------------- | | beforeExecute() | 业务方法执行前 | | afterExecute() | 业务方法执行后 | | beforeResponse() | 全局 afterRequest 之后,序列化前 | | afterResponse() | 全局 afterResponse 之后 | | onError(error) | 任何钩子或业务方法抛出错误 | | onTimeout() | 请求超时 |

执行顺序:

text

全局 beforeRequest → 路由 beforeExecute → 业务方法 → 路由 afterExecute →
路由 beforeResponse → 全局 afterRequest → 全局 beforeResponse →
路由 afterResponse → 全局 afterResponse

6. BFF 能力

6.1 this.bff 方法

  • 基本用法:this.bff({ user: fetch(...), orders: fetch(...) })
  • 数组用法:this.bff([fetch(...), fetch(...)])
  • 超时:全局 timeout,单接口 timeoutEach
  • 降级:fallback 对象
  • 串行依赖:this.bff.step(name, promise)
  • 条件请求:动态构建并发对象
  • 多端裁剪:this.is('web'|'mobile'|'desktop')

6.2 其他 BFF 能力

  • 重试:this.bff.retry(promise, { times, delay })
  • 缓存:this.bff.cache(key, promise, { ttl })
  • 合并重复请求:this.bff.dedupe(key, promise, { window })
  • 日志追踪:trace: true

7. 双队列机制

RequestingProcess 管理两个队列:

  • 同步通道队列:处理快速请求,由 SyncWorker 领取
  • 异步通道队列:处理长连接、文件上传、流式响应,由 AsyncWorker 领取

分流逻辑:

  • WebSocket 升级请求 → 异步
  • 文件上传(multipart)→ 异步
  • 路由标记 static channel = 'async' → 异步
  • 其他 → 同步

AsyncWorker 空闲时可帮同步通道,反之不行。

SyncWorker 强制超时 30 秒,超时自动中断并触发 onTimeout


8. 定时任务

tasks/ 目录下文件,继承 Task,用 static schedule 定义执行时间。

javascript

export default class extends Task {
  static schedule = '0 3 * * *'  // cron 表达式

  async execute() {
    // 业务逻辑
  }
}

支持简写:@daily@hourly@every 5m@every 30s

CronProcess 独立进程执行,每个任务在独立线程跑,互不影响。


9. 日志系统

框架自动采集,用户只需注册回调:

javascript

app.accessLog((info) => {
  // info: { method, path, status, duration, requestId, ip, ... }
})

LoggerProcess 收线程 + 写线程 + 缓冲线程,写盘慢不阻塞收。


10. 其他内置功能

| 功能 | 说明 | | :--------- | :---------------------------------------------- | | 静态文件 | public/ 目录自动映射,缓存策略 max-age=3600 | | 压缩 | 默认 brotli level 6,阈值 1KB | | 上传 | this.file.save(),分片 appendChunk/merge | | 限流 | app.setLimit({ max, window }) 返回函数 | | 健康检查 | app.healthCheck({...})/health 自动暴露 | | 监控指标 | /metrics Prometheus 格式 | | CORS | 导出 cors 函数,放 beforeRequest 使用 | | Session | this.session,配置存储驱动 | | 队列 | this.queue.push() | | 多环境配置 | config/ 目录,按 NODE_ENV 合并 | | 数据库 | this.db 连接池 | | 优雅关闭 | SIGTERM 按序退出,退回未完成请求 | | CPU 绑核 | affinity: true | | 热重载 | 开发模式监听整个项目,部分重载 | | Debug | __routes 路由表,时间线,错误栈 | | 启动进度 | 清屏显示当前步骤,成功后打印最终状态 |


11. 配置校验

new App({...}) 必须校验配置字段,拼错字段启动时报错并提示最接近的正确字段名。


12. Worker 预热

Worker 启动后自动执行一轮空请求预热,JIT 编译完成后再标记为就绪,RequestingProcess 只向就绪 Worker 分发任务。


13. 框架入口

用户侧代码:

javascript

import { App, Router, Task } from 'dracokite'

const app = new App({
  port: 3000,
  errors: './errors.json'
})

app.beforeRequest(authHook)
app.accessLog(logHandler)
app.healthCheck({ db: checkDb })
app.start()

导出:AppRouterTask


14. 实现要求

  • TypeScript 严格模式
  • 零第三方依赖,仅用 Node.js 内置模块
  • 单文件 core.ts 或合理拆分
  • ESM 模块
  • 所有公共接口完整类型导出
  • 多进程对用户透明,开发体验与单进程一致