Skip to content

Commit c775b75

Browse files
committed
refactor remaining element endpoints
1 parent 25fbbdc commit c775b75

File tree

7 files changed

+136
-161
lines changed

7 files changed

+136
-161
lines changed

src/Endpoint/Element/DeleteElementEndpoint.ts

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,37 @@
1-
import { NetworkError, ParseError } from '../../Error/index.js';
2-
import { FetchHelper, Logger } from '../../Service/index.js';
1+
import { FetchHelper, Logger, ServiceResolver } from '../../Service/index.js';
32
import { Uuid } from '../../Type/Definition/index.js';
3+
import { ServiceIdentifier } from '../../Type/Enum/index.js';
44

55
/**
66
* The delete element endpoint deletes a single element.
77
*
8-
* **⚠️ Warning**: This is an internal class. You should not use it directly.
9-
*
108
* @see [Further documentation](https://ember-nexus.github.io/web-sdk/#/endpoints/element?id=deleteelementendpoint)
119
* @see [Ember Nexus API: Delete Element Endpoint](https://ember-nexus.github.io/api/#/api-endpoints/element/delete-element)
12-
*
13-
* @internal
1410
*/
15-
1611
class DeleteElementEndpoint {
12+
static identifier: ServiceIdentifier = ServiceIdentifier.endpointElementDeleteElementEndpoint;
1713
constructor(
1814
private logger: Logger,
1915
private fetchHelper: FetchHelper,
2016
) {}
2117

18+
static constructFromServiceResolver(serviceResolver: ServiceResolver): DeleteElementEndpoint {
19+
return new DeleteElementEndpoint(
20+
serviceResolver.getServiceOrFail<Logger>(ServiceIdentifier.logger),
21+
serviceResolver.getServiceOrFail<FetchHelper>(ServiceIdentifier.fetchHelper),
22+
);
23+
}
24+
2225
deleteElement(elementId: Uuid): Promise<void> {
23-
const url = this.fetchHelper.buildUrl(`/${elementId}`);
24-
this.logger.debug(`Executing HTTP DELETE request against url ${url} .`);
25-
return fetch(url, this.fetchHelper.getDefaultDeleteOptions())
26-
.catch((networkError) => {
27-
throw new NetworkError(`Experienced generic network error during deleting resource.`, networkError);
28-
})
29-
.then(async (response: Response) => {
30-
if (response.ok && response.status === 204) {
31-
return;
32-
}
33-
const contentType = response.headers.get('Content-Type');
34-
if (contentType === null) {
35-
throw new ParseError('Response does not contain content type header.');
36-
}
37-
if (!contentType.includes('application/problem+json')) {
38-
throw new ParseError("Unable to parse response as content type is not 'application/problem+json'.");
39-
}
40-
const data = await response.json();
41-
throw this.fetchHelper.createResponseErrorFromBadResponse(response, data);
26+
return Promise.resolve()
27+
.then(() => {
28+
const url = this.fetchHelper.buildUrl(`/${elementId}`);
29+
this.logger.debug(`Executing HTTP DELETE request against URL: ${url}`);
30+
return fetch(url, this.fetchHelper.getDefaultDeleteOptions());
4231
})
43-
.catch((error) => {
44-
this.logger.error(error.message, error);
45-
throw error;
46-
});
32+
.catch((error) => this.fetchHelper.rethrowErrorAsNetworkError(error))
33+
.then((response) => this.fetchHelper.parseEmptyResponse(response))
34+
.catch((error) => this.fetchHelper.logAndThrowError(error));
4735
}
4836
}
4937

src/Endpoint/Element/PatchElementEndpoint.ts

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,41 @@
1-
import { NetworkError, ParseError } from '../../Error/index.js';
2-
import { FetchHelper, Logger } from '../../Service/index.js';
1+
import { FetchHelper, Logger, ServiceResolver } from '../../Service/index.js';
32
import { Data, Uuid } from '../../Type/Definition/index.js';
3+
import { ServiceIdentifier } from '../../Type/Enum/index.js';
44

55
/**
66
* The patch element endpoint updates a single element.
77
*
8-
* **⚠️ Warning**: This is an internal class. You should not use it directly.
9-
*
108
* @see [Further documentation](https://ember-nexus.github.io/web-sdk/#/endpoints/element?id=patchelementendpoint)
119
* @see [Ember Nexus API: Update Element Endpoint](https://ember-nexus.github.io/api/#/api-endpoints/element/patch-element)
12-
*
13-
* @internal
1410
*/
15-
1611
class PatchElementEndpoint {
12+
static identifier: ServiceIdentifier = ServiceIdentifier.endpointElementPatchElementEndpoint;
1713
constructor(
1814
private logger: Logger,
1915
private fetchHelper: FetchHelper,
2016
) {}
2117

18+
static constructFromServiceResolver(serviceResolver: ServiceResolver): PatchElementEndpoint {
19+
return new PatchElementEndpoint(
20+
serviceResolver.getServiceOrFail<Logger>(ServiceIdentifier.logger),
21+
serviceResolver.getServiceOrFail<FetchHelper>(ServiceIdentifier.fetchHelper),
22+
);
23+
}
24+
2225
patchElement(elementId: Uuid, data: Data): Promise<void> {
2326
return Promise.resolve()
2427
.then(() => {
28+
// @todo what exactly will change?
2529
this.logger.warn(
2630
'The endpoint patch element will be changed in the next major version, expect changed interfaces.',
2731
);
2832
const url = this.fetchHelper.buildUrl(`/${elementId}`);
29-
this.logger.debug(`Executing HTTP PATCH request against url ${url} .`);
33+
this.logger.debug(`Executing HTTP PATCH request against URL: ${url}`);
3034
return fetch(url, this.fetchHelper.getDefaultPatchOptions(JSON.stringify(data)));
3135
})
32-
.catch((error) => {
33-
throw new NetworkError(`Experienced generic network error during patching resource.`, error);
34-
})
35-
.then(async (response: Response) => {
36-
if (response.ok && response.status === 204) {
37-
return;
38-
}
39-
const contentType = response.headers.get('Content-Type');
40-
if (contentType === null) {
41-
throw new ParseError('Response does not contain content type header.');
42-
}
43-
if (!contentType.includes('application/problem+json')) {
44-
throw new ParseError("Unable to parse response as content type is not 'application/problem+json'.");
45-
}
46-
const data = await response.json();
47-
throw this.fetchHelper.createResponseErrorFromBadResponse(response, data);
48-
})
49-
.catch((error) => {
50-
this.logger.error(error.message, error);
51-
throw error;
52-
});
36+
.catch((error) => this.fetchHelper.rethrowErrorAsNetworkError(error))
37+
.then((response) => this.fetchHelper.parseEmptyResponse(response))
38+
.catch((error) => this.fetchHelper.logAndThrowError(error));
5339
}
5440
}
5541

src/Endpoint/Element/PostElementEndpoint.ts

Lines changed: 15 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,37 @@
1-
import { NetworkError, ParseError } from '../../Error/index.js';
2-
import { FetchHelper, Logger } from '../../Service/index.js';
3-
import { NodeWithOptionalId, Uuid, validateUuidFromString } from '../../Type/Definition/index.js';
1+
import { FetchHelper, Logger, ServiceResolver } from '../../Service/index.js';
2+
import { NodeWithOptionalId, Uuid } from '../../Type/Definition/index.js';
3+
import { ServiceIdentifier } from '../../Type/Enum/index.js';
44

55
/**
66
* The post element endpoint creates a single child node.
77
*
8-
* **⚠️ Warning**: This is an internal class. You should not use it directly.
9-
*
108
* @see [Further documentation](https://ember-nexus.github.io/web-sdk/#/endpoints/element?id=postelementendpoint)
119
* @see [Ember Nexus API: Create Element Endpoint](https://ember-nexus.github.io/api/#/api-endpoints/element/post-element)
12-
*
13-
* @internal
1410
*/
15-
1611
class PostElementEndpoint {
12+
static identifier: ServiceIdentifier = ServiceIdentifier.endpointElementPostElementEndpoint;
1713
constructor(
1814
private logger: Logger,
1915
private fetchHelper: FetchHelper,
2016
) {}
2117

18+
static constructFromServiceResolver(serviceResolver: ServiceResolver): PostElementEndpoint {
19+
return new PostElementEndpoint(
20+
serviceResolver.getServiceOrFail<Logger>(ServiceIdentifier.logger),
21+
serviceResolver.getServiceOrFail<FetchHelper>(ServiceIdentifier.fetchHelper),
22+
);
23+
}
24+
2225
postElement(parentId: Uuid, element: NodeWithOptionalId): Promise<Uuid> {
2326
return Promise.resolve()
2427
.then(() => {
2528
const url = this.fetchHelper.buildUrl(`/${parentId}`);
26-
this.logger.debug(`Executing HTTP POST request against url ${url} .`);
29+
this.logger.debug(`Executing HTTP POST request against URL: ${url}`);
2730
return fetch(url, this.fetchHelper.getDefaultPostOptions(JSON.stringify(element)));
2831
})
29-
.catch((error) => {
30-
throw new NetworkError(`Experienced generic network error during creating resource.`, error);
31-
})
32-
.then(async (response: Response) => {
33-
if (response.ok && response.status === 204) {
34-
if (response.headers.has('Location')) {
35-
const location = response.headers.get('Location') as string;
36-
const rawUuid = location.split('/').at(-1) as string;
37-
return validateUuidFromString(rawUuid);
38-
}
39-
}
40-
const contentType = response.headers.get('Content-Type');
41-
if (contentType === null) {
42-
throw new ParseError('Response does not contain content type header.');
43-
}
44-
if (!contentType.includes('application/problem+json')) {
45-
throw new ParseError("Unable to parse response as content type is not 'application/problem+json'.");
46-
}
47-
const data = await response.json();
48-
throw this.fetchHelper.createResponseErrorFromBadResponse(response, data);
49-
})
50-
.catch((error) => {
51-
this.logger.error(error.message, error);
52-
throw error;
53-
});
32+
.catch((error) => this.fetchHelper.rethrowErrorAsNetworkError(error))
33+
.then((response) => this.fetchHelper.parseLocationResponse(response))
34+
.catch((error) => this.fetchHelper.logAndThrowError(error));
5435
}
5536
}
5637

src/Endpoint/Element/PostIndexEndpoint.ts

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,37 @@
1-
import { NetworkError, ParseError } from '../../Error/index.js';
2-
import { FetchHelper, Logger } from '../../Service/index.js';
3-
import {
4-
NodeWithOptionalId,
5-
RelationWithOptionalId,
6-
Uuid,
7-
validateUuidFromString,
8-
} from '../../Type/Definition/index.js';
1+
import { FetchHelper, Logger, ServiceResolver } from '../../Service/index.js';
2+
import { NodeWithOptionalId, RelationWithOptionalId, Uuid } from '../../Type/Definition/index.js';
3+
import { ServiceIdentifier } from '../../Type/Enum/index.js';
94

105
/**
116
* The post index endpoint creates a single element.
127
*
13-
* **⚠️ Warning**: This is an internal class. You should not use it directly.
14-
*
158
* @see [Further documentation](https://ember-nexus.github.io/web-sdk/#/endpoints/element?id=postindexendpoint)
169
* @see [Ember Nexus API: Create Root Level Element Endpoint](https://ember-nexus.github.io/api/#/api-endpoints/element/post-index)
17-
*
18-
* @internal
1910
*/
20-
2111
class PostIndexEndpoint {
12+
static identifier: ServiceIdentifier = ServiceIdentifier.endpointElementPostIndexEndpoint;
2213
constructor(
2314
private logger: Logger,
2415
private fetchHelper: FetchHelper,
2516
) {}
2617

18+
static constructFromServiceResolver(serviceResolver: ServiceResolver): PostIndexEndpoint {
19+
return new PostIndexEndpoint(
20+
serviceResolver.getServiceOrFail<Logger>(ServiceIdentifier.logger),
21+
serviceResolver.getServiceOrFail<FetchHelper>(ServiceIdentifier.fetchHelper),
22+
);
23+
}
24+
2725
postIndex(element: NodeWithOptionalId | RelationWithOptionalId): Promise<Uuid> {
2826
return Promise.resolve()
2927
.then(() => {
3028
const url = this.fetchHelper.buildUrl(`/`);
31-
this.logger.debug(`Executing HTTP POST request against url ${url} .`);
29+
this.logger.debug(`Executing HTTP POST request against URL: ${url}`);
3230
return fetch(url, this.fetchHelper.getDefaultPostOptions(JSON.stringify(element)));
3331
})
34-
.catch((error) => {
35-
throw new NetworkError(`Experienced generic network error during creating resource.`, error);
36-
})
37-
.then(async (response: Response) => {
38-
if (response.ok && response.status === 204) {
39-
if (response.headers.has('Location')) {
40-
const location = response.headers.get('Location') as string;
41-
const rawUuid = location.split('/').at(-1) as string;
42-
return validateUuidFromString(rawUuid);
43-
}
44-
}
45-
const contentType = response.headers.get('Content-Type');
46-
if (contentType === null) {
47-
throw new ParseError('Response does not contain content type header.');
48-
}
49-
if (!contentType.includes('application/problem+json')) {
50-
throw new ParseError("Unable to parse response as content type is not 'application/problem+json'.");
51-
}
52-
const data = await response.json();
53-
throw this.fetchHelper.createResponseErrorFromBadResponse(response, data);
54-
})
55-
.catch((error) => {
56-
this.logger.error(error.message, error);
57-
throw error;
58-
});
32+
.catch((error) => this.fetchHelper.rethrowErrorAsNetworkError(error))
33+
.then((response) => this.fetchHelper.parseLocationResponse(response))
34+
.catch((error) => this.fetchHelper.logAndThrowError(error));
5935
}
6036
}
6137

src/Endpoint/Element/PutElementEndpoint.ts

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,42 @@
1-
import { NetworkError, ParseError } from '../../Error/index.js';
2-
import { FetchHelper, Logger } from '../../Service/index.js';
1+
import { FetchHelper, Logger, ServiceResolver } from '../../Service/index.js';
32
import { Data, Uuid } from '../../Type/Definition/index.js';
3+
import { ServiceIdentifier } from '../../Type/Enum/index.js';
44

55
/**
66
* The put element endpoint replaces a single element.
77
*
8-
* **⚠️ Warning**: This is an internal class. You should not use it directly.
9-
*
108
* @see [Further documentation](https://ember-nexus.github.io/web-sdk/#/endpoints/element?id=putelementendpoint)
119
* @see [Ember Nexus API: Replace Element Endpoint](https://ember-nexus.github.io/api/#/api-endpoints/element/put-element)
12-
*
13-
* @internal
1410
*/
1511

1612
class PutElementEndpoint {
13+
static identifier: ServiceIdentifier = ServiceIdentifier.endpointElementPutElementEndpoint;
1714
constructor(
1815
private logger: Logger,
1916
private fetchHelper: FetchHelper,
2017
) {}
2118

19+
static constructFromServiceResolver(serviceResolver: ServiceResolver): PutElementEndpoint {
20+
return new PutElementEndpoint(
21+
serviceResolver.getServiceOrFail<Logger>(ServiceIdentifier.logger),
22+
serviceResolver.getServiceOrFail<FetchHelper>(ServiceIdentifier.fetchHelper),
23+
);
24+
}
25+
2226
putElement(elementId: Uuid, data: Data): Promise<void> {
2327
return Promise.resolve()
2428
.then(() => {
29+
// @todo what exactly will change?
2530
this.logger.warn(
2631
'The endpoint put element will be changed in the next major version, expect changed interfaces.',
2732
);
2833
const url = this.fetchHelper.buildUrl(`/${elementId}`);
29-
this.logger.debug(`Executing HTTP PUT request against url ${url} .`);
34+
this.logger.debug(`Executing HTTP PUT request against URL: ${url}`);
3035
return fetch(url, this.fetchHelper.getDefaultPutOptions(JSON.stringify(data)));
3136
})
32-
.catch((error) => {
33-
throw new NetworkError(`Experienced generic network error during updating resource.`, error);
34-
})
35-
.then(async (response: Response) => {
36-
if (response.ok && response.status === 204) {
37-
return;
38-
}
39-
const contentType = response.headers.get('Content-Type');
40-
if (contentType === null) {
41-
throw new ParseError('Response does not contain content type header.');
42-
}
43-
if (!contentType.includes('application/problem+json')) {
44-
throw new ParseError("Unable to parse response as content type is not 'application/problem+json'.");
45-
}
46-
const data = await response.json();
47-
throw this.fetchHelper.createResponseErrorFromBadResponse(response, data);
48-
})
49-
.catch((error) => {
50-
this.logger.error(error.message, error);
51-
throw error;
52-
});
37+
.catch((error) => this.fetchHelper.rethrowErrorAsNetworkError(error))
38+
.then((response) => this.fetchHelper.parseEmptyResponse(response))
39+
.catch((error) => this.fetchHelper.logAndThrowError(error));
5340
}
5441
}
5542

0 commit comments

Comments
 (0)