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

shiyue

v2.0.5

Published

a http server like express

Downloads

20

Readme

shiyue 使用教程

简单但够用的 Node.js web 服务框架

安装

npm i shiyue -S

基础使用

简单使用 - 写一个接口

TypeScript 写法:

import { createServer } from "shiyue";

createServer().route("/", (ctx) => {
    ctx.success('hello world')
}).listen(8888)

JavaScript 写法:

const { createServer } = require("shiyue");

createServer().route("/", function(ctx) {
    ctx.success('hello world')
}).listen(8888)

访问链接 http://127.0.0.1:8888/ 会成功返回:

{"success":true,"msg":"成功","data":"hello world"}

链式调用,写多个接口

TypeScript 写法:

import { createServer } from "shiyue";

createServer()
    .route("/", (ctx) => {
        ctx.success('hello world')
    })
    .route("/api1", (ctx) => {
        ctx.success("api1 data")
    })
    .route("/api2", (ctx) => {
        ctx.success("api2 data")
    })
    .listen(8888)

JavaScript 写法:

const { createServer } = require("shiyue");

createServer()
    .route("/", function(ctx) {
        ctx.success('hello world')
    })
    .route("/api1", function(ctx) {
        ctx.success("api1 data")
    })
    .route("/api2", function(ctx) {
        ctx.success("api2 data")
    })
    .listen(8888)

上下文对象 (ctx)

ctx 为上下文对象,其结构主要为:

{
    res: http.ServerResponse;        // HTTP 响应对象
    req: http.IncomingMessage;       // HTTP 请求对象
    shareData: object;                // 中间件数据共享对象
    files: Record<string, UploadedFile | UploadedFile[]>; // 上传的文件
    
    // 获取请求参数
    params(key?: string, dvalue?: any): any;
    
    // 设置请求参数
    paramsSet(key: string, value: any): this;
    
    // 获取数据(带验证)
    data(...keys: string[]): any;
    
    // 获取数据(带验证)- 别名
    paramsData(...keys: string[]): any;
    
    // 返回成功响应
    success(data: any): void;
    
    // 返回错误响应
    error(msg?: string, code?: number, data?: any): void;
    
    // 返回 HTML 响应
    html(html: string): void;
    
    // 返回内容响应(同 html)
    content(content: string): void;
    
    // 获取单个上传文件
    file(fieldname: string): UploadedFile | undefined;
    
    // 获取多个上传文件
    filesGet(fieldname: string): UploadedFile[];
    
    canNext: boolean;                 // 是否继续执行后续中间件
}

核心功能

1. 路由系统

基础路由

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer();

// 默认支持所有 HTTP 方法
app.route("/api", (ctx) => {
    ctx.success({ message: "Hello from API" });
});

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

// 默认支持所有 HTTP 方法
app.route("/api", function(ctx) {
    ctx.success({ message: "Hello from API" });
});

app.listen(8888);

HTTP 方法路由

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer();

// GET 方法
app.get("/user", (ctx) => {
    ctx.success({ message: "GET request" });
});

// POST 方法
app.post("/user", (ctx) => {
    ctx.success({ message: "POST request" });
});

// PUT 方法
app.put("/user", (ctx) => {
    ctx.success({ message: "PUT request" });
});

// DELETE 方法
app.delete("/user", (ctx) => {
    ctx.success({ message: "DELETE request" });
});

// PATCH 方法
app.patch("/user", (ctx) => {
    ctx.success({ message: "PATCH request" });
});

// HEAD 方法
app.head("/user", (ctx) => {
    // HEAD 方法只返回头部,不返回主体
    ctx.res.end();
});

// OPTIONS 方法
app.options("/user", (ctx) => {
    ctx.res.end();
});

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

// GET 方法
app.get("/user", function(ctx) {
    ctx.success({ message: "GET request" });
});

// POST 方法
app.post("/user", function(ctx) {
    ctx.success({ message: "POST request" });
});

