abler-api 0.1.25 → 0.1.28

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.
@@ -1,18 +1,20 @@
1
- import require$$0$1 from 'crypto';
1
+ import require$$0 from 'crypto';
2
2
  import require$$1 from 'abler-util';
3
3
  import require$$2 from 'abler-db';
4
4
  import require$$3 from 'abler-net';
5
- import require$$0$2 from 'fs';
5
+ import require$$0$1 from 'fs';
6
6
  import require$$1$1 from 'path';
7
+ import require$$1$2 from 'abler-messenger';
8
+ import require$$0$2 from 'node-cron';
7
9
 
8
- const crypto = require$$0$1;
10
+ const crypto = require$$0;
9
11
  const ppUtil$4 = require$$1.ppUtil;
10
12
  const {
11
13
  dbUtil,
12
14
  kvStorage
13
15
  } = require$$2;
14
16
  const netUtil$1 = require$$3;
15
- let conf$2, appSetting$1, err$1, dbSql;
17
+ let conf$3, appSetting$1, err$2, dbSql;
16
18
  const pnToken = "access_token",
17
19
  hnToken = pnToken,
18
20
  pnApiKey = "apiKey",
@@ -23,7 +25,7 @@ pnApiSecret = "apiSecret",
23
25
  const MD5 = ppUtil$4.MD5,
24
26
  moveProperty = ppUtil$4.moveProperty;
25
27
 
