chanjs 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/helper.js +27 -0
- package/core/lib/cache.js +1 -2
- package/core/lib/task.js +140 -0
- package/index.js +7 -6
- package/package.json +1 -1
package/core/helper.js
CHANGED
@@ -71,3 +71,30 @@ export const loadWebToEnd = function(module=[]){
|
|
71
71
|
}
|
72
72
|
return module;
|
73
73
|
}
|
74
|
+
|
75
|
+
|
76
|
+
// import { z } from "zod";
|
77
|
+
|
78
|
+
export const zodValidator = (schemas) => (req, res, next) => {
|
79
|
+
// 分别验证 headers/params/query/body
|
80
|
+
const sections = {
|
81
|
+
headers: schemas.headers,
|
82
|
+
params: schemas.params,
|
83
|
+
query: schemas.query,
|
84
|
+
body: schemas.body
|
85
|
+
};
|
86
|
+
|
87
|
+
for (const [key, schema] of Object.entries(sections)) {
|
88
|
+
if (!schema) continue;
|
89
|
+
|
90
|
+
const result = schema.safeParse(req[key]);
|
91
|
+
if (!result.success) {
|
92
|
+
// 返回首个错误信息
|
93
|
+
const firstError = result.error.errors[0];
|
94
|
+
return res.status(400).json({ error: firstError.message });
|
95
|
+
}
|
96
|
+
// 将验证后的数据挂载到 req 对象
|
97
|
+
req[key] = result.data;
|
98
|
+
}
|
99
|
+
next();
|
100
|
+
};
|
package/core/lib/cache.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
class Cache {
|
1
|
+
export default class Cache {
|
2
2
|
constructor(maxSize = 1000) {
|
3
3
|
this.cache = new Map(); // 使用 Map 存储缓存数据
|
4
4
|
this.maxSize = maxSize; // 缓存最大容量
|
@@ -104,7 +104,6 @@ class Cache {
|
|
104
104
|
}
|
105
105
|
}
|
106
106
|
|
107
|
-
export default new Cache();
|
108
107
|
|
109
108
|
// // 示例用法
|
110
109
|
// const cache = new SimpleCache(100); // 设置缓存最大容量为 100
|
package/core/lib/task.js
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
const schedule = require('node-schedule');
|
2
|
+
|
3
|
+
export default class Task {
|
4
|
+
constructor(config = {}) {
|
5
|
+
this.tasks = new Map();
|
6
|
+
this.config = {
|
7
|
+
taskPrefix: 'TASK_',
|
8
|
+
maxRetry: 3,
|
9
|
+
onError: (id, err) => console.error(`[${id}] Error: ${err.message}`),
|
10
|
+
...config
|
11
|
+
};
|
12
|
+
}
|
13
|
+
|
14
|
+
/**
|
15
|
+
* 添加定时任务
|
16
|
+
* @param {string|Date|Object} rule - 调度规则(Cron/Date/RecurrenceRule)
|
17
|
+
* @param {Function} callback - 任务回调函数
|
18
|
+
* @param {boolean} [immediate=false] - 是否立即执行首次
|
19
|
+
* @returns {string} 任务ID
|
20
|
+
*/
|
21
|
+
addTask(rule, callback, immediate = false) {
|
22
|
+
const taskId = `${this.config.taskPrefix}${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
23
|
+
|
24
|
+
// 创建任务[2,7](@ref)
|
25
|
+
const job = schedule.scheduleJob(taskId, rule, async () => {
|
26
|
+
try {
|
27
|
+
await callback(taskId);
|
28
|
+
job.emit('success');
|
29
|
+
} catch (error) {
|
30
|
+
job.emit('error', error);
|
31
|
+
}
|
32
|
+
});
|
33
|
+
|
34
|
+
// 事件监听[5](@ref)
|
35
|
+
job
|
36
|
+
.on('scheduled', () => console.log(`[${taskId}] 任务已计划`))
|
37
|
+
.on('run', () => console.log(`[${taskId}] 任务执行中`))
|
38
|
+
.on('success', () => console.log(`[${taskId}] 执行成功`))
|
39
|
+
.on('error', (err) => this.config.onError(taskId, err))
|
40
|
+
.on('canceled', () => console.log(`[${taskId}] 已取消`));
|
41
|
+
|
42
|
+
this.tasks.set(taskId, job);
|
43
|
+
|
44
|
+
// 立即执行首次[3](@ref)
|
45
|
+
if (immediate) {
|
46
|
+
process.nextTick(() => callback(taskId));
|
47
|
+
}
|
48
|
+
|
49
|
+
return taskId;
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* 创建循环规则任务(简化版)
|
54
|
+
* @param {Object} options - 循环规则配置 { hour, minute, dayOfWeek 等 }
|
55
|
+
* @param {Function} callback - 任务回调
|
56
|
+
* @param {boolean} [immediate] - 是否立即执行
|
57
|
+
*/
|
58
|
+
addRecurringTask(options, callback, immediate) {
|
59
|
+
const rule = new schedule.RecurrenceRule();
|
60
|
+
Object.assign(rule, options);
|
61
|
+
return this.addTask(rule, callback, immediate);
|
62
|
+
}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* 取消任务
|
66
|
+
* @param {string} taskId - 任务ID
|
67
|
+
* @param {boolean} [graceful=true] - 是否等待当前执行完成
|
68
|
+
* @returns {boolean} 是否取消成功
|
69
|
+
*/
|
70
|
+
cancelTask(taskId, graceful = true) {
|
71
|
+
const job = this.tasks.get(taskId);
|
72
|
+
if (!job) return false;
|
73
|
+
|
74
|
+
graceful ? job.cancel() : job.cancelNext();
|
75
|
+
this.tasks.delete(taskId);
|
76
|
+
return true;
|
77
|
+
}
|
78
|
+
|
79
|
+
/**
|
80
|
+
* 取消所有任务[4](@ref)
|
81
|
+
*/
|
82
|
+
cancelAllTasks() {
|
83
|
+
this.tasks.forEach(job => job.cancel());
|
84
|
+
this.tasks.clear();
|
85
|
+
schedule.gracefulShutdown();
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* 获取任务状态
|
90
|
+
* @param {string} taskId - 任务ID
|
91
|
+
* @returns {'pending'|'running'|'canceled'} 任务状态
|
92
|
+
*/
|
93
|
+
getTaskStatus(taskId) {
|
94
|
+
const job = this.tasks.get(taskId);
|
95
|
+
if (!job) return 'canceled';
|
96
|
+
return job.pendingInvocations.length > 0 ? 'pending' : 'running';
|
97
|
+
}
|
98
|
+
|
99
|
+
/**
|
100
|
+
* 获取所有任务ID
|
101
|
+
* @returns {string[]} 任务ID列表
|
102
|
+
*/
|
103
|
+
getAllTaskIds() {
|
104
|
+
return Array.from(this.tasks.keys());
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
// ==================== 使用示例 ====================
|
109
|
+
// const scheduler = new TaskScheduler({
|
110
|
+
// onError: (id, err) => console.error(`[ALERT] 任务 ${id} 失败: ${err.message}`)
|
111
|
+
// });
|
112
|
+
|
113
|
+
// // 示例1: Cron表达式任务(每分钟30秒时执行)[2](@ref)
|
114
|
+
// const task1 = scheduler.addTask('30 * * * * *', (id) => {
|
115
|
+
// console.log(`[${id}] 执行时间: ${new Date().toISOString()}`);
|
116
|
+
// });
|
117
|
+
|
118
|
+
// // 示例2: 对象语法任务(每天9:30执行)[3](@ref)
|
119
|
+
// const task2 = scheduler.addRecurringTask(
|
120
|
+
// { hour: 9, minute: 30 },
|
121
|
+
// (id) => console.log(`[${id}] 晨间任务执行`)
|
122
|
+
// );
|
123
|
+
|
124
|
+
// // 示例3: 每月1号执行(月初任务)[6](@ref)
|
125
|
+
// const task3 = scheduler.addTask('0 0 1 * *', (id) => {
|
126
|
+
// console.log(`[${id}] 月初自动报表生成`);
|
127
|
+
// });
|
128
|
+
|
129
|
+
// // 示例4: 5秒后执行的一次性任务
|
130
|
+
// const task4 = scheduler.addTask(
|
131
|
+
// new Date(Date.now() + 5000),
|
132
|
+
// (id) => console.log(`[${id}] 一次性任务完成`),
|
133
|
+
// true // 立即先执行一次
|
134
|
+
// );
|
135
|
+
|
136
|
+
// // 取消任务示例
|
137
|
+
// setTimeout(() => {
|
138
|
+
// scheduler.cancelTask(task1);
|
139
|
+
// console.log('当前活跃任务:', scheduler.getAllTaskIds());
|
140
|
+
// }, 10000);
|
package/index.js
CHANGED
@@ -4,21 +4,22 @@ import fs from "fs";
|
|
4
4
|
import cors from "cors";
|
5
5
|
import { pathToFileURL } from 'url'; // 新增顶部导入
|
6
6
|
import config from "./core/config.js";
|
7
|
-
import
|
8
|
-
|
7
|
+
import * as helper from "./core/helper.js";
|
9
8
|
import Service from "./core/lib/service.js";
|
10
|
-
import
|
9
|
+
import Cache from './core/lib/cache.js';
|
10
|
+
import Task from "./core/lib/task.js";
|
11
11
|
import core from "./core/lib/index.js";
|
12
|
-
|
12
|
+
const {bindClass, createKnex, loadWebToEnd} = helper;
|
13
13
|
/**
|
14
14
|
* @description 基于express封装的mvc框架,遵循约定优于配置原则
|
15
15
|
*/
|
16
16
|
class Chan {
|
17
|
-
static helper =
|
17
|
+
static helper = helper;
|
18
18
|
static modules = {};
|
19
19
|
static plugins = {};
|
20
20
|
static config = config;
|
21
|
-
static
|
21
|
+
static Cache = Cache;
|
22
|
+
static Task = Task;
|
22
23
|
constructor() {
|
23
24
|
this.app = express();
|
24
25
|
this.router = express.Router();
|