@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,442 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const Readable = require('stream').Readable;
4
+
5
+ const getCrc32 = require('crc32');
6
+ const mime = require('mime');
7
+ const FormStream = require('formstream');
8
+
9
+ const conf = require('../conf');
10
+ const util = require('../util');
11
+ const rpc = require('../rpc');
12
+ const { SERVICE_NAME } = require('../httpc/region');
13
+ const { ResponseWrapper } = require('../httpc/responseWrapper');
14
+ const { EndpointsRetryPolicy } = require('../httpc/endpointsRetryPolicy');
15
+ const { RegionsRetryPolicy } = require('../httpc/regionsRetryPolicy');
16
+ const { Retrier } = require('../retry');
17
+ const {
18
+ AccUnavailableRetryPolicy,
19
+ handleReqCallback
20
+ } = require('./internal');
21
+
22
+ exports.FormUploader = FormUploader;
23
+ exports.PutExtra = PutExtra;
24
+
25
+ /**
26
+ * @class
27
+ * @param {conf.Config} [config]
28
+ * @constructor
29
+ */
30
+ function FormUploader (config) {
31
+ this.config = config || new conf.Config();
32
+ }
33
+
34
+ /**
35
+ * @private
36
+ * @param {Object} options
37
+ * @param {string} options.accessKey
38
+ * @param {string} options.bucketName
39
+ * @param {boolean} [options.retryable]
40
+ * @returns {Promise<Retrier>}
41
+ */
42
+ function _getRegionsRetrier (options) {
43
+ const {
44
+ bucketName,
45
+ accessKey,
46
+ retryable = true
47
+ } = options;
48
+
49
+ return this.config.getRegionsProvider({
50
+ bucketName,
51
+ accessKey
52
+ })
53
+ .then(regionsProvider => {
54
+ let retryPolicies;
55
+ if (this.config.accelerateUploading) {
56
+ retryPolicies = [
57
+ new AccUnavailableRetryPolicy(),
58
+ new EndpointsRetryPolicy({
59
+ skipInitContext: true
60
+ }),
61
+ new RegionsRetryPolicy({
62
+ regionsProvider,
63
+ serviceNames: [SERVICE_NAME.UP_ACC, SERVICE_NAME.UP]
64
+ })
65
+ ];
66
+ } else {
67
+ retryPolicies = [
68
+ new EndpointsRetryPolicy({
69
+ skipInitContext: true
70
+ }),
71
+ new RegionsRetryPolicy({
72
+ regionsProvider,
73
+ serviceNames: [SERVICE_NAME.UP]
74
+ })
75
+ ];
76
+ }
77
+
78
+ return new Retrier({
79
+ retryPolicies,
80
+ onBeforeRetry: (context, policy) => {
81
+ if (context.error) {
82
+ return retryable;
83
+ }
84
+ if (policy instanceof AccUnavailableRetryPolicy) {
85
+ return true;
86
+ }
87
+ return retryable && context.result && context.result.needRetry();
88
+ }
89
+ });
90
+ });
91
+ };
92
+
93
+ /**
94
+ * 上传可选参数
95
+ * @class
96
+ * @constructor
97
+ * @param {string} [fname] 请求体中的文件的名称
98
+ * @param {Object} [params] 额外参数设置,参数名称必须以x:开头
99
+ * @param {string} [mimeType] 指定文件的mimeType
100
+ * @param {string} [crc32] 指定文件的crc32值
101
+ * @param {number | boolean} [checkCrc] 指定是否检测文件的crc32值
102
+ * @param {Object} [metadata] 元数据设置,参数名称必须以 x-qn-meta-${name}: 开头
103
+ */
104
+ function PutExtra (
105
+ fname,
106
+ params,
107
+ mimeType,
108
+ crc32,
109
+ checkCrc,
110
+ metadata
111
+ ) {
112
+ this.fname = fname || '';
113
+ this.params = params || {};
114
+ this.mimeType = mimeType || null;
115
+ this.crc32 = crc32 || null;
116
+ this.checkCrc = checkCrc || true;
117
+ this.metadata = metadata || {};
118
+ }
119
+
120
+ /**
121
+ * @callback reqCallback
122
+ *
123
+ * @param { Error } err
124
+ * @param { Object } ret
125
+ * @param { http.IncomingMessage } info
126
+ */
127
+
128
+ /**
129
+ * @param {string} uploadToken
130
+ * @param {string | null} key
131
+ * @param {stream.Readable} fsStream
132
+ * @param {PutExtra | null} putExtra
133
+ * @param {reqCallback} callbackFunc
134
+ * @returns {Promise<ResponseWrapper>}
135
+ */
136
+ FormUploader.prototype.putStream = function (
137
+ uploadToken,
138
+ key,
139
+ fsStream,
140
+ putExtra,
141
+ callbackFunc
142
+ ) {
143
+ const preferredScheme = this.config.useHttpsDomain ? 'https' : 'http';
144
+
145
+ // PutExtra
146
+ putExtra = getDefaultPutExtra(
147
+ putExtra,
148
+ {
149
+ key
150
+ }
151
+ );
152
+
153
+ // Why need retrier even if retryable is false?
154
+ // Because the retrier is used to get the endpoints,
155
+ // which will be initialed by region policy.
156
+ const result = _getRegionsRetrier.call(this, {
157
+ bucketName: util.getBucketFromUptoken(uploadToken),
158
+ accessKey: util.getAKFromUptoken(uploadToken),
159
+ retryable: false
160
+ })
161
+ .then(retrier => Promise.all([
162
+ retrier,
163
+ retrier.initContext()
164
+ ]))
165
+ .then(([retrier, context]) => retrier.retry({
166
+ func: context => putReq(
167
+ context.endpoint.getValue({ scheme: preferredScheme }),
168
+ uploadToken,
169
+ key,
170
+ fsStream,
171
+ putExtra
172
+ ),
173
+ context
174
+ }));
175
+ handleReqCallback(result, callbackFunc);
176
+ return result;
177
+ };
178
+
179
+ /**
180
+ * @param {string} upDomain
181
+ * @param {string} uploadToken
182
+ * @param {string} key
183
+ * @param {Readable} fsStream
184
+ * @param {PutExtra} putExtra
185
+ * @returns {Promise<any>}
186
+ */
187
+ function putReq (
188
+ upDomain,
189
+ uploadToken,
190
+ key,
191
+ fsStream,
192
+ putExtra
193
+ ) {
194
+ const postForm = createMultipartForm(
195
+ uploadToken,
196
+ key,
197
+ fsStream,
198
+ putExtra
199
+ );
200
+ return new Promise((resolve, reject) => {
201
+ rpc.postMultipart(
202
+ upDomain,
203
+ postForm,
204
+ function (err, data, resp) {
205
+ if (err) {
206
+ err.resp = resp;
207
+ reject(err);
208
+ return;
209
+ }
210
+ resolve(new ResponseWrapper({
211
+ data,
212
+ resp
213
+ }));
214
+ }
215
+ );
216
+ });
217
+ }
218
+
219
+ /**
220
+ * 上传字节
221
+ * @param {string} uploadToken
222
+ * @param {string | null} key
223
+ * @param {any} body
224
+ * @param {PutExtra | null} putExtra
225
+ * @param {reqCallback} [callbackFunc]
226
+ * @returns {Promise<UploadResult>}
227
+ */
228
+ FormUploader.prototype.put = function (
229
+ uploadToken,
230
+ key,
231
+ body,
232
+ putExtra,
233
+ callbackFunc
234
+ ) {
235
+ const preferredScheme = this.config.useHttpsDomain ? 'https' : 'http';
236
+
237
+ // initial PutExtra
238
+ putExtra = getDefaultPutExtra(
239
+ putExtra,
240
+ {
241
+ key
242
+ }
243
+ );
244
+
245
+ // initial retrier and try upload
246
+ const result = _getRegionsRetrier.call(this, {
247
+ bucketName: util.getBucketFromUptoken(uploadToken),
248
+ accessKey: util.getAKFromUptoken(uploadToken)
249
+ })
250
+ .then(retrier => Promise.all([
251
+ retrier,
252
+ retrier.initContext()
253
+ ]))
254
+ .then(([retrier, context]) => retrier.retry({
255
+ func: context => {
256
+ const fsStream = new Readable();
257
+ fsStream.push(body);
258
+ fsStream.push(null);
259
+
260
+ return putReq(
261
+ context.endpoint.getValue({ scheme: preferredScheme }),
262
+ uploadToken,
263
+ key,
264
+ fsStream,
265
+ putExtra
266
+ );
267
+ },
268
+ context
269
+ }));
270
+ handleReqCallback(result, callbackFunc);
271
+ return result;
272
+ };
273
+
274
+ /**
275
+ * @param {string} uploadToken
276
+ * @param {any} body
277
+ * @param {PutExtra | null} putExtra
278
+ * @param {reqCallback} callbackFunc
279
+ * @returns {Promise<UploadResult>}
280
+ */
281
+ FormUploader.prototype.putWithoutKey = function (
282
+ uploadToken,
283
+ body,
284
+ putExtra,
285
+ callbackFunc
286
+ ) {
287
+ return this.put(uploadToken, null, body, putExtra, callbackFunc);
288
+ };
289
+
290
+ /**
291
+ * @param {string} uploadToken
292
+ * @param {string | null} key
293
+ * @param {stream.Readable} fsStream
294
+ * @param {PutExtra | null} putExtra
295
+ * @returns {FormStream}
296
+ */
297
+ function createMultipartForm (uploadToken, key, fsStream, putExtra) {
298
+ const postForm = new FormStream();
299
+ postForm.field('token', uploadToken);
300
+ if (key != null) {
301
+ postForm.field('key', key);
302
+ }
303
+ // fix the bug of formstream
304
+ // https://html.spec.whatwg.org/#multipart-form-data
305
+ const escapeFname = putExtra.fname.replace(/"/g, '%22')
306
+ .replace(/\r/g, '%0D')
307
+ .replace(/\n/g, '%0A');
308
+ postForm.stream(
309
+ 'file',
310
+ fsStream,
311
+ escapeFname,
312
+ putExtra.mimeType
313
+ );
314
+
315
+ // putExtra params
316
+ for (const k in putExtra.params) {
317
+ if (k.startsWith('x:')) {
318
+ postForm.field(k, putExtra.params[k].toString());
319
+ }
320
+ }
321
+
322
+ // putExtra metadata
323
+ for (const metadataKey in putExtra.metadata) {
324
+ if (metadataKey.startsWith('x-qn-meta-')) {
325
+ postForm.field(metadataKey, putExtra.metadata[metadataKey].toString());
326
+ }
327
+ }
328
+
329
+ let fileBody = [];
330
+ fsStream.on('data', function (data) {
331
+ fileBody.push(data);
332
+ });
333
+
334
+ fsStream.on('end', function () {
335
+ if (putExtra.checkCrc) {
336
+ if (putExtra.crc32 == null) {
337
+ fileBody = Buffer.concat(fileBody);
338
+ const bodyCrc32 = parseInt('0x' + getCrc32(fileBody));
339
+ postForm.field('crc32', bodyCrc32.toString());
340
+ } else {
341
+ postForm.field('crc32', putExtra.crc32);
342
+ }
343
+ }
344
+ });
345
+
346
+ return postForm;
347
+ }
348
+
349
+ /** 上传本地文件
350
+ * @param {string} uploadToken 上传凭证
351
+ * @param {string | null} key 目标文件名
352
+ * @param {string} localFile 本地文件路径
353
+ * @param {PutExtra | null} putExtra 额外选项
354
+ * @param {reqCallback} [callbackFunc] 回调函数
355
+ * @returns {Promise<UploadResult>}
356
+ */
357
+ FormUploader.prototype.putFile = function (
358
+ uploadToken,
359
+ key,
360
+ localFile,
361
+ putExtra,
362
+ callbackFunc
363
+ ) {
364
+ const preferredScheme = this.config.useHttpsDomain ? 'https' : 'http';
365
+
366
+ // initial PutExtra
367
+ putExtra = putExtra || new PutExtra();
368
+ if (!putExtra.mimeType) {
369
+ putExtra.mimeType = mime.getType(localFile);
370
+ }
371
+
372
+ if (!putExtra.fname) {
373
+ putExtra.fname = path.basename(localFile);
374
+ }
375
+
376
+ putExtra = getDefaultPutExtra(
377
+ putExtra,
378
+ {
379
+ key
380
+ }
381
+ );
382
+
383
+ // initial retrier and try upload
384
+ const result = _getRegionsRetrier.call(this, {
385
+ bucketName: util.getBucketFromUptoken(uploadToken),
386
+ accessKey: util.getAKFromUptoken(uploadToken)
387
+ })
388
+ .then(retrier => Promise.all([
389
+ retrier,
390
+ retrier.initContext()
391
+ ]))
392
+ .then(([retrier, context]) => retrier.retry({
393
+ func: context => {
394
+ const fsStream = fs.createReadStream(localFile);
395
+ return putReq(
396
+ context.endpoint.getValue({ scheme: preferredScheme }),
397
+ uploadToken,
398
+ key,
399
+ fsStream,
400
+ putExtra
401
+ );
402
+ },
403
+ context
404
+ }));
405
+ handleReqCallback(result, callbackFunc);
406
+ return result;
407
+ };
408
+
409
+ /** 上传本地文件
410
+ * @param {string} uploadToken 上传凭证
411
+ * @param {string} localFile 本地文件路径
412
+ * @param {PutExtra | null} putExtra 额外选项
413
+ * @param callbackFunc 回调函数
414
+ * @returns {Promise<UploadResult>}
415
+ */
416
+ FormUploader.prototype.putFileWithoutKey = function (
417
+ uploadToken,
418
+ localFile,
419
+ putExtra,
420
+ callbackFunc
421
+ ) {
422
+ return this.putFile(uploadToken, null, localFile, putExtra, callbackFunc);
423
+ };
424
+
425
+ /**
426
+ * @param {PutExtra} putExtra
427
+ * @param {Object} options
428
+ * @param {string} options.key
429
+ * @returns {PutExtra}
430
+ */
431
+ function getDefaultPutExtra (putExtra, options) {
432
+ putExtra = putExtra || new PutExtra();
433
+ if (!putExtra.mimeType) {
434
+ putExtra.mimeType = 'application/octet-stream';
435
+ }
436
+
437
+ if (!putExtra.fname) {
438
+ putExtra.fname = options.key || 'fname';
439
+ }
440
+
441
+ return putExtra;
442
+ }
@@ -0,0 +1,214 @@
1
+ // internal
2
+ // DO NOT use this file, unless you know what you're doing.
3
+ // Because its API may make broken change for internal usage.
4
+
5
+ const { RetryPolicy } = require('../retry');
6
+
7
+ // --- split to files --- //
8
+ /**
9
+ * @typedef {RetryPolicyContext} TokenExpiredRetryPolicyContext
10
+ * @property {string} resumeRecordFilePath
11
+ * @property {'v1' | 'v2' | string} uploadApiVersion
12
+ */
13
+
14
+ /**
15
+ * @class
16
+ * @extends RetryPolicy
17
+ * @param {Object} options
18
+ * @param {string} options.uploadApiVersion
19
+ * @param {function} options.recordDeleteHandler
20
+ * @param {function} options.recordExistsHandler
21
+ * @param {number} [options.maxRetryTimes]
22
+ * @constructor
23
+ */
24
+ function TokenExpiredRetryPolicy (options) {
25
+ this.id = Symbol(this.constructor.name);
26
+ this.uploadApiVersion = options.uploadApiVersion;
27
+ this.recordDeleteHandler = options.recordDeleteHandler;
28
+ this.recordExistsHandler = options.recordExistsHandler;
29
+ this.maxRetryTimes = options.maxRetryTimes || 1;
30
+ }
31
+
32
+ TokenExpiredRetryPolicy.prototype = Object.create(RetryPolicy.prototype);
33
+ TokenExpiredRetryPolicy.prototype.constructor = TokenExpiredRetryPolicy;
34
+
35
+ /**
36
+ * @param {Object} context
37
+ * @returns {Promise<void>}
38
+ */
39
+ TokenExpiredRetryPolicy.prototype.initContext = function (context) {
40
+ context[this.id] = {
41
+ retriedTimes: 0,
42
+ uploadApiVersion: this.uploadApiVersion
43
+ };
44
+ return Promise.resolve();
45
+ };
46
+
47
+ /**
48
+ * @param {Object} context
49
+ * @returns {boolean}
50
+ */
51
+ TokenExpiredRetryPolicy.prototype.shouldRetry = function (context) {
52
+ const {
53
+ retriedTimes,
54
+ uploadApiVersion
55
+ } = context[this.id];
56
+
57
+ if (
58
+ retriedTimes >= this.maxRetryTimes ||
59
+ !this.recordExistsHandler()
60
+ ) {
61
+ return false;
62
+ }
63
+
64
+ if (!context.result) {
65
+ return false;
66
+ }
67
+
68
+ if (uploadApiVersion === 'v1' &&
69
+ context.result.resp.statusCode === 701
70
+ ) {
71
+ return true;
72
+ }
73
+
74
+ if (uploadApiVersion === 'v2' &&
75
+ context.result.resp.statusCode === 612
76
+ ) {
77
+ return true;
78
+ }
79
+
80
+ return false;
81
+ };
82
+
83
+ /**
84
+ * @param {Object} context
85
+ * @returns {Promise<void>}
86
+ */
87
+ TokenExpiredRetryPolicy.prototype.prepareRetry = function (context) {
88
+ context[this.id].retriedTimes += 1;
89
+ return new Promise(resolve => {
90
+ if (!this.recordExistsHandler()) {
91
+ resolve();
92
+ return;
93
+ }
94
+ this.recordDeleteHandler();
95
+ resolve();
96
+ });
97
+ };
98
+
99
+ exports.TokenExpiredRetryPolicy = TokenExpiredRetryPolicy;
100
+
101
+ /**
102
+ * @class
103
+ * @extends RetryPolicy
104
+ * @constructor
105
+ */
106
+ function AccUnavailableRetryPolicy () {
107
+ }
108
+
109
+ AccUnavailableRetryPolicy.prototype = Object.create(RetryPolicy.prototype);
110
+ AccUnavailableRetryPolicy.prototype.constructor = AccUnavailableRetryPolicy;
111
+
112
+ AccUnavailableRetryPolicy.prototype.initContext = function (context) {
113
+ return Promise.resolve();
114
+ };
115
+
116
+ AccUnavailableRetryPolicy.prototype.isAccNotAvailable = function (context) {
117
+ try {
118
+ return context.result.resp.statusCode === 400 &&
119
+ context.result.resp.data.error.includes('transfer acceleration is not configured on this bucket');
120
+ } catch (_err) {
121
+ return false;
122
+ }
123
+ };
124
+
125
+ AccUnavailableRetryPolicy.prototype.shouldRetry = function (context) {
126
+ if (!context.result) {
127
+ return false;
128
+ }
129
+ if (!context.alternativeServiceNames.length) {
130
+ return false;
131
+ }
132
+ const [nextServiceName] = context.alternativeServiceNames;
133
+ if (
134
+ !context.region.services[nextServiceName] ||
135
+ !context.region.services[nextServiceName].length
136
+ ) {
137
+ return false;
138
+ }
139
+ return this.isAccNotAvailable(context);
140
+ };
141
+
142
+ AccUnavailableRetryPolicy.prototype.prepareRetry = function (context) {
143
+ if (!context.alternativeServiceNames.length) {
144
+ return Promise.reject(new Error(
145
+ 'No alternative service available.'
146
+ ));
147
+ }
148
+
149
+ context.serviceName = context.alternativeServiceNames.shift();
150
+ [context.endpoint, ...context.alternativeEndpoints] = context.region.services[context.serviceName];
151
+ if (!context.endpoint) {
152
+ return Promise.reject(new Error(
153
+ 'No alternative endpoint available.'
154
+ ));
155
+ }
156
+
157
+ return Promise.resolve();
158
+ };
159
+
160
+ exports.AccUnavailableRetryPolicy = AccUnavailableRetryPolicy;
161
+
162
+ /**
163
+ * @param {Error} err
164
+ * @param {string} msg
165
+ */
166
+ function getNoNeedRetryError (err, msg) {
167
+ err.message = msg + '\n' + err.message;
168
+ err.noNeedRetry = true;
169
+ return err;
170
+ }
171
+ exports.getNoNeedRetryError = getNoNeedRetryError;
172
+
173
+ /**
174
+ * @param fn
175
+ * @returns {(function(...[*]): (*|undefined))|*}
176
+ */
177
+ function wrapTryCallback (fn) {
178
+ if (typeof fn !== 'function') {
179
+ return () => {};
180
+ }
181
+ return (...args) => {
182
+ try {
183
+ return fn(...args);
184
+ } catch (err) {
185
+ console.warn(
186
+ 'WARNING:\n' +
187
+ 'qiniu SDK will migrate API to Promise style gradually.\n' +
188
+ 'The callback style will not be removed for now,\n' +
189
+ 'but you should catch your error in your callback function itself'
190
+ );
191
+ console.error(err);
192
+ }
193
+ };
194
+ }
195
+
196
+ /**
197
+ * Compatible with callback style
198
+ * Could be removed when make break changes.
199
+ */
200
+ function handleReqCallback (responseWrapperPromise, callbackFunc) {
201
+ if (typeof callbackFunc !== 'function') {
202
+ return;
203
+ }
204
+ const wrappedCallback = wrapTryCallback(callbackFunc);
205
+ responseWrapperPromise
206
+ .then(({ data, resp }) => {
207
+ wrappedCallback(null, data, resp);
208
+ })
209
+ .catch(err => {
210
+ wrappedCallback(err, null, err.resp);
211
+ });
212
+ }
213
+
214
+ exports.handleReqCallback = handleReqCallback;