@yvhitxcel/opencode-remote 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +82 -0
  2. package/bin/opencode-remote.js +70 -0
  3. package/bin/opencode-weixin.js +10 -0
  4. package/dist/AGENTS.md +20 -0
  5. package/dist/MEMORY.md +21 -0
  6. package/dist/bot-runner.js +180 -0
  7. package/dist/cli.js +256 -0
  8. package/dist/core/approval.js +95 -0
  9. package/dist/core/auth.js +119 -0
  10. package/dist/core/config.js +61 -0
  11. package/dist/core/notifications.js +134 -0
  12. package/dist/core/qiniu.js +267 -0
  13. package/dist/core/registry.js +86 -0
  14. package/dist/core/router.js +344 -0
  15. package/dist/core/session.js +403 -0
  16. package/dist/core/setup.js +418 -0
  17. package/dist/core/types.js +16 -0
  18. package/dist/feishu/adapter.js +72 -0
  19. package/dist/feishu/bot.js +168 -0
  20. package/dist/feishu/commands.js +601 -0
  21. package/dist/feishu/handler.js +380 -0
  22. package/dist/index.js +60 -0
  23. package/dist/opencode/client.js +823 -0
  24. package/dist/package-lock.json +762 -0
  25. package/dist/patch_spawn.js +28 -0
  26. package/dist/plugins/agents/acp/acp-adapter.js +42 -0
  27. package/dist/plugins/agents/claude-code/index.js +69 -0
  28. package/dist/plugins/agents/codex/index.js +44 -0
  29. package/dist/plugins/agents/copilot/index.js +44 -0
  30. package/dist/plugins/agents/opencode/index.js +66 -0
  31. package/dist/telegram/bot.js +288 -0
  32. package/dist/utils/message-split.js +38 -0
  33. package/dist/web/code-viewer.js +266 -0
  34. package/dist/weixin/adapter.js +135 -0
  35. package/dist/weixin/api.js +179 -0
  36. package/dist/weixin/bot.js +183 -0
  37. package/dist/weixin/commands.js +758 -0
  38. package/dist/weixin/handler.js +577 -0
  39. package/dist/weixin/node_modules/encodeurl/LICENSE +22 -0
  40. package/dist/weixin/node_modules/encodeurl/README.md +109 -0
  41. package/dist/weixin/node_modules/encodeurl/index.js +60 -0
  42. package/dist/weixin/node_modules/encodeurl/package.json +40 -0
  43. package/dist/weixin/node_modules/qiniu/.claude/settings.local.json +7 -0
  44. package/dist/weixin/node_modules/qiniu/.github/workflows/ci-test.yml +36 -0
  45. package/dist/weixin/node_modules/qiniu/.github/workflows/npm-publish.yml +20 -0
  46. package/dist/weixin/node_modules/qiniu/.github/workflows/version-check.yml +19 -0
  47. package/dist/weixin/node_modules/qiniu/.idea/MarsCodeWorkspaceAppSettings.xml +7 -0
  48. package/dist/weixin/node_modules/qiniu/.idea/codeStyles/Project.xml +44 -0
  49. package/dist/weixin/node_modules/qiniu/.idea/codeStyles/codeStyleConfig.xml +5 -0
  50. package/dist/weixin/node_modules/qiniu/.idea/git_toolbox_blame.xml +6 -0
  51. package/dist/weixin/node_modules/qiniu/.idea/inspectionProfiles/Project_Default.xml +6 -0
  52. package/dist/weixin/node_modules/qiniu/.idea/jsLibraryMappings.xml +6 -0
  53. package/dist/weixin/node_modules/qiniu/.idea/modules.xml +8 -0
  54. package/dist/weixin/node_modules/qiniu/.idea/nodejs-sdk.iml +12 -0
  55. package/dist/weixin/node_modules/qiniu/.idea/vcs.xml +6 -0
  56. package/dist/weixin/node_modules/qiniu/CHANGELOG.md +292 -0
  57. package/dist/weixin/node_modules/qiniu/README.md +56 -0
  58. package/dist/weixin/node_modules/qiniu/StorageResponseInterface.d.ts +239 -0
  59. package/dist/weixin/node_modules/qiniu/codecov.yml +28 -0
  60. package/dist/weixin/node_modules/qiniu/index.d.ts +1995 -0
  61. package/dist/weixin/node_modules/qiniu/index.js +32 -0
  62. package/dist/weixin/node_modules/qiniu/node_modules/encodeurl/HISTORY.md +14 -0
  63. package/dist/weixin/node_modules/qiniu/node_modules/encodeurl/LICENSE +22 -0
  64. package/dist/weixin/node_modules/qiniu/node_modules/encodeurl/README.md +128 -0
  65. package/dist/weixin/node_modules/qiniu/node_modules/encodeurl/index.js +60 -0
  66. package/dist/weixin/node_modules/qiniu/node_modules/encodeurl/package.json +40 -0
  67. package/dist/weixin/node_modules/qiniu/package.json +80 -0
  68. package/dist/weixin/node_modules/qiniu/qiniu/auth/digest.js +13 -0
  69. package/dist/weixin/node_modules/qiniu/qiniu/cdn.js +149 -0
  70. package/dist/weixin/node_modules/qiniu/qiniu/conf.js +254 -0
  71. package/dist/weixin/node_modules/qiniu/qiniu/fop.js +112 -0
  72. package/dist/weixin/node_modules/qiniu/qiniu/httpc/client.js +253 -0
  73. package/dist/weixin/node_modules/qiniu/qiniu/httpc/endpoint.js +66 -0
  74. package/dist/weixin/node_modules/qiniu/qiniu/httpc/endpointsProvider.js +27 -0
  75. package/dist/weixin/node_modules/qiniu/qiniu/httpc/endpointsRetryPolicy.js +76 -0
  76. package/dist/weixin/node_modules/qiniu/qiniu/httpc/middleware/base.js +31 -0
  77. package/dist/weixin/node_modules/qiniu/qiniu/httpc/middleware/index.js +9 -0
  78. package/dist/weixin/node_modules/qiniu/qiniu/httpc/middleware/qiniuAuth.js +53 -0
  79. package/dist/weixin/node_modules/qiniu/qiniu/httpc/middleware/retryDomains.js +101 -0
  80. package/dist/weixin/node_modules/qiniu/qiniu/httpc/middleware/ua.js +36 -0
  81. package/dist/weixin/node_modules/qiniu/qiniu/httpc/region.js +349 -0
  82. package/dist/weixin/node_modules/qiniu/qiniu/httpc/regionsProvider.js +788 -0
  83. package/dist/weixin/node_modules/qiniu/qiniu/httpc/regionsRetryPolicy.js +242 -0
  84. package/dist/weixin/node_modules/qiniu/qiniu/httpc/responseWrapper.js +40 -0
  85. package/dist/weixin/node_modules/qiniu/qiniu/retry/index.js +4 -0
  86. package/dist/weixin/node_modules/qiniu/qiniu/retry/retrier.js +99 -0
  87. package/dist/weixin/node_modules/qiniu/qiniu/retry/retryPolicy.js +55 -0
  88. package/dist/weixin/node_modules/qiniu/qiniu/rpc.js +237 -0
  89. package/dist/weixin/node_modules/qiniu/qiniu/rtc/app.js +123 -0
  90. package/dist/weixin/node_modules/qiniu/qiniu/rtc/credentials.js +57 -0
  91. package/dist/weixin/node_modules/qiniu/qiniu/rtc/room.js +118 -0
  92. package/dist/weixin/node_modules/qiniu/qiniu/rtc/util.js +16 -0
  93. package/dist/weixin/node_modules/qiniu/qiniu/sms/message.js +58 -0
  94. package/dist/weixin/node_modules/qiniu/qiniu/storage/form.js +442 -0
  95. package/dist/weixin/node_modules/qiniu/qiniu/storage/internal.js +214 -0
  96. package/dist/weixin/node_modules/qiniu/qiniu/storage/resume.js +1272 -0
  97. package/dist/weixin/node_modules/qiniu/qiniu/storage/rs.js +1764 -0
  98. package/dist/weixin/node_modules/qiniu/qiniu/util.js +382 -0
  99. package/dist/weixin/node_modules/qiniu/qiniu/zone.js +230 -0
  100. package/dist/weixin/node_modules/qiniu/tsconfig.json +112 -0
  101. package/dist/weixin/types.js +25 -0
  102. package/package.json +56 -0
