@nymphjs/client 1.0.0-alpha.3 → 1.0.0-alpha.30

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.
package/src/Entity.ts CHANGED
@@ -78,15 +78,15 @@ export default class Entity<T extends EntityData = EntityData>
78
78
  /**
79
79
  * Whether this instance is a sleeping reference.
80
80
  */
81
- private $isASleepingReference = false;
81
+ protected $isASleepingReference = false;
82
82
  /**
83
83
  * The reference to use to wake.
84
84
  */
85
- private $sleepingReference: EntityReference | null = null;
85
+ protected $sleepingReference: EntityReference | null = null;
86
86
  /**
87
87
  * A promise that resolved when the entity's data is ready.
88
88
  */
89
- private $readyPromise: Promise<Entity<T>> | null = null;
89
+ protected $readyPromise: Promise<Entity<T>> | null = null;
90
90
 
91
91
  /**
92
92
  * Load an entity.
@@ -100,7 +100,7 @@ export default class Entity<T extends EntityData = EntityData>
100
100
  console.error(`Tried to check data on a sleeping reference: ${name}`);
101
101
  return false;
102
102
  }
103
- return data.hasOwnProperty(name);
103
+ return name in data;
104
104
  },
105
105
 
106
106
  get: (data: EntityData, name: string) => {
@@ -139,6 +139,42 @@ export default class Entity<T extends EntityData = EntityData>
139
139
  }
140
140
  return true;
141
141
  },
142
+
143
+ defineProperty: (
144
+ data: EntityData,
145
+ name: string,
146
+ descriptor: PropertyDescriptor
147
+ ) => {
148
+ if (typeof name !== 'symbol' && this.$isASleepingReference) {
149
+ console.error(
150
+ `Tried to define data on a sleeping reference: ${name}`
151
+ );
152
+ return false;
153
+ }
154
+ if (typeof name !== 'symbol') {
155
+ this.$dirty[name] = true;
156
+ }
157
+ Object.defineProperty(data, name, descriptor);
158
+ return true;
159
+ },
160
+
161
+ getOwnPropertyDescriptor: (data: EntityData, name: string) => {
162
+ if (typeof name !== 'symbol' && this.$isASleepingReference) {
163
+ console.error(
164
+ `Tried to get property descriptor on a sleeping reference: ${name}`
165
+ );
166
+ return undefined;
167
+ }
168
+ return Object.getOwnPropertyDescriptor(data, name);
169
+ },
170
+
171
+ ownKeys: (data: EntityData) => {
172
+ if (this.$isASleepingReference) {
173
+ console.error(`Tried to enumerate data on a sleeping reference.`);
174
+ return undefined;
175
+ }
176
+ return Object.getOwnPropertyNames(data);
177
+ },
142
178
  };
143
179
  this.$dataStore = {} as T;
144
180
  this.$data = new Proxy(this.$dataStore, this.$dataHandler);
@@ -205,11 +241,49 @@ export default class Entity<T extends EntityData = EntityData>
205
241
  getPrototypeOf(entity: Entity) {
206
242
  return entity.constructor.prototype;
207
243
  },
244
+
245
+ defineProperty(
246
+ entity: Entity,
247
+ name: string,
248
+ descriptor: PropertyDescriptor
249
+ ) {
250
+ if (
251
+ typeof name !== 'string' ||
252
+ name in entity ||
253
+ name.substring(0, 1) === '$'
254
+ ) {
255
+ Object.defineProperty(entity, name, descriptor);
256
+ } else {
257
+ Object.defineProperty(entity.$data, name, descriptor);
258
+ }
259
+ return true;
260
+ },
261
+
262
+ getOwnPropertyDescriptor(entity: Entity, name: string) {
263
+ if (
264
+ typeof name !== 'string' ||
265
+ name in entity ||
266
+ name.substring(0, 1) === '$'
267
+ ) {
268
+ return Object.getOwnPropertyDescriptor(entity, name);
269
+ } else {
270
+ return Object.getOwnPropertyDescriptor(entity.$data, name);
271
+ }
272
+ },
273
+
274
+ ownKeys(entity: Entity) {
275
+ return Object.getOwnPropertyNames(entity).concat(
276
+ Object.getOwnPropertyNames(entity.$data)
277
+ );
278
+ },
208
279
  }) as Entity<T>;
209
280
  }
210
281
 
211
282
  public static async factory(guid?: string) {
212
- const entity = new this(guid);
283
+ const cacheEntity = (
284
+ guid ? this.nymph.getEntityFromCache(this, guid) : null
285
+ ) as Entity | null;
286
+ const entity = cacheEntity || new this(guid);
213
287
  if (guid != null) {
214
288
  await entity.$ready();
215
289
  }
@@ -217,12 +291,21 @@ export default class Entity<T extends EntityData = EntityData>
217
291
  }
218
292
 
219
293
  public static factorySync(guid?: string) {
220
- return new this(guid);
294
+ const cacheEntity = (
295
+ guid ? this.nymph.getEntityFromCache(this, guid) : null
296
+ ) as Entity | null;
297
+ return cacheEntity || new this(guid);
221
298
  }
222
299
 
223
300
  public static factoryReference(reference: EntityReference) {
224
- const entity = new this();
225
- entity.$referenceSleep(reference);
301
+ const cacheEntity = (
302
+ reference[1] ? this.nymph.getEntityFromCache(this, reference[1]) : null
303
+ ) as Entity | null;
304
+
305
+ const entity = cacheEntity || new this();
306
+ if (!cacheEntity) {
307
+ entity.$referenceSleep(reference);
308
+ }
226
309
  return entity;
227
310
  }
228
311
 
@@ -280,6 +363,8 @@ export default class Entity<T extends EntityData = EntityData>
280
363
  ) as T;
281
364
  this.$data = new Proxy(this.$dataStore, this.$dataHandler);
282
365
 
366
+ this.$nymph.setEntityToCache(this.constructor as EntityConstructor, this);
367
+
283
368
  return this as Entity<T>;
284
369
  }
285
370
 
@@ -0,0 +1,32 @@
1
+ import { EntityConstructor, EntityInterface } from './Entity.types';
2
+
3
+ export default class EntityWeakCache {
4
+ private references: WeakMap<EntityConstructor, { [k: string]: any }> =
5
+ new WeakMap();
6
+
7
+ get(EntityClass: EntityConstructor, guid: string): EntityInterface | null {
8
+ const classMap = this.references.get(EntityClass);
9
+ if (classMap && guid in classMap) {
10
+ const weakRef = classMap[guid];
11
+ if (weakRef && weakRef.deref() != null) {
12
+ return weakRef.deref();
13
+ } else {
14
+ delete classMap[guid];
15
+ }
16
+ }
17
+ return null;
18
+ }
19
+
20
+ set(EntityClass: EntityConstructor, entity: EntityInterface) {
21
+ if (!entity.guid) {
22
+ return;
23
+ }
24
+
25
+ // @ts-ignore TS doesn't know about WeakRef.
26
+ const weakRef = new WeakRef(entity);
27
+
28
+ const classMap = this.references.get(EntityClass) || {};
29
+ this.references.set(EntityClass, classMap);
30
+ classMap[entity.guid] = weakRef;
31
+ }
32
+ }
@@ -52,7 +52,7 @@ export default class HttpRequester {
52
52
  : T extends 'response'
53
53
  ? 'responseCallbacks'
54
54
  : never;
55
- if (!this.hasOwnProperty(prop)) {
55
+ if (!(prop in this)) {
56
56
  throw new Error('Invalid event type.');
57
57
  }
58
58
  // @ts-ignore: The callback should always be the right type here.
@@ -73,7 +73,7 @@ export default class HttpRequester {
73
73
  : T extends 'response'
74
74
  ? 'responseCallbacks'
75
75
  : never;
76
- if (!this.hasOwnProperty(prop)) {
76
+ if (!(prop in this)) {
77
77
  return false;
78
78
  }
79
79
  // @ts-ignore: The callback should always be the right type here.
package/src/Nymph.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import Entity from './Entity';
2
2
  import {
3
3
  EntityConstructor,
4
+ EntityData,
4
5
  EntityInterface,
5
6
  EntityJson,
6
7
  ServerCallResponse,
7
8
  ServerCallStaticResponse,
8
9
  } from './Entity.types';
10
+ import EntityWeakCache from './EntityWeakCache';
9
11
  import HttpRequester from './HttpRequester';
10
12
  import {
11
13
  EventType,
@@ -21,17 +23,36 @@ import { entitiesToReferences, entityConstructorsToClassNames } from './utils';
21
23
  let requester: HttpRequester;
22
24
 
23
25
  export default class Nymph {
26
+ /**
27
+ * And optional PubSub client instance.
28
+ */
24
29
  public pubsub: PubSub | undefined = undefined;
