typedrest 0.4.0 → 0.5.0

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 (67) hide show
  1. package/README.md +2 -0
  2. package/endpoints/Endpoint.js +14 -27
  3. package/endpoints/Endpoint.ts +5 -5
  4. package/endpoints/EntryEndpoint.js +3 -14
  5. package/endpoints/generic/ETagEndpointBase.js +27 -42
  6. package/endpoints/generic/ElementEndpoint.js +39 -60
  7. package/endpoints/generic/GenericCollectionEndpoint.js +70 -44
  8. package/endpoints/generic/GenericCollectionEndpoint.test.ts +123 -0
  9. package/endpoints/generic/GenericCollectionEndpoint.ts +54 -1
  10. package/endpoints/generic/PartialResponse.js +33 -0
  11. package/endpoints/generic/PartialResponse.ts +28 -0
  12. package/endpoints/generic/index.js +2 -1
  13. package/endpoints/generic/index.ts +1 -0
  14. package/endpoints/index.js +3 -2
  15. package/endpoints/index.ts +1 -0
  16. package/endpoints/raw/BlobEndpoint.js +10 -27
  17. package/endpoints/raw/UploadEndpoint.js +11 -23
  18. package/endpoints/raw/UploadEndpoint.test.ts +1 -4
  19. package/endpoints/raw/UploadEndpoint.ts +1 -2
  20. package/endpoints/reactive/Delay.js +27 -0
  21. package/endpoints/reactive/Delay.ts +26 -0
  22. package/endpoints/reactive/GenericStreamingCollectionEndpoint.js +79 -0
  23. package/endpoints/reactive/GenericStreamingCollectionEndpoint.ts +73 -0
  24. package/endpoints/reactive/PollingEndpoint.js +67 -0
  25. package/endpoints/reactive/PollingEndpoint.test.ts +84 -0
  26. package/endpoints/reactive/PollingEndpoint.ts +66 -0
  27. package/endpoints/reactive/SseStreamingEndpoint.js +120 -0
  28. package/endpoints/reactive/SseStreamingEndpoint.test.ts +169 -0
  29. package/endpoints/reactive/SseStreamingEndpoint.ts +115 -0
  30. package/endpoints/reactive/StreamingCollectionEndpoint.js +23 -0
  31. package/endpoints/reactive/StreamingCollectionEndpoint.test.ts +110 -0
  32. package/endpoints/reactive/StreamingCollectionEndpoint.ts +20 -0
  33. package/endpoints/reactive/StreamingEndpoint.js +56 -0
  34. package/endpoints/reactive/StreamingEndpoint.test.ts +130 -0
  35. package/endpoints/reactive/StreamingEndpoint.ts +50 -0
  36. package/endpoints/reactive/index.js +22 -0
  37. package/endpoints/reactive/index.ts +5 -0
  38. package/endpoints/rpc/ActionEndpoint.js +3 -14
  39. package/endpoints/rpc/ConsumerEndpoint.js +5 -16
  40. package/endpoints/rpc/FunctionEndpoint.js +6 -17
  41. package/endpoints/rpc/ProducerEndpoint.js +4 -15
  42. package/endpoints/rpc/RpcEndpointBase.js +3 -14
  43. package/errors/DefaultErrorHandler.js +20 -22
  44. package/errors/DefaultErrorHandler.ts +12 -4
  45. package/errors/Errors.js +8 -2
  46. package/errors/Errors.ts +5 -0
  47. package/http/EntityStream.js +42 -0
  48. package/http/EntityStream.ts +40 -0
  49. package/http/HttpContentRange.js +39 -0
  50. package/http/HttpContentRange.ts +41 -0
  51. package/http/HttpHeader.js +6 -1
  52. package/http/HttpHeader.ts +6 -1
  53. package/http/HttpStatusCode.js +4 -1
  54. package/http/HttpStatusCode.ts +4 -1
  55. package/http/ResponseCache.js +4 -15
  56. package/http/RetryAfter.js +24 -0
  57. package/http/RetryAfter.ts +19 -0
  58. package/http/ServerSentEvents.js +140 -0
  59. package/http/ServerSentEvents.ts +145 -0
  60. package/http/index.js +5 -1
  61. package/http/index.ts +4 -0
  62. package/jest.config.js +1 -1
  63. package/links/AggregateLinkExtractor.js +7 -18
  64. package/links/HalLinkExtractor.js +9 -20
  65. package/links/HeaderLinkExtractor.js +5 -16
  66. package/links/HeaderLinkExtractor.ts +1 -1
  67. package/package.json +9 -9
@@ -1,16 +1,8 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.GenericCollectionEndpoint = void 0;
13
4
  const ETagEndpointBase_1 = require("./ETagEndpointBase");
5
+ const PartialResponse_1 = require("./PartialResponse");
14
6
  const http_1 = require("../../http");
15
7
  /**
16
8
  * Endpoint for a collection of `TEntity`s addressable as `TElementEndpoint`s.<br>
@@ -28,6 +20,12 @@ class GenericCollectionEndpoint extends ETagEndpointBase_1.ETagEndpointBase {
28
20
  constructor(referrer, relativeUri, elementEndpoint) {
29
21
  super(referrer, relativeUri);
30
22
  this.elementEndpoint = elementEndpoint;
23
+ /**
24
+ * The unit used when requesting ranges of elements. Sent in the {@link http!HttpHeader.Range} header.
25
+ */
26
+ this.rangeUnit = "elements";
27
+ // NOTE: Only modified when the server reports its capabilities.
28
+ this.acceptedRangeUnits = [];
31
29
  this.setDefaultLinkTemplate("child", "./{id}");
