spiceflow 1.10.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +244 -118
- package/dist/_node-server.d.ts +3 -3
- package/dist/_node-server.d.ts.map +1 -1
- package/dist/client/index.d.ts +4 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +201 -195
- package/dist/client/types.d.ts +8 -6
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client.test.js +9 -0
- package/dist/context.d.ts +3 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/cors.d.ts.map +1 -1
- package/dist/cors.js +1 -1
- package/dist/error.d.ts +0 -8
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +0 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp.d.ts +5 -5
- package/dist/mcp.d.ts.map +1 -1
- package/dist/openapi.d.ts +2 -2
- package/dist/openapi.d.ts.map +1 -1
- package/dist/spiceflow.d.ts +60 -43
- package/dist/spiceflow.d.ts.map +1 -1
- package/dist/spiceflow.js +52 -16
- package/dist/spiceflow.test.js +85 -0
- package/dist/types.d.ts +24 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/package.json +7 -7
- package/src/_node-server.ts +3 -3
- package/src/client/index.ts +20 -14
- package/src/client/types.ts +11 -11
- package/src/client.test.ts +10 -0
- package/src/context.ts +3 -2
- package/src/cors.ts +1 -2
- package/src/error.ts +0 -10
- package/src/index.ts +1 -1
- package/src/spiceflow.test.ts +113 -0
- package/src/spiceflow.ts +181 -68
- package/src/types.ts +38 -28
package/src/spiceflow.ts
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { copy } from 'copy-anything'
|
|
2
|
+
|
|
3
|
+
import { SpiceflowFetchError } from './client/errors.ts'
|
|
4
|
+
import { ValidationError } from './error.ts'
|
|
2
5
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
6
|
+
ComposeSpiceflowResponse,
|
|
7
|
+
ContentType,
|
|
8
|
+
CreateClient,
|
|
9
|
+
DefinitionBase,
|
|
10
|
+
ErrorHandler,
|
|
11
|
+
ExtractParamsFromPath,
|
|
12
|
+
GetRequestSchema,
|
|
13
|
+
HTTPMethod,
|
|
14
|
+
InlineHandler,
|
|
15
|
+
InputSchema,
|
|
16
|
+
IsAny,
|
|
17
|
+
JoinPath,
|
|
18
|
+
LocalHook,
|
|
19
|
+
MetadataBase,
|
|
20
|
+
MiddlewareHandler,
|
|
21
|
+
Reconcile,
|
|
22
|
+
ResolvePath,
|
|
23
|
+
RouteBase,
|
|
24
|
+
RouteSchema,
|
|
25
|
+
SingletonBase,
|
|
26
|
+
TypeSchema,
|
|
27
|
+
UnwrapRoute,
|
|
23
28
|
} from './types.ts'
|
|
24
29
|
|
|
25
30
|
import OriginalRouter from '@medley/router'
|
|
@@ -29,7 +34,6 @@ import { StandardSchemaV1 } from '@standard-schema/spec'
|
|
|
29
34
|
import { IncomingMessage, ServerResponse } from 'node:http'
|
|
30
35
|
import { handleForNode, listenForNode } from 'spiceflow/_node-server'
|
|
31
36
|
import { MiddlewareContext } from './context.ts'
|
|
32
|
-
import { ValidationError } from './error.ts'
|
|
33
37
|
import { superjsonSerialize } from './serialize.ts'
|
|
34
38
|
import { isAsyncIterable, isResponse, redirect } from './utils.ts'
|
|
35
39
|
|
|
@@ -37,7 +41,15 @@ let globalIndex = 0
|
|
|
37
41
|
|
|
38
42
|
type AsyncResponse = Response | Promise<Response>
|
|
39
43
|
|
|
40
|
-
type
|
|
44
|
+
export type SpiceflowServerError =
|
|
45
|
+
| ValidationError
|
|
46
|
+
| SpiceflowFetchError<number, any>
|
|
47
|
+
| Error
|
|
48
|
+
|
|
49
|
+
type OnError = (x: {
|
|
50
|
+
error: SpiceflowServerError
|
|
51
|
+
request: Request
|
|
52
|
+
}) => AsyncResponse
|
|
41
53
|
|
|
42
54
|
type ValidationFunction = (
|
|
43
55
|
value: unknown,
|
|
@@ -83,7 +95,8 @@ export class Spiceflow<
|
|
|
83
95
|
macro: {}
|
|
84
96
|
macroFn: {}
|
|
85
97
|
},
|
|
86
|
-
const out
|
|
98
|
+
const out ClientRoutes extends RouteBase = {},
|
|
99
|
+
const out RoutePaths extends string = '',
|
|
87
100
|
> {
|
|
88
101
|
private id: number = globalIndex++
|
|
89
102
|
private router: MedleyRouter = new OriginalRouter()
|
|
@@ -93,6 +106,16 @@ export class Spiceflow<
|
|
|
93
106
|
private defaultState: Record<any, any> = {}
|
|
94
107
|
topLevelApp?: AnySpiceflow
|
|
95
108
|
|
|
109
|
+
_types = {
|
|
110
|
+
Prefix: '' as BasePath,
|
|
111
|
+
ClientRoutes: {} as ClientRoutes,
|
|
112
|
+
RoutePaths: '' as RoutePaths,
|
|
113
|
+
Scoped: false as Scoped,
|
|
114
|
+
Singleton: {} as Singleton,
|
|
115
|
+
Definitions: {} as Definitions,
|
|
116
|
+
Metadata: {} as Metadata,
|
|
117
|
+
}
|
|
118
|
+
|
|
96
119
|
/** @internal */
|
|
97
120
|
prefix?: string
|
|
98
121
|
|
|
@@ -245,7 +268,8 @@ export class Spiceflow<
|
|
|
245
268
|
},
|
|
246
269
|
Definitions,
|
|
247
270
|
Metadata,
|
|
248
|
-
|
|
271
|
+
ClientRoutes,
|
|
272
|
+
RoutePaths
|
|
249
273
|
> {
|
|
250
274
|
this.defaultState[name] = value
|
|
251
275
|
return this as any
|
|
@@ -268,16 +292,6 @@ export class Spiceflow<
|
|
|
268
292
|
this.prefix = options.basePath
|
|
269
293
|
}
|
|
270
294
|
|
|
271
|
-
_routes: Routes = {} as any
|
|
272
|
-
|
|
273
|
-
_types = {
|
|
274
|
-
Prefix: '' as BasePath,
|
|
275
|
-
Scoped: false as Scoped,
|
|
276
|
-
Singleton: {} as Singleton,
|
|
277
|
-
Definitions: {} as Definitions,
|
|
278
|
-
Metadata: {} as Metadata,
|
|
279
|
-
}
|
|
280
|
-
|
|
281
295
|
post<
|
|
282
296
|
const Path extends string,
|
|
283
297
|
const LocalSchema extends InputSchema<keyof Definitions['type'] & string>,
|
|
@@ -304,12 +318,12 @@ export class Spiceflow<
|
|
|
304
318
|
Singleton,
|
|
305
319
|
Definitions,
|
|
306
320
|
Metadata,
|
|
307
|
-
|
|
321
|
+
ClientRoutes &
|
|
308
322
|
CreateClient<
|
|
309
323
|
JoinPath<BasePath, Path>,
|
|
310
324
|
{
|
|
311
325
|
post: {
|
|
312
|
-
|
|
326
|
+
request: GetRequestSchema<Schema>
|
|
313
327
|
params: undefined extends Schema['params']
|
|
314
328
|
? ResolvePath<Path>
|
|
315
329
|
: Schema['params']
|
|
@@ -317,7 +331,8 @@ export class Spiceflow<
|
|
|
317
331
|
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
318
332
|
}
|
|
319
333
|
}
|
|
320
|
-
|
|
334
|
+
>,
|
|
335
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
321
336
|
> {
|
|
322
337
|
this.add({ method: 'POST', path, handler: handler, hooks: hook })
|
|
323
338
|
|
|
@@ -351,12 +366,12 @@ export class Spiceflow<
|
|
|
351
366
|
Singleton,
|
|
352
367
|
Definitions,
|
|
353
368
|
Metadata,
|
|
354
|
-
|
|
369
|
+
ClientRoutes &
|
|
355
370
|
CreateClient<
|
|
356
371
|
JoinPath<BasePath, Path>,
|
|
357
372
|
{
|
|
358
373
|
get: {
|
|
359
|
-
|
|
374
|
+
request: GetRequestSchema<Schema>
|
|
360
375
|
params: undefined extends Schema['params']
|
|
361
376
|
? ResolvePath<Path>
|
|
362
377
|
: Schema['params']
|
|
@@ -365,7 +380,8 @@ export class Spiceflow<
|
|
|
365
380
|
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
366
381
|
}
|
|
367
382
|
}
|
|
368
|
-
|
|
383
|
+
>,
|
|
384
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
369
385
|
> {
|
|
370
386
|
this.add({ method: 'GET', path, handler: handler, hooks: hook })
|
|
371
387
|
return this as any
|
|
@@ -397,12 +413,12 @@ export class Spiceflow<
|
|
|
397
413
|
Singleton,
|
|
398
414
|
Definitions,
|
|
399
415
|
Metadata,
|
|
400
|
-
|
|
416
|
+
ClientRoutes &
|
|
401
417
|
CreateClient<
|
|
402
418
|
JoinPath<BasePath, Path>,
|
|
403
419
|
{
|
|
404
420
|
put: {
|
|
405
|
-
|
|
421
|
+
request: GetRequestSchema<Schema>
|
|
406
422
|
params: undefined extends Schema['params']
|
|
407
423
|
? ResolvePath<Path>
|
|
408
424
|
: Schema['params']
|
|
@@ -411,13 +427,80 @@ export class Spiceflow<
|
|
|
411
427
|
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
412
428
|
}
|
|
413
429
|
}
|
|
414
|
-
|
|
430
|
+
>,
|
|
431
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
415
432
|
> {
|
|
416
433
|
this.add({ method: 'PUT', path, handler: handler, hooks: hook })
|
|
417
434
|
|
|
418
435
|
return this as any
|
|
419
436
|
}
|
|
420
437
|
|
|
438
|
+
route<
|
|
439
|
+
const Path extends string,
|
|
440
|
+
const LocalSchema extends InputSchema<keyof Definitions['type'] & string>,
|
|
441
|
+
const Schema extends UnwrapRoute<LocalSchema, Definitions['type']>,
|
|
442
|
+
const Handle extends InlineHandler<
|
|
443
|
+
Schema,
|
|
444
|
+
Singleton,
|
|
445
|
+
JoinPath<BasePath, Path>
|
|
446
|
+
>,
|
|
447
|
+
>(
|
|
448
|
+
options: {
|
|
449
|
+
path: Path
|
|
450
|
+
method: HTTPMethod | HTTPMethod[]
|
|
451
|
+
handler: Handle
|
|
452
|
+
} & LocalHook<
|
|
453
|
+
LocalSchema,
|
|
454
|
+
Schema,
|
|
455
|
+
Singleton,
|
|
456
|
+
Definitions['error'],
|
|
457
|
+
Metadata['macro'],
|
|
458
|
+
JoinPath<BasePath, Path>
|
|
459
|
+
>,
|
|
460
|
+
): Spiceflow<
|
|
461
|
+
BasePath,
|
|
462
|
+
Scoped,
|
|
463
|
+
Singleton,
|
|
464
|
+
Definitions,
|
|
465
|
+
Metadata,
|
|
466
|
+
ClientRoutes &
|
|
467
|
+
CreateClient<
|
|
468
|
+
JoinPath<BasePath, Path>,
|
|
469
|
+
{
|
|
470
|
+
put: {
|
|
471
|
+
request: GetRequestSchema<Schema>
|
|
472
|
+
params: undefined extends Schema['params']
|
|
473
|
+
? ResolvePath<Path>
|
|
474
|
+
: Schema['params']
|
|
475
|
+
query: Schema['query']
|
|
476
|
+
|
|
477
|
+
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
>,
|
|
481
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
482
|
+
> {
|
|
483
|
+
if (Array.isArray(options.method)) {
|
|
484
|
+
options.method.map((method) =>
|
|
485
|
+
this.add({
|
|
486
|
+
method,
|
|
487
|
+
path: options.path,
|
|
488
|
+
handler: options.handler,
|
|
489
|
+
hooks: options,
|
|
490
|
+
}),
|
|
491
|
+
)
|
|
492
|
+
} else {
|
|
493
|
+
this.add({
|
|
494
|
+
method: options.method,
|
|
495
|
+
path: options.path,
|
|
496
|
+
handler: options.handler,
|
|
497
|
+
hooks: options,
|
|
498
|
+
})
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return this as any
|
|
502
|
+
}
|
|
503
|
+
|
|
421
504
|
patch<
|
|
422
505
|
const Path extends string,
|
|
423
506
|
const LocalSchema extends InputSchema<keyof Definitions['type'] & string>,
|
|
@@ -444,12 +527,12 @@ export class Spiceflow<
|
|
|
444
527
|
Singleton,
|
|
445
528
|
Definitions,
|
|
446
529
|
Metadata,
|
|
447
|
-
|
|
530
|
+
ClientRoutes &
|
|
448
531
|
CreateClient<
|
|
449
532
|
JoinPath<BasePath, Path>,
|
|
450
533
|
{
|
|
451
534
|
patch: {
|
|
452
|
-
|
|
535
|
+
request: GetRequestSchema<Schema>
|
|
453
536
|
params: undefined extends Schema['params']
|
|
454
537
|
? ResolvePath<Path>
|
|
455
538
|
: Schema['params']
|
|
@@ -458,7 +541,8 @@ export class Spiceflow<
|
|
|
458
541
|
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
459
542
|
}
|
|
460
543
|
}
|
|
461
|
-
|
|
544
|
+
>,
|
|
545
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
462
546
|
> {
|
|
463
547
|
this.add({ method: 'PATCH', path, handler: handler, hooks: hook })
|
|
464
548
|
|
|
@@ -491,12 +575,12 @@ export class Spiceflow<
|
|
|
491
575
|
Singleton,
|
|
492
576
|
Definitions,
|
|
493
577
|
Metadata,
|
|
494
|
-
|
|
578
|
+
ClientRoutes &
|
|
495
579
|
CreateClient<
|
|
496
580
|
JoinPath<BasePath, Path>,
|
|
497
581
|
{
|
|
498
582
|
delete: {
|
|
499
|
-
|
|
583
|
+
request: GetRequestSchema<Schema>
|
|
500
584
|
params: undefined extends Schema['params']
|
|
501
585
|
? ResolvePath<Path>
|
|
502
586
|
: Schema['params']
|
|
@@ -505,7 +589,8 @@ export class Spiceflow<
|
|
|
505
589
|
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
506
590
|
}
|
|
507
591
|
}
|
|
508
|
-
|
|
592
|
+
>,
|
|
593
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
509
594
|
> {
|
|
510
595
|
this.add({ method: 'DELETE', path, handler: handler, hooks: hook })
|
|
511
596
|
|
|
@@ -538,12 +623,12 @@ export class Spiceflow<
|
|
|
538
623
|
Singleton,
|
|
539
624
|
Definitions,
|
|
540
625
|
Metadata,
|
|
541
|
-
|
|
626
|
+
ClientRoutes &
|
|
542
627
|
CreateClient<
|
|
543
628
|
JoinPath<BasePath, Path>,
|
|
544
629
|
{
|
|
545
630
|
options: {
|
|
546
|
-
|
|
631
|
+
request: GetRequestSchema<Schema>
|
|
547
632
|
params: undefined extends Schema['params']
|
|
548
633
|
? ResolvePath<Path>
|
|
549
634
|
: Schema['params']
|
|
@@ -552,7 +637,8 @@ export class Spiceflow<
|
|
|
552
637
|
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
553
638
|
}
|
|
554
639
|
}
|
|
555
|
-
|
|
640
|
+
>,
|
|
641
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
556
642
|
> {
|
|
557
643
|
this.add({ method: 'OPTIONS', path, handler: handler, hooks: hook })
|
|
558
644
|
|
|
@@ -585,12 +671,12 @@ export class Spiceflow<
|
|
|
585
671
|
Singleton,
|
|
586
672
|
Definitions,
|
|
587
673
|
Metadata,
|
|
588
|
-
|
|
674
|
+
ClientRoutes &
|
|
589
675
|
CreateClient<
|
|
590
676
|
JoinPath<BasePath, Path>,
|
|
591
677
|
{
|
|
592
678
|
[method in string]: {
|
|
593
|
-
|
|
679
|
+
request: GetRequestSchema<Schema>
|
|
594
680
|
params: undefined extends Schema['params']
|
|
595
681
|
? ResolvePath<Path>
|
|
596
682
|
: Schema['params']
|
|
@@ -599,7 +685,8 @@ export class Spiceflow<
|
|
|
599
685
|
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
600
686
|
}
|
|
601
687
|
}
|
|
602
|
-
|
|
688
|
+
>,
|
|
689
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
603
690
|
> {
|
|
604
691
|
for (const method of METHODS) {
|
|
605
692
|
this.add({ method, path, handler: handler, hooks: hook })
|
|
@@ -634,12 +721,12 @@ export class Spiceflow<
|
|
|
634
721
|
Singleton,
|
|
635
722
|
Definitions,
|
|
636
723
|
Metadata,
|
|
637
|
-
|
|
724
|
+
ClientRoutes &
|
|
638
725
|
CreateClient<
|
|
639
726
|
JoinPath<BasePath, Path>,
|
|
640
727
|
{
|
|
641
728
|
head: {
|
|
642
|
-
|
|
729
|
+
request: GetRequestSchema<Schema>
|
|
643
730
|
params: undefined extends Schema['params']
|
|
644
731
|
? ResolvePath<Path>
|
|
645
732
|
: Schema['params']
|
|
@@ -648,7 +735,8 @@ export class Spiceflow<
|
|
|
648
735
|
response: ComposeSpiceflowResponse<Schema['response'], Handle>
|
|
649
736
|
}
|
|
650
737
|
}
|
|
651
|
-
|
|
738
|
+
>,
|
|
739
|
+
RoutePaths | JoinPath<BasePath, Path>
|
|
652
740
|
> {
|
|
653
741
|
this.add({ method: 'HEAD', path, handler: handler, hooks: hook })
|
|
654
742
|
|
|
@@ -668,8 +756,10 @@ export class Spiceflow<
|
|
|
668
756
|
Definitions,
|
|
669
757
|
Metadata,
|
|
670
758
|
BasePath extends ``
|
|
671
|
-
?
|
|
672
|
-
:
|
|
759
|
+
? ClientRoutes & NewSpiceflow['_types']['ClientRoutes']
|
|
760
|
+
: ClientRoutes &
|
|
761
|
+
CreateClient<BasePath, NewSpiceflow['_types']['ClientRoutes']>,
|
|
762
|
+
RoutePaths | NewSpiceflow['_types']['RoutePaths']
|
|
673
763
|
>
|
|
674
764
|
use<const Schema extends RouteSchema>(
|
|
675
765
|
handler: MiddlewareHandler<Schema, Singleton>,
|
|
@@ -694,10 +784,10 @@ export class Spiceflow<
|
|
|
694
784
|
return this
|
|
695
785
|
}
|
|
696
786
|
|
|
697
|
-
async
|
|
787
|
+
handle = async (
|
|
698
788
|
request: Request,
|
|
699
789
|
{ state: customState }: { state?: Singleton['state'] } = {},
|
|
700
|
-
): Promise<Response> {
|
|
790
|
+
): Promise<Response> => {
|
|
701
791
|
let u = new URL(request.url, 'http://localhost')
|
|
702
792
|
const self = this
|
|
703
793
|
let path = u.pathname + u.search
|
|
@@ -719,7 +809,7 @@ export class Spiceflow<
|
|
|
719
809
|
} = route
|
|
720
810
|
const middlewares = appsInScope.flatMap((x) => x.middlewares)
|
|
721
811
|
|
|
722
|
-
let state = customState ||
|
|
812
|
+
let state = customState || copy(defaultState)
|
|
723
813
|
|
|
724
814
|
let content = route?.internalRoute?.hooks?.content
|
|
725
815
|
|
|
@@ -939,14 +1029,15 @@ export class Spiceflow<
|
|
|
939
1029
|
return this.handleForNode(req, res, context)
|
|
940
1030
|
}
|
|
941
1031
|
|
|
942
|
-
|
|
1032
|
+
handleForNode = (
|
|
943
1033
|
req: IncomingMessage,
|
|
944
1034
|
res: ServerResponse,
|
|
945
1035
|
context: { state?: Singleton['state'] } = {},
|
|
946
|
-
) {
|
|
1036
|
+
) => {
|
|
947
1037
|
return handleForNode(this, req, res, context)
|
|
948
1038
|
}
|
|
949
1039
|
|
|
1040
|
+
/* @deprecated */
|
|
950
1041
|
async listenForNode(port: number, hostname: string = '0.0.0.0') {
|
|
951
1042
|
if (typeof Bun !== 'undefined') {
|
|
952
1043
|
console.warn(
|
|
@@ -1081,6 +1172,28 @@ export class Spiceflow<
|
|
|
1081
1172
|
},
|
|
1082
1173
|
)
|
|
1083
1174
|
}
|
|
1175
|
+
|
|
1176
|
+
safePath<
|
|
1177
|
+
const Path extends RoutePaths,
|
|
1178
|
+
const Params extends ExtractParamsFromPath<Path>,
|
|
1179
|
+
>(path: Path, params: Params): string {
|
|
1180
|
+
let result = path as string
|
|
1181
|
+
|
|
1182
|
+
// First, handle all provided parameters
|
|
1183
|
+
if (params && typeof params === 'object') {
|
|
1184
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
1185
|
+
// Handle both required (:key) and optional (:key?) parameters
|
|
1186
|
+
const regex = new RegExp(`:${key}\\??`, 'g')
|
|
1187
|
+
result = result.replace(regex, String(value))
|
|
1188
|
+
})
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
// Then, handle any remaining optional parameters that weren't provided
|
|
1192
|
+
// Replace any remaining :param? with empty string (keeping trailing slash)
|
|
1193
|
+
result = result.replace(/:[\w-]+\?/g, '')
|
|
1194
|
+
|
|
1195
|
+
return result
|
|
1196
|
+
}
|
|
1084
1197
|
}
|
|
1085
1198
|
|
|
1086
1199
|
const METHODS = [
|
|
@@ -1209,7 +1322,7 @@ export async function turnHandlerResultIntoResponse(
|
|
|
1209
1322
|
})
|
|
1210
1323
|
}
|
|
1211
1324
|
|
|
1212
|
-
export type AnySpiceflow = Spiceflow<any, any, any, any, any, any>
|
|
1325
|
+
export type AnySpiceflow = Spiceflow<any, any, any, any, any, any, any>
|
|
1213
1326
|
|
|
1214
1327
|
export function isZodSchema(value: unknown): value is ZodType {
|
|
1215
1328
|
return (
|
|
@@ -1290,5 +1403,5 @@ function parseQuery(queryString: string) {
|
|
|
1290
1403
|
}
|
|
1291
1404
|
|
|
1292
1405
|
export function cloneDeep(x) {
|
|
1293
|
-
return
|
|
1406
|
+
return copy(x)
|
|
1294
1407
|
}
|
package/src/types.ts
CHANGED
|
@@ -7,13 +7,8 @@ import type { OpenAPIV3 } from 'openapi-types'
|
|
|
7
7
|
|
|
8
8
|
import { ZodTypeAny } from 'zod'
|
|
9
9
|
import type { Context, ErrorContext, MiddlewareContext } from './context.ts'
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
ParseError,
|
|
13
|
-
SPICEFLOW_RESPONSE,
|
|
14
|
-
ValidationError,
|
|
15
|
-
} from './error.ts'
|
|
16
|
-
import { Spiceflow } from './spiceflow.ts'
|
|
10
|
+
import { SPICEFLOW_RESPONSE, ValidationError } from './error.ts'
|
|
11
|
+
import { AnySpiceflow, Spiceflow } from './spiceflow.ts'
|
|
17
12
|
|
|
18
13
|
export type MaybeArray<T> = T | T[]
|
|
19
14
|
export type MaybePromise<T> = T | Promise<T>
|
|
@@ -154,6 +149,7 @@ export interface MetadataBase {
|
|
|
154
149
|
|
|
155
150
|
export type RouteSchema = {
|
|
156
151
|
body?: unknown
|
|
152
|
+
request?: unknown
|
|
157
153
|
query?: unknown
|
|
158
154
|
params?: unknown
|
|
159
155
|
response?: unknown
|
|
@@ -178,11 +174,18 @@ export type UnwrapSchema<
|
|
|
178
174
|
: Definitions
|
|
179
175
|
: unknown
|
|
180
176
|
|
|
177
|
+
export type GetRequestSchema<Schema extends InputSchema<any>> =
|
|
178
|
+
'request' extends keyof Schema
|
|
179
|
+
? Schema['request']
|
|
180
|
+
: 'body' extends keyof Schema
|
|
181
|
+
? Schema['body']
|
|
182
|
+
: undefined
|
|
183
|
+
|
|
181
184
|
export interface UnwrapRoute<
|
|
182
185
|
in out Schema extends InputSchema<any>,
|
|
183
186
|
in out Definitions extends DefinitionBase['type'] = {},
|
|
184
187
|
> {
|
|
185
|
-
|
|
188
|
+
request: UnwrapSchema<GetRequestSchema<Schema>, Definitions>
|
|
186
189
|
query: UnwrapSchema<Schema['query'], Definitions>
|
|
187
190
|
params: UnwrapSchema<Schema['params'], Definitions>
|
|
188
191
|
response: Schema['response'] extends TypeSchema | string
|
|
@@ -263,7 +266,11 @@ export type HTTPMethod =
|
|
|
263
266
|
| 'ALL'
|
|
264
267
|
|
|
265
268
|
export interface InputSchema<Name extends string = string> {
|
|
269
|
+
/**
|
|
270
|
+
* @deprecated The 'body' property is deprecated, use request instead.
|
|
271
|
+
*/
|
|
266
272
|
body?: TypeSchema | Name
|
|
273
|
+
request?: TypeSchema | Name
|
|
267
274
|
query?: TypeObject | Name
|
|
268
275
|
params?: TypeObject | Name
|
|
269
276
|
response?:
|
|
@@ -277,7 +284,9 @@ export interface MergeSchema<
|
|
|
277
284
|
in out A extends RouteSchema,
|
|
278
285
|
in out B extends RouteSchema,
|
|
279
286
|
> {
|
|
280
|
-
|
|
287
|
+
request: undefined extends GetRequestSchema<A>
|
|
288
|
+
? GetRequestSchema<B>
|
|
289
|
+
: GetRequestSchema<A>
|
|
281
290
|
query: undefined extends A['query'] ? B['query'] : A['query']
|
|
282
291
|
params: undefined extends A['params'] ? B['params'] : A['params']
|
|
283
292
|
response: {} extends A['response']
|
|
@@ -511,20 +520,7 @@ export type ErrorHandler<
|
|
|
511
520
|
// error: Readonly<NotFoundError>
|
|
512
521
|
// } & NeverKey<Singleton['state']>
|
|
513
522
|
// >
|
|
514
|
-
|
|
515
|
-
{
|
|
516
|
-
request: Request
|
|
517
|
-
code: 'PARSE'
|
|
518
|
-
error: Readonly<ParseError>
|
|
519
|
-
} & Singleton['state']
|
|
520
|
-
>
|
|
521
|
-
| Prettify<
|
|
522
|
-
{
|
|
523
|
-
request: Request
|
|
524
|
-
code: 'INTERNAL_SERVER_ERROR'
|
|
525
|
-
error: Readonly<InternalServerError>
|
|
526
|
-
} & Partial<Singleton['state']>
|
|
527
|
-
>
|
|
523
|
+
// Removed ParseError and InternalServerError from here
|
|
528
524
|
| Prettify<
|
|
529
525
|
{
|
|
530
526
|
[K in keyof T]: {
|
|
@@ -652,7 +648,7 @@ type _ComposeSpiceflowResponse<Response, Handle> = Prettify<
|
|
|
652
648
|
>
|
|
653
649
|
|
|
654
650
|
export type MergeSpiceflowInstances<
|
|
655
|
-
Instances extends
|
|
651
|
+
Instances extends AnySpiceflow[] = [],
|
|
656
652
|
Prefix extends string = '',
|
|
657
653
|
Scoped extends boolean = false,
|
|
658
654
|
Singleton extends SingletonBase = {
|
|
@@ -669,8 +665,8 @@ export type MergeSpiceflowInstances<
|
|
|
669
665
|
},
|
|
670
666
|
Routes extends RouteBase = {},
|
|
671
667
|
> = Instances extends [
|
|
672
|
-
infer Current extends
|
|
673
|
-
...infer Rest extends
|
|
668
|
+
infer Current extends AnySpiceflow,
|
|
669
|
+
...infer Rest extends AnySpiceflow[],
|
|
674
670
|
]
|
|
675
671
|
? Current['_types']['Scoped'] extends true
|
|
676
672
|
? MergeSpiceflowInstances<
|
|
@@ -691,8 +687,8 @@ export type MergeSpiceflowInstances<
|
|
|
691
687
|
Metadata & Current['_types']['Metadata'],
|
|
692
688
|
Routes &
|
|
693
689
|
(Prefix extends ``
|
|
694
|
-
? Current['
|
|
695
|
-
: AddPrefix<Prefix, Current['
|
|
690
|
+
? Current['_types']['ClientRoutes']
|
|
691
|
+
: AddPrefix<Prefix, Current['_types']['ClientRoutes']>)
|
|
696
692
|
>
|
|
697
693
|
: Spiceflow<
|
|
698
694
|
Prefix,
|
|
@@ -869,3 +865,17 @@ export type JoinPath<A extends string, B extends string> = `${A}${B extends '/'
|
|
|
869
865
|
|
|
870
866
|
export type PartialWithRequired<T, K extends keyof T> = Partial<Omit<T, K>> &
|
|
871
867
|
Pick<T, K>
|
|
868
|
+
|
|
869
|
+
export type GetPathsFromRoutes<Routes extends Record<string, unknown>> =
|
|
870
|
+
Routes extends Record<infer K, any> ? (K extends string ? K : never) : never
|
|
871
|
+
|
|
872
|
+
export type ExtractParamsFromPath<Path extends string> =
|
|
873
|
+
Path extends `${string}:${infer Param}/${infer Rest}`
|
|
874
|
+
? Param extends `${infer Name}?`
|
|
875
|
+
? { [K in Name]?: string } & ExtractParamsFromPath<`/${Rest}`>
|
|
876
|
+
: { [K in Param]: string } & ExtractParamsFromPath<`/${Rest}`>
|
|
877
|
+
: Path extends `${string}:${infer Param}`
|
|
878
|
+
? Param extends `${infer Name}?`
|
|
879
|
+
? { [K in Name]?: string }
|
|
880
|
+
: { [K in Param]: string }
|
|
881
|
+
: {}
|