@outfoxx/sunday 1.1.0-alpha.8 → 1.1.0-beta.1

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.
Files changed (123) hide show
  1. package/LICENSE.txt +203 -0
  2. package/README.md +6 -7
  3. package/dist/any-type.js +13 -0
  4. package/dist/any-type.js.map +1 -1
  5. package/dist/class-type.js +13 -0
  6. package/dist/class-type.js.map +1 -1
  7. package/dist/date-time-types.js +13 -0
  8. package/dist/date-time-types.js.map +1 -1
  9. package/dist/event-parser.d.ts +1 -1
  10. package/dist/event-parser.js +17 -4
  11. package/dist/event-parser.js.map +1 -1
  12. package/dist/fetch-event-source.d.ts +5 -1
  13. package/dist/fetch-event-source.js +15 -3
  14. package/dist/fetch-event-source.js.map +1 -1
  15. package/dist/fetch-request-factory.d.ts +3 -0
  16. package/dist/fetch-request-factory.js +47 -9
  17. package/dist/fetch-request-factory.js.map +1 -1
  18. package/dist/fetch.js +24 -5
  19. package/dist/fetch.js.map +1 -1
  20. package/dist/header-parameters.js +13 -0
  21. package/dist/header-parameters.js.map +1 -1
  22. package/dist/index.js +13 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/logger.js +13 -0
  25. package/dist/logger.js.map +1 -1
  26. package/dist/media-type-codecs/any-text-decoder.d.ts +7 -0
  27. package/dist/media-type-codecs/any-text-decoder.js +29 -0
  28. package/dist/media-type-codecs/any-text-decoder.js.map +1 -0
  29. package/dist/media-type-codecs/any-text-encoder.d.ts +5 -0
  30. package/dist/media-type-codecs/any-text-encoder.js +23 -0
  31. package/dist/media-type-codecs/any-text-encoder.js.map +1 -0
  32. package/dist/media-type-codecs/binary-decoder.js +13 -0
  33. package/dist/media-type-codecs/binary-decoder.js.map +1 -1
  34. package/dist/media-type-codecs/binary-encoder.js +13 -0
  35. package/dist/media-type-codecs/binary-encoder.js.map +1 -1
  36. package/dist/media-type-codecs/cbor-decoder.js +13 -0
  37. package/dist/media-type-codecs/cbor-decoder.js.map +1 -1
  38. package/dist/media-type-codecs/cbor-encoder.js +13 -0
  39. package/dist/media-type-codecs/cbor-encoder.js.map +1 -1
  40. package/dist/media-type-codecs/cbor-tags.js +13 -0
  41. package/dist/media-type-codecs/cbor-tags.js.map +1 -1
  42. package/dist/media-type-codecs/json-decoder.js +13 -0
  43. package/dist/media-type-codecs/json-decoder.js.map +1 -1
  44. package/dist/media-type-codecs/json-encoder.js +13 -0
  45. package/dist/media-type-codecs/json-encoder.js.map +1 -1
  46. package/dist/media-type-codecs/media-type-decoder.js +13 -0
  47. package/dist/media-type-codecs/media-type-decoder.js.map +1 -1
  48. package/dist/media-type-codecs/media-type-decoders.js +21 -3
  49. package/dist/media-type-codecs/media-type-decoders.js.map +1 -1
  50. package/dist/media-type-codecs/media-type-encoder.js +13 -0
  51. package/dist/media-type-codecs/media-type-encoder.js.map +1 -1
  52. package/dist/media-type-codecs/media-type-encoders.js +21 -3
  53. package/dist/media-type-codecs/media-type-encoders.js.map +1 -1
  54. package/dist/media-type-codecs/www-form-url-encoder.js +56 -6
  55. package/dist/media-type-codecs/www-form-url-encoder.js.map +1 -1
  56. package/dist/media-type.d.ts +4 -2
  57. package/dist/media-type.js +34 -5
  58. package/dist/media-type.js.map +1 -1
  59. package/dist/problem.js +19 -2
  60. package/dist/problem.js.map +1 -1
  61. package/dist/request-factory.d.ts +6 -0
  62. package/dist/request-factory.js +13 -0
  63. package/dist/request-factory.js.map +1 -1
  64. package/dist/result-response.d.ts +4 -0
  65. package/dist/result-response.js +15 -0
  66. package/dist/result-response.js.map +1 -0
  67. package/dist/sunday-error.js +13 -0
  68. package/dist/sunday-error.js.map +1 -1
  69. package/dist/url-template.js +13 -0
  70. package/dist/url-template.js.map +1 -1
  71. package/dist/util/any.js +13 -0
  72. package/dist/util/any.js.map +1 -1
  73. package/dist/util/base64.js +13 -0
  74. package/dist/util/base64.js.map +1 -1
  75. package/dist/util/error.d.ts +2 -0
  76. package/dist/util/error.js +26 -0
  77. package/dist/util/error.js.map +1 -0
  78. package/dist/util/hex.js +13 -0
  79. package/dist/util/hex.js.map +1 -1
  80. package/dist/util/rxjs.js +14 -2
  81. package/dist/util/rxjs.js.map +1 -1
  82. package/dist/util/stream-rxjs.js +13 -0
  83. package/dist/util/stream-rxjs.js.map +1 -1
  84. package/dist/util/temporal.js +13 -0
  85. package/dist/util/temporal.js.map +1 -1
  86. package/package.json +33 -28
  87. package/src/any-type.ts +14 -0
  88. package/src/class-type.ts +16 -2
  89. package/src/date-time-types.ts +14 -0
  90. package/src/event-parser.ts +22 -10
  91. package/src/fetch-event-source.ts +39 -11
  92. package/src/fetch-request-factory.ts +92 -32
  93. package/src/fetch.ts +27 -8
  94. package/src/header-parameters.ts +16 -2
  95. package/src/index.ts +14 -0
  96. package/src/logger.ts +14 -0
  97. package/src/media-type-codecs/any-text-decoder.ts +34 -0
  98. package/src/media-type-codecs/any-text-encoder.ts +26 -0
  99. package/src/media-type-codecs/binary-decoder.ts +16 -2
  100. package/src/media-type-codecs/binary-encoder.ts +15 -1
  101. package/src/media-type-codecs/cbor-decoder.ts +30 -16
  102. package/src/media-type-codecs/cbor-encoder.ts +28 -14
  103. package/src/media-type-codecs/cbor-tags.ts +14 -0
  104. package/src/media-type-codecs/json-decoder.ts +31 -16
  105. package/src/media-type-codecs/json-encoder.ts +21 -7
  106. package/src/media-type-codecs/media-type-decoder.ts +16 -2
  107. package/src/media-type-codecs/media-type-decoders.ts +28 -8
  108. package/src/media-type-codecs/media-type-encoder.ts +19 -5
  109. package/src/media-type-codecs/media-type-encoders.ts +28 -8
  110. package/src/media-type-codecs/www-form-url-encoder.ts +81 -17
  111. package/src/media-type.ts +46 -12
  112. package/src/problem.ts +22 -4
  113. package/src/request-factory.ts +46 -7
  114. package/src/result-response.ts +18 -0
  115. package/src/sunday-error.ts +18 -4
  116. package/src/url-template.ts +15 -1
  117. package/src/util/any.ts +14 -0
  118. package/src/util/base64.ts +15 -1
  119. package/src/util/error.ts +28 -0
  120. package/src/util/hex.ts +14 -0
  121. package/src/util/rxjs.ts +18 -5
  122. package/src/util/stream-rxjs.ts +15 -1
  123. package/src/util/temporal.ts +14 -0
