forked from johnpapa/angular-ngrx-data
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttp-url-generator.ts
135 lines (123 loc) · 4.56 KB
/
http-url-generator.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
import { Pluralizer } from '../utils/interfaces';
/**
* Known resource URLS for specific entity types.
* Each entity's resource URLS are endpoints that
* target single entity and multi-entity HTTP operations.
* Used by the `DefaultHttpUrlGenerator`.
*/
export abstract class EntityHttpResourceUrls {
[entityName: string]: HttpResourceUrls;
}
/**
* Resource URLS for HTTP operations that target single entity
* and multi-entity endpoints.
*/
export interface HttpResourceUrls {
/**
* The URL path for a single entity endpoint, e.g, `some-api-root/hero/`
* such as you'd use to add a hero.
* Example: `httpClient.post<Hero>('some-api-root/hero/', addedHero)`.
* Note trailing slash (/).
*/
entityResourceUrl: string;
/**
* The URL path for a multiple-entity endpoint, e.g, `some-api-root/heroes/`
* such as you'd use when getting all heroes.
* Example: `httpClient.get<Hero[]>('some-api-root/heroes/')`
* Note trailing slash (/).
*/
collectionResourceUrl: string;
}
/**
* Generate the base part of an HTTP URL for
* single entity or entity collection resource
*/
export abstract class HttpUrlGenerator {
/**
* Return the base URL for a single entity resource,
* e.g., the base URL to get a single hero by its id
*/
abstract entityResource(entityName: string, root: string): string;
/**
* Return the base URL for a collection resource,
* e.g., the base URL to get all heroes
*/
abstract collectionResource(entityName: string, root: string): string;
/**
* Register known single-entity and collection resource URLs for HTTP calls
* @param entityHttpResourceUrls {EntityHttpResourceUrls} resource urls for specific entity type names
*/
abstract registerHttpResourceUrls(
entityHttpResourceUrls: EntityHttpResourceUrls
): void;
}
@Injectable()
export class DefaultHttpUrlGenerator implements HttpUrlGenerator {
/**
* Known single-entity and collection resource URLs for HTTP calls.
* Generator methods returns these resource URLs for a given entity type name.
* If the resources for an entity type name are not know, it generates
* and caches a resource name for future use
*/
protected knownHttpResourceUrls: EntityHttpResourceUrls = {};
constructor(private pluralizer: Pluralizer) {}
/**
* Get or generate the entity and collection resource URLs for the given entity type name
* @param entityName {string} Name of the entity type, e.g, 'Hero'
* @param root {string} Root path to the resource, e.g., 'some-api`
*/
protected getResourceUrls(
entityName: string,
root: string
): HttpResourceUrls {
let resourceUrls = this.knownHttpResourceUrls[entityName];
if (!resourceUrls) {
const nRoot = normalizeRoot(root);
resourceUrls = {
entityResourceUrl: `${nRoot}/${entityName}/`.toLowerCase(),
collectionResourceUrl: `${nRoot}/${this.pluralizer.pluralize(
entityName
)}/`.toLowerCase()
};
this.registerHttpResourceUrls({ [entityName]: resourceUrls });
}
return resourceUrls;
}
/**
* Create the path to a single entity resource
* @param entityName {string} Name of the entity type, e.g, 'Hero'
* @param root {string} Root path to the resource, e.g., 'some-api`
* @returns complete path to resource, e.g, 'some-api/hero'
*/
entityResource(entityName: string, root: string): string {
return this.getResourceUrls(entityName, root).entityResourceUrl;
}
/**
* Create the path to a multiple entity (collection) resource
* @param entityName {string} Name of the entity type, e.g, 'Hero'
* @param root {string} Root path to the resource, e.g., 'some-api`
* @returns complete path to resource, e.g, 'some-api/heroes'
*/
collectionResource(entityName: string, root: string): string {
return this.getResourceUrls(entityName, root).collectionResourceUrl;
}
/**
* Register known single-entity and collection resource URLs for HTTP calls
* @param entityHttpResourceUrls {EntityHttpResourceUrls} resource urls for specific entity type names
* Well-formed resource urls end in a '/';
* Note: this method does not ensure that resource urls are well-formed.
*/
registerHttpResourceUrls(
entityHttpResourceUrls: EntityHttpResourceUrls
): void {
this.knownHttpResourceUrls = {
...this.knownHttpResourceUrls,
...(entityHttpResourceUrls || {})
};
}
}
/** Remove leading & trailing spaces or slashes */
export function normalizeRoot(root: string) {
return root.replace(/^[\/\s]+|[\/\s]+$/g, '');
}