Skip to content

Commit 21cd602

Browse files
committed
isRemotePhantomMode, bump minor version to 1.16.0
1 parent a09b704 commit 21cd602

4 files changed

Lines changed: 99 additions & 19 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@onehat/data",
3-
"version": "1.15.7",
3+
"version": "1.16.0",
44
"description": "JS data modeling package with adapters for many storage mediums.",
55
"main": "src/index.js",
66
"type": "module",
@@ -63,7 +63,7 @@
6363
"cypress": "5.2.0",
6464
"ink-docstrap": "^1.3.2",
6565
"jsdoc": "^4.0.0",
66-
"webpack": "^5.75.0",
66+
"webpack": "^5.76.0",
6767
"joi": "^17.7.0",
6868
"yup": "^0.32.11"
6969

src/Entity.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ class Entity extends EventEmitter {
3232
* @param {Schema} schema - Schema object
3333
* @param {object} rawData - Raw data object. Keys are Property names, Values are Property values.
3434
* @param {Repository} repository
35-
* @param {boolean} - Has rawData already been mapped according to schema?
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?
3637
*/
37-
constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false) {
38+
constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false, isRemotePhantomMode = false) {
3839
super(...arguments);
3940

4041
if (!schema) {
@@ -133,11 +134,26 @@ class Entity extends EventEmitter {
133134
this.isDestroyed = false;
134135

135136
/**
136-
* @member {boolean} isFrozen - Prevent the entity from being saved, so an editor can change it before it gets saved to remote storage.
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.
137138
* @public
138139
*/
139140
this.isDelayedSave = isDelayedSave;
140141

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+
141157
/**
142158
* @member {boolean} lastModified - Last time this entity was modified
143159
* @public
@@ -945,9 +961,15 @@ class Entity extends EventEmitter {
945961
if (this.isDestroyed) {
946962
throw Error('this.isPhantom is no longer valid. Entity has been destroyed.');
947963
}
948-
const idProperty = this.getIdProperty(),
949-
id = idProperty.getSubmitValue();
950964

965+
if (this.isRemotePhantomMode) {
966+
return this.isRemotePhantom;
967+
}
968+
969+
const
970+
idProperty = this.getIdProperty(),
971+
id = idProperty.getSubmitValue();
972+
951973
// No ID
952974
if (_.isNil(id)) {
953975
return true;

src/Repository/Ajax.js

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -533,10 +533,15 @@ class AjaxRepository extends Repository {
533533

534534
this._operations.add = true;
535535

536-
const method = this.methods.add,
536+
const
537+
method = this.methods.add,
537538
url = this.api.add,
538539
data = entity.getSubmitValues();
539540

541+
if (entity.isRemotePhantomMode) {
542+
data.isRemotePhantom = true;
543+
}
544+
540545
return this._send(method, url, data)
541546
.then(result => {
542547
if (this.debugMode) {
@@ -555,6 +560,9 @@ class AjaxRepository extends Repository {
555560
}
556561

557562
entity.loadOriginalData(root[0]);
563+
if (entity.isRemotePhantomMode) {
564+
entity.isRemotePhantom = true;
565+
}
558566
});
559567
}
560568

@@ -573,10 +581,17 @@ class AjaxRepository extends Repository {
573581

574582
this._operations.add = true;
575583

576-
const method = this.methods.add,
584+
const
585+
method = this.methods.add,
577586
url = this.api.batchAdd,
578587
data = {
579-
entities: _.map(entities, entity => entity.submitValues),
588+
entities: _.map(entities, entity => {
589+
const values = entity.submitValues;
590+
if (entity.isRemotePhantomMode) {
591+
values.isRemotePhantom = true;
592+
}
593+
return values;
594+
}),
580595
};
581596

582597
return this._send(method, url, data)
@@ -600,6 +615,9 @@ class AjaxRepository extends Repository {
600615
// TODO: Check this
601616
_.each(entities, (entity, ix) => {
602617
entity.loadOriginalData(root[ix]);
618+
if (entity.isRemotePhantomMode) {
619+
entity.isRemotePhantom = true;
620+
}
603621
});
604622
});
605623
}
@@ -617,10 +635,15 @@ class AjaxRepository extends Repository {
617635

618636
this._operations.edit = true;
619637

620-
const method = this.methods.edit,
638+
const
639+
method = this.methods.edit,
621640
url = this.api.edit,
622641
data = entity.getSubmitValues();
623642

643+
if (entity.isRemotePhantomMode) {
644+
data.isRemotePhantom = false;
645+
}
646+
624647
return this._send(method, url, data)
625648
.then(result => {
626649
if (this.debugMode) {
@@ -639,6 +662,9 @@ class AjaxRepository extends Repository {
639662
}
640663

641664
entity.loadOriginalData(root[0]);
665+
if (entity.isRemotePhantomMode && entity.isRemotePhantom) {
666+
entity.isRemotePhantom = false;
667+
}
642668
});
643669
}
644670

@@ -657,10 +683,17 @@ class AjaxRepository extends Repository {
657683

658684
this._operations.edit = true;
659685

660-
const method = this.methods.edit,
686+
const
687+
method = this.methods.edit,
661688
url = this.api.batchEdit,
662689
data = {
663-
entities: _.map(entities, entity => entity.submitValues),
690+
entities: _.map(entities, entity => {
691+
const values = entity.submitValues;
692+
if (entity.isRemotePhantomMode) {
693+
values.isRemotePhantom = false;
694+
}
695+
return values;
696+
}),
664697
};
665698

666699
return this._send(method, url, data)
@@ -684,6 +717,9 @@ class AjaxRepository extends Repository {
684717
// TODO: Check this
685718
_.each(entities, (entity, ix) => {
686719
entity.loadOriginalData(root[ix]);
720+
if (entity.isRemotePhantomMode && entity.isRemotePhantom) {
721+
entity.isRemotePhantom = false;
722+
}
687723
});
688724
});
689725
}
@@ -701,7 +737,8 @@ class AjaxRepository extends Repository {
701737

702738
this._operations.delete = true;
703739

704-
const method = this.methods.delete,
740+
const
741+
method = this.methods.delete,
705742
url = this.api.delete,
706743
data = { id: entity.id, };
707744

@@ -744,7 +781,8 @@ class AjaxRepository extends Repository {
744781

745782
this._operations.delete = true;
746783

747-
const method = this.methods.delete,
784+
const
785+
method = this.methods.delete,
748786
url = this.api.batchDelete,
749787
ids = _.map(entities, entity => entity.id),
750788
data = { ids, };

src/Repository/Repository.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,17 @@ export default class Repository extends EventEmitter {
8686
*/
8787
isRemoteSort: false,
8888

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+
89100
/**
90101
* @member {boolean} isPaginated - Whether this Repository is paginated
91102
*/
@@ -297,7 +308,7 @@ export default class Repository extends EventEmitter {
297308
const methodDefinitions = this.schema.repository.methods || this.originalConfig.methods; // The latter is mainly for lfr repositories
298309
if (!_.isEmpty(methodDefinitions)) {
299310
_.each(methodDefinitions, (method, name) => {
300-
this[name] = method; // NOTE: Methods must be defined in schema as "function() {}", not as "() => {}" so "this" will be assigned correctly
311+
this[name] = method; // NOTE: Methods must be defined in schema as "function() {}", not as "() => {}" so scope of "this" will be correct
301312
});
302313
}
303314
}
@@ -983,13 +994,13 @@ export default class Repository extends EventEmitter {
983994
this.entities.push(entity);
984995

985996
// Create id if needed
986-
if (entity.isPhantom) { // i.e. idProperty has no value
997+
if (!this.isRemotePhantomMode && entity.isPhantom) {
987998
entity.createTempId();
988999
}
9891000

9901001
this.emit('add', entity);
9911002

992-
if (this.isAutoSave && !entity.isPersisted && !entity.isDelayedSave) {
1003+
if (this.isRemotePhantomMode || (this.isAutoSave && !entity.isPersisted && !entity.isDelayedSave)) {
9931004
await this.save(entity);
9941005
}
9951006

@@ -998,16 +1009,22 @@ export default class Repository extends EventEmitter {
9981009

9991010
/**
10001011
* 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.
10011013
* @param {object} data - Either raw data object or Entity. If raw data, keys are Property names, Values are Property values.
10021014
* @param {boolean} isPersisted - Whether the new entity should be marked as already being persisted in storage medium.
10031015
* @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?
10041017
* @return {object} entity - new Entity object
10051018
*/
10061019
createStandaloneEntity = async (data, isPersisted = false, originalIsMapped = false, isDelayedSave = false) => {
10071020
if (this.isDestroyed) {
10081021
this.throwError('this.createStandaloneEntity is no longer valid. Repository has been destroyed.');
10091022
return;
10101023
}
1024+
if (this.isRemotePhantomMode) {
1025+
this.throwError('This repository uses isRemotePhantomMode, and therefore cannot create standalone entities.');
1026+
return;
1027+
}
10111028

10121029
const entity = Repository._createEntity(this.schema, data, this, isPersisted, originalIsMapped, isDelayedSave);
10131030

@@ -1029,6 +1046,7 @@ export default class Repository extends EventEmitter {
10291046
* Convenience function to create multiple new Entities in storage medium.
10301047
* @param {array} data - Array of data objects or Entities.
10311048
* @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?
10321050
* @return {array} entities - new Entity objects
10331051
*/
10341052
addMultiple = async (allData, isPersisted = false, originalIsMapped = false) => {
@@ -1052,11 +1070,13 @@ export default class Repository extends EventEmitter {
10521070
* @param {object} rawData - Raw data object. Keys are Property names, Values are Property values.
10531071
* @param {boolean} repository - Optional repository to connect the entity to.
10541072
* @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?
10551075
* @return {object} entity - new Entity object
10561076
* @private
10571077
*/
10581078
static _createEntity = (schema, rawData, repository = null, isPersisted = false, originalIsMapped = false, isDelayedSave = false) => {
1059-
const entity = new Entity(schema, rawData, repository, originalIsMapped, isDelayedSave);
1079+
const entity = new Entity(schema, rawData, repository, originalIsMapped, isDelayedSave, this.isRemotePhantomMode);
10601080
entity.initialize();
10611081
entity.isPersisted = isPersisted;
10621082
return entity;

0 commit comments

Comments
 (0)