ts-procedures 3.2.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +222 -2
- package/build/errors.d.ts +5 -0
- package/build/errors.js +14 -0
- package/build/errors.js.map +1 -1
- package/build/implementations/http/hono-stream/index.d.ts +92 -0
- package/build/implementations/http/hono-stream/index.js +229 -0
- package/build/implementations/http/hono-stream/index.js.map +1 -0
- package/build/implementations/http/hono-stream/index.test.d.ts +1 -0
- package/build/implementations/http/hono-stream/index.test.js +681 -0
- package/build/implementations/http/hono-stream/index.test.js.map +1 -0
- package/build/implementations/http/hono-stream/types.d.ts +24 -0
- package/build/implementations/http/hono-stream/types.js +2 -0
- package/build/implementations/http/hono-stream/types.js.map +1 -0
- package/build/implementations/types.d.ts +15 -1
- package/build/index.d.ts +62 -3
- package/build/index.js +96 -1
- package/build/index.js.map +1 -1
- package/build/index.test.js +283 -2
- package/build/index.test.js.map +1 -1
- package/build/schema/compute-schema.d.ts +6 -1
- package/build/schema/compute-schema.js +4 -1
- package/build/schema/compute-schema.js.map +1 -1
- package/build/schema/parser.d.ts +6 -0
- package/build/schema/parser.js +42 -0
- package/build/schema/parser.js.map +1 -1
- package/build/schema/types.d.ts +1 -0
- package/package.json +5 -1
- package/src/errors.ts +16 -0
- package/src/implementations/http/README.md +87 -55
- package/src/implementations/http/hono-stream/README.md +261 -0
- package/src/implementations/http/hono-stream/index.test.ts +1009 -0
- package/src/implementations/http/hono-stream/index.ts +327 -0
- package/src/implementations/http/hono-stream/types.ts +29 -0
- package/src/implementations/types.ts +17 -1
- package/src/index.test.ts +402 -44
- package/src/index.ts +189 -3
- package/src/schema/compute-schema.ts +10 -3
- package/src/schema/parser.ts +55 -4
- package/src/schema/types.ts +4 -0
package/README.md
CHANGED
|
@@ -71,6 +71,34 @@ Create(name, config, handler)
|
|
|
71
71
|
- `procedure` - Generic reference to the handler
|
|
72
72
|
- `info` - Procedure meta (name, description, schema, `TExtendedConfig` properties, etc.)
|
|
73
73
|
|
|
74
|
+
### CreateStream Function
|
|
75
|
+
|
|
76
|
+
The `CreateStream` function defines streaming procedures that yield values over time using async generators:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
CreateStream(name, config, handler)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Config Options:**
|
|
83
|
+
- `schema.params` - Input parameter schema (validated at runtime)
|
|
84
|
+
- `schema.yieldType` - Schema for each yielded value (validated if `validateYields: true`)
|
|
85
|
+
- `schema.returnType` - Schema for final return value (documentation only)
|
|
86
|
+
- `validateYields` - Enable runtime validation of yielded values (default: `false`)
|
|
87
|
+
|
|
88
|
+
**Handler Signature:**
|
|
89
|
+
```typescript
|
|
90
|
+
async function* (ctx, params) => AsyncGenerator<TYield, TReturn | void>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Context Extensions:**
|
|
94
|
+
- `ctx.error(message, meta?)` - Create a ProcedureError
|
|
95
|
+
- `ctx.signal` - AbortSignal for cancellation support
|
|
96
|
+
|
|
97
|
+
**Returns:**
|
|
98
|
+
- `{ [name]: handler }` - Named generator export
|
|
99
|
+
- `procedure` - Generic reference to the generator
|
|
100
|
+
- `info` - Procedure meta with `isStream: true`
|
|
101
|
+
|
|
74
102
|
## Using Generics
|
|
75
103
|
|
|
76
104
|
### Base Context
|
|
@@ -237,6 +265,193 @@ AJV is configured with:
|
|
|
237
265
|
|
|
238
266
|
**Note:** `schema.params` is validated at runtime. `schema.returnType` is for documentation/introspection only.
|
|
239
267
|
|
|
268
|
+
## Streaming Procedures
|
|
269
|
+
|
|
270
|
+
Streaming procedures use async generators to yield values over time, enabling SSE (Server-Sent Events), HTTP streaming, and real-time data feeds.
|
|
271
|
+
|
|
272
|
+
### Basic Streaming
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
import { Procedures } from 'ts-procedures'
|
|
276
|
+
import { v } from 'suretype'
|
|
277
|
+
|
|
278
|
+
const { CreateStream } = Procedures<{ userId: string }>()
|
|
279
|
+
|
|
280
|
+
const { StreamUpdates } = CreateStream(
|
|
281
|
+
'StreamUpdates',
|
|
282
|
+
{
|
|
283
|
+
description: 'Stream real-time updates',
|
|
284
|
+
schema: {
|
|
285
|
+
params: v.object({ topic: v.string().required() }),
|
|
286
|
+
yieldType: v.object({
|
|
287
|
+
id: v.string().required(),
|
|
288
|
+
message: v.string().required(),
|
|
289
|
+
timestamp: v.number().required(),
|
|
290
|
+
}),
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
async function* (ctx, params) {
|
|
294
|
+
// Types are inferred from schema:
|
|
295
|
+
// - params.topic: string
|
|
296
|
+
// - yield value must match { id, message, timestamp }
|
|
297
|
+
// - ctx.signal: AbortSignal for cancellation
|
|
298
|
+
|
|
299
|
+
let counter = 0
|
|
300
|
+
while (!ctx.signal.aborted) {
|
|
301
|
+
yield {
|
|
302
|
+
id: `${counter++}`,
|
|
303
|
+
message: `Update for ${params.topic}`,
|
|
304
|
+
timestamp: Date.now(),
|
|
305
|
+
}
|
|
306
|
+
await new Promise(r => setTimeout(r, 1000))
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
// Consume the stream
|
|
312
|
+
for await (const update of StreamUpdates({ userId: 'user-123' }, { topic: 'news' })) {
|
|
313
|
+
console.log(update.message)
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Yield Validation
|
|
318
|
+
|
|
319
|
+
By default, yielded values are not validated for performance. Enable validation with `validateYields: true`:
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
const { ValidatedStream } = CreateStream(
|
|
323
|
+
'ValidatedStream',
|
|
324
|
+
{
|
|
325
|
+
schema: {
|
|
326
|
+
yieldType: v.object({ count: v.number().required() }),
|
|
327
|
+
},
|
|
328
|
+
validateYields: true, // Enable runtime validation of each yield
|
|
329
|
+
},
|
|
330
|
+
async function* () {
|
|
331
|
+
yield { count: 1 } // Valid
|
|
332
|
+
yield { count: 2 } // Valid
|
|
333
|
+
// yield { count: 'invalid' } // Would throw ProcedureYieldValidationError
|
|
334
|
+
},
|
|
335
|
+
)
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Abort Signal Integration
|
|
339
|
+
|
|
340
|
+
The `ctx.signal` allows handlers to detect when consumers stop iterating:
|
|
341
|
+
|
|
342
|
+
```typescript
|
|
343
|
+
const { CancellableStream } = CreateStream(
|
|
344
|
+
'CancellableStream',
|
|
345
|
+
{},
|
|
346
|
+
async function* (ctx) {
|
|
347
|
+
try {
|
|
348
|
+
while (!ctx.signal.aborted) {
|
|
349
|
+
yield await fetchNextItem()
|
|
350
|
+
}
|
|
351
|
+
} finally {
|
|
352
|
+
// Cleanup when stream ends (consumer stopped or completed)
|
|
353
|
+
await cleanup()
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
// Consumer can break early - signal.aborted becomes true
|
|
359
|
+
for await (const item of CancellableStream({}, {})) {
|
|
360
|
+
if (shouldStop) break // Triggers abort
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### SSE Integration Example
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
import express from 'express'
|
|
368
|
+
import { Procedures } from 'ts-procedures'
|
|
369
|
+
|
|
370
|
+
const app = express()
|
|
371
|
+
|
|
372
|
+
const { CreateStream, getProcedures } = Procedures<{ req: express.Request }>({
|
|
373
|
+
onCreate: (proc) => {
|
|
374
|
+
if (proc.isStream) {
|
|
375
|
+
// Register streaming procedures as SSE endpoints
|
|
376
|
+
app.get(`/stream/${proc.name}`, async (req, res) => {
|
|
377
|
+
res.writeHead(200, {
|
|
378
|
+
'Content-Type': 'text/event-stream',
|
|
379
|
+
'Cache-Control': 'no-cache',
|
|
380
|
+
'Connection': 'keep-alive',
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
const generator = proc.handler({ req }, req.query)
|
|
384
|
+
|
|
385
|
+
req.on('close', async () => {
|
|
386
|
+
// Client disconnected - stop the generator
|
|
387
|
+
await generator.return(undefined)
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
for await (const data of generator) {
|
|
392
|
+
res.write(`data: ${JSON.stringify(data)}\n\n`)
|
|
393
|
+
}
|
|
394
|
+
} finally {
|
|
395
|
+
res.end()
|
|
396
|
+
}
|
|
397
|
+
})
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
// Define a streaming procedure
|
|
403
|
+
CreateStream(
|
|
404
|
+
'LiveFeed',
|
|
405
|
+
{
|
|
406
|
+
schema: {
|
|
407
|
+
params: v.object({ channel: v.string() }),
|
|
408
|
+
yieldType: v.object({ event: v.string(), data: v.any() }),
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
async function* (ctx, params) {
|
|
412
|
+
while (!ctx.signal.aborted) {
|
|
413
|
+
const event = await pollForEvent(params.channel)
|
|
414
|
+
yield event
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
app.listen(3000)
|
|
420
|
+
// SSE endpoint: GET /stream/LiveFeed?channel=updates
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Stream Errors
|
|
424
|
+
|
|
425
|
+
Streaming procedures support the same error handling as regular procedures:
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
const { StreamWithErrors } = CreateStream(
|
|
429
|
+
'StreamWithErrors',
|
|
430
|
+
{},
|
|
431
|
+
async function* (ctx) {
|
|
432
|
+
yield { status: 'starting' }
|
|
433
|
+
|
|
434
|
+
const data = await fetchData()
|
|
435
|
+
if (!data) {
|
|
436
|
+
throw ctx.error('No data available', { code: 'NO_DATA' })
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
yield { status: 'complete', data }
|
|
440
|
+
},
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
try {
|
|
444
|
+
for await (const item of StreamWithErrors({}, {})) {
|
|
445
|
+
console.log(item)
|
|
446
|
+
}
|
|
447
|
+
} catch (e) {
|
|
448
|
+
if (e instanceof ProcedureError) {
|
|
449
|
+
console.log(e.message) // 'No data available'
|
|
450
|
+
console.log(e.meta) // { code: 'NO_DATA' }
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
240
455
|
## Error Handling
|
|
241
456
|
|
|
242
457
|
### Using ctx.error()
|
|
@@ -262,7 +477,8 @@ Create(
|
|
|
262
477
|
| Error Class | Trigger |
|
|
263
478
|
|-------------|---------|
|
|
264
479
|
| ProcedureError | `ctx.error()` in handlers |
|
|
265
|
-
| ProcedureValidationError | Schema validation failure |
|
|
480
|
+
| ProcedureValidationError | Schema validation failure (params) |
|
|
481
|
+
| ProcedureYieldValidationError | Yield validation failure (streaming with `validateYields: true`) |
|
|
266
482
|
| ProcedureRegistrationError | Invalid schema at registration |
|
|
267
483
|
|
|
268
484
|
### Error Properties
|
|
@@ -470,10 +686,13 @@ import {
|
|
|
470
686
|
ProcedureError,
|
|
471
687
|
ProcedureValidationError,
|
|
472
688
|
ProcedureRegistrationError,
|
|
473
|
-
|
|
689
|
+
ProcedureYieldValidationError, // For streaming yield validation
|
|
690
|
+
|
|
474
691
|
// Types
|
|
475
692
|
TLocalContext,
|
|
693
|
+
TStreamContext, // Streaming context with AbortSignal
|
|
476
694
|
TProcedureRegistration,
|
|
695
|
+
TStreamProcedureRegistration, // Streaming procedure registration
|
|
477
696
|
TNoContextProvided,
|
|
478
697
|
|
|
479
698
|
// Schema utilities
|
|
@@ -485,6 +704,7 @@ import {
|
|
|
485
704
|
// Schema types
|
|
486
705
|
TJSONSchema,
|
|
487
706
|
TSchemaLib,
|
|
707
|
+
TSchemaLibGenerator, // AsyncGenerator type utility
|
|
488
708
|
TSchemaParsed,
|
|
489
709
|
TSchemaValidationError,
|
|
490
710
|
Prettify,
|
package/build/errors.d.ts
CHANGED
|
@@ -26,3 +26,8 @@ export declare class ProcedureRegistrationError extends ProcedureError {
|
|
|
26
26
|
readonly procedureName: string;
|
|
27
27
|
constructor(procedureName: string, message: string, definitionInfo?: DefinitionInfo);
|
|
28
28
|
}
|
|
29
|
+
export declare class ProcedureYieldValidationError extends ProcedureError {
|
|
30
|
+
readonly procedureName: string;
|
|
31
|
+
readonly errors?: TSchemaValidationError[] | undefined;
|
|
32
|
+
constructor(procedureName: string, message: string, errors?: TSchemaValidationError[] | undefined, definitionInfo?: DefinitionInfo);
|
|
33
|
+
}
|
package/build/errors.js
CHANGED
|
@@ -70,4 +70,18 @@ export class ProcedureRegistrationError extends ProcedureError {
|
|
|
70
70
|
Object.setPrototypeOf(this, ProcedureRegistrationError.prototype);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
export class ProcedureYieldValidationError extends ProcedureError {
|
|
74
|
+
procedureName;
|
|
75
|
+
errors;
|
|
76
|
+
constructor(procedureName, message, errors,
|
|
77
|
+
// Used for error stack trace details
|
|
78
|
+
definitionInfo) {
|
|
79
|
+
super(procedureName, message, undefined, definitionInfo);
|
|
80
|
+
this.procedureName = procedureName;
|
|
81
|
+
this.errors = errors;
|
|
82
|
+
this.name = 'ProcedureYieldValidationError';
|
|
83
|
+
// https://www.dannyguo.com/blog/how-to-fix-instanceof-not-working-for-custom-errors-in-typescript/
|
|
84
|
+
Object.setPrototypeOf(this, ProcedureYieldValidationError.prototype);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
73
87
|
//# sourceMappingURL=errors.js.map
|
package/build/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAsC,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AAE3F,MAAM,OAAO,cAAe,SAAQ,KAAK;IAM5B;IACA;IACA;IAPX,KAAK,CAAU;IACN,SAAS,CAAqB;IAC9B,eAAe,CAAS;IAEjC,YACW,aAAqB,EACrB,OAAe,EACf,IAAa;IACtB,qCAAqC;IACrC,cAA+B;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAA;QANL,kBAAa,GAAb,aAAa,CAAQ;QACrB,YAAO,GAAP,OAAO,CAAQ;QACf,SAAI,GAAJ,IAAI,CAAS;QAKtB,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAA;QAE5B,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,GAAG,cAAc,CAAC,SAAS,CAAA;YACzC,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC,eAAe,CAAA;YACrD,IAAI,CAAC,YAAY,EAAE,CAAA;QACrB,CAAC;QAED,mGAAmG;QACnG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,cAAc,CAAC,SAAS,CAAC,CAAA;IACvD,CAAC;IAED;;OAEG;IACH,qBAAqB;QACnB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,SAAS,CAAA;QAClB,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAA;IACjF,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACnC,OAAM;QACR,CAAC;QAED,MAAM,iBAAiB,GAAG,oBAAoB,CAC5C,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,EACpE,IAAI,CAAC,aAAa,CACnB,CAAA;QAED,IAAI,iBAAiB,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,iBAAiB,CAAA;QAC7C,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,cAAc;IAE/C;IAEA;IAHX,YACW,aAAqB,EAC9B,OAAe,EACN,MAAiC;IAC1C,qCAAqC;IACrC,cAA+B;QAE/B,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,CAAC,CAAA;QAN/C,kBAAa,GAAb,aAAa,CAAQ;QAErB,WAAM,GAAN,MAAM,CAA2B;QAK1C,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAA;QAEtC,mGAAmG;QACnG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,wBAAwB,CAAC,SAAS,CAAC,CAAA;IACjE,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,cAAc;IAEjD;IADX,YACW,aAAqB,EAC9B,OAAe;IACf,qCAAqC;IACrC,cAA+B;QAE/B,KAAK,CAAC,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,CAAC,CAAA;QAL/C,kBAAa,GAAb,aAAa,CAAQ;QAM9B,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAA;QAExC,mGAAmG;QACnG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,0BAA0B,CAAC,SAAS,CAAC,CAAA;IACnE,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Hono, Context } from 'hono';
|
|
2
|
+
import { TStreamProcedureRegistration } from '../../../index.js';
|
|
3
|
+
import { ExtractConfig, ExtractContext, ProceduresFactory, RPCConfig } from '../../types.js';
|
|
4
|
+
import { StreamHttpRouteDoc, StreamMode } from './types.js';
|
|
5
|
+
export type { StreamHttpRouteDoc, StreamMode };
|
|
6
|
+
export type HonoStreamAppBuilderConfig = {
|
|
7
|
+
/**
|
|
8
|
+
* An existing Hono application instance to use.
|
|
9
|
+
* If not provided, a new instance will be created.
|
|
10
|
+
*/
|
|
11
|
+
app?: Hono;
|
|
12
|
+
/** Optional path prefix for all stream routes. */
|
|
13
|
+
pathPrefix?: string;
|
|
14
|
+
/** Default stream mode for all routes. Defaults to 'sse'. */
|
|
15
|
+
defaultStreamMode?: StreamMode;
|
|
16
|
+
onRequestStart?: (c: Context) => void;
|
|
17
|
+
onRequestEnd?: (c: Context) => void;
|
|
18
|
+
onStreamStart?: (procedure: TStreamProcedureRegistration, c: Context) => void;
|
|
19
|
+
onStreamEnd?: (procedure: TStreamProcedureRegistration, c: Context) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Error handler called when a streaming procedure throws an error.
|
|
22
|
+
*/
|
|
23
|
+
onStreamError?: (procedure: TStreamProcedureRegistration, c: Context, error: Error) => Response | Promise<Response>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Builder class for creating a Hono application with streaming RPC routes.
|
|
27
|
+
*
|
|
28
|
+
* Usage:
|
|
29
|
+
* const StreamRPC = Procedures<StreamContext, RPCConfig>()
|
|
30
|
+
*
|
|
31
|
+
* const streamApp = new HonoStreamAppBuilder()
|
|
32
|
+
* .register(StreamRPC, (c): Promise<StreamContext> => { /* context resolution logic * / })
|
|
33
|
+
* .build();
|
|
34
|
+
*
|
|
35
|
+
* const app = streamApp.app; // Hono application
|
|
36
|
+
* const docs = streamApp.docs; // Stream route documentation
|
|
37
|
+
*/
|
|
38
|
+
export declare class HonoStreamAppBuilder {
|
|
39
|
+
readonly config?: HonoStreamAppBuilderConfig | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Constructor for HonoStreamAppBuilder.
|
|
42
|
+
*/
|
|
43
|
+
constructor(config?: HonoStreamAppBuilderConfig | undefined);
|
|
44
|
+
/**
|
|
45
|
+
* Generates the stream route path based on the RPC configuration.
|
|
46
|
+
*/
|
|
47
|
+
static makeStreamHttpRoutePath({ name, config, prefix, }: {
|
|
48
|
+
name: string;
|
|
49
|
+
prefix?: string;
|
|
50
|
+
config: RPCConfig;
|
|
51
|
+
}): string;
|
|
52
|
+
/**
|
|
53
|
+
* Instance method wrapper for makeStreamHttpRoutePath that uses the builder's pathPrefix.
|
|
54
|
+
*/
|
|
55
|
+
makeStreamHttpRoutePath(name: string, config: RPCConfig): string;
|
|
56
|
+
private factories;
|
|
57
|
+
private _app;
|
|
58
|
+
private _docs;
|
|
59
|
+
get app(): Hono;
|
|
60
|
+
get docs(): StreamHttpRouteDoc[];
|
|
61
|
+
/**
|
|
62
|
+
* Registers a procedure factory with its context.
|
|
63
|
+
* Only streaming procedures (created with CreateStream) will be registered.
|
|
64
|
+
*/
|
|
65
|
+
register<TFactory extends ProceduresFactory>(factory: TFactory, factoryContext: ExtractContext<TFactory> | ((c: Context) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>), options?: {
|
|
66
|
+
streamMode?: StreamMode;
|
|
67
|
+
extendProcedureDoc?: (params: {
|
|
68
|
+
base: StreamHttpRouteDoc;
|
|
69
|
+
procedure: TStreamProcedureRegistration<any, ExtractConfig<TFactory>>;
|
|
70
|
+
}) => Record<string, any>;
|
|
71
|
+
}): this;
|
|
72
|
+
/**
|
|
73
|
+
* Creates a route handler for streaming procedures.
|
|
74
|
+
*/
|
|
75
|
+
private createStreamHandler;
|
|
76
|
+
/**
|
|
77
|
+
* Handles SSE streaming mode.
|
|
78
|
+
*/
|
|
79
|
+
private handleSSEStream;
|
|
80
|
+
/**
|
|
81
|
+
* Handles text streaming mode.
|
|
82
|
+
*/
|
|
83
|
+
private handleTextStream;
|
|
84
|
+
/**
|
|
85
|
+
* Builds and returns the Hono application with registered streaming routes.
|
|
86
|
+
*/
|
|
87
|
+
build(): Hono;
|
|
88
|
+
/**
|
|
89
|
+
* Generates the Stream HTTP route documentation for the given procedure.
|
|
90
|
+
*/
|
|
91
|
+
private buildStreamHttpRouteDoc;
|
|
92
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { streamSSE, streamText } from 'hono/streaming';
|
|
3
|
+
import { kebabCase } from 'es-toolkit/string';
|
|
4
|
+
import { castArray } from 'es-toolkit/compat';
|
|
5
|
+
/**
|
|
6
|
+
* Builder class for creating a Hono application with streaming RPC routes.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const StreamRPC = Procedures<StreamContext, RPCConfig>()
|
|
10
|
+
*
|
|
11
|
+
* const streamApp = new HonoStreamAppBuilder()
|
|
12
|
+
* .register(StreamRPC, (c): Promise<StreamContext> => { /* context resolution logic * / })
|
|
13
|
+
* .build();
|
|
14
|
+
*
|
|
15
|
+
* const app = streamApp.app; // Hono application
|
|
16
|
+
* const docs = streamApp.docs; // Stream route documentation
|
|
17
|
+
*/
|
|
18
|
+
export class HonoStreamAppBuilder {
|
|
19
|
+
config;
|
|
20
|
+
/**
|
|
21
|
+
* Constructor for HonoStreamAppBuilder.
|
|
22
|
+
*/
|
|
23
|
+
constructor(config) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
if (config?.app) {
|
|
26
|
+
this._app = config.app;
|
|
27
|
+
}
|
|
28
|
+
if (config?.onRequestStart) {
|
|
29
|
+
this._app.use('*', async (c, next) => {
|
|
30
|
+
config.onRequestStart(c);
|
|
31
|
+
await next();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (config?.onRequestEnd) {
|
|
35
|
+
this._app.use('*', async (c, next) => {
|
|
36
|
+
await next();
|
|
37
|
+
config.onRequestEnd(c);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Generates the stream route path based on the RPC configuration.
|
|
43
|
+
*/
|
|
44
|
+
static makeStreamHttpRoutePath({ name, config, prefix, }) {
|
|
45
|
+
const normalizedPrefix = prefix ? (prefix.startsWith('/') ? prefix : `/${prefix}`) : '';
|
|
46
|
+
return `${normalizedPrefix}/${castArray(config.scope).map(kebabCase).join('/')}/${kebabCase(name)}/${String(config.version).trim()}`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Instance method wrapper for makeStreamHttpRoutePath that uses the builder's pathPrefix.
|
|
50
|
+
*/
|
|
51
|
+
makeStreamHttpRoutePath(name, config) {
|
|
52
|
+
return HonoStreamAppBuilder.makeStreamHttpRoutePath({
|
|
53
|
+
name,
|
|
54
|
+
config,
|
|
55
|
+
prefix: this.config?.pathPrefix,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
factories = [];
|
|
59
|
+
_app = new Hono();
|
|
60
|
+
_docs = [];
|
|
61
|
+
get app() {
|
|
62
|
+
return this._app;
|
|
63
|
+
}
|
|
64
|
+
get docs() {
|
|
65
|
+
return this._docs;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Registers a procedure factory with its context.
|
|
69
|
+
* Only streaming procedures (created with CreateStream) will be registered.
|
|
70
|
+
*/
|
|
71
|
+
register(factory, factoryContext, options) {
|
|
72
|
+
this.factories.push({
|
|
73
|
+
factory,
|
|
74
|
+
factoryContext,
|
|
75
|
+
streamMode: options?.streamMode,
|
|
76
|
+
extendProcedureDoc: options?.extendProcedureDoc,
|
|
77
|
+
});
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Creates a route handler for streaming procedures.
|
|
82
|
+
*/
|
|
83
|
+
createStreamHandler(procedure, factoryContext, streamMode) {
|
|
84
|
+
return async (c) => {
|
|
85
|
+
try {
|
|
86
|
+
const context = typeof factoryContext === 'function'
|
|
87
|
+
? await factoryContext(c)
|
|
88
|
+
: factoryContext;
|
|
89
|
+
// GET: query params, POST: JSON body
|
|
90
|
+
const params = c.req.method === 'GET'
|
|
91
|
+
? Object.fromEntries(new URL(c.req.url).searchParams)
|
|
92
|
+
: await c.req.json().catch(() => ({}));
|
|
93
|
+
if (this.config?.onStreamStart) {
|
|
94
|
+
this.config.onStreamStart(procedure, c);
|
|
95
|
+
}
|
|
96
|
+
if (streamMode === 'sse') {
|
|
97
|
+
return this.handleSSEStream(procedure, context, params, c);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
return this.handleTextStream(procedure, context, params, c);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (this.config?.onStreamError) {
|
|
105
|
+
return this.config.onStreamError(procedure, c, error);
|
|
106
|
+
}
|
|
107
|
+
return c.json({ error: error.message }, 500);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Handles SSE streaming mode.
|
|
113
|
+
*/
|
|
114
|
+
handleSSEStream(procedure, context, params, c) {
|
|
115
|
+
return streamSSE(c, async (stream) => {
|
|
116
|
+
const generator = procedure.handler(context, params);
|
|
117
|
+
stream.onAbort(async () => {
|
|
118
|
+
await generator.return(undefined);
|
|
119
|
+
});
|
|
120
|
+
try {
|
|
121
|
+
let eventId = 0;
|
|
122
|
+
for await (const value of generator) {
|
|
123
|
+
await stream.writeSSE({
|
|
124
|
+
data: JSON.stringify(value),
|
|
125
|
+
event: procedure.name,
|
|
126
|
+
id: String(eventId++),
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
// Write error as SSE event before closing
|
|
132
|
+
await stream.writeSSE({
|
|
133
|
+
data: JSON.stringify({ error: error.message }),
|
|
134
|
+
event: 'error',
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
if (this.config?.onStreamEnd) {
|
|
139
|
+
this.config.onStreamEnd(procedure, c);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Handles text streaming mode.
|
|
146
|
+
*/
|
|
147
|
+
handleTextStream(procedure, context, params, c) {
|
|
148
|
+
return streamText(c, async (stream) => {
|
|
149
|
+
const generator = procedure.handler(context, params);
|
|
150
|
+
stream.onAbort(async () => {
|
|
151
|
+
await generator.return(undefined);
|
|
152
|
+
});
|
|
153
|
+
try {
|
|
154
|
+
for await (const value of generator) {
|
|
155
|
+
await stream.writeln(JSON.stringify(value));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
// Write error as JSON line before closing
|
|
160
|
+
await stream.writeln(JSON.stringify({ error: error.message }));
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
if (this.config?.onStreamEnd) {
|
|
164
|
+
this.config.onStreamEnd(procedure, c);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Builds and returns the Hono application with registered streaming routes.
|
|
171
|
+
*/
|
|
172
|
+
build() {
|
|
173
|
+
this.factories.forEach(({ factory, factoryContext, streamMode, extendProcedureDoc }) => {
|
|
174
|
+
const mode = streamMode ?? this.config?.defaultStreamMode ?? 'sse';
|
|
175
|
+
factory
|
|
176
|
+
.getProcedures()
|
|
177
|
+
.filter((p) => p.isStream === true)
|
|
178
|
+
.forEach((procedure) => {
|
|
179
|
+
const route = this.buildStreamHttpRouteDoc(procedure, mode, extendProcedureDoc);
|
|
180
|
+
this._docs.push(route);
|
|
181
|
+
const handler = this.createStreamHandler(procedure, factoryContext, mode);
|
|
182
|
+
// Register both GET and POST handlers
|
|
183
|
+
this._app.get(route.path, handler);
|
|
184
|
+
this._app.post(route.path, handler);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
return this._app;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Generates the Stream HTTP route documentation for the given procedure.
|
|
191
|
+
*/
|
|
192
|
+
buildStreamHttpRouteDoc(procedure, streamMode, extendProcedureDoc) {
|
|
193
|
+
const { config } = procedure;
|
|
194
|
+
const path = HonoStreamAppBuilder.makeStreamHttpRoutePath({
|
|
195
|
+
name: procedure.name,
|
|
196
|
+
config,
|
|
197
|
+
prefix: this.config?.pathPrefix,
|
|
198
|
+
});
|
|
199
|
+
const methods = ['get', 'post'];
|
|
200
|
+
const jsonSchema = {};
|
|
201
|
+
if (config.schema?.params) {
|
|
202
|
+
jsonSchema.params = config.schema.params;
|
|
203
|
+
}
|
|
204
|
+
if (config.schema?.yieldType) {
|
|
205
|
+
jsonSchema.yieldType = config.schema.yieldType;
|
|
206
|
+
}
|
|
207
|
+
if (config.schema?.returnType) {
|
|
208
|
+
jsonSchema.returnType = config.schema.returnType;
|
|
209
|
+
}
|
|
210
|
+
const base = {
|
|
211
|
+
name: procedure.name,
|
|
212
|
+
version: config.version,
|
|
213
|
+
scope: config.scope,
|
|
214
|
+
path,
|
|
215
|
+
methods: [...methods],
|
|
216
|
+
streamMode,
|
|
217
|
+
jsonSchema,
|
|
218
|
+
};
|
|
219
|
+
let extendedDoc = {};
|
|
220
|
+
if (extendProcedureDoc) {
|
|
221
|
+
extendedDoc = extendProcedureDoc({ base, procedure });
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
...extendedDoc,
|
|
225
|
+
...base,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/implementations/http/hono-stream/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|