@absolutejs/errors

中文文档
0.10.3发布于 2026/10/28BSL-1.1TypeScriptES Module构建来源已验证近 30 天下载 3402

绝对JS基质的效果-内在,哨兵等同的例外捕捉. 创建 ErrorTracker 装饰@absolutejs/ audit + @absolutejs/遥测 + 持久问题存储; capt () 返回带有 per- sink 交付状态 + 键入( Data) 的捕获结果 .

中文使用文档
文档目录7 节
  1. 错误- as- 值
  2. API 密码
  3. Elysia 服务器集成
  4. 持久性问题(“问题”表面)
  5. 指纹
  6. 内存界限
  7. 许可证

@absolutejs/errors

绝对JS 效果内在、哨兵等同的例外捕捉 下结.

createErrorTracker 是一个薄薄的装饰器 @absolutejs/audit, (中文(简体) ), @absolutejs/telemetry, (中文(简体) ), 和一个耐用的问题商店. capture(error, context?) 是一个 Effect<CaptureOutcome, never> —— 说 无法捕捉错误本身 失败 - 一次就做六件事: - 不,不,不,不

  1. 计算马力 指纹 所以不同的错误是相同的 呼叫网站崩溃成一个"问题"
  2. 记录例外 活动 OTel 跨度当追踪器是 提供.
  3. 表示a 审计活动 (单位:千美元)kind: 'errors.captured') (中文(简体) ).
  4. 增加组 问题 + 将事件附加到持久 store和火灾 onIssue 关于一个新的/倒退的问题.
  5. 推入进程 最新错误 LRU 缓冲器。 。 。 .
  6. 每个指印的凸起 计量计数器。 。 。 .

嵌入 Error.cause 链条被附加到所储存的堆栈并保存为 结构化 extra.errorCauses 条目,包括数据库等驱动字段 错误代码、严重程度、细节和常规。 外部错误继续驱动 指纹的产生会增加诊断 而不破坏不同的手术.

浏览器 ingest 在可选功能后重新计算其犬形指纹 prepare() 步骤。 因此,同一故障的出处 即使其原始内容与块名不同,它们也同时释放. 摄入的边界还重新刻出具有证书的场、无记名/JWT值, badcrumb 文本, 以及 URL 查询/ 随机值, 在计划验证后但在此之前 指纹或缓冲。 默认允许这种深入防御的通行证; createIngestEndpoint({ redact: false }) 仅供主机使用 换成等同的可信任的边界政策,而习惯 redact(event) 函数可以扩展内置策略.

错误- as- 值

每个扇出( 审计 / 跟踪 / 存储 /) onIssue)是一个信任边界. 每一个都被包住了 所以它的失败变成了一个 键入, 标记值 (单位:千美元)Data.TaggedError——从未被吞入 匿名计数器或一个 onError(unknown)成果报告逐一沉入 交货状态('ok' | 'failed' | 'skipped'),所以一个呼叫者可以作出反应 具体地说——重新测试商店,审计损失的页面,忽略一个片面 onIssue - 详尽无遗 switch (failure._tag)。 。 。 .

import { Effect } from "effect";
import { status } from "elysia";
import { createErrorTracker, createMemoryIssueStore } from "@absolutejs/errors";
import { tracerOrNoop } from "@absolutejs/telemetry";

const errors = createErrorTracker({
  audit: broker, // @absolutejs/audit
  tracer: tracerOrNoop(otelProvider, "app"),
  store: createMemoryIssueStore(), // or @absolutejs/errors-postgres
  project: "acme",
  release: process.env.RELEASE,
  environment: "production",
  onIssue: (r) => alert(r.issue), // only on new / regression
});

// Effect API (primary):
const outcome = await Effect.runPromise(
  errors.capture(e, {
    tenant,
    target: `order_${orderId}`,
    tags: { component: "billing" },
  }),
);

// Promise edge (for Promise-world consumers) — identical outcome:
const out = await errors.captureException(e);

if (out.failures.length > 0) {
  for (const f of out.failures) {
    switch (f._tag) {
      case "StoreFailure":
        retryLater(f.cause);
        break; // f.cause: IssueStoreError
      case "AuditSinkFailure":
        page("audit lost", f.cause);
        break;
      case "TracerFailure":
      case "OnIssueFailure":
      case "FingerprintFailure":
        /* tolerate */ break;
    }
  }
}
return status(
  "Internal Server Error",
  `Request failed. Reference: ${out.fingerprint}`,
);

API 密码

