@toa.io/extensions.realtime 1.0.0-alpha.28 → 1.0.0-alpha.283

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.
Files changed (85) hide show
  1. package/CHANGELOG.md +337 -0
  2. package/components/realtime.streams/manifest.toa.yaml +47 -0
  3. package/components/{streams → realtime.streams}/operations/create.d.ts +7 -4
  4. package/components/realtime.streams/operations/create.js +65 -0
  5. package/components/realtime.streams/operations/create.js.map +1 -0
  6. package/components/realtime.streams/operations/lib/Stash.d.ts +21 -0
  7. package/components/realtime.streams/operations/lib/Stash.js +86 -0
  8. package/components/realtime.streams/operations/lib/Stash.js.map +1 -0
  9. package/components/realtime.streams/operations/lib/Stream.d.ts +13 -0
  10. package/components/realtime.streams/operations/lib/Stream.js +43 -0
  11. package/components/realtime.streams/operations/lib/Stream.js.map +1 -0
  12. package/components/realtime.streams/operations/lib/index.d.ts +2 -0
  13. package/components/realtime.streams/operations/lib/index.js +3 -0
  14. package/components/realtime.streams/operations/lib/index.js.map +1 -0
  15. package/components/{streams → realtime.streams}/operations/push.d.ts +1 -1
  16. package/components/realtime.streams/operations/push.js +10 -0
  17. package/components/realtime.streams/operations/push.js.map +1 -0
  18. package/components/realtime.streams/source/create.ts +97 -0
  19. package/components/realtime.streams/source/lib/Stash.ts +133 -0
  20. package/components/realtime.streams/source/lib/Stream.ts +56 -0
  21. package/components/realtime.streams/source/lib/index.ts +2 -0
  22. package/components/realtime.streams/source/push.ts +12 -0
  23. package/components/{streams → realtime.streams}/tsconfig.json +1 -0
  24. package/components/realtime.streams/tsconfig.tsbuildinfo +1 -0
  25. package/components/realtime.streams/types/index.d.ts +20 -0
  26. package/components/realtime.streams/types/toa.d.ts +29 -0
  27. package/{components/context.toa.yaml → context.toa.yaml} +0 -1
  28. package/cucumber.mjs +5 -0
  29. package/features/static.feature +120 -0
  30. package/features/steps/Components.ts +14 -14
  31. package/features/steps/Realtime.ts +14 -18
  32. package/features/steps/Streams.ts +51 -13
  33. package/features/steps/components/messages/manifest.toa.yaml +37 -6
  34. package/features/steps/config.ts +12 -0
  35. package/package.json +8 -7
  36. package/readme.md +33 -7
  37. package/source/Composition.ts +24 -13
  38. package/source/Factory.ts +11 -13
  39. package/source/Realtime.ts +41 -13
  40. package/source/Receiver.ts +86 -0
  41. package/source/Routes.ts +14 -37
  42. package/source/extension.ts +82 -0
  43. package/source/index.ts +2 -1
  44. package/transpiled/Composition.d.ts +10 -4
  45. package/transpiled/Composition.js +21 -20
  46. package/transpiled/Composition.js.map +1 -1
  47. package/transpiled/Factory.d.ts +4 -4
  48. package/transpiled/Factory.js +13 -18
  49. package/transpiled/Factory.js.map +1 -1
  50. package/transpiled/Realtime.d.ts +3 -2
  51. package/transpiled/Realtime.js +36 -11
  52. package/transpiled/Realtime.js.map +1 -1
  53. package/transpiled/Receiver.d.ts +25 -0
  54. package/transpiled/Receiver.js +55 -0
  55. package/transpiled/Receiver.js.map +1 -0
  56. package/transpiled/Routes.d.ts +5 -10
  57. package/transpiled/Routes.js +14 -31
  58. package/transpiled/Routes.js.map +1 -1
  59. package/transpiled/extension.d.ts +19 -0
  60. package/transpiled/extension.js +48 -0
  61. package/transpiled/extension.js.map +1 -0
  62. package/transpiled/index.d.ts +2 -1
  63. package/transpiled/index.js +2 -5
  64. package/transpiled/index.js.map +1 -1
  65. package/tsconfig.json +2 -1
  66. package/tsconfig.tsbuildinfo +1 -0
  67. package/components/streams/manifest.toa.yaml +0 -21
  68. package/components/streams/operations/create.js +0 -29
  69. package/components/streams/operations/create.js.map +0 -1
  70. package/components/streams/operations/lib/stream.d.ts +0 -10
  71. package/components/streams/operations/lib/stream.js +0 -31
  72. package/components/streams/operations/lib/stream.js.map +0 -1
  73. package/components/streams/operations/push.js +0 -8
  74. package/components/streams/operations/push.js.map +0 -1
  75. package/components/streams/operations/tsconfig.tsbuildinfo +0 -1
  76. package/components/streams/operations/types.d.ts +0 -11
  77. package/components/streams/operations/types.js +0 -3
  78. package/components/streams/operations/types.js.map +0 -1
  79. package/components/streams/source/create.ts +0 -38
  80. package/components/streams/source/lib/stream.ts +0 -37
  81. package/components/streams/source/push.ts +0 -5
  82. package/components/streams/source/types.ts +0 -13
  83. package/cucumber.js +0 -8
  84. package/stage/streams.test.ts +0 -128
  85. package/transpiled/tsconfig.tsbuildinfo +0 -1