@@ -1,4 +1,19 @@
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
+
1
15
  import { MediaType } from '../media-type';
16
+ import { AnyTextEncoder } from './any-text-encoder';
2
17
  import { BinaryEncoder } from './binary-encoder';
3
18
  import { CBOREncoder } from './cbor-encoder';
4
19
  import { JSONEncoder } from './json-encoder';
@@ -10,7 +25,7 @@ export interface MediaTypeEncodersBuilder {
10
25
 
11
26
  add(
12
27
  mediaType: MediaType,
13
- encoder: MediaTypeEncoder
28
+ encoder: MediaTypeEncoder,
14
29
  ): MediaTypeEncodersBuilder;
15
30
 
16
31
  build(): MediaTypeEncoders;
@@ -21,22 +36,27 @@ export interface MediaTypeEncodersBuilderConstructor {
21
36
 
22
37
  export class MediaTypeEncoders {
23
38
  static Builder: MediaTypeEncodersBuilderConstructor = class Builder
24
- implements MediaTypeEncodersBuilder {
39
+ implements MediaTypeEncodersBuilder
40
+ {
25
41
  encoders = new Map<MediaType, MediaTypeEncoder>();
26
42
 
27
43
  add(
28
44
  mediaType: MediaType,
29
- encoder: MediaTypeEncoder
45
+ encoder: MediaTypeEncoder,
30
46
  ): MediaTypeEncodersBuilder {
31
47
  this.encoders.set(mediaType, encoder);
32
48
  return this;
33
49
  }
34
50
 
35
51
  addDefaults(): MediaTypeEncodersBuilder {
36
- return this.add(MediaType.JSON, JSONEncoder.default)
37
- .add(MediaType.OctetStream, BinaryEncoder.default)
52
+ return this.add(MediaType.OctetStream, BinaryEncoder.default)
38
53
  .add(MediaType.WWWFormUrlEncoded, WWWFormUrlEncoder.default)
39
- .add(MediaType.CBOR, CBOREncoder.default);
54
+ .add(MediaType.JSON, JSONEncoder.default)
55
+ .add(MediaType.JSONStructured, JSONEncoder.default)
56
+ .add(MediaType.CBOR, CBOREncoder.default)
57
+ .add(MediaType.AnyText, AnyTextEncoder.default)
58
+ .add(MediaType.X509CACert, BinaryEncoder.default)
59
+ .add(MediaType.X509UserCert, BinaryEncoder.default);
40
60
  }
41
61
 
42
62
  build(): MediaTypeEncoders {
@@ -52,13 +72,13 @@ export class MediaTypeEncoders {
52
72
 
53
73
  supports(mediaType: MediaType): boolean {
54
74
  return Array.from(this.encoders.keys()).some((key) =>
55
- key.compatible(mediaType)
75
+ key.compatible(mediaType),
56
76
  );
57
77
  }
58
78
 
59
79
  find(mediaType: MediaType): MediaTypeEncoder {
60
80
  const found = Array.from(this.encoders.entries()).find(([type]) =>
61
- type.compatible(mediaType)
81
+ type.compatible(mediaType),
62
82
  );
63
83
  if (!found) {
64
84
  throw Error(`Unsupported media type - ${mediaType}`);
@@ -1,4 +1,28 @@
1
- import { Instant } from '@js-joda/core';
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 {
16
+ DateTimeFormatter,
17
+ Instant,
18
+ LocalDate,
19
+ LocalDateTime,
20
+ LocalTime,
21
+ OffsetDateTime,
22
+ OffsetTime,
23
+ Temporal,
24
+ ZonedDateTime,
25
+ } from '@js-joda/core';
2
26
  import { JsonStringifier } from '@outfoxx/jackson-js';
3
27
  import { URLQueryParamsEncoder } from './media-type-encoder';
4
28
 
@@ -7,7 +31,7 @@ export class WWWFormUrlEncoder implements URLQueryParamsEncoder {
7
31
  return new WWWFormUrlEncoder(
8
32
  WWWFormUrlEncoder.ArrayEncoding.UNBRACKETED,
9
33
  WWWFormUrlEncoder.BoolEncoding.LITERAL,
10
- WWWFormUrlEncoder.DateEncoding.DECIMAL_SECONDS_SINCE_EPOCH
34
+ WWWFormUrlEncoder.DateEncoding.DECIMAL_SECONDS_SINCE_EPOCH,
11
35
  );
12
36
  }
13
37
 
@@ -16,7 +40,7 @@ export class WWWFormUrlEncoder implements URLQueryParamsEncoder {
16
40
  private boolEncoding: WWWFormUrlEncoder.BoolEncoding,
17
41
  private dateEncoding: WWWFormUrlEncoder.DateEncoding,
18
42
  private json = new JsonStringifier(),
19
- private encoder = new TextEncoder()
43
+ private encoder = new TextEncoder(),
20
44
  ) {}
21
45
 
22
46
  encode<T = unknown>(value: T): ArrayBuffer | SharedArrayBuffer {
@@ -50,23 +74,35 @@ export class WWWFormUrlEncoder implements URLQueryParamsEncoder {
50
74
  components.push(
51
75
  ...this.encodeQueryComponent(
52
76
  encodeArrayKey(key, this.arrayEncoding),
53
- item
54
- )
77
+ item,
78
+ ),
55
79
  );
56
80
  }
57
- } else if (value instanceof Instant) {
81
+ } else if (value instanceof Date) {
58
82
  //
59
83
  components.push(
60
84
  encodeURIComponent(key) +
61
85
  '=' +
62
- encodeURIComponent(encodeDate(value, this.dateEncoding))
86
+ encodeURIComponent(
87
+ encodeInstant(
88
+ Instant.ofEpochMilli(value.getTime()),
89
+ this.dateEncoding,
90
+ ),
91
+ ),
92
+ );
93
+ } else if (value instanceof Temporal) {
94
+ //
95
+ components.push(
96
+ encodeURIComponent(key) +
97
+ '=' +
98
+ encodeURIComponent(encodeTemporal(value, this.dateEncoding)),
63
99
  );
64
100
  } else if (typeof value === 'boolean') {
65
101
  //
66
102
  components.push(
67
103
  encodeURIComponent(key) +
68
104
  '=' +
69
- encodeURIComponent(encodeBoolean(value, this.boolEncoding))
105
+ encodeURIComponent(encodeBoolean(value, this.boolEncoding)),
70
106
  );
71
107
  } else if (typeof value === 'object') {
72
108
  //
@@ -74,13 +110,13 @@ export class WWWFormUrlEncoder implements URLQueryParamsEncoder {
74
110
 
75
111
  for (const nestedKey of Object.keys(rec).sort()) {
76
112
  components.push(
77
- ...this.encodeQueryComponent(`${key}[${nestedKey}]`, rec[nestedKey])
113
+ ...this.encodeQueryComponent(`${key}[${nestedKey}]`, rec[nestedKey]),
78
114
  );
79
115
  }
80
116
  } else {
81
117
  //
82
118
  components.push(
83
- encodeURIComponent(key) + '=' + encodeURIComponent(`${value}`)
119
+ encodeURIComponent(key) + '=' + encodeURIComponent(`${value}`),
84
120
  );
85
121
  }
86
122
 
@@ -90,7 +126,7 @@ export class WWWFormUrlEncoder implements URLQueryParamsEncoder {
90
126
 
91
127
  function encodeArrayKey(
92
128
  key: string,
93
- encoding: WWWFormUrlEncoder.ArrayEncoding
129
+ encoding: WWWFormUrlEncoder.ArrayEncoding,
94
130
  ): string {
95
131
  return encoding === WWWFormUrlEncoder.ArrayEncoding.BRACKETED
96
132
  ? `${key}[]`
@@ -99,7 +135,7 @@ function encodeArrayKey(
99
135
 
100
136
  function encodeBoolean(
101
137
  value: boolean,
102
- encoding: WWWFormUrlEncoder.BoolEncoding
138
+ encoding: WWWFormUrlEncoder.BoolEncoding,
103
139
  ): string {
104
140
  switch (encoding) {
105
141
  case WWWFormUrlEncoder.BoolEncoding.NUMERIC:
@@ -111,18 +147,46 @@ function encodeBoolean(
111
147
  }
112
148
  }
113
149
 
114
- function encodeDate(
115
- value: Date | Instant,
116
- encoding: WWWFormUrlEncoder.DateEncoding
150
+ function encodeTemporal(
151
+ value: Temporal,
152
+ encoding: WWWFormUrlEncoder.DateEncoding,
153
+ ): string {
154
+ if (value instanceof Instant) {
155
+ return encodeInstant(value, encoding);
156
+ } else if (value instanceof OffsetDateTime) {
157
+ if (encoding == WWWFormUrlEncoder.DateEncoding.ISO8601) {
158
+ return value.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
159
+ }
160
+ return encodeInstant(value.toInstant(), encoding);
161
+ } else if (value instanceof ZonedDateTime) {
162
+ if (encoding == WWWFormUrlEncoder.DateEncoding.ISO8601) {
163
+ return value.format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
164
+ }
165
+ return encodeInstant(value.toInstant(), encoding);
166
+ } else if (value instanceof LocalDateTime) {
167
+ return value.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
168
+ } else if (value instanceof LocalDate) {
169
+ return value.format(DateTimeFormatter.ISO_LOCAL_DATE);
170
+ } else if (value instanceof LocalTime) {
171
+ return value.format(DateTimeFormatter.ISO_LOCAL_TIME);
172
+ } else if (value instanceof OffsetTime) {
173
+ return value.format(DateTimeFormatter.ISO_OFFSET_TIME);
174
+ } else {
175
+ throw Error('unsupported temporal value for ');
176
+ }
177
+ }
178
+
179
+ function encodeInstant(
180
+ value: Instant,
181
+ encoding: WWWFormUrlEncoder.DateEncoding,
117
182
  ): string {
118
- value = value instanceof Date ? Instant.ofEpochMilli(value.getTime()) : value;
119
183
  switch (encoding) {
120
184
  case WWWFormUrlEncoder.DateEncoding.DECIMAL_SECONDS_SINCE_EPOCH:
121
185
  return (value.epochSecond() + value.nano() / 1_000_000_000.0).toFixed(7);
122
186
  case WWWFormUrlEncoder.DateEncoding.MILLISECONDS_SINCE_EPOCH:
123
187
  return `${value.toEpochMilli()}`;
124
188
  case WWWFormUrlEncoder.DateEncoding.ISO8601:
125
- return value.toString();
189
+ return DateTimeFormatter.ISO_INSTANT.format(value);
126
190
  default:
127
191
  throw new Error('unknown date encoding');
128
192
  }
package/src/media-type.ts CHANGED
@@ -1,3 +1,17 @@
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
+
1
15
  export class MediaType {
2
16
  type: MediaType.Type;
3
17
  tree: MediaType.Tree;
@@ -21,7 +35,7 @@ export class MediaType {
21
35
  obj[name.toLowerCase()] = value.toLowerCase();
22
36
  return obj;
23
37
  },
24
- {} as Record<string, string>
38
+ {} as Record<string, string>,
25
39
  );
26
40
  }
27
41
 
@@ -47,7 +61,7 @@ export class MediaType {
47
61
 
48
62
  withParameter(
49
63
  parameter: MediaType.ParameterName | string,
50
- value: string
64
+ value: string,
51
65
  ): MediaType {
52
66
  const parameters = Object.assign({}, this.parameters, {
53
67
  [parameter]: value,
@@ -181,28 +195,35 @@ export namespace MediaType {
181
195
  CharSet = 'charset',
182
196
  }
183
197
 
184
- export function from(value?: string | null): MediaType | undefined;
198
+ export function from(value?: string | null): MediaType;
185
199
  export function from(
186
200
  value: string | null | undefined,
187
- def: MediaType
201
+ def: MediaType,
188
202
  ): MediaType;
189
203
  export function from(
190
204
  value?: string | null,
191
- def: MediaType | undefined = undefined
192
- ): MediaType | undefined {
193
- if (!value) {
205
+ def: MediaType | undefined = undefined,
206
+ ): MediaType {
207
+ const reqDef = () => {
208
+ if (!def) {
209
+ throw Error('Invalid media type');
210
+ }
194
211
  return def;
212
+ };
213
+
214
+ if (!value) {
215
+ return reqDef();
195
216
  }
196
217
 
197
218
  fullRegex.lastIndex = 0;
198
219
  const match = fullRegex.exec(value);
199
220
  if (match?.[0] != value) {
200
- return def;
221
+ return reqDef();
201
222
  }
202
223
 
203
224
  const type = MediaType.Type.from(match[1]?.toLowerCase());
204
225
  if (!type) {
205
- return def;
226
+ return reqDef();
206
227
  }
207
228
 
208
229
  const tree =
@@ -210,7 +231,7 @@ export namespace MediaType {
210
231
 
211
232
  const subtype = match[3]?.toLowerCase();
212
233
  if (!subtype) {
213
- return def;
234
+ return reqDef();
214
235
  }
215
236
 
216
237
  const suffix = MediaType.Suffix.from(match[4]?.toLowerCase());
@@ -239,7 +260,8 @@ export namespace MediaType {
239
260
  });
240
261
  }
241
262
 
242
- const fullRegex = /^((?:[a-z]+|\*))\/(x(?:-|\\.)|(?:(?:vnd|prs|x)\.)|\*)?([a-z0-9\-.]+|\*)(?:\+([a-z]+))?( *(?:; *(?:(?:[\w.-]+) *= *(?:[\w.-]+)) *)*)$/gi;
263
+ const fullRegex =
264
+ /^((?:[a-z]+|\*))\/(x(?:-|\\.)|(?:(?:vnd|prs|x)\.)|\*)?([a-z0-9\-.]+|\*)(?:\+([a-z]+))?( *(?:; *(?:(?:[\w.-]+) *= *(?:[\w.-]+)) *)*)$/gi;
243
265
  const paramRegex = / *; *([\w.-]+) *= *([\w.-]+)/gi;
244
266
 
245
267
  export const Plain = new MediaType({
@@ -320,9 +342,21 @@ export namespace MediaType {
320
342
  suffix: Suffix.XML,
321
343
  });
322
344
 
323
- export const ProblemJSON = new MediaType({
345
+ export const Problem = new MediaType({
324
346
  type: MediaType.Type.Application,
325
347
  subtype: 'problem',
326
348
  suffix: Suffix.JSON,
327
349
  });
350
+
351
+ export const JsonPatch = new MediaType({
352
+ type: MediaType.Type.Application,
353
+ subtype: 'json-patch',
354
+ suffix: Suffix.JSON,
355
+ });
356
+
357
+ export const MergePatch = new MediaType({
358
+ type: MediaType.Type.Application,
359
+ subtype: 'merge-patch',
360
+ suffix: Suffix.JSON,
361
+ });
328
362
  }
package/src/problem.ts CHANGED
@@ -1,3 +1,17 @@
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
+
1
15
  import { ResponseExample } from './fetch';
2
16
  import {
3
17
  JsonAnyGetter,
@@ -67,7 +81,7 @@ export class Problem extends Error implements Problem {
67
81
  constructor(spec: ProblemSpec) {
68
82
  super(`${spec.status.toString()} ${spec.type} - ${spec.title}`);
69
83
 
70
- const src = (spec as unknown) as Record<string, unknown>;
84
+ const src = spec as unknown as Record<string, unknown>;
71
85
 
72
86
  const json = Object.assign({}, src);
73
87
 
@@ -118,7 +132,7 @@ export class Problem extends Error implements Problem {
118
132
  static async fromResponse(response: Response): Promise<Problem> {
119
133
  const [bodyExcerpt, body] = await ResponseExample.bodyExcerpt(
120
134
  response,
121
- 256
135
+ 256,
122
136
  );
123
137
 
124
138
  return new Problem({
@@ -129,9 +143,13 @@ export class Problem extends Error implements Problem {
129
143
  url: response.url,
130
144
  },
131
145
  response: {
132
- type: response.type,
133
146
  headers: response.headers,
134
- trailer: response.trailer,
147
+ ok: response.ok,
148
+ redirected: response.redirected,
149
+ status: response.status,
150
+ statusText: response.statusText,
151
+ type: response.type,
152
+ url: response.url,
135
153
  body,
136
154
  example: ResponseExample.build(response, bodyExcerpt),
137
155
  },
@@ -1,9 +1,24 @@
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
+
1
15
  import { Observable } from 'rxjs';
2
16
  import { AnyType } from './any-type';
3
17
  import { ClassType, ConstructableClassType } from './class-type';
4
18
  import { MediaType } from './media-type';
5
19
  import { TextMediaTypeDecoder } from './media-type-codecs/media-type-decoder';
6
20
  import { Problem } from './problem';
21
+ import { ResultResponse } from './result-response';
7
22
  import { URLTemplate } from './url-template';
8
23
  import { Logger } from './logger';
9
24
 
@@ -12,7 +27,7 @@ export interface RequestFactory {
12
27
 
13
28
  registerProblem(
14
29
  type: URL | string,
15
- problemType: ConstructableClassType<Problem>
30
+ problemType: ConstructableClassType<Problem>,
16
31
  ): void;
17
32
 
18
33
  request(requestSpec: RequestSpec<unknown>): Observable<Request>;
@@ -21,22 +36,46 @@ export interface RequestFactory {
21
36
 
22
37
  response<B>(
23
38
  requestSpec: RequestSpec<B>,
24
- dataExpected?: boolean
39
+ dataExpected?: boolean,
25
40
  ): Observable<Response>;
26
41
 
42
+ resultResponse<B, R>(
43
+ requestSpec: RequestSpec<B>,
44
+ resultType: [ClassType<R>],
45
+ ): Observable<ResultResponse<R>>;
46
+
47
+ resultResponse<B, R>(
48
+ requestSpec: RequestSpec<B>,
49
+ resultType: [ClassType<Array<unknown>>, ClassType<R>],
50
+ ): Observable<ResultResponse<Array<R>>>;
51
+
52
+ resultResponse<B, R>(
53
+ requestSpec: RequestSpec<B>,
54
+ resultType: [ClassType<Set<unknown>>, ClassType<R>],
55
+ ): Observable<ResultResponse<Set<R>>>;
56
+
57
+ resultResponse<B, R>(
58
+ requestSpec: RequestSpec<B>,
59
+ resultType: AnyType,
60
+ ): Observable<ResultResponse<R>>;
61
+
62
+ resultResponse<B>(
63
+ requestSpec: RequestSpec<B>,
64
+ ): Observable<ResultResponse<void>>;
65
+
27
66
  result<B, R>(
28
67
  requestSpec: RequestSpec<B>,
29
- resultType: [ClassType<R>]
68
+ resultType: [ClassType<R>],
30
69
  ): Observable<R>;
31
70
 
32
71
  result<B, R>(
33
72
  requestSpec: RequestSpec<B>,
34
- resultType: [ClassType<Array<unknown>>, ClassType<R>]
73
+ resultType: [ClassType<Array<unknown>>, ClassType<R>],
35
74
  ): Observable<Array<R>>;
36
75
 
37
76
  result<B, R>(
38
77
  requestSpec: RequestSpec<B>,
39
- resultType: [ClassType<Set<unknown>>, ClassType<R>]
78
+ resultType: [ClassType<Set<unknown>>, ClassType<R>],
40
79
  ): Observable<Set<R>>;
41
80
 
42
81
  result<B, R>(requestSpec: RequestSpec<B>, resultType: AnyType): Observable<R>;
@@ -52,8 +91,8 @@ export interface RequestFactory {
52
91
  event: string | undefined,
53
92
  id: string | undefined,
54
93
  data: string,
55
- logger?: Logger
56
- ) => E | undefined
94
+ logger?: Logger,
95
+ ) => E | undefined,
57
96
  ): Observable<E>;
58
97
  }
59
98
 
@@ -0,0 +1,18 @@
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 interface ResultResponse<R> {
16
+ readonly result: R;
17
+ readonly response: Response;
18
+ }
@@ -1,3 +1,17 @@
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
+
1
15
  import { ResponseExample } from './fetch';
2
16
 
3
17
  export class SundayError extends Error {
@@ -9,18 +23,18 @@ export class SundayError extends Error {
9
23
  public statusText: string,
10
24
  public headers: Headers,
11
25
  public body: unknown | undefined,
12
- public responseExample: string
26
+ public responseExample: string,
13
27
  ) {
14
28
  super(message);
15
29
  }
16
30
 
17
31
  static async fromResponse(
18
32
  message: string,
19
- response: Response
33
+ response: Response,
20
34
  ): Promise<SundayError> {
21
35
  const [bodyExcerpt, body] = await ResponseExample.bodyExcerpt(
22
36
  response,
23
- 256
37
+ 256,
24
38
  );
25
39
 
26
40
  return new SundayError(
@@ -31,7 +45,7 @@ export class SundayError extends Error {
31
45
  response.statusText,
32
46
  response.headers,
33
47
  body,
34
- ResponseExample.build(response, bodyExcerpt)
48
+ ResponseExample.build(response, bodyExcerpt),
35
49
  );
36
50
  }
37
51
  }
@@ -1,9 +1,23 @@
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
+
1
15
  import { URI } from 'uri-template-lite';
2
16
 
3
17
  export class URLTemplate {
4
18
  constructor(
5
19
  public template: string,
6
- public parameters: Record<string, unknown> = {}
20
+ public parameters: Record<string, unknown> = {},
7
21
  ) {}
8
22
 
9
23
  complete(relativeTemplate: string, parameters: Record<string, unknown>): URL {
package/src/util/any.ts CHANGED
@@ -1,3 +1,17 @@
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
+
1
15
  export function unknownGet<T = unknown>(obj: unknown, key: string): T {
2
16
  return (obj as Record<string, unknown>)?.[key] as T;
3
17
  }
@@ -1,3 +1,17 @@
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
+
1
15
  const chars =
2
16
  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
3
17
 
@@ -17,7 +31,7 @@ export namespace Base64 {
17
31
  export function encodeSlice(
18
32
  buffer: ArrayBufferLike,
19
33
  offset: number,
20
- length: number
34
+ length: number,
21
35
  ): string {
22
36
  const bytes = new Uint8Array(buffer, offset, length);
23
37
  const len = bytes.length;
@@ -0,0 +1,28 @@
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 function isError(value: unknown): value is Error {
16
+ return value instanceof Error;
17
+ }
18
+
19
+ export function errorToMessage(value: unknown, defMsg?: string): string {
20
+ return isError(value) ? value.message : defMsg ?? `${fmtMsg(value)}`;
21
+ }
22
+
23
+ function fmtMsg(value: unknown): string {
24
+ if (value instanceof Object) {
25
+ return JSON.stringify(value);
26
+ }
27
+ return `${value}`;
28
+ }