@blokjs/trigger-pubsub 0.6.17 → 0.6.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/dist/PubSubTrigger.js +20 -1
- package/package.json +5 -4
- package/CHANGELOG.md +0 -22
- package/__tests__/integration/gcp-pubsub.real-emulator.test.ts +0 -235
- package/__tests__/integration/kafka-pubsub.real-kafka.test.ts +0 -269
- package/__tests__/integration/nats-pubsub.real-nats.test.ts +0 -138
- package/src/PubSubTrigger.test.ts +0 -151
- package/src/PubSubTrigger.ts +0 -402
- package/src/adapters/AWSSNSAdapter.ts +0 -322
- package/src/adapters/AzureServiceBusAdapter.ts +0 -263
- package/src/adapters/GCPPubSubAdapter.ts +0 -236
- package/src/adapters/KafkaPubSubAdapter.ts +0 -194
- package/src/adapters/NATSPubSubAdapter.ts +0 -326
- package/src/adapters/RedisStreamsPubSubAdapter.ts +0 -225
- package/src/adapters/factory.test.ts +0 -87
- package/src/adapters/factory.ts +0 -88
- package/src/adapters/new-adapters.test.ts +0 -108
- package/src/index.ts +0 -67
- package/template/.env.example +0 -8
- package/template/package.json +0 -44
- package/template/src/Nodes.ts +0 -10
- package/template/src/Workflows.ts +0 -8
- package/template/src/index.ts +0 -41
- package/template/src/runner/PubSubServer.ts +0 -39
- package/template/src/runner/types/Workflows.ts +0 -7
- package/template/src/workflows/messages/on-message.ts +0 -48
- package/template/tsconfig.json +0 -31
- package/template/vitest.config.ts +0 -39
- package/tsconfig.json +0 -32
package/src/adapters/factory.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* v0.7 PR 6 — pub/sub adapter factory.
|
|
3
|
-
*
|
|
4
|
-
* Resolves a `provider` string to a concrete `PubSubAdapter` instance.
|
|
5
|
-
* Used by `PubSubTrigger` (per-workflow provider dispatch) and by the
|
|
6
|
-
* `@blokjs/pubsub-publish` helper.
|
|
7
|
-
*
|
|
8
|
-
* Provider resolution order:
|
|
9
|
-
* 1. Explicit `provider` field on the workflow.
|
|
10
|
-
* 2. `BLOK_PUBSUB_ADAPTER` env var.
|
|
11
|
-
* 3. `"nats"` fallback (cheapest infra; matches the v0.7 plan's
|
|
12
|
-
* "default for pub/sub" recommendation).
|
|
13
|
-
*
|
|
14
|
-
* Each adapter lazy-imports its broker SDK on first use; workflows
|
|
15
|
-
* that don't use a given provider don't pay the install cost.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import type { PubSubProvider } from "@blokjs/helper";
|
|
19
|
-
import type { PubSubAdapter } from "../PubSubTrigger";
|
|
20
|
-
import { AWSSNSAdapter } from "./AWSSNSAdapter";
|
|
21
|
-
import { AzureServiceBusAdapter } from "./AzureServiceBusAdapter";
|
|
22
|
-
import { GCPPubSubAdapter } from "./GCPPubSubAdapter";
|
|
23
|
-
import { KafkaPubSubAdapter } from "./KafkaPubSubAdapter";
|
|
24
|
-
import { NATSPubSubAdapter } from "./NATSPubSubAdapter";
|
|
25
|
-
import { RedisStreamsPubSubAdapter } from "./RedisStreamsPubSubAdapter";
|
|
26
|
-
|
|
27
|
-
export function resolveProvider(provider?: PubSubProvider): PubSubProvider {
|
|
28
|
-
if (provider) return provider;
|
|
29
|
-
const envValue = process.env.BLOK_PUBSUB_ADAPTER;
|
|
30
|
-
if (envValue && isPubSubProvider(envValue)) return envValue;
|
|
31
|
-
return "nats";
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function isPubSubProvider(value: string): value is PubSubProvider {
|
|
35
|
-
return (
|
|
36
|
-
value === "nats" ||
|
|
37
|
-
value === "redis-streams" ||
|
|
38
|
-
value === "kafka" ||
|
|
39
|
-
value === "gcp" ||
|
|
40
|
-
value === "aws" ||
|
|
41
|
-
value === "azure"
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function createPubSubAdapter(provider: PubSubProvider): PubSubAdapter {
|
|
46
|
-
switch (provider) {
|
|
47
|
-
case "nats":
|
|
48
|
-
return new NATSPubSubAdapter();
|
|
49
|
-
case "redis-streams":
|
|
50
|
-
return new RedisStreamsPubSubAdapter();
|
|
51
|
-
case "kafka":
|
|
52
|
-
return new KafkaPubSubAdapter();
|
|
53
|
-
case "gcp":
|
|
54
|
-
return new GCPPubSubAdapter();
|
|
55
|
-
case "aws":
|
|
56
|
-
return new AWSSNSAdapter();
|
|
57
|
-
case "azure":
|
|
58
|
-
return new AzureServiceBusAdapter();
|
|
59
|
-
default: {
|
|
60
|
-
const exhaustive: never = provider;
|
|
61
|
-
throw new Error(`[blok][pubsub] unknown provider "${exhaustive as string}". Check PubSubProviderSchema.`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Process-singleton adapter pool — one instance per provider. The
|
|
68
|
-
* trigger calls `getOrCreateAdapter("nats")` once per workflow, and
|
|
69
|
-
* subsequent workflows on the same provider share the broker
|
|
70
|
-
* connection.
|
|
71
|
-
*/
|
|
72
|
-
const pool: Map<PubSubProvider, PubSubAdapter> = new Map();
|
|
73
|
-
|
|
74
|
-
export function getOrCreateAdapter(provider: PubSubProvider): PubSubAdapter {
|
|
75
|
-
let adapter = pool.get(provider);
|
|
76
|
-
if (!adapter) {
|
|
77
|
-
adapter = createPubSubAdapter(provider);
|
|
78
|
-
pool.set(provider, adapter);
|
|
79
|
-
}
|
|
80
|
-
return adapter;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function _resetAdapterPoolForTests(): void {
|
|
84
|
-
for (const adapter of pool.values()) {
|
|
85
|
-
void adapter.disconnect?.().catch(() => {});
|
|
86
|
-
}
|
|
87
|
-
pool.clear();
|
|
88
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Smoke tests for the v0.7 PR 6 pub/sub adapters (NATS, Redis
|
|
3
|
-
* Streams, Kafka) plus the v0.7 publish() backfill on the existing
|
|
4
|
-
* 3 (GCP, AWS, Azure). Boundary-only — constructor, provider name,
|
|
5
|
-
* initial state, `disconnect()` before connect.
|
|
6
|
-
*
|
|
7
|
-
* Live broker round-trips need docker-compose CI (see PR 6 plan,
|
|
8
|
-
* deferred to follow-up).
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { describe, expect, it } from "vitest";
|
|
12
|
-
|
|
13
|
-
import { AWSSNSAdapter } from "./AWSSNSAdapter";
|
|
14
|
-
import { AzureServiceBusAdapter } from "./AzureServiceBusAdapter";
|
|
15
|
-
import { GCPPubSubAdapter } from "./GCPPubSubAdapter";
|
|
16
|
-
import { KafkaPubSubAdapter } from "./KafkaPubSubAdapter";
|
|
17
|
-
import { NATSPubSubAdapter } from "./NATSPubSubAdapter";
|
|
18
|
-
import { RedisStreamsPubSubAdapter } from "./RedisStreamsPubSubAdapter";
|
|
19
|
-
|
|
20
|
-
describe("NATSPubSubAdapter — v0.7 PR 6", () => {
|
|
21
|
-
it("reports provider 'nats'", () => {
|
|
22
|
-
expect(new NATSPubSubAdapter().provider).toBe("nats");
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("is not connected before connect()", () => {
|
|
26
|
-
expect(new NATSPubSubAdapter().isConnected()).toBe(false);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("disconnect() before connect is a no-op", async () => {
|
|
30
|
-
await expect(new NATSPubSubAdapter().disconnect()).resolves.toBeUndefined();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("reads server list from NATS_SERVERS env var", () => {
|
|
34
|
-
process.env.NATS_SERVERS = "nats-a:4222,nats-b:4222";
|
|
35
|
-
const adapter = new NATSPubSubAdapter();
|
|
36
|
-
expect((adapter as unknown as { config: { servers: string[] } }).config.servers).toEqual([
|
|
37
|
-
"nats-a:4222",
|
|
38
|
-
"nats-b:4222",
|
|
39
|
-
]);
|
|
40
|
-
process.env.NATS_SERVERS = undefined;
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
describe("RedisStreamsPubSubAdapter — v0.7 PR 6", () => {
|
|
45
|
-
it("reports provider 'redis-streams'", () => {
|
|
46
|
-
expect(new RedisStreamsPubSubAdapter().provider).toBe("redis-streams");
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("is not connected before connect()", () => {
|
|
50
|
-
expect(new RedisStreamsPubSubAdapter().isConnected()).toBe(false);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("disconnect() before connect is a no-op", async () => {
|
|
54
|
-
await expect(new RedisStreamsPubSubAdapter().disconnect()).resolves.toBeUndefined();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("generates a unique consumer name per instance (fan-out isolation)", () => {
|
|
58
|
-
const a = new RedisStreamsPubSubAdapter();
|
|
59
|
-
const b = new RedisStreamsPubSubAdapter();
|
|
60
|
-
expect((a as unknown as { consumerName: string }).consumerName).not.toBe(
|
|
61
|
-
(b as unknown as { consumerName: string }).consumerName,
|
|
62
|
-
);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
describe("KafkaPubSubAdapter — v0.7 PR 6", () => {
|
|
67
|
-
it("reports provider 'kafka'", () => {
|
|
68
|
-
expect(new KafkaPubSubAdapter().provider).toBe("kafka");
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("is not connected before connect()", () => {
|
|
72
|
-
expect(new KafkaPubSubAdapter().isConnected()).toBe(false);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("disconnect() before connect is a no-op", async () => {
|
|
76
|
-
await expect(new KafkaPubSubAdapter().disconnect()).resolves.toBeUndefined();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("honors the explicit broker list override", () => {
|
|
80
|
-
const adapter = new KafkaPubSubAdapter({ brokers: ["kafka-prod:9092"] });
|
|
81
|
-
expect((adapter as unknown as { config: { brokers: string[] } }).config.brokers).toEqual(["kafka-prod:9092"]);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
describe("Existing adapters — provider names + publish() surface (v0.7 PR 6 backfill)", () => {
|
|
86
|
-
it("GCPPubSubAdapter reports provider 'gcp'", () => {
|
|
87
|
-
expect(new GCPPubSubAdapter().provider).toBe("gcp");
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it("AWSSNSAdapter reports provider 'aws'", () => {
|
|
91
|
-
expect(new AWSSNSAdapter().provider).toBe("aws");
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it("AzureServiceBusAdapter reports provider 'azure'", () => {
|
|
95
|
-
const adapter = new AzureServiceBusAdapter({
|
|
96
|
-
connectionString: "Endpoint=sb://example.servicebus.windows.net/;...",
|
|
97
|
-
});
|
|
98
|
-
expect(adapter.provider).toBe("azure");
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it("all three now expose a publish() method (added in PR 6)", () => {
|
|
102
|
-
expect(typeof new GCPPubSubAdapter().publish).toBe("function");
|
|
103
|
-
expect(typeof new AWSSNSAdapter().publish).toBe("function");
|
|
104
|
-
expect(
|
|
105
|
-
typeof new AzureServiceBusAdapter({ connectionString: "Endpoint=sb://x.servicebus.windows.net/;Y" }).publish,
|
|
106
|
-
).toBe("function");
|
|
107
|
-
});
|
|
108
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @blokjs/trigger-pubsub
|
|
3
|
-
*
|
|
4
|
-
* Pub/Sub-based trigger for Blok workflows. Supports 6 providers:
|
|
5
|
-
*
|
|
6
|
-
* - **NATS** (Core + JetStream) — cheapest infra; subject wildcards.
|
|
7
|
-
* - **Redis Streams** — when Redis is already in stack.
|
|
8
|
-
* - **Kafka** — high-throughput streaming.
|
|
9
|
-
* - **GCP Pub/Sub** — Google Cloud-locked.
|
|
10
|
-
* - **AWS SNS+SQS** — SNS fan-out → SQS queueing.
|
|
11
|
-
* - **Azure Service Bus** — Azure Service Bus.
|
|
12
|
-
*
|
|
13
|
-
* v0.7+ — pick the adapter per workflow via `trigger.pubsub.provider`.
|
|
14
|
-
* `BLOK_PUBSUB_ADAPTER` env var sets the default (falls back to NATS).
|
|
15
|
-
* Subclasses can still set `protected adapter` directly for back-
|
|
16
|
-
* compat with the pre-v0.7 single-adapter pattern.
|
|
17
|
-
*
|
|
18
|
-
* **Fan-out vs competing-consumer**: omit `consumerGroup` for fan-out
|
|
19
|
-
* (every subscriber sees every message); set it for competing-consumer
|
|
20
|
-
* (1 of N within group). One field disambiguates the two semantics.
|
|
21
|
-
*
|
|
22
|
-
* @example v0.7 — NATS subject hierarchy with JSON workflow
|
|
23
|
-
* ```json
|
|
24
|
-
* {
|
|
25
|
-
* "name": "audit-all-order-events",
|
|
26
|
-
* "trigger": {
|
|
27
|
-
* "pubsub": {
|
|
28
|
-
* "provider": "nats",
|
|
29
|
-
* "topic": "orders.>",
|
|
30
|
-
* "durable": true,
|
|
31
|
-
* "startFrom": "earliest"
|
|
32
|
-
* }
|
|
33
|
-
* },
|
|
34
|
-
* "steps": [...]
|
|
35
|
-
* }
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
// Core exports
|
|
40
|
-
export {
|
|
41
|
-
PubSubTrigger,
|
|
42
|
-
type PubSubAdapter,
|
|
43
|
-
type PubSubMessage,
|
|
44
|
-
} from "./PubSubTrigger";
|
|
45
|
-
|
|
46
|
-
// Adapters
|
|
47
|
-
export { AWSSNSAdapter, type AWSSNSConfig } from "./adapters/AWSSNSAdapter";
|
|
48
|
-
export { AzureServiceBusAdapter, type AzureServiceBusConfig } from "./adapters/AzureServiceBusAdapter";
|
|
49
|
-
export { GCPPubSubAdapter, type GCPPubSubConfig } from "./adapters/GCPPubSubAdapter";
|
|
50
|
-
export { KafkaPubSubAdapter, type KafkaPubSubConfig } from "./adapters/KafkaPubSubAdapter";
|
|
51
|
-
export { NATSPubSubAdapter, type NATSPubSubConfig } from "./adapters/NATSPubSubAdapter";
|
|
52
|
-
export { RedisStreamsPubSubAdapter, type RedisStreamsPubSubConfig } from "./adapters/RedisStreamsPubSubAdapter";
|
|
53
|
-
|
|
54
|
-
// v0.7 PR 6 — factory + pool used by PubSubTrigger and exposed for
|
|
55
|
-
// helper nodes (`@blokjs/pubsub-publish`).
|
|
56
|
-
export {
|
|
57
|
-
_resetAdapterPoolForTests,
|
|
58
|
-
createPubSubAdapter,
|
|
59
|
-
getOrCreateAdapter,
|
|
60
|
-
resolveProvider,
|
|
61
|
-
} from "./adapters/factory";
|
|
62
|
-
|
|
63
|
-
// Re-export types from helper for convenience
|
|
64
|
-
export type {
|
|
65
|
-
PubSubProvider,
|
|
66
|
-
PubSubTriggerOpts,
|
|
67
|
-
} from "@blokjs/helper";
|
package/template/.env.example
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
PROJECT_NAME=trigger-pubsub-server
|
|
2
|
-
PROJECT_VERSION=0.0.1
|
|
3
|
-
PORT=4006
|
|
4
|
-
WORKFLOWS_PATH=PROJECT_PATH/workflows
|
|
5
|
-
NODES_PATH=PROJECT_PATH/src/nodes
|
|
6
|
-
CONSOLE_LOG_ACTIVE=true
|
|
7
|
-
APP_NAME=blok-pubsub
|
|
8
|
-
DISABLE_TRIGGER_RUN=false # Set to true to disable trigger run and use this project as a module
|
package/template/package.json
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "blok-pubsub-trigger",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "Pub/Sub trigger for Blok workflows",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"engines": {
|
|
7
|
-
"node": ">=18.0.0"
|
|
8
|
-
},
|
|
9
|
-
"main": "dist/index.js",
|
|
10
|
-
"types": "dist/index.d.ts",
|
|
11
|
-
"author": "",
|
|
12
|
-
"license": "MIT",
|
|
13
|
-
"scripts": {
|
|
14
|
-
"dev": "bun --watch run src/index.ts",
|
|
15
|
-
"start": "bun run dist/index.js",
|
|
16
|
-
"build": "rimraf ./dist && tsc",
|
|
17
|
-
"test": "vitest run",
|
|
18
|
-
"test:dev": "vitest"
|
|
19
|
-
},
|
|
20
|
-
"devDependencies": {
|
|
21
|
-
"@types/node": "^22.15.21",
|
|
22
|
-
"@types/uuid": "^11.0.0",
|
|
23
|
-
"rimraf": "^6.1.2",
|
|
24
|
-
"typescript": "^5.8.3",
|
|
25
|
-
"vitest": "^4.0.18"
|
|
26
|
-
},
|
|
27
|
-
"dependencies": {
|
|
28
|
-
"@blokjs/api-call": "^0.6.17",
|
|
29
|
-
"@blokjs/helper": "^0.6.17",
|
|
30
|
-
"@blokjs/if-else": "^0.6.17",
|
|
31
|
-
"@blokjs/runner": "^0.6.17",
|
|
32
|
-
"@blokjs/shared": "^0.6.17",
|
|
33
|
-
"@blokjs/trigger-pubsub": "^0.6.17",
|
|
34
|
-
"@opentelemetry/api": "^1.9.0",
|
|
35
|
-
"@opentelemetry/exporter-prometheus": "^0.57.2",
|
|
36
|
-
"@opentelemetry/resources": "^1.30.1",
|
|
37
|
-
"@opentelemetry/sdk-metrics": "^1.30.1",
|
|
38
|
-
"@opentelemetry/sdk-trace-base": "^1.30.1",
|
|
39
|
-
"@opentelemetry/semantic-conventions": "^1.39.0",
|
|
40
|
-
"uuid": "^11.1.0",
|
|
41
|
-
"zod": "^3.24.2"
|
|
42
|
-
},
|
|
43
|
-
"private": true
|
|
44
|
-
}
|
package/template/src/Nodes.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import ApiCall from "@blokjs/api-call";
|
|
2
|
-
import IfElse from "@blokjs/if-else";
|
|
3
|
-
import type { BlokService } from "@blokjs/runner";
|
|
4
|
-
|
|
5
|
-
const nodes: Record<string, BlokService<unknown>> = {
|
|
6
|
-
"@blokjs/api-call": ApiCall,
|
|
7
|
-
"@blokjs/if-else": IfElse,
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export default nodes;
|
package/template/src/index.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { DefaultLogger } from "@blokjs/runner";
|
|
2
|
-
import { type Span, metrics, trace } from "@opentelemetry/api";
|
|
3
|
-
import PubSubServer from "./runner/PubSubServer";
|
|
4
|
-
|
|
5
|
-
export default class App {
|
|
6
|
-
private pubsubServer: PubSubServer = <PubSubServer>{};
|
|
7
|
-
protected trigger_initializer = 0;
|
|
8
|
-
protected initializer = 0;
|
|
9
|
-
protected tracer = trace.getTracer(
|
|
10
|
-
process.env.PROJECT_NAME || "trigger-pubsub-server",
|
|
11
|
-
process.env.PROJECT_VERSION || "0.0.1",
|
|
12
|
-
);
|
|
13
|
-
private logger = new DefaultLogger();
|
|
14
|
-
protected app_cold_start = metrics.getMeter("default").createGauge("initialization", {
|
|
15
|
-
description: "Application cold start",
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
constructor() {
|
|
19
|
-
this.initializer = performance.now();
|
|
20
|
-
this.pubsubServer = new PubSubServer();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async run() {
|
|
24
|
-
this.tracer.startActiveSpan("initialization", async (span: Span) => {
|
|
25
|
-
await this.pubsubServer.listen();
|
|
26
|
-
this.initializer = performance.now() - this.initializer;
|
|
27
|
-
|
|
28
|
-
this.logger.log(`Pub/Sub trigger initialized in ${this.initializer.toFixed(2)}ms`);
|
|
29
|
-
this.app_cold_start.record(this.initializer, {
|
|
30
|
-
pid: process.pid,
|
|
31
|
-
env: process.env.NODE_ENV,
|
|
32
|
-
app: process.env.APP_NAME,
|
|
33
|
-
});
|
|
34
|
-
span.end();
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (process.env.DISABLE_TRIGGER_RUN !== "true") {
|
|
40
|
-
new App().run();
|
|
41
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { GCPPubSubAdapter, PubSubTrigger } from "@blokjs/trigger-pubsub";
|
|
2
|
-
import nodes from "../Nodes";
|
|
3
|
-
import workflows from "../Workflows";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* PubSubServer - Concrete Pub/Sub trigger implementation
|
|
7
|
-
*
|
|
8
|
-
* This server extends the abstract PubSubTrigger and provides:
|
|
9
|
-
* - A specific adapter (GCP Pub/Sub by default, can be changed to AWS or Azure)
|
|
10
|
-
* - Node and workflow registries
|
|
11
|
-
*
|
|
12
|
-
* To change the provider, replace:
|
|
13
|
-
* - GCPPubSubAdapter with AWSSNSAdapter or AzureServiceBusAdapter
|
|
14
|
-
* - Update the adapter configuration accordingly
|
|
15
|
-
*
|
|
16
|
-
* @example AWS SNS/SQS
|
|
17
|
-
* ```typescript
|
|
18
|
-
* import { AWSSNSAdapter } from "@blokjs/trigger-pubsub";
|
|
19
|
-
* protected adapter = new AWSSNSAdapter({
|
|
20
|
-
* region: process.env.AWS_REGION || "us-east-1",
|
|
21
|
-
* });
|
|
22
|
-
* ```
|
|
23
|
-
*
|
|
24
|
-
* @example Azure Service Bus
|
|
25
|
-
* ```typescript
|
|
26
|
-
* import { AzureServiceBusAdapter } from "@blokjs/trigger-pubsub";
|
|
27
|
-
* protected adapter = new AzureServiceBusAdapter({
|
|
28
|
-
* connectionString: process.env.AZURE_SERVICE_BUS_CONNECTION_STRING || "",
|
|
29
|
-
* });
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export default class PubSubServer extends PubSubTrigger {
|
|
33
|
-
protected adapter = new GCPPubSubAdapter({
|
|
34
|
-
projectId: process.env.GCP_PROJECT_ID || "my-project",
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
protected nodes: Record<string, import("@blokjs/runner").BlokService<unknown>> = nodes;
|
|
38
|
-
protected workflows: Record<string, import("@blokjs/helper").HelperResponse> = workflows;
|
|
39
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { workflow } from "@blokjs/helper";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Example Pub/Sub workflow — fires when a message arrives on a subscription.
|
|
5
|
-
*
|
|
6
|
-
* Message payload + metadata on ctx.request:
|
|
7
|
-
* - ctx.request.body — the message payload
|
|
8
|
-
* - ctx.request.headers — message attributes
|
|
9
|
-
* - ctx.request.params.topic — topic name
|
|
10
|
-
* - ctx.request.params.subscription — subscription name
|
|
11
|
-
* - ctx.request.params.messageId — unique message ID
|
|
12
|
-
* - ctx.vars._pubsub_message — full broker metadata
|
|
13
|
-
*
|
|
14
|
-
* Pick a provider in the trigger config:
|
|
15
|
-
* provider: "gcp" | "aws" | "azure"
|
|
16
|
-
*
|
|
17
|
-
* v2 reliability knobs available on each step (uncomment to use):
|
|
18
|
-
* idempotencyKey: "$.req.params.messageId" — at-most-once delivery semantics
|
|
19
|
-
* retry: { maxAttempts: 3 } — retry on transient failures
|
|
20
|
-
*/
|
|
21
|
-
export default workflow({
|
|
22
|
-
name: "On Pub/Sub Message",
|
|
23
|
-
version: "1.0.0",
|
|
24
|
-
description: "Handles incoming Pub/Sub messages",
|
|
25
|
-
trigger: {
|
|
26
|
-
pubsub: {
|
|
27
|
-
provider: "gcp",
|
|
28
|
-
topic: "my-topic",
|
|
29
|
-
subscription: "my-subscription",
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
steps: [
|
|
33
|
-
{
|
|
34
|
-
id: "log-message",
|
|
35
|
-
use: "@blokjs/api-call",
|
|
36
|
-
type: "module",
|
|
37
|
-
inputs: {
|
|
38
|
-
url: "https://httpbin.org/post",
|
|
39
|
-
method: "POST",
|
|
40
|
-
body: {
|
|
41
|
-
message: "js/ctx.request.body",
|
|
42
|
-
topic: "js/ctx.request.params.topic",
|
|
43
|
-
messageId: "js/ctx.request.params.messageId",
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
|
-
});
|
package/template/tsconfig.json
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"ts-node": {
|
|
3
|
-
"transpileOnly": true
|
|
4
|
-
},
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"target": "ES2022",
|
|
7
|
-
"module": "es2022",
|
|
8
|
-
"moduleResolution": "bundler",
|
|
9
|
-
"rootDir": "./src",
|
|
10
|
-
"baseUrl": ".",
|
|
11
|
-
"paths": {
|
|
12
|
-
"@nodes/*": ["./src/nodes/*"],
|
|
13
|
-
"@src/*": ["src/*"]
|
|
14
|
-
},
|
|
15
|
-
"allowJs": true,
|
|
16
|
-
"declaration": true,
|
|
17
|
-
"declarationMap": true,
|
|
18
|
-
"sourceMap": true,
|
|
19
|
-
"outDir": "./dist",
|
|
20
|
-
"esModuleInterop": true,
|
|
21
|
-
"forceConsistentCasingInFileNames": true,
|
|
22
|
-
"strict": true,
|
|
23
|
-
"noUnusedLocals": true,
|
|
24
|
-
"noImplicitReturns": true,
|
|
25
|
-
"skipLibCheck": true,
|
|
26
|
-
"resolveJsonModule": true
|
|
27
|
-
},
|
|
28
|
-
"compileOnSave": true,
|
|
29
|
-
"include": ["./src", "./src/nodes/**/*.json", "./src/nodes/**/*.md"],
|
|
30
|
-
"exclude": ["src/nodes/**/test/*.ts", "**/*.test.ts", "node_modules", "dist"]
|
|
31
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { defineConfig } from "vitest/config";
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
test: {
|
|
6
|
-
globals: true,
|
|
7
|
-
environment: "node",
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: "istanbul",
|
|
10
|
-
reporter: ["text", "json", "html", "lcov"],
|
|
11
|
-
exclude: [
|
|
12
|
-
"node_modules/",
|
|
13
|
-
"dist/",
|
|
14
|
-
"**/*.d.ts",
|
|
15
|
-
"**/*.config.ts",
|
|
16
|
-
"__tests__/",
|
|
17
|
-
"src/nodes/",
|
|
18
|
-
"src/workflows/",
|
|
19
|
-
"src/runner/types/",
|
|
20
|
-
"src/runner/metrics/",
|
|
21
|
-
],
|
|
22
|
-
thresholds: {
|
|
23
|
-
lines: 90,
|
|
24
|
-
functions: 90,
|
|
25
|
-
branches: 85,
|
|
26
|
-
statements: 90,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
include: ["__tests__/**/*.test.ts"],
|
|
30
|
-
exclude: ["node_modules", "dist"],
|
|
31
|
-
testTimeout: 10000,
|
|
32
|
-
hookTimeout: 10000,
|
|
33
|
-
},
|
|
34
|
-
resolve: {
|
|
35
|
-
alias: {
|
|
36
|
-
"@": path.resolve(__dirname, "./src"),
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"ts-node": {
|
|
3
|
-
"transpileOnly": true
|
|
4
|
-
},
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"target": "ES2022",
|
|
7
|
-
"module": "es2022",
|
|
8
|
-
"lib": ["ES2022"],
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"strict": true,
|
|
11
|
-
"noImplicitAny": true,
|
|
12
|
-
"strictNullChecks": true,
|
|
13
|
-
"noImplicitThis": true,
|
|
14
|
-
"alwaysStrict": true,
|
|
15
|
-
"noUnusedLocals": false,
|
|
16
|
-
"noUnusedParameters": false,
|
|
17
|
-
"noImplicitReturns": true,
|
|
18
|
-
"noFallthroughCasesInSwitch": false,
|
|
19
|
-
"inlineSourceMap": true,
|
|
20
|
-
"inlineSources": true,
|
|
21
|
-
"experimentalDecorators": true,
|
|
22
|
-
"emitDecoratorMetadata": true,
|
|
23
|
-
"skipLibCheck": true,
|
|
24
|
-
"esModuleInterop": true,
|
|
25
|
-
"resolveJsonModule": true,
|
|
26
|
-
"outDir": "./dist",
|
|
27
|
-
"rootDir": "./src",
|
|
28
|
-
"moduleResolution": "bundler"
|
|
29
|
-
},
|
|
30
|
-
"include": ["src/**/*"],
|
|
31
|
-
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
32
|
-
}
|