# @ayronforge/haversack 中文文档

规范地址：https://npmcn.com/package/%40ayronforge/haversack/

版本：0\.12\.0
npm 元数据更新时间：2026-10-22T14:47:38.447Z
中文译文更新时间：2026-11-08T03:50:27.661Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40ayronforge/haversack
原文对照：https://npmcn.com/package/%40ayronforge/haversack/?lang=original
项目主页：https://github.com/ayronforge/haversack#readme
源码仓库：https://github.com/ayronforge/haversack

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：304 kB，60 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=18
- 运行依赖：1 个
- peer 依赖：react \>=18，effect ^4\.0\.0，resend ^6\.0\.0，stripe ^22\.0\.0，posthog-js \>=1\.390\.2，react-email ^6\.0\.0，@clerk/backend ^3\.0\.0，@posthog/react \>=1\.10\.2 \<2，@workos-inc/node ^10\.0\.0，libphonenumber-js ^1\.12\.0
- 首次发布：2026-08-08T21:39:42.231Z
- 最新版本发布：2026-10-22T14:47:38.020Z
- 近 30 天下载量：1901（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：13（近 12 个月 13 个）

## 中文简介

已键入 TypeScript 工具箱: 后端集成效果服务 + PostHog 特性旗的有重点反应绑定

## 安装

```sh
npm install @ayronforge/haversack
```

也可以使用：`pnpm add @ayronforge/haversack`、`yarn add @ayronforge/haversack`、`bun add @ayronforge/haversack`

## README

# 哈勃萨克

> 背包是你们打包的包 到处都是.

