@outfoxx/sunday 1.0.9 → 1.1.0-alpha.11
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 +35 -2
- package/dist/any-type.d.ts +2 -0
- package/dist/any-type.js +13 -0
- package/dist/any-type.js.map +1 -1
- package/dist/class-type.d.ts +2 -2
- package/dist/class-type.js +13 -0
- package/dist/class-type.js.map +1 -1
- package/dist/date-time-types.d.ts +2 -7
- package/dist/date-time-types.js +15 -4
- package/dist/date-time-types.js.map +1 -1
- package/dist/event-parser.d.ts +17 -0
- package/dist/event-parser.js +153 -0
- package/dist/event-parser.js.map +1 -0
- package/dist/fetch-event-source.d.ts +12 -10
- package/dist/fetch-event-source.js +154 -138
- package/dist/fetch-event-source.js.map +1 -1
- package/dist/fetch-request-factory.d.ts +10 -5
- package/dist/fetch-request-factory.js +100 -71
- package/dist/fetch-request-factory.js.map +1 -1
- package/dist/fetch.d.ts +7 -1
- package/dist/fetch.js +74 -8
- package/dist/fetch.js.map +1 -1
- package/dist/header-parameters.d.ts +3 -0
- package/dist/header-parameters.js +53 -0
- package/dist/header-parameters.js.map +1 -0
- package/dist/index.d.ts +12 -12
- package/dist/index.js +25 -12
- package/dist/index.js.map +1 -1
- package/dist/logger.js +13 -0
- package/dist/logger.js.map +1 -1
- package/dist/{binary-decoder.d.ts → media-type-codecs/binary-decoder.d.ts} +2 -2
- package/dist/media-type-codecs/binary-decoder.js +29 -0
- package/dist/media-type-codecs/binary-decoder.js.map +1 -0
- package/dist/{binary-encoder.d.ts → media-type-codecs/binary-encoder.d.ts} +0 -0
- package/dist/media-type-codecs/binary-encoder.js +26 -0
- package/dist/media-type-codecs/binary-encoder.js.map +1 -0
- package/dist/media-type-codecs/cbor-decoder.d.ts +39 -0
- package/dist/media-type-codecs/cbor-decoder.js +426 -0
- package/dist/media-type-codecs/cbor-decoder.js.map +1 -0
- package/dist/media-type-codecs/cbor-encoder.d.ts +43 -0
- package/dist/media-type-codecs/cbor-encoder.js +239 -0
- package/dist/media-type-codecs/cbor-encoder.js.map +1 -0
- package/dist/media-type-codecs/cbor-tags.d.ts +4 -0
- package/dist/media-type-codecs/cbor-tags.js +18 -0
- package/dist/media-type-codecs/cbor-tags.js.map +1 -0
- package/dist/media-type-codecs/json-decoder.d.ts +39 -0
- package/dist/media-type-codecs/json-decoder.js +380 -0
- package/dist/media-type-codecs/json-decoder.js.map +1 -0
- package/dist/media-type-codecs/json-encoder.d.ts +44 -0
- package/dist/media-type-codecs/json-encoder.js +276 -0
- package/dist/media-type-codecs/json-encoder.js.map +1 -0
- package/dist/media-type-codecs/media-type-decoder.d.ts +11 -0
- package/dist/media-type-codecs/media-type-decoder.js +19 -0
- package/dist/media-type-codecs/media-type-decoder.js.map +1 -0
- package/dist/{media-type-decoders.d.ts → media-type-codecs/media-type-decoders.d.ts} +5 -4
- package/dist/media-type-codecs/media-type-decoders.js +53 -0
- package/dist/media-type-codecs/media-type-decoders.js.map +1 -0
- package/dist/{media-type-encoder.d.ts → media-type-codecs/media-type-encoder.d.ts} +5 -1
- package/dist/media-type-codecs/media-type-encoder.js +24 -0
- package/dist/media-type-codecs/media-type-encoder.js.map +1 -0
- package/dist/{media-type-encoders.d.ts → media-type-codecs/media-type-encoders.d.ts} +5 -4
- package/dist/media-type-codecs/media-type-encoders.js +55 -0
- package/dist/media-type-codecs/media-type-encoders.js.map +1 -0
- package/dist/{url-encoder.d.ts → media-type-codecs/www-form-url-encoder.d.ts} +8 -8
- package/dist/{url-encoder.js → media-type-codecs/www-form-url-encoder.js} +51 -37
- package/dist/media-type-codecs/www-form-url-encoder.js.map +1 -0
- package/dist/media-type.d.ts +91 -13
- package/dist/media-type.js +286 -15
- package/dist/media-type.js.map +1 -1
- package/dist/problem.d.ts +24 -9
- package/dist/problem.js +153 -6
- package/dist/problem.js.map +1 -1
- package/dist/request-factory.d.ts +10 -10
- package/dist/request-factory.js +13 -0
- package/dist/request-factory.js.map +1 -1
- package/dist/sunday-error.d.ts +11 -0
- package/dist/sunday-error.js +31 -0
- package/dist/sunday-error.js.map +1 -0
- package/dist/url-template.js +13 -0
- package/dist/url-template.js.map +1 -1
- package/dist/util/any.d.ts +2 -0
- package/dist/util/any.js +24 -0
- package/dist/util/any.js.map +1 -0
- package/dist/util/base64.js +13 -0
- package/dist/util/base64.js.map +1 -1
- package/dist/util/error.d.ts +2 -0
- package/dist/util/error.js +26 -0
- package/dist/util/error.js.map +1 -0
- package/dist/util/hex.js +16 -2
- package/dist/util/hex.js.map +1 -1
- package/dist/util/rxjs.d.ts +3 -0
- package/dist/util/rxjs.js +22 -5
- package/dist/util/rxjs.js.map +1 -1
- package/dist/util/stream-rxjs.js +13 -0
- package/dist/util/stream-rxjs.js.map +1 -1
- package/dist/util/temporal.d.ts +2 -0
- package/dist/util/temporal.js +31 -0
- package/dist/util/temporal.js.map +1 -0
- package/package.json +29 -22
- package/src/any-type.ts +18 -0
- package/src/class-type.ts +20 -2
- package/src/date-time-types.ts +35 -8
- package/src/event-parser.ts +204 -0
- package/src/fetch-event-source.ts +163 -159
- package/src/fetch-request-factory.ts +142 -100
- package/src/fetch.ts +79 -14
- package/src/header-parameters.ts +66 -0
- package/src/index.ts +26 -12
- package/src/logger.ts +14 -0
- package/src/media-type-codecs/binary-decoder.ts +38 -0
- package/src/media-type-codecs/binary-encoder.ts +33 -0
- package/src/media-type-codecs/cbor-decoder.ts +529 -0
- package/src/media-type-codecs/cbor-encoder.ts +321 -0
- package/src/media-type-codecs/cbor-tags.ts +18 -0
- package/src/media-type-codecs/json-decoder.ts +484 -0
- package/src/media-type-codecs/json-encoder.ts +342 -0
- package/src/media-type-codecs/media-type-decoder.ts +34 -0
- package/src/media-type-codecs/media-type-decoders.ts +81 -0
- package/src/media-type-codecs/media-type-encoder.ts +45 -0
- package/src/media-type-codecs/media-type-encoders.ts +83 -0
- package/src/media-type-codecs/www-form-url-encoder.ts +193 -0
- package/src/media-type.ts +340 -22
- package/src/problem.ts +158 -12
- package/src/request-factory.ts +35 -12
- package/src/sunday-error.ts +51 -0
- package/src/url-template.ts +14 -0
- package/src/util/any.ts +24 -0
- package/src/util/base64.ts +14 -0
- package/src/util/error.ts +28 -0
- package/src/util/hex.ts +17 -2
- package/src/util/rxjs.ts +30 -5
- package/src/util/stream-rxjs.ts +14 -0
- package/src/util/temporal.ts +32 -0
- package/dist/binary-decoder.js +0 -16
- package/dist/binary-decoder.js.map +0 -1
- 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/http-error.d.ts +0 -10
- package/dist/http-error.js +0 -45
- package/dist/http-error.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/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.js +0 -40
- package/dist/media-type-decoders.js.map +0 -1
- package/dist/media-type-encoder.js +0 -6
- package/dist/media-type-encoder.js.map +0 -1
- package/dist/media-type-encoders.js +0 -42
- package/dist/media-type-encoders.js.map +0 -1
- package/dist/url-encoder.js.map +0 -1
- 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/http-error.ts +0 -55
- package/src/json-decoder.ts +0 -164
- package/src/json-encoder.ts +0 -162
- 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/url-encoder.ts +0 -173
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
// Copyright 2020 Outfox, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
import { Instant } from '@js-joda/core';
|
|
16
|
+
import { JsonStringifier } from '@outfoxx/jackson-js';
|
|
17
|
+
import { URLQueryParamsEncoder } from './media-type-encoder';
|
|
18
|
+
|
|
19
|
+
export class WWWFormUrlEncoder implements URLQueryParamsEncoder {
|
|
20
|
+
static get default(): WWWFormUrlEncoder {
|
|
21
|
+
return new WWWFormUrlEncoder(
|
|
22
|
+
WWWFormUrlEncoder.ArrayEncoding.UNBRACKETED,
|
|
23
|
+
WWWFormUrlEncoder.BoolEncoding.LITERAL,
|
|
24
|
+
WWWFormUrlEncoder.DateEncoding.DECIMAL_SECONDS_SINCE_EPOCH
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
constructor(
|
|
29
|
+
private arrayEncoding: WWWFormUrlEncoder.ArrayEncoding,
|
|
30
|
+
private boolEncoding: WWWFormUrlEncoder.BoolEncoding,
|
|
31
|
+
private dateEncoding: WWWFormUrlEncoder.DateEncoding,
|
|
32
|
+
private json = new JsonStringifier(),
|
|
33
|
+
private encoder = new TextEncoder()
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
encode<T = unknown>(value: T): ArrayBuffer | SharedArrayBuffer {
|
|
37
|
+
const parameters = this.json.transform(value);
|
|
38
|
+
|
|
39
|
+
return this.encoder.encode(this.encodeQueryString(parameters));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
encodeQueryString(parameters: Record<string, unknown>): string {
|
|
43
|
+
const components: string[] = [];
|
|
44
|
+
|
|
45
|
+
for (const key of Object.keys(parameters).sort()) {
|
|
46
|
+
components.push(...this.encodeQueryComponent(key, parameters[key]));
|
|
47
|
+
}
|
|
48
|
+
return components.join('&');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
encodeQueryComponent(key: string, value: unknown): string[] {
|
|
52
|
+
const components: string[] = [];
|
|
53
|
+
|
|
54
|
+
if (value === undefined) {
|
|
55
|
+
return components;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (value == null) {
|
|
59
|
+
//
|
|
60
|
+
components.push(encodeURIComponent(key));
|
|
61
|
+
} else if (value instanceof Array) {
|
|
62
|
+
// encode key according to `arrayEncoding`
|
|
63
|
+
for (const item of value) {
|
|
64
|
+
components.push(
|
|
65
|
+
...this.encodeQueryComponent(
|
|
66
|
+
encodeArrayKey(key, this.arrayEncoding),
|
|
67
|
+
item
|
|
68
|
+
)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
} else if (value instanceof Instant) {
|
|
72
|
+
//
|
|
73
|
+
components.push(
|
|
74
|
+
encodeURIComponent(key) +
|
|
75
|
+
'=' +
|
|
76
|
+
encodeURIComponent(encodeDate(value, this.dateEncoding))
|
|
77
|
+
);
|
|
78
|
+
} else if (typeof value === 'boolean') {
|
|
79
|
+
//
|
|
80
|
+
components.push(
|
|
81
|
+
encodeURIComponent(key) +
|
|
82
|
+
'=' +
|
|
83
|
+
encodeURIComponent(encodeBoolean(value, this.boolEncoding))
|
|
84
|
+
);
|
|
85
|
+
} else if (typeof value === 'object') {
|
|
86
|
+
//
|
|
87
|
+
const rec = (value ?? {}) as Record<string, unknown>;
|
|
88
|
+
|
|
89
|
+
for (const nestedKey of Object.keys(rec).sort()) {
|
|
90
|
+
components.push(
|
|
91
|
+
...this.encodeQueryComponent(`${key}[${nestedKey}]`, rec[nestedKey])
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
//
|
|
96
|
+
components.push(
|
|
97
|
+
encodeURIComponent(key) + '=' + encodeURIComponent(`${value}`)
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return components;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function encodeArrayKey(
|
|
106
|
+
key: string,
|
|
107
|
+
encoding: WWWFormUrlEncoder.ArrayEncoding
|
|
108
|
+
): string {
|
|
109
|
+
return encoding === WWWFormUrlEncoder.ArrayEncoding.BRACKETED
|
|
110
|
+
? `${key}[]`
|
|
111
|
+
: key;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function encodeBoolean(
|
|
115
|
+
value: boolean,
|
|
116
|
+
encoding: WWWFormUrlEncoder.BoolEncoding
|
|
117
|
+
): string {
|
|
118
|
+
switch (encoding) {
|
|
119
|
+
case WWWFormUrlEncoder.BoolEncoding.NUMERIC:
|
|
120
|
+
return value ? '1' : '0';
|
|
121
|
+
case WWWFormUrlEncoder.BoolEncoding.LITERAL:
|
|
122
|
+
return value ? 'true' : 'false';
|
|
123
|
+
default:
|
|
124
|
+
throw new Error('unknown boolean encoding');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function encodeDate(
|
|
129
|
+
value: Date | Instant,
|
|
130
|
+
encoding: WWWFormUrlEncoder.DateEncoding
|
|
131
|
+
): string {
|
|
132
|
+
value = value instanceof Date ? Instant.ofEpochMilli(value.getTime()) : value;
|
|
133
|
+
switch (encoding) {
|
|
134
|
+
case WWWFormUrlEncoder.DateEncoding.DECIMAL_SECONDS_SINCE_EPOCH:
|
|
135
|
+
return (value.epochSecond() + value.nano() / 1_000_000_000.0).toFixed(7);
|
|
136
|
+
case WWWFormUrlEncoder.DateEncoding.MILLISECONDS_SINCE_EPOCH:
|
|
137
|
+
return `${value.toEpochMilli()}`;
|
|
138
|
+
case WWWFormUrlEncoder.DateEncoding.ISO8601:
|
|
139
|
+
return value.toString();
|
|
140
|
+
default:
|
|
141
|
+
throw new Error('unknown date encoding');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export namespace WWWFormUrlEncoder {
|
|
146
|
+
/**
|
|
147
|
+
* Configures how `Array` parameters are encoded.
|
|
148
|
+
*/
|
|
149
|
+
export enum ArrayEncoding {
|
|
150
|
+
/**
|
|
151
|
+
* An empty set of square brackets is appended to the key for every value. This is the default behavior.
|
|
152
|
+
*/
|
|
153
|
+
BRACKETED,
|
|
154
|
+
/**
|
|
155
|
+
* No brackets are appended. The key is encoded as is.
|
|
156
|
+
*/
|
|
157
|
+
UNBRACKETED,
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Configures how `Bool` parameters are encoded.
|
|
162
|
+
*/
|
|
163
|
+
export enum BoolEncoding {
|
|
164
|
+
/**
|
|
165
|
+
* Encode `true` as `1` and `false` as `0`. This is the default behavior.
|
|
166
|
+
*/
|
|
167
|
+
NUMERIC,
|
|
168
|
+
/**
|
|
169
|
+
* Encode `true` and `false` as string literals.
|
|
170
|
+
*/
|
|
171
|
+
LITERAL,
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Configures how `Date` parameters are encoded.
|
|
176
|
+
*/
|
|
177
|
+
export enum DateEncoding {
|
|
178
|
+
/**
|
|
179
|
+
* Encode the `Date` as a UNIX timestamp (decimal seconds since epoch).
|
|
180
|
+
*/
|
|
181
|
+
DECIMAL_SECONDS_SINCE_EPOCH,
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Encode the `Date` as UNIX millisecond timestamp (integer milliseconds since epoch).
|
|
185
|
+
*/
|
|
186
|
+
MILLISECONDS_SINCE_EPOCH,
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Encode the `Date` as an ISO-8601-formatted string (in RFC 3339 format). This is the default behavior.
|
|
190
|
+
*/
|
|
191
|
+
ISO8601,
|
|
192
|
+
}
|
|
193
|
+
}
|
package/src/media-type.ts
CHANGED
|
@@ -1,25 +1,343 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
// Copyright 2020 Outfox, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
export class MediaType {
|
|
16
|
+
type: MediaType.Type;
|
|
17
|
+
tree: MediaType.Tree;
|
|
18
|
+
subtype: string;
|
|
19
|
+
suffix?: MediaType.Suffix;
|
|
20
|
+
parameters: Record<string, string>;
|
|
21
|
+
|
|
22
|
+
constructor(params: {
|
|
23
|
+
type: MediaType.Type;
|
|
24
|
+
tree?: MediaType.Tree;
|
|
25
|
+
subtype: string;
|
|
26
|
+
suffix?: MediaType.Suffix;
|
|
27
|
+
parameters?: Record<string, string>;
|
|
28
|
+
}) {
|
|
29
|
+
this.type = params.type;
|
|
30
|
+
this.tree = params.tree ?? MediaType.Tree.Standard;
|
|
31
|
+
this.subtype = params.subtype.toLowerCase();
|
|
32
|
+
this.suffix = params.suffix;
|
|
33
|
+
this.parameters = Object.entries(params.parameters ?? {}).reduce(
|
|
34
|
+
(obj, [name, value]) => {
|
|
35
|
+
obj[name.toLowerCase()] = value.toLowerCase();
|
|
36
|
+
return obj;
|
|
37
|
+
},
|
|
38
|
+
{} as Record<string, string>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
parameter(name: MediaType.ParameterName | string): string | undefined {
|
|
43
|
+
return this.parameters[name];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
with(params: {
|
|
47
|
+
type?: MediaType.Type;
|
|
48
|
+
tree?: MediaType.Tree;
|
|
49
|
+
subtype?: string;
|
|
50
|
+
suffix?: MediaType.Suffix;
|
|
51
|
+
parameters?: Record<string, string>;
|
|
52
|
+
}): MediaType {
|
|
53
|
+
return new MediaType({
|
|
54
|
+
type: params.type ?? this.type,
|
|
55
|
+
tree: params.tree ?? this.tree,
|
|
56
|
+
subtype: params.subtype ?? this.subtype,
|
|
57
|
+
suffix: params.suffix ?? this.suffix,
|
|
58
|
+
parameters: params.parameters ?? this.parameters,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
withParameter(
|
|
63
|
+
parameter: MediaType.ParameterName | string,
|
|
64
|
+
value: string
|
|
65
|
+
): MediaType {
|
|
66
|
+
const parameters = Object.assign({}, this.parameters, {
|
|
67
|
+
[parameter]: value,
|
|
68
|
+
});
|
|
69
|
+
return this.with({ parameters });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get value(): string {
|
|
73
|
+
const type = this.type;
|
|
74
|
+
const tree = this.tree;
|
|
75
|
+
const suffix = this.suffix ? `+${this.suffix.toLowerCase()}` : '';
|
|
76
|
+
const parameters = Object.keys(this.parameters)
|
|
77
|
+
.sort()
|
|
78
|
+
.map((key) => `;${key}=${this.parameters[key]}`)
|
|
79
|
+
.join('');
|
|
80
|
+
return `${type}/${tree}${this.subtype}${suffix}${parameters}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
compatible(other: MediaType): boolean {
|
|
84
|
+
if (
|
|
85
|
+
this.type != MediaType.Type.Any &&
|
|
86
|
+
other.type != MediaType.Type.Any &&
|
|
87
|
+
this.type != other.type
|
|
88
|
+
) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
if (
|
|
92
|
+
this.tree != MediaType.Tree.Any &&
|
|
93
|
+
other.tree != MediaType.Tree.Any &&
|
|
94
|
+
this.tree != other.tree
|
|
95
|
+
) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
if (
|
|
99
|
+
this.subtype != '*' &&
|
|
100
|
+
other.subtype != '*' &&
|
|
101
|
+
this.subtype != other.subtype
|
|
102
|
+
) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
if (this.suffix != other.suffix) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
const thisKeys = Object.keys(this.parameters);
|
|
109
|
+
const otherKeys = Object.keys(other.parameters);
|
|
110
|
+
return thisKeys
|
|
111
|
+
.filter((key) => otherKeys.includes(key))
|
|
112
|
+
.every((key) => this.parameters[key] == other.parameters[key]);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
equals(other: MediaType): boolean {
|
|
116
|
+
if (this === other) return true;
|
|
117
|
+
|
|
118
|
+
if (this.type != other.type) return false;
|
|
119
|
+
if (this.tree != other.tree) return false;
|
|
120
|
+
if (this.suffix != other.suffix) return false;
|
|
121
|
+
if (this.subtype != other.subtype) return false;
|
|
122
|
+
for (const parameterName of Object.keys(this.parameters)) {
|
|
123
|
+
if (this.parameters[parameterName] != other.parameters[parameterName]) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
toString(): string {
|
|
131
|
+
return this.value;
|
|
132
|
+
}
|
|
12
133
|
}
|
|
13
134
|
|
|
14
|
-
export
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
135
|
+
export namespace MediaType {
|
|
136
|
+
export enum Type {
|
|
137
|
+
Application = 'application',
|
|
138
|
+
Audio = 'audio',
|
|
139
|
+
Example = 'example',
|
|
140
|
+
Font = 'font',
|
|
141
|
+
Image = 'image',
|
|
142
|
+
Message = 'message',
|
|
143
|
+
Model = 'model',
|
|
144
|
+
Multipart = 'multipart',
|
|
145
|
+
Text = 'text',
|
|
146
|
+
Video = 'video',
|
|
147
|
+
Any = '*',
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export namespace Type {
|
|
151
|
+
export function from(value: string): Type | undefined {
|
|
152
|
+
return Object.values(Type).includes(value as Type)
|
|
153
|
+
? (value as Type)
|
|
154
|
+
: undefined;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export enum Tree {
|
|
159
|
+
Standard = '',
|
|
160
|
+
Vendor = 'vnd.',
|
|
161
|
+
Personal = 'prs.',
|
|
162
|
+
Unregistered = 'x.',
|
|
163
|
+
Obsolete = 'x-',
|
|
164
|
+
Any = '*',
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export namespace Tree {
|
|
168
|
+
export function from(value: string): Tree | undefined {
|
|
169
|
+
return Object.values(Tree).includes(value as Tree)
|
|
170
|
+
? (value as Tree)
|
|
171
|
+
: undefined;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export enum Suffix {
|
|
176
|
+
XML = 'xml',
|
|
177
|
+
JSON = 'json',
|
|
178
|
+
BER = 'ber',
|
|
179
|
+
DER = 'der',
|
|
180
|
+
FastInfoSet = 'fastinfoset',
|
|
181
|
+
WBXML = 'wbxml',
|
|
182
|
+
Zip = 'zip',
|
|
183
|
+
CBOR = 'cbor',
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export namespace Suffix {
|
|
187
|
+
export function from(value: string): Suffix | undefined {
|
|
188
|
+
return Object.values(Suffix).includes(value as Suffix)
|
|
189
|
+
? (value as Suffix)
|
|
190
|
+
: undefined;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export enum ParameterName {
|
|
195
|
+
CharSet = 'charset',
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function from(value?: string | null): MediaType | undefined;
|
|
199
|
+
export function from(
|
|
200
|
+
value: string | null | undefined,
|
|
201
|
+
def: MediaType
|
|
202
|
+
): MediaType;
|
|
203
|
+
export function from(
|
|
204
|
+
value?: string | null,
|
|
205
|
+
def: MediaType | undefined = undefined
|
|
206
|
+
): MediaType | undefined {
|
|
207
|
+
if (!value) {
|
|
208
|
+
return def;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
fullRegex.lastIndex = 0;
|
|
212
|
+
const match = fullRegex.exec(value);
|
|
213
|
+
if (match?.[0] != value) {
|
|
214
|
+
return def;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const type = MediaType.Type.from(match[1]?.toLowerCase());
|
|
218
|
+
if (!type) {
|
|
219
|
+
return def;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const tree =
|
|
223
|
+
MediaType.Tree.from(match[2]?.toLowerCase()) ?? MediaType.Tree.Standard;
|
|
224
|
+
|
|
225
|
+
const subtype = match[3]?.toLowerCase();
|
|
226
|
+
if (!subtype) {
|
|
227
|
+
return def;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const suffix = MediaType.Suffix.from(match[4]?.toLowerCase());
|
|
231
|
+
|
|
232
|
+
const parameters: Record<string, string> = {};
|
|
233
|
+
|
|
234
|
+
let parametersMatch = paramRegex.exec(match[5] ?? '');
|
|
235
|
+
while (parametersMatch?.[0]) {
|
|
236
|
+
const name = parametersMatch[1];
|
|
237
|
+
if (!name) continue;
|
|
238
|
+
|
|
239
|
+
const value = parametersMatch[2];
|
|
240
|
+
if (!value) continue;
|
|
241
|
+
|
|
242
|
+
parameters[name.toLowerCase()] = value.toLowerCase();
|
|
243
|
+
|
|
244
|
+
parametersMatch = paramRegex.exec(match[5]);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return new MediaType({
|
|
248
|
+
type,
|
|
249
|
+
tree,
|
|
250
|
+
subtype,
|
|
251
|
+
suffix,
|
|
252
|
+
parameters,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const fullRegex =
|
|
257
|
+
/^((?:[a-z]+|\*))\/(x(?:-|\\.)|(?:(?:vnd|prs|x)\.)|\*)?([a-z0-9\-.]+|\*)(?:\+([a-z]+))?( *(?:; *(?:(?:[\w.-]+) *= *(?:[\w.-]+)) *)*)$/gi;
|
|
258
|
+
const paramRegex = / *; *([\w.-]+) *= *([\w.-]+)/gi;
|
|
259
|
+
|
|
260
|
+
export const Plain = new MediaType({
|
|
261
|
+
type: MediaType.Type.Text,
|
|
262
|
+
subtype: 'plain',
|
|
263
|
+
});
|
|
264
|
+
export const HTML = new MediaType({
|
|
265
|
+
type: MediaType.Type.Text,
|
|
266
|
+
subtype: 'html',
|
|
267
|
+
});
|
|
268
|
+
export const JSON = new MediaType({
|
|
269
|
+
type: MediaType.Type.Application,
|
|
270
|
+
subtype: 'json',
|
|
271
|
+
});
|
|
272
|
+
export const YAML = new MediaType({
|
|
273
|
+
type: MediaType.Type.Application,
|
|
274
|
+
subtype: 'yaml',
|
|
275
|
+
});
|
|
276
|
+
export const CBOR = new MediaType({
|
|
277
|
+
type: MediaType.Type.Application,
|
|
278
|
+
subtype: 'cbor',
|
|
279
|
+
});
|
|
280
|
+
export const EventStream = new MediaType({
|
|
281
|
+
type: MediaType.Type.Text,
|
|
282
|
+
subtype: 'event-stream',
|
|
283
|
+
});
|
|
284
|
+
export const OctetStream = new MediaType({
|
|
285
|
+
type: MediaType.Type.Application,
|
|
286
|
+
subtype: 'octet-stream',
|
|
287
|
+
});
|
|
288
|
+
export const WWWFormUrlEncoded = new MediaType({
|
|
289
|
+
type: MediaType.Type.Application,
|
|
290
|
+
tree: MediaType.Tree.Obsolete,
|
|
291
|
+
subtype: 'www-form-urlencoded',
|
|
292
|
+
});
|
|
293
|
+
export const X509CACert = new MediaType({
|
|
294
|
+
type: MediaType.Type.Application,
|
|
295
|
+
tree: MediaType.Tree.Obsolete,
|
|
296
|
+
subtype: 'x509-ca-cert',
|
|
297
|
+
});
|
|
298
|
+
export const X509UserCert = new MediaType({
|
|
299
|
+
type: MediaType.Type.Application,
|
|
300
|
+
tree: MediaType.Tree.Obsolete,
|
|
301
|
+
subtype: 'x509-user-cert',
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
export const Any = new MediaType({
|
|
305
|
+
type: MediaType.Type.Any,
|
|
306
|
+
subtype: '*',
|
|
307
|
+
});
|
|
308
|
+
export const AnyText = new MediaType({
|
|
309
|
+
type: MediaType.Type.Text,
|
|
310
|
+
subtype: '*',
|
|
311
|
+
});
|
|
312
|
+
export const AnyImage = new MediaType({
|
|
313
|
+
type: MediaType.Type.Image,
|
|
314
|
+
subtype: '*',
|
|
315
|
+
});
|
|
316
|
+
export const AnyAudio = new MediaType({
|
|
317
|
+
type: MediaType.Type.Audio,
|
|
318
|
+
subtype: '*',
|
|
319
|
+
});
|
|
320
|
+
export const AnyVideo = new MediaType({
|
|
321
|
+
type: MediaType.Type.Video,
|
|
322
|
+
subtype: '*',
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
export const JSONStructured = new MediaType({
|
|
326
|
+
type: MediaType.Type.Any,
|
|
327
|
+
tree: MediaType.Tree.Any,
|
|
328
|
+
subtype: '*',
|
|
329
|
+
suffix: Suffix.JSON,
|
|
330
|
+
});
|
|
331
|
+
export const XMLStructured = new MediaType({
|
|
332
|
+
type: MediaType.Type.Any,
|
|
333
|
+
tree: MediaType.Tree.Any,
|
|
334
|
+
subtype: '*',
|
|
335
|
+
suffix: Suffix.XML,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
export const ProblemJSON = new MediaType({
|
|
339
|
+
type: MediaType.Type.Application,
|
|
340
|
+
subtype: 'problem',
|
|
341
|
+
suffix: Suffix.JSON,
|
|
342
|
+
});
|
|
25
343
|
}
|