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

@mxyu/yang

v1.0.4

Published

A lightweight Koa-based web framework with hook plugin architecture

Readme

@mxyu/yang

一个基于 Koa.js 的轻量级 Node.js Web 框架,采用 Hook 插件架构和约定优于配置的设计理念。

特性

  • Hook 插件架构 — 15 个内置 Hook,按顺序自动加载,开箱即用
  • 三层配置合并 — 框架默认 → 项目基础 → 环境配置,层层覆盖
  • 文件约定路由 — 控制器文件路径自动映射为 API 路由,零配置
  • TypeScript 优先 — 完整类型定义,Context 扩展开箱即用
  • 生产就绪 — 全局错误处理、Redis/MySQL 连接池、优雅关闭
  • 统一响应格式ctx.success() / ctx.error() 统一 JSON 返回格式
  • 请求参数校验 — 集成 Zod,ctx.validate() 一行校验
  • 文件上传 — 集成 @koa/multer,配置即用

安装

npm install @mxyu/yang

快速开始

1. 创建项目目录

my-app/
├── app.ts                      # 应用入口
├── config/
│   ├── config.base.ts          # 基础配置(可选)
│   └── config.development.ts   # 开发环境配置(可选)
├── controller/                 # 文件路由控制器
│   └── goods/
│       └── list.ts             # → GET /goods/list
├── middleware/                 # 自定义中间件
├── package.json
└── tsconfig.json

2. 应用入口

// app.ts
import yang from '@mxyu/yang';

(async () => {
  await yang({ appPath: __dirname });
})();

3. 编写控制器

// controller/goods/list.ts → GET /goods/list
export default {
  method: 'GET',
  handler: async (ctx) => {
    ctx.success([{ id: 1, name: 'Apple' }, { id: 2, name: 'Banana' }]);
  },
};

4. 启动

# 开发
NODE_ENV=development ts-node app.ts

# 生产
NODE_ENV=production node app.ts

框架自带默认配置(端口 3000、文件路由、bodyparser 等),零配置即可启动。

配置

三层配置合并

框架按以下顺序加载配置,后者覆盖前者:

框架默认配置     @mxyu/yang 内置(config/config.default.ts)
      ↓ deepMerge
项目基础配置     {appPath}/config/config.base.ts
      ↓ deepMerge
项目环境配置     {appPath}/config/config.{NODE_ENV}.ts
      ↓
最终 app.config
  • 所有配置文件都是可选的,不存在则跳过
  • 配置文件可导出对象函数(函数会传入 app 实例)

框架默认配置

框架内置以下默认值,项目可按需覆盖:

// @mxyu/yang 内置 config/config.default.ts
{
  port: 3000,
  router: 'file',
  static: {},
  cors: false,
  middlewares: [],
  login: { needLogin: false, secret: '' },
  view: { extension: 'ejs' },
  bodyparser: { enableTypes: ['json', 'form'] },
  upload: { enabled: false },
  redis: false,        // false 表示不连接
  mysql: false,        // false 表示不连接
  log: false,          // false 表示不启用
}

项目配置示例

只需覆盖想要修改的字段:

// config/config.development.ts
export default {
  port: 8888,
  cors: { origin: '*' },
  redis: { host: '127.0.0.1', port: 6379 },
  mysql: { host: 'localhost', user: 'root', password: '123456', database: 'dev' },
};
// config/config.production.ts
export default {
  port: 80,
  login: { needLogin: true, secret: process.env.JWT_SECRET },
  redis: { host: process.env.REDIS_HOST, port: 6379, password: process.env.REDIS_PASSWORD },
  mysql: { host: process.env.MYSQL_HOST, user: 'app', password: process.env.MYSQL_PASSWORD, database: 'prod' },
};

也支持函数导出(可访问 app 实例):

// config/config.development.ts
import path from 'path';

export default (app) => {
  return {
    port: 8888,
    log: { dir: path.join(__dirname, '../log') },
  };
};

完整配置项参考

{
  // 服务端口
  port: 3000,

  // 路由模式: 'file' | 'koa-router'
  router: 'file',

  // 静态文件服务(传给 koa-static)
  static: {},

  // CORS 跨域,false 表示禁用
  cors: {
    origin: '*',
    maxAge: 86400,
    credentials: true,
    allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
  },

  // 自定义中间件(文件名对应 middleware/ 目录)
  middlewares: [],

  // JWT 登录认证
  login: {
    needLogin: false,
    secret: 'your-jwt-secret',
    cookieOption: { path: '/', httpOnly: true, maxAge: 3600000 },
  },

  // 模板引擎
  view: { extension: 'ejs' },

  // 请求体解析
  bodyparser: { enableTypes: ['json', 'form'], jsonLimit: '1mb' },

  // 文件上传
  upload: { enabled: false, dir: '/tmp/uploads', maxSize: 10485760 },

  // Redis(false 或对象)
  redis: { host: '127.0.0.1', port: 6379, password: '', db: 0 },

  // MySQL(false 或对象)
  mysql: { host: 'localhost', port: 3306, user: 'root', password: '', database: 'mydb', connectionLimit: 10 },

  // 日志(false 或对象)
  log: { dir: '/var/log/yang' },
}

