@x-9lab/xlab 1.0.0-alpha.1

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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +182 -0
  3. package/dist/@config/config.dev.js +13 -0
  4. package/dist/@config/config.js +25 -0
  5. package/dist/@config/config.sand.js +10 -0
  6. package/dist/bin/watch.js +145 -0
  7. package/dist/bin/xlab +49 -0
  8. package/dist/business/utils/cookie/1.1.0/clean/index.js +35 -0
  9. package/dist/business/utils/cookie/1.1.0/clean/js/@tpls/js.tpl +32 -0
  10. package/dist/business/utils/cookie/1.1.0/clean/js/index.js +30 -0
  11. package/dist/cluster.js +120 -0
  12. package/dist/components/assets/index.js +31 -0
  13. package/dist/components/cache/index.js +9 -0
  14. package/dist/components/cache/lru.js +75 -0
  15. package/dist/components/cluster/index.js +40 -0
  16. package/dist/components/combo/index.js +170 -0
  17. package/dist/components/common.js +324 -0
  18. package/dist/components/cron.js +117 -0
  19. package/dist/components/header/index.js +74 -0
  20. package/dist/components/header/time.js +37 -0
  21. package/dist/components/html-processor/index.js +95 -0
  22. package/dist/components/injection/index.js +83 -0
  23. package/dist/components/js-processor/index.js +65 -0
  24. package/dist/components/log.js +112 -0
  25. package/dist/components/md5/index.js +19 -0
  26. package/dist/components/mime/index.js +18 -0
  27. package/dist/components/platform/index.js +103 -0
  28. package/dist/components/proxy/index.js +62 -0
  29. package/dist/components/querystring/index.js +60 -0
  30. package/dist/components/redirect/index.js +79 -0
  31. package/dist/components/return-code.js +117 -0
  32. package/dist/components/uuid/index.js +33 -0
  33. package/dist/components/version/index.js +96 -0
  34. package/dist/config/getEnv.js +61 -0
  35. package/dist/config/index.js +137 -0
  36. package/dist/config/process-custom-config-files.js +67 -0
  37. package/dist/config/process-def-config-file.js +29 -0
  38. package/dist/custom.js +44 -0
  39. package/dist/global.js +67 -0
  40. package/dist/middleware/@bin/html-filter.js +94 -0
  41. package/dist/middleware/bad-request.js +36 -0
  42. package/dist/middleware/combo.js +13 -0
  43. package/dist/middleware/compress.js +36 -0
  44. package/dist/middleware/cors.js +66 -0
  45. package/dist/middleware/fresh-filter.js +63 -0
  46. package/dist/middleware/handle-pre-dir.js +25 -0
  47. package/dist/middleware/request-filter.js +144 -0
  48. package/dist/middleware/service-mark.js +30 -0
  49. package/dist/middlewares.js +40 -0
  50. package/dist/package.json +61 -0
  51. package/dist/router.js +101 -0
  52. package/dist/server.js +132 -0
  53. package/package.json +59 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 x-9lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,182 @@
