@ngx-resource/core
Version:
Core of resource library
1 lines • 86.9 kB
Source Map (JSON)
{"version":3,"file":"ngx-resource-core.mjs","sources":["../../../../projects/ngx-resource/core/src/lib/Declarations.ts","../../../../projects/ngx-resource/core/src/lib/ResourceGlobalConfig.ts","../../../../projects/ngx-resource/core/src/lib/ResourceHelper.ts","../../../../projects/ngx-resource/core/src/lib/ResourceHandler.ts","../../../../projects/ngx-resource/core/src/lib/ResourceHandlerNoop.ts","../../../../projects/ngx-resource/core/src/lib/ResourceModule.ts","../../../../projects/ngx-resource/core/src/lib/Resource.ts","../../../../projects/ngx-resource/core/src/lib/ResourceAction.ts","../../../../projects/ngx-resource/core/src/lib/ResourceModel.ts","../../../../projects/ngx-resource/core/src/lib/ResourceParams.ts","../../../../projects/ngx-resource/core/src/lib/ResourceCommon/ResourceCRUDBase.ts","../../../../projects/ngx-resource/core/src/lib/ResourceCommon/ResourceCRUD.ts","../../../../projects/ngx-resource/core/src/lib/ResourceCommon/ResourceCRUDPromise.ts","../../../../projects/ngx-resource/core/src/lib/ResourceCommon/ResourceCRUDObservable.ts","../../../../projects/ngx-resource/core/src/public-api.ts","../../../../projects/ngx-resource/core/src/ngx-resource-core.ts"],"sourcesContent":["import { Observable, Subscription } from 'rxjs';\nimport { Provider } from '@angular/core';\n\nexport type TTypePromiseNull<T = {}> = T | Promise<T> | null;\n\nexport interface IResourceModuleConfig {\n handler?: Provider;\n}\n\nexport interface IResourceParamsBase {\n url?: string;\n pathPrefix?: string;\n path?: string;\n headers?: any;\n body?: any;\n params?: any;\n query?: any;\n}\n\nexport interface IResourceParams extends IResourceParamsBase {\n rootNode?: string;\n removeTrailingSlash?: boolean;\n addTimestamp?: boolean | string;\n withCredentials?: boolean;\n lean?: boolean;\n mutateBody?: boolean;\n returnAs?: ResourceActionReturnType;\n keepEmptyBody?: boolean;\n requestBodyType?: ResourceRequestBodyType;\n responseBodyType?: ResourceResponseBodyType;\n queryMappingMethod?: ResourceQueryMappingMethod;\n\n [prop: string]: any;\n}\n\nexport interface IResourceAction extends IResourceParams {\n method?: ResourceRequestMethod; // get default\n expectJsonArray?: boolean;\n resultFactory?: TResourceResultFactory;\n map?: TResourceResponseMap;\n filter?: TResourceResponseFilter;\n}\n\nexport type TResourceResponseMap = (item: any, options: IResourceActionInner) => any;\n\nexport type TResourceResponseFilter = (item: any, options: IResourceActionInner) => boolean;\n\nexport type TResourceResultFactory = (item: any, options: IResourceActionInner) => any;\n\nexport interface IResourceActionAttributes {\n body?: any;\n query?: any;\n params?: any;\n\n onSuccess?(data: any): any;\n\n onError?(data: any): any;\n}\n\nexport interface IResourceActionInner {\n actionAttributes?: IResourceActionAttributes;\n actionOptions?: IResourceAction;\n resolvedOptions?: IResourceParamsBase;\n\n queryMappingMethod?: ResourceQueryMappingMethod;\n\n usedInPath?: { [key: string]: boolean };\n mainObservable?: Observable<any>;\n subscription?: Subscription | null;\n promise?: Promise<any>;\n isModel?: boolean;\n\n requestOptions?: IResourceRequest;\n\n returnData?: any;\n}\n\nexport interface IResourceRequest {\n method?: ResourceRequestMethod;\n headers?: any;\n url?: string;\n withCredentials?: boolean;\n body?: any;\n query?: { [prop: string]: string };\n responseBodyType?: ResourceResponseBodyType;\n requestBodyType?: ResourceRequestBodyType;\n}\n\nexport interface IResourceHandlerResponse {\n promise?: Promise<IResourceResponse>;\n observable?: Observable<IResourceResponse>;\n\n abort?(): void;\n}\n\nexport interface IResourceResponse<B = any> {\n status: number;\n headers?: any;\n body?: B;\n}\n\nexport interface IResourceMethodStrictBase<IB, IQ, IP, O, R> {\n (body: IB,\n query: IQ,\n params: IP,\n onSuccess?: (data: O) => any,\n onError?: (err: IResourceResponse) => any): R;\n\n (body: IB,\n query: IQ,\n onSuccess?: (data: O) => any,\n onError?: (err: IResourceResponse) => any): R;\n\n (body: IB,\n onSuccess?: (data: O) => any,\n onError?: (err: IResourceResponse) => any): R;\n\n (onSuccess?: (data: O) => any,\n onError?: (err: IResourceResponse) => any): R;\n}\n\nexport interface IResourceMethodBase<IB, O, R>\n extends IResourceMethodStrictBase<IB, any, any, O, R> {\n}\n\n/**\n * @deprecated use IResourceMethodPromiseStrict instead\n */\nexport interface IResourceMethodStrict<IB, IQ, IP, O>\n extends IResourceMethodStrictBase<IB, IQ, IP, O, Promise<O>> {\n}\n\n/**\n * @deprecated use IResourceMethodPromise instead\n */\nexport interface IResourceMethod<IB, O>\n extends IResourceMethodBase<IB, O, Promise<O>> {\n}\n\nexport interface IResourceMethodPromiseStrict<IB, IQ, IP, O>\n extends IResourceMethodStrictBase<IB, IQ, IP, O, Promise<O>> {\n}\n\nexport interface IResourceMethodPromise<IB, O>\n extends IResourceMethodBase<IB, O, Promise<O>> {\n}\n\nexport interface IResourceMethodObservableStrict<IB, IQ, IP, O>\n extends IResourceMethodStrictBase<IB, IQ, IP, O, Observable<O>> {\n}\n\nexport interface IResourceMethodObservable<IB, O>\n extends IResourceMethodBase<IB, O, Observable<O>> {\n}\n\n\nexport interface IResourceMethodResultStrict<IB, IQ, IP, O extends {}>\n extends IResourceMethodStrictBase<IB, IQ, IP, O, ResourceResult<O>> {\n}\n\nexport interface IResourceMethodResult<IB, O extends {}>\n extends IResourceMethodBase<IB, O, ResourceResult<O>> {\n}\n\n\n// As IResourceResponse\n\n/**\n * @deprecated use IResourceMethodPromiseStrictFull instead\n */\nexport interface IResourceMethodStrictFull<IB, IQ, IP, O>\n extends IResourceMethodStrictBase<IB, IQ, IP, O, Promise<IResourceResponse<O>>> {\n}\n\n/**\n * @deprecated use IResourceMethodPromiseFull instead\n */\nexport interface IResourceMethodFull<IB, O>\n extends IResourceMethodBase<IB, O, Promise<IResourceResponse<O>>> {\n}\n\nexport interface IResourceMethodPromiseStrictFull<IB, IQ, IP, O>\n extends IResourceMethodStrictBase<IB, IQ, IP, O, Promise<IResourceResponse<O>>> {\n}\n\nexport interface IResourceMethodPromiseFull<IB, O>\n extends IResourceMethodBase<IB, O, Promise<IResourceResponse<O>>> {\n}\n\nexport interface IResourceMethodObservableStrictFull<IB, IQ, IP, O>\n extends IResourceMethodStrictBase<IB, IQ, IP, O, Observable<IResourceResponse<O>>> {\n}\n\nexport interface IResourceMethodObservableFull<IB, O>\n extends IResourceMethodBase<IB, O, Observable<IResourceResponse<O>>> {\n}\n\n\nexport interface IResourceMethodResultStrictFull<IB, IQ, IP, O>\n extends IResourceMethodStrictBase<IB, IQ, IP, O, ResourceResult<IResourceResponse<O>>> {\n}\n\nexport interface IResourceMethodResultFull<IB, O>\n extends IResourceMethodBase<IB, O, ResourceResult<IResourceResponse<O>>> {\n}\n\n\nexport type ResourceResult<R extends {}> = R & {\n $resolved?: boolean;\n $promise?: Promise<R>;\n $abort?(): void;\n};\n\n\nexport enum ResourceRequestBodyType {\n NONE = 0,\n JSON = 1,\n FORM = 2,\n FORM_DATA = 3,\n TEXT = 4,\n BLOB = 5,\n ARRAY_BUFFER = 6\n}\n\nexport enum ResourceResponseBodyType {\n Text = 1,\n Json = 2,\n ArrayBuffer = 3,\n Blob = 4\n}\n\nexport enum ResourceRequestMethod {\n Get = 1,\n Post = 2,\n Put = 3,\n Delete = 4,\n Options = 5,\n Head = 6,\n Patch = 7\n}\n\nexport enum ResourceQueryMappingMethod {\n Plain = 1,\n Bracket = 2,\n JQueryParamsBracket = 3,\n\n None = 99\n}\n\nexport enum ResourceActionReturnType {\n Promise = 'promise',\n Observable = 'observable',\n Resource = 'resource'\n}\n","import { ResourceActionReturnType, ResourceQueryMappingMethod, ResourceResponseBodyType, TTypePromiseNull } from './Declarations';\n\nexport class ResourceGlobalConfig {\n static url: TTypePromiseNull<string> = null;\n static pathPrefix: TTypePromiseNull<string> = null;\n static path: TTypePromiseNull<string> = null;\n static headers: TTypePromiseNull = null;\n static body: TTypePromiseNull = null;\n static params: TTypePromiseNull = null;\n static query: TTypePromiseNull = null;\n\n static removeTrailingSlash = true;\n static addTimestamp: boolean | string = false;\n static withCredentials = false;\n static lean: boolean | null = null;\n static returnAs: ResourceActionReturnType = ResourceActionReturnType.Observable;\n static responseBodyType: ResourceResponseBodyType = ResourceResponseBodyType.Json;\n\n\n static queryMappingMethod: ResourceQueryMappingMethod = ResourceQueryMappingMethod.Plain;\n\n}\n","import {\n IResourceAction,\n IResourceActionAttributes,\n IResourceActionInner,\n IResourceParamsBase,\n IResourceRequest,\n ResourceQueryMappingMethod,\n ResourceRequestBodyType\n} from './Declarations';\n\nexport class ResourceHelper {\n\n static cleanDataFields: string[] = [\n '$resolved',\n '$promise',\n '$abort',\n '$resource'\n ];\n\n\n private static isBrowser: boolean | null = null;\n\n static isRunningInBrowser(): boolean {\n\n if (this.isBrowser !== null) {\n return this.isBrowser;\n }\n\n try {\n this.isBrowser = !!window;\n } catch (e) {\n this.isBrowser = false;\n }\n\n return this.isBrowser;\n }\n\n static getRealTypeOf(data: any): ResourceRequestBodyType {\n if (!data) {\n return ResourceRequestBodyType.NONE;\n }\n\n if (this.isRunningInBrowser()) {\n if (FormData && data instanceof FormData) {\n return ResourceRequestBodyType.FORM_DATA;\n }\n\n if (Blob && data instanceof Blob) {\n return ResourceRequestBodyType.BLOB;\n }\n }\n\n if (data instanceof ArrayBuffer) {\n return ResourceRequestBodyType.ARRAY_BUFFER;\n }\n\n if (['string', 'number'].indexOf(typeof data) > -1) {\n return ResourceRequestBodyType.TEXT;\n }\n\n return ResourceRequestBodyType.JSON;\n }\n\n static defaults(dst: any, src: any): any {\n\n if (!dst) {\n dst = {};\n }\n\n Object.keys(src)\n .forEach((key: string) => {\n if (dst[key] === undefined) {\n dst[key] = src[key];\n }\n });\n\n return dst;\n\n }\n\n static isNullOrUndefined(value: any): boolean {\n return value === null || value === undefined;\n }\n\n static cleanData(obj: any): any {\n\n if (Array.isArray(obj)) {\n return this.cleanDataArray(obj);\n } else {\n return this.cleanDataObject(obj);\n }\n\n }\n\n static cleanDataArray(obj: any[]): any[] {\n\n obj = obj.filter(value => typeof value !== 'function');\n\n return obj;\n\n }\n\n static cleanDataObject(obj: any): any {\n const cleanedObj: any = {};\n\n for (const propName in obj) {\n\n if (typeof obj[propName] !== 'function' && this.cleanDataFields.indexOf(propName) === -1) {\n cleanedObj[propName] = obj[propName];\n }\n\n }\n\n return cleanedObj;\n }\n\n static defineReturnDataPropertiesResolvedAbort(returnData: any) {\n Object.defineProperty(returnData, '$resolved', {\n enumerable: false,\n configurable: true,\n writable: true,\n value: false\n });\n\n Object.defineProperty(returnData, '$abort', {\n enumerable: false,\n configurable: true,\n writable: true,\n value: () => {\n // does nothing for now\n }\n });\n }\n\n static defineReturnDataPropertiesPromise(returnData: any, value: any) {\n Object.defineProperty(returnData, '$promise', {\n enumerable: false,\n configurable: true,\n writable: true,\n value\n });\n }\n\n static getRequestOptionsOrThrow(options: IResourceActionInner): IResourceRequest {\n // tslint:disable-next-line: prefer-immediate-return\n const value = this.getResourceActionInnerOrThrow(options, 'requestOptions');\n\n return value;\n }\n\n // tslint:disable-next-line: no-identical-functions\n static getResolvedOptionsOrThrow(options: IResourceActionInner): IResourceParamsBase {\n // tslint:disable-next-line: prefer-immediate-return\n const value = this.getResourceActionInnerOrThrow(options, 'resolvedOptions');\n\n return value;\n }\n\n // tslint:disable-next-line: no-identical-functions\n static getActionAttributesOrThrow(options: IResourceActionInner): IResourceActionAttributes {\n // tslint:disable-next-line: prefer-immediate-return\n const value = this.getResourceActionInnerOrThrow(options, 'actionAttributes');\n\n return value;\n }\n\n // tslint:disable-next-line: no-identical-functions\n static getActionOptionsOrThrow(options: IResourceActionInner): IResourceAction {\n // tslint:disable-next-line: prefer-immediate-return\n const value = this.getResourceActionInnerOrThrow(options, 'actionOptions');\n\n return value;\n }\n\n static setRequestOptionsUrlParams(requestOptions: IResourceRequest,\n resolvedOptions: IResourceParamsBase,\n actionAttributes: IResourceActionAttributes,\n usedInPath: { [key: string]: boolean }) {\n\n if (!requestOptions.url) {\n throw new Error('setRequestOptionsUrlParams options.requestOptions.url missing');\n }\n\n const params = this.defaults(actionAttributes.params, resolvedOptions.params);\n const pathParams = requestOptions.url.match(/{([^}]*)}/g) || [];\n\n for (const pathParam of pathParams) {\n\n let pathKey = pathParam.substr(1, pathParam.length - 2);\n const isMandatory = pathKey[0] === '!';\n if (isMandatory) {\n pathKey = pathKey.substr(1);\n }\n\n const onlyPathParam = pathKey[0] === ':';\n if (onlyPathParam) {\n pathKey = pathKey.substr(1);\n }\n\n if (actionAttributes.query && actionAttributes.query === actionAttributes.params) {\n usedInPath[pathKey] = true;\n }\n\n const value = params[pathKey];\n\n if (onlyPathParam) {\n delete params[pathKey];\n }\n\n // Replacing in the url\n requestOptions.url = this.setRequestOptionsUrlParamsNewUrl(value, isMandatory, pathParam, requestOptions);\n\n }\n }\n\n static setRequestOptionsUrlParamsNewUrl(value: any,\n isMandatory: boolean,\n pathParam: string,\n requestOptions: IResourceRequest): string {\n\n if (!requestOptions.url) {\n throw new Error('setRequestOptionsUrlParamsNewUrl requestOptions.url missing');\n }\n\n if (this.isNullOrUndefined(value)) {\n if (isMandatory) {\n const consoleMsg = `Mandatory ${pathParam} path parameter is missing`;\n console.warn(consoleMsg);\n\n throw new Error(consoleMsg);\n }\n\n return requestOptions.url.substr(0, requestOptions.url.indexOf(pathParam));\n\n }\n\n return requestOptions.url.replace(pathParam, value);\n }\n\n static createRequestOptionsFormDataBody(body: any, actionOptions: IResourceAction): FormData {\n\n const newBody = new FormData();\n\n Object.keys(body).forEach((key: string) => {\n\n const value = body[key];\n\n if (body.hasOwnProperty(key) && typeof value !== 'function') {\n\n const isArrayOfFiles = value instanceof Array && value.reduce((acc, elem) => acc && elem instanceof File, true);\n\n if (isArrayOfFiles) {\n value.forEach((f: File, index: number) => {\n newBody.append(`${key}[${index}]`, f, f.name);\n });\n } else if (value instanceof File) {\n newBody.append(key, value, value.name);\n } else if (!actionOptions.rootNode) {\n newBody.append(key, value);\n }\n }\n\n });\n\n if (actionOptions.rootNode) {\n newBody.append(actionOptions.rootNode, JSON.stringify(body));\n }\n\n return newBody;\n\n }\n\n static appendQueryParams(query: { [prop: string]: string | any[] },\n key: string,\n value: any,\n queryMappingMethod?: ResourceQueryMappingMethod): void {\n\n if (value instanceof Date) {\n query[key] = value.toISOString();\n\n return;\n }\n\n if (typeof value === 'object') {\n\n switch (queryMappingMethod) {\n\n case ResourceQueryMappingMethod.Plain:\n this.appendQueryParamsMappingMethodPlain(query, key, value);\n\n return;\n\n case ResourceQueryMappingMethod.Bracket:\n /// Convert object and arrays to query params\n this.appendQueryParamsMappingMethodBracket(query, key, value, queryMappingMethod);\n\n return;\n\n case ResourceQueryMappingMethod.JQueryParamsBracket:\n /// Convert object and arrays to query params according to $.params\n this.appendQueryParamsMappingMethodJQueryParamsBracket(query, key, value, queryMappingMethod);\n\n return;\n\n }\n\n }\n\n query[key] = value;\n\n }\n\n static appendQueryParamsMappingMethodPlain(query: { [prop: string]: any }, key: string, value: any) {\n\n if (Array.isArray(value)) {\n query[key] = value.join(',');\n } else {\n\n if (value && typeof value === 'object') {\n /// Convert dates to ISO format string\n if (value instanceof Date) {\n value = value.toISOString();\n } else {\n value = JSON.stringify(value);\n }\n }\n\n query[key] = value;\n }\n }\n\n static appendQueryParamsMappingMethodBracket(query: { [prop: string]: any },\n key: string,\n value: any,\n queryMappingMethod: ResourceQueryMappingMethod) {\n\n for (const k in value) {\n if (value.hasOwnProperty(k)) {\n this.appendQueryParams(query, `${key}[${k}]`, value[k], queryMappingMethod);\n }\n }\n\n }\n\n static appendQueryParamsMappingMethodJQueryParamsBracket(query: { [prop: string]: any },\n key: string,\n value: any,\n queryMappingMethod: ResourceQueryMappingMethod) {\n\n for (const k in value) {\n if (value.hasOwnProperty(k)) {\n let path = `${key}[${k}]`;\n\n if (Array.isArray(value) && typeof value[k] !== 'object') {\n path = `${key}[]`;\n }\n this.appendQueryParams(query, path, value[k], queryMappingMethod);\n }\n }\n\n }\n\n /**\n * Creates new abort method from subscription\n */\n static createNewAbortMethod(options: IResourceActionInner) {\n if (options.returnData && options.subscription) {\n\n const abort = options.returnData.abort;\n\n options.returnData.abort = () => {\n\n if (abort) {\n abort();\n }\n\n if (options.subscription) {\n options.subscription.unsubscribe();\n options.subscription = null;\n }\n\n };\n }\n }\n\n\n private static getResourceActionInnerOrThrow(options: IResourceActionInner, param: string): any {\n if (options[param]) {\n return options[param];\n }\n\n throw new Error('getResourceActionInnerOrThrow options.' + param + ' missing');\n }\n\n}\n","import { IResourceHandlerResponse, IResourceRequest } from './Declarations';\n\nexport abstract class ResourceHandler {\n abstract handle(req: IResourceRequest): IResourceHandlerResponse;\n}\n","import { IResourceHandlerResponse, IResourceRequest } from './Declarations';\nimport { ResourceHandler } from './ResourceHandler';\n\nexport class ResourceHandlerNoop extends ResourceHandler {\n handle(req: IResourceRequest): IResourceHandlerResponse {\n throw new Error('ResourceHandler is not provided');\n }\n}\n","import { Injector, ModuleWithProviders, NgModule } from '@angular/core';\nimport { ResourceHandlerNoop } from './ResourceHandlerNoop';\nimport { ResourceHandler } from './ResourceHandler';\nimport { IResourceModuleConfig } from './Declarations';\n\n@NgModule()\nexport class ResourceModule {\n\n static injector: Injector | null = null;\n\n /**\n * For root\n */\n static forRoot(config: IResourceModuleConfig = {}): ModuleWithProviders<ResourceModule> {\n return {\n ngModule: ResourceModule,\n providers: [\n config.handler || {provide: ResourceHandler, useClass: ResourceHandlerNoop}\n ]\n };\n }\n\n /**\n * For child\n */\n // tslint:disable-next-line: no-identical-functions\n static forChild(config: IResourceModuleConfig = {}): ModuleWithProviders<ResourceModule> {\n return {\n ngModule: ResourceModule,\n providers: [\n config.handler || {provide: ResourceHandler, useClass: ResourceHandlerNoop}\n ]\n };\n }\n\n constructor(injector: Injector) {\n ResourceModule.injector = injector;\n }\n\n}\n","import { Observable, of } from 'rxjs';\nimport { catchError, map, switchMap } from 'rxjs/operators';\n\nimport {\n IResourceAction,\n IResourceActionInner,\n IResourceResponse,\n ResourceActionReturnType,\n ResourceQueryMappingMethod,\n ResourceRequestBodyType,\n ResourceRequestMethod\n} from './Declarations';\nimport { ResourceGlobalConfig } from './ResourceGlobalConfig';\nimport { ResourceHelper } from './ResourceHelper';\nimport { ResourceHandler } from './ResourceHandler';\nimport { ResourceModule } from './ResourceModule';\nimport { Optional, Type } from '@angular/core';\n\nexport class Resource {\n\n protected get requestHandler(): ResourceHandler {\n\n if (!this._requestHandler) {\n\n if (!ResourceModule.injector) {\n throw new Error('ResourceModule.injector is missing');\n }\n\n this._requestHandler = ResourceModule.injector.get(ResourceHandler as Type<ResourceHandler>);\n\n if (!this._requestHandler) {\n throw new Error('ResourceHandler provider is missing');\n }\n\n }\n\n return this._requestHandler;\n\n }\n\n private $url: string | null = null;\n private $pathPrefix: string | null = null;\n private $path: string | null = null;\n private $headers: {} | null = null;\n private $body: {} | null = null;\n private $params: {} | null = null;\n private $query: {} | null = null;\n\n // tslint:disable-next-line:variable-name\n private _requestHandler: ResourceHandler | null = null;\n\n constructor(@Optional() requestHandler?: ResourceHandler) {\n\n if (requestHandler) {\n this._requestHandler = requestHandler;\n }\n\n (this.constructor as any).instance = this;\n\n }\n\n /**\n * Used to get url\n */\n $getUrl(actionOptions: IResourceAction = {}): string | Promise<string> {\n return this.$url || actionOptions.url || ResourceGlobalConfig.url || '';\n }\n\n $setUrl(url: string) {\n this.$url = url;\n }\n\n /**\n * Used to get path prefix\n */\n $getPathPrefix(actionOptions: IResourceAction = {}): string | Promise<string> {\n return this.$pathPrefix || actionOptions.pathPrefix || ResourceGlobalConfig.pathPrefix || '';\n }\n\n $setPathPrefix(path: string) {\n this.$pathPrefix = path;\n }\n\n /**\n * Used to get path\n */\n $getPath(actionOptions: IResourceAction = {}): string | Promise<string> {\n return this.$path || actionOptions.path || ResourceGlobalConfig.path || '';\n }\n\n $setPath(path: string) {\n this.$path = path;\n }\n\n /**\n * Get headers.\n */\n $getHeaders(actionOptions: IResourceAction = {}): any | Promise<any> {\n return this.$headers || actionOptions.headers || ResourceGlobalConfig.headers || {};\n }\n\n $setHeaders(headers: any) {\n this.$headers = headers;\n }\n\n /**\n * Get body\n */\n $getBody(actionOptions: IResourceAction = {}): any | Promise<any> {\n return this.$body || actionOptions.body || ResourceGlobalConfig.body || {};\n }\n\n $setBody(body: any) {\n this.$body = body;\n }\n\n /**\n * Get path params\n */\n $getParams(actionOptions: IResourceAction = {}): any | Promise<any> {\n return this.$params || actionOptions.params || ResourceGlobalConfig.params || {};\n }\n\n $setParams(params: any) {\n this.$params = params;\n }\n\n /**\n * Get query params\n */\n $getQuery(actionOptions: IResourceAction = {}): any | Promise<any> {\n return this.$query || actionOptions.query || ResourceGlobalConfig.query || {};\n }\n\n $setQuery(query: any) {\n this.$query = query;\n }\n\n /**\n * Used to filter received data.\n * Is applied on each element of array or object\n */\n $filter(data: any, options: IResourceActionInner = {}): boolean {\n return true;\n }\n\n /**\n * Used to map received data\n * Is applied on each element of array or object\n */\n $map(data: any, options: IResourceActionInner = {}): any {\n return data;\n }\n\n /**\n * Used to create result object\n * Is applied on each element of array or object\n */\n $resultFactory(data: any, options: IResourceActionInner = {}): any {\n return data == null ? {} : data;\n }\n\n $restAction(options: IResourceActionInner) {\n\n this.$_setResourceActionInnerDefaults(options);\n this.$_setResourceActionOptionDefaults(options);\n\n if (!options.actionOptions) {\n throw new Error('Action options are not set');\n }\n\n const actionOptions = options.actionOptions;\n\n if (!actionOptions.resultFactory) {\n throw new Error('Action options resultFactory is not set');\n }\n\n if (!options.actionAttributes) {\n throw new Error('Action attributes is not set');\n }\n\n\n if (actionOptions.mutateBody || options.isModel) {\n options.returnData = options.actionAttributes.body;\n }\n\n if (actionOptions.returnAs === ResourceActionReturnType.Resource) {\n options.returnData = actionOptions.expectJsonArray ? [] : actionOptions.resultFactory.call(this, null, options);\n }\n\n if (this.$_canSetInternalData(options)) {\n ResourceHelper.defineReturnDataPropertiesResolvedAbort(options.returnData);\n }\n\n options.mainObservable = this.$_createMainObservable(options);\n\n if (this.$_canSetInternalData(options)) {\n ResourceHelper.defineReturnDataPropertiesPromise(options.returnData, this.$_createPromise(options));\n }\n\n switch (actionOptions.returnAs) {\n case ResourceActionReturnType.Observable:\n return options.mainObservable;\n\n case ResourceActionReturnType.Promise:\n return this.$_createPromise(options);\n\n default:\n return options.returnData;\n\n }\n\n }\n\n /**\n * Converts observable to promise and ads abort method\n */\n protected $_createPromise(options: IResourceActionInner): Promise<any> {\n\n if (!options.promise) {\n options.promise = new Promise<any>((resolve, reject) => {\n\n if (!options.mainObservable) {\n reject(new Error('$_createPromise options.mainObservable missing'));\n\n return;\n }\n\n options.subscription = options.mainObservable.subscribe(\n resolve,\n error => {\n reject(error);\n options.subscription = null;\n },\n () => {\n options.subscription = null;\n }\n );\n\n ResourceHelper.createNewAbortMethod(options);\n\n });\n }\n\n return options.promise;\n\n }\n\n\n /**\n * Creates main request observable\n */\n protected $_createMainObservable(options: IResourceActionInner): Observable<any> {\n\n const requestPreparationPromise = this.$_setResolvedOptions(options)\n .then((o: IResourceActionInner) => this.$_createRequestOptions(o));\n\n return of(requestPreparationPromise)\n .pipe(\n switchMap((oPromise: Promise<IResourceActionInner>) => {\n return oPromise\n .then((o: IResourceActionInner) => {\n\n if (!o.requestOptions) {\n throw new Error('IResourceActionInner miss request options');\n }\n\n const handlerResp = this.requestHandler.handle(o.requestOptions);\n\n if (o.returnData && this.$_canSetInternalData(options)) {\n o.returnData.$abort = handlerResp.abort;\n }\n\n if (handlerResp.observable) {\n return handlerResp.observable as any;\n }\n\n return handlerResp.promise;\n\n });\n }),\n switchMap(s => s instanceof Observable ? s : of(s)),\n map((resp: IResourceResponse) => this.$handleSuccessResponse(options, resp)),\n catchError((resp: IResourceResponse) => {\n throw this.$handleErrorResponse(options, resp);\n })\n );\n }\n\n /**\n * Success response handler\n */\n protected $handleSuccessResponse(options: IResourceActionInner, resp: IResourceResponse): any {\n\n let body = resp.body;\n\n if (Array.isArray(body)) {\n body = this.$prepareSuccessResponseBodyArray(body, options);\n } else {\n body = this.$prepareSuccessResponseBodyObject(body, options);\n }\n\n if (this.$_canSetInternalData(options)) {\n options.returnData.$resolved = true;\n }\n\n if (options.actionOptions && options.actionOptions.asResourceResponse) {\n resp.body = body;\n body = resp;\n }\n\n if (options.actionAttributes && options.actionAttributes.onSuccess) {\n options.actionAttributes.onSuccess(body);\n }\n\n return body;\n }\n\n /**\n * Prepare success response body as array\n */\n protected $prepareSuccessResponseBodyArray(body: any[], options: IResourceActionInner): any[] {\n\n if (!options.actionOptions) {\n throw new Error('$prepareSuccessResponseBodyArray options.actionOptions missing');\n }\n\n const actionOptions = options.actionOptions;\n\n body = body\n .filter((item: any) => {\n return actionOptions.filter ? actionOptions.filter.call(this, item, options) : true;\n })\n .map((item: any) => {\n\n if (actionOptions.map) {\n item = actionOptions.map.call(this, item, options);\n }\n\n return actionOptions.resultFactory ? actionOptions.resultFactory.call(this, item, options) : item;\n });\n\n if (options.returnData) {\n Array.prototype.push.apply(options.returnData, body);\n body = options.returnData;\n }\n\n return body;\n\n }\n\n /**\n * Prepare success response body as object\n */\n protected $prepareSuccessResponseBodyObject(body: any, options: IResourceActionInner): any {\n\n if (!options.actionOptions) {\n throw new Error('$prepareSuccessResponseBodyObject options.actionOptions missing');\n }\n\n const actionOptions = options.actionOptions;\n\n if (actionOptions.filter && !actionOptions.filter.call(this, body, options)) {\n return null;\n }\n\n if (actionOptions.map) {\n body = actionOptions.map.call(this, body, options);\n }\n\n let newBody = options.returnData;\n\n if (newBody) {\n if (typeof newBody.$setData === 'function') {\n newBody.$setData(body);\n } else {\n Object.assign(newBody, body);\n }\n } else {\n newBody = actionOptions.resultFactory ? actionOptions.resultFactory.call(this, body, options) : body;\n }\n\n body = newBody;\n\n // If it's model\n if (body.$resource) {\n body.$resolved = true;\n body.$promise = options.mainObservable;\n body.$abort = () => true;\n }\n\n return body;\n\n }\n\n /**\n * Handle error\n */\n protected $handleErrorResponse(options: IResourceActionInner, resp: IResourceResponse): any {\n\n if (options.returnData && this.$_canSetInternalData(options)) {\n options.returnData.$resolved = true;\n }\n\n if (options.actionAttributes && options.actionAttributes.onError) {\n options.actionAttributes.onError(resp);\n }\n\n throw resp;\n }\n\n /**\n * Sets request options url\n */\n protected $setRequestOptionsUrl(options: IResourceActionInner): void {\n\n const requestOptions = ResourceHelper.getRequestOptionsOrThrow(options);\n const resolvedOptions = ResourceHelper.getResolvedOptionsOrThrow(options);\n const actionAttributes = ResourceHelper.getActionAttributesOrThrow(options);\n\n if (!requestOptions.url) {\n requestOptions.url =\n (resolvedOptions.url || '') +\n (resolvedOptions.pathPrefix || '') +\n (resolvedOptions.path || '');\n }\n\n\n options.usedInPath = {};\n\n ResourceHelper.setRequestOptionsUrlParams(\n requestOptions,\n resolvedOptions,\n actionAttributes,\n options.usedInPath\n );\n\n // Removing double slashed from final url\n requestOptions.url = requestOptions.url.replace(/\\/\\/+/g, '/');\n if (requestOptions.url.startsWith('http')) {\n requestOptions.url = requestOptions.url.replace(':/', '://');\n }\n\n // Remove trailing slash\n if (options.actionOptions && options.actionOptions.removeTrailingSlash) {\n while (requestOptions.url[requestOptions.url.length - 1] === '/') {\n requestOptions.url = requestOptions.url.substr(0, requestOptions.url.length - 1);\n }\n }\n\n }\n\n protected $setRequestOptionsBody(options: IResourceActionInner): void {\n\n const actionOptions = ResourceHelper.getActionOptionsOrThrow(options);\n const actionAttributes = ResourceHelper.getActionAttributesOrThrow(options);\n const requestOptions = ResourceHelper.getRequestOptionsOrThrow(options);\n\n let body = actionAttributes.body;\n\n if (!body) {\n return;\n }\n\n const realBodyType = ResourceHelper.getRealTypeOf(body);\n\n let bodyOk: boolean = realBodyType === actionOptions.requestBodyType;\n\n if (\n !bodyOk &&\n realBodyType === ResourceRequestBodyType.JSON &&\n actionOptions.requestBodyType === ResourceRequestBodyType.FORM_DATA) {\n\n body = ResourceHelper.createRequestOptionsFormDataBody(body, actionOptions);\n bodyOk = true;\n\n }\n\n if (!bodyOk) {\n throw new Error('Can not convert body');\n }\n\n if (!(body instanceof FormData)) {\n // Add root node if needed\n if (actionOptions.rootNode) {\n const newBody: any = {};\n newBody[actionOptions.rootNode] = body;\n body = newBody;\n }\n\n\n if ((actionOptions.requestBodyType === ResourceRequestBodyType.NONE ||\n (actionOptions.requestBodyType === ResourceRequestBodyType.JSON &&\n typeof body === 'object' && Object.keys(body).length === 0)\n ) && !actionOptions.keepEmptyBody) {\n return;\n }\n\n }\n\n requestOptions.body = body;\n\n }\n\n protected $setRequestOptionsQuery(options: IResourceActionInner): void {\n\n const actionAttributes = ResourceHelper.getActionAttributesOrThrow(options);\n const resolvedOptions = ResourceHelper.getResolvedOptionsOrThrow(options);\n const requestOptions = ResourceHelper.getRequestOptionsOrThrow(options);\n const actionOptions = ResourceHelper.getActionOptionsOrThrow(options);\n\n options.usedInPath = options.usedInPath || {};\n\n let oq = actionAttributes.query || {};\n if (resolvedOptions.query) {\n oq = {...resolvedOptions.query, ...oq};\n }\n\n if (oq) {\n requestOptions.query = {};\n Object.keys(oq).forEach((key: string) => {\n // tslint:disable-next-line: no-non-null-assertion\n if (oq.hasOwnProperty(key) && !options.usedInPath![key]) {\n this.$appendQueryParams(requestOptions.query as any, key, oq[key], options.queryMappingMethod);\n }\n });\n }\n\n if (actionOptions.addTimestamp) {\n\n requestOptions.query = requestOptions.query || {};\n\n this.$appendQueryParams(\n requestOptions.query,\n actionOptions.addTimestamp as string,\n Date.now().toString(10),\n options.queryMappingMethod);\n }\n\n }\n\n protected $appendQueryParams(query: { [prop: string]: string | any[] },\n key: string,\n value: any,\n queryMappingMethod?: ResourceQueryMappingMethod): void {\n\n ResourceHelper.appendQueryParams(query, key, value, queryMappingMethod);\n\n }\n\n protected $_setResourceActionInnerDefaults(options: IResourceActionInner) {\n\n const actionOptions = ResourceHelper.getActionOptionsOrThrow(options);\n const actionAttributes = ResourceHelper.getActionAttributesOrThrow(options);\n\n // Setting default request method\n if (!actionOptions.method) {\n actionOptions.method = ResourceRequestMethod.Get;\n }\n\n\n if (actionAttributes.body) {\n\n // Setting default request content type\n if (!actionOptions.requestBodyType) {\n actionOptions.requestBodyType = ResourceHelper.getRealTypeOf(actionAttributes.body);\n }\n\n\n // Setting params and query if needed\n if (actionOptions.requestBodyType === ResourceRequestBodyType.JSON &&\n typeof actionAttributes.body === 'object' && !Array.isArray(actionAttributes.body)) {\n\n if (!actionAttributes.params) {\n actionAttributes.params = actionAttributes.body;\n }\n\n options.isModel = !!actionAttributes.body.$resource;\n\n }\n\n }\n\n actionAttributes.params = actionAttributes.params || {};\n\n if (!actionAttributes.query && actionOptions.method === ResourceRequestMethod.Get) {\n actionAttributes.query = actionAttributes.params;\n }\n\n options.queryMappingMethod = actionOptions.queryMappingMethod || ResourceGlobalConfig.queryMappingMethod;\n\n }\n\n // tslint:disable-next-line: cognitive-complexity\n protected $_setResourceActionOptionDefaults(options: IResourceActionInner) {\n\n const actionOptions = ResourceHelper.getActionOptionsOrThrow(options);\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.filter)) {\n actionOptions.filter = this.$filter;\n }\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.map)) {\n actionOptions.map = this.$map;\n }\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.resultFactory)) {\n actionOptions.resultFactory = this.$resultFactory;\n }\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.removeTrailingSlash)) {\n actionOptions.removeTrailingSlash = ResourceGlobalConfig.removeTrailingSlash;\n }\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.withCredentials)) {\n actionOptions.withCredentials = ResourceGlobalConfig.withCredentials;\n }\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.returnAs)) {\n actionOptions.returnAs = ResourceGlobalConfig.returnAs;\n }\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.responseBodyType)) {\n actionOptions.responseBodyType = ResourceGlobalConfig.responseBodyType;\n }\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.lean)) {\n actionOptions.lean = !!ResourceGlobalConfig.lean;\n\n if (actionOptions.mutateBody\n && actionOptions.returnAs === ResourceActionReturnType.Resource\n && ResourceHelper.isNullOrUndefined(actionOptions.lean)) {\n\n actionOptions.lean = true;\n\n }\n }\n\n if (ResourceHelper.isNullOrUndefined(actionOptions.addTimestamp)) {\n actionOptions.addTimestamp = ResourceGlobalConfig.addTimestamp;\n\n if (actionOptions.addTimestamp && typeof actionOptions.addTimestamp !== 'string') {\n actionOptions.addTimestamp = 'ts';\n }\n }\n }\n\n protected $_setResolvedOptions(options: IResourceActionInner): Promise<IResourceActionInner> {\n return Promise.all([\n this.$getUrl(options.actionOptions),\n this.$getPathPrefix(options.actionOptions),\n this.$getPath(options.actionOptions),\n this.$getHeaders(options.actionOptions),\n this.$getBody(options.actionOptions),\n this.$getParams(options.actionOptions),\n this.$getQuery(options.actionOptions)\n ])\n .then(([url, pathPrefix, path, headers, body, params, query]: any[]) => {\n\n options.resolvedOptions = {\n url,\n pathPrefix,\n path,\n headers,\n body,\n params,\n query\n };\n\n return options;\n });\n }\n\n protected $_createRequestOptions(options: IResourceActionInner): IResourceActionInner | Promise<IResourceActionInner> {\n\n const actionOptions = ResourceHelper.getActionOptionsOrThrow(options);\n const resolvedOptions = ResourceHelper.getResolvedOptionsOrThrow(options);\n\n options.requestOptions = {};\n\n // Step 1 set main\n options.requestOptions.method = actionOptions.method;\n options.requestOptions.headers = resolvedOptions.headers;\n options.requestOptions.withCredentials = actionOptions.withCredentials;\n options.requestOptions.responseBodyType = actionOptions.responseBodyType;\n options.requestOptions.requestBodyType = actionOptions.requestBodyType;\n\n // Step 2 create url\n this.$setRequestOptionsUrl(options);\n\n // Step 3 create body\n this.$setRequestOptionsBody(options);\n\n // Step 4 set query params\n this.$setRequestOptionsQuery(options);\n\n return options;\n }\n\n protected $_canSetInternalData(options: IResourceActionInner): boolean {\n const actionOptions = ResourceHelper.getActionOptionsOrThrow(options);\n\n return !!(options.returnData && (!actionOptions.lean || options.isModel));\n }\n\n}\n","import { Resource } from './Resource';\nimport { IResourceAction, ResourceRequestMethod } from './Declarations';\n\n\nexport function ResourceAction(methodOptions?: IResourceAction) {\n\n methodOptions = methodOptions || {};\n\n if (methodOptions.method === undefined) {\n methodOptions.method = ResourceRequestMethod.Get;\n }\n\n // tslint:disable-next-line: only-arrow-functions\n return function(target: Resource, propertyKey: string) {\n\n (target as any)[propertyKey] = function(...args: any[]): any {\n\n const callbacks: any = args.filter((arg: any) => typeof arg === 'function');\n const data: any = args.filter((arg: any) => typeof arg !== 'function');\n\n const [body, query, params] = data;\n const [onSuccess, onError] = callbacks;\n\n const actionOptions: IResourceAction = {...this.getResourceOptions(), ...methodOptions};\n\n return this.$restAction({actionAttributes: {body, query, params, onSuccess, onError}, actionOptions});\n\n };\n\n };\n\n}\n","import { ResourceHelper } from './ResourceHelper';\nimport { ResourceCRUDPromise } from './ResourceCommon/ResourceCRUDPromise';\n\nexport abstract class ResourceModel {\n\n static resourceInstance: ResourceCRUDPromise<any, any, any> | null = null;\n\n protected static methodQuery = 'query';\n protected static methodGet = 'get';\n protected static methodCreate = 'create';\n protected static methodUpdate = 'update';\n protected static methodRemove = 'remove';\n\n\n abstract readonly $resource: any;\n\n $resolved = true;\n $promise: Promise<any> | null = null;\n $abort: () => void;\n\n $idField = 'id';\n\n static get(id: string | number): Promise<any> {\n // tslint:disable-next-line: prefer-immediate-return\n const p = this.getInstance()[this.methodGet]({id});\n\n return p;\n }\n\n static query(query?: any): Promise<any> {\n // tslint:disable-next-line: prefer-immediate-return\n const p = this.getInstance()[this.methodQuery](query);\n\n return p;\n }\n\n static remove(id: string | number): Promise<void> {\n // tslint:disable-next-line: prefer-immediate-return\n const p = this.getInstance()[this.methodRemove]({id});\n\n return p;\n }\n\n private static getInstance(): any {\n if (!this.resourceInstance) {\n\n const model: ResourceModel = (new (this as any)());\n\n if (!model.$resource) {\n throw new Error('Your resource is not defined');\n }\n\n if (!model.$resource.instance) {\n throw new Error('Your resource is not created (inject it somewhere)');\n }\n\n this.resourceInstance = (new (this as any)()).$resource.instance;\n }\n\n return this.resourceInstance;\n }\n\n\n public $setData(data: any) {\n Object.assign(this, data);\n\n return this;\n }\n\n public $save(query?: any, params?: any) {\n\n if (this.isNew()) {\n return this.$create(query, params);\n } else {\n return this.$update(query, params);\n }\n\n }\n\n public $create(query?: any, params?: any) {\n return this.$executeResourceMethod((this.constructor as any).methodCreate, query, params);\n }\n\n public $update(query?: any, params?: any) {\n return this.$executeResourceMethod((this.constructor as any).methodUpdate, query, params);\n }\n\n public $remove(query?: any, params?: any) {\n return this.$executeResourceMethod((this.constructor as any).methodRemove, query, params);\n }\n\n public toJSON(): any {\n return ResourceHelper.cleanData(this);\n }\n\n protected isNew(): boolean {\n return !(this as any)[this.$idField];\n }\n\n protected $getResourceWithMethodCheck(methodName: string): any {\n\n if (!this.$resource) {\n console.error(`Your Resource is not defined`);\n\n return null;\n }\n\n const restInstance = this.$resource.instance;\n\n if (!restInstance) {\n console.error(`Your Resource is not defined or not created`);\n\n return null;\n }\n\n if (!restInstance[methodName]) {\n console.error(`Your Resource has no implemented ${methodName} method.`);\n\n return null;\n }\n\n return restInstance;\n\n }\n\n protected $executeResourceMethod(methodName: string, query?: any, params?: any) {\n\n const resource = this.$getResourceWithMethodCheck(methodName);\n\n if (resource) {\n resource[methodName](this, query, params);\n }\n\n return this;\n }\n\n\n}\n","import { IResourceParams } from './Declarations';\n\nexport function ResourceParams(params: IResourceParams = {}) {\n\n // tslint:disable-next-line: only-arrow-functions\n return function(target: any) {\n\n target.prototype.getResourceOptions = () => params;\n\n };\n}\n","import { Resource } from '../Resource';\nimport { IResourceAction, IResourceResponse, ResourceActionReturnType, ResourceRequestMethod } from '../Declarations';\n\n\nexport abstract class ResourceCRUDBase<TQuery, TShort, TFull, TQueryResult, TRetQuery, TRetFull, TRetAny> extends Resource {\n\n protected readonly abstract $crudReturnAs: ResourceActionReturnType;\n\n query(query?: TQuery,\n onSuccess?: (data: TQueryResult) => any,\n onError?: (err: IResourceResponse) => any): TRetQuery {\n\n return this.$restAction({\n actionAttributes: {\n body: query,\n onSuccess,\n onError\n },\n actionOptions: this.$_crudBaseGetActionOptions()\n });\n\n }\n\n get(data: { id: any },\n onSuccess?: (data: TFull) => any,\n onError?: (err: IResourceResponse) => any): TRetFull {\n\n return this.$restAction({\n actionAttributes: {\n body: data,\n onSuccess,\n onError\n },\n actionOptions: this.$_crudBaseGetActionOptions({\n path: '/{!id}'\n })\n });\n\n }\n\n save(data: TFull,\n onSuccess?: (data: TFull) => any,\n onError?: (err: IResourceResponse) => any): TRetFull {\n\n return this.$restAction({\n actionAttributes: {\n body: data,\n onSuccess,\n onError\n },\n actionOptions: this.$_crudBaseGetActionOptions({\n method: ResourceRequestMethod.Post,\n })\n });\n\n }\n\n update(data: TFull,\n onSuccess?: (data: TFull) => any,\n onError?: (err: IResourceResponse) => any): TRetFull {\n\n return this.$restAction({\n actionAttributes: {\n body: data,\n onSuccess,\n onError\n },\n actionOptions: this.$_crudBaseGetActionOptions({\n method: ResourceRequestMethod.Put,\n path: '/{!id}'\n })\n });\n\n }\n\n remove(data: { id: any },\n onSuccess?: (data: any) => any,\n onError?: (err: IResourceResponse) => any): TRetAny {\n\n return this.$restAction({\n actionAttributes: {\n body: data,\n onSuccess,\n onError\n },\n actionOptions: this.$_crudBaseGetActionOptions({\n method: ResourceRequestMethod.Delete,\n path: '/{!id}'\n })\n });\n\n }\n\n patch(data: { id: any } & Partial<TFull>,\n onSuccess?: (data: TFull) => any,\n onError?: (err: IResourceResponse) => any): TRetFull {\n\n return this.$restAction({\n actionAttributes: {\n body: data,\n onSuccess,\n onError\n },\n actionOptions: this.$_crudBaseGetActionOptions({\n method: ResourceRequestMethod.Patch,\n path: '/{!id}'\n })\n });\n\n }\n\n // Alias to save\n create(data: TFull, callback?: (res: TFull) => any): TRetFull {\n return this.save(data, callback);\n }\n\n\n private $_crudBaseGetActionOptions(actionOptions: IResourceAction = {}): IResourceAction {\n return {\n ...(this as any).getResourceOptions(),\n method: ResourceRequestMethod.Get,\n returnAs: this.$crudReturnAs,\n ...actionOptions\n };\n }\n\n}\n","import { ResourceActionReturnType } from '../Declarations';\nimport { ResourceCRUDBase } from './ResourceCRUDBase';\n\n\n/**\n * @deprecated use ResourceCRUDPromise or ResourceCRUDObservable instead\n */\nexport abstract class ResourceCRUD<TQuery, TShort, TFull, TQueryResult = TShort[]>\n extends ResourceCRUDBase<TQuery, TShort, TFull, TQueryResult,\n Promise<TQueryResult>, Promise<TFull>, Promise<any>> {\n\n protected readonly $crudReturnAs = ResourceActionReturnType.Promise;\n\n}\n","import { ResourceActionReturnType } from '../Declarations';\nimport { ResourceCRUDBase } from './ResourceCRUDBase';\n\n\nexport abstract class ResourceC