createErrorTracker(options?: {
  audit?: { append: (event) => Promise<void> | void };
  tracer?: { startSpan?: (name) => Span };
  store?: IssueStore;          // durable "Issues" surface
  project?: string;            // default 'default'
  onIssue?: (r: IssueUpsertResult) => void | Promise<void>;  // new/regression only
  release?: string;
  environment?: string;
  fingerprint?: (error: Error, context: ErrorContext) => string | Promise<string>;
  maxRecent?: number;          // default 100
  maxFingerprints?: number;    // default 1000
  clock?: () => number;
}) => ErrorTracker
capture(error, context?)          => Effect<CaptureOutcome, never>   // primary
captureException(error, context?) => Promise<CaptureOutcome>         // Promise edge
recentErrors()                    => ReadonlyArray<CapturedError>
clearRecent()                     => void
metrics()                         => { captured, captureErrors, byFingerprint }
store?                            => IssueStore

type CaptureOutcome = {
  fingerprint: string;
  delivered: Record<'fingerprint'|'audit'|'tracer'|'store'|'onIssue', 'ok'|'failed'|'skipped'>;
  issue?: IssueUpsertResult;          // present iff the store delivered
  failures: CaptureFailure[];         // typed, tagged; empty ⇒ fully delivered
};

ErrorContext 携带标准的哨兵式分门别类信封: tenant, (中文(简体) ), target, (中文(简体) ), traceId, (中文(简体) ), spanId, (中文(简体) ), replayId, (中文(简体) ), tags, (中文(简体) ), extra, (中文(简体) ), level,可选语义 groupingKey组合键 信息或源框可能改变的合成或集成失败 在释放之间:

await errors.captureException(providerError, {
  groupingKey: "google-ads-tag-load",
  tags: { provider: "google" },
});

该密钥在信任的错误边界被验证并散列 。 客户从不 直接选择存储的指纹,项目范围界定仍然隔离 其它相同的密钥.

Elysia 服务器集成

@absolutejs/errors/elysia 提供一个具有单独设置的服务器插件 用于两个错误路径:

import { createErrorTracker, createMemoryIssueStore } from "@absolutejs/errors";
import { errorsPlugin, handledError } from "@absolutejs/errors/elysia";
import { Elysia, status } from "elysia";

const tracker = createErrorTracker({
  store: createMemoryIssueStore(), // use the Postgres adapter in production
});

const app = new Elysia()
  .use(
    errorsPlugin({
      tracker,
      server: {
        context: ({ request }) => ({
          tenant: request.headers.get("x-user-id") ?? undefined,
        }),
      },
      ingest: {
        path: "/ingest",
        reporting: {
          path: "/ingest/reports",
          project: "web",
          environment: "production",
          release: process.env.RELEASE_SHA,
        },
        // authorize, limits, buffer, symbolication, and drain settings
      },
    }),
  )
  .get("/report", async () => {
    try {
      return await buildReport();
    } catch (error) {
      return handledError(
        status(500, { message: "Unable to build the report." }),
        error,
      );
    }
  });

server 抓获、处理和未说明原因的5xx回复. 设定 captureReturned5xx 故意控制平面时的 反应,如准备状态 503 应通过健康保持可观察性 监测工作不成为一个例外问题。 上游收到 请求上下文、反应类型和状态; 扔出和明确处理 例外情况不受影响. 默认启用,可以禁用 server: false。 。 。 . ingest 挂载浏览器- 事件端点, 并选择输入; 通过 {} 要使用跟踪器 存储和默认值,或 false打开它 暴露任何路线.

ingest.reporting 挂载浏览器报告 API 接收器并转换崩溃, 同一经证实的问题的折旧、干预和政策执行 输油管。 发送回复信头 Reporting-Endpoints: default="/ingest/reports" 关于启用浏览器的文档 交货。 无法收集崩溃报告 ReportingObserver: 页面 JavaScript在浏览器-进程崩溃后不再运行.

此子路径只包含服务器, 包含效果支持的跟踪器/ 摄入器 运行时间。 浏览器代码应使用 @absolutejs/beacon (或 @absolutejs/observability)并且永远不导入 @absolutejs/errors/elysia。 。 。 . 仅转发服务器可省略 tracker 和提供 server.capture 直接; 仍然不变 errorsPlugin。 。 。 .

持久性问题(“问题”表面)

程序内缓冲器是用于分解的;对于持续可查询的 问题 产品(第一眼 / 最后眼 / 发生数 / 状态 / 受让人/回归探测)通过a store数字 :

import { createErrorTracker, createMemoryIssueStore } from "@absolutejs/errors";
// or, for durability:
// import { createPostgresIssueStore } from '@absolutejs/errors-postgres';

const errors = createErrorTracker({
  project: "acme",
  release: process.env.RELEASE,
  store: createMemoryIssueStore(), // swap for the Postgres adapter
  onIssue: (r) => {
    // fires ONLY on new / regression
    if (r.isNew || r.isRegression) alert(r.issue); // → @absolutejs/dispatch
  },
});

