Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit b71d39f

Browse files
brandonrobertsIgorMinar
authored andcommitted
chore: release 0.8.0
1 parent 30456ba commit b71d39f

34 files changed

+2449
-0
lines changed

backend.service.d.ts

+198
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import { Observable, BehaviorSubject } from 'rxjs';
2+
import { HeadersCore, RequestInfoUtilities, InMemoryDbService, InMemoryBackendConfigArgs, ParsedRequestUrl, PassThruBackend, RequestCore, RequestInfo, ResponseOptions, UriInfo } from './interfaces';
3+
/**
4+
* Base class for in-memory web api back-ends
5+
* Simulate the behavior of a RESTy web api
6+
* backed by the simple in-memory data store provided by the injected `InMemoryDbService` service.
7+
* Conforms mostly to behavior described here:
8+
* http://www.restapitutorial.com/lessons/httpmethods.html
9+
*/
10+
export declare abstract class BackendService {
11+
protected inMemDbService: InMemoryDbService;
12+
protected config: InMemoryBackendConfigArgs;
13+
protected db: Object;
14+
protected dbReadySubject: BehaviorSubject<boolean>;
15+
private passThruBackend;
16+
protected requestInfoUtils: RequestInfoUtilities;
17+
constructor(inMemDbService: InMemoryDbService, config?: InMemoryBackendConfigArgs);
18+
protected readonly dbReady: Observable<boolean>;
19+
/**
20+
* Process Request and return an Observable of Http Response object
21+
* in the manner of a RESTy web api.
22+
*
23+
* Expect URI pattern in the form :base/:collectionName/:id?
24+
* Examples:
25+
* // for store with a 'customers' collection
26+
* GET api/customers // all customers
27+
* GET api/customers/42 // the character with id=42
28+
* GET api/customers?name=^j // 'j' is a regex; returns customers whose name starts with 'j' or 'J'
29+
* GET api/customers.json/42 // ignores the ".json"
30+
*
31+
* Also accepts direct commands to the service in which the last segment of the apiBase is the word "commands"
32+
* Examples:
33+
* POST commands/resetDb,
34+
* GET/POST commands/config - get or (re)set the config
35+
*
36+
* HTTP overrides:
37+
* If the injected inMemDbService defines an HTTP method (lowercase)
38+
* The request is forwarded to that method as in
39+
* `inMemDbService.get(requestInfo)`
40+
* which must return either an Observable of the response type
41+
* for this http library or null|undefined (which means "keep processing").
42+
*/
43+
protected handleRequest(req: RequestCore): Observable<any>;
44+
protected handleRequest_(req: RequestCore): Observable<any>;
45+
/**
46+
* Add configured delay to response observable unless delay === 0
47+
*/
48+
protected addDelay(response: Observable<any>): Observable<any>;
49+
/**
50+
* Apply query/search parameters as a filter over the collection
51+
* This impl only supports RegExp queries on string properties of the collection
52+
* ANDs the conditions together
53+
*/
54+
protected applyQuery(collection: any[], query: Map<string, string[]>): any[];
55+
/**
56+
* Get a method from the `InMemoryDbService` (if it exists), bound to that service
57+
*/
58+
protected bind<T extends Function>(methodName: string): T;
59+
protected bodify(data: any): any;
60+
protected clone(data: any): any;
61+
protected collectionHandler(reqInfo: RequestInfo): ResponseOptions;
62+
/**
63+
* Commands reconfigure the in-memory web api service or extract information from it.
64+
* Commands ignore the latency delay and respond ASAP.
65+
*
66+
* When the last segment of the `apiBase` path is "commands",
67+
* the `collectionName` is the command.
68+
*
69+
* Example URLs:
70+
* commands/resetdb (POST) // Reset the "database" to its original state
71+
* commands/config (GET) // Return this service's config object
72+
* commands/config (POST) // Update the config (e.g. the delay)
73+
*
74+
* Usage:
75+
* http.post('commands/resetdb', undefined);
76+
* http.get('commands/config');
77+
* http.post('commands/config', '{"delay":1000}');
78+
*/
79+
protected commands(reqInfo: RequestInfo): Observable<any>;
80+
protected createErrorResponseOptions(url: string, status: number, message: string): ResponseOptions;
81+
/**
82+
* Create standard HTTP headers object from hash map of header strings
83+
* @param headers
84+
*/
85+
protected abstract createHeaders(headers: {
86+
[index: string]: string;
87+
}): HeadersCore;
88+
/**
89+
* create the function that passes unhandled requests through to the "real" backend.
90+
*/
91+
protected abstract createPassThruBackend(): PassThruBackend;
92+
/**
93+
* return a search map from a location query/search string
94+
*/
95+
protected abstract createQueryMap(search: string): Map<string, string[]>;
96+
/**
97+
* Create a cold response Observable from a factory for ResponseOptions
98+
* @param resOptionsFactory - creates ResponseOptions when observable is subscribed
99+
* @param withDelay - if true (default), add simulated latency delay from configuration
100+
*/
101+
protected createResponse$(resOptionsFactory: () => ResponseOptions, withDelay?: boolean): Observable<any>;
102+
/**
103+
* Create a Response observable from ResponseOptions observable.
104+
*/
105+
protected abstract createResponse$fromResponseOptions$(resOptions$: Observable<ResponseOptions>): Observable<any>;
106+
/**
107+
* Create a cold Observable of ResponseOptions.
108+
* @param resOptionsFactory - creates ResponseOptions when observable is subscribed
109+
*/
110+
protected createResponseOptions$(resOptionsFactory: () => ResponseOptions): Observable<ResponseOptions>;
111+
protected delete({ collection, collectionName, headers, id, url }: RequestInfo): ResponseOptions;
112+
/**
113+
* Find first instance of item in collection by `item.id`
114+
* @param collection
115+
* @param id
116+
*/
117+
protected findById<T extends {
118+
id: any;
119+
}>(collection: T[], id: any): T;
120+
/**
121+
* Generate the next available id for item in this collection
122+
* Use method from `inMemDbService` if it exists and returns a value,
123+
* else delegates to `genIdDefault`.
124+
* @param collection - collection of items with `id` key property
125+
*/
126+
protected genId<T extends {
127+
id: any;
128+
}>(collection: T[], collectionName: string): any;
129+
/**
130+
* Default generator of the next available id for item in this collection
131+
* This default implementation works only for numeric ids.
132+
* @param collection - collection of items with `id` key property
133+
* @param collectionName - name of the collection
134+
*/
135+
protected genIdDefault<T extends {
136+
id: any;
137+
}>(collection: T[], collectionName: string): any;
138+
protected get({ collection, collectionName, headers, id, query, url }: RequestInfo): ResponseOptions;
139+
/** Get JSON body from the request object */
140+
protected abstract getJsonBody(req: any): any;
141+
/**
142+
* Get location info from a url, even on server where `document` is not defined
143+
*/
144+
protected getLocation(url: string): UriInfo;
145+
/**
146+
* get or create the function that passes unhandled requests
147+
* through to the "real" backend.
148+
*/
149+
protected getPassThruBackend(): PassThruBackend;
150+
/**
151+
* Get utility methods from this service instance.
152+
* Useful within an HTTP method override
153+
*/
154+
protected getRequestInfoUtils(): RequestInfoUtilities;
155+
/**
156+
* return canonical HTTP method name (lowercase) from the request object
157+
* e.g. (req.method || 'get').toLowerCase();
158+
* @param req - request object from the http call
159+
*
160+
*/
161+
protected abstract getRequestMethod(req: any): string;
162+
protected indexOf(collection: any[], id: number): number;
163+
/** Parse the id as a number. Return original value if not a number. */
164+
protected parseId(collection: any[], collectionName: string, id: string): any;
165+
/**
166+
* return true if can determine that the collection's `item.id` is a number
167+
* This implementation can't tell if the collection is empty so it assumes NO
168+
* */
169+
protected isCollectionIdNumeric<T extends {
170+
id: any;
171+
}>(collection: T[], collectionName: string): boolean;
172+
/**
173+
* Parses the request URL into a `ParsedRequestUrl` object.
174+
* Parsing depends upon certain values of `config`: `apiBase`, `host`, and `urlRoot`.
175+
*
176+
* Configuring the `apiBase` yields the most interesting changes to `parseRequestUrl` behavior:
177+
* When apiBase=undefined and url='http://localhost/api/collection/42'
178+
* {base: 'api/', collectionName: 'collection', id: '42', ...}
179+
* When apiBase='some/api/root/' and url='http://localhost/some/api/root/collection'
180+
* {base: 'some/api/root/', collectionName: 'collection', id: undefined, ...}
181+
* When apiBase='/' and url='http://localhost/collection'
182+
* {base: '/', collectionName: 'collection', id: undefined, ...}
183+
*
184+
* The actual api base segment values are ignored. Only the number of segments matters.
185+
* The following api base strings are considered identical: 'a/b' ~ 'some/api/' ~ `two/segments'
186+
*
187+
* To replace this default method, assign your alternative to your InMemDbService['parseRequestUrl']
188+
*/
189+
protected parseRequestUrl(url: string): ParsedRequestUrl;
190+
protected post({ collection, collectionName, headers, id, req, resourceUrl, url }: RequestInfo): ResponseOptions;
191+
protected put({ collection, collectionName, headers, id, req, url }: RequestInfo): ResponseOptions;
192+
protected removeById(collection: any[], id: number): boolean;
193+
/**
194+
* Tell your in-mem "database" to reset.
195+
* returns Observable of the database because resetting it could be async
196+
*/
197+
protected resetDb(reqInfo?: RequestInfo): Observable<boolean>;
198+
}

0 commit comments

Comments
 (0)