# @abinnovision/nestjs-hatchet 中文文档

规范地址：https://npmcn.com/package/%40abinnovision/nestjs-hatchet/

版本：0\.9\.0
npm 元数据更新时间：2026-11-10T14:18:14.459Z
中文译文更新时间：2026-11-10T14:19:09.178Z
软件包许可：Apache-2\.0

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

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

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

- 包体积（解压后）：220 kB，136 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.12\.0
- 运行依赖：2 个
- peer 依赖：@nestjs/core ^11\.0\.0 \|\| ^12\.0\.0，@nestjs/common ^11\.0\.0 \|\| ^12\.0\.0，@hatchet-dev/typescript-sdk ^1\.45\.0
- 首次发布：2025-12-14T16:08:08.392Z
- 最新版本发布：2026-11-10T14:18:14.105Z
- 近 30 天下载量：3096（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：44（近 12 个月 44 个）

## 中文简介

NestJS 整合Hatchet工作流程与申报性任务和工作流程装饰器,以构建分布式工作系统.

## 安装

```sh
npm install @abinnovision/nestjs-hatchet
```

也可以使用：`pnpm add @abinnovision/nestjs-hatchet`、`yarn add @abinnovision/nestjs-hatchet`、`bun add @abinnovision/nestjs-hatchet`

## README

# @abinnovision/nestjs-hatchet (英语)

