@onehat/data 1.8.9 → 1.8.12

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.
@@ -232,6 +232,17 @@ describe('Entity', function() {
232
232
  expect(_.isEqual(this.entity.rawValues, expected)).to.be.true;
233
233
  });
234
234
 
235
+ it('getParsedRawValues & parsedRawValues', function() {
236
+ const result = this.entity.getParsedRawValues(),
237
+ expected = {
238
+ foo: 1,
239
+ bar: 'one',
240
+ baz: true,
241
+ };
242
+ expect(_.isEqual(result, expected)).to.be.true;
243
+ expect(_.isEqual(this.entity.parsedRawValues, expected)).to.be.true;
244
+ });
245
+
235
246
  it('getParsedValues & parsedValues', function() {
236
247
  const result = this.entity.getParsedValues(),
237
248
  expected = {
@@ -620,6 +631,22 @@ describe('Entity', function() {
620
631
  lateLastModified = this.entity.lastModified;
621
632
  expect(earlyLastModified < lateLastModified).to.be.true;
622
633
  });
634
+
635
+ it('freeze', function() {
636
+ this.entity.freeze();
637
+ expect(this.entity.isFrozen).to.be.true;
638
+
639
+ this.entity.destroy();
640
+ expect(this.entity.isDestroyed).to.be.false;
641
+
642
+ let isError = false;
643
+ try {
644
+ this.entity.foo = 2;
645
+ } catch(e) {
646
+ isError = true;
647
+ }
648
+ expect(isError).to.be.true;
649
+ });
623
650
  });
624
651
 
625
652
  describe('events', function() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/data",
3
- "version": "1.8.9",
3
+ "version": "1.8.12",
4
4
  "description": "JS data modeling package with adapters for many storage mediums.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/Entity.js CHANGED
@@ -135,6 +135,12 @@ class Entity extends EventEmitter {
135
135
  */
136
136
  this.lastModified = null;
137
137
 
138
+ /**
139
+ * @member {string} isFrozen - Prevent the entity from being destroyed, but don't let it be changed either.
140
+ */
141
+ this.isFrozen = false;
142
+
143
+
138
144
  // This ES6 Proxy allows us to create magic getters and setters for all property values.
139
145
  // However, these getters and setters are *not* available within the Entity itself.
140
146
  this._proxy = new Proxy(this, {
@@ -151,6 +157,9 @@ class Entity extends EventEmitter {
151
157
  return Reflect.get(target, name, receiver);
152
158
  },
153
159
  set (target, name, value, receiver) {
160
+ if (this.isFrozen) {
161
+ throw Error('Entity is frozen.');
162
+ }
154
163
  if (!Reflect.has(target, name)) {
155
164
  target.setValue(name, value);
156
165
  } else {
@@ -584,7 +593,7 @@ class Entity extends EventEmitter {
584
593
  */
585
594
  getRawValues = () => {
586
595
  if (this.isDestroyed) {
587
- throw Error('this.getSubmitValues is no longer valid. Entity has been destroyed.');
596
+ throw Error('this.getRawValues is no longer valid. Entity has been destroyed.');
588
597
  }
589
598
  let propertyValues = {};
590
599
  _.forOwn(this.properties, (property) => {
@@ -604,6 +613,33 @@ class Entity extends EventEmitter {
604
613
  return this.getRawValues();
605
614
  }
606
615
 
616
+ /**
617
+ * Gets an object of values for this Entity,
618
+ * Values are the "raw" values in their parsed form, not the "parsed" or "submit" or "display" values.
619
+ * @return {object} propertyValues
620
+ */
621
+ getParsedRawValues = () => {
622
+ if (this.isDestroyed) {
623
+ throw Error('this.getParsedRawValues is no longer valid. Entity has been destroyed.');
624
+ }
625
+ let propertyValues = {};
626
+ _.forOwn(this.properties, (property) => {
627
+ propertyValues[property.name] = property.getParsedRawValue();
628
+ });
629
+ return propertyValues;
630
+ }
631
+
632
+ /**
633
+ * Gets "raw" values in their parsed form for this Entity.
634
+ * @return {object} values
635
+ */
636
+ get parsedRawValues() {
637
+ if (this.isDestroyed) {
638
+ throw Error('this.parsedRawValues is no longer valid. Entity has been destroyed.');
639
+ }
640
+ return this.getParsedRawValues();
641
+ }
642
+
607
643
  /**
608
644
  * Gets an object of values for this Entity,
609
645
  * Values are the "parsed" values, not the "raw" or "submit" or "display" values.
@@ -726,7 +762,7 @@ class Entity extends EventEmitter {
726
762
  */
727
763
  getChanged = () => {
728
764
  const original = this._originalDataParsed,
729
- current = this.getRawValues(),
765
+ current = this.getParsedRawValues(),
730
766
  diff = Object.keys(original).reduce((result, key) => { // from https://stackoverflow.com/a/40610459/9163076
731
767
  if (current && !current.hasOwnProperty(key)) {
732
768
  result.push(key);
@@ -984,6 +1020,9 @@ class Entity extends EventEmitter {
984
1020
  * @return {boolean} isChanged - Whether id was actually changed
985
1021
  */
986
1022
  setId = (id, force = false) => {
1023
+ if (this.isFrozen) {
1024
+ throw Error('Entity is frozen.');
1025
+ }
987
1026
  let isChanged = false;
988
1027
  const idProperty = this.getIdProperty();
989
1028
 
@@ -1018,6 +1057,9 @@ class Entity extends EventEmitter {
1018
1057
  * @return {boolean} isChanged - Whether any values were actually changed
1019
1058
  */
1020
1059
  setValue = (propertyName, rawValue) => {
1060
+ if (this.isFrozen) {
1061
+ throw Error('Entity is frozen.');
1062
+ }
1021
1063
  if (this.isDestroyed) {
1022
1064
  throw Error('this.setValue is no longer valid. Entity has been destroyed.');
1023
1065
  }
@@ -1034,6 +1076,9 @@ class Entity extends EventEmitter {
1034
1076
  * @return {boolean} isChanged - Whether any values were actually changed
1035
1077
  */
1036
1078
  setRawValues = (rawData) => {
1079
+ if (this.isFrozen) {
1080
+ throw Error('Entity is frozen.');
1081
+ }
1037
1082
  if (this.isDestroyed) {
1038
1083
  throw Error('this.setRawValues is no longer valid. Entity has been destroyed.');
1039
1084
  }
@@ -1068,6 +1113,9 @@ class Entity extends EventEmitter {
1068
1113
  * @fires change
1069
1114
  */
1070
1115
  setValues = (data) => {
1116
+ if (this.isFrozen) {
1117
+ throw Error('Entity is frozen.');
1118
+ }
1071
1119
  if (this.isDestroyed) {
1072
1120
  throw Error('this.setValues is no longer valid. Entity has been destroyed.');
1073
1121
  }
@@ -1129,6 +1177,9 @@ class Entity extends EventEmitter {
1129
1177
  * @fires save
1130
1178
  */
1131
1179
  save = () => {
1180
+ if (this.isFrozen) {
1181
+ throw Error('Entity is frozen.');
1182
+ }
1132
1183
  if (this.isDestroyed) {
1133
1184
  throw Error('this.save is no longer valid. Entity has been destroyed.');
1134
1185
  }
@@ -1142,6 +1193,9 @@ class Entity extends EventEmitter {
1142
1193
  * Marks an entity as having been saved to storage medium.
1143
1194
  */
1144
1195
  markSaved = () => {
1196
+ if (this.isFrozen) {
1197
+ throw Error('Entity is frozen.');
1198
+ }
1145
1199
  if (this.isDestroyed) {
1146
1200
  throw Error('this.markSaved is no longer valid. Entity has been destroyed.');
1147
1201
  }
@@ -1157,6 +1211,9 @@ class Entity extends EventEmitter {
1157
1211
  * @param {boolean} bool - How it should be marked. Defaults to true.
1158
1212
  */
1159
1213
  markDeleted = (bool = true) => {
1214
+ if (this.isFrozen) {
1215
+ throw Error('Entity is frozen.');
1216
+ }
1160
1217
  if (this.isDestroyed) {
1161
1218
  throw Error('this.markDeleted is no longer valid. Entity has been destroyed.');
1162
1219
  }
@@ -1168,6 +1225,9 @@ class Entity extends EventEmitter {
1168
1225
  * @fires delete
1169
1226
  */
1170
1227
  delete = () => {
1228
+ if (this.isFrozen) {
1229
+ throw Error('Entity is frozen.');
1230
+ }
1171
1231
  if (this.isDestroyed) {
1172
1232
  throw Error('this.delete is no longer valid. Entity has been destroyed.');
1173
1233
  }
@@ -1184,6 +1244,9 @@ class Entity extends EventEmitter {
1184
1244
  * @fires delete
1185
1245
  */
1186
1246
  undelete = () => {
1247
+ if (this.isFrozen) {
1248
+ throw Error('Entity is frozen.');
1249
+ }
1187
1250
  if (this.isDestroyed) {
1188
1251
  throw Error('this.undelete is no longer valid. Entity has been destroyed.');
1189
1252
  }
@@ -1200,6 +1263,9 @@ class Entity extends EventEmitter {
1200
1263
  * @param {boolean} bool - How it should be marked. Defaults to true.
1201
1264
  */
1202
1265
  markStaged = (bool = true) => {
1266
+ if (this.isFrozen) {
1267
+ throw Error('Entity is frozen.');
1268
+ }
1203
1269
  if (this.isDestroyed) {
1204
1270
  throw Error('this.markStaged is no longer valid. Entity has been destroyed.');
1205
1271
  }
@@ -1213,6 +1279,13 @@ class Entity extends EventEmitter {
1213
1279
  this.markStaged(true);
1214
1280
  }
1215
1281
 
1282
+ /**
1283
+ * Prevent the entity from being destroyed, but don't let it be changed either.
1284
+ */
1285
+ freeze = () => {
1286
+ this.isFrozen = true;
1287
+ }
1288
+
1216
1289
  /**
1217
1290
  * Destroy this object.
1218
1291
  * - Removes all circular references to parent objects
@@ -1221,6 +1294,9 @@ class Entity extends EventEmitter {
1221
1294
  * @fires destroy
1222
1295
  */
1223
1296
  destroy = () => {
1297
+ if (this.isFrozen) {
1298
+ return;
1299
+ }
1224
1300
  this._id = this.id; // save id, so we can query it later--even on a destroyed entity
1225
1301
 
1226
1302
  // parent objects
@@ -183,7 +183,7 @@ export default class Property extends EventEmitter {
183
183
  }
184
184
 
185
185
  /**
186
- * Gets "raw" value, prior to any parsing
186
+ * Gets "raw" value
187
187
  * @return {any} rawValue
188
188
  */
189
189
  getRawValue = () => {
@@ -193,6 +193,17 @@ export default class Property extends EventEmitter {
193
193
  return this.rawValue;
194
194
  }
195
195
 
196
+ /**
197
+ * Gets "raw" value in its parsed form
198
+ * @return {any} rawValue
199
+ */
200
+ getParsedRawValue = () => {
201
+ if (this.isDestroyed) {
202
+ throw Error('this.getParsedRawValue is no longer valid. Property has been destroyed.');
203
+ }
204
+ return this.parse(this.rawValue);
205
+ }
206
+
196
207
  /**
197
208
  * Gets "parsed" value, without any formatting applied
198
209
  * @return {any} parsedValue
@@ -285,7 +285,7 @@ class LocalFromRemoteRepository extends EventEmitter {
285
285
  /**
286
286
  * Syncs local and remote repositories, based on operation mode.
287
287
  */
288
- sync = async (entity) => {
288
+ sync = async (entity, callback = null) => {
289
289
  try {
290
290
  if (!this.isOnline) {
291
291
  this._doAutoSync(true);
@@ -405,6 +405,9 @@ class LocalFromRemoteRepository extends EventEmitter {
405
405
  } finally {
406
406
  this.isSyncing = false;
407
407
  this.emit('endSync', this);
408
+ if (callback) {
409
+ callback();
410
+ }
408
411
  }
409
412
 
410
413
  }