Skip to content

Commit

Permalink
Improve typings (issue #81)
Browse files Browse the repository at this point in the history
 - Expose getProperty/setProperty on Entity
 - Add isDeletedOrDetached() and isAddedOrModified() on EntityState
  • Loading branch information
steveschmitt committed Jul 23, 2024
1 parent aa5ffd0 commit 8326490
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 36 deletions.
8 changes: 4 additions & 4 deletions src/entity-aspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -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<string, any>;
/** Whether this entity has any validation errors. __Read Only__ */
hasValidationErrors: boolean;
/** Whether this entity has a temporary [[EntityKey]]. */
Expand Down Expand Up @@ -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<string, any>;
/** 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__ */
Expand Down
4 changes: 2 additions & 2 deletions src/entity-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, any>;
core.objectForEach(aspect.originalValues, function (propName, val) {
let prop = stype.getProperty(propName) as DataProperty;
val = transformFn ? transformFn(prop, val) : val;
Expand Down Expand Up @@ -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<string, any>;
core.objectForEach(entity.entityAspect.originalValues, function (propName, value) {
let prop = stype.getProperty(propName) as DataProperty;
let val = entity.getProperty(propName);
Expand Down
58 changes: 32 additions & 26 deletions src/entity-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -91,21 +97,21 @@ export class MetadataStore {
**/
metadataFetched: BreezeEvent<MetadataFetchedEventArgs>;
/** @hidden @internal */
_resourceEntityTypeMap: {};
/** @hidden @internal */
_entityTypeResourceMap: {};
_resourceEntityTypeMap: Record<string, string>;
/** @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<string, string>;
/** @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<string, string>;
/** @hidden @internal key is either short or qual type name - value is ctor; **/
_ctorRegistry: Record<string, CtorRecord>;
/** @hidden @internal key is entityTypeName; value is array of nav props **/
_incompleteTypeMap: Record<string, NavigationProperty[]>;
/** @hidden @internal **/
_deferredTypes: {};
_incompleteComplexTypeMap: Record<string, DataProperty[]>;
/** @hidden @internal { json: any, stype: StructuralType }[] | { entityType: EntityType, csdlEntityType: any }[] **/
_deferredTypes: Record<string, any>;
/** @hidden @internal **/
_id: number;

Expand Down Expand Up @@ -866,15 +872,15 @@ 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 */
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.
Expand Down Expand Up @@ -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[];
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1993,7 +1999,7 @@ export interface DataPropertyConfig {
displayName?: string;
enumType?: string;
rawTypeName?: string; // occurs with undefined datatypes
custom?: Object;
custom?: any;
}

/**
Expand Down Expand Up @@ -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;
/**
Expand Down Expand Up @@ -2140,7 +2146,7 @@ export class DataProperty {

}

static getRawValueFromServer(rawEntity: Object, dp: DataProperty) {
static getRawValueFromServer(rawEntity: Object & Record<string, any>, dp: DataProperty) {
if (dp.isUnmapped) {
return rawEntity[dp.nameOnServer || dp.name];
} else {
Expand All @@ -2149,7 +2155,7 @@ export class DataProperty {
}
}

static getRawValueFromClient(rawEntity: Object, dp: DataProperty) {
static getRawValueFromClient(rawEntity: Object & Record<string, any>, dp: DataProperty) {
let val = rawEntity[dp.name];
return val !== undefined ? val : dp.defaultValue;
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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( {
Expand Down Expand Up @@ -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.");
Expand Down
10 changes: 10 additions & 0 deletions src/entity-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/key-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { config } from './config';
interface IPropEntry {
entityType: EntityType;
propertyName: string;
keyMap: Object;
keyMap: Record<string, any>;
}

interface ITempIdMap {
Expand Down
6 changes: 3 additions & 3 deletions src/mapping-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class MappingContext {
mergeOptions: MergeOptions;
adapter: DataServiceAdapter; // assigned in the AbstractDataServiceAdapter.

refMap: Object; // TODO
refMap: Record<string, any>; // TODO
deferredFns: Function[]; // TODO
jsonResultsAdapter: JsonResultsAdapter;
metadataStore: MetadataStore;
Expand Down Expand Up @@ -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<string, any>;

stype.dataProperties.forEach(function (dp) {
if (dp.isComplexProperty) {
Expand Down Expand Up @@ -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<string, any>, key: string) {
let jra = mc.jsonResultsAdapter;
let meta = jra.visitNode(node, mc, nodeContext) || {};
// allows visitNode to change the value;
Expand Down

0 comments on commit 8326490

Please sign in to comment.