odata-v4-server
Version:
OData V4 Server
1,022 lines (993 loc) • 55.9 kB
text/typescript
import "reflect-metadata";
import * as util from "util";
import { ODataController } from "./controller";
import { ODataServer } from "./server";
import { getFunctionParameters, Decorator } from "./utils";
import * as odata from "./odata";
const EdmProperties:string = "edm:properties";
const EdmKeyProperties:string = "edm:keyproperties";
const EdmKeyProperty:string = "edm:keyproperty";
const EdmForeignKeys:string = "edm:foreignkeys";
const EdmComputedProperty:string = "edm:computedproperty";
const EdmNullableProperty:string = "edm:nullableproperty";
const EdmPartnerProperty:string = "edm:partnerproperty";
const EdmType:string = "edm:type";
const EdmElementType:string = "edm:elementtype";
const EdmComplexType:string = "edm:complextype";
const EdmEntityType:string = "edm:entitytype";
const EdmEnumType:string = "edm:enumtype";
const EdmTypeDefinition:string = "edm:typedefinition";
const EdmFlags:string = "edm:flags";
const EdmOperations:string = "edm:operations";
const EdmAction:string = "edm:action";
const EdmFunction:string = "edm:function";
const EdmReturnType:string = "edm:returntype";
const EdmParameters:string = "edm:parameters";
const EdmAnnotations:string = "edm:annotations";
const EdmConverter:string = "edm:converter";
const EdmSerializer:string = "edm:serializer";
const EdmDeserializer:string = "edm:deserializer";
const EdmURLSerializer:string = "edm:urlserializer";
const EdmURLDeserializer:string = "edm:urldeserializer";
const EdmMediaEntity:string = "edm:mediaentity";
const EdmOpenType:string = "emd:opentype";
const EdmChildren:string = "edm:children";
const EdmContainer:Function[] = [];
const EdmMaxLength:string = "edm:maxlength";
const EdmPrecision:string = "edm:precision";
const EdmScale:string = "edm:scale";
const EdmUnicode:string = "edm:unicode";
const EdmSRID:string = "edm:srid";
const EdmDefaultValue:string = "edm:defaultvalue";
const EdmConcurrencyMode:string = "edm:concurrencymode";
/**
* Defines OData Edm decorators
*
* @param type Edm decorator type
* @return Edm decorator
*/
function typeDecoratorFactory(type:string):any{
let decorator = function(target?:any, targetKey?:string, parameterIndex?:number){
let baseType = Object.getPrototypeOf(target).constructor;
if (baseType != Object && getProperties(baseType.prototype).length > 0){
EntityType()(baseType.prototype);
let children = Reflect.getOwnMetadata(EdmChildren, baseType) || [];
if (children.indexOf(target.constructor) < 0){
children.unshift(target.constructor);
}
Reflect.defineMetadata(EdmChildren, children, baseType);
}
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.type = type;
}else{
existingParameters.push({
name: paramName,
type: type
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
let desc = Object.getOwnPropertyDescriptor(target, targetKey);
if (targetKey != EdmType && ((desc && typeof desc.value != "function") || (!desc && typeof target[targetKey] != "function"))) {
let properties:string[] = Reflect.getOwnMetadata(EdmProperties, target) || [];
if (properties.indexOf(targetKey) < 0) properties.push(targetKey);
Reflect.defineMetadata(EdmProperties, properties, target);
}
Reflect.defineMetadata(EdmType, type, target, targetKey);
}
};
return function(this:any, ...args:any[]){
if (arguments.length == 0) return decorator;
else return decorator.apply(this, args);
};
}
/** Edm.Binary primitive type property decorator */
export const Binary = typeDecoratorFactory("Edm.Binary");
/** Edm.Boolean primitive type property decorator */
export const Boolean = typeDecoratorFactory("Edm.Boolean");
/** Edm.Byte primitive type property decorator */
export const Byte = typeDecoratorFactory("Edm.Byte");
/** Edm.Date primitive type property decorator */
export const Date = typeDecoratorFactory("Edm.Date");
/** Edm.DateTimeOffset primitive type property decorator */
export const DateTimeOffset = typeDecoratorFactory("Edm.DateTimeOffset");
/** Edm.Decimal primitive type property decorator */
export const Decimal = typeDecoratorFactory("Edm.Decimal");
/** Edm.Double primitive type property decorator */
export const Double = typeDecoratorFactory("Edm.Double");
/** Edm.Duration primitive type property decorator */
export const Duration = typeDecoratorFactory("Edm.Duration");
/** Edm.Guid primitive type property decorator */
export const Guid = typeDecoratorFactory("Edm.Guid");
/** Edm.Int16 primitive type property decorator */
export const Int16 = typeDecoratorFactory("Edm.Int16");
/** Edm.Int32 primitive type property decorator */
export const Int32 = typeDecoratorFactory("Edm.Int32");
/** Edm.Int64 primitive type property decorator */
export const Int64 = typeDecoratorFactory("Edm.Int64");
/** Edm.SByte primitive type property decorator */
export const SByte = typeDecoratorFactory("Edm.SByte");
/** Edm.Single primitive type property decorator */
export const Single = typeDecoratorFactory("Edm.Single");
/** Edm.Stream primitive type property decorator */
export function Stream(contentType?:string);
export function Stream(target?:any, targetKey?:string);
export function Stream(this:any, target?:any){
if (typeof target == "string"){
const contentType = target;
return function(target, targetKey){
Reflect.defineMetadata(EdmMediaEntity, contentType, target, targetKey);
typeDecoratorFactory("Edm.Stream")(target, targetKey);
}
}
return typeDecoratorFactory("Edm.Stream").apply(this, arguments);
};
/** Edm.String primitive type property decorator */
export const String = typeDecoratorFactory("Edm.String");
/** Edm.TimeOfDay primitive type property decorator */
export const TimeOfDay = typeDecoratorFactory("Edm.TimeOfDay");
/** Edm.Geography primitive type property decorator */
export const Geography = typeDecoratorFactory("Edm.Geography");
/** Edm.GeographyPoint primitive type property decorator */
export const GeographyPoint = typeDecoratorFactory("Edm.GeographyPoint");
/** Edm.GeographyLineString primitive type property decorator */
export const GeographyLineString = typeDecoratorFactory("Edm.GeographyLineString");
/** Edm.GeographyPolygon primitive type property decorator */
export const GeographyPolygon = typeDecoratorFactory("Edm.GeographyPolygon");
/** Edm.GeographyMultiPoint primitive type property decorator */
export const GeographyMultiPoint = typeDecoratorFactory("Edm.GeographyMultiPoint");
/** Edm.GeographyMultiLineString primitive type property decorator */
export const GeographyMultiLineString = typeDecoratorFactory("Edm.GeographyMultiLineString");
/** Edm.GeographyMultiPolygon primitive type property decorator */
export const GeographyMultiPolygon = typeDecoratorFactory("Edm.GeographyMultiPolygon");
/** Edm.GeographyCollection primitive type property decorator */
export const GeographyCollection = (function GeographyCollection(){
return typeDecoratorFactory("Edm.GeographyCollection");
})();
/** Edm.Geometry primitive type property decorator */
export const Geometry = (function Geometry(){
return typeDecoratorFactory("Edm.Geometry");
})();
/** Edm.GeometryPoint primitive type property decorator */
export const GeometryPoint = (function GeometryPoint(){
return typeDecoratorFactory("Edm.GeometryPoint");
})();
/** Edm.GeometryLineString primitive type property decorator */
export const GeometryLineString = (function GeometryLineString(){
return typeDecoratorFactory("Edm.GeometryLineString");
})();
/** Edm.GeometryPolygon primitive type property decorator */
export const GeometryPolygon = (function GeometryPolygon(){
return typeDecoratorFactory("Edm.GeometryPolygon");
})();
/** Edm.GeometryMultiPoint primitive type property decorator */
export const GeometryMultiPoint = (function GeometryMultiPoint(){
return typeDecoratorFactory("Edm.GeometryMultiPoint");
})();
/** Edm.GeometryMultiLineString primitive type property decorator */
export const GeometryMultiLineString = (function GeometryMultiLineString(){
return typeDecoratorFactory("Edm.GeometryMultiLineString");
})();
/** Edm.GeometryMultiPolygon primitive type property decorator */
export const GeometryMultiPolygon = (function GeometryMultiPolygon(){
return typeDecoratorFactory("Edm.GeometryMultiPolygon");
})();
/** Edm.GeometryCollection primitive type property decorator */
export const GeometryCollection = (function GeometryCollection(){
return typeDecoratorFactory("Edm.GeometryCollection");
})();
/** ?????????? */
/** Edm.Collection decorator for describing properties as collections */
export function Collection(elementType:Function):Decorator{
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let element = function Collection(){};
Reflect.decorate([elementType()], element, EdmType);
let elementTypeName = Reflect.getMetadata(EdmType, element, EdmType);
if (typeof elementTypeName == "function"){
elementTypeName = ((<any>elementTypeName).namespace || (<any>target).namespace) + "." + (<any>elementTypeName).name;
}
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.type = "Collection(" + elementTypeName + ")";
}else{
existingParameters.push({
name: paramName,
type: "Collection(" + elementTypeName + ")"
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
let baseType = Object.getPrototypeOf(target).constructor;
if (baseType != Object && getProperties(baseType.prototype).length > 0){
EntityType()(baseType.prototype);
let children = Reflect.getOwnMetadata(EdmChildren, baseType) || [];
if (children.indexOf(target.constructor) < 0){
children.unshift(target.constructor);
}
Reflect.defineMetadata(EdmChildren, children, baseType);
}
let desc = Object.getOwnPropertyDescriptor(target, targetKey);
if ((desc && typeof desc.value != "function") || (!desc && typeof target[targetKey] != "function")) {
let properties:string[] = Reflect.getOwnMetadata(EdmProperties, target) || [];
if (properties.indexOf(targetKey) < 0) properties.push(targetKey);
Reflect.defineMetadata(EdmProperties, properties, target);
}
let element = function Collection(){};
try{
Reflect.decorate([elementType()], element, EdmType);
}catch(err){
Reflect.decorate([<any>elementType], element, EdmType);
}
let type = Reflect.getMetadata(EdmComplexType, element, EdmType);
let elementTypeName = Reflect.getMetadata(EdmType, element, EdmType);
Reflect.defineMetadata(EdmType, "Collection", target, targetKey);
Reflect.defineMetadata(EdmElementType, elementTypeName, target, targetKey);
if (type){
Reflect.defineMetadata(EdmComplexType, type, target, targetKey);
}else{
type = Reflect.getMetadata(EdmEntityType, element, EdmType);
Reflect.defineMetadata(EdmEntityType, type, target, targetKey);
}
}
};
}
/** ?????????? */
export function getTypeName(target:Function, propertyKey:string, container?: ContainerBase):string{
let type = Reflect.getMetadata(EdmType, target) || Reflect.getMetadata(EdmType, target.prototype, propertyKey) || Reflect.getMetadata(EdmType, target.prototype);
let elementType = Reflect.getMetadata(EdmElementType, target) || Reflect.getMetadata(EdmElementType, target.prototype, propertyKey) || Reflect.getMetadata(EdmElementType, target.prototype);
type = (type && type["@odata.type"]) || (type && type.prototype && type.prototype["@odata.type"]) || type;
if (container && container instanceof ContainerBase){
let containerType = container.resolve(type);
if (containerType){
const containerPrototype = Object.getPrototypeOf(container);
let namespace = odata.getNamespace(containerPrototype.constructor, containerType) || (<any>(containerPrototype.constructor || target)).namespace || "Default";
if (containerType.indexOf(".") > 0){
namespace = containerType.slice(0, containerType.lastIndexOf("."));
containerType = containerType.slice(containerType.lastIndexOf(".") + 1);
}
type = namespace + "." + containerType;
}
}
if (typeof type == "string" && type != "Collection" && type.indexOf(".") < 0){
for (let i = 0; i < EdmContainer.length; i++) {
let containerType = EdmContainer[i];
let namespace = (<any>containerType).namespace || (<any>target).namespace || "Default";
let containerTypeName = (<any>containerType).name;
if (containerTypeName == type) {
type = namespace + "." + type;
break;
}
}
}else if (typeof type == "function"){
if (type.__forward__ref__){
type = ((<any>type).namespace || (<any>target).namespace || "Default") + "." + (<any>type)().name;
}else type = ((<any>type).namespace || (<any>target).namespace || "Default") + "." + (<any>type).name;
}
if (typeof elementType == "string" && elementType != "Collection" && elementType.indexOf(".") < 0) {
for (let i = 0; i < EdmContainer.length; i++) {
let containerType = EdmContainer[i];
let namespace = (<any>containerType).namespace || (<any>target).namespace || "Default";
let containerTypeName = (<any>containerType).name;
if (containerTypeName == elementType) {
elementType = namespace + "." + elementType;
break;
}
}
} else if (typeof elementType == "string" && elementType == "Collection") {
// ?
} else if (typeof elementType == "function") {
if (elementType.__forward__ref__){
elementType = ((<any>elementType).namespace || (<any>target).namespace || "Default") + "." + (<any>elementType)().name;
}else elementType = ((<any>elementType).namespace || (<any>target).namespace || "Default") + "." + (<any>elementType).name;
}
return elementType ? type + "(" + elementType + ")" : type;
}
/** ?????????? */
export function getType(target:Function, propertyKey:string, container?: ContainerBase):Function | string{
let type = !propertyKey ? Reflect.getMetadata(EdmType, target) : Reflect.getMetadata(EdmType, target.prototype, propertyKey);
let elementType = !propertyKey ? Reflect.getMetadata(EdmElementType, target) : Reflect.getMetadata(EdmElementType, target.prototype, propertyKey);
let hasEntityType = isEntityType(target, propertyKey) || isComplexType(target, propertyKey);
if (!elementType) elementType = type;
if (elementType && elementType.__forward__ref__) elementType = elementType();
if (type && type.__forward__ref__) type = type();
if (hasEntityType){
if (typeof elementType == "string" && elementType.indexOf(".") < 0) elementType = ((<any>target).namespace || "Default") + "." + elementType;
if (typeof type == "string" && type.indexOf(".") < 0) type = ((<any>target).namespace || "Default") + "." + type;
}
if (typeof elementType == "string"){
if (container && container instanceof ContainerBase){
let containerType = container.resolve(type);
if (containerType){
let namespace = (<any>containerType).namespace || Object.getPrototypeOf(container).constructor.namespace || (<any>target).namespace || "Default";
let containerTypeName = (<any>containerType).name;
type = namespace + "." + containerTypeName;
}
}
for (let i = 0; i < EdmContainer.length; i++){
let containerType = EdmContainer[i];
let namespace = (<any>containerType).namespace || (<any>target).namespace || "Default";
let containerTypeName = (namespace ? namespace + "." : "") + (<any>containerType).name;
if (containerTypeName == elementType){
return containerType;
}
}
}
return elementType;
}
/** Returns true if property is a collection (decorated by Edm.Collection) */
export function isCollection(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmType, target.prototype, propertyKey) == "Collection";
}
/** ?????????? */
export function getProperties(target:Function):string[]{
try{
return Reflect.getOwnMetadata(EdmProperties, target) || [];
}catch(err){
return [];
}
}
/** ?????????? */
export function getParameters(target:Function, targetKey:string):any[]{
let params = [];
let __proto__ = target.prototype;
while (__proto__){
params.push(...(Reflect.getOwnMetadata(EdmParameters, __proto__, targetKey) || []));
__proto__ = Object.getPrototypeOf(__proto__);
}
return params;
}
export function getChildren(target:Function){
return Reflect.getOwnMetadata(EdmChildren, target) || [];
}
/** Edm.Key decorator for describing properties as keys */
export const Key = (function Key(){
return function(target, targetKey){
if (typeof target == "function"){
register(target);
}
let properties:string[] = Reflect.getOwnMetadata(EdmKeyProperties, target) || [];
if (properties.indexOf(targetKey) < 0) properties.push(targetKey);
Reflect.defineMetadata(EdmKeyProperties, properties, target);
Reflect.defineMetadata(EdmKeyProperty, true, target, targetKey);
};
})();
/** Returns true if property is a key (decorated by Edm.Key) */
export function isKey(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmKeyProperty, target.prototype, propertyKey) || false;
}
/** Returns property names that build up the key (names of properties decorated by Edm.Key) */
export function getKeyProperties(target:Function):string[]{
return Reflect.getOwnMetadata(EdmKeyProperties, target) || Reflect.getOwnMetadata(EdmKeyProperties, target.prototype) || [];
}
/**
* Returns escaped strings according to the OData format
* Strings are quoted in single quotes therefore single quotes in strings are converted to two singlequotes.
* Binary values are converted to hexadecimal strings.
*
* @param value Input value of any type
* @param type OData type of the provided value
* @return Escaped string
*/
export async function escape(value:any, type:any, serializer?:Function){
if (typeof serializer == "function") return await serializer(value);
if (typeof value == "undefined" || value == null) return value;
switch (type){
case "Edm.Binary":
return value.toString("hex");
case "Edm.Boolean":
case "Edm.Byte":
case "Edm.Decimal":
case "Edm.Double":
case "Edm.Guid":
case "Edm.Int16":
case "Edm.Int32":
case "Edm.Int64":
case "Edm.SByte":
case "Edm.Single":
return value.toString();
case "Edm.String": return "'" + ("" + value).replace(/'/g, "''") + "'";
default:
return `'${value.toString()}'`;
}
}
/** Edm.Computed decorator for describing computed properties */
export const Computed = (function Computed(){
return function(target, targetKey){
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmComputedProperty, true, target, targetKey);
};
})();
/** Returns true if property is computed (decorated by Edm.Computed) */
export function isComputed(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmComputedProperty, target.prototype, propertyKey) || false;
}
/** Edm.Nullable decorator for describing nullable properties (which can be missing) */
export const Nullable = (function Nullable(){
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.nullable = true;
}else{
existingParameters.push({
name: parameterNames[parameterIndex],
nullable: true
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmNullableProperty, true, target, targetKey);
}
}
})();
/** Returns true if property is nullable (decorated by Edm.Nullable) */
export function isNullable(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmNullableProperty, target.prototype, propertyKey);
}
/** Edm.Required decorator for describing non-nullable properties that must have value (cannot be missing) */
export const Required = (function Required(){
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.nullable = false;
}else{
existingParameters.push({
name: parameterNames[parameterIndex],
nullable: false
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmNullableProperty, false, target, targetKey);
}
}
})();
/** Returns true if property is required (decorated by Edm.Required) */
export function isRequired(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmNullableProperty, target.prototype, propertyKey) == false ? true : false;
}
/** Edm.MaxLength decorator to set property max length */
export function MaxLength(maxLength: number){
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.maxLength = maxLength;
}else{
existingParameters.push({
name: parameterNames[parameterIndex],
maxLength
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmMaxLength, maxLength, target, targetKey);
}
};
}
/** Returns property max length (decorated by Edm.MaxLength) */
export function getMaxLength(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmMaxLength, target.prototype, propertyKey);
}
/** Edm.Precision decorator to set property precision */
export function Precision(precision: number){
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.precision = precision;
}else{
existingParameters.push({
name: parameterNames[parameterIndex],
precision
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmPrecision, precision, target, targetKey);
}
};
}
/** Returns property precision (decorated by Edm.Precision) */
export function getPrecision(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmPrecision, target.prototype, propertyKey);
}
/** Edm.Scale decorator to set property scale */
export function Scale(scale: number){
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.scale = scale;
}else{
existingParameters.push({
name: parameterNames[parameterIndex],
scale
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmScale, scale, target, targetKey);
}
};
}
/** Returns property scale (decorated by Edm.Scale) */
export function getScale(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmScale, target.prototype, propertyKey);
}
/** Edm.Unicode decorator for describing unicode properties */
export const Unicode = (function Unicode(){
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.unicode = true;
}else{
existingParameters.push({
name: parameterNames[parameterIndex],
unicode: true
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmUnicode, true, target, targetKey);
}
};
})();
/** Returns true if property is unicode (decorated by Edm.Unicode) */
export function isUnicode(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmUnicode, target.prototype, propertyKey);
}
/** Edm.SRID decorator to set property SRID */
export function SRID(srid: number){
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.srid = srid;
}else{
existingParameters.push({
name: parameterNames[parameterIndex],
SRID: srid
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmSRID, srid, target, targetKey);
}
};
}
/** Returns property SRID (decorated by Edm.SRID) */
export function getSRID(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmSRID, target.prototype, propertyKey);
}
/** Edm.DefaultValue decorator to set property default value */
export function DefaultValue(value: any){
return function(target, targetKey, parameterIndex?:number){
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.defaultValue = value;
}else{
existingParameters.push({
name: parameterNames[parameterIndex],
defaultValue: value
});
}
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmDefaultValue, value, target, targetKey);
}
};
}
/** Returns property default value (decorated by Edm.DefaultValue) */
export function getDefaultValue(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmDefaultValue, target.prototype, propertyKey);
}
/** Edm.ConcurrencyMode decorator to set property concurrency mode */
export function ConcurrencyMode(mode: string){
return function(target, targetKey){
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmConcurrencyMode, mode, target, targetKey);
};
}
/** Returns property concurrency mode (decorated by Edm.ConcurrencyMode) */
export function getConcurrencyMode(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmConcurrencyMode, target.prototype, propertyKey);
}
function operationDecoratorFactory(type, returnType?){
return function(target, targetKey){
let element = function(){};
(<any>element).target = target;
(<any>element).targetKey = targetKey;
if (typeof returnType == "function"){
try {
Reflect.decorate([returnType()], element.prototype, EdmReturnType);
}
catch (err) {
returnType(element.prototype, EdmReturnType);
}
}
let existingOperations:any[] = Reflect.getOwnMetadata(EdmOperations, target) || [];
existingOperations.push(targetKey);
Reflect.defineMetadata(EdmOperations, existingOperations, target);
Reflect.defineMetadata(type, type, target, targetKey);
Reflect.defineMetadata(EdmReturnType, element, target, targetKey);
};
}
/** Edm.ActionImport decorator for describing unbound actions callable from the service root */
export function ActionImport();
export function ActionImport(returnType?:any);
export function ActionImport(target?:any, targetKey?:string);
export function ActionImport(target?:any, targetKey?:string){
if (arguments.length > 1) return operationDecoratorFactory(EdmAction)(target, targetKey);
else return operationDecoratorFactory(EdmAction, target);
}
/** Edm.Action decorator for describing actions */
export function _Action();
export function _Action(returnType?:any);
export function _Action(target?:any, targetKey?:string);
export function _Action(target?:any, targetKey?:string){
if (arguments.length > 1) return operationDecoratorFactory(EdmAction)(target, targetKey);
else return operationDecoratorFactory(EdmAction, target);
}
export const Action = _Action;
/** ?????????? */
/** Edm.FunctionImport decorator for describing unbound actions callable from the service root */
export function FunctionImport();
export function FunctionImport(returnType?:any);
export function FunctionImport(target?:any, targetKey?:string);
export function FunctionImport(target?:any, targetKey?:string){
if (arguments.length > 1) return operationDecoratorFactory(EdmFunction)(target, targetKey);
else return operationDecoratorFactory(EdmFunction, target);
}
/** ?????????? */
/** Edm.Function decorator for describing actions */
export function _Function();
export function _Function(returnType?:any);
export function _Function(target?:any, targetKey?:string);
export function _Function(target?:any, targetKey?:string){
if (arguments.length > 1) return operationDecoratorFactory(EdmFunction)(target, targetKey);
else return operationDecoratorFactory(EdmFunction, target);
}
export const Function = _Function;
/** ?????????? */
export function getOperations(target:Function):string[]{
return Reflect.getOwnMetadata(EdmOperations, target.prototype) || [];
}
/** ?????????? */
export function getReturnTypeName(target:Function, propertyKey:string, container?:ContainerBase):string{
let returnType = Reflect.getMetadata(EdmReturnType, target.prototype, propertyKey);
return getTypeName(returnType, EdmReturnType, container) || getTypeName(target, propertyKey, container);
}
/** ?????????? */
export function getReturnType(target:Function, propertyKey:string, container?:ContainerBase):Function | string{
let returnType = Reflect.getMetadata(EdmReturnType, target.prototype, propertyKey);
return getType(returnType, EdmReturnType, container) || getType(target, propertyKey, container);
}
/** Returns true if property is a statically callable action (decorated by Edm.ActionImport) */
export function isActionImport(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmAction, target.prototype, propertyKey) || false;
}
/** Returns true if property is a statically callable function (decorated by Edm.FunctionImport) */
export function isFunctionImport(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmFunction, target.prototype, propertyKey) || false;
}
/** Returns true if property is an action (decorated by Edm.Action) */
export function isAction(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmAction, target.prototype, propertyKey) || false;
}
/** Returns true if property is an function (decorated by Edm.Function) */
export function isFunction(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmFunction, target.prototype, propertyKey) || false;
}
/** Edm.ComplexType decorator for describing properties of complex types */
export function ComplexType(type?:Function | string){
return function(target:any, targetKey?:string, parameterIndex?:any){
if (type && (<any>type).__forward__ref__) type = (<any>type)();
let baseType = Object.getPrototypeOf(target).constructor;
if (baseType != Object && getProperties(baseType.prototype).length > 0){
ComplexType()(baseType.prototype);
let children = Reflect.getOwnMetadata(EdmChildren, baseType) || [];
if (children.indexOf(target.constructor) < 0){
children.unshift(target.constructor);
}
Reflect.defineMetadata(EdmChildren, children, baseType);
}
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.type = type;
}else{
existingParameters.push(param = {
name: paramName,
type: type
});
}
Reflect.defineMetadata(EdmComplexType, true, param.type);
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
let desc = Object.getOwnPropertyDescriptor(target, targetKey);
if (targetKey && targetKey != EdmType && ((desc && typeof desc.value != "function") || (!desc && typeof target[targetKey] != "function"))) {
let properties:string[] = Reflect.getOwnMetadata(EdmProperties, target) || [];
if (properties.indexOf(targetKey) < 0) properties.push(targetKey);
Reflect.defineMetadata(EdmProperties, properties, target);
}
if (type) Reflect.defineMetadata(EdmComplexType, true, type);
Reflect.defineMetadata(EdmComplexType, type || true, target, targetKey);
Reflect.defineMetadata(EdmType, type, target, targetKey);
}
};
}
/** Returns true if property is a complex type (decorated by Edm.ComplexType) */
export function isComplexType(target:Function, propertyKey?:string):boolean{
return typeof propertyKey == "string"
? Reflect.hasMetadata(EdmComplexType, target.prototype, propertyKey)
: Reflect.hasMetadata(EdmComplexType, target);
}
/** Edm.MediaEntity decorator for describing media entity properties */
export function MediaEntity(contentType:string){
return Reflect.metadata(EdmMediaEntity, contentType);
}
/** Returns true if property is a media entity (decorated by Edm.MediaEntity) */
export function isMediaEntity(target:Function){
return Reflect.hasMetadata(EdmMediaEntity, target);
}
/** ?????????? */
export function getContentType(target:Function, targetKey?:string){
return Reflect.getMetadata(EdmMediaEntity, target, targetKey);
}
/** Edm.OpenType decorator for describing open type properties */
export const OpenType = (function OpenType(){
return Reflect.metadata(EdmOpenType, true);
})();
/** Returns true if property is a open type (decorated by Edm.OpenType) */
export function isOpenType(target:Function){
return Reflect.hasMetadata(EdmOpenType, target) || false;
}
/** ?????????? */
/** Edm.EntityType decorator for describing entity types */
export function EntityType(type?:Function | string){
return function(target:any, targetKey?:string, parameterIndex?:any){
let baseType = Object.getPrototypeOf(target).constructor;
if (baseType != Object && getProperties(baseType.prototype).length > 0){
EntityType()(baseType.prototype);
let children = Reflect.getOwnMetadata(EdmChildren, baseType) || [];
if (children.indexOf(target.constructor) < 0){
children.unshift(target.constructor);
}
Reflect.defineMetadata(EdmChildren, children, baseType);
}
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.type = type;
}else{
existingParameters.push(param = {
name: paramName,
type: type
});
}
Reflect.defineMetadata(EdmEntityType, true, param.type);
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
let desc = Object.getOwnPropertyDescriptor(target, targetKey);
if (targetKey && targetKey != EdmType && ((desc && typeof desc.value != "function") || (!desc && typeof target[targetKey] != "function"))) {
let properties:string[] = Reflect.getOwnMetadata(EdmProperties, target) || [];
if (properties.indexOf(targetKey) < 0) properties.push(targetKey);
Reflect.defineMetadata(EdmProperties, properties, target);
}
if (type) Reflect.defineMetadata(EdmEntityType, true, type);
Reflect.defineMetadata(EdmEntityType, type || true, target, targetKey);
Reflect.defineMetadata(EdmType, type, target, targetKey);
}
};
}
/** Returns true if property is an EntityType (decorated by Edm.EntityType) */
export function isEntityType(target:Function, propertyKey?:string):boolean{
return typeof propertyKey == "string"
? !Reflect.hasMetadata(EdmComplexType, target.prototype, propertyKey) && Reflect.hasMetadata(EdmEntityType, target.prototype, propertyKey)
: !Reflect.hasMetadata(EdmComplexType, target) && Reflect.hasMetadata(EdmEntityType, target);
}
export function Flags(target, targetKey){
Reflect.defineMetadata(EdmFlags, true, target, targetKey);
}
export function isFlags(target:Function, propertyKey:string):boolean{
return Reflect.getMetadata(EdmFlags, target.prototype, propertyKey);
}
export function EnumType(type:any):Decorator{
return function(target:any, targetKey?:string, parameterIndex?:number):any{
let baseType = Object.getPrototypeOf(target).constructor;
if (baseType != Object && getProperties(baseType.prototype).length > 0){
EntityType()(baseType.prototype);
let children = Reflect.getOwnMetadata(EdmChildren, baseType) || [];
if (children.indexOf(target.constructor) < 0){
children.unshift(target.constructor);
}
Reflect.defineMetadata(EdmChildren, children, baseType);
}
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.type = type;
}else{
existingParameters.push(param = {
name: paramName,
type: type
});
}
Reflect.defineMetadata(EdmEnumType, true, param.type);
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
let desc = Object.getOwnPropertyDescriptor(target, targetKey);
if (targetKey && targetKey != EdmType && ((desc && typeof desc.value != "function") || (!desc && typeof target[targetKey] != "function"))) {
let properties:string[] = Reflect.getOwnMetadata(EdmProperties, target) || [];
if (properties.indexOf(targetKey) < 0) properties.push(targetKey);
Reflect.defineMetadata(EdmProperties, properties, target);
}
Reflect.defineMetadata(EdmEnumType, true, target, targetKey);
Reflect.defineMetadata(EdmType, type, target, targetKey);
}
}
}
export function isEnumType(target:any, propertyKey?:string):boolean{
return typeof propertyKey == "string"
? Reflect.hasMetadata(EdmEnumType, target.prototype, propertyKey)
: Reflect.hasMetadata(EdmEnumType, target);
}
export function TypeDefinition(type){
return function(target, targetKey?, parameterIndex?){
let baseType = Object.getPrototypeOf(target).constructor;
if (baseType != Object && getProperties(baseType.prototype).length > 0){
EntityType()(baseType.prototype);
let children = Reflect.getOwnMetadata(EdmChildren, baseType) || [];
if (children.indexOf(target.constructor) < 0){
children.unshift(target.constructor);
}
Reflect.defineMetadata(EdmChildren, children, baseType);
}
if (typeof parameterIndex == "number"){
let parameterNames = getFunctionParameters(target, targetKey);
let existingParameters: any[] = Reflect.getOwnMetadata(EdmParameters, target, targetKey) || [];
let paramName = parameterNames[parameterIndex];
let param:any = existingParameters.filter(p => p.name == paramName)[0];
if (param){
param.type = type;
}else{
existingParameters.push(param = {
name: paramName,
type: type
});
}
Reflect.defineMetadata(EdmTypeDefinition, true, param.type);
Reflect.defineMetadata(EdmParameters, existingParameters, target, targetKey);
}else{
if (typeof target == "function"){
register(target);
}
let desc = Object.getOwnPropertyDescriptor(target, targetKey);
if (targetKey && targetKey != EdmType && ((desc && typeof desc.value != "function") || (!desc && typeof target[targetKey] != "function"))) {
let properties:string[] = Reflect.getOwnMetadata(EdmProperties, target) || [];
if (properties.indexOf(targetKey) < 0) properties.push(targetKey);
Reflect.defineMetadata(EdmProperties, properties, target);
}
Reflect.defineMetadata(EdmTypeDefinition, true, target, targetKey);
Reflect.defineMetadata(EdmType, type, target, targetKey);
}
};
}
export function isTypeDefinition(target:any, propertyKey?:string):boolean{
return typeof propertyKey == "string"
? Reflect.hasMetadata(EdmTypeDefinition, target.prototype, propertyKey)
: Reflect.hasMetadata(EdmTypeDefinition, target);
}
/** ?????????? */
export function register(type:Function){
if (EdmContainer.indexOf(type) < 0) EdmContainer.push(type);
}
/** ?????????? */
export function Convert(converter:Function){
return function(target, targetKey){
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmConverter, converter, target, targetKey);
};
}
/** ?????????? */
export function getConverter(target:Function, propertyKey:string):Function{
return Reflect.getMetadata(EdmConverter, target.prototype, propertyKey);
}
/** ?????????? */
export function Serialize(converter:Function){
return function(target, targetKey){
if (typeof target == "function"){
register(target);
}
Reflect.defineMetadata(EdmSerializer, converter, target, targetKe