[![npm](https://img.shields.io/npm/v/@abinnovision/nestjs-hatchet?style=flat-square)](https://www.npmjs.com/package/@abinnovision/nestjs-hatchet)

雀巢JS整合 [标签](https://hatchet.run/) - 一个分布式工作流程管弦引擎。 提供类型安全的装饰,服务和事件处理,以构建强大的工作流程.

## 安装

```bash
yarn add @abinnovision/nestjs-hatchet @hatchet-dev/typescript-sdk
```

`@hatchet-dev/typescript-sdk` 是一个对等依赖,所以您的应用程序控制 SDK 版本。 导入 SDK 等类型 `Context` 直接从它.

## 快速启动

### 1\. 配置模块

```typescript
import { HatchetModule } from "@abinnovision/nestjs-hatchet";
import { Module } from "@nestjs/common";

@Module({
  imports: [
    HatchetModule.forRoot({
      config: {
        token: process.env.HATCHET_CLIENT_TOKEN,
        tls_config: { tls_strategy: "none" },
      },
      worker: { name: "my-worker" },
    }),
  ],
})
export class AppModule {}
```

工人通过Nest的停机钩被拦住 等待工作 结束。 打电话 `app.enableShutdownHooks()` 所以这也发生在 `SIGTERM`编号 :`SIGINT`。 。 。 . 让Hatchet SDK自己处理这些信号 设定 `handleKill: true` 内 工人的选择.

### 2\. 界定任务

```typescript
import { Host, Task, TaskCtx, taskHost } from "@abinnovision/nestjs-hatchet";
import { z } from "zod";

@Host({ name: "process-data" })
export class ProcessDataTask extends taskHost(z.object({ data: z.string() })) {
  @Task({})
  public async task(ctx: TaskCtx<typeof this>) {
    return { result: ctx.input.data.toUpperCase() };
  }
}
```

### 3\. 登记和举报

```typescript
import { Client, HatchetModule, taskRef } from "@abinnovision/nestjs-hatchet";
import { Injectable, Module } from "@nestjs/common";

import { ProcessDataTask } from "./process-data.task";

@Injectable()
export class MyService {
  constructor(private readonly client: Client) {}

  async process(data: string) {
    return this.client.run(taskRef(ProcessDataTask), { data });
  }
}

@Module({
  imports: [HatchetModule.forFeature(taskRef(ProcessDataTask))],
  providers: [ProcessDataTask, MyService],
})
export class ProcessDataModule {}
```

`forFeature()` 只向工人登记宿主。 每个主机也必须列出 输入 `providers` 模块,否则工人无法解决这个问题 应用程序无法启动 .

## 核心概念

### 任务

采用单一可执行方法的独立工作单位.

```typescript
@Host({ name: "cleanup" })
export class CleanupTask extends taskHost() {
  @Task({})
  public async task(ctx: TaskCtx<typeof this>) {
    return { cleaned: true };
  }
}
```

### 工作流量

具有任务依赖性的多步骤进程.

```typescript
@Host({ name: "order-workflow" })
export class OrderWorkflow extends workflowHost(
  z.object({ orderId: z.string() }),
) {
  @WorkflowTask<typeof OrderWorkflow>({ parents: [] })
  public async validate(ctx: WorkflowCtx<typeof this>) {
    return { valid: true };
  }

  @WorkflowTask<typeof OrderWorkflow>({ parents: ["validate"] })
  public async process(ctx: WorkflowCtx<typeof this>) {
    const validation = await ctx.parent(this.validate);
    return { processed: validation.valid };
  }
}
```

### 活动

具有schema验证的类型安全事件定义.

```typescript
// Define event
export const UserCreatedEvent = defineEvent(
  "user:created",
  z.object({ userId: z.string(), email: z.string().email() }),
);

// Workflow triggered by event
@Host({ name: "user-handler", onEvents: ["user:created"] })
export class UserHandlerWorkflow extends workflowHost() {
  @WorkflowTask<typeof UserHandlerWorkflow>({ parents: [] })
  public async handle(ctx: WorkflowCtx<typeof this>) {
    if (UserCreatedEvent.isCtx(ctx)) {
      return { userId: ctx.input.userId };
    }
  }
}

// Emit event
await client.emit(UserCreatedEvent, {
  userId: "123",
  email: "user@example.com",
});
```

## 高级使用

### 非锁定执行

```typescript
const runRef = await ctx.run(taskRef(SomeTask), input, { wait: false });
// Continue without waiting...
const result = await runRef.output; // Await when needed
```

### 散装事件排放

```typescript
await client.emit(OrderEvent, [
  { orderId: "1", total: 100 },
  { orderId: "2", total: 200 },
]);
```

### 任务截取器

任务截取器将每个任务执行包在工人身上,包括每个工作流程的任务,例如: 记录或追踪。 传过来 `forRoot()`编号 :`forRootAsync()` 并把他们列为供养者,因为他们 由应用程序而不是模块即时解决。 生产方 电话,看 [客户截取器](https://npmcn.com/package/%40abinnovision/nestjs-hatchet/#readme-client-interceptors)。 。 。 .

```typescript
import {
  BaseCtx,
  HatchetModule,
  TaskInterceptor,
} from "@abinnovision/nestjs-hatchet";
import { Injectable, Logger, Module } from "@nestjs/common";

@Injectable()
export class LoggingInterceptor extends TaskInterceptor {
  private readonly logger = new Logger(LoggingInterceptor.name);

  public async intercept<T>(ctx: BaseCtx<any>, next: () => Promise<T>) {
    this.logger.log(`Running ${ctx.fromSDK.taskName()}`);
    return next();
  }
}

@Module({
  imports: [
    HatchetModule.forRoot({
      config: {},
      worker: { name: "my-worker" },
      taskInterceptors: [LoggingInterceptor],
    }),
  ],
  providers: [LoggingInterceptor],
})
export class AppModule {}
```

### 客户截取器

客户端截取器包装制片方呼叫 `Client`数字 : `client.emit` (和 已贬值 `emitBulk`和 `client.run`扩展 `ClientInterceptor` 执行 `interceptEmit`, (中文(简体) ), `interceptRun`或两者兼有。 以 `clientInterceptors` 选项 `forRoot()`编号 :`forRootAsync()` 并列出在 `providers`。 。 。 .

以下例子宣传了一种关联性标识。 客户截取器写到 `additionalMetadata`并有一个任务拦截器 工人从 运行中任务的元数据 .

```typescript
import { AsyncLocalStorage } from "node:async_hooks";
import { randomUUID } from "node:crypto";

import {
  BaseCtx,
  ClientInterceptor,
  EmitCtx,
  EmitOptions,
  HatchetModule,
  TaskInterceptor,
  RunCtx,
  RunOptions,
} from "@abinnovision/nestjs-hatchet";
import { Injectable, Module } from "@nestjs/common";

export const correlation = new AsyncLocalStorage<{ id: string }>();

@Injectable()
export class CorrelationClientInterceptor extends ClientInterceptor {
  public override async interceptEmit(
    ctx: EmitCtx,
    next: (options?: EmitOptions) => Promise<unknown>,
  ) {
    const id = correlation.getStore()?.id;
    if (!id) return next();

    return next({
      ...ctx.options,
      additionalMetadata: {
        correlationId: id,
        ...ctx.options?.additionalMetadata,
      },
    });
  }

  public override async interceptRun(
    ctx: RunCtx,
    next: (options?: RunOptions) => Promise<unknown>,
  ) {
    const id = correlation.getStore()?.id;
    if (!id) return next();

    return next({
      ...ctx.options,
      additionalMetadata: {
        correlationId: id,
        ...ctx.options?.additionalMetadata,
      },
    });
  }
}

@Injectable()
export class CorrelationInterceptor extends TaskInterceptor {
  public async intercept<T>(ctx: BaseCtx<any>, next: () => Promise<T>) {
    const id = ctx.fromSDK.additionalMetadata()?.correlationId ?? randomUUID();
    return correlation.run({ id }, next);
  }
}

@Module({
  imports: [
    HatchetModule.forRootAsync({
      useFactory: () => ({ config: {}, worker: { name: "my-worker" } }),
      clientInterceptors: [CorrelationClientInterceptor],
      taskInterceptors: [CorrelationInterceptor],
    }),
  ],
  providers: [CorrelationClientInterceptor, CorrelationInterceptor],
})
export class AppModule {}
```

行为:

-   每个拦截器每次呼叫一次 散装弹出(数列有效载荷)和 `run` 与 数组输入每个计为一个调用 .
-   截取器只改变选项。 有效载荷或输入不可改变.
-   `next()` 保留当前选项. `next(options)` 替换如下: 截取器和SDK呼叫,所以散开 `ctx.options` 以保持呼叫者值.
-   `next(undefined)` 行为就像 `next()`。要放弃所有选项,请通过 `{}`。 。 。 .
-   `wait` 和返回形状 `client.run` 不能被推翻. `RunOptions` 不包括 `wait`。 。 。 .
-   与 `wait: true` (默认), `interceptRun` 覆盖全部运行,包括 等待输出。 与 `wait: false` 它只包着花序.
-   `childKey` 没有任何影响 `Client.run`。 。 。 .
-   拦截器按阵列顺序运行,第一个是最外层. 拦截器可能 跳过 `next()` 把电话传短路.
-   客户端截取类必须列出于 `providers`失败 应用拖带.
-   儿童运行始于 `ctx.run` 继承父方的 `additionalMetadata` 打开 弹夹引擎 `>= v0.104.0`所以他们不需要客户拦截器.

洞穴:

-   通话 `client.emit` 或者说 `client.run` 在一个拦截器内部 重新进入链. 保护自己避免重犯.
-   不支持请求范围拦截器提供者, 与任务相同 拦截器.

### 帮助方法

```typescript
@Host({ name: "my-task" })
export class MyTask extends taskHost(schema) {
  @Task({})
  public async task(ctx: TaskCtx<typeof this>) {
    return this.helper(ctx);
  }

  private async helper(ctx: HelperCtx<typeof this>) {
    return { result: ctx.input.value };
  }
}
```

## API 参考

### 模块

| 方法 | 说明 |
| --- | --- |
| `HatchetModule.forRoot(config)` | 以同步配置初始化 |
| `HatchetModule.forRootAsync(options)` | 初始化为 async 配置厂 |
| `HatchetModule.forFeature(...refs)` | 特征模块中的任务/工作流程注册 |

模块选项( extras to `forRoot`编号 :`forRootAsync`:

| 选项 | 说明 |
| --- | --- |
| `taskInterceptors` | `TaskInterceptor` 类 环绕每个任务执行 |
| `interceptors` | 折旧、使用 `taskInterceptors` |
| `clientInterceptors` | `ClientInterceptor` 类包 `emit` 财务报告和审定财务报表 `run` |

### 装饰者

| 装饰 | 说明 |
| --- | --- |
| `@Host(opts)` | 将类标为任务或工作流程主机 |
| `@Task(opts)` | 将方法标为独立任务 |
| `@WorkflowTask(opts)` | 将方法标为工作流程步骤 |

### 主机厂

| 工厂 | 说明 |
| --- | --- |
| `taskHost(schema?)` | 创建任务控点类 |
| `workflowHost(schema?)` | 创建 WorkflowHost 基础类 |

### 参考资料

| 函数 | 说明 |
| --- | --- |
| `taskRef(TaskClass)` | 创建类型安全任务引用 |
| `workflowRef(WorkflowClass)` | 创建类型安全的工作流程引用 |

### 客户端

| 方法 | 说明 |
| --- | --- |
| `client.run(ref, input, opts?)` | 执行任务/工作流程 |
| `client.emit(event, payload | payloads)` | 释放一个或许多事件 |
| `client.emitBulk(event, payloads)` | 释放多起事件( 过期) – 使用 `emit`(中文(简体) ) |

呼吁 `emit`, (中文(简体) ), `emitBulk` 财务报告和审定财务报表 `run` 通过注册 [客户端截取器](https://npmcn.com/package/%40abinnovision/nestjs-hatchet/#readme-client-interceptors)。 。 。 .

### 上下文类型

| 类型 | 说明 |
| --- | --- |
| `TaskCtx<T>` | 任务执行的背景 |
| `WorkflowCtx<T>` | 工作流程任务的背景 |
| `HelperCtx<T>` | 帮助方法的背景 |

### 上下文属性

```typescript
ctx.input       // Validated input data
ctx.fromSDK     // Underlying Hatchet SDK context
ctx.run(ref, input, opts ?)  // Invoke other tasks/workflows
ctx.parent(method)          // Get parent task output (WorkflowCtx only)
```

## 许可证

阿帕奇 - 2.0

## 常见问题

### @abinnovision/nestjs-hatchet 是什么？

NestJS 整合Hatchet工作流程与申报性任务和工作流程装饰器,以构建分布式工作系统\.

### 如何安装 @abinnovision/nestjs-hatchet？

在项目目录运行 npm install @abinnovision/nestjs-hatchet，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@nestjs/core（^11\.0\.0 \|\| ^12\.0\.0）、@nestjs/common（^11\.0\.0 \|\| ^12\.0\.0）、@hatchet-dev/typescript-sdk（^1\.45\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @abinnovision/nestjs-hatchet 支持 TypeScript 吗？

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

### @abinnovision/nestjs-hatchet 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @abinnovision/nestjs-hatchet 需要什么版本的 Node\.js？

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

### @abinnovision/nestjs-hatchet 可以商用吗？

@abinnovision/nestjs-hatchet 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @abinnovision/nestjs-hatchet 的下载量有多少？

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

### @abinnovision/nestjs-hatchet 还在维护吗？

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

