@durability/transforms

中文文档
0.6.1发布于 2026/11/10ISCTypeScriptES Module构建来源已验证近 30 天下载 1.2万

Cloudflare RPC 的已打入调取器和调取器

中文使用文档
文档目录6 节
  1. 安装
  2. 虚拟设置
  3. 恢复已断裂的持久对象根
  4. 定义并安装变换器
  5. 内置呼叫器变换
  6. 手工包装

@ 耐用/ 变形

Cloudflare 持久对象和工人服务装订 RPC 的打入式呼叫器和呼叫器转换.

安装

npm install @durability/transforms

虚拟设置

Vite 插件需要 Wrangler , 读取其已验证的绑定配置, 包装可持久对象的根和所有其他对象绑定( 服务, KV, R2, Workflows, 队列等) , 生成添加声明 .with(...) 他们的怒火型。 瓦斯,秘密, 和模块blobs没有被触及。 诸如交叉工人服务等无法推断的Wrangler类型的捆绑物在运行时被包裹,但保留其手写声明.

const value = await env.CACHE.with(timeout, 1_000).get('key');
await env.MEDIA.with(retry, 2).put('file.txt', body);
const instance = await env.JOBS.with(timeout, 5_000).create({ params });

呼叫器只在客户端上运行 。 被调用者的变换和调用语境仍然需要您拥有的持久对象或工人 Entry 点 .

不进行变换,被包裹的捆绑行为与原作完全相同,包括同步方法和RPC承诺活线. 变换后,每一次呼叫都返回一个承诺 仍然支持管道连接,例如 stub.with(timeout, 1_000).counter().increment();连锁呼叫等待被改变的结果,而不是分享其来回. 关于返回物体的方法,例如: WorkflowInstance,没有改变.

对于 DurabilityRouting.client({...}) 财务报告和审定财务报表 DurabilitySemaphore.client({...}),插件注入 exportName 从目标持久对象的同模块导出。 目标必须是该模块输出的本地类,并被宣布为Wrangler本地持久对象类(包括迁移类). 支持导出别名 :

import { DurableObject } from 'cloudflare:workers';
import { DurabilityRouting as Routing } from 'durability/routing';

class InternalMailbox extends DurableObject {
  enqueue(input: string) {}
}
export { InternalMailbox as Mailbox };

const router = Routing.client({
  target: InternalMailbox,
  invoke: (stub, input) => stub.enqueue(input),
  ...defaults,
});

结果 exportName 附加在其它属性后,所以扩展不能覆盖它。 查取故意限于在同一工人模块中可见的类申报和出口;进口类,再出口,动态目标,以及非入行配置在目标可见时被单独或拒绝. 设定 exportName 很明显是那些案子的逃生口 明确 exportName 值永远不会改变.

import { defineConfig } from 'vite';
import { doTransforms } from '@durability/transforms/vite';

export default defineConfig({
  plugins: [doTransforms({ wrangler: './wrangler.jsonc' })],
});

生成的宣告默认为 do-transforms.generated.d.ts 在万克勒旁边 main 模块。 在应用程序的 TypeScript 项目中包含该文件 .

恢复已断裂的持久对象根

许多持久对象出错留下了根断裂,因此每次通过它发出的呼叫都会以相同的出错而失败. 启用 restoreBrokenStubs 重写插件的命名空间 get 财务报告和审定财务报表 getByName 调用后, 产生的分接点将替换为:

doTransforms({ wrangler: './wrangler.jsonc', restoreBrokenStubs: true });

失败的呼唤仍然拒绝,并且没有被重审. 下一个调用从命名空间获得一个与原参数相同的新分位符,这些参数只被评估一次,所以 env.MY_DO.get(env.MY_DO.newUniqueId()) 继续位于同一对象。 替换发生在呼叫器变换链的末端,所以每次尝试都是由 retry 运行在新鲜的树枝上。 没有插件, 使用 createRestorableStubFactory(env.MY_DO, 'getByName')(name)。 。 。 .

定义并安装变换器

import { DurableObject } from 'cloudflare:workers';
import {
  applyTransforms,
  createTransformContextTarget,
  defineTransform,
  registerTransform,
} from '@durability/transforms';

