This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 231
/
backend.service.d.ts
198 lines (198 loc) · 9.45 KB
/
backend.service.d.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import { Observable, BehaviorSubject } from 'rxjs';
import { HeadersCore, RequestInfoUtilities, InMemoryDbService, InMemoryBackendConfigArgs, ParsedRequestUrl, PassThruBackend, RequestCore, RequestInfo, ResponseOptions, UriInfo } from './interfaces';
/**
* Base class for in-memory web api back-ends
* Simulate the behavior of a RESTy web api
* backed by the simple in-memory data store provided by the injected `InMemoryDbService` service.
* Conforms mostly to behavior described here:
* http://www.restapitutorial.com/lessons/httpmethods.html
*/
export declare abstract class BackendService {
protected inMemDbService: InMemoryDbService;
protected config: InMemoryBackendConfigArgs;
protected db: Object;
protected dbReadySubject: BehaviorSubject<boolean>;
private passThruBackend;
protected requestInfoUtils: RequestInfoUtilities;
constructor(inMemDbService: InMemoryDbService, config?: InMemoryBackendConfigArgs);
protected readonly dbReady: Observable<boolean>;
/**
* Process Request and return an Observable of Http Response object
* in the manner of a RESTy web api.
*
* Expect URI pattern in the form :base/:collectionName/:id?
* Examples:
* // for store with a 'customers' collection
* GET api/customers // all customers
* GET api/customers/42 // the character with id=42
* GET api/customers?name=^j // 'j' is a regex; returns customers whose name starts with 'j' or 'J'
* GET api/customers.json/42 // ignores the ".json"
*
* Also accepts direct commands to the service in which the last segment of the apiBase is the word "commands"
* Examples:
* POST commands/resetDb,
* GET/POST commands/config - get or (re)set the config
*
* HTTP overrides:
* If the injected inMemDbService defines an HTTP method (lowercase)
* The request is forwarded to that method as in
* `inMemDbService.get(requestInfo)`
* which must return either an Observable of the response type
* for this http library or null|undefined (which means "keep processing").
*/
protected handleRequest(req: RequestCore): Observable<any>;
protected handleRequest_(req: RequestCore): Observable<any>;
/**
* Add configured delay to response observable unless delay === 0
*/
protected addDelay(response: Observable<any>): Observable<any>;
/**
* Apply query/search parameters as a filter over the collection
* This impl only supports RegExp queries on string properties of the collection
* ANDs the conditions together
*/
protected applyQuery(collection: any[], query: Map<string, string[]>): any[];
/**
* Get a method from the `InMemoryDbService` (if it exists), bound to that service
*/
protected bind<T extends Function>(methodName: string): T;
protected bodify(data: any): any;
protected clone(data: any): any;
protected collectionHandler(reqInfo: RequestInfo): ResponseOptions;
/**
* Commands reconfigure the in-memory web api service or extract information from it.
* Commands ignore the latency delay and respond ASAP.
*
* When the last segment of the `apiBase` path is "commands",
* the `collectionName` is the command.
*
* Example URLs:
* commands/resetdb (POST) // Reset the "database" to its original state
* commands/config (GET) // Return this service's config object
* commands/config (POST) // Update the config (e.g. the delay)
*
* Usage:
* http.post('commands/resetdb', undefined);
* http.get('commands/config');
* http.post('commands/config', '{"delay":1000}');
*/
protected commands(reqInfo: RequestInfo): Observable<any>;
protected createErrorResponseOptions(url: string, status: number, message: string): ResponseOptions;
/**
* Create standard HTTP headers object from hash map of header strings
* @param headers
*/
protected abstract createHeaders(headers: {
[index: string]: string;
}): HeadersCore;
/**
* create the function that passes unhandled requests through to the "real" backend.
*/
protected abstract createPassThruBackend(): PassThruBackend;
/**
* return a search map from a location query/search string
*/
protected abstract createQueryMap(search: string): Map<string, string[]>;
/**
* Create a cold response Observable from a factory for ResponseOptions
* @param resOptionsFactory - creates ResponseOptions when observable is subscribed
* @param withDelay - if true (default), add simulated latency delay from configuration
*/
protected createResponse$(resOptionsFactory: () => ResponseOptions, withDelay?: boolean): Observable<any>;
/**
* Create a Response observable from ResponseOptions observable.
*/
protected abstract createResponse$fromResponseOptions$(resOptions$: Observable<ResponseOptions>): Observable<any>;
/**
* Create a cold Observable of ResponseOptions.
* @param resOptionsFactory - creates ResponseOptions when observable is subscribed
*/
protected createResponseOptions$(resOptionsFactory: () => ResponseOptions): Observable<ResponseOptions>;
protected delete({ collection, collectionName, headers, id, url }: RequestInfo): ResponseOptions;
/**
* Find first instance of item in collection by `item.id`
* @param collection
* @param id
*/
protected findById<T extends {
id: any;
}>(collection: T[], id: any): T;
/**
* Generate the next available id for item in this collection
* Use method from `inMemDbService` if it exists and returns a value,
* else delegates to `genIdDefault`.
* @param collection - collection of items with `id` key property
*/
protected genId<T extends {
id: any;
}>(collection: T[], collectionName: string): any;
/**
* Default generator of the next available id for item in this collection
* This default implementation works only for numeric ids.
* @param collection - collection of items with `id` key property
* @param collectionName - name of the collection
*/
protected genIdDefault<T extends {
id: any;
}>(collection: T[], collectionName: string): any;
protected get({ collection, collectionName, headers, id, query, url }: RequestInfo): ResponseOptions;
/** Get JSON body from the request object */
protected abstract getJsonBody(req: any): any;
/**
* Get location info from a url, even on server where `document` is not defined
*/
protected getLocation(url: string): UriInfo;
/**
* get or create the function that passes unhandled requests
* through to the "real" backend.
*/
protected getPassThruBackend(): PassThruBackend;
/**
* Get utility methods from this service instance.
* Useful within an HTTP method override
*/
protected getRequestInfoUtils(): RequestInfoUtilities;
/**
* return canonical HTTP method name (lowercase) from the request object
* e.g. (req.method || 'get').toLowerCase();
* @param req - request object from the http call
*
*/
protected abstract getRequestMethod(req: any): string;
protected indexOf(collection: any[], id: number): number;
/** Parse the id as a number. Return original value if not a number. */
protected parseId(collection: any[], collectionName: string, id: string): any;
/**
* return true if can determine that the collection's `item.id` is a number
* This implementation can't tell if the collection is empty so it assumes NO
* */
protected isCollectionIdNumeric<T extends {
id: any;
}>(collection: T[], collectionName: string): boolean;
/**
* Parses the request URL into a `ParsedRequestUrl` object.
* Parsing depends upon certain values of `config`: `apiBase`, `host`, and `urlRoot`.
*
* Configuring the `apiBase` yields the most interesting changes to `parseRequestUrl` behavior:
* When apiBase=undefined and url='http://localhost/api/collection/42'
* {base: 'api/', collectionName: 'collection', id: '42', ...}
* When apiBase='some/api/root/' and url='http://localhost/some/api/root/collection'
* {base: 'some/api/root/', collectionName: 'collection', id: undefined, ...}
* When apiBase='/' and url='http://localhost/collection'
* {base: '/', collectionName: 'collection', id: undefined, ...}
*
* The actual api base segment values are ignored. Only the number of segments matters.
* The following api base strings are considered identical: 'a/b' ~ 'some/api/' ~ `two/segments'
*
* To replace this default method, assign your alternative to your InMemDbService['parseRequestUrl']
*/
protected parseRequestUrl(url: string): ParsedRequestUrl;
protected post({ collection, collectionName, headers, id, req, resourceUrl, url }: RequestInfo): ResponseOptions;
protected put({ collection, collectionName, headers, id, req, url }: RequestInfo): ResponseOptions;
protected removeById(collection: any[], id: number): boolean;
/**
* Tell your in-mem "database" to reset.
* returns Observable of the database because resetting it could be async
*/
protected resetDb(reqInfo?: RequestInfo): Observable<boolean>;
}