每次抓取都会增加一个分组问题(按 (project, fingerprint)(中文(简体) ) 并附上事件. onIssue 仅对价值的过渡开火 求人——a 新设 问题或问题 回归 联合国 resolved 问题再次出现, 这倒转回 unresolvedA级 resolved 问题 严重性不断升级,但从未降级; ignored 问题保持沉默.

存储写作是最佳的: 存储出局表面为输入 StoreFailure 内 outcome.failures (包装适配器) IssueStoreError),递增 captureErrors永远不要被俘虏.

适配器是 效应本土 ——每种方法返回一个 Effect 带有 类型 IssueStoreError 频道 (IssueStoreSchemaError 编号 : IssueStoreQueryError 编号 : IssueStoreSerializationError:

type IssueStore = {
  record: (event: StoredEvent) => Effect<IssueUpsertResult, IssueStoreError>;  // required
  listIssues?: (filter?) => Effect<IssueRecord[], IssueStoreError>;            // dashboard
  getIssue?:  (project, fingerprint) => Effect<Option<IssueRecord>, IssueStoreError>;
  setState?:  (project, fingerprint, 'unresolved'|'resolved'|'ignored') => Effect<void, IssueStoreError>;
  assign?:    (project, fingerprint, assignee | null) => Effect<void, IssueStoreError>;
  listEvents?:(project, fingerprint, limit?) => Effect<StoredEvent[], IssueStoreError>;
};

createMemoryIssueStore() 是零失败的引用执行 (用于dev/测试/单一进程); @absolutejs/errors-postgres 是耐久的适配器——两者都尊重相同的语义.

StoredEvent 携带 traceId 编号 : spanId (-) @absolutejs/telemetry(中文(简体) ) 财务报告和审定财务报表 replayId (-) @absolutejs/replay因此,仪表板可以交叉链接 一个问题 准确的追踪 和DOM重放. issueTitle() 编号 : issueCulprit() 以导出, 这样存储适配器从问题行中导出,而不连接到 内出.

handoffErrorContext(summary) 链接到 @absolutejs/handoff 通过有边框的标签和隐私安全 预测。 它不包括最新的有效载荷、电文、参考资料和 外相为相.

指纹

没有 groupingKey,默认指纹是 SHA-1 的 16-hex-char 前缀

error.name | normalized(message) | first-user-stack-frame

normalized() 将数字和引用的字符串字元脱去这样 user 'u_42' not found 财务报告和审定财务报表 user 'u_99' not found 组合在一起. 输入自定义 fingerprint 用于确定性测试或 域特定分组规则.

内存界限

  • maxRecent (默认) 100个)为进程内最近缓冲设置了上限.
  • maxFingerprints (默认) 1 000个盖上 byFingerprint 反相图,所以一个能合成独特错误的攻击者不能 吹出过程内存. 超过封顶,老字号被赶出去 任意——计数器按设计大致.

许可证

BSL-1.1 与主机错误跟踪 SaaS 的命名例外 (哨兵, Bugsnag, Rollbar, Honeybadger, Airbrake, 数据犬错误) 追踪 见 LICENSE。更改日期 : 2030-05-31 (英语) • Apache 2.0.

版本与发布记录

@absolutejs/errors 共发布 29 个版本,首次发布于 2026/05/31;过去 12 个月发布了 29 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.10.3latest2026/10/289 天前
0.10.22026/10/2413 天前
0.10.12026/10/2413 天前
0.10.02026/10/2215 天前
0.9.32026/09/271 个月前
0.9.22026/09/271 个月前

关于 @absolutejs/errors 的常见问题

@absolutejs/errors 是什么?

绝对JS基质的效果-内在,哨兵等同的例外捕捉. 创建 ErrorTracker 装饰@absolutejs/ audit + @absolutejs/遥测 + 持久问题存储; capt () 返回带有 per- sink 交付状态 + 键入( Data) 的捕获结果 .

如何安装 @absolutejs/errors?

在项目目录运行 npm install @absolutejs/errors,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:effect(>=3.22.0 <4)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@absolutejs/errors 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@absolutejs/errors 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@absolutejs/errors 可以商用吗?

@absolutejs/errors 使用 BSL-1.1 许可。声明的许可为 BSL-1.1,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@absolutejs/errors 的下载量有多少?

根据 npm 官方下载统计,@absolutejs/errors 在 2026/10/05 – 2026/11/03 这 30 天内被下载 3,402 次,日均约 113 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@absolutejs/errors 还在维护吗?

最新版本 0.10.3 发布于 2026/10/28(9 天前);至今共发布 29 个版本,其中过去 12 个月发布了 29 个;首次发布于 2026/05/31。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。