type RequestContext = { requestId?: string };

class ExampleObject extends DurableObject {
  setContext(context: RequestContext) {
    return createTransformContextTarget(this, context);
  }

  async greet(name: string) {
    return `Hello, ${name}`;
  }
}

const observability = defineTransform<ExampleObject, RequestContext>()
  .caller(
    (requestId: string) =>
      async ({ next }) =>
        next({ context: { requestId } })
  )
  .callee((metricName: string) => async ({ context, next }) => {
    console.log(metricName, context.requestId);
    return next();
  });

applyTransforms(ExampleObject, {
  methods: {
    greet: [registerTransform(observability, 'greet_calls')],
  },
});

const stub = env.EXAMPLE.getByName('example').with(
  observability,
  crypto.randomUUID()
);

await stub.greet('Ada');

applyTransforms 变异类原型并被累积. 在模块初始化时调用一次, 而不是每个请求或实例 .

为持久对象类定义的调用器变换也收到 actorId,则 DurableObjectId 中标的物体。 为其他目标定义的变换,例如: defineTransform<object>(),不看到字段,而永久对象转换不能附加在不是永久对象根的绑定上。 身份证留在呼叫者身上,不发给被呼叫者:

const actorLog = defineTransform<ExampleObject>().caller(
  () =>
    async ({ actorId, method, next }) => {
      console.log('rpc', method, actorId.toString());
      return next();
    }
);

await env.EXAMPLE.getByName('example').with(actorLog).greet('Ada');

变换上下文是不信任的调用元数据. 它适合申请身份证、追查和暗示,但不能被接受为身份、租赁、角色或授权的证据。 由独立认证的被调用人数据衍生授权.

内置呼叫器变换

import { retry, timeout } from '@durability/transforms';

const value = await stub
  .with(timeout, 5_000)
  .with(retry, {
    retries: 3,
    delay: ({ attempt }) => Math.min(1_000 * 2 ** (attempt - 1), 30_000),
  })
  .read();

呼叫者暂停等待, 但不会取消远程操作 。 每一次重试都是新的RPC引用,因此重试只使用"一能"方法或通过"一能"键. 何时 delay 被省略,重试时使用被盖住的指数后退并全焦.

其他内置设施包括:

  • betterResultCodec 用于序列化和再水合 better-result 在一个版本信封中的值。 遗留的0.1.0有效载荷因形状模糊而默认被否决;临时设定 acceptLegacy: true 只有在与一个年长的被调用者沟通时.
  • errorBoundary 将调用器可见的抛出转换为“更好的结果”出错.
  • abortAsSuccess 将预期持久对象重置为未定义的成功结果.
  • largeObjectStream 以传输大型 JSON 对象结果。 它需要一个标准Schema验证器,并强制使用一个调用器解码限制,但它仍然缓冲了完整的序列化表示;使用本土流进行无约束的数据.

手工包装

当 Vite 插件无法使用时, 直接包入目标或命名空间 :

import {
  createTransformStub,
  timeout,
  withTransforms,
} from '@durability/transforms';

const service = createTransformStub(env.MY_SERVICE).with(timeout, 5_000);
const namespace = withTransforms(env.MY_DURABLE_OBJECT);
const id = namespace.idFromName('example');
const object = namespace.get(id).with(timeout, 5_000);

版本与发布记录

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

版本发布日期距今
0.6.1latest2026/11/103 天前
0.6.02026/10/2123 天前
0.5.02026/10/1925 天前
0.4.02026/10/1826 天前
0.3.02026/10/051 个月前
0.2.02026/07/223 个月前

关于 @durability/transforms 的常见问题

@durability/transforms 是什么?

Cloudflare RPC 的已打入调取器和调取器

如何安装 @durability/transforms?

在项目目录运行 npm install @durability/transforms,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:better-result(^2.9.2)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@durability/transforms 支持 TypeScript 吗?

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

@durability/transforms 支持 ESM 还是 CommonJS?

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

@durability/transforms 可以商用吗?

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

@durability/transforms 的下载量有多少?

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

@durability/transforms 还在维护吗?

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