wok-server 0.1.0

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.
Files changed (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +47 -0
  3. package/dist/cache/cache.js +94 -0
  4. package/dist/cache/config.js +19 -0
  5. package/dist/cache/index.js +27 -0
  6. package/dist/cache/purge-task.js +56 -0
  7. package/dist/cache/stat.js +47 -0
  8. package/dist/config/convert.js +36 -0
  9. package/dist/config/exception.js +14 -0
  10. package/dist/config/index.js +67 -0
  11. package/dist/http-client/index.js +132 -0
  12. package/dist/i18n/ar.js +17 -0
  13. package/dist/i18n/de.js +17 -0
  14. package/dist/i18n/en-us.js +17 -0
  15. package/dist/i18n/es.js +17 -0
  16. package/dist/i18n/fr.js +17 -0
  17. package/dist/i18n/i18n.js +231 -0
  18. package/dist/i18n/index.js +52 -0
  19. package/dist/i18n/ja.js +17 -0
  20. package/dist/i18n/ko.js +17 -0
  21. package/dist/i18n/msg.js +2 -0
  22. package/dist/i18n/pt.js +17 -0
  23. package/dist/i18n/ru.js +17 -0
  24. package/dist/i18n/tag.js +18 -0
  25. package/dist/i18n/zh-HK.js +17 -0
  26. package/dist/i18n/zh-TW.js +17 -0
  27. package/dist/i18n/zh-cn.js +17 -0
  28. package/dist/index.js +13 -0
  29. package/dist/log/config.js +28 -0
  30. package/dist/log/date.js +21 -0
  31. package/dist/log/file.js +79 -0
  32. package/dist/log/index.js +109 -0
  33. package/dist/log/level.js +39 -0
  34. package/dist/log/store.js +16 -0
  35. package/dist/mongodb/collection.js +2 -0
  36. package/dist/mongodb/config.js +34 -0
  37. package/dist/mongodb/doc.js +2 -0
  38. package/dist/mongodb/exception.js +14 -0
  39. package/dist/mongodb/index.js +58 -0
  40. package/dist/mongodb/manager/base.js +563 -0
  41. package/dist/mongodb/manager/index.js +63 -0
  42. package/dist/mongodb/manager/tx-strict.js +84 -0
  43. package/dist/mongodb/manager/tx.js +30 -0
  44. package/dist/mongodb/migration.js +52 -0
  45. package/dist/mvc/access-log.js +31 -0
  46. package/dist/mvc/config.js +20 -0
  47. package/dist/mvc/exchange.js +113 -0
  48. package/dist/mvc/handler/index.js +6 -0
  49. package/dist/mvc/handler/json.js +33 -0
  50. package/dist/mvc/handler/restful.js +35 -0
  51. package/dist/mvc/handler/upload.js +33 -0
  52. package/dist/mvc/index.js +316 -0
  53. package/dist/mvc/interceptor.js +2 -0
  54. package/dist/mvc/query.js +43 -0
  55. package/dist/mvc/render/file.js +177 -0
  56. package/dist/mvc/render/html/html.js +90 -0
  57. package/dist/mvc/render/html/index.js +18 -0
  58. package/dist/mvc/render/html/style.js +2 -0
  59. package/dist/mvc/render/index.js +7 -0
  60. package/dist/mvc/render/json.js +26 -0
  61. package/dist/mvc/render/text.js +16 -0
  62. package/dist/mvc/router.js +2 -0
  63. package/dist/mysql/config.js +49 -0
  64. package/dist/mysql/exception.js +14 -0
  65. package/dist/mysql/index.js +85 -0
  66. package/dist/mysql/manager/base.js +233 -0
  67. package/dist/mysql/manager/index.js +107 -0
  68. package/dist/mysql/manager/ops/count.js +20 -0
  69. package/dist/mysql/manager/ops/criteria.js +326 -0
  70. package/dist/mysql/manager/ops/delete.js +65 -0
  71. package/dist/mysql/manager/ops/exist.js +26 -0
  72. package/dist/mysql/manager/ops/find.js +111 -0
  73. package/dist/mysql/manager/ops/index.js +14 -0
  74. package/dist/mysql/manager/ops/insert.js +101 -0
  75. package/dist/mysql/manager/ops/modify.js +10 -0
  76. package/dist/mysql/manager/ops/paginate.js +23 -0
  77. package/dist/mysql/manager/ops/query.js +9 -0
  78. package/dist/mysql/manager/ops/update.js +201 -0
  79. package/dist/mysql/manager/tx-strict.js +98 -0
  80. package/dist/mysql/manager/tx.js +30 -0
  81. package/dist/mysql/manager/utils.js +56 -0
  82. package/dist/mysql/migration.js +136 -0
  83. package/dist/mysql/table-info.js +8 -0
  84. package/dist/task/daily.js +58 -0
  85. package/dist/task/fixed-delay.js +33 -0
  86. package/dist/task/fixed-rate.js +37 -0
  87. package/dist/task/index.js +9 -0
  88. package/dist/task/task.js +39 -0
  89. package/dist/validation/exception.js +44 -0
  90. package/dist/validation/index.js +29 -0
  91. package/dist/validation/validator/array.js +38 -0
  92. package/dist/validation/validator/enum.js +28 -0
  93. package/dist/validation/validator/index.js +14 -0
  94. package/dist/validation/validator/length.js +40 -0
  95. package/dist/validation/validator/max-length.js +35 -0
  96. package/dist/validation/validator/max.js +29 -0
  97. package/dist/validation/validator/min-length.js +33 -0
  98. package/dist/validation/validator/min.js +29 -0
  99. package/dist/validation/validator/not-blank.js +33 -0
  100. package/dist/validation/validator/not-null.js +21 -0
  101. package/dist/validation/validator/plain-obj.js +32 -0
  102. package/dist/validation/validator/regexp.js +30 -0
  103. package/documentation/en/index.md +1 -0
  104. package/documentation/zh-cn/cache.md +59 -0
  105. package/documentation/zh-cn/config.md +68 -0
  106. package/documentation/zh-cn/http-client.md +33 -0
  107. package/documentation/zh-cn/i18n.md +154 -0
  108. package/documentation/zh-cn/index.md +25 -0
  109. package/documentation/zh-cn/log.md +40 -0
  110. package/documentation/zh-cn/mongodb.md +262 -0
  111. package/documentation/zh-cn/mvc.md +430 -0
  112. package/documentation/zh-cn/mysql.md +389 -0
  113. package/documentation/zh-cn/task.md +50 -0
  114. package/documentation/zh-cn/test.md +57 -0
  115. package/documentation/zh-cn/validate.md +125 -0
  116. package/package.json +46 -0
  117. package/types/cache/cache.d.ts +52 -0
  118. package/types/cache/config.d.ts +32 -0
  119. package/types/cache/index.d.ts +2 -0
  120. package/types/cache/purge-task.d.ts +11 -0
  121. package/types/cache/stat.d.ts +26 -0
  122. package/types/config/convert.d.ts +6 -0
  123. package/types/config/exception.d.ts +7 -0
  124. package/types/config/index.d.ts +15 -0
  125. package/types/http-client/index.d.ts +71 -0
  126. package/types/i18n/ar.d.ts +2 -0
  127. package/types/i18n/de.d.ts +2 -0
  128. package/types/i18n/en-us.d.ts +2 -0
  129. package/types/i18n/es.d.ts +2 -0
  130. package/types/i18n/fr.d.ts +2 -0
  131. package/types/i18n/i18n.d.ts +102 -0
  132. package/types/i18n/index.d.ts +9 -0
  133. package/types/i18n/ja.d.ts +2 -0
  134. package/types/i18n/ko.d.ts +2 -0
  135. package/types/i18n/msg.d.ts +50 -0
  136. package/types/i18n/pt.d.ts +2 -0
  137. package/types/i18n/ru.d.ts +2 -0
  138. package/types/i18n/tag.d.ts +11 -0
  139. package/types/i18n/zh-HK.d.ts +2 -0
  140. package/types/i18n/zh-TW.d.ts +2 -0
  141. package/types/i18n/zh-cn.d.ts +2 -0
  142. package/types/index.d.ts +10 -0
  143. package/types/log/config.d.ts +27 -0
  144. package/types/log/date.d.ts +2 -0
  145. package/types/log/file.d.ts +5 -0
  146. package/types/log/index.d.ts +34 -0
  147. package/types/log/level.d.ts +15 -0
  148. package/types/log/store.d.ts +12 -0
  149. package/types/mongodb/collection.d.ts +25 -0
  150. package/types/mongodb/config.d.ts +45 -0
  151. package/types/mongodb/doc.d.ts +11 -0
  152. package/types/mongodb/exception.d.ts +7 -0
  153. package/types/mongodb/index.d.ts +29 -0
  154. package/types/mongodb/manager/base.d.ts +188 -0
  155. package/types/mongodb/manager/index.d.ts +38 -0
  156. package/types/mongodb/manager/tx-strict.d.ts +41 -0
  157. package/types/mongodb/manager/tx.d.ts +21 -0
  158. package/types/mongodb/migration.d.ts +12 -0
  159. package/types/mvc/access-log.d.ts +7 -0
  160. package/types/mvc/config.d.ts +30 -0
  161. package/types/mvc/exchange.d.ts +72 -0
  162. package/types/mvc/handler/index.d.ts +3 -0
  163. package/types/mvc/handler/json.d.ts +23 -0
  164. package/types/mvc/handler/restful.d.ts +11 -0
  165. package/types/mvc/handler/upload.d.ts +40 -0
  166. package/types/mvc/index.d.ts +49 -0
  167. package/types/mvc/interceptor.d.ts +11 -0
  168. package/types/mvc/query.d.ts +13 -0
  169. package/types/mvc/render/file.d.ts +10 -0
  170. package/types/mvc/render/html/html.d.ts +98 -0
  171. package/types/mvc/render/html/index.d.ts +11 -0
  172. package/types/mvc/render/html/style.d.ts +1201 -0
  173. package/types/mvc/render/index.d.ts +4 -0
  174. package/types/mvc/render/json.d.ts +17 -0
  175. package/types/mvc/render/text.d.ts +10 -0
  176. package/types/mvc/router.d.ts +11 -0
  177. package/types/mysql/config.d.ts +86 -0
  178. package/types/mysql/exception.d.ts +7 -0
  179. package/types/mysql/index.d.ts +16 -0
  180. package/types/mysql/manager/base.d.ts +158 -0
  181. package/types/mysql/manager/index.d.ts +36 -0
  182. package/types/mysql/manager/ops/count.d.ts +13 -0
  183. package/types/mysql/manager/ops/criteria.d.ts +120 -0
  184. package/types/mysql/manager/ops/delete.d.ts +46 -0
  185. package/types/mysql/manager/ops/exist.d.ts +6 -0
  186. package/types/mysql/manager/ops/find.d.ts +66 -0
  187. package/types/mysql/manager/ops/index.d.ts +10 -0
  188. package/types/mysql/manager/ops/insert.d.ts +18 -0
  189. package/types/mysql/manager/ops/modify.d.ts +3 -0
  190. package/types/mysql/manager/ops/paginate.d.ts +36 -0
  191. package/types/mysql/manager/ops/query.d.ts +3 -0
  192. package/types/mysql/manager/ops/update.d.ts +70 -0
  193. package/types/mysql/manager/tx-strict.d.ts +34 -0
  194. package/types/mysql/manager/tx.d.ts +15 -0
  195. package/types/mysql/manager/utils.d.ts +17 -0
  196. package/types/mysql/migration.d.ts +8 -0
  197. package/types/mysql/table-info.d.ts +36 -0
  198. package/types/task/daily.d.ts +15 -0
  199. package/types/task/fixed-delay.d.ts +8 -0
  200. package/types/task/fixed-rate.d.ts +8 -0
  201. package/types/task/index.d.ts +4 -0
  202. package/types/task/task.d.ts +33 -0
  203. package/types/validation/exception.d.ts +43 -0
  204. package/types/validation/index.d.ts +32 -0
  205. package/types/validation/validator/array.d.ts +5 -0
  206. package/types/validation/validator/enum.d.ts +8 -0
  207. package/types/validation/validator/index.d.ts +11 -0
  208. package/types/validation/validator/length.d.ts +10 -0
  209. package/types/validation/validator/max-length.d.ts +8 -0
  210. package/types/validation/validator/max.d.ts +7 -0
  211. package/types/validation/validator/min-length.d.ts +6 -0
  212. package/types/validation/validator/min.d.ts +7 -0
  213. package/types/validation/validator/not-blank.d.ts +7 -0
  214. package/types/validation/validator/not-null.d.ts +6 -0
  215. package/types/validation/validator/plain-obj.d.ts +7 -0
  216. package/types/validation/validator/regexp.d.ts +8 -0
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ // 工具集,将一些驱动的方法进行 promise 封装,方便操作
3
+ // 程序中没有使用 mysql2/promise ,主要是在测试中发现 mysql2/promise 不是很可靠
4
+ // mysql2/promise 在查询方便处理的不是很好
5
+ // query 查询在没有记录的情况下仍然会返回列表,里面会包含列定义信息,不符合预期
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.promiseGetConnection = exports.promiseQuery = void 0;
8
+ const mysql2_1 = require("mysql2");
9
+ const log_1 = require("../../log");
10
+ /**
11
+ * 查询,适用于各种 sql 的执行
12
+ * @param config
13
+ * @param conn
14
+ * @param sql
15
+ * @param values
16
+ * @returns
17
+ */
18
+ function promiseQuery(config, conn, sql, values = []) {
19
+ return new Promise((res, rej) => {
20
+ const start = new Date().getTime();
21
+ conn.query(sql, values, (err, result) => {
22
+ if (config.slowSqlWarn) {
23
+ const cost = new Date().getTime() - start;
24
+ // 慢 sql 警告
25
+ if (cost > config.slowSqlMs) {
26
+ (0, log_1.getLogger)().warn(`[mysql slow sql] ${cost}ms ${(0, mysql2_1.format)(sql, values)}`);
27
+ }
28
+ }
29
+ if (err) {
30
+ rej(err);
31
+ }
32
+ else {
33
+ res(result);
34
+ }
35
+ });
36
+ });
37
+ }
38
+ exports.promiseQuery = promiseQuery;
39
+ /**
40
+ * 获取连接
41
+ * @param pool
42
+ * @returns
43
+ */
44
+ function promiseGetConnection(pool) {
45
+ return new Promise((res, rej) => {
46
+ pool.getConnection((err, conn) => {
47
+ if (err) {
48
+ rej(err);
49
+ }
50
+ else {
51
+ res(conn);
52
+ }
53
+ });
54
+ });
55
+ }
56
+ exports.promiseGetConnection = promiseGetConnection;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.migrate = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const log_1 = require("../log");
7
+ const exception_1 = require("./exception");
8
+ const utils_1 = require("./manager/utils");
9
+ /**
10
+ * 迁移.
11
+ * @param config
12
+ * @param conn
13
+ */
14
+ async function migrate(config, conn) {
15
+ const versionDir = config.versionControlDir;
16
+ // 查找文件
17
+ const dir = (0, path_1.isAbsolute)(versionDir) ? versionDir : (0, path_1.resolve)(process.cwd(), versionDir);
18
+ if (!(0, fs_1.existsSync)(dir)) {
19
+ throw new Error(`Directory ${versionDir} does not exist`);
20
+ }
21
+ const versions = [];
22
+ // 忽略隐藏文件
23
+ const files = (0, fs_1.readdirSync)(dir).filter(file => !file.startsWith('.'));
24
+ for (const file of files) {
25
+ const filePath = (0, path_1.resolve)(dir, file);
26
+ const stat = (0, fs_1.statSync)(filePath);
27
+ if (!stat.isFile()) {
28
+ continue;
29
+ }
30
+ if (!file.endsWith('.sql')) {
31
+ throw new Error(`版本文件名没有以 .sql 为后缀:${file}`);
32
+ }
33
+ const version = parseInt(file.substring(0, file.length - 4));
34
+ if (isNaN(version)) {
35
+ throw new Error(`Version file is not named with a number:${file}`);
36
+ }
37
+ versions.push({ version, filePath });
38
+ }
39
+ // 排序,判定顺序
40
+ versions.sort((o1, o2) => o1.version - o2.version);
41
+ for (let i = 0; i < versions.length; i++) {
42
+ const version = versions[i];
43
+ if (version.version !== i + 1) {
44
+ throw new Error(`The SQL version number must start from 1 and increment one by one,error version:${version.version}`);
45
+ }
46
+ }
47
+ await createVersionTableIfNotExist(config, conn);
48
+ // 在事务中执行版本管理,主要目的是为了通过锁来协调多个进程同时启动的情况
49
+ // 事务不能保存一个版本处理成功就完整回退,如有错误,仍然需要手动调整后再操作
50
+ await (0, utils_1.promiseQuery)(config, conn, `SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED`);
51
+ await new Promise((resolve, reject) => {
52
+ conn.beginTransaction(err => {
53
+ if (err) {
54
+ reject(err);
55
+ }
56
+ else {
57
+ resolve();
58
+ }
59
+ });
60
+ });
61
+ try {
62
+ // 执行 sql, 判定当前版本
63
+ let currentVersion = await getCurrentVersion(config, conn);
64
+ if (typeof currentVersion !== 'number') {
65
+ // 插入初始版本号
66
+ await (0, utils_1.promiseQuery)(config, conn, 'insert `db_version`(`version`) values (0)');
67
+ }
68
+ const filnalCurrentVersion = currentVersion || 0;
69
+ const pendingVersions = versions.filter(ver => ver.version > filnalCurrentVersion);
70
+ if (!pendingVersions.length) {
71
+ (0, log_1.getLogger)().info('The SQL version is already the latest.');
72
+ return;
73
+ }
74
+ const nextVersion = filnalCurrentVersion + 1;
75
+ if (pendingVersions[0].version !== nextVersion) {
76
+ throw new exception_1.MysqlException(`MySQL migration error, the next version should be ${nextVersion},but current is ${pendingVersions[0].version}`);
77
+ }
78
+ for (const verion of pendingVersions) {
79
+ (0, log_1.getLogger)().info(`Mysql migrating, version: ${verion.version}`);
80
+ let sql = (0, fs_1.readFileSync)(verion.filePath, { encoding: 'utf-8' });
81
+ await (0, utils_1.promiseQuery)(config, conn, sql);
82
+ // 版本号
83
+ await (0, utils_1.promiseQuery)(config, conn, `UPDATE db_version SET version=${verion.version};`);
84
+ }
85
+ // 提交
86
+ await new Promise((resolve, reject) => {
87
+ conn.commit(err => {
88
+ if (err) {
89
+ reject(err);
90
+ }
91
+ else {
92
+ resolve();
93
+ }
94
+ });
95
+ });
96
+ (0, log_1.getLogger)().info('Mysql migration finished.');
97
+ }
98
+ catch (e) {
99
+ // 异常回退,仅能回退 dml 操作,对 ddl 无效
100
+ await new Promise((resolve, reject) => {
101
+ conn.rollback(err => {
102
+ if (err) {
103
+ reject(err);
104
+ }
105
+ else {
106
+ resolve();
107
+ }
108
+ });
109
+ });
110
+ throw e;
111
+ }
112
+ }
113
+ exports.migrate = migrate;
114
+ async function createVersionTableIfNotExist(config, conn) {
115
+ await (0, utils_1.promiseQuery)(config, conn, 'CREATE TABLE IF NOT EXISTS `db_version` (' +
116
+ ' `version` int NOT NULL,' +
117
+ ' PRIMARY KEY (`version`)' +
118
+ ') ENGINE = innodb DEFAULT CHARACTER SET = "utf8mb4" ' +
119
+ 'COLLATE = "utf8mb4_unicode_ci";');
120
+ }
121
+ /**
122
+ * 获取当前版本,使用 for update 加锁,用于协调多进程并发场景
123
+ * @param config
124
+ * @param conn
125
+ * @returns
126
+ */
127
+ async function getCurrentVersion(config, conn) {
128
+ const res = await (0, utils_1.promiseQuery)(config, conn, 'select version from `db_version` for update');
129
+ const rows = res;
130
+ if (rows.length >= 1) {
131
+ return rows[0].version;
132
+ }
133
+ else {
134
+ return null;
135
+ }
136
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tableValidation = void 0;
4
+ const validation_1 = require("../validation");
5
+ exports.tableValidation = {
6
+ tableName: [(0, validation_1.notBlank)('表名不能为空')],
7
+ id: [(0, validation_1.notBlank)('id 不能为空')]
8
+ };
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dailyTaskDelay = exports.scheduleDailyTask = void 0;
4
+ const validation_1 = require("../validation");
5
+ const task_1 = require("./task");
6
+ /**
7
+ * 每日任务.
8
+ * @param hours 时
9
+ * @param minutes 分
10
+ * @param task 要执行的任务
11
+ * @returns
12
+ */
13
+ function scheduleDailyTask(hours, minutes, task) {
14
+ // 校验
15
+ (0, validation_1.validate)({ hours, minutes }, {
16
+ hours: [(0, validation_1.notNull)(), (0, validation_1.min)(0), (0, validation_1.max)(23)],
17
+ minutes: [(0, validation_1.notNull)(), (0, validation_1.min)(0), (0, validation_1.max)(59)]
18
+ });
19
+ const taskController = new task_1.TaskController();
20
+ const delay = dailyTaskDelay(hours, minutes);
21
+ setTimeout(() => exec(hours, minutes, task, taskController), delay);
22
+ return taskController;
23
+ }
24
+ exports.scheduleDailyTask = scheduleDailyTask;
25
+ /**
26
+ * 计算到下次指定时间点的延迟
27
+ * @param hours
28
+ * @param minutes
29
+ */
30
+ function dailyTaskDelay(hours, minutes) {
31
+ const now = new Date();
32
+ let todayTime = new Date();
33
+ todayTime.setHours(hours);
34
+ todayTime.setMinutes(minutes);
35
+ todayTime.setSeconds(0);
36
+ todayTime.setMilliseconds(0);
37
+ // 如果今天还没有到指定的点,今天就执行,否则明天执行
38
+ if (todayTime > now) {
39
+ return todayTime.getTime() - now.getTime();
40
+ }
41
+ // 明天时间
42
+ const oneDayMilliseconds = 1000 * 3600 * 24;
43
+ const tomorrowTime = todayTime.getTime() + oneDayMilliseconds;
44
+ return tomorrowTime - now.getTime();
45
+ }
46
+ exports.dailyTaskDelay = dailyTaskDelay;
47
+ function exec(hours, minutes, task, controller) {
48
+ Promise.resolve()
49
+ .then(async () => {
50
+ if (controller.isStopped()) {
51
+ return;
52
+ }
53
+ await (0, task_1.execTask)(task);
54
+ const delay = dailyTaskDelay(hours, minutes);
55
+ setTimeout(() => exec(hours, minutes, task, controller), delay);
56
+ })
57
+ .catch(console.error);
58
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scheduleWithFixedDelay = void 0;
4
+ const validation_1 = require("../validation");
5
+ const task_1 = require("./task");
6
+ /**
7
+ * 固定延迟执行任务
8
+ * @param initialDelay 第一次执行延迟的时间,单位秒
9
+ * @param delay 每次的延迟时间,单位秒
10
+ * @param task 任务
11
+ */
12
+ function scheduleWithFixedDelay(initialDelay, delay, task) {
13
+ (0, validation_1.validate)({ initialDelay, delay }, {
14
+ initialDelay: [(0, validation_1.notNull)(), (0, validation_1.min)(0), (0, validation_1.max)(3600 * 24)],
15
+ delay: [(0, validation_1.notNull)(), (0, validation_1.min)(1), (0, validation_1.max)(3600 * 24)]
16
+ });
17
+ const controller = new task_1.TaskController();
18
+ setTimeout(() => exec(delay, task, controller), initialDelay * 1000);
19
+ return controller;
20
+ }
21
+ exports.scheduleWithFixedDelay = scheduleWithFixedDelay;
22
+ function exec(delay, task, controller) {
23
+ Promise.resolve()
24
+ .then(async () => {
25
+ if (controller.isStopped()) {
26
+ return;
27
+ }
28
+ await (0, task_1.execTask)(task);
29
+ // 下次执行
30
+ setTimeout(() => exec(delay, task, controller), delay * 1000);
31
+ })
32
+ .catch(console.error);
33
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scheduleWithFixedRate = void 0;
4
+ const validation_1 = require("../validation");
5
+ const task_1 = require("./task");
6
+ /**
7
+ * 固定延迟执行任务
8
+ * @param initialDelay 第一次执行延迟的时间,单位秒
9
+ * @param period 每次的延迟时间,单位秒
10
+ * @param task 任务
11
+ */
12
+ function scheduleWithFixedRate(initialDelay, period, task) {
13
+ (0, validation_1.validate)({ initialDelay, period }, {
14
+ initialDelay: [(0, validation_1.notNull)(), (0, validation_1.min)(0), (0, validation_1.max)(3600 * 24)],
15
+ period: [(0, validation_1.notNull)(), (0, validation_1.min)(1), (0, validation_1.max)(3600 * 24)]
16
+ });
17
+ const taskController = new task_1.TaskController();
18
+ setTimeout(() => exec(period, task, taskController), initialDelay * 1000);
19
+ return taskController;
20
+ }
21
+ exports.scheduleWithFixedRate = scheduleWithFixedRate;
22
+ function exec(fixedDelay, task, controller) {
23
+ Promise.resolve()
24
+ .then(async () => {
25
+ if (controller.isStopped()) {
26
+ return;
27
+ }
28
+ const res = await (0, task_1.execTask)(task);
29
+ // 下次执行
30
+ let delay = res.start + fixedDelay * 1000 - new Date().getTime();
31
+ if (delay < 0) {
32
+ delay = 0;
33
+ }
34
+ setTimeout(() => exec(fixedDelay, task, controller), delay);
35
+ })
36
+ .catch(console.error);
37
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TaskController = void 0;
4
+ const tslib_1 = require("tslib");
5
+ var task_1 = require("./task");
6
+ Object.defineProperty(exports, "TaskController", { enumerable: true, get: function () { return task_1.TaskController; } });
7
+ tslib_1.__exportStar(require("./fixed-delay"), exports);
8
+ tslib_1.__exportStar(require("./fixed-rate"), exports);
9
+ tslib_1.__exportStar(require("./daily"), exports);
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.execTask = exports.TaskController = void 0;
4
+ const log_1 = require("../log");
5
+ /**
6
+ * 任务控制器
7
+ */
8
+ class TaskController {
9
+ #stopped = false;
10
+ isStopped() {
11
+ return this.#stopped;
12
+ }
13
+ stop() {
14
+ this.#stopped = true;
15
+ }
16
+ }
17
+ exports.TaskController = TaskController;
18
+ /**
19
+ * 任务执行,封装任务执行过程中的一些通用信息输出和异常控制.
20
+ * @param task
21
+ * @returns
22
+ */
23
+ async function execTask(task) {
24
+ const start = new Date().getTime();
25
+ try {
26
+ (0, log_1.getLogger)().info(`START TASK:${task.name}`);
27
+ await task.run();
28
+ }
29
+ catch (e) {
30
+ (0, log_1.getLogger)().error(`TASK ERROR: ${task.name}`, e);
31
+ }
32
+ const end = new Date().getTime();
33
+ const cost = end - start;
34
+ if (cost > 1000 * 60 * 5) {
35
+ (0, log_1.getLogger)().warn(`Task "${task.name}" takes too long ,cost ${cost}ms`);
36
+ }
37
+ return { start, cost, end };
38
+ }
39
+ exports.execTask = execTask;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ValidationException = void 0;
4
+ /**
5
+ * 校验异常.
6
+ */
7
+ class ValidationException {
8
+ errMsg;
9
+ validator;
10
+ propertyPath;
11
+ val;
12
+ constructor(
13
+ /**
14
+ * 异常信息,如 “不能为空” 之类的.
15
+ */
16
+ errMsg,
17
+ /**
18
+ * 校验器名称,如 length 、notNull 之类的.
19
+ */
20
+ validator,
21
+ /**
22
+ * 校验出错的路径.
23
+ */
24
+ propertyPath,
25
+ /**
26
+ * 值
27
+ */
28
+ val) {
29
+ this.errMsg = errMsg;
30
+ this.validator = validator;
31
+ this.propertyPath = propertyPath;
32
+ this.val = val;
33
+ }
34
+ /**
35
+ * 对错误的完整描述信息,用于日志记录.
36
+ */
37
+ desc() {
38
+ return `Field "${this.propertyPath}" failed to validate by validator ${this.validator} ,value:${this.val},info:${this.errMsg}`;
39
+ }
40
+ get message() {
41
+ return this.desc();
42
+ }
43
+ }
44
+ exports.ValidationException = ValidationException;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validate = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const exception_1 = require("./exception");
6
+ /**
7
+ * 校验对象.
8
+ * @param obj
9
+ */
10
+ function validate(obj, opts) {
11
+ for (const entry of Object.entries(opts)) {
12
+ const [prop, validators] = entry;
13
+ const val = obj[prop];
14
+ for (const validator of validators) {
15
+ const result = validator(val);
16
+ if (!result.ok) {
17
+ const propPath = [prop];
18
+ if (result.propPath) {
19
+ propPath.push(...result.propPath);
20
+ }
21
+ throw new exception_1.ValidationException(result.message, result.validator, propPath.join('.'), val);
22
+ }
23
+ }
24
+ }
25
+ }
26
+ exports.validate = validate;
27
+ // 导出
28
+ tslib_1.__exportStar(require("./exception"), exports);
29
+ tslib_1.__exportStar(require("./validator"), exports);
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.array = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 校验数组的条目.
7
+ */
8
+ function array(opts) {
9
+ const validator = 'array';
10
+ return val => {
11
+ if (!val) {
12
+ return { ok: true };
13
+ }
14
+ if (!Array.isArray(val)) {
15
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-array') };
16
+ }
17
+ // 条目处理
18
+ for (let i = 0; i < val.length; i++) {
19
+ const item = val[i];
20
+ for (const validation of Object.entries(opts)) {
21
+ const [prop, validators] = validation;
22
+ const val = item[prop];
23
+ for (const validate of validators) {
24
+ const result = validate(val);
25
+ if (!result.ok) {
26
+ const propPath = [`[${i}]`, prop];
27
+ if (result.propPath) {
28
+ propPath.push(...result.propPath);
29
+ }
30
+ return { ok: false, validator, message: result.message, propPath };
31
+ }
32
+ }
33
+ }
34
+ }
35
+ return { ok: true };
36
+ };
37
+ }
38
+ exports.array = array;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.enumerate = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 枚举,校验值必须是指定列表中的一个.
7
+ * @param list 支持的值列表,仅支持数字和字符串类型
8
+ * @param msg
9
+ * @returns
10
+ */
11
+ function enumerate(list, msg) {
12
+ const validator = 'enumerate';
13
+ return val => {
14
+ if (!val) {
15
+ return { ok: true };
16
+ }
17
+ if (!list.some(item => item === val)) {
18
+ return {
19
+ ok: false,
20
+ validator,
21
+ // must be one of [1,2,3]
22
+ message: msg || (0, i18n_1.getI18n)().buildMsg('validate-err-enum', `[${list.join(',')}]`)
23
+ };
24
+ }
25
+ return { ok: true };
26
+ };
27
+ }
28
+ exports.enumerate = enumerate;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./not-null"), exports);
5
+ tslib_1.__exportStar(require("./not-blank"), exports);
6
+ tslib_1.__exportStar(require("./max"), exports);
7
+ tslib_1.__exportStar(require("./min"), exports);
8
+ tslib_1.__exportStar(require("./regexp"), exports);
9
+ tslib_1.__exportStar(require("./length"), exports);
10
+ tslib_1.__exportStar(require("./enum"), exports);
11
+ tslib_1.__exportStar(require("./array"), exports);
12
+ tslib_1.__exportStar(require("./plain-obj"), exports);
13
+ tslib_1.__exportStar(require("./max-length"), exports);
14
+ tslib_1.__exportStar(require("./min-length"), exports);
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.length = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * length 校验,可用于字符串或数组.
7
+ * @returns
8
+ */
9
+ function length(opts) {
10
+ const validator = 'length';
11
+ return val => {
12
+ // 不校验空
13
+ if (!val) {
14
+ return { ok: true };
15
+ }
16
+ if (typeof val.length !== 'number') {
17
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-no-length') };
18
+ }
19
+ const { length } = val;
20
+ if (typeof length !== 'number') {
21
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-length-not-number') };
22
+ }
23
+ if (typeof opts.min === 'number' && length < opts.min) {
24
+ return {
25
+ ok: false,
26
+ validator,
27
+ message: opts.message || (0, i18n_1.getI18n)().buildMsg('validate-err-min-length', `${opts.min}`)
28
+ };
29
+ }
30
+ if (typeof opts.max === 'number' && length > opts.max) {
31
+ return {
32
+ ok: false,
33
+ validator,
34
+ message: opts.message || (0, i18n_1.getI18n)().buildMsg('validate-err-max-length', `${opts.max}`)
35
+ };
36
+ }
37
+ return { ok: true };
38
+ };
39
+ }
40
+ exports.length = length;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.maxLength = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 最大长度校验,可用于字符串或数组.
7
+ * @param maxLength
8
+ * @param message
9
+ * @returns
10
+ */
11
+ function maxLength(maxLength, message) {
12
+ const validator = 'maxLength';
13
+ return val => {
14
+ // 不校验空
15
+ if (!val) {
16
+ return { ok: true };
17
+ }
18
+ if (typeof val.length !== 'number') {
19
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-no-length') };
20
+ }
21
+ const { length } = val;
22
+ if (typeof length !== 'number') {
23
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-length-not-number') };
24
+ }
25
+ if (length > maxLength) {
26
+ return {
27
+ ok: false,
28
+ validator,
29
+ message: message || (0, i18n_1.getI18n)().buildMsg('validate-err-max-length', `${maxLength}`)
30
+ };
31
+ }
32
+ return { ok: true };
33
+ };
34
+ }
35
+ exports.maxLength = maxLength;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.max = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 最大值校验.
7
+ * @param max 最大值
8
+ * @param msg 错误消息
9
+ */
10
+ function max(max, msg) {
11
+ const validator = 'max';
12
+ return val => {
13
+ if (val == undefined || val === null) {
14
+ return { ok: true };
15
+ }
16
+ if (typeof val !== 'number') {
17
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-numer') };
18
+ }
19
+ if (val > max) {
20
+ return {
21
+ ok: false,
22
+ validator,
23
+ message: msg || (0, i18n_1.getI18n)().buildMsg('validate-err-max', `${max}`)
24
+ };
25
+ }
26
+ return { ok: true };
27
+ };
28
+ }
29
+ exports.max = max;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.minLength = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 最小长度校验,可用于字符串或数组.
7
+ * @returns
8
+ */
9
+ function minLength(minLength, message) {
10
+ const validator = 'minLength';
11
+ return val => {
12
+ // 不校验空
13
+ if (!val) {
14
+ return { ok: true };
15
+ }
16
+ if (typeof val.length !== 'number') {
17
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-no-length') };
18
+ }
19
+ const { length } = val;
20
+ if (typeof length !== 'number') {
21
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-length-not-number') };
22
+ }
23
+ if (length < minLength) {
24
+ return {
25
+ ok: false,
26
+ validator,
27
+ message: message || (0, i18n_1.getI18n)().buildMsg('validate-err-min-length', `${minLength}`)
28
+ };
29
+ }
30
+ return { ok: true };
31
+ };
32
+ }
33
+ exports.minLength = minLength;