node-turbo 1.0.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.
Files changed (44) hide show
  1. package/.c8rc.json +5 -0
  2. package/.esdoc.json +83 -0
  3. package/.eslintrc.json +10 -0
  4. package/.mocharc.json +7 -0
  5. package/LICENSE +21 -0
  6. package/README.md +620 -0
  7. package/docs/API.md +857 -0
  8. package/lib/errors/index.js +36 -0
  9. package/lib/express/express-turbo-stream.js +41 -0
  10. package/lib/express/index.js +4 -0
  11. package/lib/express/turbocharge-express.js +108 -0
  12. package/lib/index.js +8 -0
  13. package/lib/koa/index.js +4 -0
  14. package/lib/koa/koa-turbo-stream.js +44 -0
  15. package/lib/koa/turbocharge-koa.js +122 -0
  16. package/lib/request-helpers.js +53 -0
  17. package/lib/sse/index.js +3 -0
  18. package/lib/sse/sse-turbo-stream.js +137 -0
  19. package/lib/turbo-element.js +71 -0
  20. package/lib/turbo-frame.js +79 -0
  21. package/lib/turbo-readable.js +125 -0
  22. package/lib/turbo-stream-element.js +67 -0
  23. package/lib/turbo-stream.js +350 -0
  24. package/lib/ws/index.js +4 -0
  25. package/lib/ws/ws-turbo-stream.js +112 -0
  26. package/package.json +75 -0
  27. package/test/hooks.js +46 -0
  28. package/test/integration/express.test.js +137 -0
  29. package/test/integration/koa.test.js +125 -0
  30. package/test/integration/sse.test.js +80 -0
  31. package/test/integration/ws.test.js +155 -0
  32. package/test/package.test.js +68 -0
  33. package/test/unit/core/request-helpers.test.js +97 -0
  34. package/test/unit/core/turbo-element.test.js +15 -0
  35. package/test/unit/core/turbo-frame.test.js +63 -0
  36. package/test/unit/core/turbo-readable.test.js +93 -0
  37. package/test/unit/core/turbo-stream-element.test.js +76 -0
  38. package/test/unit/core/turbo-stream.test.js +308 -0
  39. package/test/unit/express/express-turbo-stream.test.js +39 -0
  40. package/test/unit/express/turbocharge-express.test.js +123 -0
  41. package/test/unit/koa/koa-turbo-stream.test.js +56 -0
  42. package/test/unit/koa/turbocharge-koa.test.js +141 -0
  43. package/test/unit/sse/sse-turbo-stream.test.js +109 -0
  44. package/test/unit/ws/ws-turbo-stream.test.js +46 -0
