1- import type ts from 'typescript' ;
2-
31import { operationResponsesMap } from '~/ir/operation' ;
42import { hasParameterGroupObjectRequired } from '~/ir/parameter' ;
53import type { IR } from '~/ir/types' ;
6- import { type Property , tsc } from '~/tsc ' ;
4+ import { $ } from '~/ts-dsl ' ;
75
86import type { FastifyPlugin } from './types' ;
97
@@ -13,8 +11,8 @@ const operationToRouteHandler = ({
1311} : {
1412 operation : IR . OperationObject ;
1513 plugin : FastifyPlugin [ 'Instance' ] ;
16- } ) : Property | undefined => {
17- const properties : Array < Property > = [ ] ;
14+ } ) => {
15+ const type = $ . type . object ( ) ;
1816
1917 const symbolDataType = plugin . querySymbol ( {
2018 category : 'type' ,
@@ -25,49 +23,49 @@ const operationToRouteHandler = ({
2523 } ) ;
2624 if ( symbolDataType ) {
2725 if ( operation . body ) {
28- properties . push ( {
29- isRequired : operation . body . required ,
30- name : 'Body' ,
31- type : `${ symbolDataType . placeholder } ['body']` ,
32- } ) ;
26+ type . prop ( 'Body' , ( p ) =>
27+ p
28+ . optional ( ! operation . body ! . required )
29+ . type ( `${ symbolDataType . placeholder } ['body']` ) ,
30+ ) ;
3331 }
3432
3533 if ( operation . parameters ) {
3634 if ( operation . parameters . header ) {
37- properties . push ( {
38- isRequired : hasParameterGroupObjectRequired (
39- operation . parameters . header ,
40- ) ,
41- name : 'Headers' ,
42- type : `${ symbolDataType . placeholder } ['headers']` ,
43- } ) ;
35+ type . prop ( 'Headers' , ( p ) =>
36+ p
37+ . optional (
38+ ! hasParameterGroupObjectRequired ( operation . parameters ! . header ) ,
39+ )
40+ . type ( `${ symbolDataType . placeholder } ['headers']` ) ,
41+ ) ;
4442 }
4543
4644 if ( operation . parameters . path ) {
47- properties . push ( {
48- isRequired : hasParameterGroupObjectRequired (
49- operation . parameters . path ,
50- ) ,
51- name : 'Params' ,
52- type : `${ symbolDataType . placeholder } ['path']` ,
53- } ) ;
45+ type . prop ( 'Params' , ( p ) =>
46+ p
47+ . optional (
48+ ! hasParameterGroupObjectRequired ( operation . parameters ! . path ) ,
49+ )
50+ . type ( `${ symbolDataType . placeholder } ['path']` ) ,
51+ ) ;
5452 }
5553
5654 if ( operation . parameters . query ) {
57- properties . push ( {
58- isRequired : hasParameterGroupObjectRequired (
59- operation . parameters . query ,
60- ) ,
61- name : 'Querystring' ,
62- type : `${ symbolDataType . placeholder } ['query']` ,
63- } ) ;
55+ type . prop ( 'Querystring' , ( p ) =>
56+ p
57+ . optional (
58+ ! hasParameterGroupObjectRequired ( operation . parameters ! . query ) ,
59+ )
60+ . type ( `${ symbolDataType . placeholder } ['query']` ) ,
61+ ) ;
6462 }
6563 }
6664 }
6765
6866 const { errors, responses } = operationResponsesMap ( operation ) ;
6967
70- let errorsTypeReference : ts . TypeReferenceNode | undefined = undefined ;
68+ let errorsTypeReference : ReturnType < typeof $ . type > | undefined ;
7169 const symbolErrorType = plugin . querySymbol ( {
7270 category : 'type' ,
7371 resource : 'operation' ,
@@ -79,25 +77,19 @@ const operationToRouteHandler = ({
7977 if ( keys . length ) {
8078 const hasDefaultResponse = keys . includes ( 'default' ) ;
8179 if ( ! hasDefaultResponse ) {
82- errorsTypeReference = tsc . typeReferenceNode ( {
83- typeName : symbolErrorType . placeholder ,
84- } ) ;
80+ errorsTypeReference = $ . type ( symbolErrorType . placeholder ) ;
8581 } else if ( keys . length > 1 ) {
86- const errorsType = tsc . typeReferenceNode ( {
87- typeName : symbolErrorType . placeholder ,
88- } ) ;
89- const defaultType = tsc . literalTypeNode ( {
90- literal : tsc . stringLiteral ( { text : 'default' } ) ,
91- } ) ;
92- errorsTypeReference = tsc . typeReferenceNode ( {
93- typeArguments : [ errorsType , defaultType ] ,
94- typeName : 'Omit' ,
95- } ) ;
82+ errorsTypeReference = $ . type ( 'Omit' , ( t ) =>
83+ t . generics (
84+ $ . type ( symbolErrorType . placeholder ) ,
85+ $ . type . literal ( 'default' ) ,
86+ ) ,
87+ ) ;
9688 }
9789 }
9890 }
9991
100- let responsesTypeReference : ts . TypeReferenceNode | undefined = undefined ;
92+ let responsesTypeReference : ReturnType < typeof $ . type > | undefined = undefined ;
10193 const symbolResponseType = plugin . querySymbol ( {
10294 category : 'type' ,
10395 resource : 'operation' ,
@@ -109,37 +101,26 @@ const operationToRouteHandler = ({
109101 if ( keys . length ) {
110102 const hasDefaultResponse = keys . includes ( 'default' ) ;
111103 if ( ! hasDefaultResponse ) {
112- responsesTypeReference = tsc . typeReferenceNode ( {
113- typeName : symbolResponseType . placeholder ,
114- } ) ;
104+ responsesTypeReference = $ . type ( symbolResponseType . placeholder ) ;
115105 } else if ( keys . length > 1 ) {
116- const responsesType = tsc . typeReferenceNode ( {
117- typeName : symbolResponseType . placeholder ,
118- } ) ;
119- const defaultType = tsc . literalTypeNode ( {
120- literal : tsc . stringLiteral ( { text : 'default' } ) ,
121- } ) ;
122- responsesTypeReference = tsc . typeReferenceNode ( {
123- typeArguments : [ responsesType , defaultType ] ,
124- typeName : 'Omit' ,
125- } ) ;
106+ responsesTypeReference = $ . type ( 'Omit' , ( t ) =>
107+ t . generics (
108+ $ . type ( symbolResponseType . placeholder ) ,
109+ $ . type . literal ( 'default' ) ,
110+ ) ,
111+ ) ;
126112 }
127113 }
128114 }
129115
130116 const replyTypes = [ errorsTypeReference , responsesTypeReference ] . filter (
131- Boolean ,
117+ ( t ) : t is ReturnType < typeof $ . type > => t !== undefined ,
132118 ) ;
133119 if ( replyTypes . length ) {
134- properties . push ( {
135- name : 'Reply' ,
136- type : tsc . typeIntersectionNode ( {
137- types : replyTypes ,
138- } ) ,
139- } ) ;
120+ type . prop ( 'Reply' , ( p ) => p . type ( $ . type . and ( ...replyTypes ) ) ) ;
140121 }
141122
142- if ( ! properties . length ) {
123+ if ( type . isEmpty ) {
143124 return ;
144125 }
145126
@@ -148,19 +129,10 @@ const operationToRouteHandler = ({
148129 resource : 'route-handler' ,
149130 tool : 'fastify' ,
150131 } ) ;
151- const routeHandler : Property = {
132+ return {
152133 name : operation . id ,
153- type : tsc . typeReferenceNode ( {
154- typeArguments : [
155- tsc . typeInterfaceNode ( {
156- properties,
157- useLegacyResolution : false ,
158- } ) ,
159- ] ,
160- typeName : symbolRouteHandler . placeholder ,
161- } ) ,
134+ type : $ . type ( symbolRouteHandler . placeholder , ( t ) => t . generic ( type ) ) ,
162135 } ;
163- return routeHandler ;
164136} ;
165137
166138export const handler : FastifyPlugin [ 'Handler' ] = ( { plugin } ) => {
@@ -181,28 +153,24 @@ export const handler: FastifyPlugin['Handler'] = ({ plugin }) => {
181153 name : 'RouteHandlers' ,
182154 } ) ;
183155
184- const routeHandlers : Array < Property > = [ ] ;
156+ const type = $ . type . object ( ) ;
185157
186158 plugin . forEach (
187159 'operation' ,
188160 ( { operation } ) => {
189161 const routeHandler = operationToRouteHandler ( { operation, plugin } ) ;
190162 if ( routeHandler ) {
191- routeHandlers . push ( routeHandler ) ;
163+ type . prop ( routeHandler . name , ( p ) => p . type ( routeHandler . type ) ) ;
192164 }
193165 } ,
194166 {
195167 order : 'declarations' ,
196168 } ,
197169 ) ;
198170
199- const node = tsc . typeAliasDeclaration ( {
200- exportType : symbolRouteHandlers . exported ,
201- name : symbolRouteHandlers . placeholder ,
202- type : tsc . typeInterfaceNode ( {
203- properties : routeHandlers ,
204- useLegacyResolution : false ,
205- } ) ,
206- } ) ;
171+ const node = $ . type
172+ . alias ( symbolRouteHandlers . placeholder )
173+ . export ( symbolRouteHandlers . exported )
174+ . type ( type ) ;
207175 plugin . setSymbolValue ( symbolRouteHandlers , node ) ;
208176} ;
0 commit comments