errors.js
1.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* 结构化计费错误(§3 契约)。所有可预期的业务失败(余额不足 / 产品缺失 /
* 规则缺失 / 重复解锁)都以 `BillingError` 抛出,绝不返回魔法值或静默吞错。
*
* 字段语义:
* - `code`:稳定枚举(见 `BillingErrorCode`),调用方据此分流,不依赖 message 文案。
* - `retryable`:是否值得重试。业务约束类(余额不足 / 产品缺失 / 已解锁)= false;
* 预留给底层瞬时故障(DB 抖动)时由调用方包成 retryable=true。
* - `cause`:底层原始错误,保留链路。
*/
/**
* 失败原因枚举(稳定字符串)。
* @readonly
*/
export const BillingErrorCode = Object.freeze({
INSUFFICIENT_BALANCE: 'INSUFFICIENT_BALANCE',
PRODUCT_NOT_FOUND: 'PRODUCT_NOT_FOUND',
RULE_NOT_FOUND: 'RULE_NOT_FOUND',
ALREADY_UNLOCKED: 'ALREADY_UNLOCKED',
})
export class BillingError extends Error {
/**
* @param {object} info
* @param {string} info.code 见 `BillingErrorCode`
* @param {boolean} [info.retryable=false]
* @param {unknown} [info.cause]
* @param {string} [info.message]
*/
constructor({ code, retryable = false, cause, message }) {
super(message || `[billing] ${code}`)
this.name = 'BillingError'
this.code = code
this.retryable = Boolean(retryable)
if (cause !== undefined) this.cause = cause
}
}