@outfoxx/sunday 1.0.9 → 1.0.10
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/LICENSE.txt +203 -0
- package/README.md +36 -2
- package/build/date-time-types.d.ts +35 -0
- package/build/date-time-types.js +699 -0
- package/build/date-time-types.js.map +1 -0
- package/build/event-parser.d.ts +17 -0
- package/build/event-parser.js +151 -0
- package/build/event-parser.js.map +1 -0
- package/build/fetch-event-source.d.ts +66 -0
- package/build/fetch-event-source.js +365 -0
- package/build/fetch-event-source.js.map +1 -0
- package/build/fetch-request-factory.d.ts +32 -0
- package/build/fetch-request-factory.js +316 -0
- package/build/fetch-request-factory.js.map +1 -0
- package/build/fetch.d.ts +9 -0
- package/build/fetch.js +140 -0
- package/build/fetch.js.map +1 -0
- package/build/header-parameters.d.ts +3 -0
- package/build/header-parameters.js +82 -0
- package/build/header-parameters.js.map +1 -0
- package/build/index.d.ts +26 -0
- package/build/index.js +41 -0
- package/build/index.js.map +1 -0
- package/{dist → build}/logger.d.ts +9 -0
- package/build/logger.js +36 -0
- package/build/logger.js.map +1 -0
- package/build/media-type-codecs/any-text-decoder.d.ts +7 -0
- package/build/media-type-codecs/any-text-decoder.js +29 -0
- package/build/media-type-codecs/any-text-decoder.js.map +1 -0
- package/build/media-type-codecs/any-text-encoder.d.ts +6 -0
- package/build/media-type-codecs/any-text-encoder.js +27 -0
- package/build/media-type-codecs/any-text-encoder.js.map +1 -0
- package/build/media-type-codecs/binary-decoder.d.ts +7 -0
- package/build/media-type-codecs/binary-decoder.js +33 -0
- package/build/media-type-codecs/binary-decoder.js.map +1 -0
- package/build/media-type-codecs/binary-encoder.d.ts +6 -0
- package/build/media-type-codecs/binary-encoder.js +30 -0
- package/build/media-type-codecs/binary-encoder.js.map +1 -0
- package/build/media-type-codecs/cbor-decoder.d.ts +13 -0
- package/build/media-type-codecs/cbor-decoder.js +38 -0
- package/build/media-type-codecs/cbor-decoder.js.map +1 -0
- package/build/media-type-codecs/cbor-encoder.d.ts +12 -0
- package/build/media-type-codecs/cbor-encoder.js +36 -0
- package/build/media-type-codecs/cbor-encoder.js.map +1 -0
- package/build/media-type-codecs/cbor-tags.d.ts +6 -0
- package/build/media-type-codecs/cbor-tags.js +20 -0
- package/build/media-type-codecs/cbor-tags.js.map +1 -0
- package/build/media-type-codecs/default-policies.d.ts +3 -0
- package/build/media-type-codecs/default-policies.js +33 -0
- package/build/media-type-codecs/default-policies.js.map +1 -0
- package/build/media-type-codecs/json-decoder.d.ts +14 -0
- package/build/media-type-codecs/json-decoder.js +40 -0
- package/build/media-type-codecs/json-decoder.js.map +1 -0
- package/build/media-type-codecs/json-encoder.d.ts +13 -0
- package/build/media-type-codecs/json-encoder.js +43 -0
- package/build/media-type-codecs/json-encoder.js.map +1 -0
- package/build/media-type-codecs/media-type-decoder.d.ts +14 -0
- package/build/media-type-codecs/media-type-decoder.js +18 -0
- package/build/media-type-codecs/media-type-decoder.js.map +1 -0
- package/build/media-type-codecs/media-type-decoders.d.ts +16 -0
- package/build/media-type-codecs/media-type-decoders.js +63 -0
- package/build/media-type-codecs/media-type-decoders.js.map +1 -0
- package/build/media-type-codecs/media-type-encoder.d.ts +12 -0
- package/build/media-type-codecs/media-type-encoder.js +22 -0
- package/build/media-type-codecs/media-type-encoder.js.map +1 -0
- package/build/media-type-codecs/media-type-encoders.d.ts +16 -0
- package/build/media-type-codecs/media-type-encoders.js +65 -0
- package/build/media-type-codecs/media-type-encoders.js.map +1 -0
- package/build/media-type-codecs/www-form-url-encoder.d.ts +31 -0
- package/build/media-type-codecs/www-form-url-encoder.js +281 -0
- package/build/media-type-codecs/www-form-url-encoder.js.map +1 -0
- package/build/media-type.d.ts +94 -0
- package/build/media-type.js +305 -0
- package/build/media-type.js.map +1 -0
- package/build/problem.d.ts +35 -0
- package/build/problem.js +122 -0
- package/build/problem.js.map +1 -0
- package/build/request-adapters.d.ts +23 -0
- package/build/request-adapters.js +53 -0
- package/build/request-adapters.js.map +1 -0
- package/build/request-factory.d.ts +39 -0
- package/build/request-factory.js +15 -0
- package/build/request-factory.js.map +1 -0
- package/build/result-response.d.ts +4 -0
- package/build/result-response.js +15 -0
- package/build/result-response.js.map +1 -0
- package/build/schema-builtins.d.ts +21 -0
- package/build/schema-builtins.js +201 -0
- package/build/schema-builtins.js.map +1 -0
- package/build/schema-policy.d.ts +31 -0
- package/build/schema-policy.js +41 -0
- package/build/schema-policy.js.map +1 -0
- package/build/schema-runtime.d.ts +25 -0
- package/build/schema-runtime.js +77 -0
- package/build/schema-runtime.js.map +1 -0
- package/build/sunday-error.d.ts +10 -0
- package/build/sunday-error.js +36 -0
- package/build/sunday-error.js.map +1 -0
- package/build/url-template.js +33 -0
- package/build/url-template.js.map +1 -0
- package/build/util/async-iterables.d.ts +15 -0
- package/build/util/async-iterables.js +179 -0
- package/build/util/async-iterables.js.map +1 -0
- package/build/util/errors.d.ts +2 -0
- package/build/util/errors.js +65 -0
- package/build/util/errors.js.map +1 -0
- package/build/util/nullify.d.ts +5 -0
- package/build/util/nullify.js +37 -0
- package/build/util/nullify.js.map +1 -0
- package/build/util/numbers.d.ts +11 -0
- package/build/util/numbers.js +41 -0
- package/build/util/numbers.js.map +1 -0
- package/build/util/subscriptions.d.ts +16 -0
- package/build/util/subscriptions.js +78 -0
- package/build/util/subscriptions.js.map +1 -0
- package/build/util/unknowns.d.ts +2 -0
- package/build/util/unknowns.js +23 -0
- package/build/util/unknowns.js.map +1 -0
- package/package.json +72 -49
- package/dist/any-type.d.ts +0 -2
- package/dist/any-type.js +0 -2
- package/dist/any-type.js.map +0 -1
- package/dist/binary-decoder.d.ts +0 -6
- package/dist/binary-decoder.js +0 -16
- package/dist/binary-decoder.js.map +0 -1
- package/dist/binary-encoder.d.ts +0 -5
- package/dist/binary-encoder.js +0 -13
- package/dist/binary-encoder.js.map +0 -1
- package/dist/cbor-decoder.d.ts +0 -15
- package/dist/cbor-decoder.js +0 -126
- package/dist/cbor-decoder.js.map +0 -1
- package/dist/cbor-encoder.d.ts +0 -29
- package/dist/cbor-encoder.js +0 -81
- package/dist/cbor-encoder.js.map +0 -1
- package/dist/cbor-tags.d.ts +0 -3
- package/dist/cbor-tags.js +0 -4
- package/dist/cbor-tags.js.map +0 -1
- package/dist/class-type.d.ts +0 -2
- package/dist/class-type.js +0 -2
- package/dist/class-type.js.map +0 -1
- package/dist/date-time-types.d.ts +0 -7
- package/dist/date-time-types.js +0 -5
- package/dist/date-time-types.js.map +0 -1
- package/dist/fetch-event-source.d.ts +0 -52
- package/dist/fetch-event-source.js +0 -271
- package/dist/fetch-event-source.js.map +0 -1
- package/dist/fetch-request-factory.d.ts +0 -26
- package/dist/fetch-request-factory.js +0 -125
- package/dist/fetch-request-factory.js.map +0 -1
- package/dist/fetch.d.ts +0 -1
- package/dist/fetch.js +0 -19
- package/dist/fetch.js.map +0 -1
- package/dist/http-error.d.ts +0 -10
- package/dist/http-error.js +0 -45
- package/dist/http-error.js.map +0 -1
- package/dist/index.d.ts +0 -25
- package/dist/index.js +0 -26
- package/dist/index.js.map +0 -1
- package/dist/json-decoder.d.ts +0 -31
- package/dist/json-decoder.js +0 -139
- package/dist/json-decoder.js.map +0 -1
- package/dist/json-encoder.d.ts +0 -35
- package/dist/json-encoder.js +0 -134
- package/dist/json-encoder.js.map +0 -1
- package/dist/logger.js +0 -2
- package/dist/logger.js.map +0 -1
- package/dist/media-type-decoder.d.ts +0 -4
- package/dist/media-type-decoder.js +0 -2
- package/dist/media-type-decoder.js.map +0 -1
- package/dist/media-type-decoders.d.ts +0 -17
- package/dist/media-type-decoders.js +0 -40
- package/dist/media-type-decoders.js.map +0 -1
- package/dist/media-type-encoder.d.ts +0 -8
- package/dist/media-type-encoder.js +0 -6
- package/dist/media-type-encoder.js.map +0 -1
- package/dist/media-type-encoders.d.ts +0 -17
- package/dist/media-type-encoders.js +0 -42
- package/dist/media-type-encoders.js.map +0 -1
- package/dist/media-type.d.ts +0 -14
- package/dist/media-type.js +0 -18
- package/dist/media-type.js.map +0 -1
- package/dist/problem.d.ts +0 -16
- package/dist/problem.js +0 -11
- package/dist/problem.js.map +0 -1
- package/dist/request-factory.d.ts +0 -38
- package/dist/request-factory.js +0 -2
- package/dist/request-factory.js.map +0 -1
- package/dist/url-encoder.d.ts +0 -59
- package/dist/url-encoder.js +0 -141
- package/dist/url-encoder.js.map +0 -1
- package/dist/url-template.js +0 -18
- package/dist/url-template.js.map +0 -1
- package/dist/util/base64.d.ts +0 -5
- package/dist/util/base64.js +0 -64
- package/dist/util/base64.js.map +0 -1
- package/dist/util/hex.d.ts +0 -4
- package/dist/util/hex.js +0 -18
- package/dist/util/hex.js.map +0 -1
- package/dist/util/rxjs.d.ts +0 -2
- package/dist/util/rxjs.js +0 -14
- package/dist/util/rxjs.js.map +0 -1
- package/dist/util/stream-rxjs.d.ts +0 -2
- package/dist/util/stream-rxjs.js +0 -26
- package/dist/util/stream-rxjs.js.map +0 -1
- package/src/any-type.ts +0 -4
- package/src/binary-decoder.ts +0 -24
- package/src/binary-encoder.ts +0 -19
- package/src/cbor-decoder.ts +0 -148
- package/src/cbor-encoder.ts +0 -95
- package/src/cbor-tags.ts +0 -3
- package/src/class-type.ts +0 -3
- package/src/date-time-types.ts +0 -10
- package/src/fetch-event-source.ts +0 -387
- package/src/fetch-request-factory.ts +0 -225
- package/src/fetch.ts +0 -30
- package/src/http-error.ts +0 -55
- package/src/index.ts +0 -26
- package/src/json-decoder.ts +0 -164
- package/src/json-encoder.ts +0 -162
- package/src/logger.ts +0 -8
- package/src/media-type-decoder.ts +0 -5
- package/src/media-type-decoders.ts +0 -59
- package/src/media-type-encoder.ts +0 -16
- package/src/media-type-encoders.ts +0 -61
- package/src/media-type.ts +0 -25
- package/src/problem.ts +0 -25
- package/src/request-factory.ts +0 -76
- package/src/url-encoder.ts +0 -173
- package/src/url-template.ts +0 -21
- package/src/util/base64.ts +0 -77
- package/src/util/hex.ts +0 -15
- package/src/util/rxjs.ts +0 -18
- package/src/util/stream-rxjs.ts +0 -28
- /package/{dist → build}/url-template.d.ts +0 -0
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import { Observable, of, Subscriber } from 'rxjs';
|
|
2
|
-
import { mapTo, switchMap } from 'rxjs/operators';
|
|
3
|
-
import { AnyType } from './any-type';
|
|
4
|
-
import { validate } from './fetch';
|
|
5
|
-
import { FetchEventSource } from './fetch-event-source';
|
|
6
|
-
import { HttpError } from './http-error';
|
|
7
|
-
import { JSONDecoder } from './json-decoder';
|
|
8
|
-
import { Logger } from './logger';
|
|
9
|
-
import { mediaType, MediaType } from './media-type';
|
|
10
|
-
import { MediaTypeDecoders } from './media-type-decoders';
|
|
11
|
-
import { isURLQueryParamsEncoder } from './media-type-encoder';
|
|
12
|
-
import { MediaTypeEncoders } from './media-type-encoders';
|
|
13
|
-
import {
|
|
14
|
-
EventTypes,
|
|
15
|
-
ExtEventSource,
|
|
16
|
-
RequestAdapter,
|
|
17
|
-
RequestFactory,
|
|
18
|
-
RequestSpec,
|
|
19
|
-
} from './request-factory';
|
|
20
|
-
import { URLTemplate } from './url-template';
|
|
21
|
-
|
|
22
|
-
export class FetchRequestFactory implements RequestFactory {
|
|
23
|
-
public baseUrl: URLTemplate;
|
|
24
|
-
public adapter?: RequestAdapter;
|
|
25
|
-
public mediaTypeEncoders: MediaTypeEncoders;
|
|
26
|
-
public mediaTypeDecoders: MediaTypeDecoders;
|
|
27
|
-
public logger?: Logger;
|
|
28
|
-
|
|
29
|
-
constructor(
|
|
30
|
-
baseUrl: string | URLTemplate,
|
|
31
|
-
options?: {
|
|
32
|
-
adapter?: RequestAdapter;
|
|
33
|
-
mediaTypeEncoders?: MediaTypeEncoders;
|
|
34
|
-
mediaTypeDecoders?: MediaTypeDecoders;
|
|
35
|
-
logger?: Logger;
|
|
36
|
-
}
|
|
37
|
-
) {
|
|
38
|
-
this.baseUrl =
|
|
39
|
-
typeof baseUrl === 'string' ? new URLTemplate(baseUrl) : baseUrl;
|
|
40
|
-
this.adapter = options?.adapter;
|
|
41
|
-
this.mediaTypeEncoders =
|
|
42
|
-
options?.mediaTypeEncoders ?? MediaTypeEncoders.DEFAULT;
|
|
43
|
-
this.mediaTypeDecoders =
|
|
44
|
-
options?.mediaTypeDecoders ?? MediaTypeDecoders.DEFAULT;
|
|
45
|
-
this.logger = options?.logger ?? console;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
request(
|
|
49
|
-
requestSpec: RequestSpec<unknown>,
|
|
50
|
-
requestInit?: RequestInit
|
|
51
|
-
): Observable<Request> {
|
|
52
|
-
//
|
|
53
|
-
const url = this.baseUrl.complete(
|
|
54
|
-
requestSpec.pathTemplate,
|
|
55
|
-
requestSpec.pathParameters ?? {}
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
if (requestSpec.queryParameters) {
|
|
59
|
-
const encoder = this.mediaTypeEncoders.find(
|
|
60
|
-
MediaType.WWW_URL_FORM_ENCODED
|
|
61
|
-
);
|
|
62
|
-
if (!isURLQueryParamsEncoder(encoder)) {
|
|
63
|
-
throw Error(
|
|
64
|
-
`MediaTypeEncoder for ${MediaType.WWW_URL_FORM_ENCODED} must be an instance of URLEncoder`
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
url.search = `?${encoder.encodeQueryString(requestSpec.queryParameters)}`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const headers = new Headers(requestSpec.headers);
|
|
71
|
-
|
|
72
|
-
// Determine & add accept header
|
|
73
|
-
const supportedAcceptTypes = requestSpec.acceptTypes?.filter((type) =>
|
|
74
|
-
this.mediaTypeDecoders.supports(type)
|
|
75
|
-
);
|
|
76
|
-
if (supportedAcceptTypes?.length) {
|
|
77
|
-
const accept = supportedAcceptTypes.join(' , ');
|
|
78
|
-
|
|
79
|
-
headers.set('accept', accept);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Determine content type
|
|
83
|
-
const contentType = requestSpec.contentTypes?.find((type) =>
|
|
84
|
-
this.mediaTypeEncoders.supports(type)
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
// If matched, add content type (even if body is nil, to match any expected server requirements)
|
|
88
|
-
if (contentType) {
|
|
89
|
-
headers.set('content-type', contentType);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Encode & add body data
|
|
93
|
-
let body: BodyInit | undefined;
|
|
94
|
-
if (requestSpec.body) {
|
|
95
|
-
if (!contentType) {
|
|
96
|
-
throw Error('Unsupported content-type for request body');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
body = this.mediaTypeEncoders
|
|
100
|
-
.find(contentType)
|
|
101
|
-
.encode(requestSpec.body, requestSpec.bodyType);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const init: RequestInit = Object.assign({}, requestInit, {
|
|
105
|
-
headers,
|
|
106
|
-
body,
|
|
107
|
-
method: requestSpec.method,
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const request = new Request(url.toString(), init);
|
|
111
|
-
|
|
112
|
-
return this.adapter?.(request) ?? of(request);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
response(
|
|
116
|
-
request: Request | RequestSpec<unknown>,
|
|
117
|
-
dataExpected?: boolean
|
|
118
|
-
): Observable<Response> {
|
|
119
|
-
const request$ =
|
|
120
|
-
request instanceof Request ? of(request) : this.request(request);
|
|
121
|
-
return request$.pipe(
|
|
122
|
-
switchMap((req) => fetch(req)),
|
|
123
|
-
switchMap((response) => validate(response, dataExpected ?? false))
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
result<B, R>(requestSpec: RequestSpec<B>, resultType: AnyType): Observable<R>;
|
|
128
|
-
result<B>(requestSpec: RequestSpec<B>): Observable<void>;
|
|
129
|
-
result(
|
|
130
|
-
request: RequestSpec<unknown>,
|
|
131
|
-
responseType?: AnyType
|
|
132
|
-
): Observable<unknown> {
|
|
133
|
-
const response$ = this.response(request, !!responseType);
|
|
134
|
-
|
|
135
|
-
if (!responseType) {
|
|
136
|
-
return response$.pipe(mapTo(undefined));
|
|
137
|
-
} else {
|
|
138
|
-
return response$.pipe(
|
|
139
|
-
switchMap(async (response) => {
|
|
140
|
-
try {
|
|
141
|
-
const contentType = mediaType(
|
|
142
|
-
response.headers.get('content-type'),
|
|
143
|
-
MediaType.OCTET_STREAM
|
|
144
|
-
);
|
|
145
|
-
const decoder = this.mediaTypeDecoders.find(contentType);
|
|
146
|
-
return await decoder.decode(response, responseType);
|
|
147
|
-
} catch (error) {
|
|
148
|
-
throw await HttpError.fromResponse(
|
|
149
|
-
error.message ?? 'Unknown Error',
|
|
150
|
-
response
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
})
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
events(requestSpec: RequestSpec<void>): ExtEventSource;
|
|
159
|
-
events<E>(
|
|
160
|
-
requestSpec: RequestSpec<void>,
|
|
161
|
-
eventTypes: EventTypes<E>
|
|
162
|
-
): Observable<E>;
|
|
163
|
-
events(
|
|
164
|
-
requestSpec: RequestSpec<void>,
|
|
165
|
-
eventTypes?: EventTypes<unknown>
|
|
166
|
-
): ExtEventSource | Observable<unknown> {
|
|
167
|
-
//
|
|
168
|
-
const adapter = (
|
|
169
|
-
url: string,
|
|
170
|
-
requestInit: RequestInit
|
|
171
|
-
): Observable<Request> => {
|
|
172
|
-
const eventSourceSpec = Object.assign({}, requestSpec, {
|
|
173
|
-
pathTemplate: url,
|
|
174
|
-
});
|
|
175
|
-
return this.request(eventSourceSpec, requestInit);
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
const eventSource = new FetchEventSource(requestSpec.pathTemplate, {
|
|
179
|
-
logger: this.logger,
|
|
180
|
-
adapter,
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
if (!eventTypes) {
|
|
184
|
-
return eventSource;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const generateEventHandler = (
|
|
188
|
-
eventType: AnyType,
|
|
189
|
-
subscriber: Subscriber<unknown>
|
|
190
|
-
) => {
|
|
191
|
-
return async (event: Event) => {
|
|
192
|
-
const decoder = this.mediaTypeDecoders.find(
|
|
193
|
-
'application/json'
|
|
194
|
-
) as JSONDecoder;
|
|
195
|
-
const msgEvent = event as MessageEvent;
|
|
196
|
-
const deserializedEvent = await decoder.decodeText(
|
|
197
|
-
msgEvent.data,
|
|
198
|
-
eventType
|
|
199
|
-
);
|
|
200
|
-
subscriber.next(deserializedEvent);
|
|
201
|
-
};
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
return new Observable((subscriber) => {
|
|
205
|
-
for (const eventTypeName of Object.keys(eventTypes)) {
|
|
206
|
-
const eventType = eventTypes[eventTypeName];
|
|
207
|
-
|
|
208
|
-
eventSource.addEventListener(
|
|
209
|
-
eventTypeName,
|
|
210
|
-
generateEventHandler(eventType, subscriber)
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
eventSource.onerror = (event) => {
|
|
214
|
-
this.logger?.error?.({ event }, 'event source error');
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
eventSource.connect();
|
|
219
|
-
|
|
220
|
-
return () => {
|
|
221
|
-
eventSource.close();
|
|
222
|
-
};
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
package/src/fetch.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { mediaType, MediaType } from './media-type';
|
|
2
|
-
import { HttpError } from './http-error';
|
|
3
|
-
import { Problem } from './problem';
|
|
4
|
-
|
|
5
|
-
export async function validate(
|
|
6
|
-
response: Response,
|
|
7
|
-
dataExpected: boolean
|
|
8
|
-
): Promise<Response> {
|
|
9
|
-
if (response.status < 200 || response.status >= 300) {
|
|
10
|
-
if (
|
|
11
|
-
mediaType(response.headers.get('content-type')) !== MediaType.PROBLEM_JSON
|
|
12
|
-
) {
|
|
13
|
-
await response.body?.cancel?.();
|
|
14
|
-
throw await HttpError.fromResponse(
|
|
15
|
-
'Unacceptable response status code',
|
|
16
|
-
response
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const problemData = await response.json();
|
|
21
|
-
|
|
22
|
-
throw new Problem(problemData as Problem);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (dataExpected && (response.status === 204 || response.status === 205)) {
|
|
26
|
-
throw await HttpError.fromResponse('Unexpected empty response', response);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return response;
|
|
30
|
-
}
|
package/src/http-error.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
export class HttpError extends Error {
|
|
2
|
-
constructor(
|
|
3
|
-
message: string,
|
|
4
|
-
public url: string,
|
|
5
|
-
public httpVersion: string,
|
|
6
|
-
public status: number,
|
|
7
|
-
public statusText: string,
|
|
8
|
-
public headers: Headers,
|
|
9
|
-
public body?: string
|
|
10
|
-
) {
|
|
11
|
-
super(message);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
static async fromResponse(
|
|
15
|
-
message: string,
|
|
16
|
-
response: Response
|
|
17
|
-
): Promise<HttpError> {
|
|
18
|
-
let body: string | undefined;
|
|
19
|
-
try {
|
|
20
|
-
if (response.headers.get('content-type')?.startsWith('text/')) {
|
|
21
|
-
body = await response.text();
|
|
22
|
-
} else {
|
|
23
|
-
const blob = await response.blob();
|
|
24
|
-
body = `<binary data: ${blob.size} bytes>`;
|
|
25
|
-
}
|
|
26
|
-
} catch (e) {
|
|
27
|
-
// ignore errors
|
|
28
|
-
body = '<unable to show response data>';
|
|
29
|
-
}
|
|
30
|
-
if (body.length > 512) {
|
|
31
|
-
body = `${body.slice(0, 512)}<<... another ${body.length - 512} bytes>>`;
|
|
32
|
-
}
|
|
33
|
-
const fullMessage = `${message}
|
|
34
|
-
|
|
35
|
-
########## BEGIN REQUEST ##########
|
|
36
|
-
|
|
37
|
-
HTTP/?.? ${response.status} ${response.statusText}
|
|
38
|
-
${Array.from(response.headers.entries())
|
|
39
|
-
.map(([name, value]) => `${name}: ${value}`)
|
|
40
|
-
.join('\n ')}
|
|
41
|
-
${body ?? '<none>'}
|
|
42
|
-
|
|
43
|
-
########### END REQUEST ###########
|
|
44
|
-
`;
|
|
45
|
-
return new HttpError(
|
|
46
|
-
fullMessage,
|
|
47
|
-
response.url,
|
|
48
|
-
'?.?',
|
|
49
|
-
response.status,
|
|
50
|
-
response.statusText,
|
|
51
|
-
response.headers,
|
|
52
|
-
body
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
export * from './any-type';
|
|
2
|
-
export * from './class-type';
|
|
3
|
-
export * from './request-factory';
|
|
4
|
-
export * from './fetch-request-factory';
|
|
5
|
-
export * from './fetch-event-source';
|
|
6
|
-
export * from './url-template';
|
|
7
|
-
export * from './media-type';
|
|
8
|
-
export * from './media-type-decoder';
|
|
9
|
-
export * from './media-type-decoders';
|
|
10
|
-
export * from './media-type-encoder';
|
|
11
|
-
export * from './media-type-encoders';
|
|
12
|
-
export * from './json-decoder';
|
|
13
|
-
export * from './json-encoder';
|
|
14
|
-
export * from './cbor-decoder';
|
|
15
|
-
export * from './cbor-encoder';
|
|
16
|
-
export * from './binary-decoder';
|
|
17
|
-
export * from './binary-encoder';
|
|
18
|
-
export * from './url-encoder';
|
|
19
|
-
export * from './logger';
|
|
20
|
-
export * from './http-error';
|
|
21
|
-
export * from './problem';
|
|
22
|
-
export * from './date-time-types';
|
|
23
|
-
|
|
24
|
-
export * from './util/base64';
|
|
25
|
-
export * from './util/hex';
|
|
26
|
-
export * from './util/rxjs';
|
package/src/json-decoder.ts
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { JsonParser } from '@outfoxx/jackson-js';
|
|
2
|
-
import { CustomMapper, Deserializer } from '@outfoxx/jackson-js/dist/@types';
|
|
3
|
-
import { DateTime } from 'luxon';
|
|
4
|
-
import { AnyType } from './any-type';
|
|
5
|
-
import { MediaTypeDecoder } from './media-type-decoder';
|
|
6
|
-
import { Base64 } from './util/base64';
|
|
7
|
-
|
|
8
|
-
export class JSONDecoder implements MediaTypeDecoder {
|
|
9
|
-
static get default(): JSONDecoder {
|
|
10
|
-
return new JSONDecoder(
|
|
11
|
-
JSONDecoder.NumericDateDecoding.MILLISECONDS_SINCE_EPOCH
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
private readonly customDeserializers: CustomMapper<Deserializer>[];
|
|
16
|
-
private readonly parser = new JsonParser();
|
|
17
|
-
|
|
18
|
-
constructor(readonly numericDateDecoding: JSONDecoder.NumericDateDecoding) {
|
|
19
|
-
this.customDeserializers = [
|
|
20
|
-
{
|
|
21
|
-
type: () => Date,
|
|
22
|
-
mapper: this.dateDeserializer,
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
type: () => DateTime,
|
|
26
|
-
mapper: this.dateTimeDeserializer,
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
type: () => URL,
|
|
30
|
-
mapper: this.urlDeserializer,
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
type: () => ArrayBuffer,
|
|
34
|
-
mapper: this.arrayBufferDeserializer,
|
|
35
|
-
},
|
|
36
|
-
];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async decode<T>(response: Response, type: AnyType): Promise<T> {
|
|
40
|
-
return this.decodeJSON(await response.json(), type);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
decodeText<T>(text: string, type: AnyType): T {
|
|
44
|
-
return this.parser.parse(text, {
|
|
45
|
-
deserializers: this.customDeserializers,
|
|
46
|
-
mainCreator: () => type,
|
|
47
|
-
}) as T;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
decodeJSON<T, U>(value: T, type: AnyType): Promise<U> {
|
|
51
|
-
return this.parser.transform(value, {
|
|
52
|
-
deserializers: this.customDeserializers,
|
|
53
|
-
mainCreator: () => type,
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
private dateTimeDeserializer: Deserializer = (
|
|
58
|
-
key: string,
|
|
59
|
-
value: unknown
|
|
60
|
-
) => {
|
|
61
|
-
if (value == null) {
|
|
62
|
-
return value;
|
|
63
|
-
}
|
|
64
|
-
if (DateTime.isDateTime(value)) {
|
|
65
|
-
return value;
|
|
66
|
-
}
|
|
67
|
-
if (value instanceof Date) {
|
|
68
|
-
return DateTime.fromJSDate(value, { zone: 'UTC' });
|
|
69
|
-
}
|
|
70
|
-
if (typeof value === 'number') {
|
|
71
|
-
if (
|
|
72
|
-
this.numericDateDecoding ===
|
|
73
|
-
JSONDecoder.NumericDateDecoding.MILLISECONDS_SINCE_EPOCH
|
|
74
|
-
) {
|
|
75
|
-
return DateTime.fromMillis(value, { zone: 'UTC' });
|
|
76
|
-
} else if (
|
|
77
|
-
this.numericDateDecoding ===
|
|
78
|
-
JSONDecoder.NumericDateDecoding.SECONDS_SINCE_EPOCH
|
|
79
|
-
) {
|
|
80
|
-
return DateTime.fromSeconds(value, { zone: 'UTC' });
|
|
81
|
-
} else {
|
|
82
|
-
console.error('Unsupported date decoding format');
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
if (typeof value === 'string') {
|
|
86
|
-
return DateTime.fromISO(value, { setZone: true });
|
|
87
|
-
}
|
|
88
|
-
throw new Error(`Invalid date value for property ${key}`);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
private dateDeserializer: Deserializer = (key: string, value: unknown) => {
|
|
92
|
-
if (value == null) {
|
|
93
|
-
return value;
|
|
94
|
-
}
|
|
95
|
-
if (value instanceof Date) {
|
|
96
|
-
return value;
|
|
97
|
-
}
|
|
98
|
-
if (typeof value === 'number') {
|
|
99
|
-
if (
|
|
100
|
-
this.numericDateDecoding ===
|
|
101
|
-
JSONDecoder.NumericDateDecoding.MILLISECONDS_SINCE_EPOCH
|
|
102
|
-
) {
|
|
103
|
-
return new Date(value);
|
|
104
|
-
} else if (
|
|
105
|
-
this.numericDateDecoding ===
|
|
106
|
-
JSONDecoder.NumericDateDecoding.SECONDS_SINCE_EPOCH
|
|
107
|
-
) {
|
|
108
|
-
return new Date(value * 1000);
|
|
109
|
-
} else {
|
|
110
|
-
console.error('Unsupported date decoding format');
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (typeof value === 'string') {
|
|
114
|
-
return new Date(value);
|
|
115
|
-
}
|
|
116
|
-
throw new Error(`Invalid date value for property ${key}`);
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
private urlDeserializer: Deserializer = (key: string, value: unknown) => {
|
|
120
|
-
if (value == null) {
|
|
121
|
-
return value;
|
|
122
|
-
}
|
|
123
|
-
if (value instanceof URL) {
|
|
124
|
-
return value;
|
|
125
|
-
}
|
|
126
|
-
if (typeof value === 'string') {
|
|
127
|
-
return new URL(value);
|
|
128
|
-
}
|
|
129
|
-
throw Error(`Invalid URL value for property ${key}`);
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
private arrayBufferDeserializer: Deserializer = (
|
|
133
|
-
key: string,
|
|
134
|
-
value: unknown
|
|
135
|
-
) => {
|
|
136
|
-
if (value == null) {
|
|
137
|
-
return value;
|
|
138
|
-
}
|
|
139
|
-
if (value instanceof ArrayBuffer) {
|
|
140
|
-
return value;
|
|
141
|
-
}
|
|
142
|
-
if (typeof value === 'string') {
|
|
143
|
-
return Base64.decode(value);
|
|
144
|
-
}
|
|
145
|
-
throw Error(`Invalid ArrayBuffer value for property ${key}`);
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export namespace JSONDecoder {
|
|
150
|
-
/**
|
|
151
|
-
* Configures how numeric `Date` & `DateTime` parameters are decoded.
|
|
152
|
-
*/
|
|
153
|
-
export enum NumericDateDecoding {
|
|
154
|
-
/**
|
|
155
|
-
* Decode the `Date`/`DateTime` as a UNIX timestamp (floating point seconds since epoch).
|
|
156
|
-
*/
|
|
157
|
-
SECONDS_SINCE_EPOCH,
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Decode the `Date`/`DateTime` as UNIX millisecond timestamp (integer milliseconds since epoch).
|
|
161
|
-
*/
|
|
162
|
-
MILLISECONDS_SINCE_EPOCH,
|
|
163
|
-
}
|
|
164
|
-
}
|
package/src/json-encoder.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { CustomMapper, Serializer } from '@outfoxx/jackson-js/dist/@types';
|
|
2
|
-
import { DateTime } from 'luxon';
|
|
3
|
-
import { MediaTypeEncoder } from './media-type-encoder';
|
|
4
|
-
import { AnyType } from './any-type';
|
|
5
|
-
import { JsonIncludeType, JsonStringifier } from '@outfoxx/jackson-js';
|
|
6
|
-
import { Base64 } from './util/base64';
|
|
7
|
-
import 'reflect-metadata';
|
|
8
|
-
|
|
9
|
-
export class JSONEncoder implements MediaTypeEncoder {
|
|
10
|
-
static get default(): JSONEncoder {
|
|
11
|
-
return new JSONEncoder(JSONEncoder.DateEncoding.ISO8601);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
private readonly customSerializers: CustomMapper<Serializer>[];
|
|
15
|
-
private stringifier = new JsonStringifier();
|
|
16
|
-
|
|
17
|
-
constructor(readonly dateEncoding: JSONEncoder.DateEncoding) {
|
|
18
|
-
this.customSerializers = [
|
|
19
|
-
{
|
|
20
|
-
type: () => Date,
|
|
21
|
-
mapper: this.dateSerializer,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
type: () => DateTime,
|
|
25
|
-
mapper: this.dateTimeSerializer,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
type: () => URL,
|
|
29
|
-
mapper: this.urlSerializer,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
type: () => ArrayBuffer,
|
|
33
|
-
mapper: this.arrayBufferSerializer,
|
|
34
|
-
},
|
|
35
|
-
];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
encode<T>(value: T, type?: AnyType, includeNulls = false): string {
|
|
39
|
-
// Use natural type when subtypes exist
|
|
40
|
-
if (
|
|
41
|
-
Reflect.hasMetadata(
|
|
42
|
-
'jackson:defaultContextGroup:JsonSubTypes',
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
-
(value as any).constructor ?? {}
|
|
45
|
-
)
|
|
46
|
-
) {
|
|
47
|
-
type = [Object];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return this.stringifier.stringify(value, {
|
|
51
|
-
serializers: this.customSerializers,
|
|
52
|
-
features: {
|
|
53
|
-
serialization: {
|
|
54
|
-
DEFAULT_PROPERTY_INCLUSION: {
|
|
55
|
-
value: includeNulls
|
|
56
|
-
? JsonIncludeType.ALWAYS
|
|
57
|
-
: JsonIncludeType.NON_NULL,
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
mainCreator: () => type ?? [Object],
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
encodeJSON<T>(value: T, type?: AnyType, includeNulls = false): unknown {
|
|
66
|
-
// Use natural type when subtypes exist
|
|
67
|
-
if (
|
|
68
|
-
Reflect.hasMetadata(
|
|
69
|
-
'jackson:defaultContextGroup:JsonSubTypes',
|
|
70
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
-
(value as any).constructor ?? {}
|
|
72
|
-
)
|
|
73
|
-
) {
|
|
74
|
-
type = [Object];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return this.stringifier.transform(value, {
|
|
78
|
-
serializers: this.customSerializers,
|
|
79
|
-
features: {
|
|
80
|
-
serialization: {
|
|
81
|
-
DEFAULT_PROPERTY_INCLUSION: {
|
|
82
|
-
value: includeNulls
|
|
83
|
-
? JsonIncludeType.ALWAYS
|
|
84
|
-
: JsonIncludeType.NON_NULL,
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
mainCreator: () => type ?? [Object],
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private dateTimeSerializer: Serializer = (key: string, value: DateTime) => {
|
|
93
|
-
if (value == null) {
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
switch (this.dateEncoding) {
|
|
98
|
-
case JSONEncoder.DateEncoding.ISO8601:
|
|
99
|
-
return value.toISO();
|
|
100
|
-
case JSONEncoder.DateEncoding.MILLISECONDS_SINCE_EPOCH:
|
|
101
|
-
return value.toMillis();
|
|
102
|
-
case JSONEncoder.DateEncoding.SECONDS_SINCE_EPOCH:
|
|
103
|
-
return value.toSeconds();
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
private dateSerializer: Serializer = (key: string, value: Date) => {
|
|
108
|
-
if (value == null) {
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
switch (this.dateEncoding) {
|
|
113
|
-
case JSONEncoder.DateEncoding.ISO8601:
|
|
114
|
-
return value.toISOString();
|
|
115
|
-
case JSONEncoder.DateEncoding.MILLISECONDS_SINCE_EPOCH:
|
|
116
|
-
return value.getTime();
|
|
117
|
-
case JSONEncoder.DateEncoding.SECONDS_SINCE_EPOCH:
|
|
118
|
-
return value.getTime() / 1000;
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
private urlSerializer: Serializer = (key: string, value: URL) => {
|
|
123
|
-
if (value == null) {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return value.toString();
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
private arrayBufferSerializer: Serializer = (
|
|
131
|
-
key: string,
|
|
132
|
-
value: ArrayBuffer
|
|
133
|
-
) => {
|
|
134
|
-
if (value == null) {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return Base64.encode(value);
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export namespace JSONEncoder {
|
|
143
|
-
/**
|
|
144
|
-
* Configures how `Date` & `DateTime` parameters are encoded.
|
|
145
|
-
*/
|
|
146
|
-
export enum DateEncoding {
|
|
147
|
-
/**
|
|
148
|
-
* Encode `Date`/`DateTime` values as a UNIX timestamp (floating point seconds since epoch).
|
|
149
|
-
*/
|
|
150
|
-
SECONDS_SINCE_EPOCH,
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Encode `Date`/`DateTime` values as UNIX millisecond timestamp (integer milliseconds since epoch).
|
|
154
|
-
*/
|
|
155
|
-
MILLISECONDS_SINCE_EPOCH,
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Encode `Date`/`DateTime` values as an ISO-8601-formatted string (in RFC 3339 format). This is the default behavior.
|
|
159
|
-
*/
|
|
160
|
-
ISO8601,
|
|
161
|
-
}
|
|
162
|
-
}
|
package/src/logger.ts
DELETED