@sovovs/bycli 2.1.26 → 2.1.27

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,5 +1,5 @@
1
1
  import {
2
- AuthRequiredError, CommandExecutionError, EmptyResultError,
2
+ AuthRequiredError, CliError, CommandExecutionError, EmptyResultError, RateLimitedError,
3
3
  } from '@sovovs/bycli/errors';
4
4
  import { buildSecretSet, redactText } from './redact.js';
5
5
 
@@ -16,12 +16,17 @@ function safePhase(error, secrets) {
16
16
  }
17
17
 
18
18
  export function isEligibleArticleFallbackError(error) {
19
- return error instanceof CommandExecutionError || error instanceof EmptyResultError;
19
+ return error instanceof CommandExecutionError
20
+ || error instanceof EmptyResultError
21
+ || (error instanceof CliError && error.code === 'RATE_LIMITED');
20
22
  }
21
23
 
22
24
  export function withMissingFallbackName(operation, error) {
23
25
  const hint = `${error.hint ? `${error.hint} ` : ''}Sogou fallback requires the exact official-account name in --name.`;
24
26
  if (error instanceof EmptyResultError) return new EmptyResultError(operation, hint);
27
+ if (error instanceof CliError && error.code === 'RATE_LIMITED') {
28
+ return new RateLimitedError(error.message, hint);
29
+ }
25
30
  return new CommandExecutionError(error.message, hint);
26
31
  }
27
32
 
@@ -31,11 +36,17 @@ export function combineArticleFallbackErrors({
31
36
  fallbackError,
32
37
  credentials,
33
38
  }) {
34
- if (fallbackError instanceof AuthRequiredError) return fallbackError;
35
39
  const secrets = buildSecretSet(credentials);
36
40
  const primary = safePhase(primaryError, secrets);
37
41
  const fallback = safePhase(fallbackError, secrets);
38
42
  const hint = `Primary (${primary.code}): ${primary.summary}; fallback (${fallback.code}): ${fallback.summary}`;
43
+ if (primaryError instanceof CliError && primaryError.code === 'RATE_LIMITED') {
44
+ return new RateLimitedError(
45
+ 'Weixin article index was rate limited and Sogou fallback failed',
46
+ hint,
47
+ );
48
+ }
49
+ if (fallbackError instanceof AuthRequiredError) return fallbackError;
39
50
  if (primaryError instanceof EmptyResultError && fallbackError instanceof EmptyResultError) {
40
51
  return new EmptyResultError(operation, hint);
41
52
  }
@@ -1,4 +1,4 @@
1
- import { AuthRequiredError, CommandExecutionError } from '@sovovs/bycli/errors';
1
+ import { AuthRequiredError, CommandExecutionError, RateLimitedError } from '@sovovs/bycli/errors';
2
2
  import { buildSecretSet, redactText } from './redact.js';
3
3
 
4
4
  const DOMAIN = 'mp.weixin.qq.com';
@@ -34,8 +34,8 @@ export function mapArticleIndexPayload(payload) {
34
34
  throw new AuthRequiredError(DOMAIN, 'WeChat article-index credentials have expired');
35
35
  }
36
36
  if (ret === 200013 && normalizedMessage === 'freq control') {
37
- throw commandError(
38
- 'was rate limited (ret=200013)',
37
+ throw new RateLimitedError(
38
+ 'WeChat appmsgpublish was rate limited (ret=200013)',
39
39
  'Wait before retrying the WeChat article-index request; repeated retries may extend frequency control.',
40
40
  );
41
41
  }
@@ -122,6 +122,10 @@ function transportError(error, credentials) {
122
122
  const redactedHint = hint ? redactText(hint, secrets) : undefined;
123
123
  if (error instanceof AuthRequiredError && error.domain === DOMAIN
124
124
  && redactedMessage === message && redactedHint === hint) return error;
125
+ if (error instanceof RateLimitedError) {
126
+ if (redactedMessage === message && redactedHint === hint) return error;
127
+ return new RateLimitedError(redactedMessage, redactedHint);
128
+ }
125
129
  if (isWechatVerificationResponse(redactedMessage, redactedHint)) {
126
130
  return new AuthRequiredError(
127
131
  DOMAIN,
@@ -14,7 +14,7 @@
14
14
  * 2 Argument / usage error (ArgumentError)
15
15
  * 66 No input / empty result (EmptyResultError)
16
16
  * 69 Service unavailable (BrowserConnectError, adapter load failures)
17
- * 75 Temporary failure, retry later (TimeoutError) EX_TEMPFAIL
17
+ * 75 Temporary failure, retry later (TimeoutError, RateLimitedError) EX_TEMPFAIL
18
18
  * 77 Permission denied / auth needed (AuthRequiredError)
19
19
  * 78 Configuration error (ConfigError)
20
20
  * 130 Interrupted by Ctrl-C (set by tui.ts SIGINT handler)
@@ -51,6 +51,9 @@ export declare class BrowserConnectError extends CliError {
51
51
  export declare class CommandExecutionError extends CliError {
52
52
  constructor(message: string, hint?: string);
53
53
  }
54
+ export declare class RateLimitedError extends CliError {
55
+ constructor(message: string, hint?: string);
56
+ }
54
57
  export declare class ConfigError extends CliError {
55
58
  constructor(message: string, hint?: string);
56
59
  }
@@ -59,6 +59,11 @@ export class CommandExecutionError extends CliError {
59
59
  super('COMMAND_EXEC', message, hint, EXIT_CODES.GENERIC_ERROR);
60
60
  }
61
61
  }
62
+ export class RateLimitedError extends CliError {
63
+ constructor(message, hint) {
64
+ super('RATE_LIMITED', message, hint, EXIT_CODES.TEMPFAIL);
65
+ }
66
+ }
62
67
  export class ConfigError extends CliError {
63
68
  constructor(message, hint) {
64
69
  super('CONFIG', message, hint, EXIT_CODES.CONFIG_ERROR);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sovovs/bycli",
3
- "version": "2.1.26",
3
+ "version": "2.1.27",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },