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.
- package/README.md +2 -0
- package/endpoints/Endpoint.js +14 -27
- package/endpoints/Endpoint.ts +5 -5
- package/endpoints/EntryEndpoint.js +3 -14
- package/endpoints/generic/ETagEndpointBase.js +27 -42
- package/endpoints/generic/ElementEndpoint.js +39 -60
- package/endpoints/generic/GenericCollectionEndpoint.js +70 -44
- package/endpoints/generic/GenericCollectionEndpoint.test.ts +123 -0
- package/endpoints/generic/GenericCollectionEndpoint.ts +54 -1
- package/endpoints/generic/PartialResponse.js +33 -0
- package/endpoints/generic/PartialResponse.ts +28 -0
- package/endpoints/generic/index.js +2 -1
- package/endpoints/generic/index.ts +1 -0
- package/endpoints/index.js +3 -2
- package/endpoints/index.ts +1 -0
- package/endpoints/raw/BlobEndpoint.js +10 -27
- package/endpoints/raw/UploadEndpoint.js +11 -23
- package/endpoints/raw/UploadEndpoint.test.ts +1 -4
- package/endpoints/raw/UploadEndpoint.ts +1 -2
- package/endpoints/reactive/Delay.js +27 -0
- package/endpoints/reactive/Delay.ts +26 -0
- package/endpoints/reactive/GenericStreamingCollectionEndpoint.js +79 -0
- package/endpoints/reactive/GenericStreamingCollectionEndpoint.ts +73 -0
- package/endpoints/reactive/PollingEndpoint.js +67 -0
- package/endpoints/reactive/PollingEndpoint.test.ts +84 -0
- package/endpoints/reactive/PollingEndpoint.ts +66 -0
- package/endpoints/reactive/SseStreamingEndpoint.js +120 -0
- package/endpoints/reactive/SseStreamingEndpoint.test.ts +169 -0
- package/endpoints/reactive/SseStreamingEndpoint.ts +115 -0
- package/endpoints/reactive/StreamingCollectionEndpoint.js +23 -0
- package/endpoints/reactive/StreamingCollectionEndpoint.test.ts +110 -0
- package/endpoints/reactive/StreamingCollectionEndpoint.ts +20 -0
- package/endpoints/reactive/StreamingEndpoint.js +56 -0
- package/endpoints/reactive/StreamingEndpoint.test.ts +130 -0
- package/endpoints/reactive/StreamingEndpoint.ts +50 -0
- package/endpoints/reactive/index.js +22 -0
- package/endpoints/reactive/index.ts +5 -0
- package/endpoints/rpc/ActionEndpoint.js +3 -14
- package/endpoints/rpc/ConsumerEndpoint.js +5 -16
- package/endpoints/rpc/FunctionEndpoint.js +6 -17
- package/endpoints/rpc/ProducerEndpoint.js +4 -15
- package/endpoints/rpc/RpcEndpointBase.js +3 -14
- package/errors/DefaultErrorHandler.js +20 -22
- package/errors/DefaultErrorHandler.ts +12 -4
- package/errors/Errors.js +8 -2
- package/errors/Errors.ts +5 -0
- package/http/EntityStream.js +42 -0
- package/http/EntityStream.ts +40 -0
- package/http/HttpContentRange.js +39 -0
- package/http/HttpContentRange.ts +41 -0
- package/http/HttpHeader.js +6 -1
- package/http/HttpHeader.ts +6 -1
- package/http/HttpStatusCode.js +4 -1
- package/http/HttpStatusCode.ts +4 -1
- package/http/ResponseCache.js +4 -15
- package/http/RetryAfter.js +24 -0
- package/http/RetryAfter.ts +19 -0
- package/http/ServerSentEvents.js +140 -0
- package/http/ServerSentEvents.ts +145 -0
- package/http/index.js +5 -1
- package/http/index.ts +4 -0
- package/jest.config.js +1 -1
- package/links/AggregateLinkExtractor.js +7 -18
- package/links/HalLinkExtractor.js +9 -20
- package/links/HeaderLinkExtractor.js +5 -16
- package/links/HeaderLinkExtractor.ts +1 -1
- 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
|
|
69
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
111
|
-
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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,
|
|
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,
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsb0RBQWtDO0FBQ2xDLHFEQUFtQztBQUNuQyxvREFBa0M7QUFDbEMsOERBQTRDO0FBQzVDLHVEQUFxQztBQUNyQyxvREFBa0MifQ==
|
package/endpoints/index.js
CHANGED
|
@@ -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,
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxxREFBcUM7QUFDckMsNkNBQTZCO0FBQzdCLDZDQUE2QjtBQUM3Qix1REFBdUM7QUFFdkMsNkNBQTJCO0FBQzNCLGtEQUFnQztBQUNoQyxvREFBa0MifQ==
|
package/endpoints/index.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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,
|
|
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
|
|
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,
|
|
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
|
}
|