@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.
@@ -14,7 +14,10 @@ class TestNode extends NodeBase {
14
14
  }
15
15
  }
16
16
 
17
- function createTestContext(overrides: Partial<Context> = {}): Context {
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
- // set_var defaults to undefined (NOT false). false short-circuits
50
- // PersistenceHelper.applyStepOutput and silently disables v2's
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, unknown>, ctx);
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
 
@@ -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.
@@ -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;;;;;;;;;OASG;IACI,OAAO,CAAW;IAEzB,4EAA4E;IAC5E,sEAAsE;IACtE,8DAA8D;IAC9D,4EAA4E;IAE5E;;;OAGG;IACI,EAAE,CAAU;IAEnB;;;;OAIG;IACI,MAAM,GAAG,KAAK,CAAC;IAEtB;;;OAGG;IACI,SAAS,GAAG,KAAK,CAAC;IAEzB,4EAA4E;IAC5E,2EAA2E;IAC3E,qEAAqE;IACrE,4EAA4E;IAC5E,kCAAkC;IAClC,EAAE;IACF,yEAAyE;IACzE,uEAAuE;IACvE,UAAU;IACV,4EAA4E;IAE5E;;;;;;;;;OASG;IACI,cAAc,CAAU;IAE/B;;;;OAIG;IACI,iBAAiB,CAAU;IAElC;;;;OAIG;IACI,KAAK,CAKV;IAEF;;;;;;;;;;;;OAYG;IACI,aAAa,CAAU;IAE9B,4EAA4E;IAC5E,wEAAwE;IACxE,wEAAwE;IACxE,+DAA+D;IAC/D,gEAAgE;IAChE,4EAA4E;IAE5E;;;;;OAKG;IACI,WAAW,CAAU;IAE5B;;;;;;;OAOG;IACI,IAAI,CAAW;IAEf,KAAK,CAAC,OAAO,CAAC,GAAY,EAAE,IAAW;QAC7C,IAAI,QAAQ,GAAoB;YAC/B,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,IAAI;SACX,CAAC;QAEF,MAAM,MAAM,GAAsB,GAAG,CAAC,MAAsC,CAAC;QAC7E,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QAE7C,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAE/B,IAAI,QAAQ,CAAC,KAAK;YAAE,MAAM,QAAQ,CAAC,KAAK,CAAC;QACzC,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAExB,OAAO,QAAQ,CAAC;IACjB,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,GAAY;QACpC,IAAI,QAAQ,GAAoB;YAC/B,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,IAAI;SACX,CAAC;QAEF,IAAI,CAAC;YACJ,MAAM,MAAM,GAAsB,GAAG,CAAC,MAAsC,CAAC;YAC7E,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;YAE7C,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACzB,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAqB,CAAC,CAAC;YACtD,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;YACzB,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,CAAC;QAED,OAAO,QAAQ,CAAC;IACjB,CAAC;IAIM,QAAQ,CAAC,IAAmB,EAAE,GAAY;QAChD,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACxD,CAAC;IAEM,KAAK,CACX,GAAW,EACX,GAAY,EACZ,OAAyB,EAAE,EAC3B,OAAwB,EAAE,EAC1B,OAAoB,EAAE;QAEtB,OAAO,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB,GAAG,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACxG,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,GAAY,EAAE,IAAiB;QAC5C,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS;YAAE,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;QAC1C,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;IACrC,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,GAAY,EAAE,IAAY;QACvC,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAEM,eAAe,GAAG,CAAC,GAAqB,EAAE,GAAY,EAAE,IAAuB,EAAE,EAAE;QACzF,IAAI,MAAM,GAA8B,GAAG,CAAC;QAE5C,IAAI,CAAC;YACJ,IAAI,OAAO,GAAG,KAAK,QAAQ;gBAC1B,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,IAAwB,CAAsB,CAAC;;gBACnF,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,EAAE,IAAwB,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACZ,gEAAgE;YAChE,gEAAgE;YAChE,gDAAgD;YAChD,IAAI,CAAC,YAAY,qBAAqB;gBAAE,MAAM,CAAC,CAAC;YAChD,+DAA+D;YAC/D,2DAA2D;YAC3D,wDAAwD;YACxD,OAAO,CAAC,KAAK,CAAC,0DAA0D,EAAE,CAAC,CAAC,CAAC;QAC9E,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC,CAAC;IAEK,QAAQ,CAAC,MAAoB;QACnC,IAAI,YAAyB,CAAC;QAE9B,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAChC,YAAY,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC;aAAM,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/D,YAAY,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,OAAiB,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACP,MAAM,GAAG,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC;YACjF,YAAY,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;YACpC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAChC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;QACF,CAAC;QAED,IAAI,MAAM,CAAC,IAAI;YAAE,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,MAAM,CAAC,KAAK;YAAE,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,MAAM,CAAC,IAAI;YAAE,YAAY,CAAC,OAAO,CAAC,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAE3F,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEhC,OAAO,YAAY,CAAC;IACrB,CAAC;CACD"}
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;AAYhC,OAAO,WAAW,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EACN,QAAQ,EAOR,OAAO,EAMP,YAAY,EACZ,WAAW,EACX,SAAS,EAGT,aAAa,EACb,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,OAAO,EACP,WAAW,GAEX,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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ConnectionContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConnectionContext.js","sourceRoot":"","sources":["../../src/types/ConnectionContext.ts"],"names":[],"mappings":""}
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=StreamContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamContext.js","sourceRoot":"","sources":["../../src/types/StreamContext.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blokjs/shared",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Shared class, interfaces and types",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",