@singularsystems/neo-core 1.0.13 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -63,7 +63,7 @@ var Deserialiser = /** @class */ (function () {
63
63
  }
64
64
  });
65
65
  };
66
- Deserialiser.prototype.deserialiseArray = function (from, to, type) {
66
+ Deserialiser.prototype.deserialiseArray = function (from, to, type, itemFactory) {
67
67
  if (!to) {
68
68
  throw "Cannot deserialise array into a non initialised property.";
69
69
  }
@@ -99,7 +99,10 @@ var Deserialiser = /** @class */ (function () {
99
99
  deserialise = false;
100
100
  }
101
101
  else {
102
- if (type) {
102
+ if (itemFactory) {
103
+ toItem = itemFactory(fromItem);
104
+ }
105
+ else if (type) {
103
106
  toItem = new type();
104
107
  }
105
108
  else {
@@ -130,13 +133,14 @@ var Deserialiser = /** @class */ (function () {
130
133
  else {
131
134
  var mustCreate = !to[key];
132
135
  if (mustCreate) {
133
- to[key] = parentProperty.createValueInstance();
136
+ to[key] = parentProperty.createValueInstance(fromItem);
134
137
  }
135
138
  this.deserialiseObject(fromItem, to[key], mustCreate);
136
139
  }
137
140
  }
138
141
  };
139
142
  Deserialiser.prototype.deserialiseObject = function (from, to, justCreated) {
143
+ var _a;
140
144
  if (!from || !to) {
141
145
  throw "From and to objects are required.";
142
146
  }
@@ -173,9 +177,9 @@ var Deserialiser = /** @class */ (function () {
173
177
  }
174
178
  else {
175
179
  if (fromValue instanceof Array && !propertyInfo.assignOnDeserialise) {
176
- if (!to[key] || !(to[key] instanceof Array) || to[key].childObjectType) {
180
+ if (!to[key] || !(to[key] instanceof Array) || to[key].canDeserialise) {
177
181
  // Deserialise into full list.
178
- this.deserialiseArray(fromValue, to[key], undefined);
182
+ this.deserialiseArray(fromValue, to[key], undefined, (_a = to[key]) === null || _a === void 0 ? void 0 : _a.itemFactory);
179
183
  }
180
184
  else {
181
185
  // Plain array
@@ -197,7 +201,7 @@ var Deserialiser = /** @class */ (function () {
197
201
  else {
198
202
  var mustCreate = !to[key];
199
203
  if (mustCreate) {
200
- to[key] = propertyInfo.createValueInstance();
204
+ to[key] = propertyInfo.createValueInstance(fromValue);
201
205
  }
202
206
  this.deserialiseObject(fromValue, to[key], mustCreate);
203
207
  }
@@ -1,4 +1,5 @@
1
1
  import { SerialiseType, DataType, TimeZoneFormat } from './Misc';
2
+ import { IObjectFactoryOptions } from './IModelBase';
2
3
  export declare function Display(name: string): (type: any, propertyKey: string) => void;
3
4
  /** Indicates that this is a date property. Json strings will be converted to date objects on deserialisation. */
4
5
  export declare function Date(timeZoneSerialisation?: TimeZoneFormat): (type: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
@@ -20,10 +21,11 @@ export declare function Observable(isObservable?: boolean): (type: any, property
20
21
  export declare function NoTracking(serialisation?: SerialiseType): (type: any, propertyKey: string) => void;
21
22
  export declare function Serialisation(serialisation: SerialiseType): (type: any, propertyKey: string) => void;
22
23
  /** Indicates that this is a list property, and specifies the item type. This is not required if the list is initialised with a value. */
23
- export declare function ChildList(childType: any): (type: any, propertyKey: string) => any;
24
+ export declare function ChildList(childType?: (new () => any) | (() => any) | IObjectFactoryOptions): (type: any, propertyKey: string) => any;
24
25
  /** Indicates that this is a child object property, and specifies the child type. This is not required if the property is initialised with a value. */
25
26
  export declare function ChildObject(childType: new () => any, isValueObject?: boolean): Function;
26
27
  export declare function ChildObject(childType: () => any, isValueObject?: boolean): Function;
28
+ export declare function ChildObject(options: IObjectFactoryOptions, isValueObject?: boolean): Function;
27
29
  export declare function Dictionary(valueType: any): (type: any, propertyKey: string) => any;
28
30
  export declare function Parent(parentType: () => any): (type: any, propertyKey: string) => void;
29
31
  /**
@@ -85,7 +85,9 @@ export function Serialisation(serialisation) {
85
85
  export function ChildList(childType) {
86
86
  return function (type, propertyKey) {
87
87
  var pi = getOrAddPropertyInfo(type, propertyKey);
88
- pi.setPropertyType(childType);
88
+ if (childType) {
89
+ pi.setPropertyType(childType);
90
+ }
89
91
  if (pi.relationType === RelationType.None) {
90
92
  pi.relationType = RelationType.ChildList;
91
93
  pi.propertyType = DataType.Array;
@@ -101,4 +101,9 @@ export interface IModelBase extends INonObservableModelBase {
101
101
  readonly isDirty: boolean;
102
102
  readonly readyToSave: boolean;
103
103
  }
104
+ export type ObjectFactory = (rawData: object) => object;
105
+ export interface IObjectFactoryOptions {
106
+ /** Function that creates an instance of an object based on some input data. */
107
+ itemFactory: ObjectFactory;
108
+ }
104
109
  export {};
@@ -1,13 +1,19 @@
1
1
  import { ISerialiseOptions } from '../Data/Serialiser';
2
- import { PlainObject, PartialPlainObject, PlainTrackedObject, IMetaItem } from './IModelBase';
2
+ import { PlainObject, PartialPlainObject, PlainTrackedObject, IMetaItem, ObjectFactory, IObjectFactoryOptions } from './IModelBase';
3
3
  import { IDeserialiseOptions } from '../Data/Deserialiser';
4
4
  export default class List<T> extends Array<T> {
5
- childObjectType: (new () => T);
6
5
  attachedTo: object | null;
6
+ childObjectType?: new () => T;
7
+ itemFactory?: ObjectFactory;
7
8
  private _deletedList;
8
9
  get deletedList(): T[];
10
+ get canDeserialise(): ObjectFactory | (new () => T) | undefined;
9
11
  private baseMethods;
10
- constructor(childObjectType: (new () => T));
12
+ /**
13
+ * Creates an instance of a list. A List is an array with the ability to auto create child instances, and track removed items.
14
+ * @param childObjectType Usually the type that the list contains. Can also pass in options for advanced usage.
15
+ */
16
+ constructor(childObjectType?: (new () => T) | IObjectFactoryOptions);
11
17
  /**
12
18
  * Copies the methods and properties from the prototype to the new instance.
13
19
  * This is needed because vue / mobx changes the prototype to its own.
@@ -69,7 +75,7 @@ export default class List<T> extends Array<T> {
69
75
  removeWithoutTracking(item: T): void;
70
76
  private removeItem;
71
77
  /** Returns a static meta object containing all the properties of the lists item type. */
72
- getMetaItem(): IMetaItem;
78
+ getMetaItem(): IMetaItem | null;
73
79
  /** True if all items in the list are valid. */
74
80
  get isValid(): boolean;
75
81
  /** True if any item in the list is dirty, or the list contains any deleted items. */
@@ -5,10 +5,19 @@ import { ObservableValue } from './ObservableValue';
5
5
  import { NeoTypeInfo } from './NeoTypeInfo';
6
6
  var List = /** @class */ (function (_super) {
7
7
  __extends(List, _super);
8
+ /**
9
+ * Creates an instance of a list. A List is an array with the ability to auto create child instances, and track removed items.
10
+ * @param childObjectType Usually the type that the list contains. Can also pass in options for advanced usage.
11
+ */
8
12
  function List(childObjectType) {
9
13
  var _this = _super.call(this) || this;
10
- _this.childObjectType = childObjectType;
11
14
  _this._deletedList = new ObservableValue([]);
15
+ if (typeof childObjectType === "function") {
16
+ _this.childObjectType = childObjectType;
17
+ }
18
+ else {
19
+ _this.itemFactory = childObjectType === null || childObjectType === void 0 ? void 0 : childObjectType.itemFactory;
20
+ }
12
21
  List.copyMethods(_this);
13
22
  return _this;
14
23
  }
@@ -19,6 +28,13 @@ var List = /** @class */ (function (_super) {
19
28
  enumerable: false,
20
29
  configurable: true
21
30
  });
31
+ Object.defineProperty(List.prototype, "canDeserialise", {
32
+ get: function () {
33
+ return this.itemFactory || this.childObjectType;
34
+ },
35
+ enumerable: false,
36
+ configurable: true
37
+ });
22
38
  /**
23
39
  * Copies the methods and properties from the prototype to the new instance.
24
40
  * This is needed because vue / mobx changes the prototype to its own.
@@ -80,6 +96,9 @@ var List = /** @class */ (function (_super) {
80
96
  };
81
97
  /** Creates a new item of type T */
82
98
  List.prototype.createChild = function () {
99
+ if (!this.childObjectType) {
100
+ throw "Cannot create child, type was not passed to constructor.";
101
+ }
83
102
  return new this.childObjectType();
84
103
  };
85
104
  List.prototype.push = function () {
@@ -89,7 +108,7 @@ var List = /** @class */ (function (_super) {
89
108
  items[_i] = arguments[_i];
90
109
  }
91
110
  items.forEach(function (item) {
92
- if (!(item instanceof _this.childObjectType)) {
111
+ if (_this.childObjectType && !(item instanceof _this.childObjectType)) {
93
112
  throw "Type error, cannot add item of type " + Utils.getTypeName(item.constructor) + " to list of type " + Utils.getTypeName(_this.childObjectType) + ".";
94
113
  }
95
114
  _this.setParent(item);
@@ -101,7 +120,7 @@ var List = /** @class */ (function (_super) {
101
120
  };
102
121
  List.prototype.setParent = function (item) {
103
122
  if (this.attachedTo) {
104
- var itemConstructor = this.childObjectType.prototype.constructor;
123
+ var itemConstructor = item.constructor.prototype.constructor;
105
124
  // set the parent property
106
125
  if (itemConstructor.neo) {
107
126
  var parentConstructor = this.attachedTo.constructor.prototype.constructor;
@@ -162,10 +181,13 @@ var List = /** @class */ (function (_super) {
162
181
  if (this.length) {
163
182
  return this[0];
164
183
  }
165
- else {
184
+ else if (this.childObjectType) {
166
185
  var ctor = this.childObjectType.prototype.constructor;
167
186
  return NeoTypeInfo.ensureInitialised(ctor).metaItem;
168
187
  }
188
+ else {
189
+ return null;
190
+ }
169
191
  };
170
192
  Object.defineProperty(List.prototype, "isValid", {
171
193
  /** True if all items in the list are valid. */
@@ -83,7 +83,7 @@ export default abstract class ModelBase extends BindableBase implements IModelBa
83
83
  * ```
84
84
  * protected static addBusinessRules(rules: ValidationRules<MyType>) {
85
85
  * ``` */
86
- protected addBusinessRules(validationRules: ValidationRules<this>): void;
86
+ protected addBusinessRules(validationRules: ValidationRules<ModelBase>): void;
87
87
  /**
88
88
  * Add custom business rules for this type.
89
89
  */
@@ -61,11 +61,12 @@ var ModelCreatorBase = /** @class */ (function () {
61
61
  // @ts-ignore
62
62
  var propertyValue = instance[propertyInfo.propertyName];
63
63
  if (propertyValue) {
64
- if (propertyValue.childObjectType) {
64
+ var list = propertyValue;
65
+ if (list.itemFactory || list.childObjectType) {
65
66
  // This is a list.
66
67
  if (propertyInfo.relationType != RelationType.ChildList) {
67
68
  // add missing annotation
68
- propertyInfo = ChildList(propertyValue.childObjectType)(instance, propertyInfo.propertyName);
69
+ propertyInfo = ChildList(list.itemFactory ? { itemFactory: list.itemFactory } : list.childObjectType)(instance, propertyInfo.propertyName);
69
70
  }
70
71
  }
71
72
  else if (propertyValue instanceof ModelBase) {
@@ -22,6 +22,7 @@ export declare class NeoTypeInfo {
22
22
  get inheritsBindableBase(): boolean;
23
23
  get inheritsModelBase(): boolean;
24
24
  get metaItem(): IMetaItem;
25
+ get typeName(): string;
25
26
  initialise(objectConstructor: NeoModelConstructor): void;
26
27
  private addPropertyInfo;
27
28
  getOrAddProperty(propertyName: string): PropertyInfo;
@@ -55,6 +55,13 @@ var NeoTypeInfo = /** @class */ (function () {
55
55
  enumerable: false,
56
56
  configurable: true
57
57
  });
58
+ Object.defineProperty(NeoTypeInfo.prototype, "typeName", {
59
+ get: function () {
60
+ return this.objectConstructor.name;
61
+ },
62
+ enumerable: false,
63
+ configurable: true
64
+ });
58
65
  NeoTypeInfo.prototype.initialise = function (objectConstructor) {
59
66
  this.objectConstructor = objectConstructor;
60
67
  };
@@ -1,6 +1,6 @@
1
1
  import { SerialiseType, RelationType, OnChangedOptions, DataType, TimeZoneFormat } from './Misc';
2
2
  import { Nullable } from '../Utils';
3
- import { INonObservableModelBase } from './IModelBase';
3
+ import { INonObservableModelBase, IObjectFactoryOptions, ObjectFactory } from './IModelBase';
4
4
  import { Rule } from '../Validation/Rules';
5
5
  export type PropertyInfoMap = {
6
6
  [index: string]: PropertyInfo;
@@ -58,6 +58,8 @@ export default class PropertyInfo {
58
58
  rules: Rule[];
59
59
  /** Indicates that this property must be assigned to on de/serialisation. The de/serialiser will not try create a model instance of the object / array. */
60
60
  assignOnDeserialise: boolean;
61
+ /** Object factory used for deserialisation. Set by ChildList / ChildObject decorators. */
62
+ itemFactory?: ObjectFactory;
61
63
  constructor(propertyName: string);
62
64
  /** Gets the readable name of the property. Uses string.readable if Display decorator was not specified. */
63
65
  get readableName(): string;
@@ -67,7 +69,7 @@ export default class PropertyInfo {
67
69
  get parent(): PropertyInfo | undefined;
68
70
  addAttributeRule(rule: Rule): void;
69
71
  clone(): PropertyInfo;
70
- setPropertyType(propertyType: (() => any) | (new () => any)): void;
72
+ setPropertyType(propertyType: (() => any) | (new () => any) | IObjectFactoryOptions): void;
71
73
  /**
72
74
  * Gets the constructor function of the return type.
73
75
  * Returns null if the property has not been decorated with a ChildObject / Parent attribute.
@@ -78,6 +80,6 @@ export default class PropertyInfo {
78
80
  * Raises an error if the property has not been decorated with a ChildObject / Parent attribute.
79
81
  */
80
82
  get typeWithAssert(): new () => any;
81
- createValueInstance(): any;
83
+ createValueInstance(data: any): any;
82
84
  setupFromInstance(instance: any): void;
83
85
  }
@@ -75,11 +75,16 @@ var PropertyInfo = /** @class */ (function () {
75
75
  return clone;
76
76
  };
77
77
  PropertyInfo.prototype.setPropertyType = function (propertyType) {
78
- if (!propertyType.prototype || !propertyType.prototype.constructor.name) {
79
- this.typeCallback = propertyType;
78
+ if (typeof propertyType === "function") {
79
+ if (!propertyType.prototype || !propertyType.prototype.constructor.name) {
80
+ this.typeCallback = propertyType;
81
+ }
82
+ else {
83
+ this._type = propertyType;
84
+ }
80
85
  }
81
86
  else {
82
- this._type = propertyType;
87
+ this.itemFactory = propertyType.itemFactory;
83
88
  }
84
89
  };
85
90
  Object.defineProperty(PropertyInfo.prototype, "type", {
@@ -116,7 +121,10 @@ var PropertyInfo = /** @class */ (function () {
116
121
  enumerable: false,
117
122
  configurable: true
118
123
  });
119
- PropertyInfo.prototype.createValueInstance = function () {
124
+ PropertyInfo.prototype.createValueInstance = function (data) {
125
+ if (this.itemFactory) {
126
+ return this.itemFactory(data);
127
+ }
120
128
  try {
121
129
  return new this.typeWithAssert();
122
130
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@singularsystems/neo-core",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "Core functionality for the Neo client library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@microsoft/signalr": "^6.0.1",
28
- "axios": "1.6.7",
28
+ "axios": "1.7.4",
29
29
  "inversify": "^6.0.2",
30
30
  "reflect-metadata": "0.1.13",
31
31
  "tslib": "2.5.0"