// PUT 方法
app.put("/user", function(ctx) {
    ctx.success({ message: "PUT request" });
});

// DELETE 方法
app.delete("/user", function(ctx) {
    ctx.success({ message: "DELETE request" });
});

// PATCH 方法
app.patch("/user", function(ctx) {
    ctx.success({ message: "PATCH request" });
});

// HEAD 方法
app.head("/user", function(ctx) {
    // HEAD 方法只返回头部,不返回主体
    ctx.res.end();
});

// OPTIONS 方法
app.options("/user", function(ctx) {
    ctx.res.end();
});

app.listen(8888);

路由参数

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer();

// 单个参数
app.route("/user/:id", (ctx) => {
    const userId = ctx.params("id");
    ctx.success({ userId });
});

// 多个参数
app.route("/user/:id/post/:postId", (ctx) => {
    const userId = ctx.params("id");
    const postId = ctx.params("postId");
    ctx.success({ userId, postId });
});

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

// 单个参数
app.route("/user/:id", function(ctx) {
    const userId = ctx.params("id");
    ctx.success({ userId });
});

// 多个参数
app.route("/user/:id/post/:postId", function(ctx) {
    const userId = ctx.params("id");
    const postId = ctx.params("postId");
    ctx.success({ userId, postId });
});

app.listen(8888);

路由方法配置

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer();

// 单个方法
app.route("/api", (ctx) => {
    ctx.success({ message: "GET request" });
}, "GET");

// 多个方法
app.route("/api", (ctx) => {
    ctx.success({ message: "GET or POST request" });
}, ["GET", "POST"]);

// 所有方法(默认)
app.route("/api", (ctx) => {
    ctx.success({ message: "Any HTTP method" });
}, "*");

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

// 单个方法
app.route("/api", function(ctx) {
    ctx.success({ message: "GET request" });
}, "GET");

// 多个方法
app.route("/api", function(ctx) {
    ctx.success({ message: "GET or POST request" });
}, ["GET", "POST"]);

// 所有方法(默认)
app.route("/api", function(ctx) {
    ctx.success({ message: "Any HTTP method" });
}, "*");

app.listen(8888);

2. 静态文件服务

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer();

// 使用默认前缀 "/static"
app.static("./public");

// 或自定义前缀
app.static("./public", "/assets");

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

// 使用默认前缀 "/static"
app.static("./public");

// 或自定义前缀
app.static("./public", "/assets");

app.listen(8888);

访问示例:

  • 默认前缀:http://localhost:8888/static/images/logo.png
  • 自定义前缀:http://localhost:8888/assets/images/logo.png

3. CORS 支持

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer();

// 默认配置
app.cors();

// 自定义配置
app.cors({
    origin: "*", // 允许的源
    methods: ["GET", "POST", "PUT", "DELETE"], // 允许的方法
    allowedHeaders: ["Content-Type", "Authorization"], // 允许的请求头
    exposedHeaders: [], // 暴露的响应头
    credentials: true, // 是否允许携带凭证
    maxAge: 86400 // 预检请求缓存时间(秒)
});

app.route("/api", (ctx) => {
    ctx.success({ message: "CORS enabled" });
});

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

// 默认配置
app.cors();

// 自定义配置
app.cors({
    origin: "*", // 允许的源
    methods: ["GET", "POST", "PUT", "DELETE"], // 允许的方法
    allowedHeaders: ["Content-Type", "Authorization"], // 允许的请求头
    exposedHeaders: [], // 暴露的响应头
    credentials: true, // 是否允许携带凭证
    maxAge: 86400 // 预检请求缓存时间(秒)
});

app.route("/api", function(ctx) {
    ctx.success({ message: "CORS enabled" });
});

app.listen(8888);

4. 文件上传

TypeScript 写法:

import { createServer, upload } from "shiyue";
import * as path from "path";

const app = createServer();

