beetle.js
Version:
Beetle is a data manager for Javascript. The goal is to be able to work with data as easy as Entity Framework and LINQ.
1,078 lines (1,007 loc) • 125 kB
TypeScript
/**
* @module
* Beetle module.
*/
declare module beetle {
/** Promise abstraction. We can change Ajax Provider result via this type. */
type AjaxCall<T> = PromiseLike<T>;
/** Beetle interfaces. Some polyfill, other duck typing signatures. */
namespace interfaces {
/** Key-value pair collection. */
interface Dictionary<T> {
[key: string]: T;
}
/** GroupBy produces this after key selection and pass to value selection. */
interface Grouping<T, TKey> extends Array<T> {
Key: TKey;
}
/** GroupBy without value selection produces this interface as result. */
interface Grouped<T, TKey> {
Key: TKey;
/** Grouped items. */
Items: Array<T>;
}
/** When a trackable array change, event args has this properties. */
interface ArrayChangeEventArgs {
added: Array<any>;
removed: Array<any>;
}
/** When a validation state change, event args has this properties. */
interface ValidationErrorsChangedEventArgs {
/** Current errors. */
errors: ValidationError[];
/** Newly added validation errors. */
added: ValidationError[];
/** Newly fixed validation errors. */
removed: ValidationError[];
}
/** When state change for an entity, event args has this properties. */
interface EntityStateChangedEventArgs {
entity: IEntity;
oldState: enums.entityStates;
newState: enums.entityStates;
/** Indicates if entity was in Unchanged state before. */
newChanged: boolean;
}
/** When a property value change for an entity, event args has this properties. */
interface PropertyChangedEventArgs {
entity: IEntity;
property: Property;
oldValue: any;
newValue: any;
}
/** When an array member of an entity is changed, event args has this properties (for internal use only). */
interface ArrayChangedEventArgs {
entity: IEntity;
property: Property;
items: Array<IEntity>;
removedItems: Array<IEntity>;
addedItems: Array<IEntity>;
}
/** When an entity state is changed or there is no more changed entity, an event is fired with this properties. */
interface HasChangesChangedEventArgs {
/** Indicates if entity manager has any changes. */
hasChanges: boolean;
}
/** Before a query is executed, an event is fired with this properties. */
interface QueryExecutingEventArgs {
manager: core.EntityManager;
/** Query can be changed by setting this value. */
query: querying.EntityQuery<any>;
/** Query options can be changed by setting this value. */
options: ManagerQueryOptions;
}
/** After a query executed, an event is fired with this properties. */
interface QueryExecutedEventArgs extends QueryExecutingEventArgs {
result: any;
}
/** Before and after manager saves changes, an event is fired with this properties. */
interface SaveEventArgs {
manager: core.EntityManager;
changes: IEntity[];
options: ManagerSaveOptions;
}
/** This properties are used for global messages (i.e. warnings, infos). */
interface MessageEventArgs {
message: string;
query: Query<any>;
options: ManagerQueryOptions;
}
/** Beetle converts plural navigation properties to TrackableArrays to track changes on collections. */
interface TrackableArray<T> extends Array<T> {
object: any;
property: string;
/** Called after a change made on the array. */
after: (o: any, s: string, a: TrackableArray<T>, removed: T[], added: T[]) => void;
changing: Event<ArrayChangeEventArgs>;
changed: Event<ArrayChangeEventArgs>;
/** Adding remove capability to array. */
remove(...T): T[];
load(expands: string[], resourceName: string, options: ManagerQueryOptions,
successCallback?: (items: T[]) => void, errorCallback?: (e: AjaxError) => void): AjaxCall<QueryResultArray<T>>;
}
/** All validator objects have these properties. */
interface Validator {
/** Validator name. */
name: string;
/** Validation error message. Arguments might be used when formatting the message. */
message: string;
/** Validation arguments. */
args?: any;
toString(): string;
}
/** Validates the value of the property. */
interface PropertyValidator extends Validator {
validate(value: any, entity: IEntity): string;
}
/** Validates all values of the entity. */
interface EntityValidator extends Validator {
validate(entity: IEntity): string;
}
/** Property validators produces error messages compatible with this interface. */
interface ValidationError {
message: string;
entity: IEntity;
/** If validation error is created for a property, this will be available. */
property?: string;
/** If validation error is created for a property, this will be available. */
value?: any;
}
/** Entity validators produces error messages compatible with this interface. */
interface EntityValidationError {
entity: IEntity;
validationErrors: ValidationError[];
}
/** Manager keeps tracks of all error messages using this interface. */
interface ManagerValidationError extends Error {
entities: IEntity[];
entitiesInError: EntityValidationError[];
manager: core.EntityManager;
}
/** All data types share this common structure. */
interface DataTypeBase {
name: string;
/** Complex Type are based on Entity Framework's. */
isComplex: boolean;
toString(): string;
/** Returns network transferable value for the data type. */
getRawValue(value: any): string;
/** Checks if given value is valid for this type. */
isValid(value: any): boolean;
/** Converts given value to OData format. */
toODataValue(value: any): string;
/** Converts given value to Beetle format. */
toBeetleValue(value: any): string;
/** Gets default value for type. */
defaultValue(): any;
/** Generates a new unique value for this type. Used for auto-incremented values. */
autoValue(): any;
/** Tries to convert given value to this type. */
handle(value: any): any;
}
/** Base type for all metadata types. */
interface MetadataPart {
name: string;
displayName?: string;
toString(): string;
validate(entity: IEntity): ValidationError[];
}
/** Shared interface for DataProperty and NavigationProperty. */
interface Property extends MetadataPart {
owner: EntityType;
/** Complex Type are based on Entity Framework's. */
isComplex: boolean;
validators: PropertyValidator[];
/** Adds validation for the property dynamically. */
addValidation(name: string, func: (value: any, entity: IEntity) => string, message: string, args?: any);
}
/** Primitive member metadata. */
interface DataProperty extends Property {
dataType: DataTypeBase;
isNullable: boolean;
/** Indicates if this property is one of the primary keys. */
isKeyPart: boolean;
/** Auto generation strategy for the property (Identity, Computed, None). */
generationPattern?: enums.generationPattern;
defaultValue: any;
/** When true, this property will be used together with keys for updates. */
useForConcurrency: boolean;
/** Navigation properties based on this property. */
relatedNavigationProperties: NavigationProperty[];
isEnum: boolean;
isValid(value: any): boolean;
handle(value: any): any;
getDefaultValue(): any;
}
/** Relational member metadata. */
interface NavigationProperty extends Property {
entityTypeName: string;
entityType: EntityType;
isScalar: boolean;
/** To be able to match two way relations. Same relations have same association name for both side. */
associationName: string;
/** Indicates if deleting this related entity causes cascade deletion. */
cascadeDelete: boolean;
foreignKeyNames: string[];
foreignKeys: DataProperty[];
/** After this property changed, owner will also be marked as modified. */
triggerOwnerModify: boolean;
/** Other side of the navigation. */
inverse?: NavigationProperty;
/** Checks if given value can be assigned to this property. If not throws an error. */
checkAssign(entity: IEntity);
}
/** Entity type metadata. */
interface EntityType extends MetadataPart {
/** Entity type's short name (i.e. 'Customer'). */
shortName: string;
keyNames: string[];
baseTypeName: string;
/** Entity set name. If this Entity is derived from another, set name is the root entity's name. */
setName: string;
/** Entity set type name. If this Entity is derived from another, set type is the root entity's type. */
setTypeName: string;
metadataManager: metadata.MetadataManager;
/** Automatically filled EntityType will be used for unknown entities. */
hasMetadata: boolean;
/** Properties that are not in metadata but available on the entity. */
properties: string[];
/** Complex Type are based on Entity Framework's. */
isComplexType: boolean;
dataProperties: DataProperty[];
navigationProperties: NavigationProperty[];
keys: DataProperty[];
/** Lowest entity type in the inheritance hierarchy. */
floorType: EntityType;
baseType: EntityType;
validators: EntityValidator[];
/** Constructor function. Called right after the entity object is generated. */
constructor: (entity: RawEntity) => void;
/** Initializer function. Called after entity started to being tracked (properties converted to observable). */
initializer: (entity: IEntity) => void;
/** Parses given string and finds property, looks recursively to navigation properties when needed. */
getProperty(propertyPath: string): Property;
/**
* Register constructor and initializer (optional) for the type.
* @param constructor Constructor function. Called right after the entity object is generated.
* @param initializer Initializer function. Called after entity started to being tracked (properties converted to observable).
*/
registerCtor(ctor?: (entity: RawEntity) => void, initializer?: (entity: IEntity) => void);
/**
* Creates an entity for this type.
* @param initialValues Entity initial values.
* @returns Entity with observable properties.
*/
createEntity(initialValues: Object): IEntity;
createRawEntity(initialValues: Object): RawEntity;
/** Checks if this type can be set with given type. */
isAssignableWith(otherType: EntityType): boolean;
/** Checks if this type can be set to given type. */
isAssignableTo(otherType: EntityType): boolean;
/** Add new validation method to entity type. */
addValidation(name: string, func: (entity: IEntity) => string, message: string, args?: any);
}
/** Beetle uses this interface internally. */
interface InternalSet<T extends IEntity> {
toString(): string;
getEntity(key: string): T;
getEntities(): T[];
}
/** Server and array query shared interface */
interface Query<T> {
/**
* Indicates wheter or not include total count in result.
* @param isEnabled When true, total count will be included in result. Default value: true.
*/
inlineCount(isEnabled?: boolean): Query<T>;
/**
* If model has inheritance, when querying base type we can tell which derived type we want to load.
* @param type Derived type name.
*/
ofType<TResult extends T>(type: string | (new (...args: any[]) => TResult)): Query<TResult>;
/**
* Filter query based on given expression.
* @param predicate A function to test each element for a condition (can be string expression).
* @param varContext Variable context for the expression.
*/
where(predicate: string | ((entity: T) => boolean), varContext?: any): Query<T>;
/**
* Sorts results based on given properties.
* @param keySelector The properties to sort by.
*/
orderBy(keySelector?: string | ((entity: T) => any)): Query<T>;
/**
* Sorts results based on given properties descendingly.
* @param keySelector The properties to sort by.
*/
orderByDesc(keySelector?: string | ((entity: T) => any)): Query<T>;
/** Selects only given properties using projection. */
select<TResult>(selector: string | string[] | ((entity: T) => TResult)): Query<TResult>;
select<TResult>(...selectors: string[]): Query<TResult>;
select(selector: string | string[] | ((entity: T) => any)): Query<any>;
select(...selectors: string[]): Query<any>;
/**
* Skips given count records and start reading.
* @param count The number of items to skip.
*/
skip(count: number): Query<T>;
/**
* Takes only given count records.
* @param count The number of items to take.
*/
take(count: number): Query<T>;
/**
* Takes only given count records .
* @param count The number of items to take.
*/
top(count: number): Query<T>;
/**
* Groups query by given keys (projects them into a new type) and returns values (projecting into new type).
* @param keySelector A projection to extract the key for each element.
* @param valueSelector A projection to create a result value from each group.
*/
groupBy<TKey, TResult>(keySelector: (entity: T) => TKey, valueSelector: (group: Grouping<T, TKey>) => TResult): Query<TResult>;
groupBy<TKey>(keySelector: (entity: T) => TKey): Query<Grouped<T, TKey>>;
groupBy<TResult>(keySelector: string | ((entity: T) => any), valueSelector: string | ((group: Grouping<T, any>) => TResult)): Query<TResult>;
groupBy(keySelector: string | ((entity: T) => any)): Query<Grouped<T, any>>;
groupBy(keySelector: string | ((entity: T) => any), valueSelector: string | ((group: Grouping<T, any>) => any)): Query<any>;
/**
* Gets only distinct items, when selector is given it will be used as comparer (project and compares projected objects).
* @param selector A projection to extract the key for each element.
*/
distinct(): Query<T>;
distinct<TResult>(selector: string | ((entity: T) => TResult)): Query<TResult>;
distinct(selector: string | ((entity: T) => any)): Query<any>;
/** Reverse the collection. */
reverse(): Query<T>;
/**
* Selects given collection property for each element and returns all in a new array.
* @param properties Properties or PropertyPaths to select (project).
*/
selectMany<TResult>(selector: string | ((entity: T) => Array<TResult>)): Query<TResult>;
selectMany(selector: string | ((entity: T) => any)): Query<any>;
/**
* Gets all the items after first succesful predicate.
* @param predicate A function to test each element for a condition (can be string expression).
* @param varContext Variable context for the expression.
*/
skipWhile(predicate: string | ((entity: T) => boolean), varContext?: any): Query<T>;
/**
* Gets all the items before first succesful predicate.
* @param predicate A function to test each element for a condition (can be string expression).
* @param varContext Variable context for the expression.
*/
takeWhile(predicate: string | ((entity: T) => boolean), varContext?: any): Query<T>;
/** Executes this query. */
then(successCallback: (result: beetle.interfaces.QueryResultArray<T>) => void, errorCallback?: (e: AjaxError) => void, options?: any): AjaxCall<beetle.interfaces.QueryResultArray<T>>;
/** Sets options to be used at execution. */
withOptions(options: any): Query<T>;
}
/** After an executer function called on a server query, this interface is returned. */
interface ClosedQueryable<T, TOptions> {
/** Executes this query using related entity manager. */
execute(options?: TOptions, successCallback?: (result: T) => void, errorCallback?: (e: AjaxError) => void): AjaxCall<T>;
/** Executes this query using related entity manager. */
execute<TResult>(options?: TOptions, successCallback?: (result: TResult) => void, errorCallback?: (e: AjaxError) => void): AjaxCall<TResult>;
/** Executes this query using related entity manager. Shortcut for 'execute'. */
x(options?: TOptions, successCallback?: (result: T) => void, errorCallback?: (e: AjaxError) => void): AjaxCall<T>;
/** Executes this query using related entity manager. Shortcut for 'execute'. */
x<TResult>(options?: TOptions, successCallback?: (result: TResult) => void, errorCallback?: (e: AjaxError) => void): AjaxCall<TResult>;
/** Executes this query using related entity manager. Shortcut for 'execute(...).then'. */
then(successCallback: (result: T) => void, errorCallback?: (e: AjaxError) => void, options?: TOptions): AjaxCall<T>;
}
/** Server query parameters are kept with this structure. */
interface EntityQueryParameter {
name: string;
value: any;
}
/** When enabled these extra information will be attached to server results. */
interface QueryResultExtra {
/** Server can send custom data using this property (carried using a http header). */
userData?: string;
/** Http header getter function. */
headerGetter: (name: string) => string;
/** When ajax provider exposes xhr, this property will be available. */
xhr?: any;
}
/** Server array results have these extra properties (when enabled). */
interface QueryResultArray<T> extends Array<T> {
/** Extra information about query (when enabled). */
$extra?: QueryResultExtra;
/** Inline count (calculated excluding skip-take from query). */
$inlineCount?: number;
}
/** Beetle uses some minified objects to reduce package size. */
interface PropertyValue {
/** Property name. */
p: string;
/** Property value. */
v: any;
}
/** This interface is used to track complex types' owners. */
interface OwnerValue {
owner: IEntity;
property: Property;
}
/** Entity tracker interface. Change tracking is made using this structure. */
interface Tracker {
entity: IEntity;
entityType: EntityType;
entityState: enums.entityStates;
/** When true, entity will be updated -even there is no modified property. */
forceUpdate: boolean;
/** Initial values of changed properties. */
originalValues: PropertyValue[];
/** Previously accepted values of changed properties. */
changedValues: PropertyValue[];
manager: core.EntityManager;
owners: OwnerValue[];
/** Validation errors for the entity. */
validationErrors: ValidationError[];
/** Notify when a valid state changed for the entity. */
validationErrorsChanged: core.Event<ValidationErrorsChangedEventArgs>;
/** Notify when a state changed for the entity. */
entityStateChanged: core.Event<EntityStateChangedEventArgs>;
/** Notify when a property changed for the entity. */
propertyChanged: core.Event<PropertyChangedEventArgs>;
/** Notify when an array property changed for the entity. */
arrayChanged: core.Event<ArrayChangedEventArgs>;
/** Entity's primary key value (multiple keys will be joined with '-'). */
key: string;
toString(): string;
isChanged(): boolean;
/** Clears all navigations and marks entity as Deleted. */
delete();
/** Clears all navigations and detached entity from its manager. */
detach();
/** Marks entity as Added. */
toAdded();
/** Marks entity as Modified. */
toModified();
/** Marks entity as Deleted. */
toDeleted();
/** Marks entity as Unchanged. */
toUnchanged();
/** Marks entity as Detached. */
toDetached();
/** Resets all changes to initial values. */
rejectChanges();
/** Resets all changes to last accepted values. */
undoChanges();
/** Accept all changes. */
acceptChanges();
/** Gets internal value of the property from observable entity. */
getValue(property: string);
/** Sets internal value of the property of observable entity. */
setValue(property: string, value: any);
/** Gets original value for property. */
getOriginalValue(property: string): any;
/**
* Get foreign key value for this navigation property.
* @returns Comma separated foreign keys.
*/
foreignKey(navProperty: NavigationProperty): string;
/** Creates a query that can load this navigation property. */
createLoadQuery<T extends IEntity>(navPropName: string, resourceName: string): querying.EntityQuery<T>;
/** Loads the navigation property using EntityManager. */
loadNavigationProperty(navPropName: string, expands: string[], resourceName: string, options?: ManagerQueryOptions,
successCallback?: (result: any) => void, errorCallback?: (e: AjaxError) => void): AjaxCall<any>;
/** Validates entity against metadata data annotation validations. */
validate(): ValidationError[];
/**
* Creates a raw javascript object representing this entity.
* @param includeNavigations When true, all navigation values will be included (recursively, so be careful it can cause stack overflow).
*/
toRaw(includeNavigations?: boolean): any;
}
/** Beetle uses some minified objects to reduce package size. */
interface TrackInfo {
/** Type name. */
t: string;
/** Entity state name. */
s: string;
/** Save index in the save array. */
i: number;
/** When true, entity will be updated -even there is no modified property. */
f?: boolean;
/** Original values object. */
o?: any;
}
/** Exported entity tracking information are kept with this structure. It's like basic version of EntityTracker. */
interface ExportEntity {
/** Entity tracking information. */
$t: TrackInfo;
}
/** Changes are merged in a package to use in server request. */
interface SavePackage {
/** These entities will be sent to server for persistence. */
entities: ExportEntity[];
/** when true, each entity will be updated -even there is no modified property. */
forceUpdate?: boolean;
/** We can send custom data to server using this property (carried using a http header). */
userData?: string;
}
/**
* Server side generated value is carried back to client in this structure.
* Index is the entity's index in the save package.
*/
interface GeneratedValue {
/** Entity's save index in the save array. */
Index: number;
/** Server side changed property name. */
Property: string;
/** Server side assigned value. */
Value: any;
}
/** Server sends back this structure after a succesful save. */
interface SaveResult {
/** Affected record count after the save. */
AffectedCount: number;
/** Server side generated changes on existing entities. */
GeneratedValues: GeneratedValue[];
/** Server side generated entities, will be merged to local cache. */
GeneratedEntities: IEntity[];
/** Server can send custom data using this property (carried using a http header). */
UserData: string;
}
/** Entities read from Beetle server has these properties (before converting to observables). */
interface RawEntity {
/** Entity type's full name (i.e. 'Package.Model.Customer'). */
$type: string;
/** Extra information about query (when enabled). */
$extra?: QueryResultExtra;
}
/** Internationalization members. */
interface I18N {
argCountMismatch: string;
arrayEmpty: string;
arrayNotSingle: string;
arrayNotSingleOrEmpty: string;
assignError: string;
assignErrorNotEntity: string;
autoGeneratedCannotBeModified: string;
beetleQueryChosenMultiTyped: string;
beetleQueryChosenPost: string;
beetleQueryNotSupported: string;
cannotBeEmptyString: string;
cannotCheckInstanceOnNull: string;
cannotDetachComplexTypeWithOwners: string;
compareError: string;
complexCannotBeNull: string;
couldNotLoadMetadata: string;
couldNotLocateNavFixer: string;
couldNotLocatePromiseProvider: string;
couldNotParseToken: string;
countDiffCantBeCalculatedForGrouped: string;
dataPropertyAlreadyExists: string;
entityAlreadyBeingTracked: string;
entityNotBeingTracked: string;
executionBothNotAllowedForNoTracking: string;
expressionCouldNotBeFound: string;
functionNeedsAlias: string;
functionNotSupportedForOData: string;
instanceError: string;
invalidArguments: string;
invalidDefaultValue: string;
invalidEnumValue: string;
invalidExpression: string;
invalidPropertyAlias: string;
invalidStatement: string;
invalidValue: string;
managerInvalidArgs: string;
maxLenError: string;
maxPrecisionError: string;
mergeStateError: string;
minLenError: string;
noMetadataEntityQuery: string;
noMetadataRegisterCtor: string;
noOpenGroup: string;
notFoundInMetadata: string;
notImplemented: string;
notNullable: string;
oDataNotSupportMultiTyped: string;
onlyManagerCreatedCanBeExecuted: string;
onlyManagerCreatedCanAcceptEntityShortName: string;
pendingChanges: string;
pluralNeedsInverse: string;
projectionsMustHaveAlias: string;
propertyNotFound: string;
queryClosed: string;
rangeError: string;
requiredError: string;
sameKeyExists: string;
sameKeyOnDifferentTypesError: string;
settingArrayNotAllowed: string;
stringLengthError: string;
syncNotSupported: string;
twoEndCascadeDeleteNotAllowed: string;
typeError: string;
typeMismatch: string;
typeRequiredForLocalQueries: string;
unclosedQuote: string;
unclosedToken: string;
unexpectedProperty: string;
unexpectedToken: string;
unknownDataType: string;
unknownExpression: string;
unknownFunction: string;
unknownParameter: string;
unknownValidator: string;
unsoppertedState: string;
validationErrors: string;
validationFailed: string;
valueCannotBeNull: string;
operatorNotSupportedForOData: string;
}
}
/** Beetle entities have these properties (after converting to observables). */
interface IEntity {
$tracker: interfaces.Tracker;
/** Extra information about query (when enabled). */
$extra?: interfaces.QueryResultExtra;
}
/** Entity related options. */
interface EntityOptions {
merge?: enums.mergeStrategy;
state?: enums.entityStates;
/** Automatically fix scalar navigations using foreign keys (fast). */
autoFixScalar?: boolean;
/** Automatically fix plural navigations looking for foreign references (slow). */
autoFixPlural?: boolean;
}
/** Data service query options. */
interface ServiceQueryOptions {
/** When true, all values will be handled by their value (i.e. some type changes, string->Date). */
handleUnmappedProperties?: boolean;
/** Use request body for beetle parameters when making request. Useful for large queries (some web servers can't process very large query strings). */
useBody?: boolean;
/** Web method to use (i.e. PUT, POST, GET etc..). */
method?: string;
/** The type of data that you're expecting back from the server. */
dataType?: string;
/** Type of data you're sending. */
contentType?: string;
/** Use async for ajax operation. Default is true. Be careful, some AjaxProviders does not support sync. */
async?: boolean;
/** Ajax request timeout. */
timeout?: number;
/** AjaxProvider extra settings. These will be mixed to ajax options. */
extra?: any;
/** Server uri to join with base address. To override existing resource address. */
uri?: string;
/** Request headers. */
headers?: any;
/** When enabled, if AjaxProvider exposes xhr, this will be attached to the results (via $extra). */
includeXhr?: boolean;
/** When enabled, response header getter function will be attached to the results (via $extra). */
includeHeaderGetter?: boolean;
}
/** Entity manager query options. */
interface ManagerQueryOptions extends ServiceQueryOptions {
/** Merge strategy to use when attaching an entity to local cache. */
merge?: enums.mergeStrategy;
/** Executing strategy for the query. */
execution?: enums.executionStrategy;
/** Automatically fix scalar navigations using foreign keys (fast). */
autoFixScalar?: boolean;
/** Automatically fix plural navigations looking for foreign references (slow). */
autoFixPlural?: boolean;
/** Variable context for the query. */
varContext?: any;
/** Even service supports another query format (like OData), use Beetle format instead for this query. */
useBeetleQueryStrings?: boolean;
}
/** Data service constructor options. */
interface ServiceOptions {
/** Ajax request timeout. */
ajaxTimeout?: number;
/** The type of data that you're expecting back from the server. */
dataType?: string;
/** Type of data you're sending. */
contentType?: string;
/** Creates properties for entity sets on the manager. */
registerMetadataTypes?: boolean;
/** Ajax provider instance. */
ajaxProvider?: baseTypes.AjaxProviderBase;
/** Serializer service instance. */
serializationService?: baseTypes.SerializationServiceBase;
}
/** Entity manager constructor options. */
interface ManagerOptions extends ServiceOptions {
/** Automatically fix scalar navigations using foreign keys (fast). */
autoFixScalar?: boolean;
/** Automatically fix plural navigations looking for foreign references (slow). */
autoFixPlural?: boolean;
/** Every merged entity will be validated. */
validateOnMerge?: boolean;
/** Validates entities before save. */
validateOnSave?: boolean;
/** Every change triggers a re-validation. Effects can be seen on EntityManager's validationErrors property. */
liveValidate?: boolean;
/** When true, all values will be handled by their value (i.e. some type changes, string->Date). */
handleUnmappedProperties?: boolean;
/** When true, entity will be updated -even there is no modified property. */
forceUpdate?: boolean;
/** Use async for ajax operation. Default is true. Be careful, some AjaxProviders does not support sync. */
workAsync?: boolean;
/** When true, while creating save package; for modified only changed and key properties, for deleted only key properties will be used. */
minimizePackage?: boolean;
/** Promise provider instance. */
promiseProvider?: baseTypes.PromiseProviderBase;
}
/**
* Entity exporting options.
* Beetle can exclude unchanged properties for modified entities to reduce package size (server side needs to support this).
*/
interface ExportOptions {
/** When true, while creating save package, for modified only changed and key properties, for deleted only key properties will be used. */
minimizePackage?: boolean;
}
/** Options used when creating a save package. */
interface PackageOptions extends ExportOptions {
/** Validates entities before save. */
validateOnSave?: boolean;
/** We can send custom data to server using this property (carried using a http header). */
userData?: string;
/** when true, each entity will be updated -even there is no modified property. */
forceUpdate?: boolean;
}
/** Data service options for save operation. */
interface ServiceSaveOptions {
/** Web method to use (i.e. PUT, POST, GET etc..). */
method?: string;
/** The type of data that you're expecting back from the server. */
dataType?: string;
/** Type of data you're sending. */
contentType?: string;
/** Use async for ajax operation. Default is true. Be careful, some AjaxProviders does not support sync. */
async?: boolean;
/** Ajax request timeout. */
timeout?: number;
/** AjaxProvider extra settings. These will be mixed to ajax options. */
extra?: any;
/** Server uri to join with base address. To override existing resource address. */
uri?: string;
/** To override existing save address (default is 'SaveChanges'). */
saveAction?: string;
/** Request headers. */
headers?: any;
/** When enabled, if AjaxProvider exposes xhr, this will be attached to the results (via $extra). */
includeXhr?: boolean;
/** When enabled, response header getter function will be attached to the results (via $extra). */
includeHeaderGetter?: boolean;
}
/**
* General save options.
* When extra entities are returned from save operation (via GeneratedEntities property), this options are used for merging with local cache.
*/
interface PackageSaveOptions extends PackageOptions, ServiceSaveOptions {
/** Automatically fix scalar navigations using foreign keys (fast). */
autoFixScalar?: boolean;
/** Automatically fix plural navigations looking for foreign references (slow). */
autoFixPlural?: boolean;
}
/** Entity manager save options, all save options are together. */
interface ManagerSaveOptions extends PackageSaveOptions {
entities?: IEntity[];
}
/** Beetle passes this interface to ObservableProviders for them to make entity observable. For advanced use only. */
interface ObservableProviderCallbackOptions {
propertyChange: (entity: any, property: string, accessor: (v?: any) => any, newValue: any) => void;
arrayChange: (entity: any, property: string, items: Array<any>, removed: Array<any>, added: Array<any>) => void;
dataPropertyChange: (entity: any, property: interfaces.DataProperty, accessor: (v?: any) => any, newValue) => void;
scalarNavigationPropertyChange: (entity: any, property: interfaces.NavigationProperty, accessor: (v?: any) => any, newValue: any) => void;
pluralNavigationPropertyChange: (entity: any, property: interfaces.NavigationProperty, items: Array<any>, removed: Array<any>, added: Array<any>) => void;
arraySet: (entity: any, property: string, oldArray: Array<any>, newArray: Array<any>) => void;
}
/**
* Ajax operation error structure.
* Some properties are not available for some libraries (like angular).
* Error callback objects might contain library dependent members.
*/
interface AjaxError extends Error {
/** Error status code (i.e. 400, 500). */
status: number;
/** Ajax provider specific extra information about error. */
detail: any;
/** Entity manager the query originated. */
manager: core.EntityManager;
/** The query that caused the error. */
query: querying.EntityQuery<any>;
/** Ajax provider's error object (when available). */
error?: any;
/** Xhr object used in the request (available only if AjaxProvider exposes xhr). */
xhr?: XMLHttpRequest;
}
/** Helper functions. We are trying not to use ECMA 5, so we polyfill some methods. */
namespace helper {
/**
* Creates an assert instance to work with, a shortcut.
* @example
* helper.assertPrm(prm, 'prm').isArray().check()
* @param value The value of parameter.
* @param name The name of the parameter.
*/
function assertPrm(obj1: any, name: string): Assert;
/**
* Combines first object's properties with second object's properties on a new object.
* @param obj1 The first object.
* @param obj2 The second object.
* @returns New object containing all properties from both objects.
*/
function combine(obj1: Object, obj2: Object): any;
/**
* Extends obj1 with obj2's properties.
* @param obj1 The main object.
* @param obj2 Object to extend with.
* @returns obj1 is returned.
*/
function extend(obj1: Object, obj2: Object): any;
/**
* Checks if the given two are equal. if parameters are both objects, recursively controls their properties too.
* @param obj1 The first object.
* @param obj2 The second object.
* @returns True when two objects are equal, otherwise false.
*/
function objEquals(obj1: Object, obj2: Object): boolean;
/**
* Format string using given arguments. %1 and {1} format can be used for placeholders.
* @param string String to format.
* @param params Values to replace.
*/
function formatString(str: string, ...params: string[]): string;
/**
* Finds the index of the given item in the array.
* @param array Array to search.
* @param item Item to find.
* @param index Start index.
* @returns Found index. If the item could not be found returns '-1'.
*/
function indexOf(array: any[], item, start?: number): number;
/**
* Calls given callback with item and current index parameters for each item in the array.
* @param array Array to iterate.
* @param callback Method to call for each item.
*/
function forEach(array: any[], callback: (item, idx) => void);
/**
* Iterate objects properties and skips ones starting with '$'.
* @param object Object to iterate.
* @param callback Method to call for each property.
*/
function forEachProperty(object: any, callback: (propName: string, value: any) => void);
/**
* Finds given item in the array.
* When property is given, looks item's property value, otherwise compares item's itself.
* @param array Array to search.
* @param value Value to find.
* @param property Property to look for the value.
* @returns When value is found; if property is provided, the array item containing the given value, otherwise value itself. When not found, null.
*/
function findInArray(array: any[], value, property?: string);
/**
* Copies array items that match the given conditions to another array and returns the new array.
* @param array The array to filter.
* @param predicate A function to test each element for a condition (can be string expression).
* @returns New array with filtered items.
*/
function filterArray<T>(array: T[], predicate: (item: T) => boolean): T[];
/**
* Removes the item from given array.
* @param array The array to remove item from.
* @param item Item to remove.
* @param property Property to look for the value.
* @returns Removed item indexes.
*/
function removeFromArray(array: any[], item, property?: string): number;
/**
* Creates a new array with the results of calling the provided function on every element in the given array.
* @param array The array to map.
* @param callback Function that produces new element.
* @returns New array with mapped values.
*/
function mapArray<T>(array: any[], callback: (item, index) => T): T[];
/**
* Creates a GUID string with "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" format.
* @returns Newly generated GUID.
*/
function createGuid(): string;
/**
* Creates string representation of given function with arrow syntax.
* @param func The function.
* @returns Arrow style code for given function.
*/
function funcToLambda(func: Function): string;
/**
* Finds and returns function name. Works for ES6 classes too.
* @param func The function (or class).
* @returns Name of the given function.
*/
function getFuncName(func: Function): string;
/**
* Reads property of value, used when we are not sure if property is observable.
* @param object Deriving type.
* @param property Property path. Can be a chain like "address.city.name".
* @returns Value of property (undefined when a property cannot be found).
*/
function getValue(object, propertyPath: string);
/**
* Gets localized value for given name using "settings.localizeFunc" function.
* @param resourceName Resource name.
* @param altValue Alternative value to use when resource cannot be found.
* @returns Value for the given resource name.
*/
function getResourceValue(resourceName: string, altValue?: string): string;
/**
* Creates validation error object using given parameters.
* @param entity Entity containing invalid value.
* @param value Invalid value itself.
* @param property Property containing invalid value.
* @param message Validation message.
* @param validator Validator instance.
* @returns Validation error object.
*/
function createValidationError(entity, value, property: string, message: string, validator: interfaces.Validator);
/**
* Creates error object by formatting provided message and populates with given object's values.
* @param message Error message.
* @param arg1 Message format arguments.
* @param arg2 Extra informations, properties will be attached to error object.
* @returns Error object.
*/
function createError(message: string, args?: Array<any>, props?: interfaces.Dictionary<any>): Error;
/**
* Updates foreign keys of given navigation property with new values.
* @param entity The entity.
* @param navProperty The navigation property.
* @param newValue Value of the navigation property.
*/
function setForeignKeys(entity: IEntity, navProperty: interfaces.NavigationProperty, newValue);
/**
* Creates an array and overrides methods to provide callbacks on array changes.
* @param initial Initial values for the array.
* @param object Owner object of the array.
* @param property Navigation property metadata.
* @param after Array change callback.
* @returns Trackable array, an array with change events.
*/
function createTrackableArray<T>(initial: Array<T>, object: Object, property: interfaces.NavigationProperty,
after: (entity: any, property: string, instance: interfaces.TrackableArray<T>, removed: Array<T>, added: Array<T>) => void): interfaces.TrackableArray<T>;
}
/**
* Assertion methods. Two different usage possible, static methods and instance methods.
* Static methods returns true or false. Instance methods can be chained and they collect errors in an array.
* Check method throws error if there are any.
*/
class Assert {
constructor(value: any, name: string);
errors: string[];
/** Checks if value is not null or undefined. */
hasValue(): Assert;
/** Checks if value is object. */
isObject(): Assert;
/** Checks if value is function. */
isFunction(): Assert;
/** Checks if value is a non-empty string. */
isNotEmptyString(): Assert;
/**
* Checks if value is an object of given type.
* @param typeName Name of the javascript type.
*/
isTypeOf(typeName: string): Assert;
/** Checks if value is array. */
isArray(): Assert;
/**
* Checks if value is an symbol of given enum.
* @param enumType Type of the enum.
*/
isEnum(enumType: string): Assert;
/**
* Checks if value is an instance of given type.
* @param type Javascript function or class to check.
*/
isInstanceOf(type: any): Assert;
/** If previous checks created any error, joins them with a new line and throws an Error. */
check();
/** Checks if value is not null or undefined. */
static hasValue(value: any): boolean;
/** Checks if value is object. */
static isObject(value: any): boolean;
/** Checks if value is function. */
static isFunction(value: any): boolean;
/** Checks if value is a non-empty string. */
static isNotEmptyString(value: any): boolean;
/**
* Checks if value is an object of given type.
* @param value The value to check.
* @param typeName Name of the javascript type.
*/
static isTypeOf(value: any, typeName: string): boolean;
/** Checks if value is array. */
static isArray(value: any): boolean;
/**
* Checks if value is an symbol of given enum.
* @param value The value to check.
* @param enumType Type of the enum.
*/
static isEnum(value: any, en