@@ -0,0 +1,76 @@
1
+ const {
2
+ RetryPolicy
3
+ } = require('../retry');
4
+ const {
5
+ StaticEndpointsProvider
6
+ } = require('./endpointsProvider');
7
+
8
+ /**
9
+ * @typedef {RetryPolicyContext} EndpointsRetryPolicyContext
10
+ * @property {Endpoint} endpoint
11
+ * @property {Endpoint[]} alternativeEndpoints
12
+ */
13
+
14
+ /**
15
+ * @class
16
+ * @extends RetryPolicy
17
+ * @param {boolean} [options.skipInitContext]
18
+ * @param {Endpoint[]} [options.endpoints]
19
+ * @param {EndpointsProvider} [options.endpointsProvider]
20
+ * @constructor
21
+ */
22
+ function EndpointsRetryPolicy (options) {
23
+ this.skipInitContext = options.skipInitContext || false;
24
+ this.endpoints = options.endpoints || [];
25
+ this.endpointsProvider = options.endpointsProvider || new StaticEndpointsProvider([]);
26
+ }
27
+
28
+ EndpointsRetryPolicy.prototype = Object.create(RetryPolicy.prototype);
29
+ EndpointsRetryPolicy.prototype.constructor = EndpointsRetryPolicy;
30
+
31
+ /**
32
+ * @param {EndpointsRetryPolicyContext} context
33
+ * @returns {Promise<void>}
34
+ */
35
+ EndpointsRetryPolicy.prototype.initContext = function (context) {
36
+ if (this.skipInitContext) {
37
+ return Promise.resolve();
38
+ }
39
+ if (this.endpoints.length > 0) {
40
+ [context.endpoint, ...context.alternativeEndpoints] = this.endpoints.slice();
41
+ return Promise.resolve();
42
+ }
43
+ return this.endpointsProvider.getEndpoints()
44
+ .then(endpoints => {
45
+ if (endpoints.length < 0) {
46
+ return Promise.reject(
47
+ new Error('There isn\'t available endpoint')
48
+ );
49
+ }
50
+ [context.endpoint, ...context.alternativeEndpoints] = endpoints.slice();
51
+ });
52
+ };
53
+
54
+ /**
55
+ * @param {EndpointsRetryPolicyContext} context
56
+ * @returns {boolean}
57
+ */
58
+ EndpointsRetryPolicy.prototype.shouldRetry = function (context) {
59
+ return context.alternativeEndpoints.length > 0;
60
+ };
61
+
62
+ /**
63
+ * @param {EndpointsRetryPolicyContext} context
64
+ * @returns {Promise<void>}
65
+ */
66
+ EndpointsRetryPolicy.prototype.prepareRetry = function (context) {
67
+ context.endpoint = context.alternativeEndpoints.shift();
68
+ if (!context.endpoint) {
69
+ return Promise.reject(
70
+ new Error('There isn\'t available endpoint for next try')
71
+ );
72
+ }
73
+ return Promise.resolve();
74
+ };
75
+
76
+ exports.EndpointsRetryPolicy = EndpointsRetryPolicy;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Middleware could be an interface if migrate to typescript
3
+ * @class
4
+ * @constructor
5
+ */
6
+ function Middleware () {
7
+ }
8
+
9
+ /**
10
+ * @memberOf Middleware
11
+ * @param _request
12
+ * @param _next
13
+ */
14
+ Middleware.prototype.send = function (_request, _next) {
15
+ throw new Error('The Middleware NOT be Implemented');
16
+ };
17
+
18
+ exports.Middleware = Middleware;
19
+
20
+ /**
21
+ * @param {Middleware[]} middlewares
22
+ * @param {function(ReqOpts):Promise<ResponseWrapper>} handler
23
+ * @returns {function(ReqOpts):Promise<ResponseWrapper>}
24
+ */
25
+ exports.composeMiddlewares = function (middlewares, handler) {
26
+ return middlewares.reverse()
27
+ .reduce(
28
+ (h, mw) => request => mw.send(request, h),
29
+ handler
30
+ );
31
+ };
@@ -0,0 +1,9 @@
1
+ const base = require('./base');
2
+
3
+ module.exports = {
4
+ composeMiddlewares: base.composeMiddlewares,
5
+ Middleware: base.Middleware,
6
+ RetryDomainsMiddleware: require('./retryDomains').RetryDomainsMiddleware,
7
+ UserAgentMiddleware: require('./ua').UserAgentMiddleware,
8
+ QiniuAuthMiddleware: require('./qiniuAuth').QiniuAuthMiddleware
9
+ };
@@ -0,0 +1,53 @@
1
+ const middleware = require('./base');
2
+ const util = require('../../util');
3
+
4
+ /**
5
+ * @class
6
+ * @extends middleware.Middleware
7
+ * @param {Object} qiniuAuthOptions
8
+ * @param {Mac} qiniuAuthOptions.mac
9
+ * @constructor
10
+ */
11
+ function QiniuAuthMiddleware (qiniuAuthOptions) {
12
+ this.mac = qiniuAuthOptions.mac;
13
+ }
14
+
15
+ QiniuAuthMiddleware.prototype = Object.create(middleware.Middleware.prototype);
16
+ QiniuAuthMiddleware.prototype.constructor = QiniuAuthMiddleware;
17
+
18
+ /**
19
+ * @memberOf QiniuAuthMiddleware
20
+ * @param {ReqOpts} reqOpts
21
+ * @param {function(ReqOpts):Promise<ResponseWrapper>} next
22
+ * @returns {Promise<ResponseWrapper>}
23
+ */
24
+ QiniuAuthMiddleware.prototype.send = function (reqOpts, next) {
25
+ const headers = reqOpts.urllibOptions.headers;
26
+ if (this._shouldSignTime()) {
27
+ headers['X-Qiniu-Date'] = util.formatDateUTC(new Date(), 'YYYYMMDDTHHmmssZ');
28
+ }
29
+
30
+ if (this.mac.accessKey) {
31
+ headers.Authorization = util.generateAccessTokenV2(
32
+ this.mac,
33
+ reqOpts.url,
34
+ reqOpts.urllibOptions.method,
35
+ reqOpts.urllibOptions.contentType,
36
+ reqOpts.urllibOptions.content,
37
+ headers
38
+ );
39
+ }
40
+
41
+ return next(reqOpts);
42
+ };
43
+
44
+ QiniuAuthMiddleware.prototype._shouldSignTime = function () {
45
+ let shouldDisable = this.mac.options.disableQiniuTimestampSignature;
46
+ if (shouldDisable === null) {
47
+ const envDisable = process.env.DISABLE_QINIU_TIMESTAMP_SIGNATURE || '';
48
+ shouldDisable = envDisable.toLowerCase() === 'true';
49
+ }
50
+ return !shouldDisable;
51
+ };
52
+
53
+ exports.QiniuAuthMiddleware = QiniuAuthMiddleware;
@@ -0,0 +1,101 @@
1
+ const middleware = require('./base');
2
+
3
+ const URL = require('url').URL;
4
+
5
+ /**
6
+ * @class
7
+ * @extends middleware.Middleware
8
+ * @param {Object} retryDomainsOptions
9
+ * @param {string[]} retryDomainsOptions.backupDomains
10
+ * @param {number} [retryDomainsOptions.maxRetryTimes]
11
+ * @param {function(Error || null, ResponseWrapper || null, ReqOpts):boolean} [retryDomainsOptions.retryCondition]
12
+ * @constructor
13
+ */
14
+ function RetryDomainsMiddleware (retryDomainsOptions) {
15
+ this.backupDomains = retryDomainsOptions.backupDomains;
16
+ this.maxRetryTimes = retryDomainsOptions.maxRetryTimes || 2;
17
+ this.retryCondition = retryDomainsOptions.retryCondition;
18
+
19
+ this._retriedTimes = 0;
20
+ }
21
+
22
+ RetryDomainsMiddleware.prototype = Object.create(middleware.Middleware.prototype);
23
+ RetryDomainsMiddleware.prototype.constructor = RetryDomainsMiddleware;
24
+
25
+ /**
26
+ * @memberOf RetryDomainsMiddleware
27
+ * @param {Error || null} err
28
+ * @param {ResponseWrapper || null} respWrapper
29
+ * @param {ReqOpts} reqOpts
30
+ * @returns {boolean}
31
+ * @private
32
+ */
33
+ RetryDomainsMiddleware.prototype._shouldRetry = function (err, respWrapper, reqOpts) {
34
+ if (typeof this.retryCondition === 'function') {
35
+ return this.retryCondition(err, respWrapper, reqOpts);
36
+ }
37
+
38
+ return !respWrapper || respWrapper.needRetry();
39
+ };
40
+
41
+ /**
42
+ * @memberOf RetryDomainsMiddleware
43
+ * @param {ReqOpts} reqOpts
44
+ * @param {function(ReqOpts):Promise<ResponseWrapper>} next
45
+ * @returns {Promise<ResponseWrapper>}
46
+ */
47
+ RetryDomainsMiddleware.prototype.send = function (reqOpts, next) {
48
+ const url = new URL(reqOpts.url);
49
+ const domains = this.backupDomains.slice(); // copy for late pop
50
+
51
+ const couldRetry = () => {
52
+ // the reason `this.maxRetryTimes - 1` is request send first then add retriedTimes
53
+ // and `this.maxRetryTimes` means max request times per domain
54
+ if (this._retriedTimes < this.maxRetryTimes - 1) {
55
+ this._retriedTimes += 1;
56
+ return true;
57
+ }
58
+
59
+ if (domains.length) {
60
+ this._retriedTimes = 0;
61
+ const domain = domains.shift();
62
+ const [hostname, port] = domain.split(':');
63
+ url.hostname = hostname;
64
+ url.port = port || url.port;
65
+ reqOpts.url = url.toString();
66
+ return true;
67
+ }
68
+
69
+ return false;
70
+ };
71
+
72
+ const tryNext = () => {
73
+ return next(reqOpts)
74
+ .then(respWrapper => {
75
+ if (!this._shouldRetry(null, respWrapper, reqOpts)) {
76
+ return respWrapper;
77
+ }
78
+
79
+ if (couldRetry()) {
80
+ return tryNext();
81
+ }
82
+
83
+ return respWrapper;
84
+ })
85
+ .catch(err => {
86
+ if (!this._shouldRetry(err, null, reqOpts)) {
87
+ return Promise.reject(err);
88
+ }
89
+
90
+ if (couldRetry()) {
91
+ return tryNext();
92
+ }
93
+
94
+ return Promise.reject(err);
95
+ });
96
+ };
97
+
98
+ return tryNext();
99
+ };
100
+
101
+ exports.RetryDomainsMiddleware = RetryDomainsMiddleware;
@@ -0,0 +1,36 @@
1
+ const os = require('os');
2
+
3
+ const middleware = require('./base');
4
+
5
+ /**
6
+ * @class
7
+ * @extends middleware.Middleware
8
+ * @param {string} sdkVersion
9
+ * @constructor
10
+ */
11
+ function UserAgentMiddleware (sdkVersion) {
12
+ this.userAgent = 'QiniuNodejs/' + sdkVersion +
13
+ ' (' +
14
+ os.type() + '; ' +
15
+ os.platform() + '; ' +
16
+ os.arch() + '; ' +
17
+ 'Node.js ' + process.version + '; )';
18
+ }
19
+ UserAgentMiddleware.prototype = Object.create(middleware.Middleware.prototype);
20
+ UserAgentMiddleware.prototype.constructor = UserAgentMiddleware;
21
+
22
+ /**
23
+ * @memberOf UserAgentMiddleware
24
+ * @param {ReqOpts} reqOpts
25
+ * @param {function(ReqOpts):Promise<ResponseWrapper>} next
26
+ * @returns {Promise<ResponseWrapper>}
27
+ */
28
+ UserAgentMiddleware.prototype.send = function (reqOpts, next) {
29
+ if (!reqOpts.urllibOptions.headers) {
30
+ reqOpts.urllibOptions.headers = {};
31
+ }
32
+ reqOpts.urllibOptions.headers['User-Agent'] = this.userAgent;
33
+ return next(reqOpts);
34
+ };
35
+
36
+ exports.UserAgentMiddleware = UserAgentMiddleware;
@@ -0,0 +1,349 @@
1
+ const { Endpoint } = require('./endpoint');
2
+
3
+ /**
4
+ * @interface RegionsProvider
5
+ */
6
+
7
+ /**
8
+ * @function
9
+ * @name RegionsProvider#getRegions
10
+ * @returns {Promise<Region[]>}
11
+ */
12
+
13
+ /**
14
+ * @interface MutableRegionsProvider
15
+ * @extends RegionsProvider
16
+ */
17
+
18
+ /**
19
+ * @function
20
+ * @name MutableRegionsProvider#setRegions
21
+ * @param {Region[]} regions
22
+ * @returns {Promise<void>}
23
+ */
24
+
25
+ // --- could split to files if migrate to typescript --- //
26
+
27
+ /**
28
+ * @readonly
29
+ * @enum {string}
30
+ */
31
+ const SERVICE_NAME = {
32
+ UC: 'uc',
33
+ UP: 'up',
34
+ UP_ACC: 'up_acc',
35
+ IO: 'io',
36
+ RS: 'rs',
37
+ RSF: 'rsf',
38
+ API: 'api',
39
+ S3: 's3'
40
+ };
41
+
42
+ // --- could split to files if migrate to typescript --- //
43
+
44
+ /**
45
+ * @typedef {SERVICE_NAME | string} ServiceKey
46
+ */
47
+
48
+ /**
49
+ * @class
50
+ * @implements RegionsProvider
51
+ * @param {Object} options
52
+ * @param {string} [options.regionId]
53
+ * @param {string} [options.s3RegionId]
54
+ * @param {Object.<ServiceKey, Endpoint[]>} [options.services]
55
+ * @param {number} [options.ttl] seconds. default 1 day.
56
+ * @param {Date} [options.createTime]
57
+ * @constructor
58
+ */
59
+ function Region (options) {
60
+ this.regionId = options.regionId;
61
+ this.s3RegionId = options.s3RegionId || options.regionId;
62
+
63
+ this.services = options.services || {};
64
+ // use Object.values when min version of Node.js update to ≥ v7.5.0
65
+ Object.keys(SERVICE_NAME).map(k => {
66
+ const v = SERVICE_NAME[k];
67
+ if (!Array.isArray(this.services[v])) {
68
+ this.services[v] = [];
69
+ }
70
+ });
71
+
72
+ this.ttl = options.ttl || 86400;
73
+ this.createTime = options.createTime || new Date();
74
+ }
75
+
76
+ /**
77
+ * This is used to be compatible with Zone.
78
+ * So this function will be removed after remove Zone.
79
+ * NOTE: The Region instance obtained using this method
80
+ * can only be used for the following services: up, io, rs, rsf, api.
81
+ * Because the Zone not support other services.
82
+ * @param {conf.Zone} zone
83
+ * @param {Object} [options]
84
+ * @param {string} [options.regionId]
85
+ * @param {string} [options.s3RegionId]
86
+ * @param {number} [options.ttl]
87
+ * @param {boolean} [options.isPreferCdnHost]
88
+ * @param {string} [options.preferredScheme]
89
+ */
90
+ Region.fromZone = function (zone, options) {
91
+ options = options || {};
92
+ options.ttl = options.ttl || -1;
93
+
94
+ const upHosts = options.isPreferCdnHost
95
+ ? zone.cdnUpHosts.concat(zone.srcUpHosts)
96
+ : zone.srcUpHosts.concat(zone.cdnUpHosts);
97
+
98
+ const endpointOptions = {};
99
+ if (options.preferredScheme) {
100
+ endpointOptions.defaultScheme = options.preferredScheme;
101
+ }
102
+
103
+ const services = {
104
+ // use array destructure if migrate to typescript
105
+ [SERVICE_NAME.UP]: upHosts.map(
106
+ h => new Endpoint(h, endpointOptions)
107
+ ),
108
+ [SERVICE_NAME.IO]: [
109
+ new Endpoint(zone.ioHost, endpointOptions)
110
+ ],
111
+ [SERVICE_NAME.RS]: [
112
+ new Endpoint(zone.rsHost, endpointOptions)
113
+ ],
114
+ [SERVICE_NAME.RSF]: [
115
+ new Endpoint(zone.rsfHost, endpointOptions)
116
+ ],
117
+ [SERVICE_NAME.API]: [
118
+ new Endpoint(zone.apiHost, endpointOptions)
119
+ ]
120
+ };
121
+
122
+ return new Region({
123
+ regionId: options.regionId,
124
+ s3RegionId: options.s3RegionId || options.regionId,
125
+ services: services,
126
+ ttl: options.ttl
127
+ });
128
+ };
129
+
130
+ /**
131
+ * @param {string} regionId
132
+ * @param {Object} [options]
133
+ * @param {string} [options.s3RegionId]
134
+ * @param {number} [options.ttl]
135
+ * @param {Date} [options.createTime]
136
+ * @param {string} [options.preferredScheme]
137
+ * @param {boolean} [options.isPreferCdnUpHost]
138
+ * @param {Object.<ServiceKey, Endpoint[]>} [options.extendedServices]
139
+ * @returns {Region}
140
+ */
141
+ Region.fromRegionId = function (regionId, options) {
142
+ options = options || {};
143
+
144
+ const s3RegionId = options.s3RegionId || regionId;
145
+ const ttl = options.ttl;
146
+ const createTime = options.createTime;
147
+ const isPreferCdnUpHost = typeof options.isPreferCdnUpHost === 'boolean'
148
+ ? options.isPreferCdnUpHost
149
+ : true;
150
+
151
+ const endpointOptions = {};
152
+ if (options.preferredScheme) {
153
+ endpointOptions.defaultScheme = options.preferredScheme;
154
+ }
155
+
156
+ const isZ0 = regionId === 'z0';
157
+ let upCdnEndpoints;
158
+ let upSourceEndpoints;
159
+ if (isZ0) {
160
+ upCdnEndpoints = [
161
+ new Endpoint(
162
+ 'upload.qiniup.com',
163
+ endpointOptions
164
+ )
165
+ ];
166
+ upSourceEndpoints = [
167
+ new Endpoint(
168
+ 'up.qiniup.com',
169
+ endpointOptions
170
+ ),
171
+ new Endpoint(
172
+ 'up.qbox.me',
173
+ endpointOptions
174
+ )
175
+ ];
176
+ } else {
177
+ upCdnEndpoints = [
178
+ new Endpoint(
179
+ 'upload-' + regionId + '.qiniup.com',
180
+ endpointOptions
181
+ )
182
+ ];
183
+ upSourceEndpoints = [
184
+ new Endpoint(
185
+ 'up-' + regionId + '.qiniup.com',
186
+ endpointOptions
187
+ ),
188
+ new Endpoint(
189
+ 'up-' + regionId + '.qbox.me',
190
+ endpointOptions
191
+ )
192
+ ];
193
+ }
194
+
195
+ /**
196
+ * @type {Object.<ServiceKey, Endpoint[]>}
197
+ */
198
+ let services = {
199
+ [SERVICE_NAME.UC]: [
200
+ new Endpoint(
201
+ 'uc.qiniuapi.com',
202
+ endpointOptions
203
+ )
204
+ ],
205
+ [SERVICE_NAME.UP]: isPreferCdnUpHost
206
+ ? upCdnEndpoints.concat(upSourceEndpoints)
207
+ : upSourceEndpoints.concat(upCdnEndpoints),
208
+ [SERVICE_NAME.IO]: isZ0
209
+ ? [
210
+ new Endpoint(
211
+ 'iovip.qiniuio.com',
212
+ endpointOptions
213
+ ),
214
+ new Endpoint(
215
+ 'iovip.qbox.me',
216
+ endpointOptions
217
+ )
218
+ ]
219
+ : [
220
+ new Endpoint(
221
+ 'iovip-' + regionId + '.qiniuio.com',
222
+ endpointOptions
223
+ ),
224
+ new Endpoint(
225
+ 'iovip-' + regionId + '.qbox.me',
226
+ endpointOptions
227
+ )
228
+ ],
229
+ [SERVICE_NAME.RS]: [
230
+ new Endpoint(
231
+ 'rs-' + regionId + '.qiniuapi.com',
232
+ endpointOptions
233
+ ),
234
+ new Endpoint(
235
+ 'rs-' + regionId + '.qbox.me',
236
+ endpointOptions
237
+ )
238
+ ],
239
+ [SERVICE_NAME.RSF]: [
240
+ new Endpoint(
241
+ 'rsf-' + regionId + '.qiniuapi.com',
242
+ endpointOptions
243
+ ),
244
+ new Endpoint(
245
+ 'rsf-' + regionId + '.qbox.me',
246
+ endpointOptions
247
+ )
248
+ ],
249
+ [SERVICE_NAME.API]: [
250
+ new Endpoint(
251
+ 'api-' + regionId + '.qiniuapi.com',
252
+ endpointOptions
253
+ ),
254
+ new Endpoint(
255
+ 'api-' + regionId + '.qbox.me',
256
+ endpointOptions
257
+ )
258
+ ],
259
+ [SERVICE_NAME.S3]: [
260
+ new Endpoint(
261
+ 's3.' + s3RegionId + '.qiniucs.com',
262
+ endpointOptions
263
+ )
264
+ ]
265
+ };
266
+
267
+ services = Object.assign(services, options.extendedServices || {});
268
+
269
+ return new Region({
270
+ regionId: regionId,
271
+ s3RegionId: s3RegionId,
272
+ services: services,
273
+ ttl: ttl,
274
+ createTime: createTime
275
+ });
276
+ };
277
+
278
+ /**
279
+ * @param {Region} regions
280
+ * @returns {Region}
281
+ */
282
+ Region.merge = function (...regions) {
283
+ const [source, ...rest] = regions;
284
+ const target = source.clone();
285
+ rest.forEach(s => {
286
+ // use Object.values when min version of Node.js update to ≥ v7.5.0
287
+ Object.keys(s.services).forEach(n => {
288
+ if (!target.services[n]) {
289
+ target.services[n] = s.services[n].map(endpoint => endpoint.clone());
290
+ return;
291
+ }
292
+ s.services[n].forEach(endpoint => {
293
+ if (!target.services[n].some(existsEndpoint => existsEndpoint.getValue() === endpoint.getValue())) {
294
+ target.services[n].push(endpoint.clone());
295
+ }
296
+ });
297
+ });
298
+ });
299
+ return target;
300
+ };
301
+
302
+ /**
303
+ * @returns {Promise<Region[]>}
304
+ */
305
+ Region.prototype.getRegions = function () {
306
+ return Promise.resolve([this]);
307
+ };
308
+
309
+ Region.prototype.clone = function () {
310
+ // use Object.entries when min version of Node.js update to ≥ v7.5.0
311
+ const services = Object.keys(this.services).reduce((s, n) => {
312
+ s[n] = this.services[n].map(endpoint => endpoint.clone());
313
+ return s;
314
+ }, {});
315
+ return new Region({
316
+ regionId: this.regionId,
317
+ s3RegionId: this.s3RegionId,
318
+ services: services,
319
+ ttl: this.ttl,
320
+ createTime: this.createTime
321
+ });
322
+ };
323
+
324
+ /**
325
+ * @param {Region} regions
326
+ * @returns {Region}
327
+ */
328
+ Region.prototype.merge = function (...regions) {
329
+ return Region.merge(this, ...regions);
330
+ };
331
+
332
+ Object.defineProperty(Region.prototype, 'isLive', {
333
+ /**
334
+ * @returns {boolean}
335
+ */
336
+ get: function () {
337
+ if (this.ttl < 0) {
338
+ return true;
339
+ }
340
+ // convert ms to s
341
+ const liveTime = Math.round((Date.now() - this.createTime) / 1000);
342
+ return liveTime < this.ttl;
343
+ },
344
+ enumerable: false,
345
+ configurable: true
346
+ });
347
+
348
+ exports.SERVICE_NAME = SERVICE_NAME;
349
+ exports.Region = Region;