@btravstack/core

中文文档
0.58.0发布于 2026/11/08MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 1.2万

应用程序内核: 启动一个 di 模块进入运行中的进程, 并停止它而不失去工作

中文使用文档
文档目录6 节
  1. 实例
  2. 对于一个运行时间作者
  3. 应用基础设施出口
  4. 诊断性披露
  5. 你得到的东西
  6. 许可证

@ btravstack/ core (中文(简体) )

应用程序内核: 启动 a @btravstack/di 模块进入 a 运行进程,并在不失去工作的情况下再次停止它——一个生命周期状态 1个工作单位登记册、1个 Runtime 合同。 它一无所知 关于HTTP,AMQP或Temperal, 从来没有扔,也没有打电话 process.exit。 。 。 .

📖 文档 • 妇女 开始 • 妇女 参考文献 • 妇女 API 参考

pnpm add @btravstack/core @btravstack/config @btravstack/di unthrown

@btravstack/config, (中文(简体) ), @btravstack/di 财务报告和审定财务报表 unthrown 为: 端点 依赖关系 安装所有四个。 内核本身取决于 node: 只有内建 节点 >=22。 。 。 .

实例

应用程序是 二模块 。 A 类 运行时间 是该模块的一项服务, 在申报的港口上提供 RuntimePort· ; start 在那里发现它,建造 和驱动它找到的东西。 运输启动器 (单位:千美元)@btravstack/http-server, (中文(简体) ), @btravstack/temporal-worker, (中文(简体) ), @btravstack/amqp-worker)提供实时运行;这个是定时器,所以 样本保持自成一体:

import { Module, Port, Provider } from "@btravstack/di";
import {
  RuntimePort,
  runMain,
  start,
  type Runtime,
  type Serving,
} from "@btravstack/core";
import { Ok, OkAsync } from "unthrown";

class Greeter extends Port("Greeter")<{
  readonly greet: (name: string) => string;
}> {}

const AppModule = Module("App")({
  provides: [
    Provider(Greeter)({
      inject: {},
      value: { greet: (name: string) => `hello, ${name}` },
    }),
  ],
  exports: [Greeter],
});

// A runtime owns the transport; the kernel owns the lifecycle. This one is a
// timer, so the sample stays self-contained — no published runtime models a
// timer, and `@btravstack/http-server` would pull in a real dependency this
// sample doesn't need.
const ticker: Runtime<typeof Greeter> = {
  name: "ticker",
  resolves: [Greeter],
  start: (host) => {
    const timer = setInterval(() => {
      // Every piece of work goes through `host.run`: that is what makes it
      // count towards the drain, and what gives it an `AbortSignal`.
      //
      // The unit's `Result` is the runtime's to map — the kernel hands it back
      // and stays out of it. A timer has nowhere to return one, so it observes
      // it instead; dropping it would hide the work's `Err` *and* a `Defect`.
      void host
        .run({ kind: "tick", id: `${Date.now()}` }, (unit, signal) =>
          signal.aborted ? Ok("") : Ok(unit.ctx.get(Greeter).greet("world")),
        )
        .tapFailure((failure) => {
          process.stderr.write(`${JSON.stringify({ tick: failure.tag })}\n`);
        });
    }, 1_000);

    const serving: Serving = {
      // Stop accepting new work. In-flight units are the kernel's business.
      drain: () => {
        clearInterval(timer);
        return OkAsync();
      },
      stop: () => OkAsync(),
    };

    return OkAsync(serving);
  },
};

// A runtime is a service the module provides, on a port declared over
// `RuntimePort` — `start` finds it by that port in the module's exports. The
// composition root is what differs between an `api`, a `worker` and a
// `consumer` process; the application module is the same in all three.
class Ticker extends RuntimePort<Runtime<typeof Greeter>> {}

const TickerApp = Module("TickerApp")({
  imports: [AppModule],
  provides: [Provider(Ticker)({ inject: {}, value: ticker })],
  exports: [Greeter, Ticker],
});

await runMain(TickerApp);

runMain 是前门: 它给模块穿靴子,等待应用程序退出 然后将结果变成一个过程退出代码——一个呼叫,和一个整体 main.ts它的内在 start,随即返回 RunningApp 并且对这个过程没有任何决定。 比赛时间宣布了 needs 与模块的输出值对照检查 编译时间 a 包括: TickerApp 不导出 Greeter 调用时出现类型错误, 因此 是一个完全不导出运行时端口的模块.

对于一个运行时间作者

Serving 携带可选的第三名成员, stopped 频道 a 运行时间报告自己的死亡, () => AsyncResult<void, never>没有它 寿命周期只移动到一个信号或一个 stop() 一个工人 民意测验环死后仍活着 /readyz 回复 200: 服务处的吊舱 结束点,没有消耗。 一个可以自行停止的运行时间应该 执行它;上面的勾选符没有,因为 setInterval 没有第三个 因此,这个字段是可选的,而不是要求的.

义务是不能表示: 停车后退出 内核要求. 一条在平凡的道路上安顿下来的手臂 干净的关闭. @btravstack/temporal-worker 已开展工作的执行,以及 运行时间参考 声明合同全文.

两个帮手坐在旁边 Runtime 合同,因为每个运输需要 任何人不得拥有私人副本:

  • releasedBy(signal, running) —— 说 running,但不迟于内核 排污期限 Serving.drain 他们的工作靠别人的 时钟.
  • traceIdOfTraceparent(header) - W3C的微量识别域 traceparent,没有其他的: 父母的半身身份被丢掉,因为 UnitMeta.traceId 是一种关联性 id 而不是一个跨度上下文。 答复 undefined 对于任何规格都称无效——一个错误的 页眉,一个全零的痕量代号,一个全零的父代码,保留版本 ff 所以你的运行时间 回到自己的身份 而不是通过一个 意为无相. 更高版本的额外字段被读取而不是拒绝.

