UNPKG

ngx-http-annotations

Version:

This is a library to angular to use http request via decorator/annotations

369 lines (362 loc) 17.3 kB
import * as i0 from '@angular/core'; import { InjectionToken, APP_INITIALIZER, NgModule } from '@angular/core'; import { delay } from 'rxjs/operators'; import { HttpClientModule, HttpClient } from '@angular/common/http'; import { CommonModule } from '@angular/common'; const HTTP_ANNOTATIONS_USE_MOCKS = new InjectionToken('HTTP_ANNOTATIONS_USE_MOCKS'); const HTTP_ANNOTATIONS_USE_DELAY = new InjectionToken('HTTP_ANNOTATIONS_USE_DELAY'); const RESOURCE_METADATA_ROOT = 'resources_metadata'; // @dynamic const NO_DELAY = 0; const MOCK_DEFAULT_DELAY = 500; function observe(annotations) { return (...args) => HttpRestUtils.decorate('observe', annotations, ...args); } function path(annotations) { return (...args) => { return HttpRestUtils.decorate('path', annotations, ...args); }; } function body(annotations) { return (...args) => HttpRestUtils.decorate('body', annotations, ...args); } function response(annotations) { return (...args) => HttpRestUtils.decorate('response', annotations, ...args); } function query(annotations) { return (...args) => HttpRestUtils.decorate('query', annotations, ...args); } function headers(annotations) { return (...args) => HttpRestUtils.decorate('headers', annotations, ...args); } function produces(annotations) { return (...args) => HttpRestUtils.decorate('produces', annotations, ...args); } var RequestMethodParams; (function (RequestMethodParams) { RequestMethodParams["get"] = "Get"; RequestMethodParams["post"] = "Post"; RequestMethodParams["put"] = "Put"; RequestMethodParams["delete"] = "Delete"; RequestMethodParams["options"] = "Options"; RequestMethodParams["head"] = "Head"; RequestMethodParams["patch"] = "Patch"; })(RequestMethodParams || (RequestMethodParams = {})); class HttpRestUtils { static decorate(decoratorName, annotations, ...args) { switch (args.length) { case 1: { const [target] = args; HttpRestUtils.constructMetadata(decoratorName, 'class', annotations, target.prototype); break; } case 2: { // eslint-disable-next-line @typescript-eslint/no-unused-vars const [target, __key] = args; HttpRestUtils.constructMetadata(decoratorName, 'props', annotations, target); break; } case 3: if (typeof args[2] === 'number') { const [target, keyName, index] = args; HttpRestUtils.constructMetadata(decoratorName, 'params', annotations, target, { keyName, index }); break; } else { // eslint-disable-next-line @typescript-eslint/no-unused-vars const [target, keyName, __descriptor] = args; HttpRestUtils.constructMetadata(decoratorName, 'methods', annotations, target, { keyName }); break; } default: throw new Error('Decorators are not valid here!'); } } /** * Set up metadata * @param entityType * @param value Value of metadata * @param target Prototype of current object * @param metaName Decorator name * @param entityData Entity extra data */ static constructMetadata(metaName, entityType, value, target, entityData) { target[RESOURCE_METADATA_ROOT] = target[RESOURCE_METADATA_ROOT] || {}; target[RESOURCE_METADATA_ROOT][entityType] = target[RESOURCE_METADATA_ROOT][entityType] || {}; const metadataObj = target[RESOURCE_METADATA_ROOT][entityType]; if (entityData && entityData.keyName) { metadataObj[entityData.keyName] = metadataObj[entityData.keyName] || {}; } if (entityData && entityData.index != null) { metadataObj[entityData.keyName][metaName] = metadataObj[entityData.keyName][metaName] || {}; } switch (entityType) { case 'class': metadataObj[metaName] = value; break; case 'props': metadataObj[metaName] = value; break; case 'methods': (entityData) ? metadataObj[entityData.keyName][metaName] = value : undefined; break; case 'params': (entityData) ? metadataObj[entityData.keyName][metaName][value || 'default'] = entityData.index : undefined; break; } target[RESOURCE_METADATA_ROOT][entityType] = metadataObj; } static requestMethod(requestMethodName) { // @dynamic return (target, key, descriptor) => { const originalFunction = descriptor.value; descriptor.value = function (...args) { const url = HttpRestUtils.collectUrl(target, key, args); // tslint:disable-next-line:no-shadowed-variable const body = HttpRestUtils.collectBodyContent(target, key, args); const search = HttpRestUtils.collectQueryParams(target, key, args); // tslint:disable-next-line:no-shadowed-variable const headers = HttpRestUtils.collectHttpHeaders(target, key, args); const producesType = HttpRestUtils.produce(target, key, args); // tslint:disable-next-line:no-shadowed-variable const observe = HttpRestUtils.getHttpClientObserve(target, key, args); const params = { body, params: search, headers, responseType: producesType, observe }; const newArgs = args; const responseIndex = HttpRestUtils.collectResponseIndex(target, key, args); const callConfig = { url, requestMethodName, params, args: newArgs, }; if (HttpRestUtils.ifUseMock(callConfig)) { // If "use mock" is true, call original function, to get mock directly from function return HttpRestUtils.processIfUseMock(responseIndex, args, newArgs, originalFunction); } const request = HttpRestUtils.getRequest(callConfig); if (responseIndex >= 0) { if (args.length > responseIndex) { newArgs[responseIndex] = request; } else { newArgs.splice(responseIndex, 0, request); } return originalFunction(...newArgs).pipe(HttpRestUtils.getDelay(callConfig)); } return request.pipe(HttpRestUtils.getDelay(callConfig)); }; }; } static getRequest(callConfig) { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { body: any, ...params } = callConfig.params; const requestBody = callConfig.params?.body ?? undefined; switch (callConfig.requestMethodName) { case RequestMethodParams.get: return HttpRestUtils.http.get(callConfig.url, callConfig.params); case RequestMethodParams.post: return HttpRestUtils.http.post(callConfig.url, requestBody, params); case RequestMethodParams.put: return HttpRestUtils.http.put(callConfig.url, requestBody, params); case RequestMethodParams.delete: return HttpRestUtils.http.delete(callConfig.url, callConfig.params); case RequestMethodParams.options: return HttpRestUtils.http.options(callConfig.url, callConfig.params); case RequestMethodParams.head: return HttpRestUtils.http.head(callConfig.url, callConfig.params); case RequestMethodParams.patch: return HttpRestUtils.http.patch(callConfig.url, requestBody, params); default: return HttpRestUtils.http.request(callConfig.requestMethodName, callConfig.url, callConfig.params); } } static ifUseMock(callConfig) { let useMock = HttpRestUtils.appInjector?.get(HTTP_ANNOTATIONS_USE_MOCKS, false); if (typeof useMock === 'function') { const useMockFunction = useMock; useMock = useMockFunction(callConfig.url, callConfig.requestMethodName, callConfig.params, callConfig.args); } return useMock; } static processIfUseMock(responseIndex, args, newArgs, originalFunction) { if (responseIndex >= 0) { if (args.length > responseIndex) { newArgs[responseIndex] = undefined; } else { newArgs.splice(responseIndex, 0, undefined); } } return originalFunction(...newArgs).pipe(this.getDelay(null, MOCK_DEFAULT_DELAY)); } static getDelay(callConfig, defaultDelay = NO_DELAY) { let useDelay = HttpRestUtils.appInjector.get(HTTP_ANNOTATIONS_USE_DELAY, defaultDelay); if (typeof useDelay === 'function' && callConfig) { const useGetDelayFunction = useDelay; useDelay = useGetDelayFunction(callConfig.url, callConfig.requestMethodName, callConfig.params, callConfig.args); } return delay(useDelay); } // eslint-disable-next-line @typescript-eslint/no-unused-vars static getHttpClientObserve(target, methodName, __args) { if (target[RESOURCE_METADATA_ROOT].methods && target[RESOURCE_METADATA_ROOT].methods[methodName]) { return target[RESOURCE_METADATA_ROOT].methods[methodName].observe; } return undefined; } // eslint-disable-next-line @typescript-eslint/no-unused-vars static produce(target, methodName, __args) { if (target[RESOURCE_METADATA_ROOT].methods && target[RESOURCE_METADATA_ROOT].methods[methodName]) { return target[RESOURCE_METADATA_ROOT].methods[methodName].produces; } return 'json'; } static collectUrl(target, methodName, args) { const baseUrl = target[RESOURCE_METADATA_ROOT] && target[RESOURCE_METADATA_ROOT].class ? target[RESOURCE_METADATA_ROOT].class.path : ''; const methodUrl = target[RESOURCE_METADATA_ROOT].methods && target[RESOURCE_METADATA_ROOT].methods[methodName] ? target[RESOURCE_METADATA_ROOT].methods[methodName].path : ''; const isRelativePath = `${baseUrl}${methodUrl}`[0] === '/'; const methodUrlWithParams = [baseUrl, methodUrl] .filter(pathToFilter => pathToFilter) .join('/') .split('/') .map(pathParams => { if (pathParams[0] === ':') { const paramName = pathParams.substring(1); const index = target[RESOURCE_METADATA_ROOT].params && target[RESOURCE_METADATA_ROOT].params[methodName] && target[RESOURCE_METADATA_ROOT].params[methodName].path ? target[RESOURCE_METADATA_ROOT].params[methodName].path[paramName] : ''; return args[index]; } return pathParams; }) .filter(pathToFilter => pathToFilter) .join('/'); if (!isRelativePath) { const [absolutePrefix, ...paths] = methodUrlWithParams.split('/'); return `${absolutePrefix}//${paths.join('/')}`; } return `/${methodUrlWithParams}`; } static collectBodyContent(target, methodName, args) { if (!target[RESOURCE_METADATA_ROOT].params || !target[RESOURCE_METADATA_ROOT].params[methodName] || !target[RESOURCE_METADATA_ROOT].params[methodName].body) { return undefined; } const index = target[RESOURCE_METADATA_ROOT].params[methodName].body.default; return args[index]; } // eslint-disable-next-line @typescript-eslint/no-unused-vars static collectResponseIndex(target, methodName, __args) { if (!target[RESOURCE_METADATA_ROOT].params || !target[RESOURCE_METADATA_ROOT].params[methodName] || !target[RESOURCE_METADATA_ROOT].params[methodName].response) { return undefined; } return target[RESOURCE_METADATA_ROOT].params[methodName].response.default; } static collectQueryParams(target, methodName, args) { if (!target[RESOURCE_METADATA_ROOT].params || !target[RESOURCE_METADATA_ROOT].params[methodName] || !target[RESOURCE_METADATA_ROOT].params[methodName].query) { return undefined; } const queryParams = {}; const queryParamsObjectIndex = target[RESOURCE_METADATA_ROOT].params[methodName].query.default; const queryMetadata = target[RESOURCE_METADATA_ROOT].params[methodName].query; const queryParamsCollection = queryParamsObjectIndex !== undefined ? args[queryParamsObjectIndex] : Object.keys(queryMetadata).reduce((mergedObj, paramName) => Object.assign(mergedObj, { [paramName]: args[queryMetadata[paramName]] }), {}); Object.keys(queryParamsCollection) .forEach((paramName) => { let value = queryParamsCollection[paramName]; if (!Array.isArray(value)) { value = [value]; } value.forEach((curParam) => { return queryParams[paramName] = curParam; }); }); return queryParams; } // eslint-disable-next-line @typescript-eslint/no-unused-vars static collectHttpHeaders(target, methodName, __args) { const classHeaders = target[RESOURCE_METADATA_ROOT].class ? target[RESOURCE_METADATA_ROOT].class.headers : {}; const methodHeaders = target[RESOURCE_METADATA_ROOT].methods && target[RESOURCE_METADATA_ROOT].methods[methodName] ? target[RESOURCE_METADATA_ROOT].methods[methodName].headers : {}; return Object.assign({}, classHeaders, methodHeaders); } } // @dynamic class NgxHttpAnnotationsModule { constructor(injector) { this.injector = injector; HttpRestUtils.appInjector = this.injector; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: NgxHttpAnnotationsModule, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.1.6", ngImport: i0, type: NgxHttpAnnotationsModule, imports: [CommonModule, HttpClientModule] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: NgxHttpAnnotationsModule, providers: [ { provide: APP_INITIALIZER, useFactory: onAppInit, multi: true, deps: [HttpClient] }, { provide: HTTP_ANNOTATIONS_USE_MOCKS, useValue: false } ], imports: [CommonModule, HttpClientModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.6", ngImport: i0, type: NgxHttpAnnotationsModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule, HttpClientModule], providers: [ { provide: APP_INITIALIZER, useFactory: onAppInit, multi: true, deps: [HttpClient] }, { provide: HTTP_ANNOTATIONS_USE_MOCKS, useValue: false } ] }] }], ctorParameters: function () { return [{ type: i0.Injector }]; } }); function onAppInit(http) { return function () { HttpRestUtils.http = http; }; } /* eslint-disable prefer-const */ // noinspection JSUnusedGlobalSymbols /** * @deprecated replace HttpRestModule by NgxHttpAnnotationsModule */ let HttpRestModule = NgxHttpAnnotationsModule; let Path = path; let PathParam = path; let Body = body(null); let ResponseObservable = response(null); let Query = query(null); let QueryParam = query; let QueryParams = query; let Observe = observe; // Headers let Headers = headers; // Produces let Produces = produces; // Request methods let GET = HttpRestUtils.requestMethod(RequestMethodParams.get); let POST = HttpRestUtils.requestMethod(RequestMethodParams.post); let PUT = HttpRestUtils.requestMethod(RequestMethodParams.put); let DELETE = HttpRestUtils.requestMethod(RequestMethodParams.delete); let OPTIONS = HttpRestUtils.requestMethod(RequestMethodParams.options); let HEAD = HttpRestUtils.requestMethod(RequestMethodParams.head); let PATCH = HttpRestUtils.requestMethod(RequestMethodParams.patch); /** * Generated bundle index. Do not edit. */ export { Body, DELETE, GET, HEAD, HTTP_ANNOTATIONS_USE_DELAY, HTTP_ANNOTATIONS_USE_MOCKS, Headers, HttpRestModule, MOCK_DEFAULT_DELAY, NO_DELAY, NgxHttpAnnotationsModule, OPTIONS, Observe, PATCH, POST, PUT, Path, PathParam, Produces, Query, QueryParam, QueryParams, RESOURCE_METADATA_ROOT, ResponseObservable, onAppInit }; //# sourceMappingURL=ngx-http-annotations.mjs.map