// 配置文件上传中间件
app.use(upload({
    dest: path.join(__dirname, "uploads"), // 上传目录
    allowedExtensions: [".jpg", ".jpeg", ".png", ".gif", ".pdf"], // 允许的文件扩展名
    maxSize: 10 * 1024 * 1024 // 最大文件大小(10MB)
}));

app.route("/upload", (ctx) => {
    // 获取单个文件
    const file = ctx.file("avatar");
    
    // 获取多个文件
    const files = ctx.filesGet("photos");
    
    ctx.success({ 
        file: file,
        files: files
    });
});

app.listen(8888);

JavaScript 写法:

const { createServer, upload } = require("shiyue");
const path = require("path");

const app = createServer();

// 配置文件上传中间件
app.use(upload({
    dest: path.join(__dirname, "uploads"), // 上传目录
    allowedExtensions: [".jpg", ".jpeg", ".png", ".gif", ".pdf"], // 允许的文件扩展名
    maxSize: 10 * 1024 * 1024 // 最大文件大小(10MB)
}));

app.route("/upload", function(ctx) {
    // 获取单个文件
    const file = ctx.file("avatar");
    
    // 获取多个文件
    const files = ctx.filesGet("photos");
    
    ctx.success({ 
        file: file,
        files: files
    });
});

app.listen(8888);

5. 中间件

自定义中间件

TypeScript 写法:

import { createServer, Context } from "shiyue";

const app = createServer();

// 同步中间件
app.use((ctx: Context) => {
    console.log("Middleware 1 executed");
    ctx.shareData.user = { id: 1, name: "John" };
});

// 异步中间件
app.use(async (ctx: Context) => {
    console.log("Middleware 2 executed");
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 100));
    console.log("Middleware 2 completed");
});

app.route("/", (ctx) => {
    ctx.success({ 
        message: "Hello",
        user: ctx.shareData.user
    });
});

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

// 同步中间件
app.use(function(ctx) {
    console.log("Middleware 1 executed");
    ctx.shareData.user = { id: 1, name: "John" };
});

// 异步中间件
app.use(async function(ctx) {
    console.log("Middleware 2 executed");
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 100));
    console.log("Middleware 2 completed");
});

app.route("/", function(ctx) {
    ctx.success({ 
        message: "Hello",
        user: ctx.shareData.user
    });
});

app.listen(8888);

第三方中间件集成

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer();

// 集成第三方中间件(如 express 风格的中间件)
app.use(function(req, res, next) {
    console.log("Third-party middleware executed");
    next();
});

app.route("/", (ctx) => {
    ctx.success({ message: "Hello from app" });
});

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

// 集成第三方中间件(如 express 风格的中间件)
app.use(function(req, res, next) {
    console.log("Third-party middleware executed");
    next();
});

app.route("/", function(ctx) {
    ctx.success({ message: "Hello from app" });
});

app.listen(8888);

6. 参数验证

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer();

app.route("/register", (ctx) => {
    // 使用验证规则
    const userData = ctx.data(
        "username/required",
        "email/email",
        "password/min:6",
        "age/number:min:18"
    );
    
    ctx.success({ user: userData });
});

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

app.route("/register", function(ctx) {
    // 使用验证规则
    const userData = ctx.data(
        "username/required",
        "email/email",
        "password/min:6",
        "age/number:min:18"
    );
    
    ctx.success({ user: userData });
});

app.listen(8888);

支持的验证规则:

  • required - 必填
  • email - 邮箱格式
  • url - URL 格式
  • number - 数字
  • min:value - 最小值
  • max:value - 最大值
  • length:value - 长度
  • min_length:value - 最小长度
  • max_length:value - 最大长度
  • password - 密码强度
  • alpha - 字母
  • alpha_num - 字母和数字
  • date - 日期
  • time - 时间
  • datetime - 日期时间
  • idcard - 身份证号
  • creditcard - 信用卡号

7. 模块化

文件模块

TypeScript 写法:

// user/info.ts
import { Context } from "shiyue";