应用基础设施出口

infrastructureExports(imports, provides) 返回可公开的 Logger 财务报告和审定财务报表 HealthChecks 导入模块和根提供者的端口. InfrastructureExports<I, P> 在类型级别上描述这些端口. 它遵循整个模块的再出口,同时保持私人供应商和商业 隐藏端口。 应用程序启动者在自己的运行时间输出的同时使用它.

诊断性披露

DiagnosticPolicy 用于诊断的共享结构合同 信息、属性和原因。 将同一政策对象明确传递给 记录、追踪和临时适配器。 内容 message, (中文(简体) ), attributes 财务报告和审定财务报表 cause 方法必须是同步的,并且不能抛出; 渲染会留下正本 结果及其故障通道不变.

@btravstack/observability 执行生产政策 作为 diagnosticPolicy() 并暴露敏感调试作为明确独立的调试 选择。 该内核不执行披露规则就宣布该类型,或 添加一个政策端口。 见 观察合同。 。 。 .

你得到的东西

  • 库伯奈特斯的下水道. 在SIGTERM:准备翻转错误 内核等待 preDrainDelayMs (单位:千美元)PRE_DRAIN_DELAY_MS默认值 5_000) 之前 告诉运行时间停止接受——终点去除是最终 一致——然后飞行中的工作得到 drainTimeoutMs (单位:千美元)DRAIN_TIMEOUT_MS, (中文(简体) ), 默认 20_000); 任何尚未打开的都被中止并报告 abandoned。随后的撕裂得到 stopTimeoutMs (单位:千美元)STOP_TIMEOUT_MS默认值 5_000因此,一个 release 永无止境 报告为 abandonedAt: "stop" 而不是离开进程 stopping 没有退出报告。 每一个等待的第二个信号停止 一次 一次吗 三分钱到舱里 terminationGracePeriodSeconds 默认 30 s,这就是部署设置它们的原因,而选择方案只给它们钉上钉子.
  • 出自国机. GET /livez 财务报告和审定财务报表 GET /readyz 打开 PROBE_PORT (默认) 9000和 PROBE_HOST (默认) 0.0.0.0,所以一个 立方体 httpGet 探测器到达它们,在图建之前. A 类 HealthCheck 能够选择加入 /readyz 与 readiness: true (1000ms缓存)或 readiness: { intervalMs: 5000 }并联探测器和 /healthz 共享该检查的缓存;普通检查只影响 /healthz。 。 。 . 失败检查无需重启即可恢复; 排出和崩溃准备 仍被绑住. RunningApp.ready() 只读生命周期. 见 探测器。 。 。 .
  • 环境配置, 已输入 . 内核提供 @btravstack/config是因为 Env 切换到每个图 : a 坏值是一个 ConfigInvalid 立即命名每个错误,然后退出 78。 。 。 .
  • 在每条路上被撕碎中,与失败的决赛者在 ExitReport.teardownErrors永远不要掩盖退出的原因.
  • 每个单位范围无人管理 ——运行时间电话 unit.fork(module, seed) 从内部 host.run工作召回,还有 单位结算时内核关闭范围.
  • 环境记录,而非环境容器 —— 说 currentUnit() 读取 { unitId, traceId, tenantId, signal }; 服务从不旅行 在这里. signal 这是非常 AbortSignal 该单位的工作召回, 因此,运行时间 其工作是图书馆的 next() - 临时活动 AMQP交付——仍然可以遵守排水期限.
  • 作为设定的端口进行观察,而不是在每个启动器中进行日志检查. 启动器 将每个操作手动到 Observers —— 说 observe(observers, operation) (单位:千美元) 横跨形状的起跑地, observed(observers, operation, call) 周围 一个 AsyncResult- 回电 - 并持有不 Logger, (中文(简体) ), Meter 或者说 Tracer 属于自己的。 编组 @btravstack/observability 是什么转动这些 操作为线条、跨度和工具; 组装无成本 惰性电话.
  • 无所投出. 每个同步表面都是 unthrown AsyncResult· ; runMain 套装 process.exitCode —— 说 0 干净, 1 模拟启动出错, 2 废弃的作品 或失败的决赛者, 70 坠机, 78 一个坏 环境.

以上每个样本均由 src/docs-examples.test-d.ts其余的... ... 页:1 Runtime 合同、排水道、嵌入式 runMain - 已经上线了 文档网站。 。 。 . 测试内核靴子是什么 @btravstack/testing工作 - a bootFixture 页:1 test.extend, (中文(简体) ), tapped 在运行中读取服务 app,一个模拟运行时间和一个假的时钟——从这个软件包中保持出去这样 生产捆绑从不拉出假货.

许可证

麻省理工学院 贝诺伊特旅行社

版本与发布记录

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

版本发布日期距今
0.58.0latest2026/11/08今天
0.57.02026/11/071 天前
0.56.12026/11/062 天前
0.56.02026/11/062 天前
0.55.12026/11/035 天前
0.55.02026/11/035 天前

关于 @btravstack/core 的常见问题

@btravstack/core 是什么?

应用程序内核: 启动一个 di 模块进入运行中的进程, 并停止它而不失去工作

如何安装 @btravstack/core?

在项目目录运行 npm install @btravstack/core,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:unthrown(^5.0.0)、@btravstack/di(^0.58.0)、@btravstack/config(^0.58.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@btravstack/core 支持 TypeScript 吗?

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

@btravstack/core 支持 ESM 还是 CommonJS?

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

@btravstack/core 需要什么版本的 Node.js?

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

@btravstack/core 可以商用吗?

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

@btravstack/core 的下载量有多少?

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

@btravstack/core 还在维护吗?

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