每个新的 [效果](https://effect.website/) 项目从重建开始 同样的事情: 环绕Resend的电子邮件服务, 失败的特性标记 打开,一个有适当追踪跨度的条纹客户端,一个可持久性的限速器 对象, CPF 用真实的检查数字验证 。 哈勃萨克就是那个密码.. 从生产应用中提取,写成平庸的效果 从尾到尾, 然后装入一个包里 这样你就不会写两次了.

**所有东西都是打字效果服务.** 无松动函数,无 未类型错误, 没有全局配置 。 每个能力都是 `Context.Service` 与 标记错误、追踪跨度和a `Layer` 你像任何其他人一样作曲 包括配置、服务、测试层.

**只导入您使用的 .** 每个模块都是独立的子路径导出, 和重 SDK (Stripe, Resend, posthog- js,...) 是可选的对等点 依赖性:如果从未导入 `/stripe`你从不安装花脸.

```bash
bun add @ayronforge/haversack effect
```

Haversack是建立在效果4上(`effect@^4.0.0`) (中文(简体) ).

## 里面的东西

| 模块 | 它给你什么 |
| --- | --- |
| [`/schema`](https://npmcn.com/package/%40ayronforge/haversack/#readme-schemas) | Schema 构件: URL、 弹壳、 电话号码、 巴西文件( CPF、 CNPJ、 CEP) |
| [`/email`](https://npmcn.com/package/%40ayronforge/haversack/#readme-email) | 以响应- 电子邮件渲染和联系同步方式恢复后端的电子邮件服务 |
| [`/posthog`](https://npmcn.com/package/%40ayronforge/haversack/#readme-posthog) | 失败打开服务器解析和旗子, 加上官方 PostHog 提供者的反键旗政策 |
| [`/stripe`](https://npmcn.com/package/%40ayronforge/haversack/#readme-stripe) | 装有操作跟踪跨度和网签校验的SDK包装 |
| [`/auth/workos`, (中文(简体) ), `/auth/clerk`](https://npmcn.com/package/%40ayronforge/haversack/#readme-auth) | Auth SDK 客户端层,带有已编辑的配置和标记出错 |
| [`/cf`](https://npmcn.com/package/%40ayronforge/haversack/#readme-cloudflare) | 工人原始:限速器,分布式锁,队列,分析引擎,R2,工作流适配器 |
| [`/contracts`, (中文(简体) ), `/aws`](https://npmcn.com/package/%40ayronforge/haversack/#readme-contracts-and-aws) | 采用R2和S3的供应商中立布洛布存储端口 |
| [`/testing`](https://npmcn.com/package/%40ayronforge/haversack/#readme-testing) | 测试助手:服务跑者、执行者、SDK分枝 |
| `/errors`, (中文(简体) ), `/utils` | 标记错误原始、 错误正常化和纯助手 |

## 示马斯

可重复使用的效果Schema 构件,并带有犬类存储值和 单独的演示文稿格式.

```ts
import { Schema } from "effect";
import {
  CnpjFromString,
  CpfFromString,
  EmailAddressFromString,
  EndpointUrlFromString,
  formatCnpj,
  formatCpf,
  PhoneNumberFromString,
  SlugFromString,
  UuidFromString,
} from "@ayronforge/haversack/schema";

const cpf = Schema.decodeUnknownSync(CpfFromString)("529.982.247-25");
// "52998224725" — canonical digits in both decoded and encoded forms
formatCpf(cpf); // "529.982.247-25"

const cnpj = Schema.decodeUnknownSync(CnpjFromString)("11.222.333/0001-81");
// "11222333000181" — canonical digits in both decoded and encoded forms
formatCnpj(cnpj); // "11.222.333/0001-81"

const phone = Schema.decodeUnknownSync(PhoneNumberFromString({ defaultCountry: "BR" }))(
  "(11) 98765-4321",
);
// "+5511987654321" — canonical E.164

const email = Schema.decodeUnknownSync(EmailAddressFromString())("User@Example.COM");
// "User@example.com" — domain normalized, local part preserved by default

const host = Schema.decodeUnknownSync(EndpointUrlFromString)("https://api.example.com/");
// "https://api.example.com" — normalized, rejects query strings and fragments

const slug = Schema.decodeUnknownSync(SlugFromString)("Café com Leite!");
// "cafe-com-leite"

const uuid = Schema.decodeUnknownSync(UuidFromString)("0198A3FC-9DB1-7BD5-8A1E-2F6A1F4C9D10");
// "0198a3fc-9db1-7bd5-8a1e-2f6a1f4c9d10" — strict, canonical UUID
```

`CepLookup.layerViaCep({ fetch })` 解析已解析 `Cep` 无 抓取全球I/O并区分未找到、无法找到和缺陷 回应. `PhoneNumberFromString` 描述国际或明确 通过 libphone number-js 进行国家范围输入.

## 电子邮件

带有Resend适配器的提供者端口. 发送预发的 HTML 或响应电子邮件 元素,并同步联系人到段落和主题.

```ts
import { Effect, Layer, Redacted } from "effect";
import { EmailConfig, EmailLive, EmailService } from "@ayronforge/haversack/email";

const config = EmailConfig.layer({
  apiKey: Redacted.make(process.env.RESEND_API_KEY!),
  from: "Acme <noreply@acme.com>",
});

const program = Effect.gen(function* () {
  const email = yield* EmailService;
  yield* email.send({
    to: "user@example.com",
    subject: "Welcome",
    html: "<p>Hello!</p>",
    idempotencyKey: "welcome-user-1",
  });
}).pipe(Effect.provide(EmailLive.pipe(Layer.provide(config))));
```

## 邮箱

服务器端抓取和特性旗在没有 SDK 的情况下运行并工作 工人们 服务器发送和评价失败打开:失败日志和倒计时 而不是打破一个请求。 运输是效应 `FetchHttpClient.Fetch` 引用( 默认为 `globalThis.fetch`;测试和 主机给自己注入 `Effect.provideService(FetchHttpClient.Fetch, fn)`。 。 。 .

```ts
import { Effect, Layer, Redacted } from "effect";
import { FeatureFlags, PostHogAnalytics, PostHogConfig } from "@ayronforge/haversack/posthog";

const config = PostHogConfig.layer({
  projectToken: Redacted.make(process.env.POSTHOG_TOKEN!),
});

const program = Effect.gen(function* () {
  const analytics = yield* PostHogAnalytics;
  yield* analytics.track({ event: "signup", distinctId: "user_1" });

  const flags = yield* FeatureFlags;
  return yield* flags.isEnabled(
    { key: "new-checkout", fallback: false },
    { distinctId: "user_1" },
  );
}).pipe(
  Effect.provide(PostHogAnalytics.layer.pipe(Layer.provide(config))),
  Effect.provide(FeatureFlags.layer.pipe(Layer.provide(config))),
);
```

反应地物旗政策在 `@ayronforge/haversack/posthog/react` 财务报告和审定财务报表 与官员直接作曲 `@posthog/react` 供养. `useFeatureFlag` 通过订阅 `useSyncExternalStore`· ; `FeatureGate` 添加已键入倒计时 在未拥有SDK初始化、捕获或身份的情况下进行渲染.

## 条纹

每个呼叫命名的 SDK 包装器: 操作成为追踪 间距( n)`stripe.checkout.sessions.create`)和错误元数据.

```ts
import { Effect, Layer, Redacted } from "effect";
import { StripeClient, StripeConfig } from "@ayronforge/haversack/stripe";

const config = StripeConfig.layer({
  secretKey: Redacted.make(process.env.STRIPE_SECRET_KEY!),
  webhookSecret: Redacted.make(process.env.STRIPE_WEBHOOK_SECRET!),
});

const program = Effect.gen(function* () {
  const stripe = yield* StripeClient;
  const session = yield* stripe.use("checkout.sessions.create", (sdk) =>
    sdk.checkout.sessions.create({ mode: "subscription", line_items: [/* ... */] }),
  );
  return session.url;
}).pipe(Effect.provide(StripeClient.layer.pipe(Layer.provide(config))));
```

`verifyWebhook(payload, signature)` 用标签验证 webhook 签名 错误. `makeStripeClientFromSdk` 是测试中注射假SDK的接缝.

## 认证

WorkOS 的瘦客户端层( T)`/auth/workos`)和办事员(`/auth/clerk`, (中文(简体) ), 遵循相同的提供者模式: 配置已编辑的密钥, `use` 与 间距,标记错误。 办事员额外暴露 `useWebhook` 用于核实 网络事件.

## 云雾花

工人原始人,所有的约束导向——你通过明确的约束 图书馆从不读取一个全局性环境.

-   `RequestRateLimiter` ——固定窗口和标志盒过关 `effect/persistence`,与 `layerMemory` 用于试验和 `layerDurableObject(namespace)` 用于跨同位素限制。 命名空间点 执行 `RateLimiterRpc`; 应用程序 拥有坚持,迁徙和清理. 无法打开商店故障 .
-   `DistributedLock` 编号 : `withLock(key, effect)` —— 说 `acquireUseRelease` 生命周期 执行打字租赁RPC合同.
-   `makeQueueClientService(queue)` ——队列制作人出版 Cloudflare's 百通批发.
-   `AnalyticsEngine` ——带有Schema-decode的严格分析引擎SQL API 作行相会. 未成功的答复仍然是输入的查询错误;库确实如此 而不是从响应文本中推断出没有记录的 Cloudflare 错误语义 。 请求通过 `FetchHttpClient.Fetch` 引用,所以没有捕获到全局获取 .
-   `makeR2BlobStorageLayer(bucket)` 编号 : `R2BlobPresignerLive` -布洛布存储器 与R2的合同(见下文合同).
-   `@ayronforge/haversack/cf/workflow` —— 说 `makeCloudflareWorkflowEngineLayer({ workflow, step })` 适应 `effect/workflow` 工作流程:活动映射到 `step.do` 复试,耐用延后到 `sendEvent`编号 :`waitForEvent`, (中文(简体) ), 持久时钟到 `step.sleep`。 。 。 .

## 合同和AWS

`@ayronforge/haversack/contracts` 定义供应商中立端口——目前 `BlobStorage` (产出/物品/删除/存在/清单)和 `BlobPresigner`守则 端口; 选择每次运行的时间 :

```ts
import { Effect } from "effect";
import { BlobStorage } from "@ayronforge/haversack/contracts";
import { makeR2BlobStorageLayer } from "@ayronforge/haversack/cf";
import { S3BlobStorageLive, S3Config } from "@ayronforge/haversack/aws";

const program = Effect.gen(function* () {
  const storage = yield* BlobStorage;
  yield* storage.put("reports/q3.pdf", bytes, { contentType: "application/pdf" });
  const report = yield* storage.get("reports/q3.pdf", { maxBytes: 10_000_000 });
});

// In a Worker:  Effect.provide(program, makeR2BlobStorageLayer(env.BUCKET))
// Elsewhere:    Effect.provide(program, S3BlobStorageLive) + S3Config.layer({ ... })
```

`BlobPresigner.presignPut` 签名 `Content-Type` 当你经过的时候 `contentLength`准确的体型 浏览器发送 `Content-Length` 自动,所以上传一个身体是其它大小的 被拒绝 在写入前存储 :

```ts
const url = yield* presigner.presignPut({
  key: "uploads/avatar.png",
  contentType: "image/png",
  contentLength: file.size,
  expiresInSeconds: 600,
});
```

## 测试

-   `runWithService(tag, layer)` - 以允诺为主的选手 在测试中不重复提供/运行锅炉板.
-   `testExecutionContext()` - 一个假的"云花" `ExecutionContext` 谁 `drainWaitUntil()` 等待着火和遗忘的工作.
-   `testStub<T>(partial)` - 假冒SDK客户被制裁的逃生舱门 在测试。 永远不要在生产代码中使用它.
-   `applyTestEnvDefaults(record)` - 补缺 `process.env` 键.

## 环境配置

Haversack故意不装任何舱道 使用 [`@ayronforge/envil`](https://github.com/ayronforge/envil) 用于类型安全 环境验证并将解码值输入配置层.

## 捐款

```bash
bun install
bun run typecheck
bun test
bun run build   # bundles with tsdown and smoke-tests every entrypoint
```

欢迎提出问题和拉动请求。 如果你要加入一个新的整合, 遵循房子的风格: `Context.Service` 带有配置 层、有标记的错误和追踪跨度 —— 和多供应商能力 端口进入 `/contracts` 每个供应商执行一次.

## 许可证

麻省理工学院

## 常见问题

### @ayronforge/haversack 是什么？

已键入 TypeScript 工具箱: 后端集成效果服务 \+ PostHog 特性旗的有重点反应绑定

### 如何安装 @ayronforge/haversack？

在项目目录运行 npm install @ayronforge/haversack，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：effect（^4\.0\.0）、libphonenumber-js（^1\.12\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @ayronforge/haversack 支持 TypeScript 吗？

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

### @ayronforge/haversack 支持 ESM 还是 CommonJS？

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

### @ayronforge/haversack 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @ayronforge/haversack 可以商用吗？

@ayronforge/haversack 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @ayronforge/haversack 的下载量有多少？

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

### @ayronforge/haversack 还在维护吗？

最新版本 0\.12\.0 发布于 2026/10/22（16 天前）；至今共发布 13 个版本，其中过去 12 个月发布了 13 个；首次发布于 2026/08/09。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

