@onehat/data 1.15.7 → 1.16.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/package.json +2 -2
- package/src/Entity.js +27 -5
- package/src/Repository/Ajax.js +46 -8
- package/src/Repository/Repository.js +27 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onehat/data",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.1",
|
|
4
4
|
"description": "JS data modeling package with adapters for many storage mediums.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"cypress": "5.2.0",
|
|
64
64
|
"ink-docstrap": "^1.3.2",
|
|
65
65
|
"jsdoc": "^4.0.0",
|
|
66
|
-
"webpack": "^5.
|
|
66
|
+
"webpack": "^5.76.0",
|
|
67
67
|
"joi": "^17.7.0",
|
|
68
68
|
"yup": "^0.32.11"
|
|
69
69
|
|
package/src/Entity.js
CHANGED
|
@@ -32,9 +32,10 @@ class Entity extends EventEmitter {
|
|
|
32
32
|
* @param {Schema} schema - Schema object
|
|
33
33
|
* @param {object} rawData - Raw data object. Keys are Property names, Values are Property values.
|
|
34
34
|
* @param {Repository} repository
|
|
35
|
-
* @param {boolean} - Has
|
|
35
|
+
* @param {boolean} originalIsMapped - Has data already been mapped according to schema?
|
|
36
|
+
* @param {boolean} isDelayedSave - Should the repository skip autosave when immediately adding the record?
|
|
36
37
|
*/
|
|
37
|
-
constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false) {
|
|
38
|
+
constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false, isRemotePhantomMode = false) {
|
|
38
39
|
super(...arguments);
|
|
39
40
|
|
|
40
41
|
if (!schema) {
|
|
@@ -133,11 +134,26 @@ class Entity extends EventEmitter {
|
|
|
133
134
|
this.isDestroyed = false;
|
|
134
135
|
|
|
135
136
|
/**
|
|
136
|
-
* @member {boolean} isFrozen - Prevent the entity from being
|
|
137
|
+
* @member {boolean} isFrozen - Prevent the entity from being autoSaved on add, so an editor can change it before it gets saved to remote storage.
|
|
137
138
|
* @public
|
|
138
139
|
*/
|
|
139
140
|
this.isDelayedSave = isDelayedSave;
|
|
140
141
|
|
|
142
|
+
/**
|
|
143
|
+
* @member {boolean} isRemotePhantomMode - Whether this Entity uses the "alternate" CRUD mode, with tempIds from server (see OneBuild repository)
|
|
144
|
+
* On a Repository, this mode overrides repository.isAutoSave, entity.isPersisted, && entity.isDelayedSave.
|
|
145
|
+
* On an Entity, this mode affects the isPhantom getter.
|
|
146
|
+
* @readonly
|
|
147
|
+
*/
|
|
148
|
+
this.isRemotePhantomMode = isRemotePhantomMode;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @member {boolean} isRemotePhantom - Whether this entity is actually phantom on server; used only when this.isRemotePhantomMode.
|
|
152
|
+
* If this.isRemotePhantomMode, isRemotePhantom defaults to true for all new Entities.
|
|
153
|
+
* @public
|
|
154
|
+
*/
|
|
155
|
+
this.isRemotePhantom = this.isRemotePhantomMode;
|
|
156
|
+
|
|
141
157
|
/**
|
|
142
158
|
* @member {boolean} lastModified - Last time this entity was modified
|
|
143
159
|
* @public
|
|
@@ -945,9 +961,15 @@ class Entity extends EventEmitter {
|
|
|
945
961
|
if (this.isDestroyed) {
|
|
946
962
|
throw Error('this.isPhantom is no longer valid. Entity has been destroyed.');
|
|
947
963
|
}
|
|
948
|
-
const idProperty = this.getIdProperty(),
|
|
949
|
-
id = idProperty.getSubmitValue();
|
|
950
964
|
|
|
965
|
+
if (this.isRemotePhantomMode) {
|
|
966
|
+
return this.isRemotePhantom;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
const
|
|
970
|
+
idProperty = this.getIdProperty(),
|
|
971
|
+
id = idProperty.getSubmitValue();
|
|
972
|
+
|
|
951
973
|
// No ID
|
|
952
974
|
if (_.isNil(id)) {
|
|
953
975
|
return true;
|
package/src/Repository/Ajax.js
CHANGED
|
@@ -533,10 +533,15 @@ class AjaxRepository extends Repository {
|
|
|
533
533
|
|
|
534
534
|
this._operations.add = true;
|
|
535
535
|
|
|
536
|
-
const
|
|
536
|
+
const
|
|
537
|
+
method = this.methods.add,
|
|
537
538
|
url = this.api.add,
|
|
538
539
|
data = entity.getSubmitValues();
|
|
539
540
|
|
|
541
|
+
if (entity.isRemotePhantomMode) {
|
|
542
|
+
data.isRemotePhantom = true;
|
|
543
|
+
}
|
|
544
|
+
|
|
540
545
|
return this._send(method, url, data)
|
|
541
546
|
.then(result => {
|
|
542
547
|
if (this.debugMode) {
|
|
@@ -555,6 +560,9 @@ class AjaxRepository extends Repository {
|
|
|
555
560
|
}
|
|
556
561
|
|
|
557
562
|
entity.loadOriginalData(root[0]);
|
|
563
|
+
if (entity.isRemotePhantomMode) {
|
|
564
|
+
entity.isRemotePhantom = true;
|
|
565
|
+
}
|
|
558
566
|
});
|
|
559
567
|
}
|
|
560
568
|
|
|
@@ -573,10 +581,17 @@ class AjaxRepository extends Repository {
|
|
|
573
581
|
|
|
574
582
|
this._operations.add = true;
|
|
575
583
|
|
|
576
|
-
const
|
|
584
|
+
const
|
|
585
|
+
method = this.methods.add,
|
|
577
586
|
url = this.api.batchAdd,
|
|
578
587
|
data = {
|
|
579
|
-
entities: _.map(entities, entity =>
|
|
588
|
+
entities: _.map(entities, entity => {
|
|
589
|
+
const values = entity.submitValues;
|
|
590
|
+
if (entity.isRemotePhantomMode) {
|
|
591
|
+
values.isRemotePhantom = true;
|
|
592
|
+
}
|
|
593
|
+
return values;
|
|
594
|
+
}),
|
|
580
595
|
};
|
|
581
596
|
|
|
582
597
|
return this._send(method, url, data)
|
|
@@ -600,6 +615,9 @@ class AjaxRepository extends Repository {
|
|
|
600
615
|
// TODO: Check this
|
|
601
616
|
_.each(entities, (entity, ix) => {
|
|
602
617
|
entity.loadOriginalData(root[ix]);
|
|
618
|
+
if (entity.isRemotePhantomMode) {
|
|
619
|
+
entity.isRemotePhantom = true;
|
|
620
|
+
}
|
|
603
621
|
});
|
|
604
622
|
});
|
|
605
623
|
}
|
|
@@ -617,10 +635,15 @@ class AjaxRepository extends Repository {
|
|
|
617
635
|
|
|
618
636
|
this._operations.edit = true;
|
|
619
637
|
|
|
620
|
-
const
|
|
638
|
+
const
|
|
639
|
+
method = this.methods.edit,
|
|
621
640
|
url = this.api.edit,
|
|
622
641
|
data = entity.getSubmitValues();
|
|
623
642
|
|
|
643
|
+
if (entity.isRemotePhantomMode) {
|
|
644
|
+
data.isRemotePhantom = false;
|
|
645
|
+
}
|
|
646
|
+
|
|
624
647
|
return this._send(method, url, data)
|
|
625
648
|
.then(result => {
|
|
626
649
|
if (this.debugMode) {
|
|
@@ -639,6 +662,9 @@ class AjaxRepository extends Repository {
|
|
|
639
662
|
}
|
|
640
663
|
|
|
641
664
|
entity.loadOriginalData(root[0]);
|
|
665
|
+
if (entity.isRemotePhantomMode && entity.isRemotePhantom) {
|
|
666
|
+
entity.isRemotePhantom = false;
|
|
667
|
+
}
|
|
642
668
|
});
|
|
643
669
|
}
|
|
644
670
|
|
|
@@ -657,10 +683,17 @@ class AjaxRepository extends Repository {
|
|
|
657
683
|
|
|
658
684
|
this._operations.edit = true;
|
|
659
685
|
|
|
660
|
-
const
|
|
686
|
+
const
|
|
687
|
+
method = this.methods.edit,
|
|
661
688
|
url = this.api.batchEdit,
|
|
662
689
|
data = {
|
|
663
|
-
entities: _.map(entities, entity =>
|
|
690
|
+
entities: _.map(entities, entity => {
|
|
691
|
+
const values = entity.submitValues;
|
|
692
|
+
if (entity.isRemotePhantomMode) {
|
|
693
|
+
values.isRemotePhantom = false;
|
|
694
|
+
}
|
|
695
|
+
return values;
|
|
696
|
+
}),
|
|
664
697
|
};
|
|
665
698
|
|
|
666
699
|
return this._send(method, url, data)
|
|
@@ -684,6 +717,9 @@ class AjaxRepository extends Repository {
|
|
|
684
717
|
// TODO: Check this
|
|
685
718
|
_.each(entities, (entity, ix) => {
|
|
686
719
|
entity.loadOriginalData(root[ix]);
|
|
720
|
+
if (entity.isRemotePhantomMode && entity.isRemotePhantom) {
|
|
721
|
+
entity.isRemotePhantom = false;
|
|
722
|
+
}
|
|
687
723
|
});
|
|
688
724
|
});
|
|
689
725
|
}
|
|
@@ -701,7 +737,8 @@ class AjaxRepository extends Repository {
|
|
|
701
737
|
|
|
702
738
|
this._operations.delete = true;
|
|
703
739
|
|
|
704
|
-
const
|
|
740
|
+
const
|
|
741
|
+
method = this.methods.delete,
|
|
705
742
|
url = this.api.delete,
|
|
706
743
|
data = { id: entity.id, };
|
|
707
744
|
|
|
@@ -744,7 +781,8 @@ class AjaxRepository extends Repository {
|
|
|
744
781
|
|
|
745
782
|
this._operations.delete = true;
|
|
746
783
|
|
|
747
|
-
const
|
|
784
|
+
const
|
|
785
|
+
method = this.methods.delete,
|
|
748
786
|
url = this.api.batchDelete,
|
|
749
787
|
ids = _.map(entities, entity => entity.id),
|
|
750
788
|
data = { ids, };
|
|
@@ -86,6 +86,17 @@ export default class Repository extends EventEmitter {
|
|
|
86
86
|
*/
|
|
87
87
|
isRemoteSort: false,
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* @member {boolean} isRemotePhantomMode - Whether this Repository uses the "alternate" CRUD mode.
|
|
91
|
+
* In this CRUD mode, records are *immediately* saved to server when added to Repository,
|
|
92
|
+
* but still marked as "phantom" until the their first "edit" operation takes place.
|
|
93
|
+
*
|
|
94
|
+
* This mode overrides repository.isAutoSave, entity.isPersisted, && entity.isDelayedSave.
|
|
95
|
+
*
|
|
96
|
+
* @readonly
|
|
97
|
+
*/
|
|
98
|
+
isRemotePhantomMode: false,
|
|
99
|
+
|
|
89
100
|
/**
|
|
90
101
|
* @member {boolean} isPaginated - Whether this Repository is paginated
|
|
91
102
|
*/
|
|
@@ -297,7 +308,7 @@ export default class Repository extends EventEmitter {
|
|
|
297
308
|
const methodDefinitions = this.schema.repository.methods || this.originalConfig.methods; // The latter is mainly for lfr repositories
|
|
298
309
|
if (!_.isEmpty(methodDefinitions)) {
|
|
299
310
|
_.each(methodDefinitions, (method, name) => {
|
|
300
|
-
this[name] = method; // NOTE: Methods must be defined in schema as "function() {}", not as "() => {}" so "this" will be
|
|
311
|
+
this[name] = method; // NOTE: Methods must be defined in schema as "function() {}", not as "() => {}" so scope of "this" will be correct
|
|
301
312
|
});
|
|
302
313
|
}
|
|
303
314
|
}
|
|
@@ -977,19 +988,19 @@ export default class Repository extends EventEmitter {
|
|
|
977
988
|
let entity = data;
|
|
978
989
|
if (!(data instanceof Entity)) {
|
|
979
990
|
// Create the new entity
|
|
980
|
-
entity = Repository._createEntity(this.schema, data, this, isPersisted, originalIsMapped, isDelayedSave);
|
|
991
|
+
entity = Repository._createEntity(this.schema, data, this, isPersisted, originalIsMapped, isDelayedSave, this.isRemotePhantomMode);
|
|
981
992
|
}
|
|
982
993
|
this._relayEntityEvents(entity);
|
|
983
994
|
this.entities.push(entity);
|
|
984
995
|
|
|
985
996
|
// Create id if needed
|
|
986
|
-
if (entity.isPhantom) {
|
|
997
|
+
if (!this.isRemotePhantomMode && entity.isPhantom) {
|
|
987
998
|
entity.createTempId();
|
|
988
999
|
}
|
|
989
1000
|
|
|
990
1001
|
this.emit('add', entity);
|
|
991
1002
|
|
|
992
|
-
if (this.isAutoSave && !entity.isPersisted && !entity.isDelayedSave) {
|
|
1003
|
+
if (this.isRemotePhantomMode || (this.isAutoSave && !entity.isPersisted && !entity.isDelayedSave)) {
|
|
993
1004
|
await this.save(entity);
|
|
994
1005
|
}
|
|
995
1006
|
|
|
@@ -998,9 +1009,11 @@ export default class Repository extends EventEmitter {
|
|
|
998
1009
|
|
|
999
1010
|
/**
|
|
1000
1011
|
* Creates a new static Entity that does NOT persist in storage medium.
|
|
1012
|
+
* Used when we want to work with an entity, but don't want that entity to appear in a repository.
|
|
1001
1013
|
* @param {object} data - Either raw data object or Entity. If raw data, keys are Property names, Values are Property values.
|
|
1002
1014
|
* @param {boolean} isPersisted - Whether the new entity should be marked as already being persisted in storage medium.
|
|
1003
1015
|
* @param {boolean} originalIsMapped - Has data already been mapped according to schema?
|
|
1016
|
+
* @param {boolean} isDelayedSave - Should the repository skip autosave when immediately adding the record?
|
|
1004
1017
|
* @return {object} entity - new Entity object
|
|
1005
1018
|
*/
|
|
1006
1019
|
createStandaloneEntity = async (data, isPersisted = false, originalIsMapped = false, isDelayedSave = false) => {
|
|
@@ -1008,8 +1021,12 @@ export default class Repository extends EventEmitter {
|
|
|
1008
1021
|
this.throwError('this.createStandaloneEntity is no longer valid. Repository has been destroyed.');
|
|
1009
1022
|
return;
|
|
1010
1023
|
}
|
|
1024
|
+
if (this.isRemotePhantomMode) {
|
|
1025
|
+
this.throwError('This repository uses isRemotePhantomMode, and therefore cannot create standalone entities.');
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1011
1028
|
|
|
1012
|
-
const entity = Repository._createEntity(this.schema, data, this, isPersisted, originalIsMapped, isDelayedSave);
|
|
1029
|
+
const entity = Repository._createEntity(this.schema, data, this, isPersisted, originalIsMapped, isDelayedSave, this.isRemotePhantomMode);
|
|
1013
1030
|
|
|
1014
1031
|
if (entity.isPhantom) {
|
|
1015
1032
|
entity.createTempId();
|
|
@@ -1029,6 +1046,7 @@ export default class Repository extends EventEmitter {
|
|
|
1029
1046
|
* Convenience function to create multiple new Entities in storage medium.
|
|
1030
1047
|
* @param {array} data - Array of data objects or Entities.
|
|
1031
1048
|
* @param {boolean} isPersisted - Whether the new entities should be marked as already being persisted in storage medium.
|
|
1049
|
+
* @param {boolean} originalIsMapped - Has data already been mapped according to schema?
|
|
1032
1050
|
* @return {array} entities - new Entity objects
|
|
1033
1051
|
*/
|
|
1034
1052
|
addMultiple = async (allData, isPersisted = false, originalIsMapped = false) => {
|
|
@@ -1052,11 +1070,13 @@ export default class Repository extends EventEmitter {
|
|
|
1052
1070
|
* @param {object} rawData - Raw data object. Keys are Property names, Values are Property values.
|
|
1053
1071
|
* @param {boolean} repository - Optional repository to connect the entity to.
|
|
1054
1072
|
* @param {boolean} isPersisted - Whether the new entity should be marked as already being persisted in storage medium.
|
|
1073
|
+
* @param {boolean} originalIsMapped - Has data already been mapped according to schema?
|
|
1074
|
+
* @param {boolean} isDelayedSave - Should the repository skip autosave when immediately adding the record?
|
|
1055
1075
|
* @return {object} entity - new Entity object
|
|
1056
1076
|
* @private
|
|
1057
1077
|
*/
|
|
1058
|
-
static _createEntity = (schema, rawData, repository = null, isPersisted = false, originalIsMapped = false, isDelayedSave = false) => {
|
|
1059
|
-
const entity = new Entity(schema, rawData, repository, originalIsMapped, isDelayedSave);
|
|
1078
|
+
static _createEntity = (schema, rawData, repository = null, isPersisted = false, originalIsMapped = false, isDelayedSave = false, isRemotePhantomMode = false) => {
|
|
1079
|
+
const entity = new Entity(schema, rawData, repository, originalIsMapped, isDelayedSave, isRemotePhantomMode);
|
|
1060
1080
|
entity.initialize();
|
|
1061
1081
|
entity.isPersisted = isPersisted;
|
|
1062
1082
|
return entity;
|