@domain.js/main 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.
- package/.eslintrc.js +67 -0
- package/.husky/pre-commit +7 -0
- package/.test/test.ts +13 -0
- package/.test/test2.js +45 -0
- package/.travis.yml +8 -0
- package/.vscode/settings.json +3 -0
- package/README.md +6 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +221 -0
- package/dist/deps/aes/index.d.ts +4 -0
- package/dist/deps/aes/index.js +16 -0
- package/dist/deps/axios/index.d.ts +22 -0
- package/dist/deps/axios/index.js +56 -0
- package/dist/deps/cache/After.d.ts +3 -0
- package/dist/deps/cache/After.js +28 -0
- package/dist/deps/cache/Before.d.ts +4 -0
- package/dist/deps/cache/Before.js +16 -0
- package/dist/deps/cache/Define.d.ts +28 -0
- package/dist/deps/cache/Define.js +2 -0
- package/dist/deps/cache/index.d.ts +5 -0
- package/dist/deps/cache/index.js +50 -0
- package/dist/deps/checker/index.d.ts +11 -0
- package/dist/deps/checker/index.js +25 -0
- package/dist/deps/cia/errors.d.ts +6 -0
- package/dist/deps/cia/errors.js +36 -0
- package/dist/deps/cia/index.d.ts +53 -0
- package/dist/deps/cia/index.js +291 -0
- package/dist/deps/counter/index.d.ts +16 -0
- package/dist/deps/counter/index.js +16 -0
- package/dist/deps/cron/index.d.ts +33 -0
- package/dist/deps/cron/index.js +98 -0
- package/dist/deps/defines.d.ts +35 -0
- package/dist/deps/defines.js +36 -0
- package/dist/deps/graceful/index.d.ts +14 -0
- package/dist/deps/graceful/index.js +115 -0
- package/dist/deps/hash/index.d.ts +17 -0
- package/dist/deps/hash/index.js +17 -0
- package/dist/deps/logger/index.d.ts +14 -0
- package/dist/deps/logger/index.js +100 -0
- package/dist/deps/parallel/index.d.ts +34 -0
- package/dist/deps/parallel/index.js +93 -0
- package/dist/deps/redis/index.d.ts +6 -0
- package/dist/deps/redis/index.js +9 -0
- package/dist/deps/rest/Before.d.ts +5 -0
- package/dist/deps/rest/Before.js +9 -0
- package/dist/deps/rest/defines.d.ts +50 -0
- package/dist/deps/rest/defines.js +2 -0
- package/dist/deps/rest/index.d.ts +34 -0
- package/dist/deps/rest/index.js +79 -0
- package/dist/deps/rest/stats.d.ts +6 -0
- package/dist/deps/rest/stats.js +155 -0
- package/dist/deps/rest/utils.d.ts +23 -0
- package/dist/deps/rest/utils.js +419 -0
- package/dist/deps/schema/index.d.ts +11 -0
- package/dist/deps/schema/index.js +39 -0
- package/dist/deps/sequelize/index.d.ts +11 -0
- package/dist/deps/sequelize/index.js +17 -0
- package/dist/deps/signer/index.d.ts +20 -0
- package/dist/deps/signer/index.js +36 -0
- package/dist/dm/dm.d.ts +21 -0
- package/dist/dm/dm.js +57 -0
- package/dist/dm/index.d.ts +12 -0
- package/dist/dm/index.js +56 -0
- package/dist/http/index.d.ts +12 -0
- package/dist/http/index.js +34 -0
- package/dist/http/router.d.ts +23 -0
- package/dist/http/router.js +215 -0
- package/dist/http/utils.d.ts +29 -0
- package/dist/http/utils.js +185 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.js +18 -0
- package/dist/utils/index.d.ts +36 -0
- package/dist/utils/index.js +84 -0
- package/jest.config.js +6 -0
- package/package.json +79 -0
- package/tsconfig.json +13 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
parser: "@typescript-eslint/parser",
|
|
3
|
+
plugins: ["@typescript-eslint"],
|
|
4
|
+
extends: ["airbnb", "eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
|
5
|
+
ignorePatterns: [".eslintrc.js"],
|
|
6
|
+
root: true,
|
|
7
|
+
env: {
|
|
8
|
+
es6: true,
|
|
9
|
+
node: true,
|
|
10
|
+
jest: true,
|
|
11
|
+
},
|
|
12
|
+
settings: {
|
|
13
|
+
react: {
|
|
14
|
+
version: "999.999.999",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
rules: {
|
|
18
|
+
"nonblock-statement-body-position": "off",
|
|
19
|
+
"operator-linebreak": ["error", "after"],
|
|
20
|
+
"prefer-destructuring": ["error", { object: true, array: true }],
|
|
21
|
+
indent: ["error", 2],
|
|
22
|
+
"no-use-before-define": ["error", { functions: true, classes: true, variables: true }],
|
|
23
|
+
"no-param-reassign": 0,
|
|
24
|
+
"no-continue": 0,
|
|
25
|
+
"no-console": 0,
|
|
26
|
+
"no-debugger": 1,
|
|
27
|
+
"no-var": 1,
|
|
28
|
+
semi: ["error", "always"],
|
|
29
|
+
"no-trailing-spaces": "error",
|
|
30
|
+
"eol-last": 1,
|
|
31
|
+
"no-underscore-dangle": 0,
|
|
32
|
+
"no-empty": "error",
|
|
33
|
+
"no-loop-func": "error",
|
|
34
|
+
"no-bitwise": "off", // "error",
|
|
35
|
+
quotes: ["error", "double"],
|
|
36
|
+
"comma-dangle": ["error", "only-multiline"],
|
|
37
|
+
"arrow-parens": ["error", "always"],
|
|
38
|
+
"object-curly-newline": 0,
|
|
39
|
+
"function-paren-newline": 0,
|
|
40
|
+
"implicit-arrow-linebreak": 0,
|
|
41
|
+
curly: 0,
|
|
42
|
+
"no-mixed-operators": "error",
|
|
43
|
+
"no-restricted-syntax": 0,
|
|
44
|
+
"no-lone-blocks": "error",
|
|
45
|
+
"lines-between-class-members": "off",
|
|
46
|
+
yoda: "error",
|
|
47
|
+
"no-plusplus": 0,
|
|
48
|
+
"import/export": 0,
|
|
49
|
+
"no-cond-assign": "error",
|
|
50
|
+
"no-shadow": 0,
|
|
51
|
+
camelcase: 0,
|
|
52
|
+
"prefer-destructuring": 0,
|
|
53
|
+
"import/prefer-default-export": "off",
|
|
54
|
+
"newline-per-chained-call": 0,
|
|
55
|
+
"@typescript-eslint/interface-name-prefix": "off",
|
|
56
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
57
|
+
"@typescript-eslint/explicit-module-boundary-types": "off",
|
|
58
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
59
|
+
"@typescript-eslint/no-namespace": 0,
|
|
60
|
+
"@typescript-eslint/ban-types": 0,
|
|
61
|
+
"import/export": 0,
|
|
62
|
+
"import/no-unresolved": 0,
|
|
63
|
+
"import/extensions": 0,
|
|
64
|
+
"@typescript-eslint/no-var-requires": 0,
|
|
65
|
+
"@typescript-eslint/no-this-alias": 0,
|
|
66
|
+
},
|
|
67
|
+
};
|
package/.test/test.ts
ADDED
package/.test/test2.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
let times = 0;
|
|
2
|
+
const obj = {
|
|
3
|
+
fn1() {
|
|
4
|
+
console.log("Apply fn1, times: %d", times += 1);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
let count = 0;
|
|
9
|
+
const handler = {
|
|
10
|
+
get(target, key) {
|
|
11
|
+
console.log("Proxy new function times: %d", count += 1);
|
|
12
|
+
return (...args) => {
|
|
13
|
+
Reflect.apply(target[key], target, args);
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const proxyObj = new Proxy(obj, handler);
|
|
19
|
+
|
|
20
|
+
proxyObj.fn1();
|
|
21
|
+
proxyObj.fn1();
|
|
22
|
+
proxyObj.fn1();
|
|
23
|
+
proxyObj.fn1();
|
|
24
|
+
proxyObj.fn1();
|
|
25
|
+
|
|
26
|
+
let t2 = 0;
|
|
27
|
+
const obj2 = {
|
|
28
|
+
fn2(...args) {
|
|
29
|
+
console.log("fn2 apply times: %d, args: %o", t2 += 1, args);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handler2 = {
|
|
34
|
+
apply(target, me, args) {
|
|
35
|
+
console.log("proxy apply me: %o, args: %o", me, args);
|
|
36
|
+
Reflect.apply(target, me, args);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
obj2.fn2 = new Proxy(obj2.fn2, handler2);
|
|
41
|
+
obj2.fn2(1, 2, 3);
|
|
42
|
+
obj2.fn2();
|
|
43
|
+
obj2.fn2();
|
|
44
|
+
obj2.fn2();
|
|
45
|
+
obj2.fn2();
|
package/.travis.yml
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# @domain.js/main DDD 领域驱动开发框架
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.com/domain-js/main)
|
|
4
|
+
[](https://codecov.io/gh/domain-js/main)
|
|
5
|
+
|
|
6
|
+
集成了常见的功能模块,采用依赖注入的模式组织项目代码
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#! /usr/bin/env ts-node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const readline = require("readline");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout,
|
|
11
|
+
terminal: true,
|
|
12
|
+
prompt: "> ",
|
|
13
|
+
removeHistoryDuplicates: true,
|
|
14
|
+
});
|
|
15
|
+
rl.setPrompt("> ");
|
|
16
|
+
const _require = require;
|
|
17
|
+
const showMessage = (msg, exit) => {
|
|
18
|
+
rl.write(`${msg}\n`);
|
|
19
|
+
if (exit != null)
|
|
20
|
+
process.exit(exit);
|
|
21
|
+
rl.setPrompt("> ");
|
|
22
|
+
};
|
|
23
|
+
const file2Module = (file) => file.replace(/(-\w)/g, (m) => m[1].toUpperCase());
|
|
24
|
+
const filePath2Var = (_path) => file2Module(_path.replace(/[/.]+/g, "-"));
|
|
25
|
+
const codeStyleFormat = (targetFile) => new Promise((resolve, reject) => {
|
|
26
|
+
(0, child_process_1.exec)(`prettier -w ${targetFile} && eslint --fix ${targetFile}`, (err) => {
|
|
27
|
+
if (err)
|
|
28
|
+
reject(err);
|
|
29
|
+
else
|
|
30
|
+
resolve();
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
const makeDefineFile = async (modules, targetFile, isTS) => {
|
|
34
|
+
const content = ["// domain-cli 自动生成"];
|
|
35
|
+
const _exports = [];
|
|
36
|
+
for (let i = 0; i < modules.length; i += 1) {
|
|
37
|
+
const name = modules[i];
|
|
38
|
+
const variable = filePath2Var(name);
|
|
39
|
+
if (isTS) {
|
|
40
|
+
content.push(`import * as ${variable} from "./${name}"`);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
content.push(`const ${variable} = require("./${name}")`);
|
|
44
|
+
}
|
|
45
|
+
_exports.push(`"${file2Module(name)}": ${variable},`);
|
|
46
|
+
}
|
|
47
|
+
// 处理导出
|
|
48
|
+
content.push("\n");
|
|
49
|
+
if (isTS) {
|
|
50
|
+
content.push("export = {");
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
content.push("module.exports = {");
|
|
54
|
+
}
|
|
55
|
+
for (const x of _exports)
|
|
56
|
+
content.push(x);
|
|
57
|
+
content.push("};");
|
|
58
|
+
fs.writeFileSync(targetFile, content.join("\n"));
|
|
59
|
+
await codeStyleFormat(targetFile);
|
|
60
|
+
console.log(`Completed: ${targetFile}`);
|
|
61
|
+
};
|
|
62
|
+
const checkHookExport = (_dir) => {
|
|
63
|
+
for (const hook of ["Before", "After"]) {
|
|
64
|
+
const TSFile = path.resolve(_dir, `${hook}.ts`);
|
|
65
|
+
const JSFile = path.resolve(_dir, `${hook}.js`);
|
|
66
|
+
const Main = _require(_dir);
|
|
67
|
+
if (fs.existsSync(JSFile)) {
|
|
68
|
+
const Hook = _require(JSFile);
|
|
69
|
+
if (Main[hook] !== Hook)
|
|
70
|
+
throw Error(`${hook} 定义和 export 不一致 ${_dir}`);
|
|
71
|
+
}
|
|
72
|
+
if (fs.existsSync(TSFile)) {
|
|
73
|
+
const { [hook]: Hook } = _require(TSFile);
|
|
74
|
+
if (Main[hook] !== Hook)
|
|
75
|
+
throw Error(`${hook} 定义和 export 不一致 ${_dir}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const loadDeps = async (rootDir = process.cwd(), ext = "js") => {
|
|
80
|
+
const isTS = ext === "ts";
|
|
81
|
+
const modules = [];
|
|
82
|
+
const dir = path.resolve(rootDir, "src/deps/");
|
|
83
|
+
for (const x of fs.readdirSync(dir)) {
|
|
84
|
+
// 忽略隐藏目录
|
|
85
|
+
if (x[0] === ".")
|
|
86
|
+
continue;
|
|
87
|
+
const _dir = path.resolve(dir, x);
|
|
88
|
+
const stat = fs.statSync(_dir);
|
|
89
|
+
// 非目录忽略,模块必须是目录
|
|
90
|
+
if (!stat.isDirectory())
|
|
91
|
+
continue;
|
|
92
|
+
checkHookExport(_dir);
|
|
93
|
+
modules.push(x);
|
|
94
|
+
}
|
|
95
|
+
// 按字典排序,后续有变动的时候不容易冲突
|
|
96
|
+
const targetFile = path.resolve(rootDir, `src/deps/defines.${ext}`);
|
|
97
|
+
await makeDefineFile(modules.sort(), targetFile, isTS);
|
|
98
|
+
};
|
|
99
|
+
const checkService = (_dir) => {
|
|
100
|
+
const TSFile = path.resolve(_dir, "index.ts");
|
|
101
|
+
const JSFile = path.resolve(_dir, "index.js");
|
|
102
|
+
if (!fs.existsSync(TSFile) && !fs.existsSync(JSFile)) {
|
|
103
|
+
throw Error("目录下缺少index.ts 或 index.js 文件");
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const loadServices = async (rootDir = process.cwd(), ext = "js") => {
|
|
107
|
+
const isTS = ext === "ts";
|
|
108
|
+
const modules = [];
|
|
109
|
+
const dir = path.resolve(rootDir, "src/services/");
|
|
110
|
+
for (const x of fs.readdirSync(dir)) {
|
|
111
|
+
// 忽略隐藏目录, 忽略私有目录
|
|
112
|
+
if (x[0] === "." || x[0] === "_")
|
|
113
|
+
continue;
|
|
114
|
+
const _dir = path.resolve(dir, x);
|
|
115
|
+
const stat = fs.statSync(_dir);
|
|
116
|
+
// 非目录忽略,模块必须是目录
|
|
117
|
+
if (!stat.isDirectory())
|
|
118
|
+
continue;
|
|
119
|
+
checkService(_dir);
|
|
120
|
+
modules.push(x);
|
|
121
|
+
}
|
|
122
|
+
// 按字典排序,后续有变动的时候不容易冲突
|
|
123
|
+
const targetFile = path.resolve(rootDir, `src/services/defines.${ext}`);
|
|
124
|
+
await makeDefineFile(modules.sort(), targetFile, isTS);
|
|
125
|
+
};
|
|
126
|
+
const deepLoadDir = (root, parent, files = []) => {
|
|
127
|
+
const paths = {};
|
|
128
|
+
const dir = path.resolve(root, parent);
|
|
129
|
+
for (const x of fs.readdirSync(dir)) {
|
|
130
|
+
// 忽略隐藏目录
|
|
131
|
+
if (x[0] === ".")
|
|
132
|
+
continue;
|
|
133
|
+
const file = path.resolve(dir, x);
|
|
134
|
+
const stat = fs.statSync(file);
|
|
135
|
+
const { name, ext } = path.parse(x);
|
|
136
|
+
const relativeFilePath = `./${path.join(parent, name)}`;
|
|
137
|
+
const moduleName = file2Module(name);
|
|
138
|
+
// 如果是文件则记录
|
|
139
|
+
if (stat.isFile()) {
|
|
140
|
+
if (ext === ".ts") {
|
|
141
|
+
const JSFile = path.resolve(dir, `${name}.js`);
|
|
142
|
+
// 对应的js文件存在,则ts文件忽略
|
|
143
|
+
if (fs.existsSync(JSFile))
|
|
144
|
+
continue;
|
|
145
|
+
// 对应的js文件不存在,抛出异常提示用户要先编译
|
|
146
|
+
throw Error(`请先编译ts文件: ${file}`);
|
|
147
|
+
}
|
|
148
|
+
files.push(relativeFilePath);
|
|
149
|
+
paths[moduleName] = relativeFilePath;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (stat.isDirectory()) {
|
|
153
|
+
paths[moduleName] = deepLoadDir(root, relativeFilePath, files);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return paths;
|
|
157
|
+
};
|
|
158
|
+
const deepLoadModule = async (rootDir, targetFile) => {
|
|
159
|
+
const files = [];
|
|
160
|
+
const paths = deepLoadDir(rootDir, "./", files);
|
|
161
|
+
const { ext } = path.parse(targetFile);
|
|
162
|
+
// 按字典排序,后续有变动的时候不容易冲突
|
|
163
|
+
files.sort();
|
|
164
|
+
const relative = path.relative(path.dirname(targetFile), rootDir);
|
|
165
|
+
const isTS = ext === ".ts";
|
|
166
|
+
const content = ["// domain-cli 自动生成"];
|
|
167
|
+
for (let i = 0; i < files.length; i += 1) {
|
|
168
|
+
const name = files[i];
|
|
169
|
+
const _path = `./${path.join(relative, name)}`;
|
|
170
|
+
const variable = filePath2Var(name);
|
|
171
|
+
if (isTS) {
|
|
172
|
+
content.push(`import * as ${variable} from "${_path}"`);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
content.push(`const ${variable} = require("${_path}")`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// 处理导出
|
|
179
|
+
content.push("\n");
|
|
180
|
+
let _exports = JSON.stringify(paths, null, 2);
|
|
181
|
+
for (let i = 0; i < files.length; i += 1) {
|
|
182
|
+
_exports = _exports.replace(`"${files[i]}"`, filePath2Var(files[i]));
|
|
183
|
+
}
|
|
184
|
+
if (isTS) {
|
|
185
|
+
content.push(`export = ${_exports}`);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
content.push(`module.exports = ${_exports}`);
|
|
189
|
+
}
|
|
190
|
+
fs.writeFileSync(targetFile, content.join("\n"));
|
|
191
|
+
await codeStyleFormat(targetFile);
|
|
192
|
+
console.log(`Completed: ${targetFile}`);
|
|
193
|
+
};
|
|
194
|
+
const actions = { loadDeps, loadServices, deepLoadModule };
|
|
195
|
+
const main = async (command) => {
|
|
196
|
+
const action = actions[command];
|
|
197
|
+
if (!action) {
|
|
198
|
+
const msg = `${action} 不存在该指令,只支持 ${Object.keys(actions)}`;
|
|
199
|
+
return showMessage(msg, 0);
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
await action(...process.argv.slice(3));
|
|
203
|
+
}
|
|
204
|
+
catch (e) {
|
|
205
|
+
showMessage(e instanceof Error ? e.message : e, 1);
|
|
206
|
+
}
|
|
207
|
+
return process.exit(0);
|
|
208
|
+
};
|
|
209
|
+
main(process.argv[2]);
|
|
210
|
+
process.on("uncaughtException", (error) => {
|
|
211
|
+
console.error("[%s]: uncaughtException", new Date());
|
|
212
|
+
console.error(error);
|
|
213
|
+
});
|
|
214
|
+
process.on("unhandledRejection", (reason, p) => {
|
|
215
|
+
console.error("[%s]: unhandledRejection", new Date());
|
|
216
|
+
console.error(reason, p);
|
|
217
|
+
});
|
|
218
|
+
process.on("rejectionHandled", (error) => {
|
|
219
|
+
console.error("[%s]: rejectionHandled", new Date());
|
|
220
|
+
console.error(error);
|
|
221
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Main = void 0;
|
|
4
|
+
const cryptojs = require("crypto-js/core");
|
|
5
|
+
const AES = require("crypto-js/aes");
|
|
6
|
+
function Main() {
|
|
7
|
+
// aes-256-cbc encrypt
|
|
8
|
+
const encrypt = (message, key) => AES.encrypt(message, key).toString();
|
|
9
|
+
// aes-256-cbc decrypt
|
|
10
|
+
const decrypt = (message, key) => AES.decrypt(message, key).toString(cryptojs.enc.Utf8);
|
|
11
|
+
return Object.freeze({
|
|
12
|
+
encrypt,
|
|
13
|
+
decrypt,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
exports.Main = Main;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AxiosInstance } from "axios";
|
|
2
|
+
import { Main as Logger } from "../logger";
|
|
3
|
+
import * as utils from "../../utils";
|
|
4
|
+
declare type VERBS = "post" | "get" | "put" | "delete";
|
|
5
|
+
interface Cnf {
|
|
6
|
+
axios: {
|
|
7
|
+
loggers?: VERBS[];
|
|
8
|
+
retrys?: VERBS[];
|
|
9
|
+
retryTimes?: number;
|
|
10
|
+
retryIntervalMS?: number;
|
|
11
|
+
conf?: {};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
interface Deps {
|
|
15
|
+
logger: ReturnType<typeof Logger>;
|
|
16
|
+
utils: typeof utils;
|
|
17
|
+
}
|
|
18
|
+
export declare function Main(cnf: Cnf, deps: Deps): AxiosInstance & {
|
|
19
|
+
origin?: import("axios").AxiosStatic | undefined;
|
|
20
|
+
};
|
|
21
|
+
export declare const Deps: string[];
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Deps = exports.Main = void 0;
|
|
4
|
+
const axios_1 = require("axios");
|
|
5
|
+
function Main(cnf, deps) {
|
|
6
|
+
const axiosError = (e) => (() => {
|
|
7
|
+
if (!e.response)
|
|
8
|
+
return ["no-response", e.message];
|
|
9
|
+
const r = e.response;
|
|
10
|
+
if (!r.data)
|
|
11
|
+
return [r.status, r.statusText];
|
|
12
|
+
const d = r.data;
|
|
13
|
+
if (typeof d === "string")
|
|
14
|
+
return [r.status, d];
|
|
15
|
+
return [d.code || r.status, d.message || d];
|
|
16
|
+
})().join("\t");
|
|
17
|
+
if (!cnf.axios)
|
|
18
|
+
cnf.axios = {};
|
|
19
|
+
const { loggers, retrys, retryTimes = 3, retryIntervalMS = 3000, conf } = cnf.axios;
|
|
20
|
+
const { utils: { sleep }, logger, } = deps;
|
|
21
|
+
const retryAble = (fn, times, interval) => {
|
|
22
|
+
const exec = async (args, no) => {
|
|
23
|
+
try {
|
|
24
|
+
const res = await fn(...args);
|
|
25
|
+
return res;
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
if (e.code === "ETIMEDOUT") {
|
|
29
|
+
if (interval)
|
|
30
|
+
await sleep(interval);
|
|
31
|
+
if (times <= no)
|
|
32
|
+
throw e;
|
|
33
|
+
return exec(args, no + 1);
|
|
34
|
+
}
|
|
35
|
+
throw e;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
return ((...args) => exec(args, 1));
|
|
39
|
+
};
|
|
40
|
+
const instance = axios_1.default.create(conf);
|
|
41
|
+
instance.origin = axios_1.default;
|
|
42
|
+
if (loggers) {
|
|
43
|
+
for (const x of loggers) {
|
|
44
|
+
const method = logger.logger(instance[x], `axios.${x}`, true, (res) => res.data, axiosError);
|
|
45
|
+
instance[x] = method;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (retrys) {
|
|
49
|
+
for (const x of retrys) {
|
|
50
|
+
instance[x] = retryAble(instance[x], retryTimes, retryIntervalMS);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return instance;
|
|
54
|
+
}
|
|
55
|
+
exports.Main = Main;
|
|
56
|
+
exports.Deps = ["logger", "utils"];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.After = void 0;
|
|
4
|
+
const After = (lru, cnf, deps, pubsub) => {
|
|
5
|
+
const { cache = {} } = cnf;
|
|
6
|
+
const { isMulti = false, delSignalChannel = "LRU_DEL_SIGNAL_CHANNEL" } = cache;
|
|
7
|
+
// 如果不是多节点分部署部署,则不需要处理
|
|
8
|
+
// 开启多节点分布式部署后,要通过redis广播cache的del事件,以此来保持cache的有效性
|
|
9
|
+
if (!isMulti || !pubsub)
|
|
10
|
+
return;
|
|
11
|
+
const { logger } = deps;
|
|
12
|
+
const { pub, sub } = pubsub;
|
|
13
|
+
sub.subscribe(delSignalChannel, (err, count) => {
|
|
14
|
+
logger.info("cache.redis.subscribe", { chanels: delSignalChannel, count });
|
|
15
|
+
if (err)
|
|
16
|
+
return logger.error(err);
|
|
17
|
+
return logger.info(`cache.redis.subscribe succeed, channel count: ${count}`);
|
|
18
|
+
});
|
|
19
|
+
const del = lru.del.bind(lru);
|
|
20
|
+
lru.del = (key) => {
|
|
21
|
+
pub.publish(delSignalChannel, key);
|
|
22
|
+
};
|
|
23
|
+
sub.on("message", async (channel, key) => {
|
|
24
|
+
if (channel === delSignalChannel)
|
|
25
|
+
del(key);
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
exports.After = After;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Before = void 0;
|
|
4
|
+
const Redis = require("ioredis");
|
|
5
|
+
const Before = (cnf, deps) => {
|
|
6
|
+
const { cache = {}, redis } = cnf;
|
|
7
|
+
const { isMulti = false } = cache;
|
|
8
|
+
if (!isMulti)
|
|
9
|
+
return [cnf, deps];
|
|
10
|
+
// 如果不是多节点分部署部署,则不需要处理
|
|
11
|
+
// 开启多节点分布式部署后,要通过redis广播cache的del事件,依次来保持cache的有效性
|
|
12
|
+
const pub = new Redis(redis);
|
|
13
|
+
const sub = new Redis(redis);
|
|
14
|
+
return [cnf, deps, { pub, sub }];
|
|
15
|
+
};
|
|
16
|
+
exports.Before = Before;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as LRU from "lru-cache";
|
|
2
|
+
import * as Redis from "ioredis";
|
|
3
|
+
import { SetRequired } from "type-fest";
|
|
4
|
+
export interface CnfDef {
|
|
5
|
+
cache?: {
|
|
6
|
+
isMulti?: boolean;
|
|
7
|
+
delSignalChannel?: string;
|
|
8
|
+
} & LRU.Options<string, string>;
|
|
9
|
+
redis?: any;
|
|
10
|
+
}
|
|
11
|
+
export interface DepsDef {
|
|
12
|
+
logger: {
|
|
13
|
+
info(message: string, extra?: any): void;
|
|
14
|
+
error(error: Error, extra?: any): void;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface PubSubDef {
|
|
18
|
+
pub: SetRequired<Partial<Redis.Redis>, "publish">;
|
|
19
|
+
sub: SetRequired<Partial<Redis.Redis>, "on" | "subscribe">;
|
|
20
|
+
}
|
|
21
|
+
export interface Cache extends LRU<string, string> {
|
|
22
|
+
caching: <T extends (...args: any[]) => Promise<any>>(func: T, life: number, getKey: (...args: Parameters<T>) => string, hit?: (hited: boolean) => void) => T;
|
|
23
|
+
hitCount: () => {
|
|
24
|
+
hits: number;
|
|
25
|
+
misseds: number;
|
|
26
|
+
};
|
|
27
|
+
needToBroad: boolean;
|
|
28
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Deps = exports.Main = exports.After = exports.Before = void 0;
|
|
4
|
+
const LRU = require("lru-cache");
|
|
5
|
+
var Before_1 = require("./Before");
|
|
6
|
+
Object.defineProperty(exports, "Before", { enumerable: true, get: function () { return Before_1.Before; } });
|
|
7
|
+
var After_1 = require("./After");
|
|
8
|
+
Object.defineProperty(exports, "After", { enumerable: true, get: function () { return After_1.After; } });
|
|
9
|
+
function Main(cnf, deps, pubsub) {
|
|
10
|
+
let hits = 0; // 击中次数
|
|
11
|
+
let misseds = 0; // 未击中次数
|
|
12
|
+
const lru = new LRU(cnf.cache);
|
|
13
|
+
const isFunction = (arg) => typeof arg === "function";
|
|
14
|
+
function caching(func, life, getKey, hit) {
|
|
15
|
+
if (!isFunction(func))
|
|
16
|
+
throw Error("The first argument must be a function");
|
|
17
|
+
if (!Number.isInteger(life) || life < 1)
|
|
18
|
+
throw Error("The second argument must be a number and great then 0");
|
|
19
|
+
if (!isFunction(getKey))
|
|
20
|
+
throw Error("The third argument must be a function");
|
|
21
|
+
if (hit && !isFunction(hit))
|
|
22
|
+
throw Error("The fourth argument must be a function");
|
|
23
|
+
const wrapped = async (...args) => {
|
|
24
|
+
const key = getKey(...args);
|
|
25
|
+
if (lru.has(key)) {
|
|
26
|
+
hits += 1;
|
|
27
|
+
if (hit)
|
|
28
|
+
hit(true);
|
|
29
|
+
return lru.get(key);
|
|
30
|
+
}
|
|
31
|
+
if (hit)
|
|
32
|
+
hit(false);
|
|
33
|
+
misseds += 1;
|
|
34
|
+
const res = await func(...args);
|
|
35
|
+
lru.set(key, res, life);
|
|
36
|
+
return res;
|
|
37
|
+
};
|
|
38
|
+
return wrapped;
|
|
39
|
+
}
|
|
40
|
+
const hitCount = () => ({ hits, misseds });
|
|
41
|
+
const needToBroad = Boolean(pubsub);
|
|
42
|
+
const cache = Object.assign(lru, {
|
|
43
|
+
caching,
|
|
44
|
+
hitCount,
|
|
45
|
+
needToBroad,
|
|
46
|
+
});
|
|
47
|
+
return cache;
|
|
48
|
+
}
|
|
49
|
+
exports.Main = Main;
|
|
50
|
+
exports.Deps = ["logger"];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface Deps {
|
|
2
|
+
errors: {
|
|
3
|
+
notAllowed(...args: any[]): Error;
|
|
4
|
+
};
|
|
5
|
+
}
|
|
6
|
+
export declare function Main(cnf: {}, deps: Deps): {
|
|
7
|
+
equal: (v1: any, v2: any) => boolean;
|
|
8
|
+
privacy: (fns: [Function, ...any[]][], error?: Error) => Promise<void>;
|
|
9
|
+
};
|
|
10
|
+
export declare const Deps: string[];
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Deps = exports.Main = void 0;
|
|
4
|
+
const async = require("async");
|
|
5
|
+
function Main(cnf, deps) {
|
|
6
|
+
const { errors } = deps;
|
|
7
|
+
/** 检测两个值是否相等 */
|
|
8
|
+
const equal = (v1, v2) => v1 === v2;
|
|
9
|
+
/** 判断判断,一次执行数组里的函数 遇到成功的立刻停止,否则抛出信息 */
|
|
10
|
+
const PRIVACY_DEFAULT_ERROR = errors.notAllowed("权限不足");
|
|
11
|
+
const privacy = async (fns, error = PRIVACY_DEFAULT_ERROR) => {
|
|
12
|
+
const passed = (await async.someSeries(fns, async ([fn, ...args]) => {
|
|
13
|
+
const ret = await fn(...args);
|
|
14
|
+
return ret;
|
|
15
|
+
}));
|
|
16
|
+
if (!passed)
|
|
17
|
+
throw error;
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
equal,
|
|
21
|
+
privacy,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
exports.Main = Main;
|
|
25
|
+
exports.Deps = ["errors"];
|