package/docs/API.md ADDED
@@ -0,0 +1,857 @@
1
+ # node-turbo API documentation
2
+
3
+ Version 1.0.0
4
+
5
+ ## Table of Contents
6
+
7
+ - [node-turbo](#node-turbo)
8
+ - [Class: TurboFrame](#class-turboframe)
9
+ - [TurboFrame.HEADER_KEY](#turboframeheader_key)
10
+ - [TurboFrame.MIME_TYPE](#turboframemime_type)
11
+ - [new TurboFrame(idOrAttributes, content)](#new-turboframeidorattributes-content)
12
+ - [turboframe.validate()](#turboframevalidate)
13
+ - [turboframe.render()](#turboframerender)
14
+ - [Class: TurboStream](#class-turbostream)
15
+ - [TurboStream.MIME_TYPE](#turbostreammime_type)
16
+ - [TurboStream.ACTIONS](#turbostreamactions)
17
+ - [new TurboStream([attributes][, content])](#new-turbostreamattributes-content)
18
+ - [turbostream.config](#turbostreamconfig)
19
+ - [turbostream.elements](#turbostreamelements)
20
+ - [turbostream.length](#turbostreamlength)
21
+ - [turbostream.updateConfig(config)](#turbostreamupdateconfigconfig)
22
+ - [turbostream.addElement(attributesOrElement, content)](#turbostreamaddelementattributesorelement-content)
23
+ - [turbostream.clear()](#turbostreamclear)
24
+ - [turbostream.render()](#turbostreamrender)
25
+ - [turbostream.renderElements()](#turbostreamrenderelements)
26
+ - [turbostream.flush()](#turbostreamflush)
27
+ - [turbostream.custom(action, target, content)](#turbostreamcustomaction-target-content)
28
+ - [turbostream.customAll(action, targets, content)](#turbostreamcustomallaction-targets-content)
29
+ - [turbostream.createReadableStream(opts[, streamOptions])](#turbostreamcreatereadablestreamopts-streamoptions)
30
+ - [Class: TurboStreamElement](#class-turbostreamelement)
31
+ - [turbostreamelement.validate()](#turbostreamelementvalidate)
32
+ - [turbostreamelement.render()](#turbostreamelementrender)
33
+ - [Class: TurboElement](#class-turboelement)
34
+ - [new TurboElement(attributes, content)](#new-turboelementattributes-content)
35
+ - [turboelement.attributes](#turboelementattributes)
36
+ - [turboelement.content](#turboelementcontent)
37
+ - [turboelement.renderAttributesAsHtml()](#turboelementrenderattributesashtml)
38
+ - [turboelement.validate()](#turboelementvalidate)
39
+ - [turboelement.render()](#turboelementrender)
40
+ - [Class: TurboReadable](#class-turboreadable)
41
+ - [new TurboReadable(turboStream[, opts])](#new-turboreadableturbostream-opts)
42
+ - [turboreadable._turboStream](#turboreadable_turbostream)
43
+ - [turboreadable._boundPush](#turboreadable_boundpush)
44
+ - [turboreadable._pushElement(el)](#turboreadable_pushelementel)
45
+ - [turboreadable._read()](#turboreadable_read)
46
+ - [turboreadable._destroy(err)](#turboreadable_destroyerr)
47
+ - [turboreadable.done()](#turboreadabledone)
48
+ - [isTurboStreamRequest(request)](#isturbostreamrequestrequest)
49
+ - [isTurboFrameRequest(request)](#isturboframerequestrequest)
50
+ - [getTurboFrameId(request)](#getturboframeidrequest)
51
+ - [node-turbo/ws](#node-turbows)
52
+ - [Class: WsTurboStream](#class-wsturbostream)
53
+ - [WsTurboStream.use(ws)](#wsturbostreamusews)
54
+ - [WsTurboStream.OPEN](#wsturbostreamopen)
55
+ - [new WsTurboStream(ws[, config])](#new-wsturbostreamws-config)
56
+ - [wsturbostream.ws](#wsturbostreamws)
57
+ - [wsturbostream.handleConfig(config)](#wsturbostreamhandleconfigconfig)
58
+ - [wsturbostream.handleRender(html)](#wsturbostreamhandlerenderhtml)
59
+ - [wsturbostream.handleElement(element)](#wsturbostreamhandleelementelement)
60
+ - [node-turbo/koa](#node-turbokoa)
61
+ - [Class: KoaTurboStream](#class-koaturbostream)
62
+ - [new KoaTurboStream(koaCtx)](#new-koaturbostreamkoactx)
63
+ - [koaturbostream.koaCtx](#koaturbostreamkoactx)
64
+ - [koaturbostream.status](#koaturbostreamstatus)
65
+ - [turbochargeKoa(koaApp, opts, opts.autoRender)](#turbochargekoakoaapp-opts-optsautorender)
66
+ - [node-turbo/express](#node-turboexpress)
67
+ - [Class: ExpressTurboStream](#class-expressturbostream)
68
+ - [new ExpressTurboStream(res[, attributes][, content])](#new-expressturbostreamres-attributes-content)
69
+ - [expressturbostream.res](#expressturbostreamres)
70
+ - [expressturbostream.send()](#expressturbostreamsend)
71
+ - [turbochargeExpress(expressApp, opts)](#turbochargeexpressexpressapp-opts)
72
+ - [node-turbo/sse](#node-turbosse)
73
+ - [Class: SseTurboStream](#class-sseturbostream)
74
+ - [SseTurboStream.MIME_TYPE](#sseturbostreammime_type)
75
+ - [new SseTurboStream([eventname])](#new-sseturbostreameventname)
76
+ - [sseturbostream.eventName](#sseturbostreameventname)
77
+ - [sseturbostream.render()](#sseturbostreamrender)
78
+ - [sseturbostream.renderSseEvent(raw)](#sseturbostreamrendersseeventraw)
79
+ - [sseturbostream.createReadableStream()](#sseturbostreamcreatereadablestream)
80
+ - [sseturbostream.event(eventName)](#sseturbostreameventeventname)
81
+ - [node-turbo/errors](#node-turboerrors)
82
+ - [Class: ValidationError](#class-validationerror)
83
+ - [Class: AttributeMalformedError](#class-attributemalformederror)
84
+ - [Class: AttributeMissingError](#class-attributemissingerror)
85
+ - [Class: AttributeInvalidError](#class-attributeinvaliderror)
86
+
87
+ ## node-turbo
88
+
89
+ ### Class: TurboFrame
90
+
91
+ ```javascript
92
+ import { TurboFrame } from 'node-turbo';
93
+ ```
94
+
95
+ ***Extends:***
96
+ - [TurboElement](#class-turboelement)
97
+
98
+ This class represents a Turbo Frame message.
99
+
100
+ #### TurboFrame.HEADER_KEY
101
+
102
+ `static` {String}
103
+
104
+ The key which is added to the HTTP headers when the request is made by a Turbo Frame.
105
+
106
+ #### TurboFrame.MIME_TYPE
107
+
108
+ `static` {String}
109
+
110
+ MIME type of a Turbo Frame HTTP response, which is just `text/html`.
111
+
112
+ #### new TurboFrame(idOrAttributes, content)
113
+
114
+ - `idOrAttributes` {String | Object} Either the ID as string or an object
115
+ containing all attributes (including `id`).
116
+ - `content` {String} The HTML content of this Turbo Frame message.
117
+
118
+ #### turboframe.validate()
119
+
120
+ Validates the attributes. `attributes.id` is mandatory. Gets called automatically by the constructor.
121
+
122
+ Throws {AttributeMissingError} when mandatory attributes are missing.
123
+ Throws {AttributeMalformedError} when mandatory attributes are malformed.
124
+
125
+ #### turboframe.render()
126
+
127
+ Renders the Turbo Frame message as HTML string and returns it.
128
+
129
+ Returns: {String} The rendered HTML.
130
+
131
+ #### Inherited from class [TurboElement](#class-turboelement):
132
+
133
+ > - attributes
134
+ The attribute object.
135
+ > - content
136
+ The HTML content.
137
+ > - renderAttributesAsHtml()
138
+ Converts the attributes object to a string in the form
139
+ of HTML attributes ({ name: value } -> 'name="value"').
140
+
141
+ ### Class: TurboStream
142
+
143
+ ```javascript
144
+ import { TurboStream } from 'node-turbo';
145
+ ```
146
+
147
+ ***Extends:***
148
+ - events~EventEmitter
149
+
150
+ A Turbo Stream message.
151
+
152
+ #### TurboStream.MIME_TYPE
153
+
154
+ `static` {String}
155
+
156
+ MIME type for Turbo Stream messages.
157
+
158
+ See [https://turbo.hotwired.dev/handbook/streams#streaming-from-http-responses](https://turbo.hotwired.dev/handbook/streams#streaming-from-http-responses)
159
+
160
+ #### TurboStream.ACTIONS
161
+
162
+ `static` {Array}
163
+
164
+ List of all supported actions: 'append', 'prepend', 'replace', 'update', 'remove', 'before' and 'after'.
165
+
166
+ See [https://turbo.hotwired.dev/handbook/streams#stream-messages-and-actions](https://turbo.hotwired.dev/handbook/streams#stream-messages-and-actions)
167
+
168
+ #### new TurboStream([attributes][, content])
169
+
170
+ - `attributes` {Object<String, String>} The attributes of this element.
171
+ - `content` {String} The HTML content of this element.
172
+
173
+ If `attributes` and `content` are available, a Turbo Stream element is added to the buffer, pending validation.
174
+
175
+ #### turbostream.config
176
+
177
+ {Object<String, String>}
178
+
179
+ - `buffer` {Boolean} Should elements be added to the buffer (default: true)?
180
+
181
+ Default configuration.
182
+
183
+ #### turbostream.elements
184
+
185
+ {Array}
186
+
187
+ Array of buffered elements. Gets filled if `config.buffer` is `true`.
188
+
189
+ #### turbostream.length
190
+
191
+ `get` {Number}
192
+
193
+ The number of buffered Turbo Stream elements.
194
+
195
+ #### turbostream.updateConfig(config)
196
+
197
+ - `config` {Object} New configuration.
198
+
199
+ Extends/Overwrites the configuration.
200
+
201
+ Returns: {TurboStream} The instance for chaining.
202
+
203
+ #### turbostream.addElement(attributesOrElement, content)
204
+
205
+ - `attributesOrElement` {Object<String, String> | TurboFrameElement}
206
+ - `content` {String} The HTML content of the element.
207
+
208
+ Adds a Turbo Stream element to the message. Adds the element to the buffer, if config.buffer === true. Fires the event 'element' with the added element.
209
+
210
+ Returns: {TurboStream} The instance for chaining.
211
+
212
+ #### turbostream.clear()
213
+
214
+ Clears the buffer.
215
+
216
+ Returns: {TurboStream} The instance for chaining.
217
+
218
+ #### turbostream.render()
219
+
220
+ Renders this Turbo Stream message if there are buffered elements.
221
+
222
+ Returns: {String | null} The rendered Turbo Stream HTML fragment or null if there were no buffered elements.
223
+
224
+ #### turbostream.renderElements()
225
+
226
+ If there are buffered elements, renders them and returns an array with the HTML fragments.
227
+
228
+ Returns: {Array | null} The rendered Turbo Stream HTML fragments as array or null if there were no buffered elements.
229
+
230
+ #### turbostream.flush()
231
+
232
+ Renders this Turbo Stream message and clears the buffer.
233
+
234
+ Returns: {String | null} The rendered Turbo Stream HTML fragment or null if there were no buffered elements.
235
+
236
+ #### turbostream.custom(action, target, content)
237
+
238
+ - `action` {String} The name of the custom action.
239
+ - `target` {String} The target ID.
240
+ - `content` {String} The HTML content of the element.
241
+
242
+ Adds a Turbo Stream Element with a custom action.
243
+
244
+ Returns: {TurboStream} The instance for chaining.
245
+
246
+ #### turbostream.customAll(action, targets, content)
247
+
248
+ - `action` {String} The name of the custom action.
249
+ - `targets` {String} The query string targeting multiple DOM elements.
250
+ - `content` {String} The HTML content of the element.
251
+
252
+ Adds a Turbo Stream Element with a custom action, targeting multiple DOM elements.
253
+
254
+ Returns: {TurboStream} The instance for chaining.
255
+
256
+ #### turbostream.createReadableStream(opts[, streamOptions])
257
+
258
+ - `opts` {*}
259
+ - `streamOptions` {{}}
260
+
261
+ Returns: {*}
262
+
263
+ ### Class: TurboStreamElement
264
+
265
+ ```javascript
266
+ import { TurboStreamElement } from 'node-turbo';
267
+ ```
268
+
269
+ ***Extends:***
270
+ - [TurboElement](#class-turboelement)
271
+
272
+ A Turbo Stream element. A Turbo Stream message consists of one or several Turbo Stream elements.
273
+
274
+ #### turbostreamelement.validate()
275
+
276
+ Validates the attributes. `attributes.target` (or `attributes.targets`) and `attributes.action` are mandatory. Gets called by the constructor.
277
+
278
+ Throws {AttributeMissingError} when mandatory attributes are missing.
279
+ Throws {AttributeMalformedError} when mandatory attributes are malformed.
280
+ Throws {AttributeInvalidError} when attributes are invalid.
281
+
282
+ #### turbostreamelement.render()
283
+
284
+ Renders this Turbo Stream element as HTML string. Omits `<template>[content]<template>` when the attribute `action` is 'remove'.
285
+
286
+ Returns: {String} The rendered HTML fragment.
287
+
288
+ #### Inherited from class [TurboElement](#class-turboelement):
289
+
290
+ > - constructor(attributes, content)
291
+ Automatically calls validate().
292
+ > - attributes
293
+ The attribute object.
294
+ > - content
295
+ The HTML content.
296
+ > - renderAttributesAsHtml()
297
+ Converts the attributes object to a string in the form
298
+ of HTML attributes ({ name: value } -&#62; 'name="value"').
299
+
300
+ ### Class: TurboElement
301
+
302
+ ```javascript
303
+ import { TurboElement } from 'node-turbo';
304
+ ```
305
+
306
+ Base class with common functionality for Turbo Stream elements and Turbo Frames. Not to be used directly.
307
+
308
+ #### new TurboElement(attributes, content)
309
+
310
+ - `attributes` {Object} The attributes of this element.
311
+ - `content` {String} The HTML content of this element.
312
+
313
+ Automatically calls validate().
314
+
315
+ #### turboelement.attributes
316
+
317
+ {Object<String, String>}
318
+
319
+ The attribute object.
320
+
321
+ #### turboelement.content
322
+
323
+ {String}
324
+
325
+ The HTML content.
326
+
327
+ #### turboelement.renderAttributesAsHtml()
328
+
329
+ Converts the attributes object to a string in the form of HTML attributes ({ name: value } -> 'name="value"').
330
+
331
+ Returns: {String} The HTML attribute string.
332
+
333
+ #### turboelement.validate()
334
+
335
+ Validation function to implement.
336
+
337
+ #### turboelement.render()
338
+
339
+ Render function to implement.
340
+
341
+ ### Class: TurboReadable
342
+
343
+ ```javascript
344
+ import { TurboReadable } from 'node-turbo';
345
+ ```
346
+
347
+ ***Extends:***
348
+ - stream~Readable
349
+
350
+ This class represents a readable stream which reads messages/elements from a Turbo Stream instance.
351
+
352
+ #### new TurboReadable(turboStream[, opts])
353
+
354
+ - `turboStream` {TurboStream} The Turbo Stream instance to create the readable stream for.
355
+ - `opts` {Object} The options for the readable stream.
356
+
357
+ Creates the readable stream instance. Updates the Turbo Stream's configuration to not buffer elements and adds an event listener for `element` events to it, which get handled by `_boundPush(el)`.
358
+
359
+ If there are already buffered elements, they get pushed into into the read queue immediately and the buffer is cleared afterwards.
360
+
361
+ #### turboreadable._turboStream
362
+
363
+ {TurboStream}
364
+
365
+ The Turbo Stream instance to create the readable stream for.
366
+
367
+ #### turboreadable._boundPush
368
+
369
+ {Function}
370
+
371
+ This is the bound variant of `_pushElement(el)`. This function serves as handler for the `element` event.
372
+
373
+ #### turboreadable._pushElement(el)
374
+
375
+ - `el` {TurboStreamElement} The Turbo Stream element.
376
+
377
+ Pushes a Turbo Stream element into the read queue.
378
+
379
+ #### turboreadable._read()
380
+
381
+ Gets called when data is available for reading. This implementation does nothing. (Normally, push data would be pushed into the read queue here.)
382
+
383
+ #### turboreadable._destroy(err)
384
+
385
+ - `err` {Error} The error object, if thrown.
386
+
387
+ Gets called when the stream is being destroyed. The event listener for the event `element` is removed and the configuration restored.
388
+
389
+ #### turboreadable.done()
390
+
391
+ Pushes `null` to the readable buffer to signal the end of the input.
392
+
393
+ #### isTurboStreamRequest(request)
394
+
395
+ ```javascript
396
+ import { isTurboStreamRequest } from 'node-turbo';
397
+ ```
398
+
399
+ `static`
400
+
401
+ - `request` {Object} The request object. Expects an object like an {http.ClientRequest} instance.
402
+
403
+ Checks if the request is a Turbo Stream request.
404
+
405
+ Returns: {Boolean} `true`, if the request has been identified as a Turbo Stream request. `false` otherwise.
406
+
407
+ #### isTurboFrameRequest(request)
408
+
409
+ ```javascript
410
+ import { isTurboFrameRequest } from 'node-turbo';
411
+ ```
412
+
413
+ `static`
414
+
415
+ - `request` {Object} The request object. Expects an object like an {http.ClientRequest} instance.
416
+
417
+ Checks if the request is a Turbo Frame request.
418
+
419
+ Returns: {Boolean} `true`, if the request has been identified as a Turbo Frame request. false otherwise.
420
+
421
+ #### getTurboFrameId(request)
422
+
423
+ ```javascript
424
+ import { getTurboFrameId } from 'node-turbo';
425
+ ```
426
+
427
+ `static`
428
+
429
+ - `request` {Object} The request object. Expects an object like an {http.ClientRequest} instance.
430
+
431
+ Returns the content of the 'turbo-frame' header, which is the ID of the requesting Turbo Frame.
432
+
433
+ Returns: {String | null} The Turbo Frame ID or `null` if not found.
434
+
435
+ ## node-turbo/ws
436
+
437
+ ### Class: WsTurboStream
438
+
439
+ ```javascript
440
+ import { WsTurboStream } from 'node-turbo/ws';
441
+ ```
442
+
443
+ ***Extends:***
444
+ - [TurboStream](#class-turbostream)
445
+
446
+ This class represents a Turbo Stream message with added functionality for WebSockets.
447
+
448
+ #### WsTurboStream.use(ws)
449
+
450
+ `static`
451
+
452
+ - `ws` {WebSocket} The WebSocket instance to send to.
453
+
454
+ Convenience function to create a non-buffering WsTurboStream instance, which uses the passed WebSocket.
455
+
456
+ Returns: {WsTurboStream} A new WsTurboStream instance.
457
+
458
+ #### WsTurboStream.OPEN
459
+
460
+ `static` {Number}
461
+
462
+ Ready-state `OPEN` of a WebSocket.
463
+
464
+ See [https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState)
465
+
466
+ #### new WsTurboStream(ws[, config])
467
+
468
+ - `ws` {WebSocket} The WebSocket to send to.
469
+ - `config` {Object} The config to override.
470
+
471
+ Listens for the event `config` and calls `handleConfig(config)` if it has been emitted.
472
+
473
+ #### wsturbostream.ws
474
+
475
+ {WebSocket}
476
+
477
+ The WebSocket instance to send to.
478
+
479
+ #### wsturbostream.handleConfig(config)
480
+
481
+ - `config` {Object} The changed config object.
482
+
483
+ Changes event listeners depending on `config.buffer`:
484
+ If `true`, it will listen for the event `render` and call `handleRender()` when the event has been emitted.
485
+ If `false`, it will listen for the event `element` and call `handleElement()` when the event has been emitted.
486
+
487
+ #### wsturbostream.handleRender(html)
488
+
489
+ - `html` {String} The rendered HTML fragment.
490
+
491
+ Sends the rendered HTML fragment to the WebSocket.
492
+
493
+ #### wsturbostream.handleElement(element)
494
+
495
+ - `element` {TurboStreamElement} The Turbo Stream element to send.
496
+
497
+ Sends the Turbo Stream element to the WebSocket.
498
+
499
+ #### Inherited from class [TurboStream](#class-turbostream):
500
+
501
+ > - `static` ACTIONS
502
+ List of all supported actions:
503
+ 'append', 'prepend', 'replace', 'update', 'remove', 'before' and 'after'.
504
+ > - `static` MIME_TYPE
505
+ MIME type for Turbo Stream messages.
506
+ > - `get` length
507
+ The number of buffered Turbo Stream elements.
508
+ > - config
509
+ Default configuration.
510
+ > - elements
511
+ Array of buffered elements. Gets filled if `config.buffer` is `true`.
512
+ > - addElement(attributesOrElement, content)
513
+ Adds a Turbo Stream element to the message.
514
+ Adds the element to the buffer, if config.buffer === true.
515
+ Fires the event 'element' with the added element.
516
+ > - clear()
517
+ Clears the buffer.
518
+ > - createReadableStream(opts[, streamOptions])
519
+
520
+ > - custom(action, target, content)
521
+ Adds a Turbo Stream Element with a custom action.
522
+ > - customAll(action, targets, content)
523
+ Adds a Turbo Stream Element with a custom action, targeting multiple DOM elements.
524
+ > - flush()
525
+ Renders this Turbo Stream message and clears the buffer.
526
+ > - render()
527
+ Renders this Turbo Stream message if there are buffered elements.
528
+ > - renderElements()
529
+ If there are buffered elements, renders them and returns an array with the HTML fragments.
530
+ > - updateConfig(config)
531
+ Extends/Overwrites the configuration.
532
+
533
+ ## node-turbo/koa
534
+
535
+ ### Class: KoaTurboStream
536
+
537
+ ```javascript
538
+ import { KoaTurboStream } from 'node-turbo/koa';
539
+ ```
540
+
541
+ ***Extends:***
542
+ - [TurboStream](#class-turbostream)
543
+
544
+ This class represents a Turbo Stream message with added functionality for Koa. Renders directly to Koa's `ctx.body` whenever a Turbo Stream element gets added.
545
+
546
+ #### new KoaTurboStream(koaCtx)
547
+
548
+ - `koaCtx` {Object} Koa's context object.
549
+
550
+ #### koaturbostream.koaCtx
551
+
552
+ {Object}
553
+
554
+ Koa's context object.
555
+
556
+ See [https://koajs.com/#context](https://koajs.com/#context)
557
+
558
+ #### koaturbostream.status
559
+
560
+ {number}
561
+
562
+ #### Inherited from class [TurboStream](#class-turbostream):
563
+
564
+ > - `static` ACTIONS
565
+ List of all supported actions:
566
+ 'append', 'prepend', 'replace', 'update', 'remove', 'before' and 'after'.
567
+ > - `static` MIME_TYPE
568
+ MIME type for Turbo Stream messages.
569
+ > - `get` length
570
+ The number of buffered Turbo Stream elements.
571
+ > - config
572
+ Default configuration.
573
+ > - elements
574
+ Array of buffered elements. Gets filled if `config.buffer` is `true`.
575
+ > - addElement(attributesOrElement, content)
576
+ Adds a Turbo Stream element to the message.
577
+ Adds the element to the buffer, if config.buffer === true.
578
+ Fires the event 'element' with the added element.
579
+ > - clear()
580
+ Clears the buffer.
581
+ > - createReadableStream(opts[, streamOptions])
582
+
583
+ > - custom(action, target, content)
584
+ Adds a Turbo Stream Element with a custom action.
585
+ > - customAll(action, targets, content)
586
+ Adds a Turbo Stream Element with a custom action, targeting multiple DOM elements.
587
+ > - flush()
588
+ Renders this Turbo Stream message and clears the buffer.
589
+ > - render()
590
+ Renders this Turbo Stream message if there are buffered elements.
591
+ > - renderElements()
592
+ If there are buffered elements, renders them and returns an array with the HTML fragments.
593
+ > - updateConfig(config)
594
+ Extends/Overwrites the configuration.
595
+
596
+ #### turbochargeKoa(koaApp, opts, opts.autoRender)
597
+
598
+ ```javascript
599
+ import { turbochargeKoa } from 'node-turbo/koa';
600
+ ```
601
+
602
+ `static`
603
+
604
+ - `koaApp` {Object} The Koa application object.
605
+ - `opts` {Object} The options.
606
+ - `opts.autoRender` {Boolean} Should Turbo Stream elements automatically be rendered and sent? (Default: `true`)
607
+
608
+ Adds the following functions to Koa's context object:
609
+
610
+ - `turboStream()`
611
+ Returns a chainable Turbo Stream instance which directly writes to `ctx.body` whenever an element is added. Also sets the correct `Content-Type` header.
612
+ - `turboFrame()`
613
+ Returns a Turbo Frame instance which directly writes to `ctx.body`.
614
+ - `isTurboStreamRequest()`
615
+ Checks if the request is a Turbo Stream request by looking for the MIME type in the `accept` headers.
616
+ Returns `true`/`false`.
617
+ - `isTurboFrameRequest()`
618
+ Checks if the request is a Turbo Frame request by looking for the `turbo-frame` header.
619
+ Returns `true`/`false`.
620
+ - `getTurboFrameId()`
621
+ Returns the contents of the `turbo-frame` header.
622
+ - `sseTurboStream()`
623
+ <em>Experimental</em>. Configures Koa to keep the connection open and use a stream to pipe to `ctx.res`.
624
+
625
+ ## node-turbo/express
626
+
627
+ ### Class: ExpressTurboStream
628
+
629
+ ```javascript
630
+ import { ExpressTurboStream } from 'node-turbo/express';
631
+ ```
632
+
633
+ ***Extends:***
634
+ - [TurboStream](#class-turbostream)
635
+
636
+ This class represents a Turbo Stream message for Express. Introduces the function `send()` to send the rendered message as HTTP response with the correct MIME type.
637
+
638
+ #### new ExpressTurboStream(res[, attributes][, content])
639
+
640
+ - `res` {Object} Express' response object to send to.
641
+ - `attributes` {Object} Attributes of the added element.
642
+ - `content` {String} The HTML content of the added element.
643
+
644
+ Stores Express' response object and creates a `TurboStream` instance.
645
+
646
+ #### expressturbostream.res
647
+
648
+ {Object}
649
+
650
+ Express' response object to send to.
651
+
652
+ #### expressturbostream.send()
653
+
654
+ Sends the rendered message as HTTP response with the correct MIME type.
655
+
656
+ #### Inherited from class [TurboStream](#class-turbostream):
657
+
658
+ > - `static` ACTIONS
659
+ List of all supported actions:
660
+ 'append', 'prepend', 'replace', 'update', 'remove', 'before' and 'after'.
661
+ > - `static` MIME_TYPE
662
+ MIME type for Turbo Stream messages.
663
+ > - `get` length
664
+ The number of buffered Turbo Stream elements.
665
+ > - config
666
+ Default configuration.
667
+ > - elements
668
+ Array of buffered elements. Gets filled if `config.buffer` is `true`.
669
+ > - addElement(attributesOrElement, content)
670
+ Adds a Turbo Stream element to the message.
671
+ Adds the element to the buffer, if config.buffer === true.
672
+ Fires the event 'element' with the added element.
673
+ > - clear()
674
+ Clears the buffer.
675
+ > - createReadableStream(opts[, streamOptions])
676
+
677
+ > - custom(action, target, content)
678
+ Adds a Turbo Stream Element with a custom action.
679
+ > - customAll(action, targets, content)
680
+ Adds a Turbo Stream Element with a custom action, targeting multiple DOM elements.
681
+ > - flush()
682
+ Renders this Turbo Stream message and clears the buffer.
683
+ > - render()
684
+ Renders this Turbo Stream message if there are buffered elements.
685
+ > - renderElements()
686
+ If there are buffered elements, renders them and returns an array with the HTML fragments.
687
+ > - updateConfig(config)
688
+ Extends/Overwrites the configuration.
689
+
690
+ #### turbochargeExpress(expressApp, opts)
691
+
692
+ ```javascript
693
+ import { turbochargeExpress } from 'node-turbo/express';
694
+ ```
695
+
696
+ `static`
697
+
698
+ - `expressApp` {Object} The Express application object.
699
+ - `opts` {Object} The options to override.
700
+
701
+ Adds the following functions to Express' request object:
702
+
703
+ - `isTurboStreamRequest()`
704
+ Checks if the request is a Turbo Stream request by looking for the MIME type in the `accept` headers.
705
+ Returns `true`/`false`.
706
+ - `isTurboFrameRequest()`
707
+ Checks if the request is a Turbo Frame request by looking for the `turbo-frame` header.
708
+ Returns `true`/`false`.
709
+ - `getTurboFrameId()` Returns the contents of the `turbo-frame` header.
710
+
711
+ Also adds the following functions to Express' `response` object:
712
+
713
+ - `turboStream()`
714
+ Returns a chainable Turbo Stream instance which introduces the function `send()` which sends the rendered Turbo Stream message as HTTP response with the correct MIME type.
715
+ - `turboFrame(id, content)` Returns a Turbo Frame instance which directly sends the rendered Turbo Frame message as HTTP response.
716
+ - `turboFrame(content)` If you omit the `id` attribute, it is automatically added by using the ID from the `turbo-frame` header.
717
+ - `sseTurboStream()`
718
+ <em>Experimental</em>. Configures Express to keep the connection open and use a stream to pipe to `res`.
719
+
720
+ ## node-turbo/sse
721
+
722
+ ### Class: SseTurboStream
723
+
724
+ ```javascript
725
+ import { SseTurboStream } from 'node-turbo/sse';
726
+ ```
727
+
728
+ ***Extends:***
729
+ - [TurboStream](#class-turbostream)
730
+
731
+ This class represents a Turbo Stream message for SSE.
732
+ **Note**: This class is in **experimental** stage.
733
+
734
+ #### SseTurboStream.MIME_TYPE
735
+
736
+ `static` {String}
737
+
738
+ MIME type for an SSE message (`text/event-stream`).
739
+
740
+ #### new SseTurboStream([eventname])
741
+
742
+ - `eventname` {String} The SSE event name to send the message under.
743
+
744
+ Creates a Turbo Stream message instance which automatically writes to the SSE stream as soon as a Turbo Stream element is added.
745
+
746
+ #### sseturbostream.eventName
747
+
748
+ {String}
749
+
750
+ The optional name to send the event under.
751
+
752
+ #### sseturbostream.render()
753
+
754
+ Renders the Turbo Stream message and adds SSE specific syntax.
755
+
756
+ Returns: {String | null} The rendered SSE or null if there were no elements in the buffer.
757
+
758
+ #### sseturbostream.renderSseEvent(raw)
759
+
760
+ - `raw` {String} The raw HTML string.
761
+
762
+ Takes a HTML fragment string and converts it to an SSE event message.
763
+
764
+ Returns: {String | null} The converted SSE event message or null if no string has been passed.
765
+
766
+ #### sseturbostream.createReadableStream()
767
+
768
+ Creates a {TurboReadable} instance, which pipes to a {node:stream~Transform} to add SSE specific syntax.
769
+
770
+ Returns: {node:stream.Transform} The Transform stream instance.
771
+
772
+ #### sseturbostream.event(eventName)
773
+
774
+ - `eventName` {String} The event name to send the message under.
775
+
776
+ Set the event name for the SSE data.
777
+
778
+ Returns: {SseTurboStream} The instance for chaining.
779
+
780
+ #### Inherited from class [TurboStream](#class-turbostream):
781
+
782
+ > - `static` ACTIONS
783
+ List of all supported actions:
784
+ 'append', 'prepend', 'replace', 'update', 'remove', 'before' and 'after'.
785
+ > - `get` length
786
+ The number of buffered Turbo Stream elements.
787
+ > - config
788
+ Default configuration.
789
+ > - elements
790
+ Array of buffered elements. Gets filled if `config.buffer` is `true`.
791
+ > - addElement(attributesOrElement, content)
792
+ Adds a Turbo Stream element to the message.
793
+ Adds the element to the buffer, if config.buffer === true.
794
+ Fires the event 'element' with the added element.
795
+ > - clear()
796
+ Clears the buffer.
797
+ > - custom(action, target, content)
798
+ Adds a Turbo Stream Element with a custom action.
799
+ > - customAll(action, targets, content)
800
+ Adds a Turbo Stream Element with a custom action, targeting multiple DOM elements.
801
+ > - flush()
802
+ Renders this Turbo Stream message and clears the buffer.
803
+ > - renderElements()
804
+ If there are buffered elements, renders them and returns an array with the HTML fragments.
805
+ > - updateConfig(config)
806
+ Extends/Overwrites the configuration.
807
+
808
+ ## node-turbo/errors
809
+
810
+ ### Class: ValidationError
811
+
812
+ ```javascript
813
+ import { ValidationError } from 'node-turbo/errors';
814
+ ```
815
+
816
+ ***Extends:***
817
+ - node:Error
818
+
819
+ Parent class for all validation errors.
820
+
821
+ ### Class: AttributeMalformedError
822
+
823
+ ```javascript
824
+ import { AttributeMalformedError } from 'node-turbo/errors';
825
+ ```
826
+
827
+ ***Extends:***
828
+ - [ValidationError](#class-validationerror)
829
+
830
+ Gets thrown when mandatory attributes are malformed.
831
+
832
+ ### Class: AttributeMissingError
833
+
834
+ ```javascript
835
+ import { AttributeMissingError } from 'node-turbo/errors';
836
+ ```
837
+
838
+ ***Extends:***
839
+ - [ValidationError](#class-validationerror)
840
+
841
+ Gets thrown when mandatory attributes are missing.
842
+
843
+ ### Class: AttributeInvalidError
844
+
845
+ ```javascript
846
+ import { AttributeInvalidError } from 'node-turbo/errors';
847
+ ```
848
+
849
+ ***Extends:***
850
+ - [ValidationError](#class-validationerror)
851
+
852
+ Gets thrown when invalid attributes are discovered.
853
+
854
+
855
+ ***
856
+
857
+ node-turbo is © 2024 by Walter Krivanek and released under the [MIT license](https://mit-license.org).