@onehat/data 1.7.5 → 1.7.6
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.
|
@@ -525,6 +525,7 @@ describe('Entity', function() {
|
|
|
525
525
|
entity.bar = 'Test';
|
|
526
526
|
entity.markSaved();
|
|
527
527
|
expect(entity.isTempId).to.be.false;
|
|
528
|
+
expect(entity.isStaged).to.be.false;
|
|
528
529
|
|
|
529
530
|
expect(entity.isPersisted).to.be.true;
|
|
530
531
|
const expected = {
|
|
@@ -557,6 +558,16 @@ describe('Entity', function() {
|
|
|
557
558
|
this.entity.undelete();
|
|
558
559
|
expect(this.entity.isDeleted).to.be.false;
|
|
559
560
|
});
|
|
561
|
+
|
|
562
|
+
it('markStaged, stage', function() {
|
|
563
|
+
expect(this.entity.isStaged).to.be.false;
|
|
564
|
+
|
|
565
|
+
this.entity.stage();
|
|
566
|
+
expect(this.entity.isStaged).to.be.true;
|
|
567
|
+
|
|
568
|
+
this.entity.markStaged(false);
|
|
569
|
+
expect(this.entity.isStaged).to.be.false;
|
|
570
|
+
});
|
|
560
571
|
});
|
|
561
572
|
|
|
562
573
|
describe('events', function() {
|
|
@@ -650,8 +650,12 @@ describe('Repository Base', function() {
|
|
|
650
650
|
it('getNonPersisted', async function() {
|
|
651
651
|
this.repository.setAutoSave(false);
|
|
652
652
|
const entity = await this.repository.add({ value: 'six' }),
|
|
653
|
-
|
|
653
|
+
entities = this.repository.entities;
|
|
654
654
|
|
|
655
|
+
let nonPersisted = this.repository.getNonPersisted();
|
|
656
|
+
expect(_.isEqual(entity, nonPersisted[0])).to.be.true;
|
|
657
|
+
|
|
658
|
+
nonPersisted = this.repository.getNonPersisted(entities);
|
|
655
659
|
expect(_.isEqual(entity, nonPersisted[0])).to.be.true;
|
|
656
660
|
});
|
|
657
661
|
|
|
@@ -690,6 +694,15 @@ describe('Repository Base', function() {
|
|
|
690
694
|
expect(_.isEqual(entity, deleted[0])).to.be.true;
|
|
691
695
|
});
|
|
692
696
|
|
|
697
|
+
it('getStaged', function() {
|
|
698
|
+
this.repository.setAutoSave(false);
|
|
699
|
+
const entity = this.repository.getByIx(0);
|
|
700
|
+
|
|
701
|
+
entity.isStaged = true;
|
|
702
|
+
const staged = this.repository.getStaged();
|
|
703
|
+
expect(_.isEqual(entity, staged[0])).to.be.true;
|
|
704
|
+
});
|
|
705
|
+
|
|
693
706
|
it('isInRepository, hasId', function() {
|
|
694
707
|
this.repository.setAutoSave(false);
|
|
695
708
|
const id = 1,
|
|
@@ -720,6 +733,9 @@ describe('Repository Base', function() {
|
|
|
720
733
|
this.repository.add({ value: 'six' });
|
|
721
734
|
|
|
722
735
|
expect(didFire).to.be.true;
|
|
736
|
+
|
|
737
|
+
// TODO: Need comprehensive test of save(), not just event firing
|
|
738
|
+
|
|
723
739
|
});
|
|
724
740
|
|
|
725
741
|
it('save by entity', async function() {
|
package/package.json
CHANGED
package/src/Entity.js
CHANGED
|
@@ -117,6 +117,12 @@ class Entity extends EventEmitter {
|
|
|
117
117
|
*/
|
|
118
118
|
this.isDeleted = false;
|
|
119
119
|
|
|
120
|
+
/**
|
|
121
|
+
* @member {boolean} isStaged - Whether this object has been marked for saving
|
|
122
|
+
* @private
|
|
123
|
+
*/
|
|
124
|
+
this.isStaged = false;
|
|
125
|
+
|
|
120
126
|
/**
|
|
121
127
|
* @member {boolean} isDestroyed - Whether this object has been destroyed
|
|
122
128
|
* @private
|
|
@@ -1057,6 +1063,7 @@ class Entity extends EventEmitter {
|
|
|
1057
1063
|
this.getIdProperty().isTempId = false;
|
|
1058
1064
|
this._originalData = this._getReconstructedOriginalData();
|
|
1059
1065
|
this._originalDataParsed = this.getParsedValues();
|
|
1066
|
+
this.markStaged(false);
|
|
1060
1067
|
}
|
|
1061
1068
|
|
|
1062
1069
|
/**
|
|
@@ -1102,6 +1109,24 @@ class Entity extends EventEmitter {
|
|
|
1102
1109
|
this.emit('undelete', this._proxy);
|
|
1103
1110
|
}
|
|
1104
1111
|
|
|
1112
|
+
/**
|
|
1113
|
+
* Marks an entity as having been staged for saving.
|
|
1114
|
+
* @param {boolean} bool - How it should be marked. Defaults to true.
|
|
1115
|
+
*/
|
|
1116
|
+
markStaged = (bool = true) => {
|
|
1117
|
+
if (this.isDestroyed) {
|
|
1118
|
+
throw Error('this.markStaged is no longer valid. Entity has been destroyed.');
|
|
1119
|
+
}
|
|
1120
|
+
this.isStaged = bool;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Convenience function.
|
|
1125
|
+
*/
|
|
1126
|
+
stage = () => {
|
|
1127
|
+
this.markStaged(true);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1105
1130
|
/**
|
|
1106
1131
|
* Destroy this object.
|
|
1107
1132
|
* - Removes all circular references to parent objects
|
|
@@ -1135,52 +1135,120 @@ export default class Repository extends EventEmitter {
|
|
|
1135
1135
|
|
|
1136
1136
|
/**
|
|
1137
1137
|
* Get all phantom (unsaved) Entities
|
|
1138
|
+
* @param {array} entities - Array of entities to filter. Optional. Defaults to this.entities
|
|
1138
1139
|
* @return {Entity[]} Array of phantom Entities, or []
|
|
1139
1140
|
*/
|
|
1140
|
-
getPhantom = () => {
|
|
1141
|
+
getPhantom = (entities = null) => {
|
|
1141
1142
|
if (this.isDestroyed) {
|
|
1142
1143
|
throw Error('this.getPhantom is no longer valid. Repository has been destroyed.');
|
|
1143
1144
|
}
|
|
1144
|
-
|
|
1145
|
+
if (!entities) {
|
|
1146
|
+
entities = this.entities;
|
|
1147
|
+
}
|
|
1148
|
+
return _.filter(this.entities, entity => entity.isPhantom);
|
|
1145
1149
|
}
|
|
1146
1150
|
|
|
1147
1151
|
/**
|
|
1148
1152
|
* Get all Entities not yet persisted to a storage medium
|
|
1153
|
+
* @param {array} entities - Array of entities to filter. Optional. Defaults to this.entities
|
|
1149
1154
|
* @return {Entity[]} Array of dirty Entities, or []
|
|
1150
1155
|
*/
|
|
1151
|
-
getNonPersisted = () => {
|
|
1156
|
+
getNonPersisted = (entities = null) => {
|
|
1152
1157
|
if (this.isDestroyed) {
|
|
1153
1158
|
throw Error('this.getDirty is no longer valid. Repository has been destroyed.');
|
|
1154
1159
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
}
|
|
1160
|
+
if (!entities) {
|
|
1161
|
+
entities = this.entities;
|
|
1162
|
+
}
|
|
1163
|
+
return _.filter(this.entities, entity => !entity.isPersisted);
|
|
1158
1164
|
}
|
|
1159
1165
|
|
|
1160
1166
|
/**
|
|
1161
1167
|
* Get all dirty (having unsaved changes) Entities
|
|
1168
|
+
* @param {array} entities - Array of entities to filter. Optional. Defaults to this.entities
|
|
1162
1169
|
* @return {Entity[]} Array of dirty Entities, or []
|
|
1163
1170
|
*/
|
|
1164
|
-
getDirty = () => {
|
|
1171
|
+
getDirty = (entities = null) => {
|
|
1165
1172
|
if (this.isDestroyed) {
|
|
1166
1173
|
throw Error('this.getDirty is no longer valid. Repository has been destroyed.');
|
|
1167
1174
|
}
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
}
|
|
1175
|
+
if (!entities) {
|
|
1176
|
+
entities = this.entities;
|
|
1177
|
+
}
|
|
1178
|
+
return _.filter(entities, entity => entity.isDirty);
|
|
1171
1179
|
}
|
|
1172
1180
|
|
|
1173
1181
|
/**
|
|
1174
1182
|
* Get all deleted Entities
|
|
1183
|
+
* @param {array} entities - Array of entities to filter. Optional. Defaults to this.entities
|
|
1175
1184
|
* @return {Entity[]} Array of deleted Entities, or []
|
|
1176
1185
|
*/
|
|
1177
|
-
getDeleted = () => {
|
|
1186
|
+
getDeleted = (entities = null) => {
|
|
1178
1187
|
if (this.isDestroyed) {
|
|
1179
1188
|
throw Error('this.getDeleted is no longer valid. Repository has been destroyed.');
|
|
1180
1189
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
}
|
|
1190
|
+
if (!entities) {
|
|
1191
|
+
entities = this.entities;
|
|
1192
|
+
}
|
|
1193
|
+
return _.filter(entities, entity => entity.isDeleted);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
/**
|
|
1197
|
+
* Get all staged Entities
|
|
1198
|
+
* @param {array} entities - Array of entities to filter. Optional. Defaults to this.entities
|
|
1199
|
+
* @return {Entity[]} Array of deleted Entities, or []
|
|
1200
|
+
*/
|
|
1201
|
+
getStaged = (entities = null) => {
|
|
1202
|
+
if (this.isDestroyed) {
|
|
1203
|
+
throw Error('this.getStaged is no longer valid. Repository has been destroyed.');
|
|
1204
|
+
}
|
|
1205
|
+
if (!entities) {
|
|
1206
|
+
entities = this.entities;
|
|
1207
|
+
}
|
|
1208
|
+
return _.filter(entities, entity => entity.isStaged);
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/**
|
|
1212
|
+
* Gets the Schema object
|
|
1213
|
+
* @return {Schema} schema
|
|
1214
|
+
*/
|
|
1215
|
+
getSchema = () => {
|
|
1216
|
+
if (this.isDestroyed) {
|
|
1217
|
+
throw Error('this.getSchema is no longer valid. Entity has been destroyed.');
|
|
1218
|
+
}
|
|
1219
|
+
return this.schema;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* Gets the associated Repository
|
|
1224
|
+
* @param {string} repositoryName - Name of the Repository to retrieve
|
|
1225
|
+
* @return {boolean} hasProperty
|
|
1226
|
+
*/
|
|
1227
|
+
getAssociatedRepository = (repositoryName) => {
|
|
1228
|
+
if (this.isDestroyed) {
|
|
1229
|
+
throw Error('this.getAssociatedRepository is no longer valid. Entity has been destroyed.');
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
const schema = this.getSchema();
|
|
1233
|
+
if (!schema.model.associations.hasOne.includes(repositoryName) &&
|
|
1234
|
+
!schema.model.associations.hasMany.includes(repositoryName) &&
|
|
1235
|
+
!schema.model.associations.belongsTo.includes(repositoryName) &&
|
|
1236
|
+
!schema.model.associations.belongsToMany.includes(repositoryName)
|
|
1237
|
+
) {
|
|
1238
|
+
throw Error(repositoryName + ' is not associated with this schema');
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
const oneHatData = this.oneHatData;
|
|
1242
|
+
if (!oneHatData) {
|
|
1243
|
+
throw Error('No global oneHatData object');
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
const associatedRepository = oneHatData.getRepository(repositoryName);
|
|
1247
|
+
if (!associatedRepository) {
|
|
1248
|
+
throw Error('Repository ' + repositoryName + ' cannot be found');
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
return associatedRepository;
|
|
1184
1252
|
}
|
|
1185
1253
|
|
|
1186
1254
|
/**
|
|
@@ -1271,8 +1339,9 @@ export default class Repository extends EventEmitter {
|
|
|
1271
1339
|
* this.entities until all operations have completed. We leave it to subclasses
|
|
1272
1340
|
* to implement that.
|
|
1273
1341
|
* @param {object} entity - Optional single entity to save (instead of doing a batch operation on everything)
|
|
1342
|
+
* @param {boolean} useStaged - Save only the staged items, not all
|
|
1274
1343
|
*/
|
|
1275
|
-
save = async (entity = null) => {
|
|
1344
|
+
save = async (entity = null, useStaged = false) => {
|
|
1276
1345
|
if (this.isDestroyed) {
|
|
1277
1346
|
throw Error('this.save is no longer valid. Repository has been destroyed.');
|
|
1278
1347
|
}
|
|
@@ -1315,6 +1384,9 @@ export default class Repository extends EventEmitter {
|
|
|
1315
1384
|
switch(operation) {
|
|
1316
1385
|
case 'add':
|
|
1317
1386
|
entities = this.getNonPersisted();
|
|
1387
|
+
if (useStaged) {
|
|
1388
|
+
entities = this.getStaged(entities);
|
|
1389
|
+
}
|
|
1318
1390
|
if (_.size(entities) > 0) {
|
|
1319
1391
|
if (this.combineBatch) {
|
|
1320
1392
|
|
|
@@ -1339,6 +1411,9 @@ export default class Repository extends EventEmitter {
|
|
|
1339
1411
|
break;
|
|
1340
1412
|
case 'edit':
|
|
1341
1413
|
entities = this.getDirty();
|
|
1414
|
+
if (useStaged) {
|
|
1415
|
+
entities = this.getStaged(entities);
|
|
1416
|
+
}
|
|
1342
1417
|
if (_.size(entities) > 0) {
|
|
1343
1418
|
if (this.combineBatch) {
|
|
1344
1419
|
|
|
@@ -1363,6 +1438,9 @@ export default class Repository extends EventEmitter {
|
|
|
1363
1438
|
break;
|
|
1364
1439
|
case 'delete':
|
|
1365
1440
|
entities = this.getDeleted();
|
|
1441
|
+
if (useStaged) {
|
|
1442
|
+
entities = this.getStaged(entities);
|
|
1443
|
+
}
|
|
1366
1444
|
if (_.size(entities) > 0) {
|
|
1367
1445
|
if (this.combineBatch) {
|
|
1368
1446
|
|
|
@@ -1520,7 +1598,7 @@ export default class Repository extends EventEmitter {
|
|
|
1520
1598
|
* Mainly used for phantom Entities
|
|
1521
1599
|
* Helper for delete()
|
|
1522
1600
|
*/
|
|
1523
|
-
|
|
1601
|
+
removeEntity = async (entity) => {
|
|
1524
1602
|
this.entities = _.filter(this.entities, e => e !== entity);
|
|
1525
1603
|
entity.destroy();
|
|
1526
1604
|
}
|