package/CHANGELOG.md ADDED
@@ -0,0 +1,337 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # [1.0.0-alpha.283](https://github.com/toa-io/toa/compare/v1.0.0-alpha.282...v1.0.0-alpha.283) (2026-09-04)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **cli:** an assignment hands back the new state, not nothing ([91304e9](https://github.com/toa-io/toa/commit/91304e9e9a3bba5933b7421b7a0ffff0c2e47795))
11
+ * **exposition:** declare the errors the built-in components return ([27200c3](https://github.com/toa-io/toa/commit/27200c348ab09068d58c52c3e83208cb29cd7290))
12
+
13
+ ### Features
14
+
15
+ * **cli:** a type module is declarations, so it sits beside a component's source ([ca755d9](https://github.com/toa-io/toa/commit/ca755d93d1a04b7697dd0dd12eb59e5b6e2a71d1))
16
+ * **cli:** the built-in components ship types generated from their manifests ([bd7db9e](https://github.com/toa-io/toa/commit/bd7db9e88e46c1060223761898932239127f389a))
17
+ * **extensions:** an extension declares what it puts on a component's context ([133bc2a](https://github.com/toa-io/toa/commit/133bc2aad1e45a2d4aa68a08a5e44ca48d3b7414))
18
+
19
+
20
+ # [1.0.0-alpha.282](https://github.com/toa-io/toa/compare/v1.0.0-alpha.281...v1.0.0-alpha.282) (2026-09-03)
21
+
22
+ ### Bug Fixes
23
+
24
+ * **boot:** declare host, and build extensions with it in the step definitions ([915d957](https://github.com/toa-io/toa/commit/915d9571823358f8fca6fe19ef3aabd1b62e5605))
25
+
26
+ ### Features
27
+
28
+ * **core:** a Host for extensions ([6315eac](https://github.com/toa-io/toa/commit/6315eac1e9fb05be472272de06385c54ad5934ce))
29
+
30
+
31
+ # [1.0.0-alpha.278](https://github.com/toa-io/toa/compare/v1.0.0-alpha.277...v1.0.0-alpha.278) (2026-09-03)
32
+
33
+ **Note:** Version bump only for package @toa.io/extensions.realtime
34
+
35
+
36
+
37
+
38
+
39
+ # [1.0.0-alpha.277](https://github.com/toa-io/toa/compare/v1.0.0-alpha.276...v1.0.0-alpha.277) (2026-09-03)
40
+
41
+ ### Bug Fixes
42
+
43
+ * drop the build output that landed beside the sources ([a724f69](https://github.com/toa-io/toa/commit/a724f6921190e5c9d945e33c6035bb12d832e5c8))
44
+ * settle what the module loader made asynchronous ([d4ab9df](https://github.com/toa-io/toa/commit/d4ab9dfb09e382da311dba08f52214e7645f4a6c))
45
+ * what the loader resolves, and what it will not ([1b8a02f](https://github.com/toa-io/toa/commit/1b8a02ff0a5e0f18ee62e3f71bc81116f86f9af1))
46
+
47
+
48
+ # [1.0.0-alpha.274](https://github.com/toa-io/toa/compare/v1.0.0-alpha.273...v1.0.0-alpha.274) (2026-09-02)
49
+
50
+
51
+ * Configuration is served by a component, followed live, and kept per epoch (#1017) ([b05997d](https://github.com/toa-io/toa/commit/b05997d3adb784f238a222cb46878b23859339a2)), closes [#1017](https://github.com/toa-io/toa/issues/1017)
52
+
53
+
54
+ ### BREAKING CHANGES
55
+
56
+ * a secret configuration value is an object, not a string;
57
+ read it with `unwrap()`.
58
+
59
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
60
+
61
+ * test(configuration): wait for the second round rather than assume it
62
+
63
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
64
+
65
+ * refactor(configuration)!: read a secret with its own unwrap
66
+
67
+ Component code depends on no Toa package, so a secret is read as
68
+ `context.configuration.apiKey.unwrap()` and the helper in `@toa.io/generic`
69
+ goes. A value a component reads as a secret is therefore given as a reference:
70
+ `identity.basic` no longer defaults `pepper` to `''`, the development context
71
+ and the feature harness give the token keys, the federation client secret and
72
+ the signing key as references, and the harness has a step for the secrets a
73
+ scenario refers to. CONTRIBUTING states the rule.
74
+ * `identity.basic` `pepper` has no default; a value read as a
75
+ secret must be given as a `$NAME` reference.
76
+
77
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
78
+
79
+ * feat(configuration): list the configurations
80
+
81
+ `configuration.values.list` returns every component's configuration for its
82
+ deployed epoch, by component name, and `GET /configuration/values/` serves it
83
+ behind `system:configuration:get`.
84
+
85
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
86
+
87
+ * fix(exposition): write a value in YAML the way its toJSON says
88
+
89
+ A redacted secret in a reply was dumped as an empty object; it is written as
90
+ `<REDACTED>`, as JSON and msgpack already write it.
91
+
92
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
93
+
94
+ * test(configuration): a secret is an object, and stays redacted in a reply
95
+
96
+ A component with `{ a: 1, b: $SECRET_B }` returns its configuration as
97
+ `{ a: 1, b: '<REDACTED>' }` and the secret itself through `unwrap()`. The reply
98
+ step also accepts a reply as a caller across a process boundary receives it,
99
+ since a call within the process hands the object over as it is.
100
+
101
+ Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
102
+
103
+ * chore(schemas): bump the dependencies
104
+
105
+ ajv 8.18.0 to 8.20.0, ajv-formats 2.1.1 to 3.0.1, better-ajv-errors 1.2.0
106
+ to 2.0.3, fast-glob 3.2.12 to 3.3.3 and js-yaml 4.3.1 to 5.4.1 — the version
107
+ exposition already uses. The three majors keep the CommonJS entry points this
108
+ library calls: ajv-formats as a function, better-ajv-errors as .default, and
109
+ js-yaml's load.
110
+
111
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
112
+
113
+ * feat(configuration)!: serve the schema with the value
114
+
115
+ GET /configuration/values/:component/ answers { configuration, schema, epoch }
116
+ where it answered with the configuration alone, and list carries the schema of
117
+ every component. Nothing reads a configuration without needing to know what it
118
+ is checked against, and the schema was only ever on the values service.
119
+
120
+ An epoch the deployment does not know has no schema; the value stored for it
121
+ is still returned.
122
+
123
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
124
+
125
+ * feat(configuration): publish a configuration UI
126
+
127
+ The values service serves a page at /.configuration on port 8003, out of the
128
+ directory ui builds: the configured components, a screen per component showing
129
+ what it holds now, and a dialog creating the next one. Reading needs
130
+ system:configuration:get and creating needs system:configuration:create.
131
+
132
+ A configuration is immutable, so the dialog opens on the current value and what
133
+ is left out of it is left out of the component. The editor takes YAML, the
134
+ schema is applied before anything is sent, and a secret is a reference the page
135
+ never shows.
136
+
137
+ The page is always published: the annotation is the per-component values map
138
+ and has nowhere to carry a switch.
139
+
140
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
141
+
142
+ * feat(introspection): link a component to its configuration
143
+
144
+ A card carrying @toa.io/extensions.configuration reads that extension as a link
145
+ to the configuration UI rather than as a name, and configuration joins the
146
+ namespaces the runtime provides, so its components band under System.
147
+
148
+ Deployed, both pages sit behind the same ingress and the path alone is right;
149
+ locally each console has its own port.
150
+
151
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
152
+
153
+ * feat(introspection): scroll the map, zoom with a modifier
154
+
155
+ The map was grabbed to move and zoomed with a bare wheel, which is neither what
156
+ a page does nor what the wheel does anywhere else. A plain scroll now pans on
157
+ both axes and the wheel scales only with the modifier held — a trackpad pinch
158
+ arrives as one of those on every platform.
159
+
160
+ A card's own scrollable box keeps its wheel, in both paths.
161
+
162
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
163
+
164
+ * refactor(introspection): centre the filter in the header
165
+
166
+ The sides take equal space, which is what leaves the filter between them.
167
+ Neither side may shrink under what it holds, or the tabs run out from under
168
+ their side and across the filter, and the filter across the sign-out button;
169
+ the title gives way instead.
170
+
171
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
172
+
173
+ * fix(configuration): connect the UI to the values service
174
+
175
+ The page was declared as a dependency from inside `open`, and a connector connects
176
+ what it depends on before `open` runs — so the server was constructed and never
177
+ listened. Nothing caught it: the UI feature builds the server itself.
178
+
179
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
180
+
181
+ * feat(configuration)!: reserve resources in the annotation
182
+
183
+ The values service deploys like any other and must state what it may take, but the
184
+ annotation is a map of component ids and had nowhere to put it — so `toa env` failed
185
+ for every context using configuration unless it declared a context-wide `resources`.
186
+
187
+ `resources` is now the service's own, read the way `introspection` and `realtime` read
188
+ theirs. A component actually named `resources` is written `default.resources`, which is
189
+ what its id is anyway.
190
+
191
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
192
+
193
+ * feat(configuration): follow the system colour scheme
194
+
195
+ The dark tokens were behind a `.dark` class nothing sets, and the `dark:` variant was
196
+ pointed at that class too — so a component's own dark styling never applied either.
197
+ Both now key off `prefers-color-scheme`, and `color-scheme` hands the native chrome
198
+ the same answer.
199
+
200
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
201
+
202
+ * feat(introspection): follow the system colour scheme
203
+
204
+ The dark tokens were behind a `.dark` class nothing sets, and the `dark:` variant was
205
+ pointed at that class too — so a component's own dark styling never applied either.
206
+ Both now key off `prefers-color-scheme`, and `color-scheme` hands the native chrome
207
+ the same answer.
208
+
209
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
210
+
211
+ * feat(configuration): present a change as an edit of what is there
212
+
213
+ A configuration is immutable and creating one replaces the whole of it, but the dialog
214
+ opens on the current value and the page never shows an older one — so what the reader
215
+ does is edit. The words follow: Edit rather than New, Update rather than Create, and
216
+ the paragraph explaining the model goes, along with the field's label, which the title
217
+ above it already said.
218
+
219
+ The editor also stayed as wide as its longest line — `field-sizing: content` sizes to
220
+ content, and no `max-width` clamps that — so a long value painted outside the dialog.
221
+ It is fixed now, the dialog takes the width the screen has rather than a fixed step,
222
+ and the band held for errors no longer leaves a gap when there are none.
223
+
224
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
225
+
226
+ * feat(configuration): mark a component that keeps a secret
227
+
228
+ A key after the name on the row, wherever the configuration holds a reference, however
229
+ deep. The predicate reads the same lines the value screen renders, so the two cannot
230
+ disagree about what counts as a secret.
231
+
232
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
233
+
234
+ * feat(configuration): lead back to the list from the title
235
+
236
+ Every address ends in a slash, so the way up is the address itself on the list and one
237
+ level above it on a component's screen — which holds wherever the page is mounted.
238
+
239
+ Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
240
+
241
+
242
+
243
+
244
+
245
+ # [1.0.0-alpha.273](https://github.com/toa-io/toa/compare/v1.0.0-alpha.272...v1.0.0-alpha.273) (2026-09-02)
246
+
247
+
248
+ ### Bug Fixes
249
+
250
+ * **exposition:** green the feature suite ([67c25ad](https://github.com/toa-io/toa/commit/67c25ad627db3b3779b09405c5a3c319ecd47722))
251
+ * **realtime:** green the feature suite ([6b4650b](https://github.com/toa-io/toa/commit/6b4650bad9e1d53dabd0b7775966694bdb05f236))
252
+
253
+
254
+
255
+
256
+
257
+ # [1.0.0-alpha.272](https://github.com/toa-io/toa/compare/v1.0.0-alpha.271...v1.0.0-alpha.272) (2026-09-01)
258
+
259
+ **Note:** Version bump only for package @toa.io/extensions.realtime
260
+
261
+
262
+
263
+
264
+
265
+ # [1.0.0-alpha.270](https://github.com/toa-io/toa/compare/v1.0.0-alpha.269...v1.0.0-alpha.270) (2026-08-31)
266
+
267
+ **Note:** Version bump only for package @toa.io/extensions.realtime
268
+
269
+
270
+
271
+
272
+
273
+ # [1.0.0-alpha.266](https://github.com/toa-io/toa/compare/v1.0.0-alpha.265...v1.0.0-alpha.266) (2026-08-29)
274
+
275
+ **Note:** Version bump only for package @toa.io/extensions.realtime
276
+
277
+
278
+
279
+
280
+
281
+ # [1.0.0-alpha.265](https://github.com/toa-io/toa/compare/v1.0.0-alpha.264...v1.0.0-alpha.265) (2026-08-29)
282
+
283
+ **Note:** Version bump only for package @toa.io/extensions.realtime
284
+
285
+
286
+
287
+
288
+
289
+ # [1.0.0-alpha.264](https://github.com/toa-io/toa/compare/v1.0.0-alpha.263...v1.0.0-alpha.264) (2026-08-29)
290
+
291
+ **Note:** Version bump only for package @toa.io/extensions.realtime
292
+
293
+
294
+
295
+
296
+
297
+ # [1.0.0-alpha.263](https://github.com/toa-io/toa/compare/v1.0.0-alpha.262...v1.0.0-alpha.263) (2026-08-29)
298
+
299
+ **Note:** Version bump only for package @toa.io/extensions.realtime
300
+
301
+
302
+
303
+
304
+
305
+ # [1.0.0-alpha.262](https://github.com/toa-io/toa/compare/v1.0.0-alpha.261...v1.0.0-alpha.262) (2026-08-28)
306
+
307
+
308
+ ### Features
309
+
310
+ * **core:** identify the origin of a call with `request.source` ([9da6b66](https://github.com/toa-io/toa/commit/9da6b66df852690351a1e82c7b8cc176fd89774a))
311
+
312
+
313
+
314
+
315
+
316
+ # [1.0.0-alpha.259](https://github.com/toa-io/toa/compare/v1.0.0-alpha.258...v1.0.0-alpha.259) (2026-08-24)
317
+
318
+ **Note:** Version bump only for package @toa.io/extensions.realtime
319
+
320
+
321
+
322
+
323
+
324
+ # [1.0.0-alpha.257](https://github.com/toa-io/toa/compare/v1.0.0-alpha.256...v1.0.0-alpha.257) (2026-08-24)
325
+
326
+ **Note:** Version bump only for package @toa.io/extensions.realtime
327
+
328
+
329
+
330
+
331
+
332
+ # [1.0.0-alpha.256](https://github.com/toa-io/toa/compare/v1.0.0-alpha.255...v1.0.0-alpha.256) (2026-08-23)
333
+
334
+
335
+ ### Features
336
+
337
+ * add toa mono and discover components at components/* ([787a111](https://github.com/toa-io/toa/commit/787a111c8f83e56ebc734801c97106c585d034ea))
@@ -0,0 +1,47 @@
1
+ namespace: realtime
2
+ name: streams
3
+
4
+ operations:
5
+ create:
6
+ input:
7
+ properties:
8
+ key:
9
+ type: string
10
+ token:
11
+ type: string
12
+ type: object
13
+ push:
14
+ output: { type: 'null' }
15
+ bindings: ~ # only for internal use
16
+ input:
17
+ properties:
18
+ data: {}
19
+ key:
20
+ type: string
21
+ event:
22
+ type: string
23
+ type: object
24
+ required:
25
+ - key
26
+ - event
27
+
28
+ configuration:
29
+ schema:
30
+ properties:
31
+ maxlen:
32
+ type: number
33
+ default: 1000
34
+ expire:
35
+ type: number
36
+ default: 300
37
+ type: object
38
+ # both have defaults, so the component reads them without checking
39
+ required: [maxlen, expire]
40
+
41
+ state: ~
42
+ stash: ~
43
+
44
+ exposition:
45
+ /:key:
46
+ auth:id: key
47
+ GET: create
@@ -1,14 +1,17 @@
1
- /// <reference types="node" />
2
1
  import { type Readable } from 'node:stream';
3
- import { type Operation } from '@toa.io/types';
4
- import { type Context } from './types';
2
+ import { type Operation } from '@toa.io/bridges.node';
3
+ import { type Context } from '../types/index.js';
5
4
  export declare class Effect implements Operation {
6
5
  private readonly streams;
6
+ private stash;
7
+ private logs;
7
8
  mount(context: Context): void;
8
- execute(input: Input, context: Context): Promise<Readable>;
9
+ unmount(): void;
10
+ execute(input: Input): Promise<Readable>;
9
11
  private createStream;
10
12
  }
11
13
  interface Input {
12
14
  key: string;
15
+ token?: string;
13
16
  }
14
17
  export {};
@@ -0,0 +1,65 @@
1
+ import { Stream, Stash } from './lib/index.js';
2
+ export class Effect {
3
+ streams = new Map();
4
+ stash;
5
+ logs;
6
+ mount(context) {
7
+ context.state.streams = this.streams;
8
+ context.state.stash = new Stash(context.stash, context.configuration, context.logs);
9
+ this.logs = context.logs;
10
+ this.stash = context.state.stash;
11
+ }
12
+ unmount() {
13
+ this.logs.info('Destroying streams', { count: this.streams.size });
14
+ // closed, not destroyed: destroying a stream that is still piped to a response
15
+ // makes end-of-stream report a premature close, which reaches no one and takes
16
+ // the process down.
17
+ for (const stream of this.streams.values())
18
+ stream.close();
19
+ }
20
+ async execute(input) {
21
+ const key = input.key;
22
+ if (!this.streams.has(key)) {
23
+ const stream = this.createStream(key);
24
+ this.streams.set(key, stream);
25
+ this.logs.debug('Stream created', { key });
26
+ }
27
+ // welcome
28
+ setTimeout(() => this.streams.get(key)?.heartbeat(), 1000);
29
+ if (input.token === undefined)
30
+ void this.stash.connect(key).then((token) => {
31
+ if (token instanceof Error)
32
+ this.logs.error('Failed to connect to stash', { key, error: token });
33
+ else
34
+ this.streams.get(key)?.push({ event: 'token', data: token });
35
+ });
36
+ else
37
+ void this.stash.pop(key, input.token).then((result) => {
38
+ if (result === null)
39
+ return;
40
+ if ('code' in result && result.code === 'NO_RESULTS')
41
+ return;
42
+ if (result instanceof Error) {
43
+ this.logs.error('Failed to pop from stash', { key, error: result });
44
+ return;
45
+ }
46
+ const stream = this.streams.get(key);
47
+ if (stream === undefined)
48
+ return;
49
+ const [token, events] = result;
50
+ for (const event of events)
51
+ stream.push({ event: event.event, data: event.data });
52
+ stream.push({ event: 'token', data: token });
53
+ });
54
+ return this.streams.get(key);
55
+ }
56
+ createStream(key) {
57
+ const stream = new Stream();
58
+ stream.events.once('destroy', () => {
59
+ this.logs.debug('Stream destroyed', { key });
60
+ this.streams.delete(key);
61
+ });
62
+ return stream;
63
+ }
64
+ }
65
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../source/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export declare class Stash {
2
+ private readonly stash;
3
+ private readonly configuration;
4
+ private readonly logs;
5
+ constructor(stash: any, configuration: Configuration, logs: any);
6
+ connect(key: string): Promise<string | Error>;
7
+ push(key: string, event: string, data: unknown): Promise<string | Error>;
8
+ pop(key: string, token: string): Promise<[string, Event[]] | null | Error>;
9
+ private xadd;
10
+ private encode;
11
+ private decode;
12
+ }
13
+ interface Configuration {
14
+ maxlen: number;
15
+ expire: number;
16
+ }
17
+ interface Event {
18
+ event: string;
19
+ data: unknown;
20
+ }
21
+ export {};
@@ -0,0 +1,86 @@
1
+ export class Stash {
2
+ stash;
3
+ configuration;
4
+ logs;
5
+ constructor(stash, configuration, logs) {
6
+ this.stash = stash;
7
+ this.configuration = configuration;
8
+ this.logs = logs;
9
+ }
10
+ async connect(key) {
11
+ return await this.xadd(key, 'connect');
12
+ }
13
+ async push(key, event, data) {
14
+ return await this.xadd(key, event, data);
15
+ }
16
+ async pop(key, token) {
17
+ const stamp = this.decode(token);
18
+ const results = await this.stash
19
+ .xread('STREAMS', key, stamp)
20
+ .catch((error) => error);
21
+ if (results === null)
22
+ return ERR_NO_RESULTS;
23
+ if (results instanceof Error)
24
+ return results;
25
+ const items = entries(results);
26
+ if (items === null)
27
+ return null;
28
+ const events = [];
29
+ let lastStamp = null;
30
+ for (const item of items) {
31
+ const [, event, , json] = item[1];
32
+ lastStamp = item[0];
33
+ const data = json === undefined ? undefined : JSON.parse(json);
34
+ if (data === undefined)
35
+ this.logs.debug('Undefined event payload', { key, event });
36
+ events.push({ event, data });
37
+ }
38
+ if (lastStamp === null)
39
+ return null;
40
+ return [this.encode(lastStamp), events];
41
+ }
42
+ async xadd(key, event, data) {
43
+ const args = ['MAXLEN', '~', this.configuration.maxlen, '*', 'type', event];
44
+ if (data !== undefined)
45
+ args.push('data', JSON.stringify(data));
46
+ const results = await this.stash
47
+ .multi()
48
+ .xadd(key, ...args)
49
+ .expire(key, this.configuration.expire)
50
+ .exec()
51
+ .catch((error) => error);
52
+ if (results === null)
53
+ return ERR_NO_RESULTS;
54
+ if (results instanceof Error)
55
+ return results;
56
+ const [[error, stamp]] = results;
57
+ if (error !== null)
58
+ return error;
59
+ return this.encode(stamp);
60
+ }
61
+ encode(token) {
62
+ return Buffer.from(token).toString('base64url');
63
+ }
64
+ decode(token) {
65
+ return Buffer.from(token, 'base64url').toString();
66
+ }
67
+ }
68
+ /**
69
+ * `xread` answers with an array of `[stream, entries]` pairs over RESP2 and with an
70
+ * object keyed by stream name over RESP3. One stream is read, so either way it is the
71
+ * first, and an empty answer means nothing has been added since the token.
72
+ */
73
+ function entries(results) {
74
+ if (Array.isArray(results))
75
+ return results.length === 0 ? null : results[0][1];
76
+ if (typeof results === 'object' && results !== null) {
77
+ const streams = Object.values(results);
78
+ return streams.length === 0 ? null : streams[0];
79
+ }
80
+ return null;
81
+ }
82
+ class NoResultsError extends Error {
83
+ code = 'NO_RESULTS';
84
+ }
85
+ const ERR_NO_RESULTS = new NoResultsError();
86
+ //# sourceMappingURL=Stash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Stash.js","sourceRoot":"","sources":["../../source/lib/Stash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { Readable } from 'node:stream';
3
+ export declare class Stream extends Readable {
4
+ events: EventEmitter<any>;
5
+ private interval;
6
+ private ended;
7
+ constructor();
8
+ _read(): void;
9
+ _destroy(error: Error | null, callback: (error?: (Error | null)) => void): void;
10
+ /** Ends the stream: whoever reads it gets EOF rather than a broken pipe. */
11
+ close(): void;
12
+ heartbeat(stream?: Readable): boolean;
13
+ }
@@ -0,0 +1,43 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { Readable } from 'node:stream';
3
+ export class Stream extends Readable {
4
+ events = new EventEmitter();
5
+ interval = null;
6
+ ended = false;
7
+ constructor() {
8
+ super(objectMode);
9
+ }
10
+ // has to be here
11
+ _read() {
12
+ if (this.interval === null)
13
+ this.interval = setInterval(() => this.heartbeat(), HEARTBEAT_INTERVAL);
14
+ }
15
+ _destroy(error, callback) {
16
+ if (this.interval !== null)
17
+ clearInterval(this.interval);
18
+ this.events.emit('destroy');
19
+ super._destroy(error, callback);
20
+ }
21
+ /** Ends the stream: whoever reads it gets EOF rather than a broken pipe. */
22
+ close() {
23
+ this.ended = true;
24
+ if (this.interval !== null) {
25
+ clearInterval(this.interval);
26
+ this.interval = null;
27
+ }
28
+ this.push(null);
29
+ }
30
+ heartbeat(stream = this) {
31
+ if (this.ended)
32
+ return false;
33
+ const resume = stream.push('heartbeat ' + Date.now());
34
+ if (!resume && this.interval !== null) {
35
+ clearInterval(this.interval);
36
+ this.interval = null;
37
+ }
38
+ return resume;
39
+ }
40
+ }
41
+ const HEARTBEAT_INTERVAL = 16_000; // why?
42
+ const objectMode = { objectMode: true };
43
+ //# sourceMappingURL=Stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Stream.js","sourceRoot":"","sources":["../../source/lib/Stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,MAAM,OAAO,MAAO,SAAQ,QAAQ;IAC3B,MAAM,GAAG,IAAI,YAAY,EAAE,CAAA;IAE1B,QAAQ,GAA0B,IAAI,CAAA;IACtC,KAAK,GAAG,KAAK,CAAA;IAErB;QACE,KAAK,CAAC,UAAU,CAAC,CAAA;IACnB,CAAC;IAED,iBAAiB;IACD,KAAK;QACnB,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;YACxB,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,kBAAkB,CAAC,CAAA;IAC3E,CAAC;IAEe,QAAQ,CAAE,KAAmB,EAAE,QAA0C;QACvF,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;YACxB,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAE9B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAE3B,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IACjC,CAAC;IAED,4EAA4E;IACrE,KAAK;QACV,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;QAEjB,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;QACtB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACjB,CAAC;IAEM,SAAS,CAAE,MAAM,GAAa,IAAI;QACvC,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAA;QAE5B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;QAErD,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;QACtB,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAED,MAAM,kBAAkB,GAAG,MAAM,CAAA,CAAC,OAAO;AACzC,MAAM,UAAU,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { Stash } from './Stash.js';
2
+ export { Stream } from './Stream.js';
@@ -0,0 +1,3 @@
1
+ export { Stash } from './Stash.js';
2
+ export { Stream } from './Stream.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA"}
@@ -1,2 +1,2 @@
1
- import { type Context, type PushInput } from './types';
1
+ import { type Context, type PushInput } from '../types/index.js';
2
2
  export declare function effect({ key, event, data }: PushInput, context: Context): Promise<void>;