@mgrcto/angular-odata-v401
Version:
Odata Library for Angular made with Angular CLI
726 lines (714 loc) • 27 kB
JavaScript
import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { NgModule, Injectable } from '@angular/core';
import { throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import * as i1 from '@angular/common/http';
import { HttpParams, HttpHeaders } from '@angular/common/http';
class AngularOdataV401Module {
static forRoot() {
return {
ngModule: AngularOdataV401Module
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AngularOdataV401Module, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.3", ngImport: i0, type: AngularOdataV401Module, imports: [CommonModule] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AngularOdataV401Module, imports: [CommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: AngularOdataV401Module, decorators: [{
type: NgModule,
args: [{
declarations: [],
imports: [CommonModule
],
exports: []
}]
}] });
class ODataOperation {
constructor(typeName, config, http) {
this.typeName = typeName;
this.config = config;
this.http = http;
this._expand = [];
this._select = [];
}
Expand(expand) {
if (expand) {
this._expand = this.toStringArray(expand);
}
return this;
}
/**
* Selects Entities. If String is separated by "/" the first part will be expanded and the second part will be selected in the expand.
* @param select
* @returns ODataOperation<T>
*/
Select(select) {
if (select) {
this._select = this.toStringArray(select);
}
return this;
}
getParams(aParams) {
const expandData = new Map();
const normalSelects = [];
this._expand.forEach((name) => expandData.set(name, []));
this._select.forEach((select) => {
const items = select.split('/');
// Select contains string like: `Boss/Name`
if (items.length > 1) {
const expandName = items[0];
const propertyName = items[1];
if (!expandData.has(expandName)) {
expandData.set(expandName, []);
}
expandData.get(expandName).push(propertyName);
}
else {
// Select is just a simple string like: `Boss`
normalSelects.push(select);
}
});
let params = (aParams && Object.keys(aParams).length > 0) ? aParams : new HttpParams();
const expands = [];
expandData.forEach((val, key) => {
if (val.length) {
expands.push(`${key}(${this.config.keys.select}=${this.toCommaString(val)})`);
return;
}
expands.push(key);
});
if (expands.length) {
params = params.append(this.config.keys.expand, this.toCommaString(expands));
}
if (normalSelects.length) {
params = params.append(this.config.keys.select, this.toCommaString(normalSelects));
}
return params;
}
handleResponse(entity) {
return entity
.pipe(map(this.extractData), catchError((err, caught) => {
if (this.config.handleError) {
this.config.handleError(err, caught);
}
return throwError(err);
}));
}
getDefaultRequestOptions() {
const options = Object.assign({}, this.config.defaultRequestOptions);
options.params = this.getParams(options.params);
return options;
}
getPostRequestOptions() {
const options = Object.assign({}, this.config.postRequestOptions);
options.params = this.getParams(options.params);
return options;
}
GeneratePostUrl(entitiesUri) {
const params = this.getParams(this.config.postRequestOptions.params);
if (params.keys().length > 0) {
return `${entitiesUri}?${params}`;
}
return entitiesUri;
}
GenerateUrl(entitiesUri) {
const params = this.getParams(this.config.defaultRequestOptions.params);
if (params.keys().length > 0) {
return `${entitiesUri}?${params}`;
}
return entitiesUri;
}
toStringArray(input) {
if (!input) {
return [];
}
if (input instanceof String || typeof input === 'string') {
return input.split(',').map(s => s.trim());
}
if (input instanceof Array) {
return input;
}
return [];
}
toCommaString(input) {
if (input instanceof String || typeof input === 'string') {
return input;
}
if (input instanceof Array) {
return input.join();
}
return "";
}
extractData(res) {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
const body = res.body;
return body || {};
}
}
class OperationWithKey extends ODataOperation {
constructor(_typeName, config, http, entityKey) {
super(_typeName, config, http);
this._typeName = _typeName;
this.config = config;
this.http = http;
this.entityKey = entityKey;
}
getEntityUri() {
return this.config.getEntityUri(this.entityKey, this.typeName);
}
GetUrl() {
return this.GenerateUrl(this.getEntityUri());
}
}
class OperationWithEntity extends ODataOperation {
constructor(_typeName, config, http, entity) {
super(_typeName, config, http);
this._typeName = _typeName;
this.config = config;
this.http = http;
this.entity = entity;
}
getEntitiesUri() {
return this.config.getEntitiesUri(this._typeName);
}
GetUrl() {
return this.GenerateUrl(this.getEntitiesUri());
}
}
class OperationWithKeyAndEntity extends OperationWithKey {
constructor(_typeName, config, http, entityKey, entity) {
super(_typeName, config, http, entityKey);
this._typeName = _typeName;
this.config = config;
this.http = http;
this.entityKey = entityKey;
this.entity = entity;
}
getEntityUri() {
return this.config.getEntityUri(this.entityKey, this._typeName);
}
}
class GetOperation extends OperationWithKey {
Exec() {
return super.handleResponse(this.http.get(this.getEntityUri(), this.getDefaultRequestOptions()));
}
}
class PostOperation extends OperationWithEntity {
Exec() {
const body = this.entity ? JSON.stringify(this.entity) : null;
return super.handleResponse(this.http.post(this.getEntitiesUri(), body, this.getPostRequestOptions()));
}
GetUrl() {
return this.GeneratePostUrl(this.getEntitiesUri());
}
}
class PatchOperation extends OperationWithKeyAndEntity {
Exec() {
const body = this.entity ? JSON.stringify(this.entity) : null;
return super.handleResponse(this.http.patch(this.getEntityUri(), body, this.getPostRequestOptions()));
}
GetUrl() {
return this.GeneratePostUrl(this.getEntityUri());
}
}
class PutOperation extends OperationWithKeyAndEntity {
Exec() {
const body = this.entity ? JSON.stringify(this.entity) : null;
return super.handleResponse(this.http.put(this.getEntityUri(), body, this.getPostRequestOptions()));
}
GetUrl() {
return this.GeneratePostUrl(this.getEntityUri());
}
}
class DeleteOperation extends OperationWithKey {
Exec() {
return super.handleResponse(this.http.delete(this.getEntityUri(), this.config.defaultRequestOptions));
}
}
var ODataExecReturnType;
(function (ODataExecReturnType) {
// Default
ODataExecReturnType[ODataExecReturnType["Array"] = 0] = "Array";
ODataExecReturnType[ODataExecReturnType["Count"] = 1] = "Count";
ODataExecReturnType[ODataExecReturnType["PagedResult"] = 2] = "PagedResult";
ODataExecReturnType[ODataExecReturnType["MetadataResult"] = 3] = "MetadataResult";
})(ODataExecReturnType || (ODataExecReturnType = {}));
class ODataQuery extends ODataOperation {
constructor(typeName, config, http) {
super(typeName, config, http);
this._filter = "";
this._top = 0;
this._skip = 0;
this._search = "";
this._orderBy = [];
this._apply = [];
this._maxPerPage = 0;
this._customQueryOptions = [];
this._customQueryHeaders = [];
this._entitiesUri = config.getEntitiesUri(this.typeName);
}
Filter(filter) {
if (filter) {
this._filter = filter;
}
return this;
}
Search(search) {
if (search) {
this._search = search;
}
return this;
}
Top(top) {
if (top > -1) {
this._top = top;
}
return this;
}
Skip(skip) {
if (skip > -1) {
this._skip = skip;
}
return this;
}
OrderBy(orderBy) {
if (orderBy) {
this._orderBy = this.toStringArray(orderBy);
}
return this;
}
MaxPerPage(maxPerPage) {
if (maxPerPage > -1) {
this._maxPerPage = maxPerPage;
}
return this;
}
Apply(apply) {
if (apply) {
this._apply = this.toStringArray(apply);
}
return this;
}
CustomQueryOptions(customOptions) {
if (customOptions) {
this._customQueryOptions = Array.isArray(customOptions) ? customOptions : [customOptions];
}
return this;
}
CustomQueryHeaders(customHeaders) {
if (customHeaders) {
this._customQueryHeaders = Array.isArray(customHeaders) ? customHeaders : [customHeaders];
}
return this;
}
GetUrl(returnType) {
let url = this._entitiesUri;
if (returnType === ODataExecReturnType.Count) {
url = `${url}/${this.config.keys.count}`;
}
const params = this.getQueryParams(this.config.defaultRequestOptions.params);
if (params.keys().length > 0) {
return `${url}?${params}`;
}
return url;
}
Exec(returnType) {
const requestOptions = this.getQueryRequestOptions(returnType);
switch (returnType) {
case ODataExecReturnType.Count:
return this.execGetCount(requestOptions);
case ODataExecReturnType.PagedResult:
return this.execGetArrayDataWithCount(this._entitiesUri, requestOptions);
case ODataExecReturnType.MetadataResult:
return this.execGetArrayDataWithMetadata(this._entitiesUri, requestOptions);
default:
return this.execGetArrayData(requestOptions);
}
}
ExecWithCount() {
return this.Exec(ODataExecReturnType.PagedResult);
}
NextPage(pagedResult) {
const requestOptions = this.getQueryRequestOptions(ODataExecReturnType.PagedResult);
return this.execGetArrayDataWithCount(pagedResult.nextLink, requestOptions);
}
execGetCount(requestOptions) {
const countUrl = `${this._entitiesUri}/${this.config.keys.count}`;
return this.http.get(countUrl, requestOptions)
.pipe(map(res => this.extractDataAsNumber(res, this.config)), catchError((err, caught) => {
if (this.config.handleError) {
this.config.handleError(err, caught);
}
return throwError(err);
}));
}
execGetArrayDataWithCount(url, requestOptions) {
return this.http.get(url, requestOptions)
.pipe(map(res => this.extractArrayDataWithCount(res, this.config)), catchError((err, caught) => {
if (this.config.handleError) {
this.config.handleError(err, caught);
}
return throwError(err);
}));
}
execGetArrayDataWithMetadata(url, requestOptions) {
return this.http.get(url, requestOptions)
.pipe(map(res => this.extractArrayDataWithMetadata(res, this.config)), catchError((err, caught) => {
if (this.config.handleError) {
this.config.handleError(err, caught);
}
return throwError(err);
}));
}
execGetArrayData(requestOptions) {
return this.http.get(this._entitiesUri, requestOptions)
.pipe(map(res => this.extractArrayData(res, this.config)), catchError((err, caught) => {
if (this.config.handleError) {
this.config.handleError(err, caught);
}
return throwError(err);
}));
}
getQueryRequestOptions(returnType) {
const options = Object.assign({}, this.config.defaultRequestOptions);
options.params = this.getQueryParams(options.params);
options.headers = this.getQueryHeaders(options.headers, returnType);
return options;
}
getQueryHeaders(headers, returnType) {
if (!headers) {
headers = new HttpHeaders();
}
if (this._maxPerPage > 0) {
headers = headers.set('Prefer', `${this.config.keys.maxPerPage}=${this._maxPerPage}`);
}
headers = headers.set(`${this.config.keys.metadata}`, `${(returnType && returnType >= ODataExecReturnType.PagedResult) ? 'full' : 'none'}`);
if (this._customQueryHeaders.length > 0) {
this._customQueryHeaders.forEach(customQueryHeader => {
headers = headers.set(customQueryHeader.key, customQueryHeader.value);
});
}
return headers;
}
getQueryParams(aParams) {
let params = super.getParams(aParams);
if (this._filter) {
params = params.append(this.config.keys.filter, this._filter);
}
if (this._search) {
params = params.append(this.config.keys.search, this._search);
}
if (this._top > 0) {
params = params.append(this.config.keys.top, this._top.toString());
}
if (this._skip > 0) {
params = params.append(this.config.keys.skip, this._skip.toString());
}
if (this._orderBy.length > 0) {
params = params.append(this.config.keys.orderBy, this.toCommaString(this._orderBy));
}
if (this._apply.length > 0) {
params = params.append(this.config.keys.apply, this.toCommaString(this._apply));
}
if (this._customQueryOptions.length > 0) {
this._customQueryOptions.forEach(customQueryOption => (params = params.append(this.checkReservedCustomQueryOptionKey(customQueryOption.key), customQueryOption.value)));
}
return params;
}
extractDataAsNumber(res, config) {
return config.extractQueryResultDataAsNumber(res);
}
extractArrayData(res, config) {
return config.extractQueryResultData(res);
}
extractArrayDataWithCount(res, config) {
return config.extractQueryResultDataWithCount(res);
}
extractArrayDataWithMetadata(res, config) {
return config.extractQueryResultDataWithMetadata(res);
}
checkReservedCustomQueryOptionKey(key) {
if (key === null || key === undefined) {
throw new Error('Custom query options MUST NOT be null or undefined.');
}
if (key.indexOf('$') === 0 || key.indexOf('@') === 0) {
throw new Error('Custom query options MUST NOT begin with a $ or @ character.');
}
return key;
}
}
class ODataUtils {
static convertObjectToString(obj) {
const properties = [];
for (const prop in obj) {
if (obj.hasOwnProperty(prop) && obj[prop] !== undefined) {
const value = ODataUtils.quoteValue(obj[prop]);
properties.push(`${prop}=${value}`);
}
}
return properties.join(', ');
}
static quoteValue(value) {
// check if GUID (UUID) type
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) {
return value;
}
// check if string
if (typeof value === 'string') {
const escaped = value.replace(/'/g, '\'\'');
return `'${escaped}'`;
}
// check if boolean or number
if (typeof value === 'boolean' || typeof value === 'number') {
return `${value}`;
}
const parts = [];
Object.getOwnPropertyNames(value).forEach((propertyName) => {
const propertyValue = value[propertyName];
parts.push(`${propertyName}=${ODataUtils.quoteValue(propertyValue)}`);
});
return parts.length > 0 ? parts.join(', ') : `${value}`;
}
static tryParseInt(input) {
if (input !== null && !isNaN(input)) {
const parsed = parseInt(input, 10);
return {
valid: !isNaN(parsed),
value: parsed
};
}
return {
valid: false,
value: NaN
};
}
}
class ODataService {
constructor(_typeName, _http, config) {
this._typeName = _typeName;
this._http = _http;
this.config = config;
this._entitiesUri = config.getEntitiesUri(_typeName);
}
get TypeName() {
return this._typeName;
}
Get(key) {
return new GetOperation(this._typeName, this.config, this._http, key);
}
Post(entity) {
return new PostOperation(this._typeName, this.config, this._http, entity);
}
Patch(entity, key) {
return new PatchOperation(this._typeName, this.config, this._http, key, entity);
}
Put(entity, key) {
return new PutOperation(this._typeName, this.config, this._http, key, entity);
}
Delete(key) {
return new DeleteOperation(this._typeName, this.config, this._http, key);
}
CustomAction(key, actionName, postdata) {
const body = postdata ? JSON.stringify(postdata) : null;
return this._http.post(`${this.getEntityUri(key)}/${actionName}`, body, this.config.customRequestOptions).pipe(map(resp => resp));
}
CustomCollectionAction(actionName, postdata) {
const body = postdata ? JSON.stringify(postdata) : null;
return this._http.post(`${this._entitiesUri}/${actionName}`, body, this.config.customRequestOptions).pipe(map(resp => resp));
}
CustomFunction(key, functionName, parameters) {
if (parameters) {
const params = ODataUtils.convertObjectToString(parameters);
functionName = `${functionName}(${params})`;
}
else if (!functionName.endsWith(')') && !functionName.endsWith('()')) {
functionName = `${functionName}()`;
}
return this._http.get(`${this.getEntityUri(key)}/${functionName}`, this.config.defaultRequestOptions).pipe(map(resp => resp));
}
CustomCollectionFunction(functionName, parameters) {
if (parameters) {
const params = ODataUtils.convertObjectToString(parameters);
functionName = `${functionName}(${params})`;
}
else if (!functionName.endsWith(')') && !functionName.endsWith('()')) {
functionName = `${functionName}()`;
}
return this._http.get(`${this._entitiesUri}/${functionName}`, this.config.defaultRequestOptions).pipe(map(resp => resp));
}
getNestedEntityService(key, typeName) {
let nestedTypeName = `${this.config.getEntityPath(key, this._typeName)}/${typeName}`;
return new ODataService(nestedTypeName, this._http, this.config);
}
ItemProperty(key, propertyName) {
return this._http.get(`${this.getEntityUri(key)}/${propertyName}`, this.config.defaultRequestOptions)
.pipe(map(r => r.body));
}
Query() {
return new ODataQuery(this.TypeName, this.config, this._http);
}
getEntityUri(key) {
return this.config.getEntityUri(key, this._typeName);
}
handleResponse(entity) {
return entity
.pipe(map(this.extractData), catchError((err, caught) => {
if (this.config.handleError) {
this.config.handleError(err, caught);
}
return throwError(err);
}));
}
extractData(res) {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
const body = res.body;
return body || {};
}
}
class KeyConfigs {
constructor() {
this.filter = '$filter';
this.top = '$top';
this.skip = '$skip';
this.orderBy = '$orderby';
this.select = '$select';
this.search = '$search';
this.expand = '$expand';
this.apply = '$apply';
this.count = '$count';
this.maxPerPage = 'odata.maxpagesize';
this.metadata = 'odata.metadata';
this.responseCount = '@odata.count';
this.responseNextLink = '@odata.nextLink';
}
}
class ODataConfiguration {
constructor() {
this._postHeaders = new HttpHeaders({ 'Content-Type': 'application/json; charset=utf-8' });
this._baseUrl = 'http://localhost/odata';
this.keys = new KeyConfigs();
this.defaultRequestOptions = { headers: new HttpHeaders(), observe: 'response' };
this.postRequestOptions = { headers: this._postHeaders, observe: 'response' };
this.customRequestOptions = { headers: new HttpHeaders(), observe: 'response' };
}
set baseUrl(baseUrl) {
this._baseUrl = baseUrl.replace(/\/+$/, '');
}
get baseUrl() {
return this._baseUrl;
}
getEntitiesUri(typeName) {
if (typeName) {
return `${this.baseUrl}/${this.sanitizeTypeName(typeName)}`;
}
return this.baseUrl;
}
getEntityUri(key, typeName) {
return `${this.getEntitiesUri(typeName)}(${ODataUtils.quoteValue(key)})`;
}
getEntityPath(key, typeName) {
return `${this.sanitizeTypeName(typeName)}(${ODataUtils.quoteValue(key)})`;
}
handleError(err, caught) {
console.warn('OData error: ', err, caught);
}
extractQueryResultDataAsNumber(res) {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
return (res && res.body);
}
extractQueryResultData(res) {
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
return (res && res.body && res.body.value);
}
extractQueryResultDataWithCount(res) {
let pagedResult;
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
const body = res.body;
let entities = body.value;
delete body.value;
if (!Array.isArray(entities)) {
entities = [];
}
pagedResult = body;
pagedResult.data = entities;
const parseResult = ODataUtils.tryParseInt(body[`${this.keys.responseCount}`]);
if (parseResult.valid) {
pagedResult.count = parseResult.value;
}
else {
console.warn('Cannot determine OData entities count. Falling back to collection length.');
pagedResult.count = entities.length;
}
if (body[`${this.keys.responseNextLink}`]) {
pagedResult.nextLink = body[`${this.keys.responseNextLink}`];
}
return pagedResult;
}
extractQueryResultDataWithMetadata(res) {
let result;
if (res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
const body = res.body;
let entities = body.value;
delete body.value;
if (!Array.isArray(entities)) {
entities = [];
}
result = body;
result.data = entities;
const parseResult = ODataUtils.tryParseInt(body[`${this.keys.responseCount}`]);
if (parseResult.valid) {
result.count = parseResult.value;
}
else {
console.warn('Cannot determine OData entities count. Falling back to collection length.');
result.count = entities.length;
}
if (body[`${this.keys.responseNextLink}`]) {
result.nextLink = body[`${this.keys.responseNextLink}`];
}
return result;
}
sanitizeTypeName(typeName) {
return typeName.replace(/\/+$/, '').replace(/^\/+/, '');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ODataConfiguration, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ODataConfiguration }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ODataConfiguration, decorators: [{
type: Injectable
}] });
class ODataServiceFactory {
constructor(http, config) {
this.http = http;
this.config = config;
}
CreateService(typeName, config) {
return new ODataService(typeName, this.http, config ? config : this.config);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ODataServiceFactory, deps: [{ token: i1.HttpClient }, { token: ODataConfiguration }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ODataServiceFactory }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.3", ngImport: i0, type: ODataServiceFactory, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: ODataConfiguration }] });
/*
* Public API Surface of angular-odata-v401
*/
/**
* Generated bundle index. Do not edit.
*/
export { AngularOdataV401Module, DeleteOperation, GetOperation, ODataConfiguration, ODataExecReturnType, ODataOperation, ODataQuery, ODataService, ODataServiceFactory, OperationWithEntity, OperationWithKey, OperationWithKeyAndEntity, PatchOperation, PostOperation, PutOperation };
//# sourceMappingURL=mgrcto-angular-odata-v401.mjs.map