export default class {
    user(ctx: Context) {
        ctx.success({ message: "User info" });
    }
    
    list(ctx: Context) {
        ctx.success({ message: "User list" });
    }
}

// index.ts
import { createServer } from "shiyue";
import * as path from "path";

const app = createServer();

app.module("/user", path.join(__dirname, "user"));

app.listen(8888);

JavaScript 写法:

// user/info.js
module.exports = {
    user(ctx) {
        ctx.success({ message: "User info" });
    },
    
    list(ctx) {
        ctx.success({ message: "User list" });
    }
};

// index.js
const { createServer } = require("shiyue");
const path = require("path");

const app = createServer();

app.module("/user", path.join(__dirname, "user"));

app.listen(8888);

访问示例:

  • http://localhost:8888/user?app=info@user - 访问 info 模块的 user 方法
  • http://localhost:8888/user?app=info@list - 访问 info 模块的 list 方法

类模块

TypeScript 写法:

// user.ts
import { Context } from "shiyue";

export default class {
    user(ctx: Context) {
        ctx.success({ message: "User info" });
    }
}

// index.ts
import { createServer } from "shiyue";
import UserModule from "./user";

const app = createServer();

app.module("/user", UserModule);

app.listen(8888);

JavaScript 写法:

// user.js
module.exports = class {
    user(ctx) {
        ctx.success({ message: "User info" });
    }
};

// index.js
const { createServer } = require("shiyue");
const UserModule = require("./user");

const app = createServer();

app.module("/user", UserModule);

app.listen(8888);

8. 装饰器(注解)

TypeScript 写法:

// check.ts
import { Context } from "shiyue";

export function checkLogin(ctx: Context) {
    const token = ctx.params("token");
    if (!token) {
        ctx.error("Please login first");
    }
}

// user.ts
import { Context, Use } from "shiyue";
import { checkLogin } from "./check";

@Use(checkLogin) // 类级装饰器,所有方法都需要登录
export default class {
    user(ctx: Context) {
        ctx.success({ message: "User info" });
    }
    
    @Use(checkLogin) // 方法级装饰器,仅该方法需要登录
    profile(ctx: Context) {
        ctx.success({ message: "User profile" });
    }
}

// index.ts
import { createServer } from "shiyue";
import UserModule from "./user";

const app = createServer();

app.module("/user", UserModule);

app.listen(8888);

JavaScript 写法:

// check.js
function checkLogin(ctx) {
    const token = ctx.params("token");
    if (!token) {
        ctx.error("Please login first");
    }
}

module.exports = { checkLogin };

// user.js
const { Use, Decorate } = require("shiyue");
const { checkLogin } = require("./check");

class UserModule {
    user(ctx) {
        ctx.success({ message: "User info" });
    }
    
    profile(ctx) {
        ctx.success({ message: "User profile" });
    }
}

// 类级装饰器,所有方法都需要登录
Decorate(Use(checkLogin), UserModule);

// 方法级装饰器,仅该方法需要登录
Decorate(Use(checkLogin), UserModule, "profile");

module.exports = UserModule;

// index.js
const { createServer } = require("shiyue");
const UserModule = require("./user");

const app = createServer();

app.module("/user", UserModule);

app.listen(8888);

配置选项

服务器配置

TypeScript 写法:

import { createServer } from "shiyue";

const app = createServer(8080); // 端口号

// 或
const app = new createServer();
app.port(8080);

app.listen();

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer(8080); // 端口号

// 或
const app = new createServer();
app.port(8080);

app.listen();

HTTPS 支持

TypeScript 写法:

import { createServer } from "shiyue";
import * as fs from "fs";

const app = createServer();

const httpsOptions = {
    key: fs.readFileSync("./key.pem"),
    cert: fs.readFileSync("./cert.pem")
};

app.listen(443, httpsOptions);

JavaScript 写法:

const { createServer } = require("shiyue");
const fs = require("fs");

const app = createServer();

