diff --git a/src/entity-aspect.ts b/src/entity-aspect.ts index 4cae4d9..14708aa 100644 --- a/src/entity-aspect.ts +++ b/src/entity-aspect.ts @@ -14,9 +14,9 @@ import { EntityQuery } from './entity-query'; export interface Entity { entityAspect: EntityAspect; entityType: EntityType; - /** @internal */ + /** Get the property with the given name */ getProperty?(prop: string): any; - /** @internal */ + /** Set the property with the given name */ setProperty?(prop: any, value: any): void; /** @hidden @internal */ prototype?: { _$typeName: string }; @@ -77,7 +77,7 @@ export class EntityAspect { isBeingSaved: boolean; /** The 'original values' of this entity where they are different from the 'current values'. This is a map where the key is a property name and the value is the 'original value' of the property. */ - originalValues: {}; + originalValues: Record; /** Whether this entity has any validation errors. __Read Only__ */ hasValidationErrors: boolean; /** Whether this entity has a temporary [[EntityKey]]. */ @@ -900,7 +900,7 @@ export class ComplexAspect { /** The 'original values' of this complex object where they are different from the 'current values'. This is a map where the key is a property name and the value is the 'original value' of the property. __Read Only__ */ - originalValues: {}; + originalValues: Record; /** The parent object that to which this aspect belongs; this will either be an entity or another complex object. __Read Only__ */ parent?: StructuralObject; /** The [[DataProperty]] on the 'parent' that contains this complex object. __Read Only__ */ diff --git a/src/entity-manager.ts b/src/entity-manager.ts index 3d27ac1..ac3c09a 100644 --- a/src/entity-manager.ts +++ b/src/entity-manager.ts @@ -2396,7 +2396,7 @@ function unwrapOriginalValues(target: StructuralObject, metadataStore: MetadataS let stype = EntityAspect.isEntity(target) ? target.entityType : target.complexType; let aspect = EntityAspect.isEntity(target) ? target.entityAspect : target.complexAspect; let fn = metadataStore.namingConvention.clientPropertyNameToServer; - let result = {}; + let result = {} as Record; core.objectForEach(aspect.originalValues, function (propName, val) { let prop = stype.getProperty(propName) as DataProperty; val = transformFn ? transformFn(prop, val) : val; @@ -2425,7 +2425,7 @@ function unwrapChangedValues(entity: Entity, metadataStore: MetadataStore, trans let stype = entity.entityType; let serializerFn = getSerializerFn(stype); let fn = metadataStore.namingConvention.clientPropertyNameToServer; - let result = {}; + let result = {} as Record; core.objectForEach(entity.entityAspect.originalValues, function (propName, value) { let prop = stype.getProperty(propName) as DataProperty; let val = entity.getProperty(propName); diff --git a/src/entity-metadata.ts b/src/entity-metadata.ts index e92b6ca..e075aec 100644 --- a/src/entity-metadata.ts +++ b/src/entity-metadata.ts @@ -20,6 +20,12 @@ export type StructuralType = EntityType | ComplexType; export interface IStructuralTypeMap { [index: string]: StructuralType; } +/** Keep track of constructors and initializers for StructuralTypes */ +interface CtorRecord { + ctor: { new (): StructuralObject }; + initFn?: Function | string; + noTrackingFn?: Function; +} // TODO: consider exposing later /** @hidden @internal */ @@ -91,21 +97,21 @@ export class MetadataStore { **/ metadataFetched: BreezeEvent; /** @hidden @internal */ - _resourceEntityTypeMap: {}; - /** @hidden @internal */ - _entityTypeResourceMap: {}; + _resourceEntityTypeMap: Record; /** @hidden @internal */ - _structuralTypeMap: IStructuralTypeMap; // key is qualified structuraltype name - value is structuralType. ( structural = entityType or complexType). - /** @hidden @internal **/ - _shortNameMap: {}; // key is shortName, value is qualified name - does not need to be serialized. - /** @hidden @internal **/ - _ctorRegistry: {}; // key is either short or qual type name - value is ctor; - /** @hidden @internal **/ - _incompleteTypeMap: {}; // key is entityTypeName; value is array of nav props - /** @hidden @internal **/ - _incompleteComplexTypeMap: {}; // + _entityTypeResourceMap: Record; + /** @hidden @internal key is qualified structuraltype name - value is structuralType. ( structural = entityType or complexType). */ + _structuralTypeMap: IStructuralTypeMap; + /** @hidden @internal key is shortName, value is qualified name - does not need to be serialized. **/ + _shortNameMap: Record; + /** @hidden @internal key is either short or qual type name - value is ctor; **/ + _ctorRegistry: Record; + /** @hidden @internal key is entityTypeName; value is array of nav props **/ + _incompleteTypeMap: Record; /** @hidden @internal **/ - _deferredTypes: {}; + _incompleteComplexTypeMap: Record; + /** @hidden @internal { json: any, stype: StructuralType }[] | { entityType: EntityType, csdlEntityType: any }[] **/ + _deferredTypes: Record; /** @hidden @internal **/ _id: number; @@ -866,7 +872,7 @@ export interface EntityTypeConfig { dataProperties?: DataProperty[] | Object[] | Object; // TODO: see if we can't qualify Object[] a little better. navigationProperties?: NavigationProperty[] | Object[] | Object; serializerFn?: (prop: EntityProperty, val: any) => any; - custom?: Object; + custom?: any; } /** Configuration info to be passed to the [[EntityType.setProperties]] method */ @@ -874,7 +880,7 @@ export interface EntityTypeSetConfig { autoGeneratedKeyType?: AutoGeneratedKeyType; defaultResourceName?: string; serializerFn?: (prop: EntityProperty, val: any) => any; - custom?: Object; + custom?: any; } /** Container for all of the metadata about a specific type of Entity. @@ -936,7 +942,7 @@ export class EntityType { /** A function that is used to customize the serialization of any EntityProperties of this type. */ serializerFn?: (prop: EntityProperty, val: any) => any; /** A free form object that can be used to define any custom metadata for this EntityType. __Read Only__ **/ - custom?: Object; + custom?: any; /** The entity level validators associated with this EntityType. Validators can be added and removed from this collection. __Read Only__. **/ validators: Validator[]; @@ -1263,7 +1269,7 @@ export class EntityType { if (this._ctor && !forceRefresh) return this._ctor; let ctorRegistry = this.metadataStore._ctorRegistry; - let r = ctorRegistry[this.name] || ctorRegistry[this.shortName] || {}; + let r = ctorRegistry[this.name] || ctorRegistry[this.shortName] || {} as CtorRecord; let aCtor = r.ctor || this._ctor; let ctorType = aCtor && aCtor.prototype && (aCtor.prototype.entityType || aCtor.prototype.complexType); @@ -1810,7 +1816,7 @@ export interface ComplexTypeConfig { namespace?: string; dataProperties?: DataProperty[] | Object[] | Object; isComplexType?: boolean; // needed because this ctor can get called from the addEntityType method which needs the isComplexType prop - custom?: Object; + custom?: any; } /** Container for all of the metadata about a specific type of Complex object. @@ -1929,7 +1935,7 @@ export class ComplexType { @param config - Custom config object @param config.custom - {Object} **/ - setProperties(config: { custom?: Object }) { + setProperties(config: { custom?: any }) { assertConfig(config) .whereParam("custom").isOptional() .applyAll(this); @@ -1993,7 +1999,7 @@ export interface DataPropertyConfig { displayName?: string; enumType?: string; rawTypeName?: string; // occurs with undefined datatypes - custom?: Object; + custom?: any; } /** @@ -2047,7 +2053,7 @@ export class DataProperty { /** The raw type name of this property. will only be defined for properties with a DataType of 'Undefined' */ declare rawTypeName?: string; // occurs with undefined datatypes /** A free form object that can be used to define any custom metadata for this DataProperty. __Read Only__ */ - declare custom?: Object; + declare custom?: any; // TODO: doc this declare inverseNavigationProperty?: NavigationProperty; /** @@ -2140,7 +2146,7 @@ export class DataProperty { } - static getRawValueFromServer(rawEntity: Object, dp: DataProperty) { + static getRawValueFromServer(rawEntity: Object & Record, dp: DataProperty) { if (dp.isUnmapped) { return rawEntity[dp.nameOnServer || dp.name]; } else { @@ -2149,7 +2155,7 @@ export class DataProperty { } } - static getRawValueFromClient(rawEntity: Object, dp: DataProperty) { + static getRawValueFromClient(rawEntity: Object & Record, dp: DataProperty) { let val = rawEntity[dp.name]; return val !== undefined ? val : dp.defaultValue; } @@ -2248,7 +2254,7 @@ export interface NavigationPropertyConfig { invForeignKeyNamesOnServer?: string[]; validators?: Validator[]; displayName?: string; - custom?: Object; + custom?: any; } /** A NavigationProperty describes the metadata for a single property of an [[EntityType]] that return instances of other EntityTypes. @@ -2313,7 +2319,7 @@ export class NavigationProperty { declare displayName: string; declare isUnmapped: boolean; /** A free form object that can be used to define any custom metadata for this NavigationProperty. **/ - declare custom: Object; + declare custom: any; /** NavigationProperty constructor > let homeAddressProp = new NavigationProperty( { @@ -2369,7 +2375,7 @@ export class NavigationProperty { foreignKeyNames?: string[], invForeignKeyNames?: string[], inverse?: NavigationProperty | string, - custom?: Object + custom?: any }) { if (!this.parentType) { throw new Error("Cannot call NavigationProperty.setProperties until the parent EntityType of the NavigationProperty has been set."); diff --git a/src/entity-state.ts b/src/entity-state.ts index ba6bc95..aafb474 100644 --- a/src/entity-state.ts +++ b/src/entity-state.ts @@ -78,6 +78,11 @@ export class EntityState extends BreezeEnum { return this === EntityState.Detached; } + /** Return true if EntityState is Deleted or Detached */ + isDeletedOrDetached() { + return this === EntityState.Detached || this === EntityState.Detached; + } + /** Returns whether an entityState instance is EntityState.Unchanged or EntityState.Modified. > var es = anEntity.entityAspect.entityState; @@ -90,6 +95,11 @@ export class EntityState extends BreezeEnum { return this === EntityState.Unchanged || this === EntityState.Modified; } + /** Return true if EntityStatis is Added or Modified */ + isAddedOrModified() { + return this === EntityState.Added || this === EntityState.Modified; + } + /** Returns whether an entityState instance is EntityState.Added or EntityState.Modified or EntityState.Deleted. > var es = anEntity.entityAspect.entityState; > return es.isAddedModifiedOrDeleted(); diff --git a/src/key-generator.ts b/src/key-generator.ts index ebd8c51..ff534fe 100644 --- a/src/key-generator.ts +++ b/src/key-generator.ts @@ -5,7 +5,7 @@ import { config } from './config'; interface IPropEntry { entityType: EntityType; propertyName: string; - keyMap: Object; + keyMap: Record; } interface ITempIdMap { diff --git a/src/mapping-context.ts b/src/mapping-context.ts index 1c8c077..a347c25 100644 --- a/src/mapping-context.ts +++ b/src/mapping-context.ts @@ -47,7 +47,7 @@ export class MappingContext { mergeOptions: MergeOptions; adapter: DataServiceAdapter; // assigned in the AbstractDataServiceAdapter. - refMap: Object; // TODO + refMap: Record; // TODO deferredFns: Function[]; // TODO jsonResultsAdapter: JsonResultsAdapter; metadataStore: MetadataStore; @@ -165,7 +165,7 @@ function processMeta(mc: MappingContext, node: any, meta: NodeMeta, assignFn?: ( } function processNoMerge(mc: MappingContext, stype: StructuralType, node: any) { - let result = {}; + let result = {} as Record; stype.dataProperties.forEach(function (dp) { if (dp.isComplexProperty) { @@ -198,7 +198,7 @@ function processAnonType(mc: MappingContext, node: any) { return result; } -function visitNode(node: any, mc: MappingContext, nodeContext: NodeContext, result: Object, key: string) { +function visitNode(node: any, mc: MappingContext, nodeContext: NodeContext, result: Record, key: string) { let jra = mc.jsonResultsAdapter; let meta = jra.visitNode(node, mc, nodeContext) || {}; // allows visitNode to change the value;