UNPKG

imng-odata-client

Version:

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

521 lines (502 loc) 19.3 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, isRelativeValue = false) { if (isRelativeValue) { return value?.toString() ?? ''; } else if (typeof value === 'string') { return `'${encodeURIComponent(value)}'`; } else if (value instanceof Date) { return `${value.toISOString().split('T')[0]}`; } return `${value}`; } const serializeSimpleFilter = (field, operator, value, isRelativeValue = false) => `${field} ${operator} ${serializeValue(value, isRelativeValue)}`; const serializeArrayFilter = (field, operator, values, isRelativeValue = false) => values && values.length > 0 ? `${field} ${operator} (${values.map((value) => serializeValue(value, isRelativeValue)).join(',')})` : ''; const serializeFunctionFilter = (field, func, value, isRelativeValue = false) => value ? `${func}(${field},${serializeValue(value, isRelativeValue)})` : ''; /** * Represents the list of supported simple filter operators. */ class FilterOperators { /** * The `eq` operator. */ static { this.equals = { name: 'equals', toODataString: (field, value, isRelativeValue = false) => serializeSimpleFilter(field, 'eq', value, isRelativeValue), }; } /** * The `gt` operator. */ static { this.greaterThan = { name: 'greaterThan', toODataString: (field, value, isRelativeValue = false) => serializeSimpleFilter(field, 'gt', value, isRelativeValue), }; } /** * The `ge` operator. */ static { this.greaterThanOrEquals = { name: 'greaterThanOrEquals', toODataString: (field, value, isRelativeValue = false) => serializeSimpleFilter(field, 'ge', value, isRelativeValue), }; } /** * The `lt` operator. */ static { this.lessThan = { name: 'lessThan', toODataString: (field, value, isRelativeValue = false) => serializeSimpleFilter(field, 'lt', value, isRelativeValue), }; } /** * The `le` operator. */ static { this.lessThanOrEquals = { name: 'lessThanOrEquals', toODataString: (field, value, isRelativeValue = false) => serializeSimpleFilter(field, 'le', value, isRelativeValue), }; } /** * The `ne` operator. */ static { this.notEquals = { name: 'notEquals', toODataString: (field, value, isRelativeValue = false) => serializeSimpleFilter(field, 'ne', value, isRelativeValue), }; } /** * The `in` operator. */ static { this.in = { name: 'in', toODataString: (field, values, isRelativeValue = false) => serializeArrayFilter(field, 'in', values, isRelativeValue), }; } /** * The `not in` operator. */ static { this.notIn = { name: 'notIn', toODataString: (field, values, isRelativeValue = false) => serializeArrayFilter(field, 'not in', values, isRelativeValue), }; } /** * 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, isRelativeValue = false) => serializeFunctionFilter(field, 'contains', value, isRelativeValue), }; } /** * The `not contain` operator. */ static { this.notContains = { name: 'notContains', toODataString: (field, value, isRelativeValue = false) => serializeFunctionFilter(field, 'not contains', value, isRelativeValue), }; } /** * The `ends with` operator. */ static { this.endsWith = { name: 'endswith', toODataString: (field, value, isRelativeValue = false) => serializeFunctionFilter(field, 'endswith', value, isRelativeValue), }; } /** * The `not ends with` operator. */ static { this.notEndsWith = { name: 'notEndsWith', toODataString: (field, value, isRelativeValue = false) => serializeFunctionFilter(field, 'not endswith', value, isRelativeValue), }; } /** * The `startswith` operator. */ static { this.startsWith = { name: 'startsWith', toODataString: (field, value, isRelativeValue = false) => serializeFunctionFilter(field, 'startswith', value, isRelativeValue), }; } /** * The `not start with` operator. */ static { this.notStartsWith = { name: 'notStartsWith', toODataString: (field, value, isRelativeValue = false) => serializeFunctionFilter(field, 'not startswith', value, isRelativeValue), }; } /** * The `empty` operator. */ static { this.isEmpty = { name: 'isEmpty', toODataString: (field) => serializeSimpleFilter(field, 'eq', '', false), }; } /** * The `not empty` operator. */ static { this.notEmpty = { name: 'notEmpty', toODataString: (field) => serializeSimpleFilter(field, 'ne', '', false), }; } } const filterOperators = { contains: FilterOperators.contains, endsWith: FilterOperators.endsWith, endswith: FilterOperators.endsWith, equals: FilterOperators.equals, eq: FilterOperators.equals, dateIs: FilterOperators.equals, greaterThan: FilterOperators.greaterThan, gt: FilterOperators.greaterThan, dateAfter: FilterOperators.greaterThan, greaterThanOrEquals: FilterOperators.greaterThanOrEquals, gte: FilterOperators.greaterThanOrEquals, ge: FilterOperators.greaterThanOrEquals, in: FilterOperators.in, isEmpty: FilterOperators.isEmpty, isNull: FilterOperators.isNull, isnull: FilterOperators.isNull, lessThan: FilterOperators.lessThan, lt: FilterOperators.lessThan, dateBefore: FilterOperators.lessThan, lessThanOrEquals: FilterOperators.lessThanOrEquals, lte: FilterOperators.lessThanOrEquals, notContains: FilterOperators.notContains, doesnotcontain: FilterOperators.notContains, notEmpty: FilterOperators.notEmpty, isnotempty: FilterOperators.notEmpty, notEndsWith: FilterOperators.notEndsWith, notEquals: FilterOperators.notEquals, ne: FilterOperators.notEquals, neq: FilterOperators.notEquals, dateIsNot: FilterOperators.notEquals, notIn: FilterOperators.notIn, notNull: FilterOperators.notNull, isnotnull: FilterOperators.notNull, notStartsWith: FilterOperators.notStartsWith, startsWith: FilterOperators.startsWith, startswith: FilterOperators.startsWith, }; function isFilter(source) { return !!source?.field; } function createEmptyODataResult() { return { value: Array(), count: 0 }; } function isODataResult(source) { return !!source?.value; } function isArrayFilter(source) { return (isFilter(source) && (source.operator === 'in' || source.operator === 'notIn' || source.operator === FilterOperators.in || source.operator === FilterOperators.notIn)); } 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.includes(t)) { utcProps.push(t); } }); options.dateNullableProps?.forEach((t) => { if (!dateProps.includes(t)) { 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)); } const getFilterOperator = (operatorName) => filterOperators[operatorName]; function processFilters(query, queryString) { if (!query.filter?.filters?.length) { return queryString; } const filterString = serializeCompositeFilter(query.filter); if (filterString === '()') { return queryString; } return `${queryString}&$filter=${filterString}`; } function serializeCompositeFilter(compositeFilter) { const filterLogicSeparator = ` ${compositeFilter.logic} `; return `(${compositeFilter.filters .map((filter) => serializeFilterItem(filter)) .filter((m) => m && m !== '()') .join(filterLogicSeparator)})`; } function serializeFilterItem(filter) { if (isCompositeFilter(filter)) { const subFilters = filter.filters.filter((subFilter) => isNotEmptyFilter(subFilter)); if (subFilters.length > 1) { return serializeCompositeFilter(filter); } else if (subFilters.length === 1) { return serializeFilterItem(subFilters[0]); } else { return ''; } } else if (isNotEmptyFilter(filter)) { return serializeFilter(filter); } return ''; } function isNotEmptyFilter(filter) { if (isCompositeFilter(filter)) { return filter.filters.every((filter) => isNotEmptyFilter(filter)); } else if (isArrayFilter(filter)) { return (filter.value !== undefined && filter.value !== null && filter.value.length > 0); } else { return (filter.field !== undefined && filter.field !== null && filter.field.length > 0); } } function serializeFilter(filter) { const operator = typeof filter.operator === 'string' ? getFilterOperator(filter.operator) : getFilterOperator(filter.operator?.name || 'equals'); const odataStringFunction = operator.toODataString; if (filter.field === undefined || filter.field === null) { return ''; } else { const field = filter.field.replaceAll('.', '/'); if (isChildFilter(filter)) { const childFieldName = `o/${field}`; return `${filter.childTable}/${filter.linqOperation}(o: ${odataStringFunction(childFieldName, filter.value, filter.isRelativeValue)})`; } else { return odataStringFunction(field, filter.value, filter.isRelativeValue); } } } const uuidRegex = /T\d{2}:\d{2}:\d{2}.\d{3}Z/gi; class ODataClientService { constructor() { this.httpClient = inject(HttpClient); } fetch(odataEndpoint, query, options = {}) { const queryStr = getODataString(query, options); return this.httpClient .get(`${odataEndpoint}?${queryStr}`) .pipe(mapData(options)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ODataClientService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ODataClientService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ODataClientService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); function getODataString(query, options = {}) { let queryString = ''; queryString = processFilters(query, queryString); queryString = processOrderBy(query, queryString); queryString = processSelectors(query, queryString); queryString = processExpanders(query, queryString); queryString = processSimpleParameters('top', query, queryString); queryString = processSimpleParameters('skip', query, queryString); queryString = processGuids(queryString); queryString = processDates(queryString); queryString = processCount(query, queryString); queryString = processCacheBusting(options, queryString); queryString = queryString.substring(1); // removing first & return queryString; } function processExpanders(query, queryString) { if (query.expand && query.expand.length > 0) { const expansionStrings = query.expand.map((element) => getExpansionString(element)); queryString += `&$expand=${expansionStrings.join(',')}`; } return queryString; } function 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 += `${getODataString(query).replaceAll('&', ';')};`; if (element.expand) { const expanders = element.expand.map((expander) => { if (isExpander(expander)) { return 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; } function 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}`; } function processSimpleParameters(parameterName, query, queryString) { if (query[parameterName] || (parameterName === 'top' && query[parameterName] === 0)) { return `${queryString}&$${parameterName}=${query[parameterName]}`; } return queryString; } function processCacheBusting(options, queryString) { if (options.bustCache) { const timeStamp = new Date().toISOString().replaceAll(/[-:.TZ]/g, ''); return `${queryString}&timestamp=${timeStamp}`; } return queryString; } function processCount(query, queryString) { if (query.count === false) { return queryString; } return `${queryString}&$count=true`; } function 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.replaceAll(uuidRegex, '')))); return queryString; } function 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.replaceAll(guid, guid.replaceAll("'", '')))); return queryString; } function processSelectors(state, queryString) { if (state.select && state.select.length > 0) { return `${queryString}&$select=${state.select.join()}`; } return queryString; } class ImngODataClientModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ImngODataClientModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.10", ngImport: i0, type: ImngODataClientModule, imports: [CommonModule] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ImngODataClientModule, providers: [ODataClientService, provideHttpClient(withInterceptorsFromDi())], imports: [CommonModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", 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, getExpansionString, getFilterOperator, getODataString, isArrayFilter, isChildFilter, isCompositeFilter, isComputation, isExpander, isFilter, isNotEmptyFilter, isODataResult, processCacheBusting, processCount, processDates, processExpanders, processFilters, processGuids, processOrderBy, processSelectors, processSimpleParameters, serializeArrayFilter, serializeCompositeFilter, serializeFilter, serializeFilterItem, serializeFunctionFilter, serializeSimpleFilter, serializeValue, uuidRegex }; //# sourceMappingURL=imng-odata-client.mjs.map