service-bridge 1.0.7 → 1.0.8-dev.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -41
- package/dist/index.js +579 -33049
- package/package.json +13 -2
- package/biome.json +0 -28
- package/bun.lock +0 -249
- package/http/dist/express.d.ts +0 -51
- package/http/dist/express.d.ts.map +0 -1
- package/http/dist/express.test.d.ts +0 -2
- package/http/dist/express.test.d.ts.map +0 -1
- package/http/dist/fastify.d.ts +0 -43
- package/http/dist/fastify.d.ts.map +0 -1
- package/http/dist/fastify.test.d.ts +0 -2
- package/http/dist/fastify.test.d.ts.map +0 -1
- package/http/dist/index.d.ts +0 -7
- package/http/dist/index.d.ts.map +0 -1
- package/http/dist/trace.d.ts +0 -19
- package/http/dist/trace.d.ts.map +0 -1
- package/http/dist/trace.test.d.ts +0 -2
- package/http/dist/trace.test.d.ts.map +0 -1
- package/http/package.json +0 -49
- package/http/src/express.test.ts +0 -125
- package/http/src/express.ts +0 -209
- package/http/src/fastify.test.ts +0 -142
- package/http/src/fastify.ts +0 -159
- package/http/src/index.ts +0 -10
- package/http/src/sdk-augment.d.ts +0 -11
- package/http/src/servicebridge.d.ts +0 -23
- package/http/src/trace.test.ts +0 -97
- package/http/src/trace.ts +0 -56
- package/http/tsconfig.json +0 -17
- package/http/tsconfig.test.json +0 -6
- package/sdk/dist/generated/servicebridge-package-definition.d.ts +0 -4912
- package/sdk/dist/grpc-client.d.ts +0 -344
- package/sdk/dist/grpc-client.test.d.ts +0 -1
- package/sdk/dist/index.d.ts +0 -2
- package/sdk/package.json +0 -31
- package/sdk/scripts/generate-proto.ts +0 -65
- package/sdk/src/generated/servicebridge-package-definition.ts +0 -5423
- package/sdk/src/grpc-client.d.ts +0 -332
- package/sdk/src/grpc-client.d.ts.map +0 -1
- package/sdk/src/grpc-client.test.ts +0 -422
- package/sdk/src/grpc-client.ts +0 -3105
- package/sdk/src/index.d.ts +0 -3
- package/sdk/src/index.d.ts.map +0 -1
- package/sdk/src/index.ts +0 -31
- package/sdk/tsconfig.json +0 -13
package/README.md
CHANGED
|
@@ -95,7 +95,7 @@ bun add service-bridge
|
|
|
95
95
|
import { servicebridge } from "service-bridge";
|
|
96
96
|
|
|
97
97
|
const sb = servicebridge(
|
|
98
|
-
process.env.SERVICEBRIDGE_URL ?? "
|
|
98
|
+
process.env.SERVICEBRIDGE_URL ?? "localhost:14445",
|
|
99
99
|
process.env.SERVICEBRIDGE_SERVICE_KEY!,
|
|
100
100
|
"payments",
|
|
101
101
|
);
|
|
@@ -104,7 +104,7 @@ sb.handleRpc("charge", async (payload: { orderId: string; amount: number }) => {
|
|
|
104
104
|
return { ok: true, txId: `tx_${Date.now()}`, orderId: payload.orderId };
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
await sb.serve({ host: "
|
|
107
|
+
await sb.serve({ host: "localhost" });
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
### 3. Call it from another service
|
|
@@ -113,7 +113,7 @@ await sb.serve({ host: "0.0.0.0" });
|
|
|
113
113
|
import { servicebridge } from "service-bridge";
|
|
114
114
|
|
|
115
115
|
const sb = servicebridge(
|
|
116
|
-
process.env.SERVICEBRIDGE_URL ?? "
|
|
116
|
+
process.env.SERVICEBRIDGE_URL ?? "localhost:14445",
|
|
117
117
|
process.env.SERVICEBRIDGE_SERVICE_KEY!,
|
|
118
118
|
"orders",
|
|
119
119
|
);
|
|
@@ -138,7 +138,7 @@ The SDK connects to a ServiceBridge runtime. The fastest way to start:
|
|
|
138
138
|
bash <(curl -fsSL https://servicebridge.dev/install.sh)
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
This installs ServiceBridge + PostgreSQL via Docker Compose and generates an admin password automatically. After install, the dashboard is at `http://localhost:14444` and the gRPC control plane at `
|
|
141
|
+
This installs ServiceBridge + PostgreSQL via Docker Compose and generates an admin password automatically. After install, the dashboard is at `http://localhost:14444` and the gRPC control plane at `localhost:14445`.
|
|
142
142
|
|
|
143
143
|
For manual Docker Compose setup, configuration reference, and all runtime environment variables, see the **[Runtime Setup](../README.md#runtime-setup)** section in the main SDK README.
|
|
144
144
|
|
|
@@ -153,7 +153,7 @@ import { servicebridge } from "service-bridge";
|
|
|
153
153
|
|
|
154
154
|
// --- Payments service (worker) ---
|
|
155
155
|
|
|
156
|
-
const payments = servicebridge("
|
|
156
|
+
const payments = servicebridge("localhost:14445", process.env.SERVICEBRIDGE_SERVICE_KEY!, "payments");
|
|
157
157
|
|
|
158
158
|
payments.handleRpc("charge", async (payload: { orderId: string; amount: number }, ctx) => {
|
|
159
159
|
await ctx?.stream.write({ status: "charging", orderId: payload.orderId }, "progress");
|
|
@@ -164,13 +164,13 @@ payments.handleRpc("charge", async (payload: { orderId: string; amount: number }
|
|
|
164
164
|
return { ok: true, txId: `tx_${Date.now()}` };
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
await payments.serve({ host: "
|
|
167
|
+
await payments.serve({ host: "localhost" });
|
|
168
168
|
```
|
|
169
169
|
|
|
170
170
|
```ts
|
|
171
171
|
// --- Orders service (caller + event publisher) ---
|
|
172
172
|
|
|
173
|
-
const orders = servicebridge("
|
|
173
|
+
const orders = servicebridge("localhost:14445", process.env.SERVICEBRIDGE_SERVICE_KEY!, "orders");
|
|
174
174
|
|
|
175
175
|
// Call payments, then publish event
|
|
176
176
|
const charge = await orders.rpc<{ ok: boolean; txId: string }>("payments/charge", {
|
|
@@ -190,7 +190,7 @@ await orders.event("orders.completed", {
|
|
|
190
190
|
```ts
|
|
191
191
|
// --- Notifications service (event consumer) ---
|
|
192
192
|
|
|
193
|
-
const notifications = servicebridge("
|
|
193
|
+
const notifications = servicebridge("localhost:14445", process.env.SERVICEBRIDGE_SERVICE_KEY!, "notifications");
|
|
194
194
|
|
|
195
195
|
notifications.handleEvent("orders.*", async (payload, ctx) => {
|
|
196
196
|
const body = payload as { orderId: string; txId: string };
|
|
@@ -198,7 +198,7 @@ notifications.handleEvent("orders.*", async (payload, ctx) => {
|
|
|
198
198
|
// ... send email ...
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
-
await notifications.serve({ host: "
|
|
201
|
+
await notifications.serve({ host: "localhost" });
|
|
202
202
|
```
|
|
203
203
|
|
|
204
204
|
```ts
|
|
@@ -230,7 +230,7 @@ Every step above — RPC, event publish, event delivery, workflow execution —
|
|
|
230
230
|
- **Jobs** — cron, delayed, and workflow-triggered scheduling
|
|
231
231
|
|
|
232
232
|
### Security
|
|
233
|
-
- **
|
|
233
|
+
- **TLS by default** — control plane TLS + worker mTLS with gRPC certificate provisioning
|
|
234
234
|
- **Access Policy** — service-level caller/target restrictions and RBAC
|
|
235
235
|
|
|
236
236
|
### Observability
|
|
@@ -267,11 +267,11 @@ ServiceBridge keeps the core API shape consistent across Node.js, Go, and Python
|
|
|
267
267
|
constructor, RPC, events, jobs, workflows, `runWorkflow`, streams, serve/stop, and `ServiceBridgeError`.
|
|
268
268
|
|
|
269
269
|
Constructor-level defaults for `timeout`, `retries`, and `retryDelay` are available
|
|
270
|
-
across all three SDKs.
|
|
270
|
+
across all three SDKs. Parity differences are naming-only (language idioms):
|
|
271
271
|
|
|
272
|
-
-
|
|
273
|
-
-
|
|
274
|
-
-
|
|
272
|
+
- Constructor TLS overrides: `workerTLS`/`caCert` (Node), `WorkerTLS`/`CACert` (Go), `worker_tls`/`ca_cert` (Python)
|
|
273
|
+
- Handler hints: timeout/retryable/concurrency/prefetch are advisory in all SDKs
|
|
274
|
+
- Shared `serve()` fields across SDKs: host, max in-flight, instance ID, weight, and per-serve TLS override
|
|
275
275
|
|
|
276
276
|
### `servicebridge(url, serviceKey, serviceName?, opts?)`
|
|
277
277
|
|
|
@@ -290,21 +290,22 @@ Creates an SDK client instance.
|
|
|
290
290
|
|
|
291
291
|
| Option | Type | Default | Description |
|
|
292
292
|
|---|---|---|---|
|
|
293
|
-
| `timeout` | `number` | `30000` | Default timeout (ms)
|
|
293
|
+
| `timeout` | `number` | `30000` | Default hard timeout per RPC attempt (ms). |
|
|
294
294
|
| `retries` | `number` | `3` | Default retry count for `rpc()`. |
|
|
295
295
|
| `retryDelay` | `number` | `300` | Base backoff delay (ms) for `rpc()`. |
|
|
296
296
|
| `discoveryRefreshMs` | `number` | `10000` | Discovery refresh period for endpoint updates. |
|
|
297
297
|
| `queueMaxSize` | `number` | `1000` | Max offline queue size for control-plane writes. |
|
|
298
298
|
| `queueOverflow` | `"drop-oldest" \| "drop-newest" \| "error"` | `"drop-oldest"` | Overflow strategy for offline queue. |
|
|
299
299
|
| `heartbeatIntervalMs` | `number` | `10000` | Base heartbeat period for worker registrations. |
|
|
300
|
-
| `workerTransport` | `"tls"` | `"tls"` | Worker server transport. |
|
|
301
|
-
| `workerTLS` | `WorkerTLSOpts` | auto | Explicit cert/key/CA for worker mTLS. |
|
|
302
|
-
| `adminUrl` | `string` | derived from `url` | HTTP admin base URL (TLS provisioning and management API calls). |
|
|
303
|
-
| `adminSessionCookie` | `string` | `undefined` | Admin session cookie for browser-authenticated endpoints (e.g. `cancelWorkflowRun`). |
|
|
304
|
-
| `adminCsrfToken` | `string` | `undefined` | CSRF token paired with `adminSessionCookie` for unsafe HTTP methods. |
|
|
305
|
-
| `adminOrigin` | `string` | `undefined` | Origin header required by admin CSRF/origin checks. |
|
|
306
300
|
| `captureLogs` | `boolean` | `true` | Forward `console.*` logs to ServiceBridge. |
|
|
307
301
|
|
|
302
|
+
### Advanced TLS overrides
|
|
303
|
+
|
|
304
|
+
| Option | Type | Default | Description |
|
|
305
|
+
|---|---|---|---|
|
|
306
|
+
| `workerTLS` | `WorkerTLSOpts` | auto | Explicit cert/key/CA for worker mTLS. |
|
|
307
|
+
| `caCert` | `string \| Buffer` | from `serviceKey` | Optional control-plane CA override. By default SDK reads CA from sbv2 service key. |
|
|
308
|
+
|
|
308
309
|
`WorkerTLSOpts`:
|
|
309
310
|
|
|
310
311
|
```ts
|
|
@@ -343,6 +344,10 @@ const user = await sb.rpc<{ id: string; name: string }>("users/get", { id: "u_1"
|
|
|
343
344
|
});
|
|
344
345
|
```
|
|
345
346
|
|
|
347
|
+
`rpc()` is bounded even when a downstream worker is silent:
|
|
348
|
+
each attempt has a hard local timeout, retries are finite (`retries + 1` total attempts),
|
|
349
|
+
and after the final failed attempt the root RPC span is closed with `error`.
|
|
350
|
+
|
|
346
351
|
---
|
|
347
352
|
|
|
348
353
|
### `event(topic, payload?, opts?)`
|
|
@@ -503,9 +508,9 @@ Registers an RPC handler. Chainable.
|
|
|
503
508
|
|
|
504
509
|
| Option | Type | Description |
|
|
505
510
|
|---|---|---|
|
|
506
|
-
| `timeout` | `number` |
|
|
507
|
-
| `retryable` | `boolean` |
|
|
508
|
-
| `concurrency` | `number` |
|
|
511
|
+
| `timeout` | `number` | Advisory timeout hint (currently metadata-level, not hard-enforced by runtime). |
|
|
512
|
+
| `retryable` | `boolean` | Advisory retry hint (currently metadata-level, not a strict policy switch). |
|
|
513
|
+
| `concurrency` | `number` | Advisory concurrency hint (currently not hard-enforced). |
|
|
509
514
|
| `schema` | `RpcSchemaOpts` | Inline protobuf schema for binary encode/decode. |
|
|
510
515
|
| `allowedCallers` | `string[]` | Allow-list of caller service names. |
|
|
511
516
|
|
|
@@ -536,8 +541,8 @@ Registers an event consumer handler. Chainable.
|
|
|
536
541
|
| Option | Type | Description |
|
|
537
542
|
|---|---|---|
|
|
538
543
|
| `groupName` | `string` | Consumer group name. Default: `<service>.<pattern>`. |
|
|
539
|
-
| `concurrency` | `number` |
|
|
540
|
-
| `prefetch` | `number` |
|
|
544
|
+
| `concurrency` | `number` | Advisory concurrency hint (currently not hard-enforced). |
|
|
545
|
+
| `prefetch` | `number` | Advisory prefetch hint (currently not hard-enforced). |
|
|
541
546
|
| `retryPolicyJson` | `string` | Retry policy JSON string. |
|
|
542
547
|
| `filterExpr` | `string` | Server-side filter expression. |
|
|
543
548
|
|
|
@@ -577,15 +582,15 @@ the Node.js process).
|
|
|
577
582
|
|
|
578
583
|
| Option | Type | Description |
|
|
579
584
|
|---|---|---|
|
|
580
|
-
| `host` | `string` | Bind host. Default: `0.0.0.0
|
|
581
|
-
| `
|
|
582
|
-
| `
|
|
583
|
-
| `
|
|
584
|
-
| `tls` | `WorkerTLSOpts` | Per-serve TLS override
|
|
585
|
+
| `host` | `string` | Bind host. Default: `localhost`. Use `0.0.0.0` in Docker/Kubernetes so ServiceBridge can reach the worker. |
|
|
586
|
+
| `maxInFlight` | `number` | Max in-flight runtime-originated commands over `OpenWorkerSession`. Default: `128`. |
|
|
587
|
+
| `instanceId` | `string` | Stable worker instance identifier. |
|
|
588
|
+
| `weight` | `number` | Scheduling/discovery weight hint. |
|
|
589
|
+
| `tls` | `WorkerTLSOpts` | Per-serve worker TLS override. |
|
|
585
590
|
|
|
586
591
|
```ts
|
|
587
592
|
await sb.serve({
|
|
588
|
-
host: "
|
|
593
|
+
host: "localhost",
|
|
589
594
|
instanceId: process.env.HOSTNAME,
|
|
590
595
|
});
|
|
591
596
|
```
|
|
@@ -693,6 +698,13 @@ identifier used by `ctx.stream.write(...)` (typically a trace ID).
|
|
|
693
698
|
| `data` | `unknown` | JSON-decoded chunk payload. |
|
|
694
699
|
| `runStatus` | `string \| undefined` | Final status on `run_complete`. |
|
|
695
700
|
|
|
701
|
+
Behavior:
|
|
702
|
+
|
|
703
|
+
- Auto-reconnect with exponential backoff (`500ms` → `5000ms`) on retryable stream failures.
|
|
704
|
+
- Deduplicates by `sequence` across reconnects.
|
|
705
|
+
- Enforces strict JSON for `type="chunk"` payloads (non-JSON chunk terminates stream with fatal error).
|
|
706
|
+
- Enforces internal queue limit `256`; overflow is fatal (consumer must drain promptly).
|
|
707
|
+
|
|
696
708
|
```ts
|
|
697
709
|
for await (const evt of sb.watchRun(runId, { key: "output", fromSequence: 0 })) {
|
|
698
710
|
if (evt.type === "chunk") {
|
|
@@ -859,7 +871,9 @@ Runs a Fastify handler inside the current trace context so downstream SDK calls
|
|
|
859
871
|
### TLS behavior
|
|
860
872
|
|
|
861
873
|
- Worker transport is TLS-only.
|
|
862
|
-
-
|
|
874
|
+
- Control plane is TLS-only. Trust source is embedded into sbv2 service key by default.
|
|
875
|
+
- Embedded/explicit CA PEM is validated with strict x509 parsing.
|
|
876
|
+
- If `workerTLS` is not provided, SDK auto-provisions worker certs via gRPC `ProvisionWorkerCertificate`.
|
|
863
877
|
- `workerTLS.cert` and `workerTLS.key` must be provided together.
|
|
864
878
|
- `serve({ tls })` overrides global `workerTLS` for a specific worker instance.
|
|
865
879
|
|
|
@@ -879,19 +893,15 @@ The SDK requires values you pass into `servicebridge(...)`. Common setup:
|
|
|
879
893
|
|
|
880
894
|
| Variable | Required | Example | Description |
|
|
881
895
|
|---|---|---|---|
|
|
882
|
-
| `SERVICEBRIDGE_URL` | yes | `
|
|
883
|
-
| `SERVICEBRIDGE_SERVICE_KEY` | yes | `
|
|
896
|
+
| `SERVICEBRIDGE_URL` | yes | `localhost:14445` | gRPC control plane URL |
|
|
897
|
+
| `SERVICEBRIDGE_SERVICE_KEY` | yes | `sbv2.<id>.<secret>.<ca>` | Service authentication key (sbv2 only) |
|
|
884
898
|
| `SERVICEBRIDGE_SERVICE` | yes (worker mode) | `orders` | Service name in registry |
|
|
885
|
-
| `SERVICEBRIDGE_ADMIN_URL` | optional | `http://0.0.0.0:14444` | Explicit admin API base URL |
|
|
886
899
|
|
|
887
900
|
```ts
|
|
888
901
|
const sb = servicebridge(
|
|
889
|
-
process.env.SERVICEBRIDGE_URL ?? "
|
|
902
|
+
process.env.SERVICEBRIDGE_URL ?? "localhost:14445",
|
|
890
903
|
process.env.SERVICEBRIDGE_SERVICE_KEY!,
|
|
891
904
|
process.env.SERVICEBRIDGE_SERVICE ?? "orders",
|
|
892
|
-
{
|
|
893
|
-
adminUrl: process.env.SERVICEBRIDGE_ADMIN_URL,
|
|
894
|
-
},
|
|
895
905
|
);
|
|
896
906
|
```
|
|
897
907
|
|
|
@@ -949,7 +959,7 @@ try {
|
|
|
949
959
|
## FAQ
|
|
950
960
|
|
|
951
961
|
**How does ServiceBridge handle service failures?**
|
|
952
|
-
RPC calls have configurable retries with exponential backoff. Events are durable (PostgreSQL-backed) with at-least-once delivery per consumer group. Failed deliveries are retried according to policy, then moved to DLQ. Workflows track step state and can be resumed.
|
|
962
|
+
RPC calls have configurable retries with exponential backoff and hard per-attempt timeouts, so a silent downstream service cannot keep a call pending forever. Events are durable (PostgreSQL-backed) with at-least-once delivery per consumer group. Failed deliveries are retried according to policy, then moved to DLQ. Workflows track step state and can be resumed.
|
|
953
963
|
|
|
954
964
|
**Is there vendor lock-in?**
|
|
955
965
|
ServiceBridge is self-hosted. The runtime is a single Go binary + PostgreSQL. SDK calls map to standard patterns (RPC, pub/sub, cron) — migrating away means replacing SDK calls with equivalent library calls.
|