@@ -21,46 +21,59 @@ export type { ResponseEncoder } from './response';
21
21
const isHttpVerb = ( verb : string ) : verb is 'get' | 'put' | 'post' | 'delete' =>
22
22
verb === 'get' || verb === 'put' || verb === 'post' || verb === 'delete' ;
23
23
24
- export const createServerWithResponseEncoder =
25
- ( encoder : ResponseEncoder ) =>
26
- < Spec extends ApiSpec > (
27
- spec : ApiSpec ,
28
- configureExpressApplication : ( app : express . Application ) => {
29
- [ ApiName in keyof Spec ] : {
30
- [ Method in keyof Spec [ ApiName ] ] : RouteHandler < Spec [ ApiName ] [ Method ] > ;
31
- } ;
32
- } ,
33
- ) => {
34
- const app : express . Application = express ( ) ;
35
- const routes = configureExpressApplication ( app ) ;
36
-
37
- const router = express . Router ( ) ;
38
- for ( const apiName of Object . keys ( spec ) ) {
39
- const resource = spec [ apiName ] as Spec [ string ] ;
40
- for ( const method of Object . keys ( resource ) ) {
41
- if ( ! isHttpVerb ( method ) ) {
42
- continue ;
43
- }
44
- const httpRoute : HttpRoute = resource [ method ] ! ;
45
- const routeHandler = routes [ apiName ] ! [ method ] ! ;
46
- const expressRouteHandler = decodeRequestAndEncodeResponse (
47
- apiName ,
48
- httpRoute ,
49
- // FIXME: TS is complaining that `routeHandler` is not necessarily guaranteed to be a
50
- // `ServiceFunction`, because subtypes of Spec[string][string] can have arbitrary extra keys.
51
- getServiceFunction ( routeHandler as any ) ,
52
- encoder ,
53
- ) ;
54
- const handlers = [ ...getMiddleware ( routeHandler ) , expressRouteHandler ] ;
24
+ type CreateRouterProps < Spec extends ApiSpec > = {
25
+ spec : Spec ;
26
+ routeHandlers : {
27
+ [ ApiName in keyof Spec ] : {
28
+ [ Method in keyof Spec [ ApiName ] ] : RouteHandler < Spec [ ApiName ] [ Method ] > ;
29
+ } ;
30
+ } ;
31
+ encoder ?: ResponseEncoder ;
32
+ } ;
55
33
56
- const expressPath = apiTsPathToExpress ( httpRoute . path ) ;
57
- router [ method ] ( expressPath , handlers ) ;
34
+ export function routerForApiSpec < Spec extends ApiSpec > ( {
35
+ spec,
36
+ routeHandlers,
37
+ encoder = defaultResponseEncoder ,
38
+ } : CreateRouterProps < Spec > ) {
39
+ const router = express . Router ( ) ;
40
+ for ( const apiName of Object . keys ( spec ) ) {
41
+ const resource = spec [ apiName ] as Spec [ string ] ;
42
+ for ( const method of Object . keys ( resource ) ) {
43
+ if ( ! isHttpVerb ( method ) ) {
44
+ continue ;
58
45
}
59
- }
46
+ const httpRoute : HttpRoute = resource [ method ] ! ;
47
+ const routeHandler = routeHandlers [ apiName ] ! [ method ] ! ;
48
+ const expressRouteHandler = decodeRequestAndEncodeResponse (
49
+ apiName ,
50
+ httpRoute ,
51
+ // FIXME: TS is complaining that `routeHandler` is not necessarily guaranteed to be a
52
+ // `ServiceFunction`, because subtypes of Spec[string][string] can have arbitrary extra keys.
53
+ getServiceFunction ( routeHandler as any ) ,
54
+ encoder ,
55
+ ) ;
56
+ const handlers = [ ...getMiddleware ( routeHandler ) , expressRouteHandler ] ;
60
57
61
- app . use ( router ) ;
58
+ const expressPath = apiTsPathToExpress ( httpRoute . path ) ;
59
+ router [ method ] ( expressPath , handlers ) ;
60
+ }
61
+ }
62
62
63
- return app ;
64
- } ;
63
+ return router ;
64
+ }
65
65
66
- export const createServer = createServerWithResponseEncoder ( defaultResponseEncoder ) ;
66
+ export const createServer = < Spec extends ApiSpec > (
67
+ spec : Spec ,
68
+ configureExpressApplication : ( app : express . Application ) => {
69
+ [ ApiName in keyof Spec ] : {
70
+ [ Method in keyof Spec [ ApiName ] ] : RouteHandler < Spec [ ApiName ] [ Method ] > ;
71
+ } ;
72
+ } ,
73
+ ) => {
74
+ const app = express ( ) ;
75
+ const routeHandlers = configureExpressApplication ( app ) ;
76
+ const router = routerForApiSpec ( { spec, routeHandlers } ) ;
77
+ app . use ( router ) ;
78
+ return app ;
79
+ } ;
0 commit comments