30
+
31
+ /**
32
+ * A simple map of names to Entity classes.
33
+ */
25
34
  private entityClasses: { [k: string]: EntityConstructor } = {};
35
+
36
+ /**
37
+ * The entity class for this instance of Nymph.
38
+ */
39
+ public Entity: typeof Entity = Entity;
40
+
26
41
  private requestCallbacks: RequestCallback[] = [];
27
42
  private responseCallbacks: ResponseCallback[] = [];
28
43
  private restUrl: string = '';
44
+ private weakCache = false;
45
+ public cache = new EntityWeakCache();
29
46
 
30
47
  public constructor(NymphOptions: NymphOptions) {
31
48
  this.restUrl = NymphOptions.restUrl;
49
+ // @ts-ignore TS doesn't know about WeakRef.
50
+ this.weakCache = !!NymphOptions.weakCache && typeof WeakRef !== 'undefined';
32
51
 
33
- class NymphEntity extends Entity {}
34
- this.setEntityClass(NymphEntity.class, NymphEntity);
52
+ class NymphEntity<T extends EntityData = EntityData> extends Entity<T> {}
53
+ NymphEntity.nymph = this;
54
+ this.Entity = NymphEntity;
55
+ this.addEntityClass(NymphEntity);
35
56
 
36
57
  requester = new HttpRequester(
37
58
  'fetch' in NymphOptions ? NymphOptions.fetch : undefined
@@ -50,8 +71,8 @@ export default class Nymph {
50
71
  });
51
72
  }
