build: import in-memory-web-api project (#37182)
Moves the `angular-in-memory-web-api` project into the main repository in order to make it easier to maintain and release. PR Close #37182
This commit is contained in:
89
packages/misc/angular-in-memory-web-api/test/fixtures/hero-in-mem-data-override-service.ts
vendored
Normal file
89
packages/misc/angular-in-memory-web-api/test/fixtures/hero-in-mem-data-override-service.ts
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is an example of a Hero-oriented InMemoryDbService with method overrides.
|
||||
*/
|
||||
import {Injectable} from '@angular/core';
|
||||
import {getStatusText, ParsedRequestUrl, RequestInfo, RequestInfoUtilities, ResponseOptions, STATUS} from 'angular-in-memory-web-api';
|
||||
import {Observable} from 'rxjs';
|
||||
|
||||
import {HeroInMemDataService} from './hero-in-mem-data-service';
|
||||
|
||||
const villains = [
|
||||
// deliberately using string ids that look numeric
|
||||
{id: 100, name: 'Snidley Wipsnatch'}, {id: 101, name: 'Boris Badenov'},
|
||||
{id: 103, name: 'Natasha Fatale'}
|
||||
];
|
||||
|
||||
// Pseudo guid generator
|
||||
function guid() {
|
||||
const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class HeroInMemDataOverrideService extends HeroInMemDataService {
|
||||
// Overrides id generator and delivers next available `id`, starting with 1001.
|
||||
genId<T extends {id: any}>(collection: T[], collectionName: string): any {
|
||||
if (collectionName === 'nobodies') {
|
||||
return guid();
|
||||
} else if (collection) {
|
||||
return 1 + collection.reduce((prev, curr) => Math.max(prev, curr.id || 0), 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP GET interceptor
|
||||
get(reqInfo: RequestInfo): Observable<any>|undefined {
|
||||
const collectionName = reqInfo.collectionName;
|
||||
if (collectionName === 'villains') {
|
||||
return this.getVillains(reqInfo);
|
||||
}
|
||||
return undefined; // let the default GET handle all others
|
||||
}
|
||||
|
||||
// HTTP GET interceptor handles requests for villains
|
||||
private getVillains(reqInfo: RequestInfo) {
|
||||
return reqInfo.utils.createResponse$(() => {
|
||||
const collection = villains.slice();
|
||||
const dataEncapsulation = reqInfo.utils.getConfig().dataEncapsulation;
|
||||
const id = reqInfo.id;
|
||||
const data = id == null ? collection : reqInfo.utils.findById(collection, id);
|
||||
|
||||
const options: ResponseOptions = data ?
|
||||
{body: dataEncapsulation ? {data} : data, status: STATUS.OK} :
|
||||
{body: {error: `'Villains' with id='${id}' not found`}, status: STATUS.NOT_FOUND};
|
||||
return this.finishOptions(options, reqInfo);
|
||||
});
|
||||
}
|
||||
|
||||
// parseRequestUrl override
|
||||
// Do this to manipulate the request URL or the parsed result
|
||||
// into something your data store can handle.
|
||||
// This example turns a request for `/foo/heroes` into just `/heroes`.
|
||||
// It leaves other URLs untouched and forwards to the default parser.
|
||||
// It also logs the result of the default parser.
|
||||
parseRequestUrl(url: string, utils: RequestInfoUtilities): ParsedRequestUrl {
|
||||
const newUrl = url.replace(/\/foo\/heroes/, '/heroes');
|
||||
return utils.parseRequestUrl(newUrl);
|
||||
}
|
||||
|
||||
responseInterceptor(resOptions: ResponseOptions, reqInfo: RequestInfo) {
|
||||
if (resOptions.headers) {
|
||||
resOptions.headers = resOptions.headers.set('x-test', 'test-header');
|
||||
}
|
||||
return resOptions;
|
||||
}
|
||||
|
||||
private finishOptions(options: ResponseOptions, {headers, url}: RequestInfo) {
|
||||
options.statusText = options.status == null ? undefined : getStatusText(options.status);
|
||||
options.headers = headers;
|
||||
options.url = url;
|
||||
return options;
|
||||
}
|
||||
}
|
79
packages/misc/angular-in-memory-web-api/test/fixtures/hero-in-mem-data-service.ts
vendored
Normal file
79
packages/misc/angular-in-memory-web-api/test/fixtures/hero-in-mem-data-service.ts
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This is an example of a Hero-oriented InMemoryDbService.
|
||||
*
|
||||
* For demonstration purposes, it can return the database
|
||||
* synchronously as an object (default),
|
||||
* as an observable, or as a promise.
|
||||
*
|
||||
* Add the following line to `AppModule.imports`
|
||||
* InMemoryWebApiModule.forRoot(HeroInMemDataService) // or HeroInMemDataOverrideService
|
||||
*/
|
||||
import {Injectable} from '@angular/core';
|
||||
import {InMemoryDbService, RequestInfo} from 'angular-in-memory-web-api';
|
||||
import {Observable, of} from 'rxjs';
|
||||
import {delay} from 'rxjs/operators';
|
||||
|
||||
interface Person {
|
||||
id: string|number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface PersonResponse {
|
||||
heroes: Person[];
|
||||
stringers: Person[];
|
||||
nobodies: Person[];
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class HeroInMemDataService implements InMemoryDbService {
|
||||
createDb(reqInfo?: RequestInfo):
|
||||
Observable<PersonResponse>|Promise<PersonResponse>|PersonResponse {
|
||||
const heroes = [
|
||||
{id: 1, name: 'Windstorm'}, {id: 2, name: 'Bombasto'}, {id: 3, name: 'Magneta'},
|
||||
{id: 4, name: 'Tornado'}
|
||||
];
|
||||
|
||||
const nobodies: any[] = [];
|
||||
|
||||
// entities with string ids that look like numbers
|
||||
const stringers = [{id: '10', name: 'Bob String'}, {id: '20', name: 'Jill String'}];
|
||||
|
||||
// default returnType
|
||||
let returnType = 'object';
|
||||
// let returnType = 'observable';
|
||||
// let returnType = 'promise';
|
||||
|
||||
// demonstrate POST commands/resetDb
|
||||
// this example clears the collections if the request body tells it to do so
|
||||
if (reqInfo) {
|
||||
const body = reqInfo.utils.getJsonBody(reqInfo.req) || {};
|
||||
if (body.clear === true) {
|
||||
heroes.length = 0;
|
||||
nobodies.length = 0;
|
||||
stringers.length = 0;
|
||||
}
|
||||
|
||||
// 'returnType` can be 'object' | 'observable' | 'promise'
|
||||
returnType = body.returnType || 'object';
|
||||
}
|
||||
const db = {heroes, nobodies, stringers};
|
||||
|
||||
switch (returnType) {
|
||||
case 'observable':
|
||||
return of(db).pipe(delay(10));
|
||||
case 'promise':
|
||||
return new Promise(resolve => setTimeout(() => resolve(db), 10));
|
||||
default:
|
||||
return db;
|
||||
}
|
||||
}
|
||||
}
|
21
packages/misc/angular-in-memory-web-api/test/fixtures/hero-service.ts
vendored
Normal file
21
packages/misc/angular-in-memory-web-api/test/fixtures/hero-service.ts
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Observable} from 'rxjs';
|
||||
import {Hero} from './hero';
|
||||
|
||||
export abstract class HeroService {
|
||||
heroesUrl = 'api/heroes'; // URL to web api
|
||||
|
||||
abstract getHeroes(): Observable<Hero[]>;
|
||||
abstract getHero(id: number): Observable<Hero>;
|
||||
abstract addHero(name: string): Observable<Hero>;
|
||||
abstract deleteHero(hero: Hero|number): Observable<Hero>;
|
||||
abstract searchHeroes(term: string): Observable<Hero[]>;
|
||||
abstract updateHero(hero: Hero): Observable<Hero>;
|
||||
}
|
14
packages/misc/angular-in-memory-web-api/test/fixtures/hero.ts
vendored
Normal file
14
packages/misc/angular-in-memory-web-api/test/fixtures/hero.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
export class Hero {
|
||||
constructor(public id = 0, public name = '') {}
|
||||
clone() {
|
||||
return new Hero(this.id, this.name);
|
||||
}
|
||||
}
|
76
packages/misc/angular-in-memory-web-api/test/fixtures/http-client-hero-service.ts
vendored
Normal file
76
packages/misc/angular-in-memory-web-api/test/fixtures/http-client-hero-service.ts
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Observable, throwError} from 'rxjs';
|
||||
import {catchError} from 'rxjs/operators';
|
||||
|
||||
import {Hero} from './hero';
|
||||
import {HeroService} from './hero-service';
|
||||
|
||||
const cudOptions = {
|
||||
headers: new HttpHeaders({'Content-Type': 'application/json'})
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class HttpClientHeroService extends HeroService {
|
||||
constructor(private http: HttpClient) {
|
||||
super();
|
||||
}
|
||||
|
||||
getHeroes(): Observable<Hero[]> {
|
||||
return this.http.get<Hero[]>(this.heroesUrl).pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
// This get-by-id will 404 when id not found
|
||||
getHero(id: number): Observable<Hero> {
|
||||
const url = `${this.heroesUrl}/${id}`;
|
||||
return this.http.get<Hero>(url).pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
// This get-by-id does not 404; returns undefined when id not found
|
||||
// getHero<Data>(id: number): Observable<Hero> {
|
||||
// const url = `${this._heroesUrl}/?id=${id}`;
|
||||
// return this.http.get<Hero[]>(url)
|
||||
// .map(heroes => heroes[0] as Hero)
|
||||
// .catch(this.handleError);
|
||||
// }
|
||||
|
||||
addHero(name: string): Observable<Hero> {
|
||||
const hero = {name};
|
||||
|
||||
return this.http.post<Hero>(this.heroesUrl, hero, cudOptions)
|
||||
.pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
deleteHero(hero: Hero|number): Observable<Hero> {
|
||||
const id = typeof hero === 'number' ? hero : hero.id;
|
||||
const url = `${this.heroesUrl}/${id}`;
|
||||
|
||||
return this.http.delete<Hero>(url, cudOptions).pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
searchHeroes(term: string): Observable<Hero[]> {
|
||||
term = term.trim();
|
||||
// add safe, encoded search parameter if term is present
|
||||
const options = term ? {params: new HttpParams().set('name', term)} : {};
|
||||
|
||||
return this.http.get<Hero[]>(this.heroesUrl, options).pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
updateHero(hero: Hero): Observable<Hero> {
|
||||
return this.http.put<Hero>(this.heroesUrl, hero, cudOptions).pipe(catchError(this.handleError));
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
// In a real world app, we might send the error to remote logging infrastructure
|
||||
// and reformat for user consumption
|
||||
return throwError(error);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user