32
30
  }
33
31
  /**
@@ -64,10 +62,44 @@ class GenericCollectionEndpoint extends ETagEndpointBase_1.ETagEndpointBase {
64
62
  * @throws {@link errors!ConflictError}: {@link http!HttpStatusCode.Conflict}
65
63
  * @throws {@link errors!HttpError}: Other non-success status code
66
64
  */
67
- readAll(signal) {
68
- return __awaiter(this, void 0, void 0, function* () {
69
- return this.serializer.deserialize(yield this.getContent(signal));
65
+ async readAll(signal) {
66
+ return this.serializer.deserialize(await this.getContent(signal));
67
+ }
68
+ /**
69
+ * @inheritDoc
70
+ */
71
+ handleCapabilities(response) {
72
+ super.handleCapabilities(response);
73
+ const header = response.headers.get(http_1.HttpHeader.AcceptRanges);
74
+ if (header) {
75
+ this.acceptedRangeUnits = header.split(",").map(x => x.trim());
76
+ }
77
+ }
78
+ /**
79
+ * Shows whether the server has indicated that {@link readRange} is currently allowed.
80
+ * Uses cached data from last response.
81
+ * @returns `true` if the method is allowed, `false` if the method is not allowed, `undefined` if no request has been sent yet or the server did not specify accepted range units.
82
+ */
83
+ get readRangeAllowed() {
84
+ if (this.acceptedRangeUnits.length === 0)
85
+ return undefined;
86
+ return this.acceptedRangeUnits.indexOf(this.rangeUnit) !== -1;
87
+ }
88
+ /**
89
+ * Returns a subset of the `TEntity`s in the collection.
90
+ * @param from The index of the first element to return. Leave unspecified to return the last `to` elements ("tail").
91
+ * @param to The index of the last element to return. Leave unspecified to return all elements starting at `from`.
92
+ * @param signal Used to cancel the request.
93
+ * @throws {@link errors!AuthenticationError}: {@link http!HttpStatusCode.Unauthorized}
94
+ * @throws {@link errors!AuthorizationError}: {@link http!HttpStatusCode.Forbidden}
95
+ * @throws {@link errors!RangeNotSatisfiableError}: {@link http!HttpStatusCode.RangeNotSatisfiable}, i.e. the requested range lies outside of the elements currently available
96
+ * @throws {@link errors!HttpError}: Other non-success status code
97
+ */
98
+ async readRange(from, to, signal) {
99
+ const response = await this.send(http_1.HttpMethod.Get, signal, {
100
+ [http_1.HttpHeader.Range]: `${this.rangeUnit}=${from !== null && from !== void 0 ? from : ""}-${to !== null && to !== void 0 ? to : ""}`
70
101
  });
102
+ return new PartialResponse_1.PartialResponse(this.serializer.deserialize(await response.text()), http_1.HttpContentRange.from(response));
71
103
  }
72
104
  /**
73
105
  * Shows whether the server has indicated that {@link create} is currently allowed.
@@ -86,30 +118,28 @@ class GenericCollectionEndpoint extends ETagEndpointBase_1.ETagEndpointBase {
86
118
  * @throws {@link errors!ConflictError}: {@link http!HttpStatusCode.Conflict}
87
119
  * @throws {@link errors!HttpError}: Other non-success status code
88
120
  */
89
- create(entity, signal) {
90
- return __awaiter(this, void 0, void 0, function* () {
91
- const response = yield this.send(http_1.HttpMethod.Post, signal, {
92
- [http_1.HttpHeader.ContentType]: this.serializer.supportedMediaTypes[0]
93
- }, this.serializer.serialize(entity));
94
- const location = response.headers.get(http_1.HttpHeader.Location);
95
- let elementEndpoint;
96
- if (location) {
97
- // Explicit element endpoint URL from "Location" header
98
- elementEndpoint = new this.elementEndpoint(this, this.join(location));
121
+ async create(entity, signal) {
122
+ const response = await this.send(http_1.HttpMethod.Post, signal, {
123
+ [http_1.HttpHeader.ContentType]: this.serializer.supportedMediaTypes[0]
124
+ }, this.serializer.serialize(entity));
125
+ const location = response.headers.get(http_1.HttpHeader.Location);
126
+ let elementEndpoint;
127
+ if (location) {
128
+ // Explicit element endpoint URL from "Location" header
129
+ elementEndpoint = new this.elementEndpoint(this, this.join(location));
130
+ }
131
+ else {
132
+ try {
133
+ // Infer URL from entity ID in response body
134
+ elementEndpoint = this.get(this.serializer.deserialize(await response.clone().text()));
99
135
  }
100
- else {
101
- try {
102
- // Infer URL from entity ID in response body
103
- elementEndpoint = this.get(this.serializer.deserialize(yield response.clone().text()));
104
- }
105
- catch (_a) {
106
- // No element endpoint
107
- return undefined;
108
- }
136
+ catch (_a) {
137
+ // No element endpoint
138
+ return undefined;
109
139
  }
110
- elementEndpoint.responseCache = yield http_1.ResponseCache.from(response);
111
- return elementEndpoint;
112
- });
140
+ }
141
+ elementEndpoint.responseCache = await http_1.ResponseCache.from(response);
142
+ return elementEndpoint;
113
143
  }
114
144
  /**
115
145
  * Shows whether the server has indicated that {@link createAll} is currently allowed.
@@ -127,12 +157,10 @@ class GenericCollectionEndpoint extends ETagEndpointBase_1.ETagEndpointBase {
127
157
  * @throws {@link errors!ConflictError}: {@link http!HttpStatusCode.Conflict}
128
158
  * @throws {@link errors!HttpError}: Other non-success status code
129
159
  */
130
- createAll(entities, signal) {
131
- return __awaiter(this, void 0, void 0, function* () {
132
- yield this.send(http_1.HttpMethod.Patch, signal, {
133
- [http_1.HttpHeader.ContentType]: this.serializer.supportedMediaTypes[0]
134
- }, this.serializer.serialize(entities));
135
- });
160
+ async createAll(entities, signal) {
161
+ await this.send(http_1.HttpMethod.Patch, signal, {
162
+ [http_1.HttpHeader.ContentType]: this.serializer.supportedMediaTypes[0]
163
+ }, this.serializer.serialize(entities));
136
164
  }
137
165
  /**
138
166
  * Shows whether the server has indicated that {@link setAll} is currently allowed.
@@ -149,9 +177,7 @@ class GenericCollectionEndpoint extends ETagEndpointBase_1.ETagEndpointBase {
149
177
  * @throws {@link errors!ConflictError}: {@link http!HttpStatusCode.Conflict}
150
178
  * @throws {@link errors!HttpError}: Other non-success status code
151
179
  */
152
- setAll(entities) {
153
- return __awaiter(this, void 0, void 0, function* () { yield this.putContent(entities); });
154
- }
180
+ async setAll(entities) { await this.putContent(entities); }
155
181
  /**
156
182
  * Determines whether the collection contains a specific element.
157
183
  * @param element The ID identifying the entity or an entity to extract the ID from.
@@ -193,4 +219,4 @@ class GenericCollectionEndpoint extends ETagEndpointBase_1.ETagEndpointBase {
193
219
  delete(element) { return this.get(element).delete(); }
194
220
  }
195
221
  exports.GenericCollectionEndpoint = GenericCollectionEndpoint;
196
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiR2VuZXJpY0NvbGxlY3Rpb25FbmRwb2ludC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIkdlbmVyaWNDb2xsZWN0aW9uRW5kcG9pbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUEseURBQXNEO0FBSXRELHFDQUFtRTtBQUVuRTs7Ozs7R0FLRztBQUNILE1BQWEseUJBQXNGLFNBQVEsbUNBQWdCO0lBQ3ZIOzs7OztPQUtHO0lBQ0gsWUFBWSxRQUFrQixFQUFFLFdBQXlCLEVBQW1CLGVBQXVFO1FBQy9JLEtBQUssQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFEMkMsb0JBQWUsR0FBZixlQUFlLENBQXdEO1FBRS9JLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7T0FHRztJQUNILEdBQUcsQ0FBQyxPQUEyQjtRQUMzQixJQUFJLE9BQU8sSUFBSSxJQUFJO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1FBRWpGLElBQUksRUFBVSxDQUFDO1FBQ2YsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM5QixFQUFFLEdBQUcsT0FBTyxDQUFDO1FBQ2pCLENBQUM7YUFBTSxDQUFDO1lBQ0osRUFBRSxHQUFJLE9BQWUsQ0FBQyxFQUFFLENBQUM7WUFDekIsSUFBSSxFQUFFLEtBQUssU0FBUztnQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLFdBQVcsT0FBTyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBQzlGLENBQUM7UUFDRCxJQUFJLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxLQUFLLEVBQUU7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7UUFFOUUsT0FBTyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLEVB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
222
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiR2VuZXJpY0NvbGxlY3Rpb25FbmRwb2ludC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIkdlbmVyaWNDb2xsZWN0aW9uRW5kcG9pbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEseURBQXNEO0FBRXRELHVEQUFvRDtBQUdwRCxxQ0FBcUY7QUFFckY7Ozs7O0dBS0c7QUFDSCxNQUFhLHlCQUFzRixTQUFRLG1DQUFnQjtJQUN2SDs7Ozs7T0FLRztJQUNILFlBQVksUUFBa0IsRUFBRSxXQUF5QixFQUFtQixlQUF1RTtRQUMvSSxLQUFLLENBQUMsUUFBUSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBRDJDLG9CQUFlLEdBQWYsZUFBZSxDQUF3RDtRQTJDbko7O1dBRUc7UUFDSCxjQUFTLEdBQUcsVUFBVSxDQUFDO1FBRXZCLGdFQUFnRTtRQUN4RCx1QkFBa0IsR0FBYSxFQUFFLENBQUM7UUEvQ3RDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOzs7T0FHRztJQUNILEdBQUcsQ0FBQyxPQUEyQjtRQUMzQixJQUFJLE9BQU8sSUFBSSxJQUFJO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO1FBRWpGLElBQUksRUFBVSxDQUFDO1FBQ2YsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM5QixFQUFFLEdBQUcsT0FBTyxDQUFDO1FBQ2pCLENBQUM7YUFBTSxDQUFDO1lBQ0osRUFBRSxHQUFJLE9BQWUsQ0FBQyxFQUFFLENBQUM7WUFDekIsSUFBSSxFQUFFLEtBQUssU0FBUztnQkFBRSxNQUFNLElBQUksS0FBSyxDQUFDLFdBQVcsT0FBTyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBQzlGLENBQUM7UUFDRCxJQUFJLEVBQUUsSUFBSSxJQUFJLElBQUksRUFBRSxLQUFLLEVBQUU7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFD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
@@ -0,0 +1,123 @@
1
+ /**
2
+ * NOTE: The jsdom environment strips the "Range" request header, so these tests need the node environment.
3
+ * @jest-environment node
4
+ */
5
+
6
+ import fetchMock from 'jest-fetch-mock';
7
+ import { CollectionEndpoint } from '.';
8
+ import { EntryEndpoint } from '..';
9
+ import { HttpHeader, HttpStatusCode, HttpContentRange } from '../../http';
10
+ import { RangeNotSatisfiableError } from '../../errors';
11
+
12
+ class MockEntity {
13
+ constructor(public id: number, public name: string) { }
14
+ }
15
+
16
+ fetchMock.enableMocks();
17
+ let endpoint: CollectionEndpoint<MockEntity>;
18
+
19
+ beforeEach(() => {
20
+ fetchMock.resetMocks();
21
+ endpoint = new CollectionEndpoint(new EntryEndpoint('http://localhost/'), 'endpoint');
22
+ });
23
+
24
+ test('readRange', async () => {
25
+ fetchMock.mockOnceIf(
26
+ 'http://localhost/endpoint',
27
+ async req => {
28
+ expect(req.headers.get(HttpHeader.Range)).toBe('elements=1-2');
29
+ return {
30
+ body: '[{"id":6,"name":"test2"}, {"id":7,"name":"test3"}]',
31
+ status: HttpStatusCode.PartialContent,
32
+ headers: {
33
+ [HttpHeader.ContentRange]: 'elements 1-2/3'
34
+ }
35
+ };
36
+ }
37
+ );
38
+
39
+ const result = await endpoint.readRange(1, 2);
40
+ expect(result.elements).toEqual([new MockEntity(6, 'test2'), new MockEntity(7, 'test3')]);
41
+ expect(result.range).toEqual(new HttpContentRange('elements', 1, 2, 3));
42
+ expect(result.endReached).toBe(true);
43
+ });
44
+
45
+ test('readRangeOffset', async () => {
46
+ fetchMock.mockOnceIf(
47
+ 'http://localhost/endpoint',
48
+ async req => {
49
+ expect(req.headers.get(HttpHeader.Range)).toBe('elements=1-');
50
+ return {
51
+ body: '[{"id":6,"name":"test2"}]',
52
+ status: HttpStatusCode.PartialContent,
53
+ headers: {
54
+ [HttpHeader.ContentRange]: 'elements 1-1/*'
55
+ }
56
+ };
57
+ }
58
+ );
59
+
60
+ const result = await endpoint.readRange(1);
61
+ expect(result.elements).toEqual([new MockEntity(6, 'test2')]);
62
+ expect(result.range).toEqual(new HttpContentRange('elements', 1, 1, undefined));
63
+ expect(result.endReached).toBe(false);
64
+ });
65
+
66
+ test('readRangeTail', async () => {
67
+ fetchMock.mockOnceIf(
68
+ 'http://localhost/endpoint',
69
+ async req => {
70
+ expect(req.headers.get(HttpHeader.Range)).toBe('elements=-1');
71
+ return {
72
+ body: '[{"id":6,"name":"test2"}]',
73
+ status: HttpStatusCode.PartialContent
74
+ };
75
+ }
76
+ );
77
+
78
+ const result = await endpoint.readRange(undefined, 1);
79
+ expect(result.elements).toEqual([new MockEntity(6, 'test2')]);
80
+ expect(result.range).toBeUndefined();
81
+ expect(result.endReached).toBe(true);
82
+ });
83
+
84
+ test('readRangeNotSatisfiable', async () => {
85
+ fetchMock.mockOnceIf(
86
+ 'http://localhost/endpoint',
87
+ async () => ({ status: HttpStatusCode.RangeNotSatisfiable })
88
+ );
89
+
90
+ await expect(endpoint.readRange(1)).rejects.toThrow(RangeNotSatisfiableError);
91
+ });
92
+
93
+ test('readRangeAllowed', async () => {
94
+ expect(endpoint.readRangeAllowed).toBeUndefined();
95
+
96
+ fetchMock.mockOnceIf(
97
+ 'http://localhost/endpoint',
98
+ '[]',
99
+ {
100
+ headers: {
101
+ [HttpHeader.AcceptRanges]: 'elements'
102
+ }
103
+ }
104
+ );
105
+ await endpoint.readAll();
106
+
107
+ expect(endpoint.readRangeAllowed).toBe(true);
108
+ });
109
+
110
+ test('readRangeNotAllowed', async () => {
111
+ fetchMock.mockOnceIf(
112
+ 'http://localhost/endpoint',
113
+ '[]',
114
+ {
115
+ headers: {
116
+ [HttpHeader.AcceptRanges]: 'none'
117
+ }
118
+ }
119
+ );
120
+ await endpoint.readAll();
121
+
122
+ expect(endpoint.readRangeAllowed).toBe(false);
123
+ });
@@ -1,8 +1,9 @@
1
1
  import { ETagEndpointBase } from "./ETagEndpointBase";
2
2
  import { ElementEndpoint } from "./ElementEndpoint";
3
+ import { PartialResponse } from "./PartialResponse";
3
4
  import { Endpoint } from "../Endpoint";
4
5
  import { CachingEndpoint } from "../CachingEndpoint";
5
- import { HttpMethod, HttpHeader, ResponseCache } from "../../http";
6
+ import { HttpMethod, HttpHeader, HttpContentRange, ResponseCache } from "../../http";
6
7
 
7
8
  /**
8
9
  * Endpoint for a collection of `TEntity`s addressable as `TElementEndpoint`s.<br>
@@ -60,6 +61,58 @@ export class GenericCollectionEndpoint<TEntity, TElementEndpoint extends Element
60
61
  return this.serializer.deserialize<TEntity[]>(await this.getContent(signal));
61
62
  }
62
63
 
64
+ /**
65
+ * The unit used when requesting ranges of elements. Sent in the {@link http!HttpHeader.Range} header.
66
+ */
67
+ rangeUnit = "elements";
68
+
69
+ // NOTE: Only modified when the server reports its capabilities.
70
+ private acceptedRangeUnits: string[] = [];
71
+
72
+ /**
73
+ * @inheritDoc
74
+ */
75
+ protected handleCapabilities(response: Response) {
76
+ super.handleCapabilities(response);
77
+
78
+ const header = response.headers.get(HttpHeader.AcceptRanges);
79
+ if (header) {
80
+ this.acceptedRangeUnits = header.split(",").map(x => x.trim());
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Shows whether the server has indicated that {@link readRange} is currently allowed.
86
+ * Uses cached data from last response.
87
+ * @returns `true` if the method is allowed, `false` if the method is not allowed, `undefined` if no request has been sent yet or the server did not specify accepted range units.
88
+ */
89
+ get readRangeAllowed(): boolean | undefined {
90
+ if (this.acceptedRangeUnits.length === 0)
91
+ return undefined;
92
+
93
+ return this.acceptedRangeUnits.indexOf(this.rangeUnit) !== -1;
94
+ }
95
+
96
+ /**
97
+ * Returns a subset of the `TEntity`s in the collection.
98
+ * @param from The index of the first element to return. Leave unspecified to return the last `to` elements ("tail").
99
+ * @param to The index of the last element to return. Leave unspecified to return all elements starting at `from`.
100
+ * @param signal Used to cancel the request.
101
+ * @throws {@link errors!AuthenticationError}: {@link http!HttpStatusCode.Unauthorized}
102
+ * @throws {@link errors!AuthorizationError}: {@link http!HttpStatusCode.Forbidden}
103
+ * @throws {@link errors!RangeNotSatisfiableError}: {@link http!HttpStatusCode.RangeNotSatisfiable}, i.e. the requested range lies outside of the elements currently available
104
+ * @throws {@link errors!HttpError}: Other non-success status code
105
+ */
106
+ async readRange(from?: number, to?: number, signal?: AbortSignal): Promise<PartialResponse<TEntity>> {
107
+ const response = await this.send(HttpMethod.Get, signal, {
108
+ [HttpHeader.Range]: `${this.rangeUnit}=${from ?? ""}-${to ?? ""}`
109
+ });
110
+
111
+ return new PartialResponse<TEntity>(
112
+ this.serializer.deserialize<TEntity[]>(await response.text()),
113
+ HttpContentRange.from(response));
114
+ }
115
+
63
116
  /**
64
117
  * Shows whether the server has indicated that {@link create} is currently allowed.
65
118
  * Uses cached data from last response.
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PartialResponse = void 0;
4
+ /**
5
+ * Represents a subset of a set of elements.
6
+ * @typeParam TEntity The type of element the response contains.
7
+ */
8
+ class PartialResponse {
9
+ /**
10
+ * Creates a new partial response.
11
+ * @param elements The returned elements.
12
+ * @param range The range the `elements` come from.
13
+ */
14
+ constructor(elements, range) {
15
+ this.elements = elements;
16
+ this.range = range;
17
+ }
18
+ /**
19
+ * Indicates whether the response reaches the end of the elements available on the server.
20
+ */
21
+ get endReached() {
22
+ var _a;
23
+ // No range specified, must be complete response
24
+ if (((_a = this.range) === null || _a === void 0 ? void 0 : _a.to) === undefined)
25
+ return true;
26
+ // No length specified, can't be the end
27
+ if (this.range.length === undefined)
28
+ return false;
29
+ return this.range.to === this.range.length - 1;
30
+ }
31
+ }
32
+ exports.PartialResponse = PartialResponse;
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFydGlhbFJlc3BvbnNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiUGFydGlhbFJlc3BvbnNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBOzs7R0FHRztBQUNILE1BQWEsZUFBZTtJQUN4Qjs7OztPQUlHO0lBQ0gsWUFBNEIsUUFBbUIsRUFBa0IsS0FBd0I7UUFBN0QsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUFrQixVQUFLLEdBQUwsS0FBSyxDQUFtQjtJQUN6RixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLFVBQVU7O1FBQ1YsZ0RBQWdEO1FBQ2hELElBQUksQ0FBQSxNQUFBLElBQUksQ0FBQyxLQUFLLDBDQUFFLEVBQUUsTUFBSyxTQUFTO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFFOUMsd0NBQXdDO1FBQ3hDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssU0FBUztZQUFFLE9BQU8sS0FBSyxDQUFDO1FBRWxELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ25ELENBQUM7Q0FDSjtBQXJCRCwwQ0FxQkMifQ==
@@ -0,0 +1,28 @@
1
+ import { HttpContentRange } from "../../http";
2
+
3
+ /**
4
+ * Represents a subset of a set of elements.
5
+ * @typeParam TEntity The type of element the response contains.
6
+ */
7
+ export class PartialResponse<TEntity> {
8
+ /**
9
+ * Creates a new partial response.
10
+ * @param elements The returned elements.
11
+ * @param range The range the `elements` come from.
12
+ */
13
+ constructor(public readonly elements: TEntity[], public readonly range?: HttpContentRange) {
14
+ }
15
+
16
+ /**
17
+ * Indicates whether the response reaches the end of the elements available on the server.
18
+ */
19
+ get endReached(): boolean {
20
+ // No range specified, must be complete response
21
+ if (this.range?.to === undefined) return true;
22
+
23
+ // No length specified, can't be the end
24
+ if (this.range.length === undefined) return false;
25
+
26
+ return this.range.to === this.range.length - 1;
27
+ }
28
+ }
@@ -16,7 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./IndexerEndpoint"), exports);
18
18
  __exportStar(require("./ETagEndpointBase"), exports);
19
+ __exportStar(require("./PartialResponse"), exports);
19
20
  __exportStar(require("./GenericCollectionEndpoint"), exports);
20
21
  __exportStar(require("./CollectionEndpoint"), exports);
21
22
  __exportStar(require("./ElementEndpoint"), exports);
22
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsb0RBQWtDO0FBQ2xDLHFEQUFtQztBQUNuQyw4REFBNEM7QUFDNUMsdURBQXFDO0FBQ3JDLG9EQUFrQyJ9
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsb0RBQWtDO0FBQ2xDLHFEQUFtQztBQUNuQyxvREFBa0M7QUFDbEMsOERBQTRDO0FBQzVDLHVEQUFxQztBQUNyQyxvREFBa0MifQ==
@@ -1,5 +1,6 @@
1
1
  export * from "./IndexerEndpoint";
2
2
  export * from "./ETagEndpointBase";
3
+ export * from "./PartialResponse";
3
4
  export * from "./GenericCollectionEndpoint";
4
5
  export * from "./CollectionEndpoint";
5
6
  export * from "./ElementEndpoint";
@@ -36,11 +36,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
36
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.raw = exports.rpc = exports.generic = void 0;
39
+ exports.reactive = exports.raw = exports.rpc = exports.generic = void 0;
40
40
  exports.generic = __importStar(require("./generic"));
41
41
  exports.rpc = __importStar(require("./rpc"));
42
42
  exports.raw = __importStar(require("./raw"));
43
+ exports.reactive = __importStar(require("./reactive"));
43
44
  __exportStar(require("./Endpoint"), exports);
44
45
  __exportStar(require("./EntryEndpoint"), exports);
45
46
  __exportStar(require("./CachingEndpoint"), exports);
46
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxREFBcUM7QUFDckMsNkNBQTZCO0FBQzdCLDZDQUE2QjtBQUU3Qiw2Q0FBMkI7QUFDM0Isa0RBQWdDO0FBQ2hDLG9EQUFrQyJ9
47
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxREFBcUM7QUFDckMsNkNBQTZCO0FBQzdCLDZDQUE2QjtBQUM3Qix1REFBdUM7QUFFdkMsNkNBQTJCO0FBQzNCLGtEQUFnQztBQUNoQyxvREFBa0MifQ==
@@ -1,6 +1,7 @@
1
1
  export * as generic from "./generic";
2
2
  export * as rpc from "./rpc";
3
3
  export * as raw from "./raw";
4
+ export * as reactive from "./reactive";
4
5
 
5
6
  export * from "./Endpoint";
6
7
  export * from "./EntryEndpoint";
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.BlobEndpoint = void 0;
13
4
  const Endpoint_1 = require("../Endpoint");
@@ -32,10 +23,8 @@ class BlobEndpoint extends Endpoint_1.Endpoint {
32
23
  * @throws {@link errors!NotFoundError}: {@link http!HttpStatusCode.NotFound} or {@link http!HttpStatusCode.Gone}
33
24
  * @throws {@link errors!HttpError}: Other non-success status code
34
25
  */
35
- probe(signal) {
36
- return __awaiter(this, void 0, void 0, function* () {
37
- yield this.send(http_1.HttpMethod.Options, signal);
38
- });
26
+ async probe(signal) {
27
+ await this.send(http_1.HttpMethod.Options, signal);
39
28
  }
40
29
  /**
41
30
  * Shows whether the server has indicated that {@link download} is currently allowed.
@@ -52,11 +41,9 @@ class BlobEndpoint extends Endpoint_1.Endpoint {
52
41
  * @throws {@link errors!NotFoundError}: {@link http!HttpStatusCode.NotFound} or {@link http!HttpStatusCode.Gone}
53
42
  * @throws {@link errors!HttpError}: Other non-success status code
54
43
  */
55
- download(signal) {
56
- return __awaiter(this, void 0, void 0, function* () {
57
- const response = yield this.send(http_1.HttpMethod.Get, signal);
58
- return response.blob();
59
- });
44
+ async download(signal) {
45
+ const response = await this.send(http_1.HttpMethod.Get, signal);
46
+ return response.blob();
60
47
  }
61
48
  /**
62
49
  * Shows whether the server has indicated that {@link upload} is currently allowed.
@@ -73,10 +60,8 @@ class BlobEndpoint extends Endpoint_1.Endpoint {
73
60
  * @throws {@link errors!AuthorizationError}: {@link http!HttpStatusCode.Forbidden}
74
61
  * @throws {@link errors!HttpError}: Other non-success status code
75
62
  */
76
- uploadFrom(blob, signal) {
77
- return __awaiter(this, void 0, void 0, function* () {
78
- yield this.send(http_1.HttpMethod.Put, signal, { [http_1.HttpHeader.ContentType]: blob.type }, blob);
79
- });
63
+ async uploadFrom(blob, signal) {
64
+ await this.send(http_1.HttpMethod.Put, signal, { [http_1.HttpHeader.ContentType]: blob.type }, blob);
80
65
  }
81
66
  /**
82
67
  * Shows whether the server has indicated that {@link delete} is currently allowed.
@@ -93,11 +78,9 @@ class BlobEndpoint extends Endpoint_1.Endpoint {
93
78
  * @throws {@link errors!NotFoundError}: {@link http!HttpStatusCode.NotFound} or {@link http!HttpStatusCode.Gone}
94
79
  * @throws {@link errors!HttpError}: Other non-success status code
95
80
  */
96
- delete(signal) {
97
- return __awaiter(this, void 0, void 0, function* () {
98
- yield this.send(http_1.HttpMethod.Delete, signal);
99
- });
81
+ async delete(signal) {
82
+ await this.send(http_1.HttpMethod.Delete, signal);
100
83
  }
101
84
  }
102
85
  exports.BlobEndpoint = BlobEndpoint;
103
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmxvYkVuZHBvaW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiQmxvYkVuZHBvaW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUFBLDBDQUF1QztBQUN2QyxxQ0FBb0Q7QUFFcEQ7O0dBRUc7QUFDSCxNQUFhLFlBQWEsU0FBUSxtQkFBUTtJQUN0Qzs7OztPQUlHO0lBQ0gsWUFBWSxRQUFrQixFQUFFLFdBQXlCO1FBQ3JELEtBQUssQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDRyxLQUFLLENBQUMsTUFBb0I7O1lBQzVCLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBVSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNoRCxDQUFDO0tBQUE7SUFFRDs7OztPQUlHO0lBQ0gsSUFBSSxlQUFlLEtBQUssT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLGlCQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXRFOzs7Ozs7OztPQVFHO0lBQ0csUUFBUSxDQUFDLE1BQW9COztZQUMvQixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDekQsT0FBTyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDM0IsQ0FBQztLQUFBO0lBRUQ7Ozs7T0FJRztJQUNILElBQUksYUFBYSxLQUFLLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxpQkFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUVwRTs7Ozs7Ozs7T0FRRztJQUNHLFVBQVUsQ0FBQyxJQUFVLEVBQUUsTUFBb0I7O1lBQzdDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBVSxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLGlCQUFVLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzNGLENBQUM7S0FBQTtJQUVEOzs7O09BSUc7SUFDSCxJQUFJLGFBQWEsS0FBSyxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsaUJBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFdkU7Ozs7Ozs7O09BUUc7SUFDRyxNQUFNLENBQUMsTUFBb0I7O1lBQzdCLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBVSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUMvQyxDQUFDO0tBQUE7Q0FDSjtBQWxGRCxvQ0FrRkMifQ==
86
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQmxvYkVuZHBvaW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiQmxvYkVuZHBvaW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDBDQUF1QztBQUN2QyxxQ0FBb0Q7QUFFcEQ7O0dBRUc7QUFDSCxNQUFhLFlBQWEsU0FBUSxtQkFBUTtJQUN0Qzs7OztPQUlHO0lBQ0gsWUFBWSxRQUFrQixFQUFFLFdBQXlCO1FBQ3JELEtBQUssQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQW9CO1FBQzVCLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBVSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNoRCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILElBQUksZUFBZSxLQUFLLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxpQkFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUV0RTs7Ozs7Ozs7T0FRRztJQUNILEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBb0I7UUFDL0IsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFVLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3pELE9BQU8sUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBSSxhQUFhLEtBQUssT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLGlCQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXBFOzs7Ozs7OztPQVFHO0lBQ0gsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFVLEVBQUUsTUFBb0I7UUFDN0MsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFVLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsaUJBQVUsQ0FBQyxXQUFXLENBQUMsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDM0YsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxJQUFJLGFBQWEsS0FBSyxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsaUJBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFdkU7Ozs7Ozs7O09BUUc7SUFDSCxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQW9CO1FBQzdCLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBVSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMvQyxDQUFDO0NBQ0o7QUFsRkQsb0NBa0ZDIn0=
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.UploadEndpoint = void 0;
13
4
  const Endpoint_1 = require("../Endpoint");
@@ -25,7 +16,6 @@ class UploadEndpoint extends Endpoint_1.Endpoint {
25
16
  constructor(referrer, relativeUri, formField) {
26
17
  super(referrer, relativeUri);
27
18
  this.formField = formField;
28
- this.formField = formField;
29
19
  }
30
20
  /**
31
21
  * Uploads data to the endpoint.
@@ -37,19 +27,17 @@ class UploadEndpoint extends Endpoint_1.Endpoint {
37
27
  * @throws {@link errors!NotFoundError}: {@link http!HttpStatusCode.NotFound} or {@link http!HttpStatusCode.Gone}
38
28
  * @throws {@link errors!HttpError}: Other non-success status code
39
29
  */
40
- uploadFrom(blob, signal) {
41
- return __awaiter(this, void 0, void 0, function* () {
42
- const fileName = blob instanceof File ? blob.name : undefined;
43
- if (this.formField) {
44
- const formData = new FormData();
45
- formData.set(this.formField, blob, fileName);
46
- yield this.send(http_1.HttpMethod.Post, signal, { [http_1.HttpHeader.ContentType]: "multipart/form-data" }, formData);
47
- }
48
- else {
49
- yield this.send(http_1.HttpMethod.Post, signal, { [http_1.HttpHeader.ContentType]: blob.type }, blob);
50
- }
51
- });
30
+ async uploadFrom(blob, signal) {
31
+ const fileName = blob instanceof File ? blob.name : undefined;
32
+ if (this.formField) {
33
+ const formData = new FormData();
34
+ formData.set(this.formField, blob, fileName);
35
+ await this.send(http_1.HttpMethod.Post, signal, undefined, formData);
36
+ }
37
+ else {
38
+ await this.send(http_1.HttpMethod.Post, signal, { [http_1.HttpHeader.ContentType]: blob.type }, blob);
39
+ }
52
40
  }
53
41
  }
54
42
  exports.UploadEndpoint = UploadEndpoint;
55
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXBsb2FkRW5kcG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJVcGxvYWRFbmRwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQSwwQ0FBdUM7QUFDdkMscUNBQW9EO0FBRXBEOztHQUVHO0FBQ0gsTUFBYSxjQUFlLFNBQVEsbUJBQVE7SUFDeEM7Ozs7O09BS0c7SUFDSCxZQUFZLFFBQWtCLEVBQUUsV0FBeUIsRUFBbUIsU0FBa0I7UUFDMUYsS0FBSyxDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUQyQyxjQUFTLEdBQVQsU0FBUyxDQUFTO1FBRTFGLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO0lBQy9CLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDRyxVQUFVLENBQUMsSUFBaUIsRUFBRSxNQUFvQjs7WUFDcEQsTUFBTSxRQUFRLEdBQUcsSUFBSSxZQUFZLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1lBRTlELElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNqQixNQUFNLFFBQVEsR0FBRyxJQUFJLFFBQVEsRUFBRSxDQUFDO2dCQUNoQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUM3QyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQVUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQyxpQkFBVSxDQUFDLFdBQVcsQ0FBQyxFQUFFLHFCQUFxQixFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDNUcsQ0FBQztpQkFBTSxDQUFDO2dCQUNKLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBVSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLGlCQUFVLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzVGLENBQUM7UUFDTCxDQUFDO0tBQUE7Q0FDSjtBQWpDRCx3Q0FpQ0MifQ==
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXBsb2FkRW5kcG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJVcGxvYWRFbmRwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQ0FBdUM7QUFDdkMscUNBQW9EO0FBRXBEOztHQUVHO0FBQ0gsTUFBYSxjQUFlLFNBQVEsbUJBQVE7SUFDeEM7Ozs7O09BS0c7SUFDSCxZQUFZLFFBQWtCLEVBQUUsV0FBeUIsRUFBbUIsU0FBa0I7UUFDMUYsS0FBSyxDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUQyQyxjQUFTLEdBQVQsU0FBUyxDQUFTO0lBRTlGLENBQUM7SUFFRDs7Ozs7Ozs7O09BU0c7SUFDSCxLQUFLLENBQUMsVUFBVSxDQUFDLElBQWlCLEVBQUUsTUFBb0I7UUFDcEQsTUFBTSxRQUFRLEdBQUcsSUFBSSxZQUFZLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBRTlELElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sUUFBUSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUM7WUFDaEMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxRQUFRLENBQUMsQ0FBQztZQUM3QyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQVUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNsRSxDQUFDO2FBQU0sQ0FBQztZQUNKLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBVSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDLGlCQUFVLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzVGLENBQUM7SUFDTCxDQUFDO0NBQ0o7QUFoQ0Qsd0NBZ0NDIn0=
@@ -32,10 +32,7 @@ test('uploadFromForm', async () => {
32
32
 
33
33
  fetchMock.mockOnceIf(
34
34
  req => req.method === HttpMethod.Post && req.url === 'http://localhost/endpoint',
35
- async req => {
36
- expect(req.headers.get(HttpHeader.ContentType)).toBe('multipart/form-data');
37
- return {};
38
- }
35
+ async () => ({})
39
36
  );
40
37
 
41
38
  await endpoint.uploadFrom(file);
@@ -13,7 +13,6 @@ export class UploadEndpoint extends Endpoint {
13
13
  */
14
14
  constructor(referrer: Endpoint, relativeUri: URL | string, private readonly formField?: string) {
15
15
  super(referrer, relativeUri);
16
- this.formField = formField;
17
16
  }
18
17
 
19
18
  /**
@@ -32,7 +31,7 @@ export class UploadEndpoint extends Endpoint {
32
31
  if (this.formField) {
33
32
  const formData = new FormData();
34
33
  formData.set(this.formField, blob, fileName);
35
- await this.send(HttpMethod.Post, signal, { [HttpHeader.ContentType]: "multipart/form-data" }, formData);
34
+ await this.send(HttpMethod.Post, signal, undefined, formData);
36
35
  } else {
37
36
  await this.send(HttpMethod.Post, signal, { [HttpHeader.ContentType]: blob.type }, blob);
38
37
  }