1
1
import { IHttpContent , IHttpOperationResponse , IMediaTypeContent } from '@stoplight/types' ;
2
2
// @ts -ignore
3
3
import * as accepts from 'accepts' ;
4
+ import { filter , findFirst , head , sort } from 'fp-ts/lib/Array' ;
5
+ import { alt , map , Option } from 'fp-ts/lib/Option' ;
6
+ import { ord , ordNumber } from 'fp-ts/lib/Ord' ;
7
+ import { pipe } from 'fp-ts/lib/pipeable' ;
4
8
import { ContentExample , NonEmptyArray , PickRequired } from '../../' ;
5
9
6
10
export type IWithExampleMediaContent = IMediaTypeContent & { examples : NonEmptyArray < ContentExample > } ;
@@ -20,48 +24,69 @@ export function hasContents(v: IHttpOperationResponse): v is PickRequired<IHttpO
20
24
export function findBestHttpContentByMediaType (
21
25
response : PickRequired < IHttpOperationResponse , 'contents' > ,
22
26
mediaType : string [ ] ,
23
- ) : IMediaTypeContent | undefined {
27
+ ) : Option < IMediaTypeContent > {
24
28
const bestType = accepts ( {
25
29
headers : {
26
30
accept : mediaType . join ( ',' ) ,
27
31
} ,
28
32
} ) . type ( response . contents . map ( c => c . mediaType ) ) ;
29
33
30
- return response . contents . find ( content => content . mediaType === bestType ) ;
34
+ return pipe (
35
+ response . contents ,
36
+ findFirst ( content => content . mediaType === bestType ) ,
37
+ ) ;
31
38
}
32
39
33
40
export function findDefaultContentType (
34
41
response : PickRequired < IHttpOperationResponse , 'contents' > ,
35
- ) : IMediaTypeContent | undefined {
36
- return response . contents . find ( content => content . mediaType === '*/*' ) ;
42
+ ) : Option < IMediaTypeContent > {
43
+ return pipe (
44
+ response . contents ,
45
+ findFirst ( content => content . mediaType === '*/*' ) ,
46
+ ) ;
37
47
}
38
48
39
- export function findLowest2xx ( httpResponses : IHttpOperationResponse [ ] ) : IHttpOperationResponse | undefined {
40
- const generic2xxResponse =
41
- findResponseByStatusCode ( httpResponses , '2XX' ) || createResponseFromDefault ( httpResponses , '200' ) ;
42
- const sorted2xxResponses = httpResponses
43
- . filter ( response => response . code . match ( / 2 \d \d / ) )
44
- . sort ( ( a : IHttpOperationResponse , b : IHttpOperationResponse ) => Number ( a . code ) - Number ( b . code ) ) ;
49
+ const byResponseCode = ord . contramap < number , IHttpOperationResponse > ( ordNumber , response => parseInt ( response . code ) ) ;
45
50
46
- return sorted2xxResponses [ 0 ] || generic2xxResponse ;
51
+ export function findLowest2xx ( httpResponses : IHttpOperationResponse [ ] ) : Option < IHttpOperationResponse > {
52
+ const generic2xxResponse = ( ) =>
53
+ pipe (
54
+ findResponseByStatusCode ( httpResponses , '2XX' ) ,
55
+ alt ( ( ) => createResponseFromDefault ( httpResponses , '200' ) ) ,
56
+ ) ;
57
+
58
+ const first2xxResponse = pipe (
59
+ httpResponses ,
60
+ filter ( response => / 2 \d \d / . test ( response . code ) ) ,
61
+ sort ( byResponseCode ) ,
62
+ head ,
63
+ ) ;
64
+
65
+ return pipe (
66
+ first2xxResponse ,
67
+ alt ( generic2xxResponse ) ,
68
+ ) ;
47
69
}
48
70
49
71
export function findResponseByStatusCode (
50
72
responses : IHttpOperationResponse [ ] ,
51
73
statusCode : string ,
52
- ) : IHttpOperationResponse | undefined {
53
- return responses . find ( response => response . code . toLowerCase ( ) === statusCode . toLowerCase ( ) ) ;
74
+ ) : Option < IHttpOperationResponse > {
75
+ return pipe (
76
+ responses ,
77
+ findFirst ( response => response . code . toLowerCase ( ) === statusCode . toLowerCase ( ) ) ,
78
+ ) ;
54
79
}
55
80
56
81
export function createResponseFromDefault (
57
82
responses : IHttpOperationResponse [ ] ,
58
83
statusCode : string ,
59
- ) : IHttpOperationResponse | undefined {
60
- const defaultResponse = responses . find ( response => response . code === 'default' ) ;
61
- if ( defaultResponse ) {
62
- return Object . assign ( { } , defaultResponse , { code : statusCode } ) ;
63
- }
64
- return undefined ;
84
+ ) : Option < IHttpOperationResponse > {
85
+ return pipe (
86
+ responses ,
87
+ findFirst ( response => response . code === 'default' ) ,
88
+ map ( response => Object . assign ( { } , response , { code : statusCode } ) ) ,
89
+ ) ;
65
90
}
66
91
67
92
export function contentHasExamples ( content : IMediaTypeContent ) : content is IWithExampleMediaContent {
0 commit comments