@di-framework/bindings

中文文档
6.0.30发布于 2026/11/07(MIT OR Apache-2.0)TypeScriptES Module零依赖构建来源已验证近 30 天下载 3596

Native platform WIT service bindings for DI Framework applications.

原始使用文档
文档目录5 节
  1. Bindings
  2. Transaction semantics
  3. Supported capabilities
  4. Unit tests
  5. Managed PostgreSQL (upcoming release)

@di-framework/bindings

Native wasmCloud WIT service bindings for DI Framework applications.

Each concrete class is a DI token, a named hostInterfaces entry, and a build-time WIT requirement. The package maps to wasmCloud/WASI interfaces rather than inventing a second capability vocabulary.

This package consumes host-interface bindings. It does not provision PostgreSQL, Redis, NATS, or object stores, and it never embeds secret values. ConfigMaps and Secrets stay with Pulumi, Terraform, Crossplane, Helm, or another infrastructure layer.

Bindings

import { Component, Container } from '@di-framework/core/decorators';
import { KeyValue, Postgres, PlatformBinding } from '@di-framework/bindings';

@PlatformBinding('user-database')
@Container()
export class UserDatabase extends Postgres {}

@PlatformBinding('sessions', { interfaces: ['store', 'atomics'] })
@Container()
export class Sessions extends KeyValue {}

@PlatformBinding('cache')
@Container()
export class Cache extends KeyValue {}

@WasmCloudBinding remains exported as a deprecated alias of @PlatformBinding for back-compat; new code should use @PlatformBinding.

Put those classes in src/bindings.ts. The wasmCloud CLI extension discovers the file, contributes each class to the shared WIT requirement graph, generates real WIT guest imports, and renders matching hostInterfaces entries. PostgreSQL entries omit hostInterfaces[].name to match the unlabeled import; the binding name still identifies the DI guest and its configuration overlays. The compiled guest world is unlabeled (import wasmcloud:postgres/[email protected]) because the qjs componentizer cannot emit cm-implements labeled imports yet. Imported async funcs (postgres, key-value, blobstore, messaging, secrets, outgoing HTTP) componentize with @di-framework/componentize-qjs (wasmtime 48). Set DI_FRAMEWORK_COMPONENTIZE_QJS to override that CLI. wasi:[email protected] is sync and also componentizes with stock jco.

For PostgreSQL, configure the host connection with WASH_POSTGRES_URL (or WASMCLOUD_POSTGRES_URL with the CLI's platform dev command), and set config: { database: 'orders' } on the binding. The unnamed import uses the host's connection and the selected database; multiple independently credentialed PostgreSQL bindings are not supported by this QuickJS path yet. Guests initialize before the application, including bindings constructed at module startup.

Transaction semantics

wasmcloud:[email protected] has query and queryBatch, and no transaction handle. Each call goes to whichever pooled connection is free. A named import (user-database-query) is served from a per-credential pool with no connection affinity, so a BEGIN in one call does not cover the next statement. A COMMIT can land on a connection that never saw the BEGIN, and that connection stays idle in transaction.

Guests that use @di-framework/repo open the binding with openPostgresDatabase from @di-framework/bindings/postgres. The handle is an AutocommitDatabase. Every statement is its own transaction, and transaction(fn) runs fn on that same handle. The adapter never sends BEGIN, COMMIT, or ROLLBACK. FOR UPDATE and advisory locks last only for the statement that carries them.

Keep an invariant in one statement:

  • a conditional UPDATE … RETURNING
  • a data-modifying CTE
  • INSERT … SELECT … WHERE NOT EXISTS

run sets changes from the rows returned. The provider does not report a command tag, so a count is a RETURNING list. A changes value of 0 means no rows came back, which is what an UPDATE or DELETE without RETURNING reports even when Postgres modified rows.

exec sends its script as one queryBatch. The host runs that string on one pooled client, and Postgres treats a multi-statement simple query as one implicit transaction.

atomicBatch is for a write-only sequence that must commit or roll back together and that does not read between statements. It renders each parameter as a literal (quotes doubled, a negative number parenthesized so it cannot form a -- comment) and submits that script as one queryBatch. The script has no BEGIN or COMMIT. Postgres runs a multi-statement simple query as one implicit transaction and rolls it back on error, returning the pooled client idle. wasmCloud v2.8.0 runs that string on one pooled client: crates/wash-runtime/src/plugin/wasmcloud_postgres/async_p3.rs checks out a single client in query_batch and calls client.batch_execute (batch_with_client, line 191).

import { openPostgresDatabase } from '@di-framework/bindings/postgres';

const db = openPostgresDatabase(database);
await db.atomicBatch([
  { sql: 'INSERT INTO t (name, n) VALUES (?, ?)', params: ["o'brien", -1] },
]);

@di-framework/repo is an optional peer of this package. The main @di-framework/bindings entry leaves it unloaded. Import @di-framework/bindings/postgres from a guest that depends on @di-framework/repo.

Secret material is referenced, never inlined:

@PlatformBinding('user-database', { secretFrom: 'orders-user-database' })
@Container()
export class UserDatabase extends Postgres {}

When secretFrom is omitted, the default Kubernetes Secret name is <application>-<binding>.

Supported capabilities

ClassWIT packageVersion
Postgreswasmcloud:postgres0.2.0
KeyValuewasmcloud:keyvalue0.2.0
Blobstorewasmcloud:blobstore0.1.0
Messagingwasmcloud:messaging0.3.0
Configwasi:config0.2.0-rc.1
Secretswasmcloud:secrets2.1.0
OutgoingHttpwasi:http client0.3.0

Package versions are independent of the WASI 0.3 component-model preview.

Unit tests

Replace a binding through the container:

class FakeUserDatabase extends UserDatabase {
  override query() {
    return Promise.resolve([]);
  }
}

testContainer.registerValue(UserDatabase, new FakeUserDatabase());

Managed PostgreSQL (upcoming release)

@PlatformBinding('orders-db', { serviceName: 'orders' })
export class OrdersDatabase extends Postgres {}

Create the service with di-framework platform service create postgres --name orders --wait. Deploying creates workload-owned ServiceBindings and waits for the controller's connection Secrets. Multiple bindings can share a service; separate services use independent credentials and PVCs. serviceName currently supports PostgreSQL only and cannot be combined with manual connection configuration.

See platform PostgreSQL lifecycle and recovery for storage prerequisites, retention, and deletion.

版本与发布记录

@di-framework/bindings 共发布 28 个版本,首次发布于 2026/09/28;过去 12 个月发布了 28 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
6.0.30latest2026/11/075 天前
6.0.292026/11/066 天前
6.0.282026/11/039 天前
6.0.272026/11/0111 天前
6.0.262026/10/3012 天前
6.0.252026/10/3013 天前

关于 @di-framework/bindings 的常见问题

@di-framework/bindings 是什么?

Native platform WIT service bindings for DI Framework applications.

如何安装 @di-framework/bindings?

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

@di-framework/bindings 支持 TypeScript 吗?

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

@di-framework/bindings 支持 ESM 还是 CommonJS?

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

@di-framework/bindings 可以商用吗?

@di-framework/bindings 使用 (MIT OR Apache-2.0) 许可。可在 MIT、Apache-2.0 中任选其一遵守。选择 MIT 时,宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@di-framework/bindings 的下载量有多少?

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

@di-framework/bindings 还在维护吗?

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