UNPKG

imng-odata-client

Version:

This library was generated with [Nx](https://nx.dev).

451 lines (435 loc) 16.6 kB
import * as i0 from '@angular/core'; import { inject, Injectable, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; import { MILLI_SECS_PER_SEC } from 'imng-nrsrx-client-utils'; import { map } from 'rxjs/operators'; function isChildFilter(source) { return !!source?.childTable; } function isCompositeFilter(source) { return !!source?.filters; } var ComputationOperators; (function (ComputationOperators) { ComputationOperators["Multiply"] = "mul"; ComputationOperators["Divide"] = "div"; ComputationOperators["Add"] = "add"; ComputationOperators["Subtract"] = "sub"; ComputationOperators["Modulus"] = "mod"; })(ComputationOperators || (ComputationOperators = {})); function isComputation(source) { return !!source?.operator; } function isExpander(source) { return !!source?.table; } function serializeValue(value) { if (typeof value === 'string') { return `'${value}'`; } return value instanceof Date ? `${value.toISOString().split('T')[0]}` : `${value}`; } const serializeSimpleFilter = (field, operator, value) => `${field}+${operator}+${serializeValue(value)}`; const serializeArrayFilter = (field, operator, values) => values ? `${field}+${operator}+(${values.map((m) => serializeValue(m)).join(',')})` : ''; const serializeFunctionFilter = (field, func, value) => (value ? `${func}(${field},${serializeValue(value)})` : ''); /** * Represents the list of supported simple filter operators. */ class FilterOperators { /** * The `eq` operator. */ static { this.equals = { name: 'equals', toODataString: (field, value) => serializeSimpleFilter(field, 'eq', value), }; } /** * The `gt` operator. */ static { this.greaterThan = { name: 'greaterThan', toODataString: (field, value) => serializeSimpleFilter(field, 'gt', value), }; } /** * The `ge` operator. */ static { this.greaterThanOrEquals = { name: 'greaterThanOrEquals', toODataString: (field, value) => serializeSimpleFilter(field, 'ge', value), }; } /** * The `lt` operator. */ static { this.lessThan = { name: 'lessThan', toODataString: (field, value) => serializeSimpleFilter(field, 'lt', value), }; } /** * The `le` operator. */ static { this.lessThanOrEquals = { name: 'lessThanOrEquals', toODataString: (field, value) => serializeSimpleFilter(field, 'le', value), }; } /** * The `ne` operator. */ static { this.notEquals = { name: 'notEquals', toODataString: (field, value) => serializeSimpleFilter(field, 'ne', value), }; } /** * The `in` operator. */ static { this.in = { name: 'in', toODataString: (field, values) => serializeArrayFilter(field, 'in', values), }; } /** * The `not in` operator. */ static { this.notIn = { name: 'notIn', toODataString: (field, values) => serializeArrayFilter(field, 'not+in', values), }; } /** * The `is not null` operator. */ static { this.notNull = { name: 'notNull', toODataString: (field) => `${field}+ne+null`, }; } /** * The `is null` operator. */ static { this.isNull = { name: 'isNull', toODataString: (field) => `${field}+eq+null`, }; } /** * The `contains` operator. */ static { this.contains = { name: 'contains', toODataString: (field, value) => serializeFunctionFilter(field, 'contains', value), }; } /** * The `not contain` operator. */ static { this.notContains = { name: 'notContains', toODataString: (field, value) => serializeFunctionFilter(field, 'not+contains', value), }; } /** * The `ends with` operator. */ static { this.endsWith = { name: 'endswith', toODataString: (field, value) => serializeFunctionFilter(field, 'endswith', value), }; } /** * The `not ends with` operator. */ static { this.notEndsWith = { name: 'notEndsWith', toODataString: (field, value) => serializeFunctionFilter(field, 'not+endswith', value), }; } /** * The `startswith` operator. */ static { this.startsWith = { name: 'startsWith', toODataString: (field, value) => serializeFunctionFilter(field, 'startswith', value), }; } /** * The `not start with` operator. */ static { this.notStartsWith = { name: 'notStartsWith', toODataString: (field, value) => serializeFunctionFilter(field, 'not+startswith', value), }; } /** * The `empty` operator. */ static { this.isEmpty = { name: 'isEmpty', toODataString: (field) => serializeSimpleFilter(field, 'eq', ''), }; } /** * The `not empty` operator. */ static { this.notEmpty = { name: 'notEmpty', toODataString: (field) => serializeSimpleFilter(field, 'ne', ''), }; } } const filterOperators = { contains: FilterOperators.contains, endsWith: FilterOperators.endsWith, equals: FilterOperators.equals, dateIs: FilterOperators.equals, greaterThan: FilterOperators.greaterThan, gt: FilterOperators.greaterThan, dateAfter: FilterOperators.greaterThan, greaterThanOrEquals: FilterOperators.greaterThanOrEquals, gte: FilterOperators.greaterThanOrEquals, in: FilterOperators.in, isEmpty: FilterOperators.isEmpty, isNull: FilterOperators.isNull, lessThan: FilterOperators.lessThan, lt: FilterOperators.lessThan, dateBefore: FilterOperators.lessThan, lessThanOrEquals: FilterOperators.lessThanOrEquals, lte: FilterOperators.lessThan, notContains: FilterOperators.notContains, notEmpty: FilterOperators.notEmpty, notEndsWith: FilterOperators.notEndsWith, notEquals: FilterOperators.notEquals, dateIsNot: FilterOperators.notEquals, notIn: FilterOperators.notIn, notNull: FilterOperators.notNull, notStartsWith: FilterOperators.notStartsWith, startsWith: FilterOperators.startsWith, }; function createEmptyODataResult() { return { value: Array(), count: 0 }; } function isODataResult(source) { return !!source?.value; } const getFilterOperator = (operatorName) => filterOperators[operatorName]; const mapData = (options) => map((response) => { if (!response) { return { value: [], count: 0 }; } return Array.isArray(response) ? { value: response, count: response.length, } : { value: parseDatesInCollection(response.value, options), count: response['@odata.count'], }; }); function parseDatesInCollection(collection, options) { if (collection.length > 0) { const utcProps = Object.keys(collection[0]).filter((x) => x.endsWith('Utc')); const dateProps = Object.keys(collection[0]).filter((x) => x.endsWith('Date') || x === 'date'); options.utcNullableProps?.forEach((t) => { if (utcProps.indexOf(t) === -1) { utcProps.push(t); } }); options.dateNullableProps?.forEach((t) => { if (dateProps.indexOf(t) === -1) { dateProps.push(t); } }); // prettier-ignore // eslint-disable-next-line @typescript-eslint/no-explicit-any collection.forEach((val) => { utcProps.filter((p) => val[p]).forEach((p) => (val[p] = new Date(val[p]))); dateProps.filter((p) => val[p]).forEach((p) => (val[p] = toLocalDate(val[p]))); }); } return collection; } function toLocalDate(date) { const dt = new Date(date); return new Date(dt.getTime() + Math.abs(dt.getTimezoneOffset() * MILLI_SECS_PER_SEC)); } class ODataClientService { constructor() { this.httpClient = inject(HttpClient); } fetch(odataEndpoint, query, options = {}) { const queryStr = this.getODataString(query, options); return this.httpClient .get(`${odataEndpoint}?${queryStr}`) .pipe(mapData(options)); } getODataString(query, options = {}) { let queryString = ''; queryString = this.processFilters(query, options, queryString); queryString = this.processOrderBy(query, queryString); queryString = this.processSelectors(query, queryString); queryString = this.processExpanders(query, queryString); queryString = this.processSimpleParameters('top', query, queryString); queryString = this.processSimpleParameters('skip', query, queryString); queryString = this.processGuids(queryString); queryString = this.processDates(queryString); queryString = this.processCount(query, queryString); queryString = this.processCacheBusting(options, queryString); queryString = queryString.substring(1); // removing first & return queryString; } processExpanders(query, queryString) { if (query.expand && query.expand.length > 0) { const expansionStrings = query.expand.map((element) => this.getExpansionString(element)); queryString += `&$expand=${expansionStrings.join(',')}`; } return queryString; } getExpansionString(element) { let result = ''; if (!element) { return result; } if (typeof element === 'string') { result += element; } else { result += `${element.table}(`; const query = { ...element, count: element.count ?? false, expand: undefined, }; result += `${this.getODataString(query).replace(/&/g, ';')};`; if (element.expand) { const expanders = element.expand.map((expander) => { if (isExpander(expander)) { return this.getExpansionString(expander); } return expander; }); result += `$expand=${expanders.join(',')};`; } result += ')'; result = result .replace(/\(;\$expand=/, '($expand=') //Replaces empty expand "(;$expand=" with "($expand=" .replace(/\$expand=;?\)$/, ')') //Replaces empty expand ";$expand=;)" or ";$expand=)" with ")" .replace(/\(;\)$/, '') //Removes empty expansion clause "(;)" .replace(/;\)$/, ')'); //Replaces ";)" with ")" } return result; } processOrderBy(query, queryString) { if (!query.orderBy?.length) { return queryString; } const sortString = query.orderBy .map((m) => `${m.field}${m.dir === 'desc' ? '+desc' : ''}`) .join(','); return `${queryString}&$orderby=${sortString}`; } processFilters(query, _options, queryString) { if (!query.filter?.filters?.length) { return queryString; } const filterString = this.serializeCompositeFilter(query.filter); return `${queryString}&$filter=${filterString}`; } serializeCompositeFilter(filter) { const filterLogicSeperator = `+${filter.logic}+`; return `(${filter.filters .map((m) => isCompositeFilter(m) ? this.serializeCompositeFilter(m) : this.serializeFilter(m)) .filter((m) => m && m !== '()') .join(filterLogicSeperator)})`; } serializeFilter(filter) { const odataStringFunction = filter.operator?.toODataString || getFilterOperator(filter.operator?.name || 'equals').toODataString; if (isChildFilter(filter)) { const childFieldName = `o/${filter.field}`; return `${filter.childTable}/${filter.linqOperation}(o: ${odataStringFunction(childFieldName, filter.value)})`; } else { return odataStringFunction(filter.field, filter.value); } } processSimpleParameters(parameterName, query, queryString) { if (query[parameterName] || (parameterName === 'top' && query[parameterName] === 0)) { return `${queryString}&$${parameterName}=${query[parameterName]}`; } return queryString; } processCacheBusting(options, queryString) { if (options.bustCache) { const timeStamp = new Date().toISOString().replace(/[-:.TZ]/g, ''); return `${queryString}&timestamp=${timeStamp}`; } return queryString; } processCount(query, queryString) { if (query.count === false) { return queryString; } return `${queryString}&$count=true`; } processDates(queryString) { const dateRegex = /Date [e-t]{2} \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/g; let m; const dateMatches = []; while ((m = dateRegex.exec(queryString)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === dateRegex.lastIndex) { dateRegex.lastIndex++; } m.forEach((match) => { dateMatches.push(match); }); } dateMatches.forEach((date) => (queryString = queryString.replace(date, date.replace(/T\d{2}:\d{2}:\d{2}.\d{3}Z/g, '')))); return queryString; } processGuids(queryString) { const guidRegex = /'[\dA-F]{8}-?[\dA-F]{4}-?[\dA-F]{4}-?[\dA-F]{4}-?[\dA-F]{12}'/gi; let m; const guidMatches = []; while ((m = guidRegex.exec(queryString)) !== null) { // This is necessary to avoid infinite loops with zero-width matches if (m.index === guidRegex.lastIndex) { guidRegex.lastIndex++; } m.forEach((match) => { guidMatches.push(match); }); } guidMatches.forEach((guid) => (queryString = queryString.replace(guid, guid.replace(/'/g, '')))); return queryString; } processSelectors(state, queryString) { if (state.select && state.select.length > 0) { return `${queryString}&$select=${state.select.join()}`; } return queryString; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ODataClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ODataClientService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ODataClientService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); class ImngODataClientModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ImngODataClientModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.4", ngImport: i0, type: ImngODataClientModule, imports: [CommonModule] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ImngODataClientModule, providers: [ODataClientService, provideHttpClient(withInterceptorsFromDi())], imports: [CommonModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ImngODataClientModule, decorators: [{ type: NgModule, args: [{ imports: [CommonModule], providers: [ODataClientService, provideHttpClient(withInterceptorsFromDi())] }] }] }); function createODataResult(t) { return { value: t, count: t?.length, }; } /** * Generated bundle index. Do not edit. */ export { ComputationOperators, FilterOperators, ImngODataClientModule, ODataClientService, createEmptyODataResult, createODataResult, filterOperators, getFilterOperator, isChildFilter, isCompositeFilter, isComputation, isExpander, isODataResult, serializeArrayFilter, serializeFunctionFilter, serializeSimpleFilter, serializeValue }; //# sourceMappingURL=imng-odata-client.mjs.map