路由

文件路由(默认)

config.router: 'file'(默认)

控制器文件路径自动映射为 API 路由:

// controller/goods/list.ts → GET /goods/list
export default {
  method: 'GET',
  handler: async (ctx) => {
    ctx.success([{ id: 1, name: 'Apple' }]);
  },
};
// controller/user/create.ts → POST /user/create
import { z } from 'zod';

export default {
  method: 'POST',
  handler: async (ctx) => {
    const data = ctx.validate(
      z.object({ username: z.string().min(3), password: z.string().min(6) }),
      ctx.request.body
    );
    ctx.success({ id: 1, ...data });
  },
};

传统路由

config.router: 'koa-router'

// routers/user.ts
import Router from 'koa-router';
const router = new Router();

router.prefix('/user');
router.get('/list', (ctx) => ctx.success([{ name: 'yang' }]));

export default router;

Context API

框架在 Koa Context 上扩展了以下方法和属性:

响应方法

ctx.success(data);              // → { code: 0, data: {...}, message: 'ok' }
ctx.error(400, '参数错误');      // → { code: 400, data: null, message: '参数错误' }

参数校验

import { z } from 'zod';

const data = ctx.validate(
  z.object({ username: z.string().min(3), email: z.string().email() }),
  ctx.request.body
);
// 校验失败自动返回 400,成功则返回带类型的数据

数据库

// Redis (ioredis)
await ctx.redis.set('key', 'value');
const value = await ctx.redis.get('key');

// MySQL (mysql2/promise)
const [rows] = await ctx.mysql.query('SELECT * FROM users WHERE id = ?', [1]);

日志

ctx.logger('User logged in:', userId);
ctx.logError('Query failed:', err.message);

用户信息

启用登录(login.needLogin: true)后:

ctx.user; // JWT 解码后的用户信息

自定义中间件

middleware/ 目录下创建文件,配置中按名称注册:

// middleware/logger.ts
export default (app) => {
  return async (ctx, next) => {
    console.log(`${ctx.method} ${ctx.url}`);
    await next();
  };
};
// config/config.base.ts
export default {
  middlewares: ['logger'],  // → middleware/logger.ts
};

内置 Hook 列表

| 顺序 | Hook | 功能 | |------|------|------| | 1 | response | 统一响应格式,注入 ctx.success / ctx.error | | 2 | access-log | 访问日志,记录 method/url/status/耗时 | | 3 | validate | 参数校验,注入 ctx.validate (Zod) | | 4 | lift | 启动 HTTP 服务 | | 5 | router | 路由注册(文件路由或 koa-router) | | 6 | static | 静态文件服务 | | 7 | cors | CORS 跨域支持 | | 8 | custom-middlewares | 加载自定义中间件 | | 9 | login | JWT 登录认证 | | 10 | view | 模板渲染 (EJS) | | 11 | bodyparser | 请求体解析 (JSON/Form) | | 12 | upload | 文件上传 (@koa/multer) | | 13 | redis | Redis 连接,注入 ctx.redis | | 14 | mysql | MySQL 连接池,注入 ctx.mysql | | 15 | log4js | 日志系统,注入 ctx.logger / ctx.logError |

全局错误处理

框架内置全局错误处理中间件,捕获所有未处理的异常:

{ "code": 500, "message": "Internal Server Error", "data": null }
ctx.throw(400, '参数不能为空');
// → { "code": 400, "message": "参数不能为空", "data": null }

优雅关闭

框架监听 SIGTERMSIGINT 信号,收到信号时关闭 Redis/MySQL 连接后退出进程。

项目结构

@mxyu/yang/
├── config/
│   └── config.default.ts       # 框架默认配置
├── hooks/                      # 内置 Hook 插件(15 个)
│   ├── response.ts
│   ├── access-log.ts
│   ├── validate.ts
│   ├── lift.ts
│   ├── router.ts
│   ├── ...
├── utils/                      # 工具函数
│   ├── deepMerge.ts
│   └── get-hooks.ts
├── index.ts                    # 入口
├── types.ts                    # 类型定义
├── package.json
└── tsconfig.json

技术栈

| 类别 | 技术 | |------|------| | 运行时 | Node.js + TypeScript | | Web 框架 | Koa.js | | 路由 | koa-router / 文件约定路由 | | 数据库 | MySQL (mysql2/promise) | | 缓存 | Redis (ioredis) | | 认证 | JWT (jsonwebtoken) | | 日志 | log4js | | 参数校验 | Zod | | 文件上传 | @koa/multer | | 模板 | EJS (koa-views) |

License

ISC