52
73
 
53
- public setEntityClass(className: string, entityClass: EntityConstructor) {
54
- this.entityClasses[className] = entityClass;
74
+ public addEntityClass(entityClass: EntityConstructor) {
75
+ this.entityClasses[entityClass.class] = entityClass;
55
76
  entityClass.nymph = this;
56
77
  }
57
78
 
@@ -315,10 +336,42 @@ export default class Nymph {
315
336
  entityJSON.class + ' class cannot be found.'
316
337
  );
317
338
  }
318
- const entity = EntityClass.factorySync();
339
+ let entity = EntityClass.factorySync();
340
+ if (this.weakCache) {
341
+ // Try to get it from cache.
342
+ const entityFromCache = this.cache.get(
343
+ EntityClass,
344
+ entityJSON.guid || ''
345
+ );
346
+ if (entityFromCache != null) {
347
+ entity = entityFromCache;
348
+ }
349
+ }
319
350
  return entity.$init(entityJSON) as ReturnType<T['factorySync']>;
320
351
  }
321
352
 
353
+ public getEntityFromCache<T extends EntityConstructor = EntityConstructor>(
354
+ EntityClass: EntityConstructor,
355
+ guid: string
356
+ ): ReturnType<T['factorySync']> | null {
357
+ if (!this.weakCache) {
358
+ return null;
359
+ }
360
+ return this.cache.get(EntityClass, guid) as ReturnType<
361
+ T['factorySync']
362
+ > | null;
363
+ }
364
+
365
+ public setEntityToCache(
366
+ EntityClass: EntityConstructor,
367
+ entity: EntityInterface
368
+ ) {
369
+ if (!this.weakCache) {
370
+ return;
371
+ }
372
+ return this.cache.set(EntityClass, entity);
373
+ }
374
+
322
375
  public initEntitiesFromData<T extends any>(item: T): T {
323
376
  if (Array.isArray(item)) {
324
377
  // Recurse into lower arrays.
@@ -436,7 +489,7 @@ export default class Nymph {
436
489
  : T extends 'request'
437
490
  ? 'responseCallbacks'
438
491
  : never;
439
- if (!this.hasOwnProperty(prop)) {
492
+ if (!(prop in this)) {
440
493
  throw new Error('Invalid event type.');
441
494
  }
442
495
  // @ts-ignore: The callback should always be the right type here.
@@ -457,7 +510,7 @@ export default class Nymph {
457
510
  : T extends 'request'
458
511
  ? 'responseCallbacks'
459
512
  : never;
460
- if (!this.hasOwnProperty(prop)) {
513
+ if (!(prop in this)) {
461
514
  return false;
462
515
  }
463
516
  // @ts-ignore: The callback should always be the right type here.
@@ -21,6 +21,25 @@ export type NymphOptions = {
21
21
  * Whether to not output status messages to the console.
22
22
  */
23
23
  noConsole?: boolean;
24
+ /**
25
+ * Use a WeakRef based cache of entities.
26
+ *
27
+ * This ensures all entities returned are the same instance if they have the
28
+ * same class and GUID. This also means that whenever an entity is returned
29
+ * from the server, the single instance in memory will be refreshed. This
30
+ * could have annoying results, like destroying dirty data (the dreaded
31
+ * triple-D).
32
+ *
33
+ * This could also be a potential source of memory leaks. Although the
34
+ * entities themselves are referenced weakly so they get garbage collected,
35
+ * the GUID used as a key and the WeakRef object itself are not weak
36
+ * references, so not destroyed when the instance is garbage collected.
37
+ *
38
+ * However, even with these caveats, this might help you if you have a big app
39
+ * with the same entities stored in several different places in memory. This
40
+ * can help to synchronize them correctly and avoid data conflicts.
41
+ */
42
+ weakCache?: boolean;
24
43
  };
25
44
 
26
45
  export type EventType = 'request' | 'response';
package/src/PubSub.ts CHANGED
@@ -682,7 +682,7 @@ export default class PubSub {
682
682
  : T extends 'disconnect'
683
683
  ? 'disconnectCallbacks'
684
684
  : never;
685
- if (!this.hasOwnProperty(prop)) {
685
+ if (!(prop in this)) {
686
686
  throw new Error('Invalid event type.');
687
687
  }
688
688
  this[prop].push(callback);
@@ -702,7 +702,7 @@ export default class PubSub {
702
702
  : T extends 'disconnect'
703
703
  ? 'disconnectCallbacks'
704
704
  : never;
705
- if (!this.hasOwnProperty(prop)) {
705
+ if (!(prop in this)) {
706
706
  return false;
707
707
  }
708
708
  const i = this[prop].indexOf(callback);
package/src/index.ts CHANGED
@@ -4,9 +4,6 @@ export { Entity };
4
4
 
5
5
  export * from './Entity.types';
6
6
 
7
- import EntitySorter from './EntitySorter';
8
- export { EntitySorter };
9
-
10
7
  export * from './HttpRequester';
11
8
 
12
9
  export * from './Nymph';
@@ -1,16 +0,0 @@
1
- export default class EntitySorter<Entity extends new () => Object, Nymph extends {
2
- getEntityClass(className: string): Entity;
3
- }> {
4
- private array;
5
- private sortProperty;
6
- private sortParent;
7
- private sortCaseSensitive;
8
- private nymph;
9
- constructor(array: Entity[], nymph: Nymph);
10
- private _arraySortProperty;
11
- hsort(property: string, parentProperty: string, caseSensitive?: boolean, reverse?: boolean): (Entity & {
12
- [k: string]: any;
13
- })[];
14
- psort(property: string, parentProperty: string, caseSensitive?: boolean, reverse?: boolean): Entity[];
15
- sort(property: string, caseSensitive?: boolean, reverse?: boolean): Entity[];
16
- }
@@ -1,134 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- class EntitySorter {
4
- constructor(array, nymph) {
5
- this.sortProperty = null;
6
- this.sortParent = null;
7
- this.sortCaseSensitive = null;
8
- this.array = array;
9
- this.nymph = nymph;
10
- }
11
- _arraySortProperty(a, b) {
12
- let prop = this.sortProperty;
13
- let parent = this.sortParent;
14
- const Entity = this.nymph.getEntityClass('Entity');
15
- if (parent != null &&
16
- a[parent] instanceof Entity &&
17
- b[parent] instanceof Entity) {
18
- const aParentProp = a[parent][prop];
19
- const bParentProp = b[parent][prop];
20
- if (typeof aParentProp !== 'undefined' ||
21
- typeof bParentProp !== 'undefined') {
22
- if (!this.sortCaseSensitive &&
23
- typeof aParentProp === 'string' &&
24
- typeof bParentProp === 'string') {
25
- const asort = aParentProp.toUpperCase();
26
- const bsort = bParentProp.toUpperCase();
27
- if (asort !== bsort) {
28
- return asort.localeCompare(bsort);
29
- }
30
- }
31
- else {
32
- if (aParentProp > bParentProp) {
33
- return 1;
34
- }
35
- if (aParentProp < bParentProp) {
36
- return -1;
37
- }
38
- }
39
- }
40
- }
41
- const aProp = a[prop];
42
- const bProp = b[prop];
43
- if (!this.sortCaseSensitive &&
44
- typeof aProp === 'string' &&
45
- typeof bProp === 'string') {
46
- const asort = aProp.toUpperCase();
47
- const bsort = bProp.toUpperCase();
48
- return asort.localeCompare(bsort);
49
- }
50
- else {
51
- if (aProp > bProp) {
52
- return 1;
53
- }
54
- if (aProp < bProp) {
55
- return -1;
56
- }
57
- }
58
- return 0;
59
- }
60
- hsort(property, parentProperty, caseSensitive = false, reverse = false) {
61
- this.sort(property, caseSensitive, reverse);
62
- if (typeof parentProperty === 'undefined' || parentProperty === null) {
63
- return this.array;
64
- }
65
- let newArray = [];
66
- let changed;
67
- while (this.array.length) {
68
- changed = false;
69
- for (let key = 0; key < this.array.length; key++) {
70
- if (this.array[key][parentProperty] == null ||
71
- typeof this.array[key][parentProperty].$inArray !== 'function' ||
72
- !this.array[key][parentProperty].$inArray(newArray.concat(this.array))) {
73
- newArray.push(this.array[key]);
74
- this.array.splice(key, 1);
75
- changed = true;
76
- break;
77
- }
78
- else if (typeof this.array[key][parentProperty].$arraySearch === 'function') {
79
- const pkey = this.array[key][parentProperty].$arraySearch(newArray);
80
- if (pkey !== -1) {
81
- const ancestry = [this.array[key][parentProperty].guid];
82
- let newKey = Number(pkey);
83
- while (typeof newArray[newKey + 1] !== 'undefined' &&
84
- newArray[newKey + 1][parentProperty] != null &&
85
- ancestry.indexOf(newArray[newKey + 1][parentProperty].guid) !== -1) {
86
- ancestry.push(newArray[newKey + 1].guid);
87
- newKey += 1;
88
- }
89
- newKey += 1;
90
- if (typeof newArray[newKey] !== 'undefined') {
91
- newArray.splice(newKey, 0, this.array[key]);
92
- }
93
- else {
94
- newArray.push(this.array[key]);
95
- }
96
- this.array.splice(key, 1);
97
- changed = true;
98
- break;
99
- }
100
- }
101
- }
102
- if (!changed) {
103
- if (this.array.length) {
104
- newArray = newArray.concat(this.array);
105
- this.array.splice(0, this.array.length);
106
- }
107
- }
108
- }
109
- this.array.splice(0, 0, ...newArray);
110
- return this.array;
111
- }
112
- psort(property, parentProperty, caseSensitive = false, reverse = false) {
113
- this.sortProperty = property;
114
- this.sortParent = parentProperty;
115
- this.sortCaseSensitive = !!caseSensitive;
116
- this.array.sort(this._arraySortProperty.bind(this));
117
- if (reverse) {
118
- this.array.reverse();
119
- }
120
- return this.array;
121
- }
122
- sort(property, caseSensitive = false, reverse = false) {
123
- this.sortProperty = property;
124
- this.sortParent = null;
125
- this.sortCaseSensitive = !!caseSensitive;
126
- this.array.sort(this._arraySortProperty.bind(this));
127
- if (reverse) {
128
- this.array.reverse();
129
- }
130
- return this.array;
131
- }
132
- }
133
- exports.default = EntitySorter;
134
- //# sourceMappingURL=EntitySorter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"EntitySorter.js","sourceRoot":"","sources":["../src/EntitySorter.ts"],"names":[],"mappings":"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"}