typedrest 0.5.0 → 0.6.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 (88) hide show
  1. package/README.md +41 -5
  2. package/endpoints/{CachingEndpoint.ts → CachingEndpoint.d.ts} +0 -1
  3. package/endpoints/Endpoint.d.ts +121 -0
  4. package/endpoints/Endpoint.js +1 -1
  5. package/endpoints/{EntryEndpoint.ts → EntryEndpoint.d.ts} +7 -27
  6. package/endpoints/generic/{CollectionEndpoint.ts → CollectionEndpoint.d.ts} +2 -5
  7. package/endpoints/generic/{ETagEndpointBase.ts → ETagEndpointBase.d.ts} +7 -38
  8. package/endpoints/generic/{ElementEndpoint.ts → ElementEndpoint.d.ts} +12 -70
  9. package/endpoints/generic/{GenericCollectionEndpoint.ts → GenericCollectionEndpoint.d.ts} +21 -106
  10. package/endpoints/generic/{IndexerEndpoint.ts → IndexerEndpoint.d.ts} +4 -11
  11. package/endpoints/generic/PartialResponse.d.ts +19 -0
  12. package/endpoints/{index.ts → index.d.ts} +1 -2
  13. package/endpoints/raw/{BlobEndpoint.ts → BlobEndpoint.d.ts} +9 -29
  14. package/endpoints/raw/{UploadEndpoint.ts → UploadEndpoint.d.ts} +4 -18
  15. package/endpoints/reactive/Delay.d.ts +7 -0
  16. package/endpoints/reactive/GenericStreamingCollectionEndpoint.d.ts +32 -0
  17. package/endpoints/reactive/{PollingEndpoint.ts → PollingEndpoint.d.ts} +7 -34
  18. package/endpoints/reactive/SseStreamingEndpoint.d.ts +50 -0
  19. package/endpoints/reactive/{StreamingCollectionEndpoint.ts → StreamingCollectionEndpoint.d.ts} +2 -5
  20. package/endpoints/reactive/{StreamingEndpoint.ts → StreamingEndpoint.d.ts} +5 -27
  21. package/endpoints/rpc/{ActionEndpoint.ts → ActionEndpoint.d.ts} +3 -10
  22. package/endpoints/rpc/{ConsumerEndpoint.ts → ConsumerEndpoint.d.ts} +3 -12
  23. package/endpoints/rpc/{FunctionEndpoint.ts → FunctionEndpoint.d.ts} +3 -14
  24. package/endpoints/rpc/{ProducerEndpoint.ts → ProducerEndpoint.d.ts} +3 -11
  25. package/endpoints/rpc/{RpcEndpointBase.ts → RpcEndpointBase.d.ts} +4 -12
  26. package/errors/DefaultErrorHandler.d.ts +21 -0
  27. package/errors/{Errors.ts → Errors.d.ts} +20 -21
  28. package/http/EntityStream.d.ts +10 -0
  29. package/http/FetchHttpClient.d.ts +15 -0
  30. package/http/FetchHttpClient.js +1 -1
  31. package/http/{HttpClient.ts → HttpClient.d.ts} +1 -3
  32. package/http/HttpContentRange.d.ts +23 -0
  33. package/http/{HttpHeader.ts → HttpHeader.d.ts} +1 -1
  34. package/http/{HttpMethod.ts → HttpMethod.d.ts} +1 -1
  35. package/http/{HttpStatusCode.ts → HttpStatusCode.d.ts} +1 -1
  36. package/http/ResponseCache.d.ts +19 -0
  37. package/http/RetryAfter.d.ts +6 -0
  38. package/http/ServerSentEvents.d.ts +50 -0
  39. package/links/AggregateLinkExtractor.d.ts +17 -0
  40. package/links/HalLinkExtractor.d.ts +13 -0
  41. package/links/HeaderLinkExtractor.d.ts +13 -0
  42. package/links/{Link.ts → Link.d.ts} +6 -2
  43. package/links/{LinkExtractor.ts → LinkExtractor.d.ts} +0 -1
  44. package/package.json +64 -14
  45. package/serializers/JsonSerializer.d.ts +18 -0
  46. package/serializers/{Serializer.ts → Serializer.d.ts} +0 -2
  47. package/endpoints/Endpoint.test.ts +0 -300
  48. package/endpoints/Endpoint.ts +0 -247
  49. package/endpoints/generic/CollectionEndpoint.test.ts +0 -215
  50. package/endpoints/generic/ElementEndpoint.test.ts +0 -262
  51. package/endpoints/generic/GenericCollectionEndpoint.test.ts +0 -123
  52. package/endpoints/generic/IndexerEndpoint.test.ts +0 -12
  53. package/endpoints/generic/PartialResponse.ts +0 -28
  54. package/endpoints/raw/BlobEndpoint.test.ts +0 -52
  55. package/endpoints/raw/UploadEndpoint.test.ts +0 -47
  56. package/endpoints/reactive/Delay.ts +0 -26
  57. package/endpoints/reactive/GenericStreamingCollectionEndpoint.ts +0 -73
  58. package/endpoints/reactive/PollingEndpoint.test.ts +0 -84
  59. package/endpoints/reactive/SseStreamingEndpoint.test.ts +0 -169
  60. package/endpoints/reactive/SseStreamingEndpoint.ts +0 -115
  61. package/endpoints/reactive/StreamingCollectionEndpoint.test.ts +0 -110
  62. package/endpoints/reactive/StreamingEndpoint.test.ts +0 -130
  63. package/endpoints/rpc/ActionEndpoint.test.ts +0 -36
  64. package/endpoints/rpc/ConsumerEndpoint.test.ts +0 -29
  65. package/endpoints/rpc/FunctionEndpoint.test.ts +0 -29
  66. package/endpoints/rpc/ProducerEndpoint.test.ts +0 -32
  67. package/errors/DefaultErrorHandler.ts +0 -65
  68. package/http/EntityStream.ts +0 -40
  69. package/http/FetchHttpClient.ts +0 -26
  70. package/http/HttpContentRange.ts +0 -41
  71. package/http/ResponseCache.ts +0 -25
  72. package/http/RetryAfter.ts +0 -19
  73. package/http/ServerSentEvents.ts +0 -145
  74. package/jest.config.js +0 -12
  75. package/links/AggregateLinkExtractor.ts +0 -28
  76. package/links/HalLinkExtractor.ts +0 -45
  77. package/links/HeaderLinkExtractor.ts +0 -56
  78. package/serializers/JsonSerializer.ts +0 -25
  79. /package/endpoints/generic/{index.ts → index.d.ts} +0 -0
  80. /package/endpoints/raw/{index.ts → index.d.ts} +0 -0
  81. /package/endpoints/reactive/{index.ts → index.d.ts} +0 -0
  82. /package/endpoints/rpc/{index.ts → index.d.ts} +0 -0
  83. /package/errors/{ErrorHandler.ts → ErrorHandler.d.ts} +0 -0
  84. /package/errors/{index.ts → index.d.ts} +0 -0
  85. /package/http/{index.ts → index.d.ts} +0 -0
  86. /package/{index.ts → index.d.ts} +0 -0
  87. /package/links/{index.ts → index.d.ts} +0 -0
  88. /package/serializers/{index.ts → index.d.ts} +0 -0
