@ reconratio/ 错误
给出您的 JavaScript 或 TypeScript app 中的每一个错误 , 一个固定代码和一个清晰的消息, 每个屏幕都一样 .
npm install @gainratio/errors (节点22.13或更新,无属地.
在大多数应用中,每个 catch 块写入它自己的错误消息, 所以有一个问题
以几种不同方式出现. 一个人工智能供应商说"402必须付款",
一个屏幕上写着"没有信用" 而另一个屏幕上写着"检查你的模型"
设置". 您的日志使用第三个措辞, 您的 API 发送第四个 。 没有人可以
搜索日志以查找一个失败,用户会被告知错误的事情.
这个软件包提供了您整个应用程序的错误代码列表 。 你给我
无论失败( HTTP 状态、 抛出错误、 网络掉落) 它都会给出
返回一个代码,例如 ai.provider.out_of_credits,一个句子一个人可以
读取,与标准 JSON 机构相同的错误 您的 API 可以发送.
每种语言的代码都是一样的. 句子来自用户的
西班牙语和葡萄牙语译文
每个内置的密码船 与包裹.
它不记录、重试或报告错误。 你的应用仍然决定如何处理他们.
技术文件: 建筑 • 妇女 API 指南 • 妇女 开始开发者
试试看
-
制作空项目并安装软件包 :
mkdir try-errors && cd try-errors && npm init -y >/dev/null && npm install @gainratio/errors -
另存为
try.mjs(这是examples/try.mjs:
import { aiPack, corePack, defineErrorsWith } from "@gainratio/errors";
// Your app's list of error codes: 10 everyday ones + 9 for calling an AI service.
// Both lists claim some statuses (401, 404, 429, 5xx, timeouts). The list you
// pass first wins those, so here a 429 is http.rate_limited, not the ai.* code.
const errors = defineErrorsWith({}, corePack, aiPack);
// Four raw failures, the way they actually reach a catch block.
const failures = [
{ status: 402 }, // fetch() got "402 Payment Required"
{ status: 429 }, // fetch() got "429 Too Many Requests"
new TypeError("Failed to fetch"), // the network dropped
{ status: 418, message: "I'm a teapot" }, // something nobody planned for
];
for (const raw of failures) {
const code = errors.classify(raw);
console.log(code.padEnd(28), errors.describe(code));
}
// The same error as a JSON body your API can send back.
const body = errors.toProblemDetails("ai.provider.out_of_credits");
console.log(JSON.stringify(body));
// An Error you can throw. Its .message is the code, so logs stay searchable.
// The sentence comes from describe().
// Starting from a raw failure, problemFor() classifies it and keeps the
// observed status — including when the matched code registers several.
const fromRaw = errors.problemFor({ status: 422 });
console.log(JSON.stringify(fromRaw));
const err = errors.create("config.missing", { field: "API_KEY" });
console.log(err.message);
console.log(errors.describe(err.code, err.params));
- 运行
node try.mjs。这是此代码中的真正输出 仓库 :
ai.provider.out_of_credits Your provider account is out of credits. Add credits and try again.
http.rate_limited Too many requests. Wait a moment and try again.
net.unreachable Couldn't reach the server. Check your connection and try again.
internal.unknown Something went wrong. Try again.
{"type":"ai.provider.out_of_credits","title":"Your provider account is out of credits. Add credits and try again.","status":402}
{"type":"internal.unknown","title":"Something went wrong. Try again.","status":422}
config.missing
A required setting is missing: API_KEY.
每次失败都有一个代码和一个句子. 这429去 corePack是因为
http.rate_limited 因为 corePack 首先列出(参见
从哪一个代码列表开始) (中文(简体) ). 这个
茶壶没有匹配,所以它掉回 internal.unknown 而不是显示
原始错误。 JSON行是网络API的标准出错格式(RFC 9457,,
"问题细节",准备从服务器发送.
后两行是您可以读取的错误 throw。 。 .message 是密码
(单位:千美元)config.missing),不是句子,所以同样的失败总是记录同样的
可搜索文本。 为了显示句子,呼叫
errors.describe(err.code, err.params)。 。 。 .
要用另一种语言显示句子,见下一节.
在用户语言中显示错误
describe 以您的应用程序的翻译功能作为第三个参数 。 它问
键 errors.<code> (例如 errors.http.rate_limited) (中文(简体) ). 狦
翻译有那个密钥,用户看到了. 如果不是,他们就会看到英国人
从代码列表中的句子,从不带生键。 代码本身从未
更改,所以在每种语言中,您的日志和API保持不变.
包裹船西班牙号(es)和巴西葡萄牙语(pt) 全部24项
内置代码,作为 plain i18next JSON 文件. 把它们装入你旁边的i18
已经使用 :
npm install @gainratio/errors i18next
另存为 languages.mjs (这是
examples/languages.mjs运行 node languages.mjs数字 :
import { corePack, defineErrorsWith } from "@gainratio/errors";
import es from "@gainratio/errors/locales/es.json" with { type: "json" };
import pt from "@gainratio/errors/locales/pt.json" with { type: "json" };
import i18next from "i18next";
const errors = defineErrorsWith({}, corePack);
// Load the Spanish and Portuguese files that ship with the package into your
// own i18next. English needs no file: it comes from the list of codes.
await i18next.init({
fallbackLng: "en",
// describe() returns plain text, like its English. Escape it where you
// render it, not here, or "/" comes back as "/".
interpolation: { escapeValue: false },
resources: { es: { translation: es }, pt: { translation: pt } },
});
const code = errors.classify({ status: 429 }); // always "http.rate_limited"
for (const language of ["en", "es", "pt-BR", "fr"]) {
const t = i18next.getFixedT(language);
console.log(language.padEnd(6), errors.describe(code, {}, t));
}
// Values fill in the same way in every language.
const t = i18next.getFixedT("es");
console.log(
errors.describe("config.missing", { field: "Settings / AI key" }, t),
);
// On the wire, only the title changes. The code and type never do.
const body = errors.toProblemDetails(
code,
{},
{ title: errors.describe(code, {}, t) },
);
console.log(JSON.stringify(body));
实际输出 :
en Too many requests. Wait a moment and try again.
es Demasiadas solicitudes. Espera un momento e inténtalo de nuevo.
pt-BR Muitas solicitações. Aguarde um momento e tente de novo.
fr Too many requests. Wait a moment and try again.
Falta un ajuste obligatorio: Settings / AI key.
{"type":"http.rate_limited","title":"Demasiadas solicitudes. Espera un momento e inténtalo de nuevo.","status":429}
i18next进行语言匹配. pt-BR (和 pt-PT得到葡萄牙语
文件,以及没有文件的语言,例如 fr获得英语。 保留
escapeValue: false数字 : describe 返回纯文本,与其英文相同,
然后从你制造的地方逃出 随着i18next的默认值,一个像
Settings / AI key 回来作为 Settings / AI key。包裹从不选择
语言本身,从不导入 i18next。 形状为
t(key, params) 在它的位置工作。 对于自己的代码,添加 errors.<code>
用于您自己的翻译文件的密钥, 或设置 i18nKey 重用密钥的条目
你已经有了。 这个 API 指南
有细节.
如何运作
flowchart LR
A["Raw failure<br/>(402, timeout, network down)"] --> B["classify()<br/>rules from YOUR catalog"]
B --> C["One stable code<br/>ai.provider.out_of_credits"]
C --> D["describe()<br/>a sentence, in your language"]
C --> E["toProblemDetails()<br/>RFC 9457 JSON"]
应用程序启动时, 您会创建一个代码列表 。 每个代码都有一个类别,一个
英文句子,以及"HTTP station 402"等可选的标注规则
或者"错误消息提到超时". classify 看看你的失败
传入( 输入) status页:1 name,并只运行规则
您的列表,所以它返回一个代码 从列表中. describe 将代码变为
句子,和 toProblemDetails 把它变成JSON的身体。 没有隐藏
全局列表,没有网络或文件访问。 逻辑大约为260行TypeScript.
从哪一个代码列表开始
货包船4个现成名单. 它们是可选的。 您也可以写 每一个代码你自己.
| 列表 | 代码 | 用它当 |
|---|---|---|
corePack | 10个 | 几乎总是。 每天HTTP出错的代码,网络故障,超时,以及不良的配置. |
aiPack | 第9条 | 你的应用程序叫AI模型提供者:没有键,坏键,出自信用,利率有限. |
bundlePack | 页:1 | 您的应用程序下载并检查设备上的文件, 如模型或数据集 . |
starterPack | 第 18 条 | 仅供已经使用过的更老的应用程序使用. 新代码应当使用 corePack。 。 。 . |
starterPack 为较早的呼叫者保留被冻结; 新呼叫者应选择 corePack, (中文(简体) ), aiPack,或 bundlePack。 。 。 .
列表组合:您通过的每一列表的每个代码都会被注册. 如果两个名单
定义相同的代码,您得到一个 DuplicateCodeError 当应用程序启动时,永远不会
寂静胜相. 只有在两个不同的代码声称相同时才有秩序
状态。 在上述例子中, corePack 首先,所以429会变成
http.rate_limited 只有402个到达 aiPack。如果仅登记
处理给 AI 提供者的电话, put aiPack 首先,一个429成为
ai.provider.rate_limited编辑 建筑 医生列表
两种情况都一样.
aiPack 没有包罗万象的密码 所以 defineErrorsWith({}, aiPack) 独自一人
扔出并告诉你添加 corePack 或者从你的密码中选择一个
fallbackCode。 。 。 .
它不会做的
- 它不记录、重试或报告错误,也不发送任何东西 随便哪里 与您的日志或错误跟踪器对等 .
- 无法猜测只有你的应用程序知道的原因 。 添加带有规则的代码 对于它.
- 它不会为 HTML 逃避消息 。 离开你制造它们的地方 数值 所以永远不要通过 暗号.
- 它只在节点测试。 它没有节点的进口, 所以捆绑机可以运送 到浏览器, 但是没有浏览器测试在 CI 中运行 .
- 这是前1.0。 代号被视为稳定合同 但API可以 仍然在小版本之间变化。 见 变化。 。 。 .
什么时候用别的东西
| 如果你需要的话 | 使用 |
|---|---|
| 一个小应用程序中的一两个错误屏幕 | 几个手写口信. 这太过分了. |
| 只有文本的 HTTP 状态, 一种语言 | 一个小 switch (status) 帮助者 |
| 收集错误、警报和仪表板 | 哨兵等错误追踪器. 它与这个配对: 登录这个软件包给你的代码 . |
| 您的屏幕、 日志和 API 回复共享的一组错误代码 | @gainratio/errors |
安装
npm install @gainratio/errors # or: pnpm add @gainratio/errors
它需要节点22.13或更新而无依赖性. 没有什么 配置 。 唯一的设置是当没有匹配时返回哪个代码(参见 页:1 API 指南) (中文(简体) ).
开发
git clone https://github.com/gainratio/errors.git && cd errors
corepack enable && pnpm install
pnpm gate
pnpm gate 运行 lint、 类型检查、 100%覆盖栏的测试以及
建设。 同样的指令CI运行,需要不到20秒。 开始
开始开发者,覆盖节点
要使用的版本,代码的映射,以及第一次修改的行走.
详细情况
- 建筑问:如何
classify选择一个代码,四个 名单,JSON机构的安全规则, 安全模型, 测试证明. - API 指南: 每一个导出, 包含您自己的代码的示例, 翻译,自定义后退,并扔出一个被编码的错误.
- 开始开发者: 从新克隆 到一个经过的建筑物 和你的第一个变化.
- 交互式架构映射: 相同的设计 作为可点击的图表.
- 实例数字 :
try.mjs财务报告和审定财务报表languages.mjs(上文),out-of-credits.mjs,以及quickstart.mjs,它添加了您的代码和一个 西班牙语译名. - 警卫:威胁模型和如何报告出问题.
- 捐款额:更改的规则.
- 变化:每个版本的变化.
许可证
麻省理工学院. 见 自由主义。 。 。 .