1
+ X-9lab 通用服务端
2
+ =======
3
+
4
+ ## 开发环境配置
5
+ 1. 安装 [node](https://nodejs.org/) ,需要 10.0.0 以上版本
6
+
7
+ ## 使用
8
+ - 将 `@x-9lab/xlab` 加入到依赖中
9
+ - `package.json` 中调用 `xlab`
10
+ ```json
11
+ {
12
+ "scripts": {
13
+ "start-dev": "xlab"
14
+ }
15
+ }
16
+ ```
17
+ - 除了静态资源,服务端业务需要放在项目根目录下的 `@server` 目录中
18
+ - 支持业务自定义以下内容 (无特殊说明的都是存放在 @server 目录中)
19
+ - 配置项,存放于 `@config` 目录
20
+ - 支持不同环境配置文件
21
+ - 无中间词缀的 config 文件为生产环境配置文件
22
+ - 中间词缀为 `dev` 的 config 文件为开发环境配置文件
23
+ - 中间词缀为`sand` 的 config 文件为沙箱环境配置文件
24
+ - 中间词缀为`lo` 的 config 文件为本地环境配置文件,该文件不应被提交到仓库
25
+ - 配置文件按照中间词缀,合并优先级为 `lo > dev = sand > 无`
26
+ - 开发环境与沙箱环境同时只会根据当前环境取其中一个,因此优先级一样
27
+ - 服务接口,存放于 `business` 目录
28
+ - 接口地址
29
+ - 默认服务接口均以 `api` 开始
30
+ - 按照目录结构生成 api
31
+ - 文件名是 `index` 的会被从 api 上先强行去掉
32
+ - 默认都是 `get` 请求
33
+ - 支持以下形式定义接口
34
+ - 模块返回的是数组,则使用文件名做为方法名,并在 api 上去掉文件名
35
+ - 非数组则文件当作正常的 api 地址
36
+ - 模块返回为函数的则直接绑定为接口处理函数
37
+ - 返回是对象则取对应的字段
38
+ - `method` 接口类型,如 `get` 或 `post`
39
+ - `middleware` 接口中间件
40
+ - `handler` 接口处理函数
41
+ - 自定义逻辑,存放于 `custom` 目录,模块需要导出一个函数作为执行入口
42
+ - 中间件,存放于 `middleware` 目录
43
+ - 定时任务,存放于 `cron` 目录
44
+ - 静态资源,默认存放在项目根目录下的 `public` 目录中
45
+ ### 全局对象与函数
46
+
47
+ #### 全局对象
48
+ - `log` 全局日志对象
49
+ - `masterLog` 只在 master 上输出的日志对象
50
+
51
+ #### 全局函数
52
+ - `getApp` 获取应用实例对象
53
+ ```ts
54
+ /**
55
+ * 获取应用实例对象
56
+ */
57
+ function getApp(): Koa;
58
+ ```
59
+ - `requireMod` 获取内置组件
60
+ ```ts
61
+ /**
62
+ * 获取内置组件
63
+ * @param name 模块名
64
+ * @return 模块对象
65
+ */
66
+ function requireMod<T extends InternalComponents[K], K extends keyof InternalComponents>(name: K): T;
67
+ ```
68
+ - `getSysConfig` 获取系统配置
69
+ - 获取全部配置
70
+ ```js
71
+ const config = getSysConfig();
72
+ ```
73
+ - 获取指定配置
74
+ ```js
75
+ const allowCache = getSysConfig("allowCache");
76
+ ```
77
+ - `setSysConfig` 更新系统配置
78
+ ```ts
79
+ /**
80
+ * 更新系统配置
81
+ * @param conf 配置项
82
+ */
83
+ function setSysConfig(conf: XLab.IConfig): void;
84
+ ```
85
+ - `requireModel` 全局获取 model 的方法
86
+ - `requireService` 全局获取 service 的方法
87
+
88
+ #### Namespace `XLab`
89
+ `XLab` 提供了一些标准化的定义及系统配置
90
+ - `IStdRes` 标准返回数据
91
+ - `IConfig` 系统配置对象
92
+ - `ICodeItem` 错误信息对象
93
+ - `ICodeDetail` 错误定义
94
+
95
+ ### 配置项
96
+ |名称|类型|默认值|说明|
97
+ |-|-|-|-|
98
+ |name|`string`| package.json 中的 name 字段 |服务(应用)名称|
99
+ |version|`string`|package.json 中的 version 字段|版本|
100
+ |env|`string`|development|环境标识|
101
+ |host|`string`| |业务绑定的域名|
102
+ |304|`boolean`| true |是否开启 304 协商缓存|
103
+ |workers|`number`|0|Worker 数量|
104
+ |biServer|`string`||业务服务器地址|
105
+ |protocol|`string`|http|业务服务器协议|
106
+ |debug|`boolean`|false|是否开启 debug 模式|
107
+ |staticMaxage|`number`|1800000|静态文件缓存时间|
108
+ |staticHtmlFileMaxage|`number`|0|静态 html 文件缓存时间|
109
+ |enableComboCache|`boolean`|true|是否开启 Combo 缓存|
110
+ |enableCron|`boolean`|false|是否开启定时任务|
111
+ |middleware|`Array<string | (string | Record<string, any>)[]>`|[]|开启的中间件列表 |
112
+ |custom|`string[]`||自定模块配置|
113
+ |strictSSL|`boolean`||是否启用严格 ssl|
114
+ |apis|`Record<string, string>`|{}|页端注入的 api 设置|
115
+ |hasLo|`boolean`||本地是否存在本地开发配置文件|
116
+ |passExtApis|`boolean`||不处理业务 api|
117
+ |allowCache|`boolean`||是否允许页端缓存|
118
+ |root|`string`|public|静态文件根目录|
119
+ |port|`number`|5000|监听端口|
120
+ |isMaster|`boolean`||是否是主进程|
121
+ |clearLocalStorage|`boolean`||是否每次都强制清除 LocalStorage|
122
+ |pathReplaceRegExp|`string`||处理代理过来多余的地址层级路径替换判断正则|
123
+ |routeMobile|`string`||移动端入口文件地址(旧版逻辑)|
124
+ |launchRouter|`Record<string, string>`||不同端入口地址设置|
125
+ |cron|`{def?: number;}`|{"def": 60}|定时任务设置|
126
+ |injection|`string[]`|[]|注入参数列表|
127
+ |indexPageCacheTime|`number`||首页缓存时间|
128
+ |staticResourceCacheTime|`number`||静态资源缓存时间|
129
+
130
+ ## 文件结构
131
+
132
+ ```
133
+ ├── README.md
134
+ ├── business
135
+ │ └── @services
136
+ │ └── @models
137
+ │ │ └── forumUser.js
138
+ │ └── ...
139
+ ├── components
140
+ │ ├── cache
141
+ │ ├── common.js
142
+ │ └── ...
143
+ ├── @config
144
+ │ ├── config.dev.ts
145
+ │ └── config.ts
146
+ ├── middleware
147
+ ├── cron
148
+ ├── public
149
+ ├── test
150
+ ├── route
151
+ ├── private
152
+ │ └── log
153
+ ├── package.json
154
+ ├── config.js
155
+ ├── router.js
156
+ └── server.js
157
+ ```
158
+
159
+ ### 说明
160
+ - ``business目录``:前端业务
161
+ - ``@services目录``:业务services
162
+ - ``@models目录``:存放model
163
+ - ``components目录``: 存放当前项目组件
164
+ - ``@config``:存放环境配置,不同环境在名称与文件后缀中间使用不同代号区分
165
+ - ``middleware目录``:存放请求特殊处理模块,一般作为中间件
166
+ - ``public目录``:存放前端资源文件
167
+ - ``cron目录``:存放定时任务文件
168
+ - ``test目录``:存放单元测试
169
+ - ``route目录``:存放不同平台的路由配置
170
+ - ``private目录``:存放业务 log ,或其他服务端相关的内容
171
+ - ``package.json``:nodejs后端所需要的依赖描述文件,即npm的 [package.json](https://www.npmjs.org/doc/files/package.json.html) 文件
172
+ - ``router.js``:路由模块
173
+ - ``server.js``:服务器主模块
174
+ - ``config.js``:配置处理模块
175
+
176
+ ## TODO
177
+
178
+ - [ ] swc 支持 `--out-file-extension` 后转为直接输出 `.mjs` 文件
179
+ 1. `packgae.json` 增加 `"type": "module"` 设置
180
+ 1. `.swcrc` 中 `module.type` 改为 `es6`
181
+ - [x] 配置文件由 `json` 改为 `ts`
182
+ - [x] 支持各内置模块的完整类型推导
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: ()=>_default
8
+ });
9
+ const CONFIG = {
10
+ "304": false,
11
+ "workers": 0
12
+ };
13
+ const _default = CONFIG;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: ()=>_default
8
+ });
9
+ const CONFIG = {
10
+ "host": "",
11
+ "304": true,
12
+ "workers": 0,
13
+ "biServer": "",
14
+ "protocol": "http",
15
+ "debug": false,
16
+ "staticMaxage": 1800000,
17
+ "staticHtmlFileMaxage": 0,
18
+ "enableComboCache": true,
19
+ "enableCron": false,
20
+ "middleware": [],
21
+ "strictSSL": false,
22
+ "launchRouter": {},
23
+ "root": "public"
24
+ };
25
+ const _default = CONFIG;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: ()=>_default
8
+ });
9
+ const CONFIG = {};
10
+ const _default = CONFIG;
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ const { date } = require("@x-drive/utils");
3
+ const crossSpawn = require("cross-spawn");
4
+ colors = require("colors/safe");
5
+ const path = require("path");
6
+ const fs = require("fs");
7
+ /**输出内容名称 */ const X_LAB_STR = colors.bold(colors.cyan("🛸 XLab"));
8
+ /**
9
+ * 子进程对象
10
+ * @type child_process.ChildProcess
11
+ */ var childProcess = null;
12
+ /**
13
+ * 获取 chokidar
14
+ * @return {FSWatcher}
15
+ */ function getChokidar() {
16
+ try {
17
+ return require("chokidar");
18
+ } catch (e) {
19
+ return null;
20
+ }
21
+ }
22
+ /**构建 Spawn 启动参数 */ function buildSpawnOptions() {
23
+ const argvs = process.argv.slice(2);
24
+ const options = [
25
+ path.resolve(__dirname, "..", "server.js")
26
+ ].concat(argvs);
27
+ return options;
28
+ }
29
+ /**停止 */ function stop() {
30
+ if (childProcess) {
31
+ childProcess.kill("SIGTERM");
32
+ }
33
+ }
34
+ /**启动 */ function start() {
35
+ childProcess = crossSpawn("node", buildSpawnOptions(), {
36
+ "stdio": "inherit"
37
+ }).on("error", (err)=>{
38
+ console.error(err);
39
+ }).on("close", (code)=>{
40
+ if (Number(code) !== 0) {
41
+ const err = new Error(`子进程退出, Code: ${code}`);
42
+ err.code = code;
43
+ // TODO: 自动拉起来?
44
+ console.error(err);
45
+ }
46
+ }).once("exit", ()=>{
47
+ childProcess.removeAllListeners();
48
+ childProcess = null;
49
+ });
50
+ }
51
+ /**日志 */ function log(...rest) {
52
+ console.log.apply(console, [
53
+ X_LAB_STR,
54
+ colors.green(`[${date(new Date(), "Y-m-d H:i:s.M")}]`),
55
+ ...rest
56
+ ]);
57
+ }
58
+ /**
59
+ * 初始化状态
60
+ * @type {boolean}
61
+ */ var inited = false;
62
+ /**
63
+ * @typedef {object} WatchConfig
64
+ * @property {string[]=} paths 需要监控的目录
65
+ * @property {boolean=} enable 监控是否已启用
66
+ */ /**
67
+ * 启动文件 watch
68
+ * @param {FSWatcher} chokidar
69
+ * @param {WatchConfig} config 监控配置
70
+ * @param {number} wait 间隔时间
71
+ */ function watch(chokidar, config, wait = 250) {
72
+ let holding = false;
73
+ let initing = true;
74
+ chokidar.watch(config.paths).on("all", ()=>{
75
+ if (inited) {
76
+ if (!holding) {
77
+ holding = true;
78
+ setTimeout(async ()=>{
79
+ holding = false;
80
+ log("Restarting app...\n");
81
+ if (childProcess) {
82
+ childProcess.on("exit", start);
83
+ stop();
84
+ } else {
85
+ start();
86
+ }
87
+ }, wait);
88
+ }
89
+ } else {
90
+ if (initing) {
91
+ initing = false;
92
+ log("Watch 模式启动\n");
93
+ setTimeout(()=>{
94
+ inited = true;
95
+ }, wait);
96
+ }
97
+ }
98
+ });
99
+ }
100
+ /**
101
+ * 设置 watch 模式
102
+ * @param {WatchConfig} config
103
+ * @param {number} wait
104
+ */ function setup(config, wait = 250) {
105
+ const chokidar = getChokidar();
106
+ if (config && config.enable) {
107
+ if (chokidar) {
108
+ if (!config.paths) {
109
+ // 默认业务自定义服务端业务文件夹
110
+ const customDir = path.resolve(process.cwd(), "@server");
111
+ config.paths = [
112
+ customDir
113
+ ];
114
+ }
115
+ var stats = 0;
116
+ try {
117
+ for(let i = 0; i < config.paths.length; i++){
118
+ fs.statSync(config.paths[i]);
119
+ stats += 1;
120
+ }
121
+ } catch (e) {
122
+ log(e);
123
+ }
124
+ if (stats > 0) {
125
+ // 传递主进程 SIGTERM
126
+ process.on("SIGTERM", ()=>{
127
+ if (childProcess && childProcess.connected) {
128
+ childProcess.kill("SIGTERM");
129
+ }
130
+ process.exit(0);
131
+ });
132
+ watch(chokidar, config, wait);
133
+ start();
134
+ } else {
135
+ log("业务自定义目录不存在, watch 模式启动失败");
136
+ }
137
+ stats = null;
138
+ } else {
139
+ log("请将 chokidar 安装到开发依赖中以启用 watch 模式");
140
+ }
141
+ } else {
142
+ log("配置不存在或 watch.enable 为 false, watch 模式启动失败\n", config);
143
+ }
144
+ }
145
+ module.exports = setup;
package/dist/bin/xlab ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env node
2
+
3
+ const argv = require("minimist")(process.argv.slice(2));
4
+ const { merge } = require("@x-drive/utils");
5
+ const Liftoff = require("liftoff");
6
+
7
+ const cli = new Liftoff({
8
+ "name": "x-lab"
9
+ , "processTitle": "X Lab"
10
+ , "moduleName": "xlab"
11
+ , "configName": "xlab-config"
12
+ , "extensions": {
13
+ ".js": null
14
+ }
15
+ });
16
+
17
+ const hasWatch = argv.w || argv.watch;
18
+
19
+ cli.launch(
20
+ {
21
+ "cwd": argv.r || argv.root
22
+ , "configPath": argv.f || argv.file
23
+ }
24
+ , function (env) {
25
+ let config = {
26
+ "watch": {
27
+ "enable": false
28
+ }
29
+ }
30
+ if (env.configPath) {
31
+ try {
32
+ let customConfig = require(env.configPath);
33
+ if (customConfig) {
34
+ merge(config, customConfig);
35
+ }
36
+ } catch (e) { }
37
+ }
38
+ if (hasWatch) {
39
+ config.watch.enable = true;
40
+ }
41
+ if (config.watch && config.watch.enable) {
42
+ const watch = require("./watch");
43
+ watch(config.watch);
44
+ } else {
45
+ const server = require("../server");
46
+ server.boot();
47
+ }
48
+ }
49
+ );
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: ()=>_default
8
+ });
9
+ function onClean(ctx) {
10
+ var cookies = ctx.query.c && ctx.query.c.split(",") || null;
11
+ if (!cookies) {
12
+ cookies = [];
13
+ (ctx.headers.cookie || "").split("; ").forEach((item)=>{
14
+ cookies.push(item.split("=")[0]);
15
+ });
16
+ }
17
+ let len = 0;
18
+ if (cookies && cookies.length) {
19
+ let cookiePath = "/";
20
+ let expires = new Date(-1);
21
+ let httpOnly = false;
22
+ cookies.forEach((cookie)=>{
23
+ if (cookie) {
24
+ ctx.cookies.set(cookie, "", {
25
+ "path": cookiePath,
26
+ expires,
27
+ httpOnly
28
+ });
29
+ len += 1;
30
+ }
31
+ });
32
+ }
33
+ ctx.body = `Clean ${len}`;
34
+ }
35
+ const _default = onClean;
@@ -0,0 +1,32 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="HandheldFriendly" content="true">
6
+ <meta name="apple-mobile-web-app-capable" content="yes">
7
+ <meta name="format-detection" content="telephone=no" />
8
+ <script type="text/javascript">
9
+ (function(){
10
+ var el = document.createElement("p");
11
+ var cookies = {cookies};
12
+ var expires = (new Date(-1)).toUTCString();
13
+ var len = 0;
14
+ if (cookies && cookies.length) {
15
+ cookies.forEach(item => {
16
+ if (item) {
17
+ document.cookie = item + "=''; path=/;expires=" + expires;
18
+ len += 1;
19
+ }
20
+ });
21
+ }
22
+ el.innerHTML = "Clean " + len;
23
+ setTimeout(function(){
24
+ document.body.append(el);
25
+ el = null;
26
+ }, 100)
27
+ })()
28
+ </script>
29
+ </head>
30
+ <body>
31
+ </body>
32
+ </html>
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: ()=>_default
8
+ });
9
+ const _path = /*#__PURE__*/ _interopRequireDefault(require("path"));
10
+ const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs"));
11
+ function _interopRequireDefault(obj) {
12
+ return obj && obj.__esModule ? obj : {
13
+ default: obj
14
+ };
15
+ }
16
+ const JS_TPL = _fs.default.readFileSync(_path.default.resolve(__dirname, "./@tpls/js.tpl"), "utf8");
17
+ function onJsClean(ctx) {
18
+ var cookies = ctx.query.c;
19
+ cookies = cookies && cookies.split(",") || null;
20
+ if (!cookies) {
21
+ cookies = [];
22
+ (ctx.headers.cookie || "").split("; ").forEach((item)=>{
23
+ if (item) {
24
+ cookies.push(item.split("=")[0]);
25
+ }
26
+ });
27
+ }
28
+ ctx.body = JS_TPL.replace("{cookies}", JSON.stringify(cookies));
29
+ }
30
+ const _default = onJsClean;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: ()=>_default
8
+ });
9
+ const _cluster = /*#__PURE__*/ _interopRequireWildcard(require("./components/cluster"));
10
+ const _config = require("./config");
11
+ const _cluster1 = /*#__PURE__*/ _interopRequireDefault(require("cluster"));
12
+ const _server = /*#__PURE__*/ _interopRequireDefault(require("./server"));
13
+ const _os = /*#__PURE__*/ _interopRequireDefault(require("os"));
14
+ function _interopRequireDefault(obj) {
15
+ return obj && obj.__esModule ? obj : {
16
+ default: obj
17
+ };
18
+ }
19
+ function _getRequireWildcardCache(nodeInterop) {
20
+ if (typeof WeakMap !== "function") return null;
21
+ var cacheBabelInterop = new WeakMap();
22
+ var cacheNodeInterop = new WeakMap();
23
+ return (_getRequireWildcardCache = function(nodeInterop) {
24
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
25
+ })(nodeInterop);
26
+ }
27
+ function _interopRequireWildcard(obj, nodeInterop) {
28
+ if (!nodeInterop && obj && obj.__esModule) {
29
+ return obj;
30
+ }
31
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
32
+ return {
33
+ default: obj
34
+ };
35
+ }
36
+ var cache = _getRequireWildcardCache(nodeInterop);
37
+ if (cache && cache.has(obj)) {
38
+ return cache.get(obj);
39
+ }
40
+ var newObj = {};
41
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
42
+ for(var key in obj){
43
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
44
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
45
+ if (desc && (desc.get || desc.set)) {
46
+ Object.defineProperty(newObj, key, desc);
47
+ } else {
48
+ newObj[key] = obj[key];
49
+ }
50
+ }
51
+ }
52
+ newObj.default = obj;
53
+ if (cache) {
54
+ cache.set(obj, newObj);
55
+ }
56
+ return newObj;
57
+ }
58
+ const logger = log.getLogger("cluster");
59
+ const CPUnum = _os.default.cpus().length;
60
+ const config = (0, _config.get)();
61
+ /**
62
+ * 消息处理函数
63
+ * @param msg 消息配置对象
64
+ */ function masterMessageHandler(msg) {
65
+ if (msg && msg.cmd) {
66
+ let handler = _cluster.get(msg.cmd);
67
+ if (handler) {
68
+ let args = msg.args || [];
69
+ args.push(msg.returnData);
70
+ let re = handler.apply(handler, args);
71
+ if (msg.wid) {
72
+ let worker = _cluster1.default.workers[msg.wid];
73
+ if (worker) {
74
+ worker.send({
75
+ "cmd": msg.cmd,
76
+ "data": re,
77
+ "returnData": msg.returnData
78
+ });
79
+ }
80
+ worker = null;
81
+ }
82
+ args = null;
83
+ }
84
+ }
85
+ }
86
+ /**尝试以 cluster 模式启动服务 */ function start() {
87
+ var server;
88
+ var serverListenConf = {
89
+ "port": config.port
90
+ };
91
+ if (config.ip) {
92
+ serverListenConf.host = config.ip;
93
+ }
94
+ if (config.isMaster) {
95
+ if (config.workers) {
96
+ // 小于使用数则取一半
97
+ let num = CPUnum < config.workers ? Math.ceil(CPUnum / 2) : config.workers;
98
+ for(var i = 0; i < num; i++){
99
+ _cluster1.default.fork();
100
+ }
101
+ // if(!config.isProd){
102
+ _cluster1.default.on("listening", function(worker, address) {
103
+ masterLog("cluster", "info", "\tWorker ", worker.process.pid, " online, Address: ", address.address, ":", address.port);
104
+ });
105
+ _cluster1.default.on("message", masterMessageHandler);
106
+ // }
107
+ _cluster1.default.on("exit", function(worker) {
108
+ logger.warn("Worker " + worker.process.pid + " is dead!");
109
+ _cluster1.default.fork();
110
+ });
111
+ } else {
112
+ server = _server.default.listen(serverListenConf);
113
+ }
114
+ masterLog("cluster", "info", "[%s] online,listening on %s port %d", config.env, config.ip || "localhost", config.port);
115
+ } else {
116
+ server = _server.default.listen(serverListenConf);
117
+ }
118
+ return server;
119
+ }
120
+ const _default = start;