@@ -1,215 +0,0 @@
1
- import fetchMock from 'jest-fetch-mock';
2
- import { CollectionEndpoint } from '.';
3
- import { EntryEndpoint } from '..';
4
- import { HttpHeader, HttpStatusCode, HttpMethod } from '../../http';
5
-
6
- class MockEntity {
7
- constructor(public id: number, public name: string) { }
8
- }
9
-
10
- fetchMock.enableMocks();
11
- let endpoint: CollectionEndpoint<MockEntity>;
12
-
13
- beforeEach(() => {
14
- fetchMock.resetMocks();
15
- endpoint = new CollectionEndpoint(new EntryEndpoint('http://localhost/'), 'endpoint');
16
- });
17
-
18
- test('getById', () => {
19
- expect(endpoint.get('x/y').uri).toEqual(new URL('http://localhost/endpoint/x%2Fy'));
20
- });
21
-
22
- test('getByIdWithLinkHeaderRelative', async () => {
23
- fetchMock.mockOnceIf(
24
- 'http://localhost/endpoint',
25
- '[]',
26
- {
27
- headers: {
28
- [HttpHeader.Link]: '<children{?id}>; rel=child; templated=true'
29
- }
30
- }
31
- );
32
- await endpoint.readAll();
33
-
34
- expect(endpoint.get('1').uri).toEqual(new URL('http://localhost/children?id=1'));
35
- });
36
-
37
- test('getByIdWithLinkHeaderAbsolute', async () => {
38
- fetchMock.mockOnceIf(
39
- 'http://localhost/endpoint',
40
- '[]',
41
- {
42
- headers: {
43
- [HttpHeader.Link]: '<http://localhost/children{?id}>; rel=child; templated=true'
44
- }
45
- }
46
- );
47
- await endpoint.readAll();
48
-
49
- expect(endpoint.get('1').uri).toEqual(new URL('http://localhost/children?id=1'));
50
- });
51
-
52
- test('getByEntity', () => {
53
- expect(endpoint.get(new MockEntity(1, 'test')).uri).toEqual(new URL('http://localhost/endpoint/1'));
54
- });
55
-
56
- test('getByEntityWithLinkHeaderRelative', async () => {
57
- fetchMock.mockOnceIf(
58
- 'http://localhost/endpoint',
59
- '[]',
60
- {
61
- headers: {
62
- [HttpHeader.Link]: '<children/{id}>; rel=child; templated=true'
63
- }
64
- }
65
- );
66
- await endpoint.readAll();
67
-
68
- expect(endpoint.get('1').uri).toEqual(new URL('http://localhost/children/1'));
69
- });
70
-
71
- test('getByEntityWithLinkHeaderAbsolute', async () => {
72
- fetchMock.mockOnceIf(
73
- 'http://localhost/endpoint',
74
- '[]',
75
- {
76
- headers: {
77
- [HttpHeader.Link]: '<http://localhost/children/{id}>; rel=child; templated=true'
78
- }
79
- }
80
- );
81
- await endpoint.readAll();
82
-
83
- expect(endpoint.get('1').uri).toEqual(new URL('http://localhost/children/1'));
84
- });
85
-
86
- test('readAll', async () => {
87
- fetchMock.mockOnceIf(
88
- 'http://localhost/endpoint',
89
- '[{"id":5,"name":"test1"}, {"id":6,"name":"test2"}]'
90
- );
91
-
92
- const result = await endpoint.readAll();
93
- expect(result).toEqual([new MockEntity(5, 'test1'), new MockEntity(6, 'test2')]);
94
- });
95
-
96
- test('readAllCache', async () => {
97
- fetchMock.mockOnceIf(
98
- 'http://localhost/endpoint',
99
- '[{"id":5,"name":"test1"}, {"id":6,"name":"test2"}]',
100
- {
101
- headers: {
102
- [HttpHeader.ETag]: '"123abc"'
103
- }
104
- }
105
- );
106
- const result1 = await endpoint.readAll();
107
- expect(result1).toEqual([new MockEntity(5, 'test1'), new MockEntity(6, 'test2')]);
108
-
109
- fetchMock.mockOnceIf(
110
- 'http://localhost/endpoint',
111
- async req => {
112
- expect(req.headers.get(HttpHeader.IfNoneMatch)).toBe('"123abc"');
113
- return { status: HttpStatusCode.NotModified };
114
- }
115
- );
116
- const result2 = await endpoint.readAll();
117
- expect(result2).toEqual([new MockEntity(5, 'test1'), new MockEntity(6, 'test2')]);
118
-
119
- expect(result2).not.toBe(result1); // Should cache response, not deserialized object
120
- });
121
-
122
- test('create', async () => {
123
- fetchMock.mockOnceIf(
124
- req => req.method === HttpMethod.Post && req.url === 'http://localhost/endpoint',
125
- async req => {
126
- expect(req.headers.get(HttpHeader.ContentType)).toBe('application/json');
127
- expect(await req.text()).toBe('{"id":0,"name":"test"}');
128
- return { body: '{"id":5,"name":"test"}' };
129
- }
130
- );
131
-
132
- const element = (await endpoint.create(new MockEntity(0, 'test')))!;
133
- expect(element!.response).toEqual(new MockEntity(5, 'test'));
134
- expect(element.uri).toEqual(new URL('http://localhost/endpoint/5'));
135
- });
136
-
137
- test('createLocation', async () => {
138
- fetchMock.mockOnceIf(
139
- req => req.method === HttpMethod.Post && req.url === 'http://localhost/endpoint',
140
- async req => {
141
- expect(req.headers.get(HttpHeader.ContentType)).toBe('application/json');
142
- expect(await req.text()).toBe('{"id":0,"name":"test"}');
143
- return {
144
- body: '{"id":5,"name":"test"}',
145
- headers: {
146
- [HttpHeader.Location]: '/endpoint/new'
147
- }
148
- };
149
- }
150
- );
151
-
152
- const element = (await endpoint.create(new MockEntity(0, 'test')))!;
153
- expect(element.response).toEqual(new MockEntity(5, 'test'));
154
- expect(element.uri).toEqual(new URL('http://localhost/endpoint/new'));
155
- });
156
-
157
- test('createUndefined', async () => {
158
- fetchMock.mockOnceIf(
159
- req => req.method === HttpMethod.Post && req.url === 'http://localhost/endpoint',
160
- async req => {
161
- expect(req.headers.get(HttpHeader.ContentType)).toBe('application/json');
162
- expect(await req.text()).toBe('{"id":0,"name":"test"}');
163
- return { status: HttpStatusCode.Accepted };
164
- }
165
- );
166
-
167
- const element = (await endpoint.create(new MockEntity(0, 'test')));
168
- expect(element).toBeUndefined();
169
- });
170
-
171
- test('createAll', async () => {
172
- fetchMock.mockOnceIf(
173
- req => req.method === HttpMethod.Patch && req.url === 'http://localhost/endpoint',
174
- async req => {
175
- expect(req.headers.get(HttpHeader.ContentType)).toBe('application/json');
176
- expect(await req.text()).toBe('[{"id":5,"name":"test1"},{"id":6,"name":"test2"}]');
177
- return {};
178
- }
179
- );
180
-
181
- await endpoint.createAll([new MockEntity(5, 'test1'), new MockEntity(6, 'test2')]);
182
- });
183
-
184
- test('setAll', async () => {
185
- fetchMock.mockOnceIf(
186
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
187
- async req => {
188
- expect(req.headers.get(HttpHeader.ContentType)).toBe('application/json');
189
- expect(await req.text()).toBe('[{"id":5,"name":"test1"},{"id":6,"name":"test2"}]');
190
- return {};
191
- }
192
- );
193
-
194
- await endpoint.setAll([new MockEntity(5, 'test1'), new MockEntity(6, 'test2')]);
195
- });
196
-
197
- test('setAllETag', async () => {
198
- fetchMock.mockOnceIf(
199
- 'http://localhost/endpoint',
200
- '[{"id":5,"name":"test1"}, {"id":6,"name":"test2"}]',
201
- {
202
- headers: { [HttpHeader.ETag]: '"123abc"' }
203
- });
204
- const result = await endpoint.readAll();
205
-
206
- fetchMock.mockOnceIf(
207
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
208
- async req => {
209
- expect(req.headers.get(HttpHeader.IfMatch)).toBe('"123abc"');
210
- expect(await req.text()).toBe('[{"id":5,"name":"test1"},{"id":6,"name":"test2"}]');
211
- return {};
212
- }
213
- );
214
- await endpoint.setAll(result);
215
- });
@@ -1,262 +0,0 @@
1
- import fetchMock from 'jest-fetch-mock';
2
- import { ElementEndpoint } from '.';
3
- import { EntryEndpoint } from '..';
4
- import { HttpStatusCode, HttpMethod, HttpHeader } from '../../http';
5
- import { ConcurrencyError } from '../../errors';
6
-
7
- class MockEntity {
8
- constructor(public id: number, public name: string) { }
9
- }
10
-
11
- fetchMock.enableMocks();
12
- let endpoint: ElementEndpoint<MockEntity>;
13
-
14
- beforeEach(() => {
15
- fetchMock.resetMocks();
16
- endpoint = new ElementEndpoint(new EntryEndpoint('http://localhost/'), 'endpoint');
17
- });
18
-
19
- test('read', async () => {
20
- fetchMock.mockOnceIf(
21
- 'http://localhost/endpoint',
22
- '{"id":5,"name":"test"}',
23
- {
24
- headers: { [HttpHeader.ContentType]: 'application/json' }
25
- });
26
-
27
- const result = await endpoint.read();
28
- expect(result).toEqual(new MockEntity(5, 'test'));
29
- });
30
-
31
- test('readCache', async () => {
32
- fetchMock.mockOnceIf(
33
- 'http://localhost/endpoint',
34
- '{"id":5,"name":"test"}',
35
- {
36
- headers: {
37
- [HttpHeader.ContentType]: 'application/json',
38
- [HttpHeader.ETag]: '"123abc"'
39
- }
40
- }
41
- );
42
- const result1 = await endpoint.read();
43
- expect(result1).toEqual(new MockEntity(5, 'test'));
44
-
45
- fetchMock.mockOnceIf(
46
- 'http://localhost/endpoint',
47
- async req => {
48
- expect(req.headers.get('If-None-Match')).toBe('"123abc"');
49
- return { status: HttpStatusCode.NotModified };
50
- }
51
- );
52
- const result2 = await endpoint.read();
53
- expect(result2).toEqual(new MockEntity(5, 'test'));
54
-
55
- expect(result2).not.toBe(result1); // Should cache response, not deserialized object
56
- });
57
-
58
- test('existsTrue', async () => {
59
- fetchMock.mockOnceIf(req => req.method === HttpMethod.Head && req.url === 'http://localhost/endpoint');
60
-
61
- const result = await endpoint.exists();
62
- expect(result).toBe(true);
63
- });
64
-
65
- test('existsFalse', async () => {
66
- fetchMock.mockOnceIf(
67
- req => req.method === HttpMethod.Head && req.url === 'http://localhost/endpoint',
68
- async () => {
69
- return { status: HttpStatusCode.NotFound };
70
- }
71
- );
72
-
73
- const result = await endpoint.exists();
74
- expect(result).toBe(false);
75
- });
76
-
77
- test('setResult', async () => {
78
- fetchMock.mockOnceIf(
79
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
80
- async req => {
81
- expect(req.headers.get(HttpHeader.ContentType)).toBe('application/json');
82
- expect(await req.text()).toBe('{"id":5,"name":"test"}');
83
- return {
84
- headers: { [HttpHeader.ContentType]: 'application/json' },
85
- body: '{"id":5,"name":"testXXX"}'
86
- };
87
- }
88
- );
89
-
90
- const result = await endpoint.set(new MockEntity(5, 'test'));
91
- expect(result).toEqual(new MockEntity(5, 'testXXX'));
92
- });
93
-
94
- test('setNoResult', async () => {
95
- fetchMock.mockOnceIf(
96
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
97
- async req => {
98
- expect(req.headers.get(HttpHeader.ContentType)).toBe('application/json');
99
- expect(await req.text()).toBe('{"id":5,"name":"test"}');
100
- return {};
101
- }
102
- );
103
-
104
- const result = await endpoint.set(new MockEntity(5, 'test'));
105
- expect(result).toBeUndefined();
106
- });
107
-
108
- test('setETag', async () => {
109
- fetchMock.mockOnceIf(
110
- 'http://localhost/endpoint',
111
- '{"id":5,"name":"test"}',
112
- {
113
- headers: {
114
- [HttpHeader.ContentType]: 'application/json',
115
- [HttpHeader.ETag]: '"123abc"'
116
- }
117
- }
118
- );
119
- const result = await endpoint.read();
120
-
121
- fetchMock.mockOnceIf(
122
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
123
- async req => {
124
- expect(req.headers.get(HttpHeader.IfMatch)).toBe('"123abc"');
125
- expect(await req.text()).toBe('{"id":5,"name":"test"}');
126
- return {};
127
-
128
- }
129
- );
130
- await endpoint.set(result);
131
- });
132
-
133
- test('updateRetry', async () => {
134
- fetchMock.mockOnceIf(
135
- req => req.method === HttpMethod.Get && req.url === 'http://localhost/endpoint',
136
- async req => {
137
- return {
138
- headers: {
139
- [HttpHeader.ContentType]: 'application/json',
140
- [HttpHeader.ETag]: '"1"'
141
- },
142
- body: '{"id":5,"name":"test1"}'
143
- };
144
- }
145
- ).mockOnceIf(
146
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
147
- async req => {
148
- expect(req.headers.get(HttpHeader.IfMatch)).toBe('"1"');
149
- expect(await req.text()).toBe('{"id":5,"name":"testX"}');
150
- return { status: HttpStatusCode.PreconditionFailed };
151
- }
152
- ).mockOnceIf(
153
- req => req.method === HttpMethod.Get && req.url === 'http://localhost/endpoint',
154
- async req => {
155
- return {
156
- headers: {
157
- [HttpHeader.ContentType]: 'application/json',
158
- [HttpHeader.ETag]: '"2"'
159
- },
160
- body: '{"id":5,"name":"test2"}'
161
- };
162
- }
163
- ).mockOnceIf(
164
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
165
- async req => {
166
- expect(req.headers.get(HttpHeader.IfMatch)).toBe('"2"');
167
- expect(await req.text()).toBe('{"id":5,"name":"testX"}');
168
- return {
169
- headers: { [HttpHeader.ContentType]: 'application/json' },
170
- body: '{"id":5,"name":"testX"}'
171
- };
172
- }
173
- );
174
-
175
- await endpoint.update(x => x.name = 'testX');
176
- });
177
-
178
- test('updateFail', async () => {
179
- fetchMock.mockOnceIf(
180
- req => req.method === HttpMethod.Get && req.url === 'http://localhost/endpoint',
181
- '{"id":5,"name":"test1"}',
182
- {
183
- headers: {
184
- [HttpHeader.ContentType]: 'application/json',
185
- [HttpHeader.ETag]: '"1"'
186
- }
187
- }
188
- );
189
- fetchMock.mockOnceIf(
190
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
191
- async req => {
192
- expect(req.headers.get(HttpHeader.IfMatch)).toBe('"1"');
193
- expect(await req.text()).toBe('{"id":5,"name":"testX"}');
194
- return { status: HttpStatusCode.PreconditionFailed };
195
- }
196
- );
197
-
198
- let errorThrown = false;
199
- try {
200
- await endpoint.update(x => x.name = 'testX', 0);
201
- } catch (err) {
202
- errorThrown = err instanceof ConcurrencyError;
203
- }
204
- expect(errorThrown).toBe(true);
205
- });
206
-
207
- test('mergeResult', async () => {
208
- fetchMock.mockOnceIf(
209
- req => req.method === HttpMethod.Patch && req.url === 'http://localhost/endpoint',
210
- async req => {
211
- expect(await req.text()).toBe('{"id":5,"name":"test"}');
212
- return {
213
- headers: { [HttpHeader.ContentType]: 'application/json' },
214
- body: '{"id":5,"name":"testXXX"}'
215
- };
216
- }
217
- );
218
-
219
- const result = await endpoint.merge(new MockEntity(5, 'test'));
220
- expect(result).toEqual(new MockEntity(5, 'testXXX'));
221
- });
222
-
223
- test('mergeNoResult', async () => {
224
- fetchMock.mockOnceIf(
225
- req => req.method === HttpMethod.Patch && req.url === 'http://localhost/endpoint',
226
- async req => {
227
- expect(await req.text()).toBe('{"id":5,"name":"test"}');
228
- return {};
229
- }
230
- );
231
-
232
- const result = await endpoint.merge(new MockEntity(5, 'test'));
233
- expect(result).toBeUndefined();
234
- });
235
-
236
- test('delete', async () => {
237
- fetchMock.mockOnceIf(req => req.method === HttpMethod.Delete && req.url === 'http://localhost/endpoint');
238
- await endpoint.delete();
239
- });
240
-
241
- test('deleteETag', async () => {
242
- fetchMock.mockOnceIf(
243
- 'http://localhost/endpoint',
244
- '{"id":5,"name":"test"}',
245
- {
246
- headers: {
247
- [HttpHeader.ContentType]: 'application/json',
248
- [HttpHeader.ETag]: '"123abc"'
249
- }
250
- }
251
- );
252
- await endpoint.read();
253
-
254
- fetchMock.mockOnceIf(
255
- req => req.method === HttpMethod.Delete && req.url === 'http://localhost/endpoint',
256
- async req => {
257
- expect(req.headers.get(HttpHeader.IfMatch)).toBe('"123abc"');
258
- return {};
259
- }
260
- );
261
- await endpoint.delete();
262
- });
@@ -1,123 +0,0 @@
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,12 +0,0 @@
1
- import { IndexerEndpoint, ElementEndpoint } from '.';
2
- import { EntryEndpoint } from '..';
3
-
4
- let endpoint: IndexerEndpoint<ElementEndpoint<{}>>;
5
-
6
- beforeEach(() => {
7
- endpoint = new IndexerEndpoint<ElementEndpoint<{}>>(new EntryEndpoint('http://localhost/'), 'endpoint', ElementEndpoint);
8
- });
9
-
10
- test('getById', () => {
11
- expect(endpoint.get('x/y').uri).toEqual(new URL('http://localhost/endpoint/x%2Fy'));
12
- });
@@ -1,28 +0,0 @@
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
- }
@@ -1,52 +0,0 @@
1
- import fetchMock from 'jest-fetch-mock';
2
- import { BlobEndpoint } from '.';
3
- import { EntryEndpoint } from '..';
4
- import { HttpMethod, HttpHeader } from '../../http';
5
-
6
- fetchMock.enableMocks();
7
- let endpoint: BlobEndpoint;
8
-
9
- beforeEach(() => {
10
- fetchMock.resetMocks();
11
- endpoint = new BlobEndpoint(new EntryEndpoint('http://localhost/'), 'endpoint');
12
- });
13
-
14
- test('probe', async () => {
15
- fetchMock.mockOnceIf(
16
- req => req.method === HttpMethod.Options && req.url === 'http://localhost/endpoint',
17
- async () => {
18
- return {
19
- headers: {
20
- [HttpHeader.Allow]: HttpMethod.Put
21
- }
22
- };
23
- }
24
- );
25
- await endpoint.probe();
26
-
27
- expect(endpoint.downloadAllowed).toBe(false);
28
- expect(endpoint.uploadAllowed).toBe(true);
29
- });
30
-
31
- test('download', async () => {
32
- fetchMock.mockOnceIf(
33
- req => req.method === HttpMethod.Get && req.url === 'http://localhost/endpoint',
34
- 'data'
35
- );
36
-
37
- await endpoint.download();
38
- });
39
-
40
- test('uploadFrom', async () => {
41
- const data = new Blob([new Uint8Array([1, 2, 3])], { type: 'mock/type' });
42
-
43
- fetchMock.mockOnceIf(
44
- req => req.method === HttpMethod.Put && req.url === 'http://localhost/endpoint',
45
- async req => {
46
- expect(req.headers.get(HttpHeader.ContentType)).toBe('mock/type');
47
- return {};
48
- }
49
- );
50
-
51
- await endpoint.uploadFrom(data);
52
- });