@onehat/data 1.5.0 → 1.6.1
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/cypress/integration/Entity.spec.js +51 -28
- package/cypress/integration/Property/Integer.spec.js +8 -0
- package/cypress/integration/Property/Property.spec.js +14 -0
- package/cypress/integration/Property/String.spec.js +15 -3
- package/cypress/integration/Repository/Repository.spec.js +34 -4
- package/package.json +1 -1
- package/src/Entity.js +33 -31
- package/src/Property/Integer.js +29 -0
- package/src/Property/Property.js +7 -1
- package/src/Property/String.js +19 -0
- package/src/Repository/Ajax.js +1 -1
- package/src/Repository/Memory.js +1 -1
- package/src/Repository/Repository.js +40 -11
|
@@ -44,7 +44,7 @@ describe('Entity', function() {
|
|
|
44
44
|
expect(this.entity.id).to.be.eq(1);
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
-
it('
|
|
47
|
+
it('createTempId, isTempId', function() {
|
|
48
48
|
const schema = new Schema({
|
|
49
49
|
name: 'baz',
|
|
50
50
|
model: {
|
|
@@ -62,33 +62,14 @@ describe('Entity', function() {
|
|
|
62
62
|
entity = new Entity(schema, data);
|
|
63
63
|
entity.initialize();
|
|
64
64
|
expect(entity.id).to.be.null;
|
|
65
|
+
expect(entity.isTempId).to.be.false;
|
|
65
66
|
|
|
66
|
-
entity.
|
|
67
|
+
entity.createTempId();
|
|
67
68
|
expect(entity.id).to.be.not.null;
|
|
68
|
-
expect(
|
|
69
|
+
expect(entity.isTempId).to.be.true;
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const schema2 = new Schema({
|
|
73
|
-
name: 'baz',
|
|
74
|
-
model: {
|
|
75
|
-
idProperty: 'foo',
|
|
76
|
-
displayProperty: 'bar',
|
|
77
|
-
properties: [
|
|
78
|
-
{ name: 'foo', type: 'uuid' }, // MOD
|
|
79
|
-
{ name: 'bar' },
|
|
80
|
-
],
|
|
81
|
-
},
|
|
82
|
-
}),
|
|
83
|
-
entity2 = new Entity(schema2, data);
|
|
84
|
-
|
|
85
|
-
entity2.initialize();
|
|
86
|
-
expect(entity2.id).to.be.null;
|
|
87
|
-
|
|
88
|
-
entity2.createId();
|
|
89
|
-
expect(entity2.id).to.be.not.null;
|
|
90
|
-
const idProperty = entity2.getIdProperty();
|
|
91
|
-
expect(Entity.isTempId(entity2.id)).to.be.false;
|
|
71
|
+
entity.markSaved();
|
|
72
|
+
expect(entity.isTempId).to.be.false;
|
|
92
73
|
});
|
|
93
74
|
|
|
94
75
|
|
|
@@ -301,9 +282,35 @@ describe('Entity', function() {
|
|
|
301
282
|
expect(_.isEqual(reverseMapped2, expected2)).to.be.true;
|
|
302
283
|
});
|
|
303
284
|
|
|
304
|
-
it('getReverseMappedRawValues', function() {
|
|
305
|
-
const
|
|
306
|
-
|
|
285
|
+
it('getReverseMappedRawValues (check deep matches)', function() {
|
|
286
|
+
const schema = new Schema({
|
|
287
|
+
name: 'baz',
|
|
288
|
+
model: {
|
|
289
|
+
idProperty: 'foo',
|
|
290
|
+
displayProperty: 'bar',
|
|
291
|
+
properties: [
|
|
292
|
+
{ name: 'foo', type: 'int' },
|
|
293
|
+
{ name: 'bar' },
|
|
294
|
+
{ name: 'baz', mapping: 'baz.test.val', type: 'bool', defaultValue: null, },
|
|
295
|
+
{ name: 'baz2', mapping: 'baz.test2', type: 'bool', defaultValue: null, },
|
|
296
|
+
],
|
|
297
|
+
},
|
|
298
|
+
}),
|
|
299
|
+
data = {
|
|
300
|
+
foo: 1,
|
|
301
|
+
bar: 'one',
|
|
302
|
+
baz: {
|
|
303
|
+
test: {
|
|
304
|
+
val: true,
|
|
305
|
+
},
|
|
306
|
+
test2: false,
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
entity = new Entity(schema, data);
|
|
310
|
+
entity.initialize();
|
|
311
|
+
|
|
312
|
+
const result = entity.getReverseMappedRawValues();
|
|
313
|
+
expect(_.isEqual(result, data)).to.be.true;
|
|
307
314
|
});
|
|
308
315
|
|
|
309
316
|
it('build a new entity from an existing one using getDataForNewEntity', function() {
|
|
@@ -381,6 +388,12 @@ describe('Entity', function() {
|
|
|
381
388
|
const entity = new Entity(this.schema, {});
|
|
382
389
|
entity.initialize();
|
|
383
390
|
expect(entity.isPhantom).to.be.true;
|
|
391
|
+
|
|
392
|
+
entity.createTempId();
|
|
393
|
+
expect(entity.isPhantom).to.be.true;
|
|
394
|
+
|
|
395
|
+
entity.markSaved();
|
|
396
|
+
expect(entity.isPhantom).to.be.false;
|
|
384
397
|
});
|
|
385
398
|
|
|
386
399
|
it('isDirty', function() {
|
|
@@ -443,6 +456,15 @@ describe('Entity', function() {
|
|
|
443
456
|
expect(this.entity.isDirty).to.be.true;
|
|
444
457
|
});
|
|
445
458
|
|
|
459
|
+
it('setId', function() {
|
|
460
|
+
expect(this.entity.foo).to.be.eq(1);
|
|
461
|
+
expect(this.entity.isTempId).to.be.false;
|
|
462
|
+
|
|
463
|
+
this.entity.setId(2);
|
|
464
|
+
expect(this.entity.foo).to.be.eq(2);
|
|
465
|
+
expect(this.entity.isTempId).to.be.false;
|
|
466
|
+
});
|
|
467
|
+
|
|
446
468
|
it('_recalculateDependentProperties', function() {
|
|
447
469
|
const schema = new Schema({
|
|
448
470
|
name: 'baz',
|
|
@@ -482,6 +504,7 @@ describe('Entity', function() {
|
|
|
482
504
|
|
|
483
505
|
entity.bar = 'Test';
|
|
484
506
|
entity.markSaved();
|
|
507
|
+
expect(entity.isTempId).to.be.false;
|
|
485
508
|
|
|
486
509
|
expect(entity.isPersisted).to.be.true;
|
|
487
510
|
const expected = {
|
|
@@ -19,6 +19,14 @@ describe('IntegerProperty', function() {
|
|
|
19
19
|
expect(className).to.be.eq('Integer');
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
+
it('newId', function() {
|
|
23
|
+
const id1 = this.property.newId();
|
|
24
|
+
expect(id1.valueOf()).to.be.eq(this.property.idStartsAt);
|
|
25
|
+
|
|
26
|
+
const id2 = this.property.newId();
|
|
27
|
+
expect(id2.valueOf()).to.be.eq(this.property.idStartsAt +1);
|
|
28
|
+
});
|
|
29
|
+
|
|
22
30
|
// it('default value', function() {
|
|
23
31
|
// const property = this.property,
|
|
24
32
|
// rawValue = property.getDefaultValue();
|
|
@@ -112,6 +112,20 @@ describe('Property', function() {
|
|
|
112
112
|
it('getMapping', function() {
|
|
113
113
|
expect(this.property.getMapping()).to.be.eq('id');
|
|
114
114
|
});
|
|
115
|
+
|
|
116
|
+
it('getMapping', function() {
|
|
117
|
+
expect(this.property.getMapping()).to.be.eq('id');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('isTempId', function() {
|
|
121
|
+
const definition = {
|
|
122
|
+
type: 'int',
|
|
123
|
+
isTempId: true,
|
|
124
|
+
},
|
|
125
|
+
Property = PropertyTypes[definition.type];
|
|
126
|
+
const property = new Property(definition);
|
|
127
|
+
expect(property.isTempId).to.be.true;
|
|
128
|
+
});
|
|
115
129
|
|
|
116
130
|
});
|
|
117
131
|
|
|
@@ -10,9 +10,21 @@ describe('StringProperty', function() {
|
|
|
10
10
|
this.property = new Property(definition);
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
describe('general', function() {
|
|
14
|
+
|
|
15
|
+
it('className', function() {
|
|
16
|
+
const className = this.property.getClassName();
|
|
17
|
+
expect(className).to.be.eq('String');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('newId', function() {
|
|
21
|
+
const id1 = this.property.newId();
|
|
22
|
+
expect(id1.valueOf()).to.be.eq('TEMP-1');
|
|
23
|
+
|
|
24
|
+
const id2 = this.property.newId();
|
|
25
|
+
expect(id2.valueOf()).to.be.eq('TEMP-2');
|
|
26
|
+
});
|
|
27
|
+
|
|
16
28
|
});
|
|
17
29
|
|
|
18
30
|
describe('parse', function() {
|
|
@@ -511,6 +511,12 @@ describe('Repository Base', function() {
|
|
|
511
511
|
expect(didFireAdd).to.be.true;
|
|
512
512
|
});
|
|
513
513
|
|
|
514
|
+
it('createStandaloneEntity', async function() {
|
|
515
|
+
const entity = await this.repository.createStandaloneEntity({ key: 6, value: 'six' });
|
|
516
|
+
expect(entity.id).to.be.eq(6);
|
|
517
|
+
expect(_.size(this.repository.entities)).to.be.eq(5);
|
|
518
|
+
});
|
|
519
|
+
|
|
514
520
|
it('addMultiple', async function() {
|
|
515
521
|
await this.repository.addMultiple([
|
|
516
522
|
{ key: 6, value: 'six' },
|
|
@@ -575,6 +581,23 @@ describe('Repository Base', function() {
|
|
|
575
581
|
expect(result.value).to.be.eq('three');
|
|
576
582
|
});
|
|
577
583
|
|
|
584
|
+
it('getById', function() {
|
|
585
|
+
const result = this.repository.getById(3);
|
|
586
|
+
expect(result.value).to.be.eq('three');
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
it('getBy', function() {
|
|
590
|
+
const result = this.repository.getBy(entity => entity.id === 2 || entity.id === 3);
|
|
591
|
+
expect(result.length).to.be.eq(2);
|
|
592
|
+
expect(result[0].value).to.be.eq('two');
|
|
593
|
+
expect(result[1].value).to.be.eq('three');
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
it('getFirstBy', function() {
|
|
597
|
+
const result = this.repository.getFirstBy(entity => entity.id === 3);
|
|
598
|
+
expect(result.value).to.be.eq('three');
|
|
599
|
+
});
|
|
600
|
+
|
|
578
601
|
it('getByRange', function() {
|
|
579
602
|
const result = this.repository.getByRange(1, 4);
|
|
580
603
|
expect(_.size(result)).to.be.eq(4);
|
|
@@ -616,11 +639,18 @@ describe('Repository Base', function() {
|
|
|
616
639
|
expect(_.isEqual(entity, deleted[0])).to.be.true;
|
|
617
640
|
});
|
|
618
641
|
|
|
619
|
-
it('isInRepository', function() {
|
|
642
|
+
it('isInRepository, hasId', function() {
|
|
620
643
|
this.repository.setAutoSave(false);
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
|
|
644
|
+
const id = 1,
|
|
645
|
+
entity = this.repository.getById(id);
|
|
646
|
+
|
|
647
|
+
let result = this.repository.isInRepository(entity);
|
|
648
|
+
expect(result).to.be.true;
|
|
649
|
+
|
|
650
|
+
result = this.repository.isInRepository(id);
|
|
651
|
+
expect(result).to.be.true;
|
|
652
|
+
|
|
653
|
+
result = this.repository.hasId(id);
|
|
624
654
|
expect(result).to.be.true;
|
|
625
655
|
});
|
|
626
656
|
|
package/package.json
CHANGED
package/src/Entity.js
CHANGED
|
@@ -4,8 +4,6 @@ import EventEmitter from '@onehat/events';
|
|
|
4
4
|
import PropertyTypes from './Property';
|
|
5
5
|
import _ from 'lodash';
|
|
6
6
|
|
|
7
|
-
const TEMP_PREFIX = 'TEMP-';
|
|
8
|
-
|
|
9
7
|
/**
|
|
10
8
|
* Class represents a single Entity (i.e. a record)
|
|
11
9
|
* which is a collection of Properties with current values.
|
|
@@ -158,31 +156,24 @@ class Entity extends EventEmitter {
|
|
|
158
156
|
|
|
159
157
|
/**
|
|
160
158
|
* Generates a new unique id and assigns it to this entity.
|
|
161
|
-
* If the idProperty is of type 'uuid', then it generates a new UUID.
|
|
162
|
-
* If not, then it generates a temp id.
|
|
163
159
|
*/
|
|
164
|
-
|
|
160
|
+
createTempId = () => {
|
|
165
161
|
if (this.isDestroyed) {
|
|
166
|
-
throw Error('this.
|
|
162
|
+
throw Error('this.createTempId is no longer valid. Entity has been destroyed.');
|
|
167
163
|
}
|
|
168
164
|
if (!_.isNil(this.id)) {
|
|
169
165
|
throw new Error('Entity id already exists.');
|
|
170
166
|
}
|
|
171
|
-
const idProperty = this.getIdProperty(),
|
|
172
|
-
id = (idProperty.type === 'uuid') ? idProperty.newId() : _.uniqueId(TEMP_PREFIX);
|
|
173
|
-
this.setId(id);
|
|
174
|
-
}
|
|
175
167
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
*/
|
|
181
|
-
static isTempId(id) {
|
|
182
|
-
if (_.isString(id) && id.match(new RegExp('^' + TEMP_PREFIX))) {
|
|
183
|
-
return true;
|
|
168
|
+
const idProperty = this.getIdProperty();
|
|
169
|
+
|
|
170
|
+
if (!idProperty.newId) {
|
|
171
|
+
throw new Error('idProperty.newId() does not exist');
|
|
184
172
|
}
|
|
185
|
-
|
|
173
|
+
|
|
174
|
+
this.setId(idProperty.newId());
|
|
175
|
+
|
|
176
|
+
idProperty.isTempId = true;
|
|
186
177
|
}
|
|
187
178
|
|
|
188
179
|
/**
|
|
@@ -640,7 +631,7 @@ class Entity extends EventEmitter {
|
|
|
640
631
|
let propertyValues = {};
|
|
641
632
|
_.forOwn(this.properties, (property) => {
|
|
642
633
|
const reverseMapped = Entity.getReverseMappedRawValue(property);
|
|
643
|
-
_.
|
|
634
|
+
_.merge(propertyValues, reverseMapped);
|
|
644
635
|
});
|
|
645
636
|
return propertyValues;
|
|
646
637
|
}
|
|
@@ -739,6 +730,14 @@ class Entity extends EventEmitter {
|
|
|
739
730
|
return this.getId();
|
|
740
731
|
}
|
|
741
732
|
|
|
733
|
+
/**
|
|
734
|
+
* Is this Entity's idProperty using a temporary ID?
|
|
735
|
+
* @return {boolean} isTempId
|
|
736
|
+
*/
|
|
737
|
+
get isTempId() {
|
|
738
|
+
return this.getIdProperty().isTempId;
|
|
739
|
+
}
|
|
740
|
+
|
|
742
741
|
/**
|
|
743
742
|
* Gets the "Display" Property object for this Entity.
|
|
744
743
|
* This is the Property whose value can easily identify the whole Entity itself.
|
|
@@ -793,13 +792,13 @@ class Entity extends EventEmitter {
|
|
|
793
792
|
const idProperty = this.getIdProperty(),
|
|
794
793
|
id = idProperty.getSubmitValue();
|
|
795
794
|
|
|
796
|
-
// No
|
|
795
|
+
// No ID
|
|
797
796
|
if (_.isNil(id)) {
|
|
798
797
|
return true;
|
|
799
798
|
}
|
|
800
799
|
|
|
801
|
-
//
|
|
802
|
-
if (
|
|
800
|
+
// ID is temporary
|
|
801
|
+
if (idProperty.isTempId) {
|
|
803
802
|
return true;
|
|
804
803
|
}
|
|
805
804
|
|
|
@@ -851,23 +850,25 @@ class Entity extends EventEmitter {
|
|
|
851
850
|
*/
|
|
852
851
|
setId = (id, force = false) => {
|
|
853
852
|
let isChanged = false;
|
|
854
|
-
const
|
|
853
|
+
const idProperty = this.getIdProperty();
|
|
855
854
|
|
|
856
|
-
|
|
857
|
-
if (
|
|
855
|
+
idProperty.pauseEvents(); // We don't need property_change to fire
|
|
856
|
+
if (idProperty.setValue(id)) {
|
|
858
857
|
isChanged = true;
|
|
859
858
|
}
|
|
860
|
-
|
|
859
|
+
idProperty.resumeEvents();
|
|
861
860
|
|
|
862
861
|
if (isChanged || force) {
|
|
863
862
|
// Set this id on the _originalData* objects
|
|
864
|
-
if (
|
|
865
|
-
_.merge(this._originalData, Entity.getReverseMappedRawValue(
|
|
863
|
+
if (idProperty.hasMapping) {
|
|
864
|
+
_.merge(this._originalData, Entity.getReverseMappedRawValue(idProperty));
|
|
866
865
|
} else {
|
|
867
|
-
this._originalData[
|
|
866
|
+
this._originalData[idProperty.name] = idProperty.getRawValue();
|
|
868
867
|
}
|
|
869
|
-
this._originalDataParsed[
|
|
868
|
+
this._originalDataParsed[idProperty.name] = idProperty.getParsedValue();
|
|
870
869
|
}
|
|
870
|
+
|
|
871
|
+
idProperty.isTempId = false;
|
|
871
872
|
|
|
872
873
|
return isChanged;
|
|
873
874
|
}
|
|
@@ -973,6 +974,7 @@ class Entity extends EventEmitter {
|
|
|
973
974
|
throw Error('this.markSaved is no longer valid. Entity has been destroyed.');
|
|
974
975
|
}
|
|
975
976
|
this.isPersisted = true;
|
|
977
|
+
this.getIdProperty().isTempId = false;
|
|
976
978
|
this._originalData = this._getReconstructedOriginalData();
|
|
977
979
|
this._originalDataParsed = this.getParsedValues();
|
|
978
980
|
}
|
package/src/Property/Integer.js
CHANGED
|
@@ -4,6 +4,8 @@ import Property from './Property';
|
|
|
4
4
|
import Parsers from '../Util/Parsers';
|
|
5
5
|
import _ from 'lodash';
|
|
6
6
|
|
|
7
|
+
let lastId = 0;
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Class represents a Property that stores an integer value.
|
|
9
11
|
* @extends Property
|
|
@@ -15,6 +17,7 @@ export default class IntegerProperty extends Property {
|
|
|
15
17
|
|
|
16
18
|
const defaults = {
|
|
17
19
|
// defaultValue: 0,
|
|
20
|
+
idStartsAt: 100 * 1000 * 1000 * 1000, // 100 billion
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
_.merge(this, defaults, config);
|
|
@@ -29,6 +32,32 @@ export default class IntegerProperty extends Property {
|
|
|
29
32
|
}
|
|
30
33
|
return Parsers.ParseInt(value);
|
|
31
34
|
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Generates a new id
|
|
38
|
+
* Mainly for temporary, in-memory usage
|
|
39
|
+
*/
|
|
40
|
+
newId = () => {
|
|
41
|
+
let id,
|
|
42
|
+
hasId = false;
|
|
43
|
+
|
|
44
|
+
const entity = this.getEntity(),
|
|
45
|
+
repository = entity && entity.repository;
|
|
46
|
+
|
|
47
|
+
if (lastId < this.idStartsAt) {
|
|
48
|
+
lastId = this.idStartsAt;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
id = lastId++;
|
|
52
|
+
hasId = repository ? repository.hasId(id) : false;
|
|
53
|
+
|
|
54
|
+
while(hasId) {
|
|
55
|
+
id = lastId++;
|
|
56
|
+
hasId = repository.hasId(id);
|
|
57
|
+
}
|
|
58
|
+
return id;
|
|
59
|
+
}
|
|
60
|
+
|
|
32
61
|
|
|
33
62
|
};
|
|
34
63
|
|
package/src/Property/Property.js
CHANGED
|
@@ -83,6 +83,12 @@ export default class Property extends EventEmitter {
|
|
|
83
83
|
* @member {boolean} isSortable - Whether this property type is sortable
|
|
84
84
|
*/
|
|
85
85
|
isSortable: true,
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @member {boolean} isTempId - Whether this property's ID is temporary
|
|
89
|
+
*/
|
|
90
|
+
isTempId: false,
|
|
91
|
+
|
|
86
92
|
|
|
87
93
|
|
|
88
94
|
// OneBuild META attributes, just bring these over wholesale for now
|
|
@@ -411,7 +417,7 @@ export default class Property extends EventEmitter {
|
|
|
411
417
|
*/
|
|
412
418
|
getMapping = () => {
|
|
413
419
|
if (this.isDestroyed) {
|
|
414
|
-
throw Error('this.
|
|
420
|
+
throw Error('this.getMapping is no longer valid. Property has been destroyed.');
|
|
415
421
|
}
|
|
416
422
|
return this.mapping;
|
|
417
423
|
}
|
package/src/Property/String.js
CHANGED
|
@@ -4,6 +4,8 @@ import Property from './Property';
|
|
|
4
4
|
import Parsers from '../Util/Parsers';
|
|
5
5
|
import _ from 'lodash';
|
|
6
6
|
|
|
7
|
+
const TEMP_PREFIX = 'TEMP-';
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* Class represents a Property that stores string data.
|
|
9
11
|
* @extends Property
|
|
@@ -29,6 +31,23 @@ export default class StringProperty extends Property {
|
|
|
29
31
|
}
|
|
30
32
|
return Parsers.ParseString(value);
|
|
31
33
|
}
|
|
34
|
+
|
|
35
|
+
newId = () => {
|
|
36
|
+
let id,
|
|
37
|
+
hasId = false;
|
|
38
|
+
|
|
39
|
+
const entity = this.getEntity(),
|
|
40
|
+
repository = entity && entity.repository;
|
|
41
|
+
|
|
42
|
+
id = _.uniqueId(TEMP_PREFIX);
|
|
43
|
+
hasId = repository ? repository.hasId(id) : false;
|
|
44
|
+
|
|
45
|
+
while(hasId) {
|
|
46
|
+
id = _.uniqueId(TEMP_PREFIX);
|
|
47
|
+
hasId = repository.hasId(id);
|
|
48
|
+
}
|
|
49
|
+
return id;
|
|
50
|
+
}
|
|
32
51
|
};
|
|
33
52
|
|
|
34
53
|
StringProperty.className = 'String';
|
package/src/Repository/Ajax.js
CHANGED
package/src/Repository/Memory.js
CHANGED
|
@@ -865,8 +865,8 @@ export default class Repository extends EventEmitter {
|
|
|
865
865
|
this.entities.push(entity);
|
|
866
866
|
|
|
867
867
|
// Create id if needed
|
|
868
|
-
if (entity.isPhantom) {
|
|
869
|
-
entity.
|
|
868
|
+
if (entity.isPhantom) { // i.e. idProperty has no value
|
|
869
|
+
entity.createTempId();
|
|
870
870
|
}
|
|
871
871
|
|
|
872
872
|
this.emit('add', entity);
|
|
@@ -878,6 +878,27 @@ export default class Repository extends EventEmitter {
|
|
|
878
878
|
return entity;
|
|
879
879
|
}
|
|
880
880
|
|
|
881
|
+
/**
|
|
882
|
+
* Creates a new static Entity that does NOT persist in storage medium.
|
|
883
|
+
* @param {object} data - Either raw data object or Entity. If raw data, keys are Property names, Values are Property values.
|
|
884
|
+
* @param {boolean} isPersisted - Whether the new entity should be marked as already being persisted in storage medium.
|
|
885
|
+
* @param {boolean} originalIsMapped - Has data already been mapped according to schema?
|
|
886
|
+
* @return {object} entity - new Entity object
|
|
887
|
+
*/
|
|
888
|
+
createStandaloneEntity = async (data, isPersisted = false, originalIsMapped = false) => {
|
|
889
|
+
if (this.isDestroyed) {
|
|
890
|
+
throw Error('this.createStandaloneEntity is no longer valid. Repository has been destroyed.');
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
const entity = Repository._createEntity(this.schema, data, this, isPersisted, originalIsMapped);
|
|
894
|
+
|
|
895
|
+
if (entity.isPhantom) {
|
|
896
|
+
entity.createTempId();
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
return entity;
|
|
900
|
+
}
|
|
901
|
+
|
|
881
902
|
/**
|
|
882
903
|
* Convenience function to add entity with mapped data.
|
|
883
904
|
*/
|
|
@@ -1043,20 +1064,19 @@ export default class Repository extends EventEmitter {
|
|
|
1043
1064
|
/**
|
|
1044
1065
|
* Get a single Entity by its id
|
|
1045
1066
|
* @param {integer} id - id of record to retrieve
|
|
1046
|
-
* @return {Entity} The Entity with matching id
|
|
1067
|
+
* @return {Entity} The Entity with matching id, or undefined
|
|
1047
1068
|
*/
|
|
1048
1069
|
getById = (id) => {
|
|
1049
1070
|
if (this.isDestroyed) {
|
|
1050
1071
|
throw Error('this.getById is no longer valid. Repository has been destroyed.');
|
|
1051
1072
|
}
|
|
1052
|
-
|
|
1053
|
-
return result.length > 0 ? result[0] : null;
|
|
1073
|
+
return this.getFirstBy(entity => entity.id === id);
|
|
1054
1074
|
}
|
|
1055
1075
|
|
|
1056
1076
|
/**
|
|
1057
1077
|
* Get an array of Entities by supplied filter function
|
|
1058
1078
|
* @param {function} filter - Filter function to apply to all entities
|
|
1059
|
-
* @return {Entity[]} Entities that passed through filter
|
|
1079
|
+
* @return {Entity[]} Entities that passed through filter, or []
|
|
1060
1080
|
*/
|
|
1061
1081
|
getBy = (filter) => {
|
|
1062
1082
|
if (this.isDestroyed) {
|
|
@@ -1072,7 +1092,7 @@ export default class Repository extends EventEmitter {
|
|
|
1072
1092
|
* filters into account. Defaults to false.
|
|
1073
1093
|
*
|
|
1074
1094
|
* @param {function} filter - Filter function to search by
|
|
1075
|
-
* @return {Entity} First Entity found
|
|
1095
|
+
* @return {Entity} First Entity found, or undefined
|
|
1076
1096
|
*/
|
|
1077
1097
|
getFirstBy = (filter) => {
|
|
1078
1098
|
if (this.isDestroyed) {
|
|
@@ -1083,7 +1103,7 @@ export default class Repository extends EventEmitter {
|
|
|
1083
1103
|
|
|
1084
1104
|
/**
|
|
1085
1105
|
* Get all phantom (unsaved) Entities
|
|
1086
|
-
* @return {Entity[]} Array of phantom Entities
|
|
1106
|
+
* @return {Entity[]} Array of phantom Entities, or []
|
|
1087
1107
|
*/
|
|
1088
1108
|
getPhantom = () => {
|
|
1089
1109
|
if (this.isDestroyed) {
|
|
@@ -1094,7 +1114,7 @@ export default class Repository extends EventEmitter {
|
|
|
1094
1114
|
|
|
1095
1115
|
/**
|
|
1096
1116
|
* Get all Entities not yet persisted to a storage medium
|
|
1097
|
-
* @return {Entity[]} Array of dirty Entities
|
|
1117
|
+
* @return {Entity[]} Array of dirty Entities, or []
|
|
1098
1118
|
*/
|
|
1099
1119
|
getNonPersisted = () => {
|
|
1100
1120
|
if (this.isDestroyed) {
|
|
@@ -1107,7 +1127,7 @@ export default class Repository extends EventEmitter {
|
|
|
1107
1127
|
|
|
1108
1128
|
/**
|
|
1109
1129
|
* Get all dirty (having unsaved changes) Entities
|
|
1110
|
-
* @return {Entity[]} Array of dirty Entities
|
|
1130
|
+
* @return {Entity[]} Array of dirty Entities, or []
|
|
1111
1131
|
*/
|
|
1112
1132
|
getDirty = () => {
|
|
1113
1133
|
if (this.isDestroyed) {
|
|
@@ -1120,7 +1140,7 @@ export default class Repository extends EventEmitter {
|
|
|
1120
1140
|
|
|
1121
1141
|
/**
|
|
1122
1142
|
* Get all deleted Entities
|
|
1123
|
-
* @return {Entity[]} Array of deleted Entities
|
|
1143
|
+
* @return {Entity[]} Array of deleted Entities, or []
|
|
1124
1144
|
*/
|
|
1125
1145
|
getDeleted = () => {
|
|
1126
1146
|
if (this.isDestroyed) {
|
|
@@ -1147,6 +1167,15 @@ export default class Repository extends EventEmitter {
|
|
|
1147
1167
|
return !_.isNil(this.getById(idOrEntity));
|
|
1148
1168
|
}
|
|
1149
1169
|
|
|
1170
|
+
/**
|
|
1171
|
+
* Convenience function
|
|
1172
|
+
* Alias for isInRepository
|
|
1173
|
+
* NOTE: It only searches in memory. Doesn't query server
|
|
1174
|
+
*/
|
|
1175
|
+
hasId = (id) => {
|
|
1176
|
+
return this.isInRepository(id);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1150
1179
|
/**
|
|
1151
1180
|
* Queues up batch operations for saving
|
|
1152
1181
|
* new, edited, and deleted entities to storage medium.
|