@domain.js/main 0.1.16 → 0.2.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 +1 -0
- package/dist/http/defines.d.ts +5 -3
- package/dist/http/index.d.ts +2 -2
- package/dist/http/index.js +7 -0
- package/dist/http/router.d.ts +2 -2
- package/dist/http/router.js +2 -1
- package/dist/http/socket.d.ts +3 -0
- package/dist/http/socket.js +134 -0
- package/dist/http/utils.d.ts +1 -1
- package/dist/http/utils.js +13 -10
- package/package.json +3 -2
package/.eslintrc.js
CHANGED
package/dist/http/defines.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export interface Cnf {
|
|
|
4
4
|
host?: string;
|
|
5
5
|
bodyMaxBytes?: number;
|
|
6
6
|
apisRoute?: string;
|
|
7
|
+
socket?: boolean;
|
|
7
8
|
[propName: string]: any;
|
|
8
9
|
}
|
|
9
10
|
interface Sign {
|
|
@@ -28,6 +29,9 @@ export interface Profile {
|
|
|
28
29
|
uuid?: string;
|
|
29
30
|
token?: string;
|
|
30
31
|
sign?: Sign;
|
|
32
|
+
isSocket?: boolean;
|
|
33
|
+
/** socket 的时候汇报自己的位置 */
|
|
34
|
+
position?: string;
|
|
31
35
|
}
|
|
32
36
|
export interface HttpCodes {
|
|
33
37
|
[propName: string]: number;
|
|
@@ -35,9 +39,7 @@ export interface HttpCodes {
|
|
|
35
39
|
export interface Domain {
|
|
36
40
|
[propName: string]: (profile: Profile, params: any) => any | Domain;
|
|
37
41
|
}
|
|
38
|
-
export
|
|
39
|
-
(methodPath: string): [any, any];
|
|
40
|
-
}
|
|
42
|
+
export declare type GetSchemaByPath = (methodPath: string) => [any, any];
|
|
41
43
|
export interface Err {
|
|
42
44
|
message: string;
|
|
43
45
|
code?: number | string;
|
package/dist/http/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as restify from "restify";
|
|
2
|
+
import { Cnf, Domain, GetSchemaByPath, HttpCodes, Profile } from "./defines";
|
|
2
3
|
import { Router } from "./router";
|
|
3
|
-
import { Cnf, Domain, Profile, HttpCodes, GetSchemaByPath } from "./defines";
|
|
4
4
|
interface Deps {
|
|
5
|
-
routers(r: ReturnType<typeof Router>)
|
|
5
|
+
routers: (r: ReturnType<typeof Router>) => void;
|
|
6
6
|
domain: Domain;
|
|
7
7
|
httpCodes: HttpCodes;
|
|
8
8
|
getSchemaByPath: GetSchemaByPath;
|
package/dist/http/index.js
CHANGED
|
@@ -21,7 +21,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
21
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
22
|
exports.Main = void 0;
|
|
23
23
|
const restify = __importStar(require("restify"));
|
|
24
|
+
const socket_io_1 = require("socket.io");
|
|
24
25
|
const router_1 = require("./router");
|
|
26
|
+
const socket_1 = require("./socket");
|
|
25
27
|
const utils_1 = require("./utils");
|
|
26
28
|
function Main(cnf, deps) {
|
|
27
29
|
const utils = (0, utils_1.Utils)(cnf);
|
|
@@ -42,6 +44,11 @@ function Main(cnf, deps) {
|
|
|
42
44
|
apisRoute: cnf.apisRoute,
|
|
43
45
|
});
|
|
44
46
|
routers(router);
|
|
47
|
+
// 根据需求起送socket服务
|
|
48
|
+
if (cnf.socket) {
|
|
49
|
+
const io = new socket_io_1.Server(server);
|
|
50
|
+
(0, socket_1.BridgeSocket)(io, domain);
|
|
51
|
+
}
|
|
45
52
|
// Http server start
|
|
46
53
|
return () => {
|
|
47
54
|
server.listen(cnf.port || 8088, cnf.host || "127.0.0.1", () => {
|
package/dist/http/router.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as restify from "restify";
|
|
2
|
+
import { Domain, GetSchemaByPath, HttpCodes, Profile } from "./defines";
|
|
2
3
|
import { Utils } from "./utils";
|
|
3
|
-
import { HttpCodes, Domain, Profile, GetSchemaByPath } from "./defines";
|
|
4
4
|
interface Deps {
|
|
5
5
|
domain: Domain;
|
|
6
6
|
getSchemaByPath: GetSchemaByPath;
|
|
7
7
|
utils: ReturnType<typeof Utils>;
|
|
8
8
|
server: restify.Server;
|
|
9
9
|
httpCodes: HttpCodes;
|
|
10
|
-
makeProfileHook
|
|
10
|
+
makeProfileHook?: (obj: Profile, req: restify.Request) => any;
|
|
11
11
|
apisRoute?: string;
|
|
12
12
|
swagger?: [any, any];
|
|
13
13
|
}
|
package/dist/http/router.js
CHANGED
|
@@ -71,6 +71,7 @@ function Router(deps) {
|
|
|
71
71
|
next();
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
|
+
// eslint-disable-next-line max-params
|
|
74
75
|
function register(verb, route, methodPath, code = 200, isList = false, handler, resHandler) {
|
|
75
76
|
/**
|
|
76
77
|
* 暂存起来,提供给apis接口来用
|
|
@@ -93,7 +94,7 @@ function Router(deps) {
|
|
|
93
94
|
try {
|
|
94
95
|
let results = await method(profile, params);
|
|
95
96
|
res.header("X-ConsumedTime", Date.now() - profile.startedAt.valueOf());
|
|
96
|
-
if (results
|
|
97
|
+
if (results === null || results === undefined)
|
|
97
98
|
results = "Ok";
|
|
98
99
|
if (resHandler) {
|
|
99
100
|
resHandler(results, res);
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BridgeSocket = void 0;
|
|
4
|
+
const proxyIps = new Set(["127.0.0.1"]);
|
|
5
|
+
class MyError extends Error {
|
|
6
|
+
constructor(code, message, data) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.data = data;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
const utils = {
|
|
13
|
+
/** 真实的连接请求端ip */
|
|
14
|
+
remoteIp(client) {
|
|
15
|
+
return client.handshake.address;
|
|
16
|
+
},
|
|
17
|
+
/**
|
|
18
|
+
* 获取客户端真实ip地址
|
|
19
|
+
*/
|
|
20
|
+
clientIp(client) {
|
|
21
|
+
const { headers } = client.handshake;
|
|
22
|
+
const clientIp = headers["x-forwarded-for"] || headers["x-real-ip"] || utils.remoteIp(client);
|
|
23
|
+
if (Array.isArray(clientIp))
|
|
24
|
+
return clientIp[0];
|
|
25
|
+
return clientIp.split(",")[0];
|
|
26
|
+
},
|
|
27
|
+
/**
|
|
28
|
+
* 获取可信任的真实ip
|
|
29
|
+
*/
|
|
30
|
+
realIp(client) {
|
|
31
|
+
const remoteIp = utils.remoteIp(client);
|
|
32
|
+
if (!proxyIps.has(remoteIp))
|
|
33
|
+
return remoteIp;
|
|
34
|
+
const realIp = client.handshake.headers["x-real-ip"] || remoteIp;
|
|
35
|
+
if (Array.isArray(realIp))
|
|
36
|
+
return realIp[0];
|
|
37
|
+
return realIp.split(",")[0];
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
const makeProfile = (client, token, params, extra) => {
|
|
41
|
+
const obj = {
|
|
42
|
+
token,
|
|
43
|
+
clientIp: utils.clientIp(client),
|
|
44
|
+
remoteIp: utils.remoteIp(client),
|
|
45
|
+
realIp: utils.realIp(client),
|
|
46
|
+
isSocket: true,
|
|
47
|
+
startedAt: new Date(),
|
|
48
|
+
userAgent: client.handshake.headers["user-agent"] || "Not captured",
|
|
49
|
+
requestId: client.id,
|
|
50
|
+
/** 客户端发布号 */
|
|
51
|
+
revision: params.revision,
|
|
52
|
+
/** 用户uuid 可以长期跨app */
|
|
53
|
+
uuid: params.uuid,
|
|
54
|
+
/** 额外信息,自由扩展 */
|
|
55
|
+
extra,
|
|
56
|
+
};
|
|
57
|
+
return obj;
|
|
58
|
+
};
|
|
59
|
+
function BridgeSocket(io, domain) {
|
|
60
|
+
const subscribe = domain["message.subscribe"];
|
|
61
|
+
const unsubscribe = domain["message.unsubscribe"];
|
|
62
|
+
if (!subscribe)
|
|
63
|
+
throw Error("要启用 socket 服务,必须要要有 message.subscribe 方法,用来处理 socket 订阅");
|
|
64
|
+
if (!unsubscribe)
|
|
65
|
+
throw Error("要启用 socket 服务,必须要要有 message.unsubscribe 方法,用来处理 socket 退订");
|
|
66
|
+
io.on("connection", (client) => {
|
|
67
|
+
console.log("[%s] connection: client.id: %s", new Date(), client.id);
|
|
68
|
+
client.on("init", async (token, params, extra) => {
|
|
69
|
+
console.log("[%s] socket.init: client.id: %s", new Date(), client.id);
|
|
70
|
+
if (!token) {
|
|
71
|
+
client.emit("initError", "Token lost");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
Object.assign(client, { profile: makeProfile(client, token, params, extra) });
|
|
76
|
+
if (!client.profile)
|
|
77
|
+
throw new MyError("noAuth", "请先登录");
|
|
78
|
+
const session = await domain["auth.session"](client.profile, {});
|
|
79
|
+
// 创建消息监听函数
|
|
80
|
+
if (!client.listener)
|
|
81
|
+
client.listener = client.emit.bind(client);
|
|
82
|
+
// 向领域注册改用户的监听函数
|
|
83
|
+
domain["message.subscribe"](client.profile, client.listener);
|
|
84
|
+
client.emit("inited", session);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
if (e instanceof MyError) {
|
|
88
|
+
client.emit("internalError", e.message, e.code || "unknown");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
console.error(e);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
client.use(async ([name, params, responseId], next) => {
|
|
95
|
+
if (name === "init")
|
|
96
|
+
return next();
|
|
97
|
+
const method = domain[name];
|
|
98
|
+
try {
|
|
99
|
+
if (!method)
|
|
100
|
+
throw new MyError("notFound", "不存在该领域方法");
|
|
101
|
+
if (!client.profile)
|
|
102
|
+
throw new MyError("noAuth", "请先执行 init");
|
|
103
|
+
const res = await method(client.profile, params);
|
|
104
|
+
if (responseId) {
|
|
105
|
+
client.emit("response", responseId, res);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
if (e instanceof Error) {
|
|
110
|
+
if (responseId) {
|
|
111
|
+
client.emit("responseError", responseId, e.code, e.message, e.data);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
client.emit(`${name}Error`, e.code, e.message, e.data);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
console.error(e);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return next();
|
|
122
|
+
});
|
|
123
|
+
// 掉线
|
|
124
|
+
client.on("disconnect", () => {
|
|
125
|
+
if (!client.profile)
|
|
126
|
+
return;
|
|
127
|
+
if (!client.listener)
|
|
128
|
+
return;
|
|
129
|
+
// 这里要取消对领域消息的监听
|
|
130
|
+
unsubscribe(client.profile, client.listener);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
exports.BridgeSocket = BridgeSocket;
|
package/dist/http/utils.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare function Utils(cnf: Cnf): {
|
|
|
15
15
|
/**
|
|
16
16
|
* 构造profile参数
|
|
17
17
|
*/
|
|
18
|
-
makeProfile(req: restify.Request, method: string, customFn?:
|
|
18
|
+
makeProfile<T extends {} = {}>(req: restify.Request, method: string, customFn?: ((obj: Profile, req: restify.Request) => T) | undefined): Profile & T;
|
|
19
19
|
/**
|
|
20
20
|
* 构造领域方法所需的 params 参数
|
|
21
21
|
*/
|
package/dist/http/utils.js
CHANGED
|
@@ -18,14 +18,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
21
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
25
|
exports.Utils = void 0;
|
|
23
|
-
const os = __importStar(require("os"));
|
|
24
|
-
const fs = __importStar(require("fs"));
|
|
25
26
|
const crypto = __importStar(require("crypto"));
|
|
26
|
-
const _ = __importStar(require("lodash"));
|
|
27
|
-
const xlsx = __importStar(require("xlsx"));
|
|
28
27
|
const csv_stringify_1 = require("csv-stringify");
|
|
28
|
+
const fs = __importStar(require("fs"));
|
|
29
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
30
|
+
const os = __importStar(require("os"));
|
|
31
|
+
const xlsx = __importStar(require("xlsx"));
|
|
29
32
|
const str2arr = ["_includes", "dimensions", "metrics", "_attrs"];
|
|
30
33
|
const enc = encodeURI;
|
|
31
34
|
const TMPDIR = os.tmpdir();
|
|
@@ -103,7 +106,7 @@ function Utils(cnf) {
|
|
|
103
106
|
*/
|
|
104
107
|
makeParams(req) {
|
|
105
108
|
let params = { ...req.params, ...req.query };
|
|
106
|
-
if (
|
|
109
|
+
if (lodash_1.default.isObject(req.body) && !Array.isArray(req.body)) {
|
|
107
110
|
params = { ...req.body, ...params };
|
|
108
111
|
}
|
|
109
112
|
else if (req.body) {
|
|
@@ -111,10 +114,10 @@ function Utils(cnf) {
|
|
|
111
114
|
}
|
|
112
115
|
// 逗号分隔的属性,自动转换为 array
|
|
113
116
|
for (const k of str2arr) {
|
|
114
|
-
if (params[k] &&
|
|
117
|
+
if (params[k] && lodash_1.default.isString(params[k]))
|
|
115
118
|
params[k] = params[k].split(",");
|
|
116
119
|
}
|
|
117
|
-
if (
|
|
120
|
+
if (lodash_1.default.size(req.files))
|
|
118
121
|
params.__files = req.files;
|
|
119
122
|
return params;
|
|
120
123
|
},
|
|
@@ -124,9 +127,9 @@ function Utils(cnf) {
|
|
|
124
127
|
*/
|
|
125
128
|
async outputCSV(rows, params, res, isXLSX = false) {
|
|
126
129
|
const { _names, _cols, _filename } = params;
|
|
127
|
-
if (!
|
|
130
|
+
if (!lodash_1.default.isString(_cols))
|
|
128
131
|
return false;
|
|
129
|
-
if (_names && !
|
|
132
|
+
if (_names && !lodash_1.default.isString(_names))
|
|
130
133
|
return false;
|
|
131
134
|
const keys = _cols.split(",");
|
|
132
135
|
const titles = (_names || _cols).split(",");
|
|
@@ -156,7 +159,7 @@ function Utils(cnf) {
|
|
|
156
159
|
await new Promise((resolve) => {
|
|
157
160
|
const stream = (0, csv_stringify_1.stringify)(rows, {
|
|
158
161
|
header: true,
|
|
159
|
-
columns:
|
|
162
|
+
columns: lodash_1.default.zipObject(keys, titles),
|
|
160
163
|
});
|
|
161
164
|
stream.pipe(res);
|
|
162
165
|
stream.on("end", resolve);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@domain.js/main",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "DDD framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"prepare": "husky install",
|
|
14
14
|
"lint-staged": "lint-staged",
|
|
15
15
|
"lint-staged:js": "eslint --ext .js,.ts",
|
|
16
|
-
"loadDeps": "ts-node src/cli/index.ts loadDeps ./ ts"
|
|
16
|
+
"loadDeps": "ts-node src/cli/index.ts loadDeps ./src/deps ts"
|
|
17
17
|
},
|
|
18
18
|
"author": "Redstone Zhao",
|
|
19
19
|
"license": "MIT",
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
"restify": "^8.6.0",
|
|
79
79
|
"restify-errors": "^8.0.2",
|
|
80
80
|
"sequelize": "6.16.1",
|
|
81
|
+
"socket.io": "^4.4.1",
|
|
81
82
|
"type-fest": "^2.8.0",
|
|
82
83
|
"uuid": "^8.3.2",
|
|
83
84
|
"xlsx": "^0.17.4"
|