@fingerprintsoft/angular-spring-hal
Version:
This Angular module offers a HAL/JSON http-client to easily interact with a Spring Data Rest API or any API that implements the Spring Data Rest resource model
1 lines • 118 kB
Source Map (JSON)
{"version":3,"file":"fingerprintsoft-angular-spring-hal.mjs","sources":["../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/services/CustomEncoder.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/Utils.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/cache/cache.helper.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/models/resource.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/models/resource-array.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/models/resource-helper.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/services/external.service.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/services/resource.service.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/interceptor/TokenConfigService.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/interceptor/Auth.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/interceptor/AuthInterceptor.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/angular-hal.module.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/lib/services/rest.service.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/public-api.ts","../../../../projects/fingerprintsoft/angular-spring-hal/src/fingerprintsoft-angular-spring-hal.ts"],"sourcesContent":["import {HttpParameterCodec} from \"@angular/common/http\";\n\nexport class CustomEncoder implements HttpParameterCodec {\n encodeKey(key: string): string {\n return encodeURIComponent(key);\n }\n\n encodeValue(value: string): string {\n return encodeURIComponent(value);\n }\n\n decodeKey(key: string): string {\n return decodeURIComponent(key);\n }\n\n decodeValue(value: string): string {\n return decodeURIComponent(value);\n }\n}","// @dynamic\nexport class Utils {\n public static isNullOrUndefined(value: any): boolean {\n return value === null || value === undefined;\n }\n\n public static isPrimitive(value: any): boolean {\n return (typeof value !== 'object' && typeof value !== 'function') || value === null;\n }\n}\n","import { Resource } from '../models/resource';\nimport * as hash from 'hash.js';\nimport { HalOptions } from '../services/rest.service';\n\nexport type ResourceExpire<T extends Resource> = { entity: any, body?: any, params?: HalOptions, expire: number };\n\nexport enum EvictStrategy {\n EvictTrivial,\n EvictSmart\n}\n\n// @dynamic\nexport class CacheHelper {\n private static cacheMap: Map<string, ResourceExpire<any>> = new Map<string, ResourceExpire<any>>();\n\n static isActive = true;\n // TODO\n static maxEntries: number = 100;\n static evictStrategy: EvictStrategy = EvictStrategy.EvictTrivial;\n static defaultExpire: number = 10 * 60 * 1000; //10 minutes\n\n static initClearCacheProcess() {\n if (this.isActive) {\n setInterval(() => {\n Date.now();\n if (CacheHelper.evictStrategy == EvictStrategy.EvictTrivial)\n this.evictAll();\n else if (CacheHelper.evictStrategy == EvictStrategy.EvictSmart) {\n this.cacheMap.forEach((value: ResourceExpire<any>, key: string) => {\n if (value.expire > 0 && Date.now() > value.expire)\n this.evict(key);\n });\n }\n }, 15 * 60 * 1000);\n }\n }\n\n static ifPresent<T extends Resource>(link: string, body?: string, params?: HalOptions, isActiveLocal: boolean = true): boolean {\n if (!this.isActive || !isActiveLocal)\n return false;\n return this.cacheMap.has(CacheHelper.key(link, body, params));\n }\n\n static getArray<T extends Resource>(link: string, body?: string, params?: HalOptions): T[] {\n return this.cacheMap.get(CacheHelper.key(link, body, params)).entity;\n }\n\n static putArray<T extends Resource>(link: string, array: T[], expireMs: number = 10 * 60 * 1000, body?: string, params?: HalOptions) {\n if (this.isActive) {\n let resourceExpire: ResourceExpire<T> = {entity: array, expire: CacheHelper.expireDate(expireMs)};\n this.cacheMap.set(CacheHelper.key(link, body, params), resourceExpire);\n }\n }\n\n static get<T extends Resource>(link: string, body?: string, params?: HalOptions): T {\n return this.cacheMap.get(CacheHelper.key(link, body, params)).entity;\n }\n\n static put<T extends Resource>(link: string, array: T, expireMs: number = 10 * 60 * 1000, body?: string, params?: HalOptions) {\n if (this.isActive) {\n let resourceExpire: ResourceExpire<T> = {entity: array, expire: CacheHelper.expireDate(expireMs)};\n this.cacheMap.set(CacheHelper.key(link, body, params), resourceExpire);\n }\n }\n\n private static expireDate(expireMs: number): number {\n if (expireMs == 0)\n return 0;\n return Date.now() + expireMs;\n }\n\n private static key(link: string, body?: string, halOptions?: HalOptions): string {\n\n let k: string = link;\n if (body)\n k += body;\n\n if (halOptions)\n k += CacheHelper.toStringParams(halOptions);\n\n let key: string = hash.sha256().update(k).digest('hex');\n return key;\n }\n\n private static toStringParams(options: HalOptions) {\n let s: string = '';\n if (options.size) {\n s = 'size=' + options.size.toString() + '&';\n }\n\n if (options.notPaged) {\n s += 'notPaged=true&';\n }\n\n if (options.params) {\n options.params.forEach(param => {\n s += param.key + '=' + param.value + '&';\n });\n }\n\n if (options.sort) {\n options.sort.forEach(sortInfo => {\n let sortString = '';\n sortString = sortInfo.path ? sortString.concat(sortInfo.path) : sortString;\n sortString = sortInfo.order ? sortString.concat(',').concat(sortInfo.order) : sortString;\n s += 'sort' + sortString + '&';\n });\n }\n return s;\n }\n\n static evict(key: string) {\n this.cacheMap.delete(key);\n }\n\n static evictAll() {\n this.cacheMap.clear();\n }\n}\n","import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs';\n\nimport { catchError, map } from 'rxjs/operators';\nimport { HttpParams, HttpResponse } from '@angular/common/http';\nimport { ResourceHelper } from './resource-helper';\nimport { ResourceArray } from './resource-array';\n\nimport { HalOptions } from '../services/rest.service';\nimport { SubTypeBuilder } from './subtype-builder';\nimport { Injectable } from '@angular/core';\nimport { CustomEncoder } from '../services/CustomEncoder';\nimport { Utils } from '../Utils';\nimport { CacheHelper } from '../cache/cache.helper';\n\nexport type Link = { href: string, templated?: boolean };\nexport type Links = { [key: string]: Link };\n\n@Injectable()\nexport abstract class Resource {\n\n public proxyUrl: string;\n public rootUrl: string;\n\n public _links: any;\n public _subtypes: Map<string, any>;\n\n public get subtypes(): Map<string, any> {\n return this._subtypes;\n }\n\n public set subtypes(_subtypes: Map<string, any>) {\n this._subtypes = _subtypes;\n }\n\n constructor() {\n }\n\n // Get self\n public uri(): string {\n if (!Utils.isNullOrUndefined(this._links) && !Utils.isNullOrUndefined(this._links['self'])) {\n return ResourceHelper.getProxy(this._links['self'].href);\n } else {\n return null;\n }\n }\n\n // Get rel uri\n public relURI(rel: string): string {\n if (!Utils.isNullOrUndefined(this._links) && !Utils.isNullOrUndefined(this._links[rel])) {\n return ResourceHelper.getProxy(this._links[rel].href);\n } else {\n return null;\n }\n }\n\n // Get related resource\n public getRelation<T extends Resource>(type: { new(): T },\n relation: string,\n builder?: SubTypeBuilder,\n expireMs: number = CacheHelper.defaultExpire,\n isCacheActive: boolean = true): Observable<T> {\n let result: T = new type();\n if (this.existRelationLink(relation)) {\n if (CacheHelper.ifPresent(this.getRelationLinkHref(relation), null, null, isCacheActive)) {\n const cached: T = CacheHelper.get(this.getRelationLinkHref(relation));\n return observableOf(cached);\n }\n\n let observable = ResourceHelper.getHttp().get(ResourceHelper.getProxy(this.getRelationLinkHref(relation)), {headers: ResourceHelper.headers});\n return observable.pipe(map((data: any) => {\n if (builder) {\n for (const embeddedClassName of Object.keys(data['_links'])) {\n if (embeddedClassName == 'self') {\n let href: string = data._links[embeddedClassName].href;\n let idx: number = href.lastIndexOf('/');\n let realClassName = href.replace(ResourceHelper.getRootUri(), '').substring(0, idx);\n result = ResourceHelper.searchSubtypes(builder, realClassName, result);\n break;\n }\n }\n }\n let resource: T = ResourceHelper.instantiateResource(result, data);\n CacheHelper.put(this.getRelationLinkHref(relation), resource, expireMs);\n return resource;\n }));\n } else {\n return observableOf(null);\n }\n }\n\n public addRelations<T extends Resource>(relation: string, resources: T[]): Observable<any> {\n if (!Utils.isNullOrUndefined(this._links) && !Utils.isNullOrUndefined(this._links[relation])) {\n let header = ResourceHelper.headers.append('Content-Type', 'text/uri-list');\n let uris = resources.map(r => r._links.self.href).join('\\n');\n return ResourceHelper.getHttp().post(ResourceHelper.getProxy(this._links[relation].href), uris, {headers: header});\n } else {\n return observableThrowError('no relation found');\n }\n }\n\n public replaceRelations<T extends Resource>(relation: string, resources: T[]): Observable<any> {\n if (!Utils.isNullOrUndefined(this._links) && !Utils.isNullOrUndefined(this._links[relation])) {\n let header = ResourceHelper.headers.append('Content-Type', 'text/uri-list');\n let uris = resources.map(r => r._links.self.href).join('\\n');\n return ResourceHelper.getHttp().put(ResourceHelper.getProxy(this._links[relation].href), uris, {headers: header});\n } else {\n return observableThrowError('no relation found');\n }\n }\n\n\n // Get collection of related resources\n public getRelationArray<T extends Resource>(type: { new(): T },\n relation: string,\n _embedded?: string,\n options?: HalOptions,\n builder?: SubTypeBuilder,\n expireMs: number = CacheHelper.defaultExpire,\n isCacheActive: boolean = true): Observable<T[]> {\n\n const params = ResourceHelper.optionParams(new HttpParams({encoder: new CustomEncoder()}), options);\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>(Utils.isNullOrUndefined(_embedded) ? '_embedded' : _embedded);\n if (this.existRelationLink(relation)) {\n if (CacheHelper.ifPresent(this.getRelationLinkHref(relation), null, options, isCacheActive))\n return observableOf(CacheHelper.getArray(this.getRelationLinkHref(relation)));\n\n let observable = ResourceHelper.getHttp().get(ResourceHelper.getProxy(this.getRelationLinkHref(relation)), {\n headers: ResourceHelper.headers, observe: 'response', params: params,\n });\n return observable\n .pipe(\n map(response => ResourceHelper.instantiateResourceCollection<T>(type, response, result, builder)),\n catchError(error => observableThrowError(error)),\n ).pipe(map((array: ResourceArray<T>) => {\n CacheHelper.putArray(this.getRelationLinkHref(relation), array.result, expireMs);\n return array.result;\n }));\n } else {\n return observableOf([]);\n }\n }\n\n public getProjection<T extends Resource>(type: { new(): T },\n resource: string,\n id: string,\n projectionName: string,\n expireMs: number = CacheHelper.defaultExpire,\n isCacheActive: boolean = true): Observable<T> {\n const uri = this.getResourceUrl(resource).concat('/', id).concat('?projection=' + projectionName);\n const result: T = new type();\n\n if (CacheHelper.ifPresent(uri, null, null, isCacheActive)) {\n const cached: T = CacheHelper.get(uri);\n return observableOf(cached);\n }\n\n let observable = ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers});\n return observable.pipe(\n map(data => {\n let resource: T = ResourceHelper.instantiateResource(result, data);\n CacheHelper.put(uri, resource, expireMs);\n return resource;\n }),\n catchError(error => observableThrowError(error)),\n );\n }\n\n public getProjectionArray<T extends Resource>(type: { new(): T },\n resource: string,\n projectionName: string,\n expireMs: number = CacheHelper.defaultExpire,\n isCacheActive: boolean = true): Observable<T[]> {\n const uri = this.getResourceUrl(resource).concat('?projection=' + projectionName);\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>('_embedded');\n\n if (CacheHelper.ifPresent(uri, null, null, isCacheActive))\n return observableOf(CacheHelper.getArray(uri));\n\n let observable = ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers, observe: 'response'});\n return observable.pipe(\n map(response => ResourceHelper.instantiateResourceCollection<T>(type, response, result)),\n map((array: ResourceArray<T>) => {\n CacheHelper.putArray(uri, array.result, expireMs);\n return array.result;\n }),\n );\n }\n\n private getResourceUrl(resource?: string): string {\n let url = ResourceHelper.getURL();\n if (!url.endsWith('/')) {\n url = url.concat('/');\n }\n if (resource) {\n return url.concat(resource);\n }\n\n url = url.replace('{?projection}', '');\n return url;\n }\n\n private getRelationLinkHref(relation: string) {\n if (this._links[relation].templated)\n return this._links[relation].href.replace('{?projection}', '');\n return this._links[relation].href;\n }\n\n private existRelationLink(relation: string): boolean {\n return !Utils.isNullOrUndefined(this._links) && !Utils.isNullOrUndefined(this._links[relation]);\n }\n\n // Adds the given resource to the bound collection by the relation\n public addRelation<T extends Resource>(relation: string, resource: T): Observable<any> {\n if (this.existRelationLink(relation)) {\n let header = ResourceHelper.headers.append('Content-Type', 'text/uri-list');\n return ResourceHelper.getHttp().post(ResourceHelper.getProxy(this.getRelationLinkHref(relation)), resource._links.self.href, {headers: header});\n } else {\n return observableThrowError('no relation found');\n }\n }\n\n // Allow for resources that are verbs instead of nouns e.g. payment/changeofaddress etc.\n public postRelation<T extends Resource>(relation: string, type: { new(): T }, resource: T = null): Observable<T> {\n if (this.existRelationLink(relation)) {\n let observable = ResourceHelper.getHttp().post(\n ResourceHelper.getProxy(this.getRelationLinkHref(relation)),\n resource,\n {\n headers: ResourceHelper.headers,\n observe: 'response'\n }\n )\n const result: T = new type();\n return observable.pipe(\n map((response: HttpResponse<any>) => {\n return ResourceHelper.instantiateResourceFromResponse(result, response);\n }),\n catchError(error => observableThrowError(error)),\n );\n } else {\n return observableThrowError('no payment relation found');\n }\n }\n\n\n public updateRelation<T extends Resource>(relation: string, resource: T): Observable<any> {\n if (this.existRelationLink(relation)) {\n let header = ResourceHelper.headers.append('Content-Type', 'text/uri-list');\n return ResourceHelper.getHttp().patch(ResourceHelper.getProxy(this.getRelationLinkHref(relation)), resource._links.self.href, {headers: header});\n } else {\n return observableThrowError('no relation found');\n }\n }\n\n // Bind the given resource to this resource by the given relation\n public substituteRelation<T extends Resource>(relation: string, resource: T): Observable<any> {\n if (this.existRelationLink(relation)) {\n let header = ResourceHelper.headers.append('Content-Type', 'text/uri-list');\n return ResourceHelper.getHttp().put(ResourceHelper.getProxy(this.getRelationLinkHref(relation)), resource._links.self.href, {headers: header});\n } else {\n return observableThrowError('no relation found');\n }\n }\n\n // Unbind the resource with the given relation from this resource\n public deleteRelation<T extends Resource>(relation: string, resource: T): Observable<any> {\n if (this.existRelationLink(relation)) {\n let link: string = resource._links['self'].href;\n let idx: number = link.lastIndexOf('/') + 1;\n\n if (idx == -1)\n return observableThrowError('no relation found');\n\n let relationId: string = link.substring(idx);\n return ResourceHelper.getHttp().delete(ResourceHelper.getProxy(this.getRelationLinkHref(relation) + '/' + relationId), {headers: ResourceHelper.headers});\n } else {\n return observableThrowError('no relation found');\n }\n }\n}\n","import { Observable, throwError as observableThrowError } from 'rxjs';\n\nimport { catchError, map } from 'rxjs/operators';\nimport { Sort } from './sort';\nimport { ArrayInterface } from './array-interface';\nimport { ResourceHelper } from './resource-helper';\nimport { Resource } from './resource';\nimport * as url from 'url';\n\n// @dynamic\nexport class ResourceArray<T extends Resource> implements ArrayInterface<T> {\n public sortInfo: Sort[];\n\n public proxyUrl: string;\n public rootUrl: string;\n\n public self_uri: string;\n public next_uri: string;\n public prev_uri: string;\n public first_uri: string;\n public last_uri: string;\n\n public _embedded;\n\n public totalElements = 0;\n public totalPages = 1;\n public pageNumber = 1;\n public pageSize: number;\n\n public result: T[] = [];\n\n push = (el: T) => {\n this.result.push(el);\n };\n\n length = (): number => {\n return this.result.length;\n };\n\n private init = (type: { new(): T }, response: any, sortInfo: Sort[]): ResourceArray<T> => {\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>(this._embedded);\n result.sortInfo = sortInfo;\n ResourceHelper.instantiateResourceCollection(type, response, result);\n return result;\n };\n\n// Load next page\n next = (type: { new(): T }): Observable<ResourceArray<T>> => {\n if (this.next_uri) {\n return ResourceHelper.getHttp().get(ResourceHelper.getProxy(this.next_uri), {headers: ResourceHelper.headers, observe: 'response'}).pipe(\n map(response => this.init(type, response, this.sortInfo)),\n catchError(error => observableThrowError(error)),);\n }\n return observableThrowError('no next defined');\n };\n\n prev = (type: { new(): T }): Observable<ResourceArray<T>> => {\n if (this.prev_uri) {\n return ResourceHelper.getHttp().get(ResourceHelper.getProxy(this.prev_uri), {headers: ResourceHelper.headers, observe: 'response'}).pipe(\n map(response => this.init(type, response, this.sortInfo)),\n catchError(error => observableThrowError(error)),);\n }\n return observableThrowError('no prev defined');\n };\n\n// Load first page\n\n first = (type: { new(): T }): Observable<ResourceArray<T>> => {\n if (this.first_uri) {\n return ResourceHelper.getHttp().get(ResourceHelper.getProxy(this.first_uri), {headers: ResourceHelper.headers, observe: 'response'}).pipe(\n map(response => this.init(type, response, this.sortInfo)),\n catchError(error => observableThrowError(error)),);\n }\n return observableThrowError('no first defined');\n };\n\n// Load last page\n\n last = (type: { new(): T }): Observable<ResourceArray<T>> => {\n if (this.last_uri) {\n return ResourceHelper.getHttp().get(ResourceHelper.getProxy(this.last_uri), {headers: ResourceHelper.headers, observe: 'response'}).pipe(\n map(response => this.init(type, response, this.sortInfo)),\n catchError(error => observableThrowError(error)),);\n }\n return observableThrowError('no last defined');\n };\n\n// Load page with given pageNumber\n\n page = (type: { new(): T }, pageNumber: number): Observable<ResourceArray<T>> => {\n this.self_uri = this.self_uri.replace('{?page,size,sort,projection}', '');\n this.self_uri = this.self_uri.replace('{&sort}', '');\n let urlParsed = url.parse(ResourceHelper.getProxy(this.self_uri));\n let query: string = ResourceArray.replaceOrAdd(urlParsed.query, 'size', this.pageSize.toString());\n query = ResourceArray.replaceOrAdd(query, 'page', pageNumber.toString());\n\n\n let uri = urlParsed.query ?\n ResourceHelper.getProxy(this.self_uri).replace(urlParsed.query, query) : ResourceHelper.getProxy(this.self_uri).concat(query);\n uri = this.addSortInfo(uri);\n return ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers, observe: 'response'}).pipe(\n map(response => this.init(type, response, this.sortInfo)),\n catchError(error => observableThrowError(error)),);\n };\n\n// Sort collection based on given sort attribute\n\n\n sortElements = (type: { new(): T }, ...sort: Sort[]): Observable<ResourceArray<T>> => {\n this.self_uri = this.self_uri.replace('{?page,size,sort}', '');\n this.self_uri = this.self_uri.replace('{&sort}', '');\n let uri = ResourceHelper.getProxy(this.self_uri).concat('?', 'size=', this.pageSize.toString(), '&page=', this.pageNumber.toString());\n uri = this.addSortInfo(uri);\n return ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers, observe: 'response'}).pipe(\n map(response => this.init(type, response, sort)),\n catchError(error => observableThrowError(error)),);\n };\n\n// Load page with given size\n\n size = (type: { new(): T }, size: number): Observable<ResourceArray<T>> => {\n let uri = ResourceHelper.getProxy(this.self_uri).concat('?', 'size=', size.toString());\n uri = this.addSortInfo(uri);\n return ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers, observe: 'response'}).pipe(\n map(response => this.init(type, response, this.sortInfo)),\n catchError(error => observableThrowError(error)),);\n };\n\n private addSortInfo(uri: string) {\n if (this.sortInfo) {\n for (const item of this.sortInfo) {\n uri = uri.concat('&sort=', item.path, ',', item.order);\n }\n }\n return uri;\n }\n\n private static replaceOrAdd(query: string, field: string, value: string): string {\n if (query) {\n let idx: number = query.indexOf(field);\n let idxNextAmp: number = query.indexOf('&', idx) == -1 ? query.indexOf('/', idx) : query.indexOf('&', idx);\n\n if (idx != -1) {\n let seachValue = query.substring(idx, idxNextAmp);\n query = query.replace(seachValue, field + '=' + value);\n } else {\n query = query.concat(\"&\" + field + '=' + value);\n }\n } else {\n query = \"?\" + field + '=' + value;\n }\n return query;\n }\n}\n","import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http';\nimport { Resource } from './index';\nimport { ResourceArray } from './index';\nimport { HalOptions, HalParam } from '../services/rest.service';\nimport { SubTypeBuilder } from './index';\nimport * as url from 'url';\nimport { Utils } from '../Utils';\n\n// @dynamic\nexport class ResourceHelper {\n\n private static readonly URL_TEMPLATE_VAR_REGEXP = /{[^}]*}/g;\n private static readonly EMPTY_STRING = '';\n private static _headers: HttpHeaders;\n private static proxy_uri: string;\n private static root_uri: string;\n private static http: HttpClient;\n\n public static get headers(): HttpHeaders {\n if (Utils.isNullOrUndefined(this._headers))\n this._headers = new HttpHeaders();\n return this._headers;\n }\n\n public static set headers(headers: HttpHeaders) {\n this._headers = headers;\n }\n\n static optionParams(params: HttpParams, options?: HalOptions): HttpParams {\n if (options) {\n\n params = this.params(params, options.params);\n\n if (options.size) {\n params = params.append('size', options.size.toString());\n }\n\n if (options.sort) {\n for (const s of options.sort) {\n let sortString = '';\n sortString = s.path ? sortString.concat(s.path) : sortString;\n sortString = s.order ? sortString.concat(',').concat(s.order) : sortString;\n params = params.append('sort', sortString);\n }\n }\n\n }\n return params;\n }\n\n static params(httpParams: HttpParams, params?: HalParam[]) {\n if (params) {\n for (const param of params) {\n httpParams = httpParams.append(param.key, param.value.toString());\n }\n }\n\n return httpParams;\n }\n\n static resolveRelations(resource: Resource): Object {\n const result: any = {};\n for (const key in resource) {\n if (!Utils.isNullOrUndefined(resource[key])) {\n if (ResourceHelper.className(resource[key])\n .find((className: string) => className == 'Resource') || resource[key]['_links']) {\n if (resource[key]['_links'])\n result[key] = resource[key]['_links']['self']['href'];\n } else if (Array.isArray(resource[key])) {\n let array: any[] = resource[key];\n if (array) {\n result[key] = new Array();\n array.forEach((element) => {\n if (Utils.isPrimitive(element)) {\n result[key].push(element);\n } else {\n result[key].push(this.resolveRelations(element));\n }\n });\n }\n } else {\n result[key] = resource[key];\n }\n }\n }\n return result as Object;\n }\n\n static createEmptyResult<T extends Resource>(_embedded: string): ResourceArray<T> {\n let resourceArray: ResourceArray<T> = new ResourceArray<T>();\n resourceArray._embedded = _embedded;\n return resourceArray;\n }\n\n static getClassName(obj: any): string {\n var funcNameRegex = /function (.+?)\\(/;\n var results = (funcNameRegex).exec(obj.constructor.toString());\n return (results && results.length > 1) ? results[1] : '';\n }\n\n static className(objProto: any): string[] {\n let classNames = [];\n let obj = Object.getPrototypeOf(objProto);\n let className: string;\n\n while ((className = ResourceHelper.getClassName(obj)) !== 'Object') {\n classNames.push(className);\n obj = Object.getPrototypeOf(obj);\n }\n\n return classNames;\n }\n\n static instantiateResourceFromResponse<T extends Resource>(entity: T, response: HttpResponse<any>): T {\n if (response.status >= 200 && response.status <= 207) {\n return ResourceHelper.instantiateResource(entity, response.body);\n } else if (response.status == 404) {\n return null;\n }\n }\n\n static instantiateResourceCollection<T extends Resource>(type: { new(): T }, response: HttpResponse<any>,\n result: ResourceArray<T>, builder?: SubTypeBuilder): ResourceArray<T> {\n\n if (response.status >= 200 && response.status <= 207) {\n let payload = response.body;\n if (payload[result._embedded]) {\n for (const embeddedClassName of Object.keys(payload[result._embedded])) {\n let embedded: any = payload[result._embedded];\n const items = embedded[embeddedClassName];\n for (let item of items) {\n let instance: T = new type();\n instance = this.searchSubtypes(builder, embeddedClassName, instance);\n\n this.instantiateResource(instance, item);\n result.push(instance);\n }\n }\n }\n\n result.totalElements = payload.page ? payload.page.totalElements : result.length;\n result.totalPages = payload.page ? payload.page.totalPages : 1;\n result.pageNumber = payload.page ? payload.page.number : 1;\n result.pageSize = payload.page ? payload.page.size : 20;\n\n result.self_uri = payload._links && payload._links.self ? payload._links.self.href : undefined;\n result.next_uri = payload._links && payload._links.next ? payload._links.next.href : undefined;\n result.prev_uri = payload._links && payload._links.prev ? payload._links.prev.href : undefined;\n result.first_uri = payload._links && payload._links.first ? payload._links.first.href : undefined;\n result.last_uri = payload._links && payload._links.last ? payload._links.last.href : undefined;\n } else if (response.status == 404) {\n result.result = [];\n }\n return result;\n }\n\n static searchSubtypes<T extends Resource>(builder: SubTypeBuilder, embeddedClassName: string, instance: T) {\n if (builder && builder.subtypes) {\n let keys = builder.subtypes.keys();\n Array.from(keys).forEach((subtypeKey: string) => {\n if (embeddedClassName.toLowerCase().startsWith(subtypeKey.toLowerCase())) {\n let subtype: { new(): any } = builder.subtypes.get(subtypeKey);\n instance = new subtype();\n }\n });\n }\n return instance;\n }\n\n static instantiateResource<T extends Resource>(entity: T, payload: Object): T {\n for (const p in payload) {\n //TODO array initClearCacheProcess\n /* if(entity[p].constructor === Array && isNullOrUndefined(payload[p]))\n entity[p] = [];\n else*/\n entity[p] = payload[p];\n }\n return entity;\n }\n\n static setProxyUri(proxy_uri: string) {\n ResourceHelper.proxy_uri = proxy_uri;\n }\n\n static setRootUri(root_uri: string) {\n ResourceHelper.root_uri = root_uri;\n }\n\n public static getURL(): string {\n return ResourceHelper.proxy_uri && ResourceHelper.proxy_uri != '' ?\n ResourceHelper.addSlash(ResourceHelper.proxy_uri) :\n ResourceHelper.addSlash(ResourceHelper.root_uri);\n }\n\n private static addSlash(uri: string): string {\n let uriParsed = url.parse(uri);\n if (Utils.isNullOrUndefined(uriParsed.search) && uri && uri[uri.length - 1] != '/')\n return uri + '/';\n return uri;\n }\n\n public static getProxy(url: string): string {\n url = url.replace('{?projection}', '');\n if (!ResourceHelper.proxy_uri || ResourceHelper.proxy_uri == '')\n return url;\n return ResourceHelper.addSlash(\n ResourceHelper.removeUrlTemplateVars(url)\n .replace(ResourceHelper.root_uri, ResourceHelper.proxy_uri));\n }\n\n private static removeUrlTemplateVars(url: string) {\n return url.replace(ResourceHelper.URL_TEMPLATE_VAR_REGEXP, ResourceHelper.EMPTY_STRING);\n }\n\n public static setHttp(http: HttpClient) {\n this.http = http;\n }\n\n public static getHttp(): HttpClient {\n return this.http;\n }\n\n static getRootUri() {\n return this.root_uri;\n }\n}\n","import {HttpClient} from '@angular/common/http';\nimport {Inject, Injectable} from '@angular/core';\nimport {ResourceHelper} from '../models/resource-helper';\nimport {ExternalConfigurationHandlerInterface} from './external-configuration.handler';\nimport {ExternalConfiguration} from './ExternalConfiguration';\nimport {CacheHelper} from '../cache/cache.helper';\n\n@Injectable()\nexport class ExternalService {\n\n constructor(@Inject('ExternalConfigurationService') private externalConfigurationService: ExternalConfigurationHandlerInterface) {\n ResourceHelper.setProxyUri(externalConfigurationService.getProxyUri());\n ResourceHelper.setRootUri(externalConfigurationService.getRootUri());\n ResourceHelper.setHttp(externalConfigurationService.getHttp());\n CacheHelper.initClearCacheProcess()\n }\n\n public updateExternalConfigurationHandlerInterface(externalConfigurationService: ExternalConfigurationHandlerInterface) {\n\tthis.externalConfigurationService = externalConfigurationService;\n\n ResourceHelper.setProxyUri(externalConfigurationService.getProxyUri());\n ResourceHelper.setRootUri(externalConfigurationService.getRootUri());\n ResourceHelper.setHttp(externalConfigurationService.getHttp());\n }\n\n public getExternalConfiguration(): ExternalConfiguration {\n return this.externalConfigurationService.getExternalConfiguration();\n }\n\n public getProxyUri(): string {\n return this.externalConfigurationService.getProxyUri();\n }\n\n public getRootUri(): string {\n return this.externalConfigurationService.getRootUri();\n }\n\n public getURL(): string {\n return ResourceHelper.getURL();\n }\n\n public getHttp(): HttpClient {\n return ResourceHelper.getHttp();\n }\n}\n","import { Observable, throwError as observableThrowError } from 'rxjs';\n\nimport { catchError, map } from 'rxjs/operators';\nimport { Resource } from '../models/resource';\nimport { ResourceHelper } from '../models/resource-helper';\nimport { Injectable } from '@angular/core';\nimport { HttpParams, HttpResponse } from '@angular/common/http';\nimport { Sort } from '../models';\nimport { ResourceArray } from '../models';\nimport { ExternalService } from './external.service';\nimport { HalOptions, HalParam } from './rest.service';\nimport { SubTypeBuilder } from '../models';\nimport { CustomEncoder } from './CustomEncoder';\nimport * as url from 'url';\n\n// @dynamic\n@Injectable()\nexport class ResourceService {\n\n constructor(private externalService: ExternalService) {\n }\n\n private static getURL(): string {\n return ResourceHelper.getURL();\n }\n\n public getAll<T extends Resource>(type: { new(): T }, resource: string, _embedded: string, options?: HalOptions, subType?: SubTypeBuilder): Observable<ResourceArray<T>> {\n const uri = this.getResourceUrl(resource);\n const params = ResourceHelper.optionParams(new HttpParams({encoder: new CustomEncoder()}), options);\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>(_embedded);\n\n this.setUrls(result);\n result.sortInfo = options ? options.sort : undefined;\n let observable = ResourceHelper.getHttp().get(uri, {\n headers: ResourceHelper.headers,\n observe: 'response',\n params: params,\n });\n return observable.pipe(map(response => ResourceHelper.instantiateResourceCollection(type, response, result, subType)),\n catchError(error => observableThrowError(error)));\n }\n\n public get<T extends Resource>(type: { new(): T }, resource: string, id: any, params?: HalParam[], builder?: SubTypeBuilder): Observable<T> {\n let self = this;\n const uri = this.getResourceUrl(resource).concat('/', id);\n\n let result: T = new type();\n const httpParams = ResourceHelper.params(new HttpParams(), params);\n\n this.setUrlsResource(result);\n let observable = ResourceHelper.getHttp().get(uri, {\n headers: ResourceHelper.headers,\n observe: 'response',\n params: httpParams,\n });\n // return observable.pipe(map(data => ResourceHelper.instantiateResource(result, data)),\n // catchError(error => observableThrowError(error)),);\n\n return observable.pipe(\n map((response: HttpResponse<any>) => {\n if (builder) {\n let linkHref = url.parse(response.body._links.self.href).pathname;\n let regex = /([A-Za-z0-9]+)\\/([A-Za-z0-9]+)\\/([A-Za-z0-9]+)/g;\n let match = regex.exec(linkHref);\n if (match != null) {\n let embeddedClassName = match[2];\n result = ResourceHelper.searchSubtypes(builder, embeddedClassName, result);\n }\n }\n return ResourceHelper.instantiateResourceFromResponse(result, response);\n }),\n catchError(error => observableThrowError(error)),\n );\n }\n\n public selfURI<T extends Resource>(type: { new(): T }, resource: string, id: any): string {\n return this.getResourceUrl(resource).concat('/', id);\n }\n\n public getBySelfLink<T extends Resource>(type: { new(): T }, resourceLink: string): Observable<T> {\n const result: T = new type();\n\n this.setUrlsResource(result);\n let observable = ResourceHelper.getHttp().get(ResourceHelper.getProxy(resourceLink), {headers: ResourceHelper.headers});\n return observable.pipe(map(data => ResourceHelper.instantiateResource(result, data)),\n catchError(error => observableThrowError(error)),);\n }\n\n public search<T extends Resource>(type: { new(): T }, query: string, resource: string, _embedded: string, options?: HalOptions,\n subType?: SubTypeBuilder): Observable<ResourceArray<T>> {\n const uri = this.getResourceUrl(resource).concat('/search/', query);\n const params = ResourceHelper.optionParams(new HttpParams({encoder: new CustomEncoder()}), options);\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>(_embedded);\n\n this.setUrls(result);\n let observable = ResourceHelper.getHttp().get(uri, {\n headers: ResourceHelper.headers,\n observe: 'response',\n params: params,\n });\n return observable.pipe(map(response => ResourceHelper.instantiateResourceCollection(type, response, result, subType)),\n catchError(error => observableThrowError(error)),);\n }\n\n public searchSingle<T extends Resource>(type: { new(): T }, query: string, resource: string, options?: HalOptions): Observable<T> {\n const uri = this.getResourceUrl(resource).concat('/search/', query);\n const params = ResourceHelper.optionParams(new HttpParams({encoder: new CustomEncoder()}), options);\n const result: T = new type();\n\n this.setUrlsResource(result);\n let observable = ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers, params: params});\n return observable.pipe(map(response => ResourceHelper.instantiateResource(result, response)),\n catchError(error => observableThrowError(error)),);\n }\n\n public customQuery<T extends Resource>(type: { new(): T }, query: string, resource: string, _embedded: string, options?: HalOptions, subType?: SubTypeBuilder): Observable<ResourceArray<T>> {\n const uri = this.getResourceUrl(resource + query);\n const params = ResourceHelper.optionParams(new HttpParams({encoder: new CustomEncoder()}), options);\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>(_embedded);\n\n this.setUrls(result);\n let observable = ResourceHelper.getHttp().get(uri, {\n headers: ResourceHelper.headers,\n observe: 'response',\n params: params,\n });\n return observable.pipe(map(response => ResourceHelper.instantiateResourceCollection(type, response, result, subType)),\n catchError(error => observableThrowError(error)));\n }\n\n public customQueryPost<T extends Resource>(type: { new(): T }, query: string, resource: string,\n _embedded: string, options?: HalOptions, body?: any,\n subType?: SubTypeBuilder): Observable<ResourceArray<T>> {\n const uri = this.getResourceUrl(resource + query);\n const params = ResourceHelper.optionParams(new HttpParams(), options);\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>(_embedded);\n\n this.setUrls(result);\n let observable = ResourceHelper.getHttp().post(uri, body, {\n headers: ResourceHelper.headers,\n observe: 'response',\n params: params,\n });\n return observable.pipe(map(response => ResourceHelper.instantiateResourceCollection(type, response, result, subType)),\n catchError(error => observableThrowError(error)));\n }\n\n public getByRelation<T extends Resource>(type: { new(): T }, resourceLink: string): Observable<T> {\n let result: T = new type();\n\n this.setUrlsResource(result);\n let observable = ResourceHelper.getHttp().get(resourceLink, {headers: ResourceHelper.headers});\n return observable.pipe(map(data => ResourceHelper.instantiateResource(result, data)),\n catchError(error => observableThrowError(error)));\n }\n\n public getByRelationArray<T extends Resource>(type: { new(): T }, resourceLink: string, _embedded: string, builder?: SubTypeBuilder): Observable<ResourceArray<T>> {\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>(_embedded);\n\n this.setUrls(result);\n let observable = ResourceHelper.getHttp().get(resourceLink, {\n headers: ResourceHelper.headers,\n observe: 'response',\n });\n return observable.pipe(\n map(response => ResourceHelper.instantiateResourceCollection(type, response, result, builder)),\n catchError(error => observableThrowError(error)),\n );\n }\n\n public getProjection<T extends Resource>(type: { new(): T }, resource: string, id: string, projectionName: string): Observable<T> {\n const uri = this.getResourceUrl(resource).concat('/', id).concat('?projection=' + projectionName);\n const result: T = new type();\n\n let observable = ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers});\n return observable.pipe(\n map(data => ResourceHelper.instantiateResource(result, data)),\n catchError(error => observableThrowError(error)),\n );\n }\n\n public getProjectionArray<T extends Resource>(type: { new(): T }, resource: string, projectionName: string): Observable<T[]> {\n const uri = this.getResourceUrl(resource).concat('?projection=' + projectionName);\n const result: ResourceArray<T> = ResourceHelper.createEmptyResult<T>('_embedded');\n\n let observable = ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers, observe: 'response'});\n return observable\n .pipe(\n map(response => ResourceHelper.instantiateResourceCollection<T>(type, response, result)),\n catchError(error => observableThrowError(error)),\n ).pipe(map((resourceArray: ResourceArray<T>) => {\n return resourceArray.result;\n }));\n }\n\n public count(resource: string, query?: string, options?: HalOptions): Observable<number> {\n const uri = this.getResourceUrl(resource).concat('/search/' + (query === undefined ? 'countAll' : query));\n const params = ResourceHelper.optionParams(new HttpParams(), options);\n\n return ResourceHelper.getHttp().get(uri, {\n headers: ResourceHelper.headers,\n observe: 'response',\n params: params,\n }).pipe(\n map((response: HttpResponse<number>) => Number(response.body)),\n catchError(error => observableThrowError(error)));\n }\n\n public create<T extends Resource>(selfResource: string, entity: T) {\n const uri = ResourceHelper.getURL() + selfResource;\n const payload = ResourceHelper.resolveRelations(entity);\n\n this.setUrlsResource(entity);\n let observable = ResourceHelper.getHttp().post(uri, payload, {\n headers: ResourceHelper.headers,\n observe: 'response',\n });\n return observable.pipe(map((response: HttpResponse<string>) => {\n if (response.status >= 200 && response.status <= 207)\n return ResourceHelper.instantiateResource(entity, response.body);\n else if (response.status == 500) {\n let body: any = response.body;\n return observableThrowError(body.error);\n }\n }), catchError(error => observableThrowError(error)));\n }\n\n public query(resource: string, query: string, options?: HalOptions): Observable<any> {\n const uri = this.getResourceUrl(resource).concat('/search/', query);\n const params = ResourceHelper.optionParams(new HttpParams(), options);\n\n return ResourceHelper.getHttp().get(uri, {headers: ResourceHelper.headers, params: params}).pipe(\n map(response => response),\n catchError(error => observableThrowError(error)),);\n }\n\n public update<T extends Resource>(entity: T) {\n const uri = ResourceHelper.getProxy(entity._links.self.href);\n const payload = ResourceHelper.resolveRelations(entity);\n this.setUrlsResource(entity);\n let observable = ResourceHelper.getHttp().put(uri, payload, {headers: ResourceHelper.headers, observe: 'response'});\n return observable.pipe(map((response: HttpResponse<string>) => {\n if (response.status >= 200 && response.status <= 207)\n return ResourceHelper.instantiateResource(entity, response.body);\n else if (response.status == 500) {\n let body: any = response.body;\n return observableThrowError(body.error);\n }\n }), catchError(error => observableThrowError(error)));\n }\n\n public patch<T extends Resource>(entity: T) {\n const uri = ResourceHelper.getProxy(entity._links.self.href);\n const payload = ResourceHelper.resolveRelations(entity);\n this.setUrlsResource(entity);\n let observable = ResourceHelper.getHttp().patch(uri, payload, {headers: ResourceHelper.headers, observe: 'response'});\n return observable.pipe(map((response: HttpResponse<string>) => {\n if