26
- class apiUtil$1 {
28
+ class apiUtil$2 {
27
29
  static debugFlag = ppUtil$4.newGuid(); //应用必须设置,否则谁也不知道是啥
28
30
 
29
31
  static testFlag = ppUtil$4.newGuid();
@@ -31,11 +33,11 @@ class apiUtil$1 {
31
33
 
32
34
  static config(appConfig, appErrCfg, appDbSql) {
33
35
  ppUtil$4.config(appConfig, appErrCfg);
34
- conf$2 = appConfig;
35
- appSetting$1 = conf$2?.appSetting;
36
- err$1 = appErrCfg, dbSql = appDbSql;
37
- apiUtil$1.debugFlag = appSetting$1?.debugFlag || apiUtil$1.debugFlag;
38
- apiUtil$1.testFlag = appSetting$1?.testFlag || apiUtil$1.testFlag; // apiUtil.apiCallRecSaver = apiCallRecSaver;
36
+ conf$3 = appConfig;
37
+ appSetting$1 = conf$3?.appSetting;
38
+ err$2 = appErrCfg, dbSql = appDbSql;
39
+ apiUtil$2.debugFlag = appSetting$1?.debugFlag || apiUtil$2.debugFlag;
40
+ apiUtil$2.testFlag = appSetting$1?.testFlag || apiUtil$2.testFlag; // apiUtil.apiCallRecSaver = apiCallRecSaver;
39
41
  } //#region ===== 需要应用系统重写的方法
40
42
 
41
43
  /**
@@ -123,7 +125,7 @@ class apiUtil$1 {
123
125
  req._requestParams = Object.assign(req.params, req._requestParams);
124
126
  }
125
127
 
126
- apiUtil$1.setParamsFunctions(req._requestParams);
128
+ apiUtil$2.setParamsFunctions(req._requestParams);
127
129
  }
128
130
 
129
131
  return req._requestParams;
@@ -134,11 +136,11 @@ class apiUtil$1 {
134
136
  return req.tokenData;
135
137
  }
136
138
 
137
- let params = apiUtil$1.extractParams(req);
139
+ let params = apiUtil$2.extractParams(req);
138
140
  let tokenData = {
139
141
  apiKey: req.headers[hnApiKey] || params[pnApiKey],
140
142
  apiSecret: req.headers[hnApiSecret] || params[pnApiSecret],
141
- clientIp: apiUtil$1.getClientIp(req)
143
+ clientIp: apiUtil$2.getClientIp(req)
142
144
  };
143
145
  return tokenData;
144
146
  }
@@ -155,7 +157,7 @@ class apiUtil$1 {
155
157
  let result = +this[name];
156
158
 
157
159
  if (typeof result !== "number" || result < minValue || result > maxValue) {
158
- throw [err$1.INVALID_PARAM, `参数 ${name} 必须是 ${minValue} ~ ${maxValue} 之间的数字`];
160
+ throw [err$2.INVALID_PARAM, `参数 ${name} 必须是 ${minValue} ~ ${maxValue} 之间的数字`];
159
161
  }
160
162
 
161
163
  return result;
@@ -225,7 +227,7 @@ class apiUtil$1 {
225
227
 
226
228
  static apiFail(error, req) {
227
229
  configNeeded();
228
- let response = err$1.ERROR(error, err$1.errorLangParamFlag + ppUtil$4.getMsgLang(req));
230
+ let response = err$2.ERROR(error, err$2.errorLangParamFlag + ppUtil$4.getMsgLang(req));
229
231
  response.datetime = new Date();
230
232
 
231
233
  if (req && req.headers) {
@@ -247,8 +249,8 @@ class apiUtil$1 {
247
249
 
248
250
 
249
251
  static spoApiSucc(data, req) {
250
- let params = apiUtil$1.extractParams(req);
251
- return apiUtil$1.apiSuccess(data, req, params.spOrderNum);
252
+ let params = apiUtil$2.extractParams(req);
253
+ return apiUtil$2.apiSuccess(data, req, params.spOrderNum);
252
254
  }
253
255
  /**
254
256
  * 生成面向服务商的API失败返回结果
@@ -259,8 +261,8 @@ class apiUtil$1 {
259
261
 
260
262
 
261
263
  static spoApiFail(error, req) {
262
- let params = apiUtil$1.extractParams(req);
263
- return apiUtil$1.apiFail(error, req, params.spOrderNum);
264
+ let params = apiUtil$2.extractParams(req);
265
+ return apiUtil$2.apiFail(error, req, params.spOrderNum);
264
266
  }
265
267
  /**
266
268
  * API 服务结束,发送响应
@@ -297,10 +299,10 @@ class apiUtil$1 {
297
299
  static async responseOf(response, promise) {
298
300
  promise.then(function (data) {
299
301
  // console.log('RES:', apiSuccess(data));
300
- if (!response.finished) response.send(apiUtil$1.apiSuccess(data, response.req));
302
+ if (!response.finished) response.send(apiUtil$2.apiSuccess(data, response.req));
301
303
  }, function (error) {
302
304
  console.log('ERROR:', error);
303
- if (!response.finished) response.send(apiUtil$1.apiFail(error, response.req));
305
+ if (!response.finished) response.send(apiUtil$2.apiFail(error, response.req));
304
306
  });
305
307
  }
306
308
  /**
@@ -312,16 +314,16 @@ class apiUtil$1 {
312
314
 
313
315
  static async spoApiResponse(response, promise) {
314
316
  promise.then(function (result) {
315
- let responseData = apiUtil$1.spoApiSucc(result, response.req);
317
+ let responseData = apiUtil$2.spoApiSucc(result, response.req);
316
318
 
317
- apiUtil$1._saveApiCallRec(response.req.apiCallRec, responseData);
319
+ apiUtil$2._saveApiCallRec(response.req.apiCallRec, responseData);
318
320
 
319
321
  if (!response.finished) response.send(responseData);
320
322
  }, function (error) {
321
323
  console.log('ERROR:', error);
322
- let responseData = apiUtil$1.spoApiFail(error, response.req);
324
+ let responseData = apiUtil$2.spoApiFail(error, response.req);
323
325
 
324
- apiUtil$1._saveApiCallRec(response.req.apiCallRec, responseData);
326
+ apiUtil$2._saveApiCallRec(response.req.apiCallRec, responseData);
325
327
 
326
328
  if (!response.finished) response.send(responseData);
327
329
  });
@@ -338,7 +340,7 @@ class apiUtil$1 {
338
340
  req.headers.timestamp = new Date().valueOf(); // let options = {replacements: {}};
339
341
 
340
342
  let options = {};
341
- let parameters = apiUtil$1.extractParams(req);
343
+ let parameters = apiUtil$2.extractParams(req);
342
344
 
343
345
  for (let qryParam in parameters) {
344
346
  if (qryParam !== 'token') {
@@ -370,7 +372,7 @@ class apiUtil$1 {
370
372
  // }
371
373
 
372
374
  options.userInfo = req.userInfo;
373
- return apiUtil$1.setOptionsPropFuncions(options, res);
375
+ return apiUtil$2.setOptionsPropFuncions(options, res);
374
376
  }
375
377
  /**
376
378
  * 为API请求 options 设置属性
@@ -435,7 +437,7 @@ class apiUtil$1 {
435
437
  let token = req.headers[hnToken] || req.headers['x-access-token']; //向后兼容
436
438
 
437
439
  if (!token) {
438
- let params = apiUtil$1.extractParams(req);
440
+ let params = apiUtil$2.extractParams(req);
439
441
  token = params[pnToken];
440
442
 
441
443
  if (token) {
@@ -446,12 +448,12 @@ class apiUtil$1 {
446
448
  delete params.token;
447
449
  } else {
448
450
  // 如果没有token,则返回错误
449
- console.log(err$1.TOKEN_NEEDED);
451
+ console.log(err$2.TOKEN_NEEDED);
450
452
 
451
453
  if (res) {
452
- res.send(err$1.ERROR(err$1.TOKEN_NEEDED));
454
+ res.send(err$2.ERROR(err$2.TOKEN_NEEDED));
453
455
  } else if (!noErr) {
454
- throw err$1.TOKEN_NEEDED;
456
+ throw err$2.TOKEN_NEEDED;
455
457
  }
456
458
  }
457
459
  }
@@ -470,8 +472,8 @@ class apiUtil$1 {
470
472
 
471
473
  static async checkInternalToken(req) {
472
474
  // return await checkInternalToken(req);
473
- const params = apiUtil$1.extractParams(req);
474
- req.accessToken = req.accessToken || apiUtil$1.extractToken(req);
475
+ const params = apiUtil$2.extractParams(req);
476
+ req.accessToken = req.accessToken || apiUtil$2.extractToken(req);
475
477
 
476
478
  if (req.accessToken === MD5(ppUtil$4.idNumDisturbing)) {
477
479
  //todo: 检查IP
@@ -494,7 +496,7 @@ class apiUtil$1 {
494
496
  return true;
495
497
  } else {
496
498
  // console.log('token error.', req.accessToken);
497
- throw err$1.TOKEN_INVALID;
499
+ throw err$2.TOKEN_INVALID;
498
500
  }
499
501
  }
500
502
  /**
@@ -505,16 +507,16 @@ class apiUtil$1 {
505
507
 
506
508
 
507
509
  static async checkRequestToken(req) {
508
- req.accessToken = req.accessToken || apiUtil$1.extractToken(req);
509
- const tokenKey = apiUtil$1.userTokenStoreKey(req.accessToken);
510
- const expireTime = apiUtil$1.tokenExpireTime(req);
511
- return await apiUtil$1.restoreTokenData(tokenKey, expireTime).then(async function (data) {
512
- req.userInfo = apiUtil$1.setUserIdNo(data, data._idNo);
510
+ req.accessToken = req.accessToken || apiUtil$2.extractToken(req);
511
+ const tokenKey = apiUtil$2.userTokenStoreKey(req.accessToken);
512
+ const expireTime = apiUtil$2.tokenExpireTime(req);
513
+ return await apiUtil$2.restoreTokenData(tokenKey, expireTime).then(async function (data) {
514
+ req.userInfo = apiUtil$2.setUserIdNo(data, data._idNo);
513
515
  if (req.tokenValidater) await req.tokenValidater(req.userInfo, req);
514
516
  return true;
515
517
  }, async function (e) {
516
518
  // 如果给定的token不存在,看看是不是平台内部调用
517
- return await apiUtil$1.checkInternalToken(req);
519
+ return await apiUtil$2.checkInternalToken(req);
518
520
  });
519
521
  }
520
522
  /**
@@ -526,7 +528,7 @@ class apiUtil$1 {
526
528
 
527
529
  static isDebugMode(req) {
528
530
  if (req.__debug__ === undefined) {
529
- let dbgToken = req.headers['__debug__'] || req.headers[apiUtil$1.debugFlag];
531
+ let dbgToken = req.headers['__debug__'] || req.headers[apiUtil$2.debugFlag];
530
532
 
531
533
  if (dbgToken) {
532
534
  let envId = process.env.ECS_DEPLOY_ID;
@@ -548,11 +550,11 @@ class apiUtil$1 {
548
550
 
549
551
  static isTestMode(req) {
550
552
  if (req.__postman__ === undefined) {
551
- let dbgToken = req.headers["__postman__"] || req.headers[apiUtil$1.testFlag];
553
+ let dbgToken = req.headers["__postman__"] || req.headers[apiUtil$2.testFlag];
552
554
 
553
555
  if (dbgToken) {
554
556
  let envId = process.env.ECS_DEPLOY_ID;
555
- let testToken = MD5(req.headers.timestamp, apiUtil$1.extractToken(req, null, true) || req.headers.apikey);
557
+ let testToken = MD5(req.headers.timestamp, apiUtil$2.extractToken(req, null, true) || req.headers.apikey);
556
558
  req.__postman__ = dbgToken === testToken && (envId.indexOf("myfacesign.com") < 0 || envId.indexOf(".dev.") > 0);
557
559
  } else {
558
560
  req.__postman__ = false;
@@ -569,7 +571,7 @@ class apiUtil$1 {
569
571
 
570
572
 
571
573
  static tokenExpireTime(req) {
572
- return apiUtil$1.isDebugMode(req) ? 30 * 24 * 60 * 60 : apiUtil$1.isTestMode(req) ? 4 * 60 * 60 : appSetting$1.tokenExpireTime;
574
+ return apiUtil$2.isDebugMode(req) ? 30 * 24 * 60 * 60 : apiUtil$2.isTestMode(req) ? 4 * 60 * 60 : appSetting$1.tokenExpireTime;
573
575
  }
574
576
  /**
575
577
  * 获取用户令牌保存键
@@ -612,7 +614,7 @@ class apiUtil$1 {
612
614
  static setUserIdNo(userInfo, idNum) {
613
615
  if (userInfo && idNum) {
614
616
  userInfo._idNo = idNum;
615
- userInfo.isHKIC = apiUtil$1.checkIsHKIC(idNum);
617
+ userInfo.isHKIC = apiUtil$2.checkIsHKIC(idNum);
616
618
  }
617
619
 
618
620
  return userInfo;
@@ -629,7 +631,7 @@ class apiUtil$1 {
629
631
 
630
632
  static async storeToken(token, tokenData, dataId, req) {
631
633
  // let timeout = tokenData.clientIp.substring(0, 8) == "192.168." ? 90 * 24 : 1;
632
- let timeout = apiUtil$1.tokenExpireTime(req);
634
+ let timeout = apiUtil$2.tokenExpireTime(req);
633
635
 
634
636
  if (req.certPublicKey) {
635
637
  tokenData.certPublicKey = req.certPublicKey;
@@ -777,7 +779,7 @@ class apiUtil$1 {
777
779
  return certInfo;
778
780
  }).catch(e => {
779
781
  console.log('获取企业证书失败:\n', e);
780
- throw [err$1.ACCESS_REFUSED, `获取企业证书失败:${err$1.ERROR(e).message}`];
782
+ throw [err$2.ACCESS_REFUSED, `获取企业证书失败:${err$2.ERROR(e).message}`];
781
783
  });
782
784
  }
783
785
  /**
@@ -791,27 +793,27 @@ class apiUtil$1 {
791
793
  static async verifyApiSignature(tokenData, req) {
792
794
  try {
793
795
  if (!req.headers.timestamp) {
794
- throw [err$1.ACCESS_REFUSED, `必须在请求头中设置时戳`];
796
+ throw [err$2.ACCESS_REFUSED, `必须在请求头中设置时戳`];
795
797
  }
796
798
 
797
799
  let timestamp = parseInt(req.headers.timestamp);
798
800
  let currentTime = new Date().valueOf();
799
- let maxTimeDiff = apiUtil$1.isDebugMode(req) ? 7 * 24 * 3600 : apiUtil$1.isTestMode(req) ? 4 * 3600 : 100; // 100
801
+ let maxTimeDiff = apiUtil$2.isDebugMode(req) ? 7 * 24 * 3600 : apiUtil$2.isTestMode(req) ? 4 * 3600 : 100; // 100
800
802
 
801
803
  if (timestamp.toString() == "NaN" || currentTime < timestamp - 5000 || currentTime - timestamp > maxTimeDiff * 1000) {
802
- throw [err$1.ACCESS_REFUSED, `时戳(${timestamp})无效,当前时戳:${currentTime},时差 ${(currentTime - timestamp) / 1000}秒`];
804
+ throw [err$2.ACCESS_REFUSED, `时戳(${timestamp})无效,当前时戳:${currentTime},时差 ${(currentTime - timestamp) / 1000}秒`];
803
805
  }
804
806
 
805
807
  let signature = req.headers.signature;
806
808
 
807
809
  if (!signature) {
808
- throw [err$1.ACCESS_REFUSED, `必须在请求头中提供签名`];
810
+ throw [err$2.ACCESS_REFUSED, `必须在请求头中提供签名`];
809
811
  }
810
812
 
811
- let signData = apiUtil$1.extractToken(req, null, true) || tokenData.apiKey;
813
+ let signData = apiUtil$2.extractToken(req, null, true) || tokenData.apiKey;
812
814
  signData += timestamp;
813
815
 
814
- if (apiUtil$1.isDebugMode(req) || apiUtil$1.isTestMode(req)) {
816
+ if (apiUtil$2.isDebugMode(req) || apiUtil$2.isTestMode(req)) {
815
817
  let publicKey = req.headers.publickey || req.body.publicKey || req.query.publicKey;
816
818
 
817
819
  if (publicKey) {
@@ -826,16 +828,16 @@ class apiUtil$1 {
826
828
  return await verifyResult;
827
829
  }
828
830
 
829
- return apiUtil$1.getCompanyCertificate(tokenData.apiKey).then(info => {
831
+ return apiUtil$2.getCompanyCertificate(tokenData.apiKey).then(info => {
830
832
  tokenData.certPublicKey = info.certLiving;
831
833
  tokenData.certPublicKeySpare = info.certSpare;
832
834
  tokenData.certLivingId = info.certLivingId;
833
835
  tokenData.certSpareId = info.certSpareId;
834
836
  req.certPublicKey = info.certLiving;
835
- let token = apiUtil$1.extractToken(req, null, true);
837
+ let token = apiUtil$2.extractToken(req, null, true);
836
838
 
837
839
  if (token) {
838
- apiUtil$1.storeToken(apiUtil$1.apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
840
+ apiUtil$2.storeToken(apiUtil$2.apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
839
841
  }
840
842
  }).then(() => {
841
843
  return doVerify(signData, signature, tokenData.certPublicKey);
@@ -860,7 +862,7 @@ class apiUtil$1 {
860
862
 
861
863
  if (!tokenData.certPublicKeySpare) {
862
864
  throw {
863
- eo: err$1.ACCESS_REFUSED,
865
+ eo: err$2.ACCESS_REFUSED,
864
866
  msgArgv: "签名验证异常",
865
867
  data: e
866
868
  };
@@ -897,10 +899,10 @@ class apiUtil$1 {
897
899
  delete tokenData.certLivingId;
898
900
  delete tokenData.certSpareId;
899
901
  delete tokenData.certPublicKeySpare;
900
- let token = apiUtil$1.extractToken(req);
902
+ let token = apiUtil$2.extractToken(req);
901
903
 
902
904
  if (token) {
903
- apiUtil$1.storeToken(apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
905
+ apiUtil$2.storeToken(apiTokenStoreKey(token), tokenData, tokenData.apiKey, req);
904
906
  }
905
907
 
906
908
  console.log(`公司(${tokenData.apiKey})备用证书成功转换为正式证书`);
@@ -909,7 +911,7 @@ class apiUtil$1 {
909
911
  } catch (e) {
910
912
  console.log("SPO服务签名验证异常(备用证书), ", e);
911
913
  throw {
912
- eo: err$1.ACCESS_REFUSED,
914
+ eo: err$2.ACCESS_REFUSED,
913
915
  msgArgv: "签名验证异常(spare)",
914
916
  data: e
915
917
  };
@@ -918,7 +920,7 @@ class apiUtil$1 {
918
920
 
919
921
  if (!verifyOK) {
920
922
  console.log("SPO服务签名验证失败, tokenData: ", tokenData);
921
- throw [err$1.ACCESS_REFUSED, "签名验证未通过"];
923
+ throw [err$2.ACCESS_REFUSED, "签名验证未通过"];
922
924
  }
923
925
 
924
926
  return verifyOK;
@@ -934,32 +936,32 @@ class apiUtil$1 {
934
936
 
935
937
  static async checkApiCallValid(tokenData, req) {
936
938
  if (!tokenData.companyInfo) {
937
- tokenData.companyInfo = await apiUtil$1.queryCompanyInfo(tokenData.apiKey, true).catch(e => {
939
+ tokenData.companyInfo = await apiUtil$2.queryCompanyInfo(tokenData.apiKey, true).catch(e => {
938
940
  console.log("执行企业信息查询发生异常", e);
939
- throw [err$1.API_KEY_INVALID, "执行企业信息查询发生异常:" + e.message || ""];
941
+ throw [err$2.API_KEY_INVALID, "执行企业信息查询发生异常:" + e.message || ""];
940
942
  });
941
943
  }
942
944
 
943
945
  const companyInfo = tokenData.companyInfo;
944
946
 
945
947
  if (companyInfo != null) {
946
- let secret = apiUtil$1._getApiSecret(tokenData.apiKey);
948
+ let secret = apiUtil$2._getApiSecret(tokenData.apiKey);
947
949
 
948
- if (secret !== tokenData.apiSecret) throw err$1.API_SCREPT_INVALID; // 不再检查 IP 白名单,改为验证证书签名
950
+ if (secret !== tokenData.apiSecret) throw err$2.API_SCREPT_INVALID; // 不再检查 IP 白名单,改为验证证书签名
949
951
  // console.log("fromIp:", tokenData.clientIp, "ipWhiteList:", companyInfo.ipWhiteList);
950
952
  // let whiteList = companyInfo.ipWhiteList || "";
951
953
  // // 没有设置ip白名单的就不检查了
952
954
  // if (whiteList == "" || ipMatched(tokenData.clientIp, whiteList + ",127.0.0.1,1"))
953
955
 
954
- if (apiUtil$1.signatureVerified()) return companyInfo;
955
- return apiUtil$1.verifyApiSignature(tokenData, req).then(x => {
956
+ if (apiUtil$2.signatureVerified()) return companyInfo;
957
+ return apiUtil$2.verifyApiSignature(tokenData, req).then(x => {
956
958
  return companyInfo;
957
959
  }, e => {
958
960
  throw e;
959
961
  });
960
962
  }
961
963
 
962
- throw [err$1.API_KEY_INVALID, tokenData.apiKey];
964
+ throw [err$2.API_KEY_INVALID, tokenData.apiKey];
963
965
  }
964
966
  /**
965
967
  * 检查令牌数据是否存在
@@ -1010,7 +1012,7 @@ class apiUtil$1 {
1010
1012
  paramExists = typeof params[paramName] != 'undefined' || typeof params[paramName + paramSufix] != 'undefined';
1011
1013
  }
1012
1014
 
1013
- if (!paramExists) return ppUtil$4.errorPormise(err$1.ERROR(err$1.PARAMETER_NEEDED, paramName));
1015
+ if (!paramExists) return ppUtil$4.errorPormise(err$2.ERROR(err$2.PARAMETER_NEEDED, paramName));
1014
1016
  }
1015
1017
 
1016
1018
  return Promise.resolve(paramSufix);
@@ -1058,7 +1060,7 @@ class apiUtil$1 {
1058
1060
 
1059
1061
 
1060
1062
  static async hostIsMySelf(host, req) {
1061
- let clientIp = apiUtil$1.getClientIp(req);
1063
+ let clientIp = apiUtil$2.getClientIp(req);
1062
1064
  return ppUtil$4.getMyIp({
1063
1065
  hosts: [host, clientIp]
1064
1066
  });
@@ -1073,13 +1075,13 @@ class apiUtil$1 {
1073
1075
  static async checkForwardsHost(options) {
1074
1076
  configNeeded();
1075
1077
  const params = options.replacements;
1076
- const myEnvHosts = apiUtil$1.getEnvHosts(params);
1078
+ const myEnvHosts = apiUtil$2.getEnvHosts(params);
1077
1079
  const myIp = ppUtil$4.getMyIp();
1078
1080
  const host = params.host || myIp;
1079
- if (!myEnvHosts.hosts.contains(host)) throw [err$1.ACCESS_REFUSED, `环境${conf$2.envId}貌似无此主机:${params.host}`];
1081
+ if (!myEnvHosts.hosts.contains(host)) throw [err$2.ACCESS_REFUSED, `环境${conf$3.envId}貌似无此主机:${params.host}`];
1080
1082
 
1081
- if (!apiUtil$1.hostIsMySelf(host, options._res.req)) {
1082
- let result = await apiUtil$1.forwardsTo(host, myEnvHosts.port, params, options._res.req, myIp);
1083
+ if (!apiUtil$2.hostIsMySelf(host, options._res.req)) {
1084
+ let result = await apiUtil$2.forwardsTo(host, myEnvHosts.port, params, options._res.req, myIp);
1083
1085
 
1084
1086
  options._res.send(result);
1085
1087
 
@@ -1115,7 +1117,7 @@ class apiUtil$1 {
1115
1117
 
1116
1118
  if (result.status !== 200) {
1117
1119
  console.log(`访问 ${reqOptions.url} 出错`, result.status, result.res.statusMessage);
1118
- throw [err$1.EXCEPTION, `[${result.status}] - ${result.res.statusMessage}`];
1120
+ throw [err$2.EXCEPTION, `[${result.status}] - ${result.res.statusMessage}`];
1119
1121
  }
1120
1122
 
1121
1123
  return result.data;
@@ -1131,7 +1133,7 @@ class apiUtil$1 {
1131
1133
  let keys = Array.isArray(keyPath) ? keyPath : keyPath.split(".");
1132
1134
  let parentKey = "";
1133
1135
  let key = "config";
1134
- let value = conf$2;
1136
+ let value = conf$3;
1135
1137
  let parent = null;
1136
1138
 
1137
1139
  for (let i = 0; i < keys.length; i++) {
@@ -1141,7 +1143,7 @@ class apiUtil$1 {
1141
1143
  value = parent[key];
1142
1144
 
1143
1145
  if (value === undefined) {
1144
- throw [err$1.INVALID_PARAM, `无此配置项: ${key}`];
1146
+ throw [err$2.INVALID_PARAM, `无此配置项: ${key}`];
1145
1147
  }
1146
1148
  }
1147
1149
 
@@ -1161,10 +1163,10 @@ class apiUtil$1 {
1161
1163
 
1162
1164
  static async $checkToken(req, res, next) {
1163
1165
  try {
1164
- await apiUtil$1.checkRequestToken(req);
1166
+ await apiUtil$2.checkRequestToken(req);
1165
1167
  await next();
1166
1168
  } catch (e) {
1167
- res.send(err$1.ERROR(e));
1169
+ res.send(err$2.ERROR(e));
1168
1170
  }
1169
1171
 
1170
1172
  return false;
@@ -1181,7 +1183,7 @@ class apiUtil$1 {
1181
1183
  let token = req.headers["access_token"] || req.headers['x-access-token']; //向后兼容
1182
1184
 
1183
1185
  if (!token) {
1184
- let params = apiUtil$1.extractParams(req);
1186
+ let params = apiUtil$2.extractParams(req);
1185
1187
  token = params["access_token"];
1186
1188
 
1187
1189
  if (token) {
@@ -1204,15 +1206,15 @@ class apiUtil$1 {
1204
1206
 
1205
1207
  try {
1206
1208
  if (extractToken(req, res)) {
1207
- await apiUtil$1.restoreTokenData(apiUtil$1.userTokenStoreKey(req.accessToken), apiUtil$1.tokenExpireTime(req)).then(function (data) {
1208
- req.userInfo = apiUtil$1.setUserIdNo(data, data._idNo);
1209
+ await apiUtil$2.restoreTokenData(apiUtil$2.userTokenStoreKey(req.accessToken), apiUtil$2.tokenExpireTime(req)).then(function (data) {
1210
+ req.userInfo = apiUtil$2.setUserIdNo(data, data._idNo);
1209
1211
  }, function (e) {//no token
1210
1212
  });
1211
1213
  }
1212
1214
 
1213
1215
  return true;
1214
1216
  } catch (e) {
1215
- res.send(err$1.ERROR(e));
1217
+ res.send(err$2.ERROR(e));
1216
1218
  return false;
1217
1219
  }
1218
1220
  }
@@ -1235,7 +1237,7 @@ class apiUtil$1 {
1235
1237
  req.isMobile = true;
1236
1238
 
1237
1239
  if (!req.signatureVerified) {
1238
- let params = apiUtil$1.extractParams(req);
1240
+ let params = apiUtil$2.extractParams(req);
1239
1241
  moveProperty(params, req.headers, "access_token");
1240
1242
  moveProperty(params, req.headers, "timestamp");
1241
1243
 
@@ -1256,25 +1258,25 @@ class apiUtil$1 {
1256
1258
 
1257
1259
  static $checkApiKeyOld(req, res, next) {
1258
1260
  //检查post的信息或者url查询参数或者头信息
1259
- let tokenData = apiUtil$1.extractTokenData(req);
1260
- let params = apiUtil$1.extractParams(req);
1261
- apiUtil$1.createApiCallRec(tokenData, req);
1261
+ let tokenData = apiUtil$2.extractTokenData(req);
1262
+ let params = apiUtil$2.extractParams(req);
1263
+ apiUtil$2.createApiCallRec(tokenData, req);
1262
1264
  let errResponse = null;
1263
1265
 
1264
1266
  if (!tokenData.clientIp) {
1265
- errResponse = apiUtil$1.spoApiFail(err$1.GET_CLIENTIP_FAIL, req);
1267
+ errResponse = apiUtil$2.spoApiFail(err$2.GET_CLIENTIP_FAIL, req);
1266
1268
  } else if (!tokenData.apiKey) {
1267
- errResponse = apiUtil$1.spoApiFail([err$1.PARAMETER_NEEDED, "apiKey"], req);
1269
+ errResponse = apiUtil$2.spoApiFail([err$2.PARAMETER_NEEDED, "apiKey"], req);
1268
1270
  } else if (!tokenData.apiSecret) {
1269
- errResponse = apiUtil$1.spoApiFail([err$1.PARAMETER_NEEDED, "apiSecret"], req);
1271
+ errResponse = apiUtil$2.spoApiFail([err$2.PARAMETER_NEEDED, "apiSecret"], req);
1270
1272
  }
1271
1273
 
1272
1274
  if (errResponse != null) {
1273
- apiUtil$1._saveApiCallRec(req.apiCallRec, errResponse);
1275
+ apiUtil$2._saveApiCallRec(req.apiCallRec, errResponse);
1274
1276
 
1275
- apiUtil$1.sendOrRedirect(req, res, errResponse);
1277
+ apiUtil$2.sendOrRedirect(req, res, errResponse);
1276
1278
  } else {
1277
- apiUtil$1.checkApiCallValid(tokenData, req).then(companyInfo => {
1279
+ apiUtil$2.checkApiCallValid(tokenData, req).then(companyInfo => {
1278
1280
  params.companyId = params.companyId || companyInfo.companyId;
1279
1281
  req.companyInfo = companyInfo;
1280
1282
  next();
@@ -1282,9 +1284,9 @@ class apiUtil$1 {
1282
1284
  console.log('apiCallInvalid:', e);
1283
1285
  let errResponse = spoApiFail(e, req);
1284
1286
 
1285
- apiUtil$1._saveApiCallRec(req.apiCallRec, errResponse);
1287
+ apiUtil$2._saveApiCallRec(req.apiCallRec, errResponse);
1286
1288
 
1287
- apiUtil$1.sendOrRedirect(req, res, errResponse);
1289
+ apiUtil$2.sendOrRedirect(req, res, errResponse);
1288
1290
  });
1289
1291
  }
1290
1292
  }
@@ -1299,31 +1301,31 @@ class apiUtil$1 {
1299
1301
  return;
1300
1302
  }
1301
1303
 
1302
- let accessToken = apiUtil$1.extractToken(req);
1304
+ let accessToken = apiUtil$2.extractToken(req);
1303
1305
 
1304
1306
  if (!accessToken) {
1305
- res.send(apiUtil$1.spoApiFail(err$1.TOKEN_NEEDED, req)); // apiUtil.sendOrRedirect(req, res, spoApiFail(err.TOKEN_NEEDED, req));
1307
+ res.send(apiUtil$2.spoApiFail(err$2.TOKEN_NEEDED, req)); // apiUtil.sendOrRedirect(req, res, spoApiFail(err.TOKEN_NEEDED, req));
1306
1308
 
1307
1309
  return;
1308
1310
  }
1309
1311
 
1310
- apiUtil$1.restoreTokenData(apiUtil$1.apiTokenStoreKey(accessToken)).then(p => {
1312
+ apiUtil$2.restoreTokenData(apiUtil$2.apiTokenStoreKey(accessToken)).then(p => {
1311
1313
  // req.headers[hnApiKey] = p.apiKey || '';
1312
1314
  // req.headers[hnApiSecret] = p.apiSecret || '';
1313
1315
  if (req.isMobile) {
1314
1316
  // GET 请求的应该都是H5页面,由手机前端发起,需要把headers中的请求方ip换成服务端的
1315
1317
  // todo: 如何在API访问记录中记住请求者(手机端)的真实IP
1316
- req.headers['x-phone-ip'] = apiUtil$1.getClientIp(req);
1318
+ req.headers['x-phone-ip'] = apiUtil$2.getClientIp(req);
1317
1319
  req.headers['x-real-ip'] = p.clientIp;
1318
1320
  } else {
1319
- p.clientIp = apiUtil$1.getClientIp(req);
1321
+ p.clientIp = apiUtil$2.getClientIp(req);
1320
1322
  }
1321
1323
 
1322
1324
  req.isApiCall = true;
1323
1325
  req.tokenData = p;
1324
- return apiUtil$1.$checkApiKeyOld(req, res, next);
1326
+ return apiUtil$2.$checkApiKeyOld(req, res, next);
1325
1327
  }).catch(e => {
1326
- apiUtil$1.sendOrRedirect(req, res, apiUtil$1.spoApiFail(err$1.TOKEN_INVALID, req));
1328
+ apiUtil$2.sendOrRedirect(req, res, apiUtil$2.spoApiFail(err$2.TOKEN_INVALID, req));
1327
1329
  });
1328
1330
  }
1329
1331
  /**
@@ -1336,24 +1338,24 @@ class apiUtil$1 {
1336
1338
 
1337
1339
 
1338
1340
  static async $checkTokenOrApiKey(req, res, next) {
1339
- let accessToken = apiUtil$1.extractToken(req, res);
1341
+ let accessToken = apiUtil$2.extractToken(req, res);
1340
1342
 
1341
1343
  if (accessToken) {
1342
- let tokenExist = await apiUtil$1.tokenDataExist(apiUtil$1.userTokenStoreKey(accessToken));
1344
+ let tokenExist = await apiUtil$2.tokenDataExist(apiUtil$2.userTokenStoreKey(accessToken));
1343
1345
 
1344
1346
  if (tokenExist) {
1345
- return await apiUtil$1.$checkToken(req, res, next);
1347
+ return await apiUtil$2.$checkToken(req, res, next);
1346
1348
  }
1347
1349
 
1348
- tokenExist = await apiUtil$1.tokenDataExist(apiUtil$1.apiTokenStoreKey(accessToken));
1350
+ tokenExist = await apiUtil$2.tokenDataExist(apiUtil$2.apiTokenStoreKey(accessToken));
1349
1351
 
1350
1352
  if (tokenExist) {
1351
- return apiUtil$1.$checkApiKey(req, res, next);
1353
+ return apiUtil$2.$checkApiKey(req, res, next);
1352
1354
  } // 如果给定的token不存在,看看是不是平台内部调用
1353
1355
 
1354
1356
 
1355
- return await apiUtil$1.checkInternalToken(req).catch(e => {
1356
- res.send(apiUtil$1.apiFail(e, req));
1357
+ return await apiUtil$2.checkInternalToken(req).catch(e => {
1358
+ res.send(apiUtil$2.apiFail(e, req));
1357
1359
  return false;
1358
1360
  });
1359
1361
  }
@@ -1373,8 +1375,8 @@ class apiUtil$1 {
1373
1375
  const params = options.replacements;
1374
1376
  let item = params.item;
1375
1377
  delete params.item;
1376
- if (await apiUtil$1.checkForwardsHost(options)) return true;
1377
- let c = apiUtil$1.parseCfgPath(item);
1378
+ if (await apiUtil$2.checkForwardsHost(options)) return true;
1379
+ let c = apiUtil$2.parseCfgPath(item);
1378
1380
  delete c.parent;
1379
1381
  c.host = ppUtil$4.getMyIp();
1380
1382
  return c;
@@ -1393,11 +1395,11 @@ class apiUtil$1 {
1393
1395
  delete params.item; // if (await checkForwardsHost(options))
1394
1396
  // return true;
1395
1397
 
1396
- await apiUtil$1.parametersOK(params, "value");
1397
- let c = apiUtil$1.parseCfgPath(item);
1398
+ await apiUtil$2.parametersOK(params, "value");
1399
+ let c = apiUtil$2.parseCfgPath(item);
1398
1400
 
1399
1401
  if (typeof c.value === "object") {
1400
- throw [err$1.ACCESS_REFUSED, `暂不支持修改复杂配置`];
1402
+ throw [err$2.ACCESS_REFUSED, `暂不支持修改复杂配置`];
1401
1403
  } // c.oldValue = c.value;
1402
1404
 
1403
1405
 
@@ -1412,21 +1414,21 @@ class apiUtil$1 {
1412
1414
  }
1413
1415
 
1414
1416
  function configNeeded() {
1415
- if (!conf$2 || !err$1) {
1417
+ if (!conf$3 || !err$2) {
1416
1418
  ppUtil$4.configNeeded();
1417
- conf$2 = ppUtil$4.appConfig;
1418
- appSetting$1 = conf$2.appSetting;
1419
- err$1 = ppUtil$4.appErrCfg;
1419
+ conf$3 = ppUtil$4.appConfig;
1420
+ appSetting$1 = conf$3.appSetting;
1421
+ err$2 = ppUtil$4.appErrCfg;
1420
1422
  }
1421
1423
  }
1422
1424
 
1423
- var ppUtilApi = apiUtil$1;
1425
+ var ppUtilApi = apiUtil$2;
1424
1426
 
1425
- const fs = require$$0$2;
1427
+ const fs = require$$0$1;
1426
1428
  const path = require$$1$1;
1427
1429
  const ppUtil$3 = require$$1.ppUtil;
1428
1430
  const redisUtil = require$$2.redisUtil;
1429
- let conf$1, err; // const dbCheck = require('../dbupdate/dd-version');
1431
+ let conf$2, err$1; // const dbCheck = require('../dbupdate/dd-version');
1430
1432
 
1431
1433
  /**
1432
1434
  * API服务启动时前置条件检查
@@ -1446,9 +1448,9 @@ class preconditions$1 {
1446
1448
 
1447
1449
  static setAppName(aName) {
1448
1450
  ppUtil$3.configNeeded();
1449
- conf$1 = ppUtil$3.appConfig;
1450
- err = ppUtil$3.appErrCfg;
1451
- preconditions$1.appName = aName || conf$1.thisApp;
1451
+ conf$2 = ppUtil$3.appConfig;
1452
+ err$1 = ppUtil$3.appErrCfg;
1453
+ preconditions$1.appName = aName || conf$2.thisApp;
1452
1454
  return preconditions$1;
1453
1455
  }
1454
1456
 
@@ -1529,20 +1531,20 @@ async function createEnvSettingFile(fileName) {
1529
1531
  try {
1530
1532
  const cfgText = await ppUtil$3.doCreateEnvSettingFile(fileName);
1531
1533
 
1532
- if (cfgText.indexOf(`cfgVersion: "${conf$1._envSetting.cfgVersion}"`) > 0) {
1534
+ if (cfgText.indexOf(`cfgVersion: "${conf$2._envSetting.cfgVersion}"`) > 0) {
1533
1535
  console.log(`\n*** 已創建新的本機環境配置文件\n${fileName}\n请檢查各項內容是否正确(此项更新服务可正常运行)\n\n`);
1534
1536
  return "";
1535
1537
  }
1536
1538
 
1537
- return `已創建新的本機環境配置文件\n${fileName}\n请檢查並正確設置各項內容,然後將配置版本號修改為${conf$1._envSettings.default.cfgVersion}`;
1539
+ return `已創建新的本機環境配置文件\n${fileName}\n请檢查並正確設置各項內容,然後將配置版本號修改為${conf$2._envSettings.default.cfgVersion}`;
1538
1540
  } catch (e) {
1539
- return `創建本機環境配置文件失敗\n《${fileName}》\n${err.ERROR(e).message}`;
1541
+ return `創建本機環境配置文件失敗\n《${fileName}》\n${err$1.ERROR(e).message}`;
1540
1542
  }
1541
1543
  }
1542
1544
 
1543
1545
  async function checkExEnvSetting(loadjs) {
1544
- if (!conf$1._envSetting.localSettingImported) {
1545
- let fileName = conf$1.getEnvSettingFileName();
1546
+ if (!conf$2._envSetting.localSettingImported) {
1547
+ let fileName = conf$2.getEnvSettingFileName();
1546
1548
 
1547
1549
  if (!fs.existsSync(fileName)) {
1548
1550
  return await createEnvSettingFile(fileName);
@@ -1550,7 +1552,7 @@ async function checkExEnvSetting(loadjs) {
1550
1552
 
1551
1553
  let envSettingEx = loadjs(fileName);
1552
1554
 
1553
- if (envSettingEx.cfgVersion !== conf$1._envSettings.default.cfgVersion) {
1555
+ if (envSettingEx.cfgVersion !== conf$2._envSettings.default.cfgVersion) {
1554
1556
  if (envSettingEx.cfgVersion !== "0.0") {
1555
1557
  let fp = path.parse(fileName);
1556
1558
  let newFileName = path.join(fp.dir, fp.name + envSettingEx.cfgVersion + fp.ext);
@@ -1569,7 +1571,7 @@ async function checkExEnvSetting(loadjs) {
1569
1571
 
1570
1572
 
1571
1573
  async function checkRedis() {
1572
- if (!conf$1.redis.enabled) return "";
1574
+ if (!conf$2.redis.enabled) return "";
1573
1575
  const redis = redisUtil.newClient("io"); // console.log(`checkRedis begin:`);
1574
1576
 
1575
1577
  await ppUtil$3.wait(15 * 1000, param => {
@@ -1590,209 +1592,393 @@ async function checkRedis() {
1590
1592
 
1591
1593
  var ppPrecond = preconditions$1;
1592
1594
 
1593
- var require$$0 = require$$2;
1595
+ // redis 可用,则使用基于 redis 的消息订阅发布系统
1596
+ // 若 redis 不可用,则将消息转发到其它主机
1594
1597
 
1595
- function _interopDefaultLegacy(e) {
1596
- return e && typeof e === 'object' && 'default' in e ? e : {
1597
- 'default': e
1598
- };
1599
- }
1598
+ const {
1599
+ ppUtil: ppUtil$2
1600
+ } = require$$1;
1601
+ const RedisMessenger = require$$1$2;
1602
+ const {
1603
+ netUtil
1604
+ } = require$$3;
1605
+ let conf$1;
1606
+
1607
+ class commonMessenger$2 {
1608
+ static myMsgAddr = "";
1609
+ static redisMessenger = null;
1610
+ static onMessage = [];
1600
1611
 
1601
- var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0); // const logger = require("log4js").getLogger();
1612
+ static initMessenger(appConfig, appErrCfg, msgChannel) {
1613
+ conf$1 = appConfig;
1614
+ this.redisMessenger = conf$1.redis.enabled ? new RedisMessenger(appConfig, appErrCfg, msgChannel).subscribe(msgChannel) : null;
1615
+ this.myMsgAddr = commonMessenger$2.getMyMsgAddr();
1616
+ }
1602
1617
 
1618
+ static getMyMsgAddr() {
1619
+ if (!conf$1.myMsgAddr) {
1620
+ conf$1.pm_id = process.env.pm_id || "0";
1621
+ let myIp = ppUtil$2.getMyIp();
1603
1622
 
1604
- const redis = require$$0__default["default"].redisUtil;
1623
+ if (this.redisMessenger) {
1624
+ myIp = `${conf$1.pm_id}@${myIp}`;
1625
+ }
1605
1626
 
1606
- class Messenger {
1607
- constructor(appConfig, appErrCfg) {
1608
- if (appConfig) {
1609
- redis.config(appConfig, appErrCfg);
1627
+ conf$1.myMsgAddr = myIp;
1628
+ console.log(`myMsgAddr: `, conf$1.myMsgAddr);
1610
1629
  }
1611
1630
 
1612
- this.channel = "ecs_messenger"; //default channel
1613
-
1614
- this.publisher = redis.newClient("publisher");
1615
- this.subscriber = redis.newClient("subscriber");
1616
- this.subscriber.on("subscribe", function (channel, count) {
1617
- console.log("chanel subscribed :", channel, count);
1618
- });
1619
- this.subscriber.on("message", this.handleMessage);
1631
+ return conf$1.myMsgAddr;
1620
1632
  }
1621
1633
 
1622
- setMessageHandle(handle, channel) {
1623
- channel = channel || this.channel;
1624
- Messenger.onmessage = Messenger.onmessage || {};
1625
- Messenger.onmessage[channel] = Messenger.onmessage[channel] || [];
1626
- const appMsgHandles = Messenger.onmessage[channel];
1634
+ static setMessageHandle(messageHandle) {
1635
+ if (this.redisMessenger) {
1636
+ return this.redisMessenger.setMessageHandle(messageHandle, msgChannel);
1637
+ }
1627
1638
 
1628
- for (let i = 0; i < appMsgHandles.length; i++) {
1629
- if (appMsgHandles[i] === handle) return this;
1639
+ if (commonMessenger$2.onMessage.indexOf(messageHandle) < 0) {
1640
+ commonMessenger$2.onMessage.push(messageHandle);
1630
1641
  }
1631
1642
 
1632
- appMsgHandles.push(handle);
1633
- return this;
1643
+ return commonMessenger$2;
1634
1644
  }
1635
1645
 
1636
- subscribe(channel) {
1637
- channel = channel || this.channel;
1638
- this.subscriber.subscribe(channel);
1639
- return this;
1646
+ static async publishMessage(message) {
1647
+ if (this.redisMessenger) {
1648
+ return this.redisMessenger.publish(message, msgChannel);
1649
+ } else {
1650
+ //没有消息处理器,则将消息转发到目标地址(不支持pm2多进程)
1651
+ if (message.destAddr) {
1652
+ await forwardMessage(message);
1653
+ } else {
1654
+ for (let i = 0; i < conf$1.appSetting.serverHosts.length; i++) {
1655
+ message.destAddr = conf$1.appSetting.serverHosts[i];
1656
+
1657
+ if (message.destAddr !== conf$1.myMsgAddr) {
1658
+ await forwardMessage(message);
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1640
1663
  }
1641
1664
 
1642
- async handleMessage(channel, message) {
1643
- console.log(`通道[${channel}]收到订阅消息:`, message);
1644
- let appMsgHandles = Messenger.onmessage[channel] || [];
1665
+ static async handleInternalMessage(options) {
1666
+ const message = options.replacements;
1645
1667
 
1646
- for (let i = 0; i < appMsgHandles.length; i++) {
1647
- const appMsgHandle = appMsgHandles[i];
1668
+ for (let i = 0; i < commonMessenger$2.onMessage.length; i++) {
1669
+ const appMsgHandle = commonMessenger$2.onMessage[i];
1648
1670
 
1649
1671
  try {
1650
- let msgObj = JSON.parse(message); // await appMsgHandle(msgObj);
1651
-
1652
- appMsgHandle(msgObj);
1672
+ await appMsgHandle(message);
1653
1673
  } catch (e) {
1654
1674
  console.log(e);
1655
1675
  }
1656
1676
  }
1657
1677
  }
1658
1678
 
1659
- async publish(message, channel) {
1660
- channel = channel || this.channel;
1661
- let msgStr = typeof message === "object" ? JSON.stringify(message) : message.toString();
1662
- console.log(`通道[${channel}]发布消息:`, message);
1663
- await this.publisher.publish(channel, msgStr);
1664
- return this;
1665
- }
1666
-
1667
1679
  }
1668
1680
 
1669
- var ppMessenger$1 = Messenger;
1670
- const ppMessenger = ppMessenger$1;
1671
- var ppUtil$2 = ppMessenger;
1672
- var ppUtil_1 = ppUtil$2;
1681
+ async function forwardMessage(message) {
1682
+ let reqOptions = {
1683
+ url: `https://${message.destAddr}:${appSetting.listenPort}/api/message`,
1684
+ method: "POST",
1685
+ data: message
1686
+ };
1687
+ let res = await netUtil.apiRequest(reqOptions).catch(e => {
1688
+ console.log(`转发消息失败, url: ${reqOptions.url}`, e);
1689
+ throw e;
1690
+ });
1691
+ return res.data;
1692
+ }
1673
1693
 
1674
- // redis 可用,则使用基于 redis 的消息订阅发布系统
1675
- // 若 redis 不可用,则将消息转发到其它主机
1694
+ var ppMessengerEx = commonMessenger$2;
1676
1695
 
1677
- const RedisMessenger = ppUtil_1;
1696
+ /**
1697
+ * CSCA 自动任务
1698
+ * ==============
1699
+ */
1700
+ const CRON = require$$0$2;
1678
1701
  const {
1679
- netUtil
1680
- } = require$$3;
1681
- let conf;
1702
+ ppUtil: ppUtil$1
1703
+ } = require$$1;
1704
+ const apiUtil$1 = ppUtilApi;
1705
+ const commonMessenger$1 = ppMessengerEx;
1706
+ const MT_SCHEDULE_STATE = 'schedule-state',
1707
+ MT_SCHEDULE_STATE_REPLY = 'schedule-state-reply';
1708
+ let conf, err;
1709
+
1710
+ class schedule$1 {
1711
+ static tasks = {};
1712
+ /**
1713
+ * 注册一个计划任务
1714
+ * @param taskName
1715
+ * @param taskCaption
1716
+ * @param cronExp
1717
+ * @param taskFunc
1718
+ * @param autoStart
1719
+ * @returns {Promise<{}|{}|{cron: *, _message_: string}|any>}
1720
+ */
1682
1721
 
1683
- class noneRedisMessenger {
1684
- static onMessage = [];
1722
+ static async registerTask(taskName, taskCaption, cronExp, taskFunc, autoStart) {
1723
+ if (!conf) {
1724
+ ppUtil$1.configNeeded();
1725
+ conf = ppUtil$1.appConfig;
1726
+ err = ppUtil$1.appErrCfg;
1727
+ }
1685
1728
 
1686
- static async publishMessage(message) {
1687
- //没有消息处理器,则将消息转发到目标地址(不支持pm2多进程)
1688
- if (message.destAddr) {
1689
- await forwardMessage(message);
1690
- } else {
1691
- for (let i = 0; i < conf.appSetting.serverHosts.length; i++) {
1692
- message.destAddr = conf.appSetting.serverHosts[i];
1729
+ if (!this.envAllowed()) return {};
1730
+ let task = this.findTask(taskName);
1731
+
1732
+ if (task) {
1733
+ if (task.cronExp !== cronExp || task.taskFunc !== taskFunc) {
1734
+ this.stop(taskName);
1735
+ task = null;
1736
+ }
1737
+ }
1693
1738
 
1694
- if (message.destAddr !== conf.myMsgAddr) {
1695
- await forwardMessage(message);
1739
+ if (!task) {
1740
+ task = {
1741
+ name: taskName,
1742
+ caption: taskCaption,
1743
+ cronExp: cronExp,
1744
+ taskFunc: taskFunc,
1745
+ schedule: null,
1746
+ doScheduleTask: async function () {
1747
+ let self = this;
1748
+ if (this._pp_task) self = this._pp_task;
1749
+ console.log(new Date().format('[yyyy/MM/dd hh:mm:ss:S]'), `开始执行${self.caption}任务 ...`);
1750
+ await self.taskFunc();
1751
+ console.log(new Date().format('[yyyy/MM/dd hh:mm:ss:S]'), `${self.caption}任务执行结束`);
1696
1752
  }
1753
+ };
1754
+ this.tasks[taskName] = task;
1755
+
1756
+ if (autoStart) {
1757
+ return await this.start(task);
1697
1758
  }
1759
+
1760
+ return this.getTaskInfo(task, "任务已注册。");
1698
1761
  }
1762
+
1763
+ return this.getTaskInfo(task, "任务已存在。");
1699
1764
  }
1700
1765
 
1701
- static setMessageHandle(messageHandle) {
1702
- if (noneRedisMessenger.onMessage.indexOf(messageHandle) < 0) {
1703
- noneRedisMessenger.onMessage.push(messageHandle);
1766
+ static getTaskInfo(task, msg) {
1767
+ // return Object.assign({_message_: msg}, task);
1768
+ return {
1769
+ name: task.name,
1770
+ caption: task.caption,
1771
+ cronExp: task.cronExp,
1772
+ state: task.schedule ? "started" : "stopped",
1773
+ _message_: msg
1774
+ };
1775
+ }
1776
+ /**
1777
+ * 启动任务
1778
+ * @param taskOrName
1779
+ * @param cronExp
1780
+ * @returns {Promise<{}|{cron: *, _message_: string}>}
1781
+ */
1782
+
1783
+
1784
+ static async start(taskOrName, cronExp) {
1785
+ if (!this.envAllowed()) return {};
1786
+ let task = taskOrName;
1787
+
1788
+ if (typeof task === "string") {
1789
+ task = this.findTask(taskOrName);
1790
+ }
1791
+
1792
+ if (!task) throw [err.INVALID_PARAM, `任务${taskOrName}不存在`];
1793
+ cronExp = cronExp || task.cronExp;
1794
+
1795
+ if (task.cronExp !== cronExp) {
1796
+ this.stop(task);
1797
+ task.cronExp = cronExp;
1704
1798
  }
1705
1799
 
1706
- return noneRedisMessenger;
1800
+ if (task.schedule) {
1801
+ return this.getTaskInfo(task, "任务已启动,无需重复启动。");
1802
+ }
1803
+
1804
+ task.schedule = CRON.schedule(cronExp, task.doScheduleTask);
1805
+ task.schedule._task._pp_task = task;
1806
+ return this.getTaskInfo(task, "任务已启动。");
1707
1807
  }
1808
+ /**
1809
+ * 停止任务
1810
+ * @param taskOrName
1811
+ * @returns {Promise<{}|{cron: *, _message_: string}|{_message_: string}>}
1812
+ */
1708
1813
 
1709
- static async handleInternalMessage(options) {
1710
- const message = options.replacements;
1711
1814
 
1712
- for (let i = 0; i < noneRedisMessenger.onMessage.length; i++) {
1713
- const appMsgHandle = noneRedisMessenger.onMessage[i];
1815
+ static async stop(taskOrName) {
1816
+ if (!this.envAllowed()) return {};
1817
+ let task = taskOrName;
1714
1818
 
1715
- try {
1716
- // await appMsgHandle(message);
1717
- appMsgHandle(message);
1718
- } catch (e) {
1719
- console.log(e);
1720
- }
1819
+ if (typeof task === "string") {
1820
+ task = this.findTask(taskOrName);
1721
1821
  }
1722
- }
1723
1822
 
1724
- }
1823
+ if (!task) throw [err.INVALID_PARAM, `任务${taskOrName}不存在`];
1725
1824
 
1726
- class commonMessenger$1 {
1727
- static myMsgAddr = "";
1728
- static redisMessenger = null;
1825
+ if (task.schedule) {
1826
+ task.schedule.stop();
1827
+ task.schedule = null;
1828
+ return this.getTaskInfo(task, "任务已停止。");
1829
+ }
1729
1830
 
1730
- static initMessenger(appConfig, appErrCfg, msgChannel) {
1731
- conf = appConfig;
1732
- this.redisMessenger = conf.redis.enabled ? new RedisMessenger(appConfig, appErrCfg, msgChannel).subscribe(msgChannel) : null;
1733
- this.myMsgAddr = commonMessenger$1.getMyMsgAddr();
1831
+ return this.getTaskInfo(task, "任务未启动,无需停止。");
1734
1832
  }
1833
+ /**
1834
+ * 获取或设置当前状态(来自远程的API调用)
1835
+ * @param options
1836
+ * @returns {Promise<unknown>}
1837
+ */
1735
1838
 
1736
- static getMyMsgAddr() {
1737
- if (!conf.myMsgAddr) {
1738
- conf.pm_id = process.env.pm_id || "0";
1739
- let myIp = ppUtil.getMyIp();
1740
1839
 
1741
- if (this.redisMessenger) {
1742
- myIp = `${conf.pm_id}@${myIp}`;
1840
+ static async state(options) {
1841
+ const params = options.replacements; // await commonMessenger.parametersOK(params, "taskName");
1842
+
1843
+ const req = options._res.req;
1844
+
1845
+ if (req) {
1846
+ if (req.method === 'GET') {
1847
+ delete params.state;
1848
+ } else {
1849
+ await apiUtil$1.parametersOK(params, 'taskName', "state");
1743
1850
  }
1851
+ }
1852
+
1853
+ if (this.envAllowed()) {
1854
+ return this._state(params);
1855
+ } // 环境变量启用计划任务,但当前环境不能执行,
1856
+ // 说明收到此API请求的进程不是第一个进程,或者此前服务器不是第一台服务器,
1857
+ // 这种情况下,将此请求作为消息发布出去,
1858
+ // 第一台服务器的第一个进程收到消息后进行处理,再将结果作为消息发布,
1859
+ // 本进程收到处理结果后果作为响应发送回客户端
1860
+
1861
+
1862
+ if (process.env.SCHEDULE_ENABLED) {
1863
+ let replyId = ppUtil$1.newGuid();
1864
+ return await new Promise((resolve, reject) => {
1865
+ commonMessenger$1.setMessageHandle(message => {
1866
+ if (message._type === MT_SCHEDULE_STATE_REPLY && message.replyId === replyId) {
1867
+ replyId = '';
1868
+ resolve(message.result);
1869
+ return;
1870
+ }
1744
1871
 
1745
- conf.myMsgAddr = myIp;
1746
- console.log(`myMsgAddr: `, conf.myMsgAddr);
1872
+ if (message._type === MT_SCHEDULE_STATE) {
1873
+ if (schedule$1.enabled()) {
1874
+ message.result = schedule$1._state(message.params);
1875
+ message._type = MT_SCHEDULE_STATE_REPLY;
1876
+ message.destAddr = message.replyAddr;
1877
+ commonMessenger$1.publishMessage(message);
1878
+ }
1879
+ }
1880
+ });
1881
+ commonMessenger$1.publishMessage({
1882
+ _type: MT_SCHEDULE_STATE,
1883
+ replyId,
1884
+ replyAddr: conf.myMsgAddr,
1885
+ params
1886
+ }).catch(e => {
1887
+ replyId = '';
1888
+ reject(e);
1889
+ });
1890
+ setTimeout(() => {
1891
+ if (replyId) {
1892
+ reject("schedule.state: 等待处理结果超时");
1893
+ }
1894
+ }, 2 * 60 * 1000);
1895
+ });
1747
1896
  }
1748
1897
 
1749
- return conf.myMsgAddr;
1898
+ return {
1899
+ _message_: "此环境无自动任务"
1900
+ };
1750
1901
  }
1751
1902
 
1752
- static setMessageHandle(messageHandle) {
1753
- if (this.redisMessenger) {
1754
- return this.redisMessenger.setMessageHandle(messageHandle, msgChannel);
1903
+ static async _state(params) {
1904
+ let apiResult = {};
1905
+ let task;
1906
+
1907
+ if (params.taskName) {
1908
+ task = this.findTask(params.taskName);
1909
+ if (!task) throw [err.INVALID_PARAM, `任务${params.taskName}不存在`];
1755
1910
  }
1756
1911
 
1757
- return noneRedisMessenger.setMessageHandle(messageHandle);
1758
- }
1912
+ if (params.state) {
1913
+ if ("started" === params.state) {
1914
+ apiResult = await this.start(task, params.cron);
1915
+ } else if ("stopped" === params.state) {
1916
+ apiResult = await this.stop(task);
1917
+ } else {
1918
+ throw [err.INVALID_PARAM, `(${params.state}), 只能是 started/stopped`];
1919
+ }
1759
1920
 
1760
- static async publishMessage(message) {
1761
- if (this.redisMessenger) {
1762
- return this.redisMessenger.publish(message, msgChannel);
1763
- } else {
1764
- return noneRedisMessenger.publishMessage(message);
1921
+ if (params.runOnce) {
1922
+ task = this.findTask(params.taskName);
1923
+ apiResult._message_ += "\n正在手动执行任务"; // await
1924
+
1925
+ task.doScheduleTask();
1926
+ }
1927
+
1928
+ return this.getTaskInfo(task, apiResult._message_);
1765
1929
  }
1930
+
1931
+ if (task) {
1932
+ return this.getTaskInfo(task);
1933
+ }
1934
+
1935
+ const result = [];
1936
+
1937
+ for (let k in this.tasks) {
1938
+ result.push(this.getTaskInfo(this.tasks[k]));
1939
+ }
1940
+
1941
+ return result;
1766
1942
  }
1767
1943
 
1768
- static async handleInternalMessage(options) {
1769
- return await noneRedisMessenger.handleInternalMessage(options);
1944
+ static deleteTask(taskName) {
1945
+ delete this.tasks[taskName];
1770
1946
  }
1771
1947
 
1772
- }
1948
+ static findTask(taskName) {
1949
+ return this.tasks[taskName];
1950
+ }
1951
+ /**
1952
+ * 确定当前进程环境是否启用自动任务
1953
+ * @returns {Promise<void>}
1954
+ */
1955
+
1956
+
1957
+ static envAllowed() {
1958
+ let enabled = // PM2配置中指定了环境变量 SCHEDULE_ENABLED
1959
+ !!process.env.SCHEDULE_ENABLED // 如果PM2启动了多个进程,则只在第一个进程执行
1960
+ && process.env.NODE_APP_INSTANCE === '0'; // 如果有多台服务器,则只在第一台执行
1961
+
1962
+ if (enabled && conf.appSetting.serverHosts && conf.appSetting.serverHosts.length > 1) {
1963
+ enabled = conf.myMsgAddr.indexOf(conf.appSetting.serverHosts[0]) === 0;
1964
+ }
1965
+
1966
+ return enabled;
1967
+ }
1773
1968
 
1774
- async function forwardMessage(message) {
1775
- let reqOptions = {
1776
- url: `https://${message.destAddr}:${appSetting.listenPort}/api/message`,
1777
- method: "POST",
1778
- data: message
1779
- };
1780
- let res = await netUtil.apiRequest(reqOptions).catch(e => {
1781
- console.log(`转发消息失败, url: ${reqOptions.url}`, e);
1782
- throw e;
1783
- });
1784
- return res.data;
1785
1969
  }
1786
1970
 
1787
- var ppMessengerEx = commonMessenger$1;
1971
+ var ppSchedule = schedule$1;
1788
1972
 
1789
1973
  const apiUtil = ppUtilApi;
1790
1974
  const preconditions = ppPrecond;
1791
1975
  const commonMessenger = ppMessengerEx;
1792
- var ppUtil$1 = {
1976
+ const schedule = ppSchedule;
1977
+ var ppUtil = {
1793
1978
  apiUtil,
1794
1979
  preconditions,
1795
- commonMessenger
1980
+ commonMessenger,
1981
+ schedule
1796
1982
  };
1797
1983
 
1798
- export { ppUtil$1 as default };
1984
+ export { ppUtil as default };