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 框架,提供了以下核心特性:
- 简洁的 API - 链式调用,代码清晰易读
- 完整的路由系统 - 支持 HTTP 方法、路由参数、路由前缀
- 静态文件服务 - 带 MIME 类型检测和缓存控制
- CORS 支持 - 灵活的跨域配置
- 文件上传 - 支持多文件上传和验证
- 中间件系统 - 支持同步和异步中间件,集成第三方中间件
- 参数验证 - 强大的参数验证规则
- 模块化 - 支持文件模块和类模块
- 装饰器 - 支持类和方法级装饰器
- TypeScript 支持 - 完整的类型定义
shiyue 适合构建中小型 web 应用和 API 服务,提供了足够的功能,同时保持了代码的简洁性和可维护性。
