@blokjs/shared 0.4.0 → 0.6.0
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/__tests__/unit/NodeBase.test.ts +10 -9
- package/__tests__/unit/utils/Mapper.test.ts +8 -7
- package/dist/NodeBase.d.ts +0 -11
- package/dist/NodeBase.js +0 -11
- package/dist/NodeBase.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/types/ConnectionContext.d.ts +79 -0
- package/dist/types/ConnectionContext.js +2 -0
- package/dist/types/ConnectionContext.js.map +1 -0
- package/dist/types/Context.d.ts +34 -0
- package/dist/types/StreamContext.d.ts +92 -0
- package/dist/types/StreamContext.js +2 -0
- package/dist/types/StreamContext.js.map +1 -0
- package/package.json +1 -1
|
@@ -14,7 +14,10 @@ class TestNode extends NodeBase {
|
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
// Loose `Record<string, unknown>` overrides so tests can pass shapes that
|
|
18
|
+
// don't strictly match `Partial<Context>` (e.g. `config: { "<node>": ... }`,
|
|
19
|
+
// which is the runtime layout but isn't reflected in the typed `ConfigContext`).
|
|
20
|
+
function createTestContext(overrides: Record<string, unknown> = {}): Context {
|
|
18
21
|
return {
|
|
19
22
|
id: "test-ctx",
|
|
20
23
|
request: { body: {}, headers: {}, query: {}, params: {} },
|
|
@@ -27,7 +30,7 @@ function createTestContext(overrides: Partial<Context> = {}): Context {
|
|
|
27
30
|
eventLogger: null,
|
|
28
31
|
_PRIVATE_: null,
|
|
29
32
|
...overrides,
|
|
30
|
-
} as Context;
|
|
33
|
+
} as unknown as Context;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
describe("NodeBase", () => {
|
|
@@ -46,10 +49,8 @@ describe("NodeBase", () => {
|
|
|
46
49
|
expect(n.name).toBe("");
|
|
47
50
|
expect(n.active).toBe(true);
|
|
48
51
|
expect(n.stop).toBe(false);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// default-store rule for every step that didn't explicitly set it.
|
|
52
|
-
expect(n.set_var).toBeUndefined();
|
|
52
|
+
expect(n.ephemeral).toBe(false);
|
|
53
|
+
expect(n.spread).toBe(false);
|
|
53
54
|
expect(n.contentType).toBe("");
|
|
54
55
|
});
|
|
55
56
|
});
|
|
@@ -162,7 +163,7 @@ describe("NodeBase", () => {
|
|
|
162
163
|
|
|
163
164
|
it("should access data parameter", () => {
|
|
164
165
|
const ctx = createTestContext();
|
|
165
|
-
const result = node.runJs("data.x", ctx, { x: 42 });
|
|
166
|
+
const result = node.runJs("data.x", ctx, { x: 42 } as unknown as Record<string, string>);
|
|
166
167
|
expect(result).toBe(42);
|
|
167
168
|
});
|
|
168
169
|
|
|
@@ -215,7 +216,7 @@ describe("NodeBase", () => {
|
|
|
215
216
|
describe("blueprintMapper()", () => {
|
|
216
217
|
it("should handle string input", () => {
|
|
217
218
|
const ctx = createTestContext();
|
|
218
|
-
const result = node.blueprintMapper("plain text", ctx);
|
|
219
|
+
const result = node.blueprintMapper("plain text" as unknown as Record<string, string>, ctx);
|
|
219
220
|
expect(result).toBe("plain text");
|
|
220
221
|
});
|
|
221
222
|
|
|
@@ -230,7 +231,7 @@ describe("NodeBase", () => {
|
|
|
230
231
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
231
232
|
const ctx = createTestContext();
|
|
232
233
|
// null will cause mapper to fail
|
|
233
|
-
const result = node.blueprintMapper(null as unknown as Record<string,
|
|
234
|
+
const result = node.blueprintMapper(null as unknown as Record<string, string>, ctx);
|
|
234
235
|
// Should not throw
|
|
235
236
|
expect(result).toBeNull();
|
|
236
237
|
consoleSpy.mockRestore();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
import type Context from "../../../src/types/Context";
|
|
3
|
+
import type ParamsDictionary from "../../../src/types/ParamsDictionary";
|
|
3
4
|
import mapper from "../../../src/utils/Mapper";
|
|
4
5
|
import { MapperResolutionError } from "../../../src/utils/MapperResolutionError";
|
|
5
6
|
|
|
@@ -66,7 +67,7 @@ describe("Mapper", () => {
|
|
|
66
67
|
it("handles nested data access via lodash.get", () => {
|
|
67
68
|
const ctx = createMockContext();
|
|
68
69
|
const data = { user: { name: "Alice" } };
|
|
69
|
-
const result = mapper.replaceString("Hi ${user.name}", ctx, data);
|
|
70
|
+
const result = mapper.replaceString("Hi ${user.name}", ctx, data as unknown as ParamsDictionary);
|
|
70
71
|
expect(result).toBe("Hi Alice");
|
|
71
72
|
});
|
|
72
73
|
|
|
@@ -100,22 +101,22 @@ describe("Mapper", () => {
|
|
|
100
101
|
// returned 0, the `||` fell through to runJs (which would throw
|
|
101
102
|
// for "count" not being in scope). Now `=== undefined` check
|
|
102
103
|
// preserves the 0.
|
|
103
|
-
expect(mapper.replaceString("${count}", ctx, { count: 0 })).toBe("0");
|
|
104
|
-
expect(mapper.replaceString("${flag}", ctx, { flag: false })).toBe("false");
|
|
105
|
-
expect(mapper.replaceString("${empty}", ctx, { empty: "" })).toBe("");
|
|
104
|
+
expect(mapper.replaceString("${count}", ctx, { count: 0 } as unknown as ParamsDictionary)).toBe("0");
|
|
105
|
+
expect(mapper.replaceString("${flag}", ctx, { flag: false } as unknown as ParamsDictionary)).toBe("false");
|
|
106
|
+
expect(mapper.replaceString("${empty}", ctx, { empty: "" } as unknown as ParamsDictionary)).toBe("");
|
|
106
107
|
});
|
|
107
108
|
|
|
108
109
|
it("JSON-encodes object values in interpolation (was: '[object Object]')", () => {
|
|
109
110
|
const ctx = createMockContext();
|
|
110
111
|
const data = { user: { id: 1, name: "Alice" } };
|
|
111
|
-
const result = mapper.replaceString("payload=${user}", ctx, data);
|
|
112
|
+
const result = mapper.replaceString("payload=${user}", ctx, data as unknown as ParamsDictionary);
|
|
112
113
|
// Pre-v0.3.x: `value as string` → "[object Object]". Now JSON.
|
|
113
114
|
expect(result).toBe('payload={"id":1,"name":"Alice"}');
|
|
114
115
|
});
|
|
115
116
|
|
|
116
117
|
it("renders null/undefined interpolation values as empty string", () => {
|
|
117
118
|
const ctx = createMockContext();
|
|
118
|
-
const result = mapper.replaceString("v=${x}", ctx, { x: null });
|
|
119
|
+
const result = mapper.replaceString("v=${x}", ctx, { x: null } as unknown as ParamsDictionary);
|
|
119
120
|
expect(result).toBe("v=");
|
|
120
121
|
});
|
|
121
122
|
|
|
@@ -220,7 +221,7 @@ describe("Mapper", () => {
|
|
|
220
221
|
setMode("strict");
|
|
221
222
|
const ctx = createMockContext();
|
|
222
223
|
expect(mapper.replaceString("js/1 + 2", ctx, {})).toBe(3);
|
|
223
|
-
expect(mapper.replaceString("${name}", ctx, { name: "ok" })).toBe("ok");
|
|
224
|
+
expect(mapper.replaceString("${name}", ctx, { name: "ok" } as unknown as ParamsDictionary)).toBe("ok");
|
|
224
225
|
});
|
|
225
226
|
});
|
|
226
227
|
|
package/dist/NodeBase.d.ts
CHANGED
|
@@ -13,17 +13,6 @@ export default abstract class NodeBase {
|
|
|
13
13
|
active: boolean;
|
|
14
14
|
stop: boolean;
|
|
15
15
|
originalConfig: ParamsDictionary;
|
|
16
|
-
/**
|
|
17
|
-
* @deprecated v2 default-stores every step's output. `set_var: true` is
|
|
18
|
-
* a no-op (default behaviour); `set_var: false` is normalized to
|
|
19
|
-
* `ephemeral: true` at workflow load time. Reading this field is still
|
|
20
|
-
* supported for legacy code paths but new code should rely on `ephemeral`.
|
|
21
|
-
*
|
|
22
|
-
* Default is `undefined` (NOT `false`) — `false` here would short-circuit
|
|
23
|
-
* `PersistenceHelper.applyStepOutput` and disable the v2 default-store
|
|
24
|
-
* rule for every step that didn't explicitly set the field.
|
|
25
|
-
*/
|
|
26
|
-
set_var?: boolean;
|
|
27
16
|
/**
|
|
28
17
|
* Alternative state key for this step's output. When set, the runner
|
|
29
18
|
* stores result.data at `ctx.state[as]` instead of `ctx.state[name]`.
|
package/dist/NodeBase.js
CHANGED
|
@@ -9,17 +9,6 @@ export default class NodeBase {
|
|
|
9
9
|
active = true;
|
|
10
10
|
stop = false;
|
|
11
11
|
originalConfig = {};
|
|
12
|
-
/**
|
|
13
|
-
* @deprecated v2 default-stores every step's output. `set_var: true` is
|
|
14
|
-
* a no-op (default behaviour); `set_var: false` is normalized to
|
|
15
|
-
* `ephemeral: true` at workflow load time. Reading this field is still
|
|
16
|
-
* supported for legacy code paths but new code should rely on `ephemeral`.
|
|
17
|
-
*
|
|
18
|
-
* Default is `undefined` (NOT `false`) — `false` here would short-circuit
|
|
19
|
-
* `PersistenceHelper.applyStepOutput` and disable the v2 default-store
|
|
20
|
-
* rule for every step that didn't explicitly set the field.
|
|
21
|
-
*/
|
|
22
|
-
set_var;
|
|
23
12
|
// =========================================================================
|
|
24
13
|
// V2 persistence knobs — populated by Configuration.getSteps from the
|
|
25
14
|
// step definition. Read by PersistenceHelper.applyStepOutput.
|
package/dist/NodeBase.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeBase.js","sourceRoot":"","sources":["../src/NodeBase.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,QAAQ,CAAC;AACvB,OAAO,WAAW,MAAM,eAAe,CAAC;AASxC,OAAO,MAAM,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,MAAM,CAAC,OAAO,OAAgB,QAAQ;IAC9B,IAAI,GAAG,KAAK,CAAC;IACb,IAAI,GAAG,EAAE,CAAC;IACV,WAAW,GAAG,EAAE,CAAC;IACjB,MAAM,GAAG,IAAI,CAAC;IACd,IAAI,GAAG,KAAK,CAAC;IACb,cAAc,GAAqB,EAAE,CAAC;IAE7C
|
|
1
|
+
{"version":3,"file":"NodeBase.js","sourceRoot":"","sources":["../src/NodeBase.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ import { Metrics, type MetricsType } from "./Metrics";
|
|
|
5
5
|
import NodeBase from "./NodeBase";
|
|
6
6
|
import Trigger from "./Trigger";
|
|
7
7
|
import ConfigContext from "./types/ConfigContext";
|
|
8
|
+
import type ConnectionContext from "./types/ConnectionContext";
|
|
8
9
|
import Context from "./types/Context";
|
|
10
|
+
import EnvContext from "./types/EnvContext";
|
|
9
11
|
import ErrorContext from "./types/ErrorContext";
|
|
10
12
|
import FunctionContext from "./types/FunctionContext";
|
|
11
13
|
import LoggerContext from "./types/LoggerContext";
|
|
@@ -14,6 +16,8 @@ import RequestContext from "./types/RequestContext";
|
|
|
14
16
|
import ResponseContext from "./types/ResponseContext";
|
|
15
17
|
import StateContext from "./types/StateContext";
|
|
16
18
|
import Step from "./types/Step";
|
|
19
|
+
import type StreamContext from "./types/StreamContext";
|
|
17
20
|
import VarsContext from "./types/VarsContext";
|
|
21
|
+
import mapper from "./utils/Mapper";
|
|
18
22
|
import MemoryUsage from "./utils/MemoryUsage";
|
|
19
|
-
export { NodeBase, Context, RequestContext, ResponseContext, ErrorContext, LoggerContext, ConfigContext, Trigger, NodeConfigContext, FunctionContext, StateContext, VarsContext, Step, GlobalLogger, GlobalError, BlokError, type BlokErrorOpts, type NodeErrorPayload, ErrorCategory, ErrorSeverity, DEFAULT_HTTP_STATUS, DEFAULT_RETRYABLE, Metrics, MemoryUsage, type MetricsType, };
|
|
23
|
+
export { NodeBase, Context, RequestContext, ResponseContext, EnvContext, ErrorContext, LoggerContext, ConfigContext, type ConnectionContext, type StreamContext, Trigger, NodeConfigContext, FunctionContext, StateContext, VarsContext, Step, GlobalLogger, GlobalError, BlokError, type BlokErrorOpts, type NodeErrorPayload, ErrorCategory, ErrorSeverity, DEFAULT_HTTP_STATUS, DEFAULT_RETRYABLE, Metrics, MemoryUsage, type MetricsType, mapper, };
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import GlobalLogger from "./GlobalLogger";
|
|
|
4
4
|
import { Metrics } from "./Metrics";
|
|
5
5
|
import NodeBase from "./NodeBase";
|
|
6
6
|
import Trigger from "./Trigger";
|
|
7
|
+
import mapper from "./utils/Mapper";
|
|
7
8
|
import MemoryUsage from "./utils/MemoryUsage";
|
|
8
|
-
export { NodeBase, Trigger, GlobalLogger, GlobalError, BlokError, ErrorCategory, ErrorSeverity, DEFAULT_HTTP_STATUS, DEFAULT_RETRYABLE, Metrics, MemoryUsage, };
|
|
9
|
+
export { NodeBase, Trigger, GlobalLogger, GlobalError, BlokError, ErrorCategory, ErrorSeverity, DEFAULT_HTTP_STATUS, DEFAULT_RETRYABLE, Metrics, MemoryUsage, mapper, };
|
|
9
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAEjB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,aAAa,GAEb,MAAM,aAAa,CAAC;AACrB,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAoB,MAAM,WAAW,CAAC;AACtD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,OAAO,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAEjB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,aAAa,GAEb,MAAM,aAAa,CAAC;AACrB,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,YAAY,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAoB,MAAM,WAAW,CAAC;AACtD,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,OAAO,MAAM,WAAW,CAAC;AAehC,OAAO,MAAM,MAAM,gBAAgB,CAAC;AACpC,OAAO,WAAW,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EACN,QAAQ,EAUR,OAAO,EAMP,YAAY,EACZ,WAAW,EACX,SAAS,EAGT,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,OAAO,EACP,WAAW,EAEX,MAAM,GACN,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.7 — per-connection API exposed on `ctx.connection` for triggers
|
|
3
|
+
* that hold long-lived bidirectional channels (WebSocket today; SSE
|
|
4
|
+
* gets a streaming variant in PR 3).
|
|
5
|
+
*
|
|
6
|
+
* Authors interact with the connection through this object — the
|
|
7
|
+
* trigger wraps the underlying transport's send/close primitives and
|
|
8
|
+
* tracks per-connection state. Lifecycle:
|
|
9
|
+
*
|
|
10
|
+
* - On `connect`: trigger creates the connection, runs the workflow
|
|
11
|
+
* once with `ctx.connection` bound. Author can call
|
|
12
|
+
* `setAttachment()` to store per-connection state.
|
|
13
|
+
* - On `message`: trigger runs the workflow again with the same
|
|
14
|
+
* `ctx.connection` instance — author reads `attachment` to recover
|
|
15
|
+
* the per-connection state.
|
|
16
|
+
* - On `disconnect`: same connection, last run. Cleanup happens here.
|
|
17
|
+
*
|
|
18
|
+
* Absent on contexts built for HTTP / Worker / Cron triggers.
|
|
19
|
+
*/
|
|
20
|
+
export interface ConnectionContext {
|
|
21
|
+
/** Stable connection identifier (uuid). Set once at connect. */
|
|
22
|
+
readonly id: string;
|
|
23
|
+
/**
|
|
24
|
+
* Send data to THIS connection.
|
|
25
|
+
* - Text payloads: send a string (typically `JSON.stringify(...)`).
|
|
26
|
+
* - Binary payloads: send a `Uint8Array` or `ArrayBuffer`.
|
|
27
|
+
*
|
|
28
|
+
* Buffered if the underlying socket is busy; backpressure visible
|
|
29
|
+
* via the trigger's `messageRateLimit` and Studio trace metrics.
|
|
30
|
+
*/
|
|
31
|
+
send(data: string | ArrayBuffer | Uint8Array): void;
|
|
32
|
+
/**
|
|
33
|
+
* Close THIS connection cleanly. Subsequent `send` calls are no-ops.
|
|
34
|
+
* Triggers the `disconnect` workflow run as a final step.
|
|
35
|
+
*
|
|
36
|
+
* @param code Close code per RFC 6455 (default 1000 — normal).
|
|
37
|
+
* @param reason Human-readable reason (max 123 bytes per RFC).
|
|
38
|
+
*/
|
|
39
|
+
close(code?: number, reason?: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Store per-connection state. Survives across message-event workflow
|
|
42
|
+
* runs on the same connection — the "userId + joinedAt + cursor"
|
|
43
|
+
* pattern. Reset by every call (no merge).
|
|
44
|
+
*
|
|
45
|
+
* Inspired by Cloudflare Durable Objects'
|
|
46
|
+
* `state.serializeAttachment()` API. Capped at 2 KB serialized JSON;
|
|
47
|
+
* larger values are rejected with a warning log (the connection
|
|
48
|
+
* stays open).
|
|
49
|
+
*/
|
|
50
|
+
setAttachment(value: unknown): void;
|
|
51
|
+
/**
|
|
52
|
+
* Retrieve per-connection state set by `setAttachment()`. Returns
|
|
53
|
+
* `undefined` if nothing was set on this connection.
|
|
54
|
+
*/
|
|
55
|
+
readonly attachment: unknown;
|
|
56
|
+
/**
|
|
57
|
+
* Channel/room membership for fan-out broadcasts. Multiple
|
|
58
|
+
* connections can join the same room; `@blokjs/ws-broadcast`
|
|
59
|
+
* targets every member.
|
|
60
|
+
*/
|
|
61
|
+
joinRoom(name: string): void;
|
|
62
|
+
leaveRoom(name: string): void;
|
|
63
|
+
readonly rooms: ReadonlySet<string>;
|
|
64
|
+
/**
|
|
65
|
+
* v0.7 — broadcast a message to every connection in the named
|
|
66
|
+
* room (workflow-scoped). Returns the number of recipients
|
|
67
|
+
* the trigger successfully sent to.
|
|
68
|
+
*
|
|
69
|
+
* Set `exceptSelf: true` to skip the connection that triggered
|
|
70
|
+
* the current workflow run (the "send to everyone except me"
|
|
71
|
+
* pattern). Bound by the trigger via this `ctx.connection`
|
|
72
|
+
* accessor so helper nodes (`@blokjs/ws-broadcast`) don't need
|
|
73
|
+
* to import the trigger package directly.
|
|
74
|
+
*/
|
|
75
|
+
broadcast(room: string, data: string | ArrayBuffer | Uint8Array, opts?: {
|
|
76
|
+
exceptSelf?: boolean;
|
|
77
|
+
}): number;
|
|
78
|
+
}
|
|
79
|
+
export default ConnectionContext;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConnectionContext.js","sourceRoot":"","sources":["../../src/types/ConnectionContext.ts"],"names":[],"mappings":""}
|
package/dist/types/Context.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type GlobalLogger from "../GlobalLogger";
|
|
2
2
|
import type ConfigContext from "./ConfigContext";
|
|
3
|
+
import type ConnectionContext from "./ConnectionContext";
|
|
3
4
|
import type EnvContext from "./EnvContext";
|
|
4
5
|
import type ErrorContext from "./ErrorContext";
|
|
5
6
|
import type FunctionContext from "./FunctionContext";
|
|
@@ -7,6 +8,7 @@ import type LoggerContext from "./LoggerContext";
|
|
|
7
8
|
import type RequestContext from "./RequestContext";
|
|
8
9
|
import type ResponseContext from "./ResponseContext";
|
|
9
10
|
import type StateContext from "./StateContext";
|
|
11
|
+
import type StreamContext from "./StreamContext";
|
|
10
12
|
import type VarsContext from "./VarsContext";
|
|
11
13
|
/**
|
|
12
14
|
* The runtime context for a single workflow execution. One Context object
|
|
@@ -111,6 +113,38 @@ type Context = {
|
|
|
111
113
|
* tests.
|
|
112
114
|
*/
|
|
113
115
|
signal?: AbortSignal;
|
|
116
|
+
/**
|
|
117
|
+
* v0.7 — per-connection API for long-lived bidirectional triggers
|
|
118
|
+
* (WebSocket). Present on contexts dispatched by `WebSocketTrigger`;
|
|
119
|
+
* absent on HTTP / Worker / Cron contexts.
|
|
120
|
+
*
|
|
121
|
+
* Authors call `ctx.connection.send(...)` to push to the specific
|
|
122
|
+
* connection that fired the event, `ctx.connection.close(...)` to
|
|
123
|
+
* terminate it, or `ctx.connection.setAttachment(...)` to store
|
|
124
|
+
* per-connection state that survives across the connect → N×message
|
|
125
|
+
* → disconnect lifecycle.
|
|
126
|
+
*
|
|
127
|
+
* Helper nodes (`@blokjs/ws-reply`, `@blokjs/ws-broadcast`,
|
|
128
|
+
* `@blokjs/ws-close`) read this field to interact with the
|
|
129
|
+
* connection without authors having to thread the ws handle through
|
|
130
|
+
* step inputs.
|
|
131
|
+
*/
|
|
132
|
+
connection?: ConnectionContext;
|
|
133
|
+
/**
|
|
134
|
+
* v0.7 — per-stream API for server-push HTTP triggers (SSE).
|
|
135
|
+
* Present on contexts dispatched by `SSETrigger` once per stream
|
|
136
|
+
* open; absent on HTTP / WebSocket / Worker / Cron contexts.
|
|
137
|
+
*
|
|
138
|
+
* Authors call `ctx.stream.writeSSE({ event, data, id, retry })`
|
|
139
|
+
* to emit frames, `ctx.stream.close()` to end the stream, and
|
|
140
|
+
* read `ctx.stream.signal.aborted` to detect client disconnects
|
|
141
|
+
* inside long-running loops.
|
|
142
|
+
*
|
|
143
|
+
* Helper nodes (`@blokjs/sse-stream`) read this field so workflow
|
|
144
|
+
* authors don't have to thread the stream handle through step
|
|
145
|
+
* inputs.
|
|
146
|
+
*/
|
|
147
|
+
stream?: StreamContext;
|
|
114
148
|
_PRIVATE_: unknown;
|
|
115
149
|
};
|
|
116
150
|
export default Context;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v0.7 — per-stream API exposed on `ctx.stream` for triggers that hold
|
|
3
|
+
* a long-lived, server-push HTTP channel (SSE today; the `streaming`
|
|
4
|
+
* Hono helper underneath). Authors emit events through this object;
|
|
5
|
+
* the trigger owns the underlying `c.writeSSE` / drain handling.
|
|
6
|
+
*
|
|
7
|
+
* Lifecycle (Pattern A — one workflow run per stream open):
|
|
8
|
+
*
|
|
9
|
+
* - The SSE trigger opens the HTTP stream via Hono's `streamSSE`,
|
|
10
|
+
* creates this object, attaches it to `ctx.stream`, and dispatches
|
|
11
|
+
* the workflow once.
|
|
12
|
+
* - The workflow body writes zero or more events via
|
|
13
|
+
* `writeSSE(...)`, typically via `@blokjs/sse-stream` consuming an
|
|
14
|
+
* async iterator from `@blokjs/sse-subscribe`.
|
|
15
|
+
* - The workflow returns when its iterator ends OR when
|
|
16
|
+
* `ctx.stream.signal.aborted` flips (client closed). The trigger
|
|
17
|
+
* ends the run with status `completed`.
|
|
18
|
+
*
|
|
19
|
+
* Absent on contexts built for HTTP (request/response), Worker, Cron,
|
|
20
|
+
* or WebSocket triggers.
|
|
21
|
+
*/
|
|
22
|
+
export interface StreamContext {
|
|
23
|
+
/** Stable stream/connection identifier (uuid). Set once at open. */
|
|
24
|
+
readonly id: string;
|
|
25
|
+
/**
|
|
26
|
+
* Write one SSE-framed event to the client. Each call produces a
|
|
27
|
+
* `data:` (and optional `event:`, `id:`, `retry:`) frame followed
|
|
28
|
+
* by a blank line.
|
|
29
|
+
*
|
|
30
|
+
* `data` is JSON-stringified when it's not a string. Pass a string
|
|
31
|
+
* to write the payload verbatim. Returns once the chunk has been
|
|
32
|
+
* accepted by Node's stream (honors backpressure via `drain`).
|
|
33
|
+
*/
|
|
34
|
+
writeSSE(opts: {
|
|
35
|
+
event?: string;
|
|
36
|
+
data: unknown;
|
|
37
|
+
id?: string;
|
|
38
|
+
retry?: number;
|
|
39
|
+
}): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Write an SSE comment line (`: <text>\n\n`). Used internally for
|
|
42
|
+
* heartbeats; authors rarely need this directly. Comments are
|
|
43
|
+
* ignored by `EventSource` clients but keep proxies from idling
|
|
44
|
+
* the connection.
|
|
45
|
+
*/
|
|
46
|
+
writeComment(text: string): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Close the stream cleanly. Subsequent `writeSSE` calls are no-ops.
|
|
49
|
+
* The workflow run ends at the next yield point.
|
|
50
|
+
*/
|
|
51
|
+
close(): void;
|
|
52
|
+
/** True after `close()` is called or the client disconnects. */
|
|
53
|
+
readonly closed: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* `AbortSignal` that fires when the client disconnects (browser tab
|
|
56
|
+
* closed, network drop, manual `EventSource.close()`). Long-running
|
|
57
|
+
* iterators / fetches should be bound to this signal so they unwind
|
|
58
|
+
* promptly:
|
|
59
|
+
*
|
|
60
|
+
* for await (const evt of source) {
|
|
61
|
+
* if (ctx.stream.signal.aborted) break;
|
|
62
|
+
* await ctx.stream.writeSSE({ data: evt });
|
|
63
|
+
* }
|
|
64
|
+
*/
|
|
65
|
+
readonly signal: AbortSignal;
|
|
66
|
+
/**
|
|
67
|
+
* `Last-Event-Id` HTTP header value from the inbound request, if
|
|
68
|
+
* the client is reconnecting. Helper nodes (`@blokjs/sse-subscribe`)
|
|
69
|
+
* read this to resume from the indicated cursor.
|
|
70
|
+
*/
|
|
71
|
+
readonly lastEventId: string | null;
|
|
72
|
+
/**
|
|
73
|
+
* v0.7 — subscribe to the in-process SSE event bus. Returns an
|
|
74
|
+
* async iterator that yields events published to any of the named
|
|
75
|
+
* channels. When `lastEventId` is provided (or omitted — defaults
|
|
76
|
+
* to `ctx.stream.lastEventId`), buffered events with `seq > lastEventId`
|
|
77
|
+
* are replayed before live events begin. Caller stops the
|
|
78
|
+
* subscription by exiting the for-await loop or calling
|
|
79
|
+
* `iterator.return()`.
|
|
80
|
+
*
|
|
81
|
+
* Bound by the trigger so helper nodes (`@blokjs/sse-subscribe`,
|
|
82
|
+
* `@blokjs/sse-stream`) don't have to import the trigger directly.
|
|
83
|
+
*/
|
|
84
|
+
subscribe(channels: string[], lastEventId?: string | null): AsyncIterableIterator<{
|
|
85
|
+
channel: string;
|
|
86
|
+
id: string;
|
|
87
|
+
event?: string;
|
|
88
|
+
data: unknown;
|
|
89
|
+
timestamp: number;
|
|
90
|
+
}>;
|
|
91
|
+
}
|
|
92
|
+
export default StreamContext;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamContext.js","sourceRoot":"","sources":["../../src/types/StreamContext.ts"],"names":[],"mappings":""}
|