pailingual-odata
Version:
TypeScript client for OData v4 services
154 lines (130 loc) • 5.17 kB
text/typescript
import { Query} from "./query";
import { EdmEntityType, EdmTypes, ApiMetadata } from "./metadata";
import { SingleSource } from "./singleSource";
import { serializeValue } from "./serialization"
import { Executable, ExecutableAndCount } from "./executable";
import * as helpers from "./utils";
export class CollectionSource extends ExecutableAndCount {
constructor(
protected __metadata: EdmEntityType,
protected __apiMetadata: ApiMetadata,
query: Query
) {
super(query);
this._generateOperationsProperties();
}
private _generateOperationsProperties() {
if (this.__apiMetadata) {
helpers.generateOperations(this, () => this.query, this.__apiMetadata, this.__metadata, true);
}
}
$byKey(key: any) {
let expression = (typeof key === "object" && !(key instanceof Date))
? this.getExpressionByValues(key as Record<string, any>)
: this.getExpressionByKeyValue(key)
var query = this.query.byKey(expression);
return new SingleSource(this.__metadata, this.__apiMetadata, query)
}
private getExpressionByKeyValue(value: any): string {
let md = this.__metadata;
let keys = this.__metadata.keys;
while (md.baseType && !keys)
{
md = md.baseType;
keys = md.keys;
}
if (!keys)
throw new Error(`Metadata: Keys not defined for entity type '${md.name}'`);
if (keys.length > 1)
throw new Error('For entity with composite key use named parameters');
let keyType = md.properties[keys[0]].type as EdmTypes;
let res = serializeValue(value, keyType, true);
if (!res)
throw new Error("Key must be not null value");
return res;
}
private getExpressionByValues(values: Record<string, any>): string {
var res = new Array<string>();
for (let prop in values) {
let propMetadata = this.__metadata.properties[prop];
if (!propMetadata)
throw new Error(`Property '${prop}' for entity '${this.__metadata.name}' not found.`);
let value = serializeValue(values[prop], propMetadata.type as EdmTypes, true);
let exp = `${prop}=${value}`;
res.push(exp);
}
return res.join(",");
}
$cast(fullTypeName: string): CollectionSource {
const typeMetadata = this.__apiMetadata.getEdmTypeMetadata(fullTypeName) as EdmEntityType;
if (!typeMetadata)
throw new Error(`EntityType '${fullTypeName}' not found.`);
const q = this.query.cast(fullTypeName);
return new CollectionSource(typeMetadata, this.__apiMetadata, q);
}
$count() {
const query = this.query.count();
return new Executable(query);
}
$delete(key: any) {
return this.$byKey(key).$delete();
}
$expand(prop: string, exp?: Function) {
const q = this.query.expand(prop, exp);
return new CollectionSource(this.__metadata, this.__apiMetadata, q);
}
$filter(expr: string) {
const q = this.query.filter(expr);
return new CollectionSource(this.__metadata, this.__apiMetadata, q);
}
$orderBy(...fields: (string | Function)[]) {
return this.orderByImpl(fields);
}
$orderByDesc(...fields: (string | Function)[]) {
return this.orderByImpl(fields, true);
}
private orderByImpl(fields: (string | Function)[], desc = false) {
var expressions: string[] = fields.map(f => {
let exp = (typeof f == "string")
? f
: helpers.buildPathExpression(f, this.__metadata, this.__apiMetadata);
if (desc)
exp += " desc";
return exp;
});
const q = this.query.orderBy(expressions);
return new CollectionSource(this.__metadata, this.__apiMetadata, q);
}
$insert(obj: any) {
const q = this.query.insert(obj);
return new Executable(q);
}
$patch(key: any, obj: any) {
return this.$byKey(key).$patch(obj);
}
$top(num: number) {
const q = this.query.top(num);
return new CollectionSource(this.__metadata, this.__apiMetadata, q);
}
$skip(num: number) {
const q = this.query.skip(num);
return new CollectionSource(this.__metadata, this.__apiMetadata, q);
}
$search(expr: string) {
const q = this.query.search(expr);
return new CollectionSource(this.__metadata, this.__apiMetadata, q);
}
$select(...fields: string[]) {
const q = this.query.select(fields);
return new CollectionSource(this.__metadata, this.__apiMetadata, q);
}
$unsafeExpand(exp: string) {
return this.$expand(exp);
}
$update(key: any, obj: any) {
return this.$byKey(key).$update(obj);
}
$urlWithCount() {
return this.query.count({ inline: true }).url();
}
}