@stepflowjs/trigger-stream 0.0.1
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/index.d.ts +93 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/package.json +57 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Trigger, TriggerHandler } from '@stepflowjs/core';
|
|
2
|
+
|
|
3
|
+
interface StreamTriggerConfig<T = unknown> {
|
|
4
|
+
/** Identifier for the stream source */
|
|
5
|
+
source: string;
|
|
6
|
+
/** The async iterable to consume */
|
|
7
|
+
stream: AsyncIterable<T>;
|
|
8
|
+
/** Optional transform function to apply to each item */
|
|
9
|
+
transform?: (item: T) => unknown;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generic async iterable stream trigger for Stepflow workflows
|
|
13
|
+
*
|
|
14
|
+
* Consumes items from an AsyncIterable and creates trigger events for each item.
|
|
15
|
+
* This is a base class for custom stream-based triggers (e.g., Kafka, NATS, message queues).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Basic usage with async generator
|
|
20
|
+
* async function* numberStream() {
|
|
21
|
+
* for (let i = 0; i < 10; i++) {
|
|
22
|
+
* yield i;
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* const trigger = new StreamTrigger({
|
|
27
|
+
* source: 'number-stream',
|
|
28
|
+
* stream: numberStream(),
|
|
29
|
+
* transform: (n) => ({ value: n, squared: n * n }),
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* await trigger.start(async (event) => {
|
|
33
|
+
* await stepflow.trigger('process-number', event.data);
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // Using the helper function
|
|
40
|
+
* const trigger = createStreamTrigger(
|
|
41
|
+
* 'events',
|
|
42
|
+
* eventStream,
|
|
43
|
+
* (event) => ({ ...event, processed: true })
|
|
44
|
+
* );
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare class StreamTrigger<T = unknown> implements Trigger<StreamTriggerConfig<T>> {
|
|
48
|
+
readonly config: StreamTriggerConfig<T>;
|
|
49
|
+
readonly type = "stream";
|
|
50
|
+
private handler?;
|
|
51
|
+
private abortController?;
|
|
52
|
+
private running;
|
|
53
|
+
private consumePromise?;
|
|
54
|
+
constructor(config: StreamTriggerConfig<T>);
|
|
55
|
+
/**
|
|
56
|
+
* Start the trigger with a handler function
|
|
57
|
+
* @param handler Function to call when stream items are received
|
|
58
|
+
*/
|
|
59
|
+
start(handler: TriggerHandler): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Consume items from the stream and create trigger events
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
64
|
+
private consumeStream;
|
|
65
|
+
/**
|
|
66
|
+
* Stop the trigger and cancel stream consumption
|
|
67
|
+
*/
|
|
68
|
+
stop(): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Health check - returns true if trigger is running
|
|
71
|
+
*/
|
|
72
|
+
healthCheck(): Promise<boolean>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create a stream trigger from an async iterable
|
|
76
|
+
*
|
|
77
|
+
* @param source Identifier for the stream source
|
|
78
|
+
* @param stream The async iterable to consume
|
|
79
|
+
* @param transform Optional transform function to apply to each item
|
|
80
|
+
* @returns A new StreamTrigger instance
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* const trigger = createStreamTrigger(
|
|
85
|
+
* 'kafka-topic',
|
|
86
|
+
* kafkaConsumer,
|
|
87
|
+
* (msg) => JSON.parse(msg.value)
|
|
88
|
+
* );
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
declare function createStreamTrigger<T>(source: string, stream: AsyncIterable<T>, transform?: (item: T) => unknown): StreamTrigger<T>;
|
|
92
|
+
|
|
93
|
+
export { StreamTrigger, type StreamTriggerConfig, createStreamTrigger };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var StreamTrigger = class {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.config = config;
|
|
5
|
+
}
|
|
6
|
+
type = "stream";
|
|
7
|
+
handler;
|
|
8
|
+
abortController;
|
|
9
|
+
running = false;
|
|
10
|
+
consumePromise;
|
|
11
|
+
/**
|
|
12
|
+
* Start the trigger with a handler function
|
|
13
|
+
* @param handler Function to call when stream items are received
|
|
14
|
+
*/
|
|
15
|
+
async start(handler) {
|
|
16
|
+
if (this.running) {
|
|
17
|
+
throw new Error("StreamTrigger is already running");
|
|
18
|
+
}
|
|
19
|
+
this.handler = handler;
|
|
20
|
+
this.abortController = new AbortController();
|
|
21
|
+
this.running = true;
|
|
22
|
+
this.consumePromise = this.consumeStream().catch((error) => {
|
|
23
|
+
if (error.name !== "AbortError") {
|
|
24
|
+
console.error("Stream error:", error);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Consume items from the stream and create trigger events
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
async consumeStream() {
|
|
33
|
+
try {
|
|
34
|
+
for await (const item of this.config.stream) {
|
|
35
|
+
if (!this.running) break;
|
|
36
|
+
const data = this.config.transform ? this.config.transform(item) : item;
|
|
37
|
+
const event = {
|
|
38
|
+
id: crypto.randomUUID(),
|
|
39
|
+
type: this.type,
|
|
40
|
+
source: this.config.source,
|
|
41
|
+
data,
|
|
42
|
+
metadata: {},
|
|
43
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
44
|
+
};
|
|
45
|
+
await this.handler?.(event);
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (this.running) {
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Stop the trigger and cancel stream consumption
|
|
55
|
+
*/
|
|
56
|
+
async stop() {
|
|
57
|
+
this.running = false;
|
|
58
|
+
this.abortController?.abort();
|
|
59
|
+
this.handler = void 0;
|
|
60
|
+
if (this.consumePromise) {
|
|
61
|
+
await this.consumePromise.catch(() => {
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Health check - returns true if trigger is running
|
|
67
|
+
*/
|
|
68
|
+
async healthCheck() {
|
|
69
|
+
return this.running;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
function createStreamTrigger(source, stream, transform) {
|
|
73
|
+
return new StreamTrigger({ source, stream, transform });
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
StreamTrigger,
|
|
77
|
+
createStreamTrigger
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { Trigger, TriggerHandler, TriggerEvent } from \"@stepflowjs/core\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StreamTriggerConfig<T = unknown> {\n /** Identifier for the stream source */\n source: string;\n /** The async iterable to consume */\n stream: AsyncIterable<T>;\n /** Optional transform function to apply to each item */\n transform?: (item: T) => unknown;\n}\n\n// ============================================================================\n// StreamTrigger Implementation\n// ============================================================================\n\n/**\n * Generic async iterable stream trigger for Stepflow workflows\n *\n * Consumes items from an AsyncIterable and creates trigger events for each item.\n * This is a base class for custom stream-based triggers (e.g., Kafka, NATS, message queues).\n *\n * @example\n * ```typescript\n * // Basic usage with async generator\n * async function* numberStream() {\n * for (let i = 0; i < 10; i++) {\n * yield i;\n * }\n * }\n *\n * const trigger = new StreamTrigger({\n * source: 'number-stream',\n * stream: numberStream(),\n * transform: (n) => ({ value: n, squared: n * n }),\n * });\n *\n * await trigger.start(async (event) => {\n * await stepflow.trigger('process-number', event.data);\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Using the helper function\n * const trigger = createStreamTrigger(\n * 'events',\n * eventStream,\n * (event) => ({ ...event, processed: true })\n * );\n * ```\n */\nexport class StreamTrigger<T = unknown> implements Trigger<\n StreamTriggerConfig<T>\n> {\n readonly type = \"stream\";\n private handler?: TriggerHandler;\n private abortController?: AbortController;\n private running = false;\n private consumePromise?: Promise<void>;\n\n constructor(readonly config: StreamTriggerConfig<T>) {}\n\n /**\n * Start the trigger with a handler function\n * @param handler Function to call when stream items are received\n */\n async start(handler: TriggerHandler): Promise<void> {\n if (this.running) {\n throw new Error(\"StreamTrigger is already running\");\n }\n\n this.handler = handler;\n this.abortController = new AbortController();\n this.running = true;\n\n // Start consuming the stream in the background\n this.consumePromise = this.consumeStream().catch((error) => {\n if (error.name !== \"AbortError\") {\n console.error(\"Stream error:\", error);\n }\n });\n }\n\n /**\n * Consume items from the stream and create trigger events\n * @private\n */\n private async consumeStream(): Promise<void> {\n try {\n for await (const item of this.config.stream) {\n if (!this.running) break;\n\n const data = this.config.transform ? this.config.transform(item) : item;\n\n const event: TriggerEvent = {\n id: crypto.randomUUID(),\n type: this.type,\n source: this.config.source,\n data,\n metadata: {},\n timestamp: new Date(),\n };\n\n await this.handler?.(event);\n }\n } catch (error) {\n if (this.running) {\n throw error;\n }\n }\n }\n\n /**\n * Stop the trigger and cancel stream consumption\n */\n async stop(): Promise<void> {\n this.running = false;\n this.abortController?.abort();\n this.handler = undefined;\n\n // Wait for stream consumption to complete\n if (this.consumePromise) {\n await this.consumePromise.catch(() => {\n // Ignore errors during shutdown\n });\n }\n }\n\n /**\n * Health check - returns true if trigger is running\n */\n async healthCheck(): Promise<boolean> {\n return this.running;\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Create a stream trigger from an async iterable\n *\n * @param source Identifier for the stream source\n * @param stream The async iterable to consume\n * @param transform Optional transform function to apply to each item\n * @returns A new StreamTrigger instance\n *\n * @example\n * ```typescript\n * const trigger = createStreamTrigger(\n * 'kafka-topic',\n * kafkaConsumer,\n * (msg) => JSON.parse(msg.value)\n * );\n * ```\n */\nexport function createStreamTrigger<T>(\n source: string,\n stream: AsyncIterable<T>,\n transform?: (item: T) => unknown,\n): StreamTrigger<T> {\n return new StreamTrigger({ source, stream, transform });\n}\n"],"mappings":";AAuDO,IAAM,gBAAN,MAEL;AAAA,EAOA,YAAqB,QAAgC;AAAhC;AAAA,EAAiC;AAAA,EAN7C,OAAO;AAAA,EACR;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA,EAQR,MAAM,MAAM,SAAwC;AAClD,QAAI,KAAK,SAAS;AAChB,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAEA,SAAK,UAAU;AACf,SAAK,kBAAkB,IAAI,gBAAgB;AAC3C,SAAK,UAAU;AAGf,SAAK,iBAAiB,KAAK,cAAc,EAAE,MAAM,CAAC,UAAU;AAC1D,UAAI,MAAM,SAAS,cAAc;AAC/B,gBAAQ,MAAM,iBAAiB,KAAK;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,gBAA+B;AAC3C,QAAI;AACF,uBAAiB,QAAQ,KAAK,OAAO,QAAQ;AAC3C,YAAI,CAAC,KAAK,QAAS;AAEnB,cAAM,OAAO,KAAK,OAAO,YAAY,KAAK,OAAO,UAAU,IAAI,IAAI;AAEnE,cAAM,QAAsB;AAAA,UAC1B,IAAI,OAAO,WAAW;AAAA,UACtB,MAAM,KAAK;AAAA,UACX,QAAQ,KAAK,OAAO;AAAA,UACpB;AAAA,UACA,UAAU,CAAC;AAAA,UACX,WAAW,oBAAI,KAAK;AAAA,QACtB;AAEA,cAAM,KAAK,UAAU,KAAK;AAAA,MAC5B;AAAA,IACF,SAAS,OAAO;AACd,UAAI,KAAK,SAAS;AAChB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC1B,SAAK,UAAU;AACf,SAAK,iBAAiB,MAAM;AAC5B,SAAK,UAAU;AAGf,QAAI,KAAK,gBAAgB;AACvB,YAAM,KAAK,eAAe,MAAM,MAAM;AAAA,MAEtC,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAgC;AACpC,WAAO,KAAK;AAAA,EACd;AACF;AAuBO,SAAS,oBACd,QACA,QACA,WACkB;AAClB,SAAO,IAAI,cAAc,EAAE,QAAQ,QAAQ,UAAU,CAAC;AACxD;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stepflowjs/trigger-stream",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Generic async iterable stream trigger for Stepflow",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@stepflowjs/core": "0.0.1"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"tsup": "^8.5.1",
|
|
23
|
+
"vitest": "^4.0.17"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"typescript": "^5.0.0"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"author": "Stepflow Contributors",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://stepflow-production.up.railway.app",
|
|
33
|
+
"directory": "packages/triggers/stream"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://stepflow-production.up.railway.app",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://stepflow-production.up.railway.app"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"stepflow",
|
|
41
|
+
"trigger",
|
|
42
|
+
"stream",
|
|
43
|
+
"async-iterable",
|
|
44
|
+
"workflow",
|
|
45
|
+
"orchestration"
|
|
46
|
+
],
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup",
|
|
52
|
+
"dev": "tsup --watch",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"test": "vitest",
|
|
55
|
+
"clean": "rm -rf dist"
|
|
56
|
+
}
|
|
57
|
+
}
|