const httpsOptions = {
    key: fs.readFileSync("./key.pem"),
    cert: fs.readFileSync("./cert.pem")
};

app.listen(443, httpsOptions);

响应格式自定义

TypeScript 写法:

import { createServer, ResponseAdvice } from "shiyue";

const app = createServer();

const customResponse: ResponseAdvice = (data, res) => {
    res.setHeader("Content-Type", "application/json");
    res.end(JSON.stringify({
        code: data.success ? 200 : 400,
        message: data.success ? "Success" : data.msg,
        data: data.data
    }));
};

app.responseAdvice(customResponse);

app.route("/", (ctx) => {
    ctx.success({ message: "Hello" });
});

app.listen(8888);

JavaScript 写法:

const { createServer } = require("shiyue");

const app = createServer();

const customResponse = (data, res) => {
    res.setHeader("Content-Type", "application/json");
    res.end(JSON.stringify({
        code: data.success ? 200 : 400,
        message: data.success ? "Success" : data.msg,
        data: data.data
    }));
};

app.responseAdvice(customResponse);

app.route("/", function(ctx) {
    ctx.success({ message: "Hello" });
});

app.listen(8888);

完整示例

TypeScript 写法:

import { createServer, upload, Context } from "shiyue";
import * as path from "path";

const app = createServer(8888);

// 中间件
app.use((ctx: Context) => {
    console.log("Request received:", ctx.req.url);
});

// CORS
app.cors();

// 静态文件
app.static(path.join(__dirname, "public"), "/static");

// 文件上传
app.use(upload({
    dest: path.join(__dirname, "uploads"),
    allowedExtensions: [".jpg", ".png", ".pdf"]
}));

// 路由
app.get("/", (ctx) => {
    ctx.success({ message: "Hello World" });
});

app.post("/api", (ctx) => {
    ctx.success({ message: "POST API" });
});

app.route("/user/:id", (ctx) => {
    const id = ctx.params("id");
    ctx.success({ userId: id });
});

app.route("/upload", (ctx) => {
    const file = ctx.file("avatar");
    ctx.success({ file });
});

// 启动服务器
app.listen();
console.log("Server started on port 8888");

JavaScript 写法:

const { createServer, upload } = require("shiyue");
const path = require("path");

const app = createServer(8888);

// 中间件
app.use(function(ctx) {
    console.log("Request received:", ctx.req.url);
});

// CORS
app.cors();

// 静态文件
app.static(path.join(__dirname, "public"), "/static");

// 文件上传
app.use(upload({
    dest: path.join(__dirname, "uploads"),
    allowedExtensions: [".jpg", ".png", ".pdf"]
}));

// 路由
app.get("/", function(ctx) {
    ctx.success({ message: "Hello World" });
});

app.post("/api", function(ctx) {
    ctx.success({ message: "POST API" });
});

app.route("/user/:id", function(ctx) {
    const id = ctx.params("id");
    ctx.success({ userId: id });
});

app.route("/upload", function(ctx) {
    const file = ctx.file("avatar");
    ctx.success({ file });
});

// 启动服务器
app.listen();
console.log("Server started on port 8888");

总结

shiyue 是一个轻量级但功能强大的 Node.js web 框架,提供了以下核心特性:

  1. 简洁的 API - 链式调用,代码清晰易读
  2. 完整的路由系统 - 支持 HTTP 方法、路由参数、路由前缀
  3. 静态文件服务 - 带 MIME 类型检测和缓存控制
  4. CORS 支持 - 灵活的跨域配置
  5. 文件上传 - 支持多文件上传和验证
  6. 中间件系统 - 支持同步和异步中间件,集成第三方中间件
  7. 参数验证 - 强大的参数验证规则
  8. 模块化 - 支持文件模块和类模块
  9. 装饰器 - 支持类和方法级装饰器
  10. TypeScript 支持 - 完整的类型定义

shiyue 适合构建中小型 web 应用和 API 服务,提供了足够的功能,同时保持了代码的简洁性和可维护性。