@onehat/data 1.16.9 → 1.17.0

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.
@@ -1,6 +1,6 @@
1
1
  import Joi from 'Joi';
2
2
  import * as yup from 'yup';
3
- import Entity from '../../src/Entity.js';
3
+ import Entity from '../../src/Entity/Entity.js';
4
4
  import Schema from '../../src/Schema/index.js';
5
5
  import PropertyTypes from '../../src/Property/index.js';
6
6
 
@@ -1,5 +1,5 @@
1
1
  import PropertyTypes from '../../../src/Property/index.js';
2
- import Entity from '../../../src/Entity.js';
2
+ import Entity from '../../../src/Entity/Entity.js';
3
3
  import Schema from '../../../src/Schema/index.js';
4
4
 
5
5
  describe('Property', function() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/data",
3
- "version": "1.16.9",
3
+ "version": "1.17.0",
4
4
  "description": "JS data modeling package with adapters for many storage mediums.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -1,7 +1,7 @@
1
1
  /** @module Entity */
2
2
 
3
3
  import EventEmitter from '@onehat/events';
4
- import PropertyTypes from './Property/index.js';
4
+ import PropertyTypes from '../Property/index.js';
5
5
  import moment from 'moment';
6
6
  import _ from 'lodash';
7
7
 
@@ -103,6 +103,11 @@ class Entity extends EventEmitter {
103
103
  */
104
104
  this.properties = [];
105
105
 
106
+ /**
107
+ * @member {boolean} isTreeNode - Whether this Entity is a TreeNode
108
+ */
109
+ this.isTreeNode = false;
110
+
106
111
  /**
107
112
  * @member {boolean} isPersisted - Whether this object has been persisted in a storage medium
108
113
  * @public
@@ -217,7 +222,7 @@ class Entity extends EventEmitter {
217
222
  return this._proxy; // Return the Proxy, not 'this'
218
223
  }
219
224
 
220
- initialize = () => {
225
+ initialize() {
221
226
  this.properties = this._createProperties();
222
227
  this._createMethods();
223
228
  this._createStatics();
@@ -311,7 +316,8 @@ class Entity extends EventEmitter {
311
316
  definition = _.clone(definition); // Clone it so you don't alter original in schema
312
317
  definition.mapping = definition.name;
313
318
  }
314
- const Property = PropertyTypes[type],
319
+ const
320
+ Property = PropertyTypes[type],
315
321
  property = new Property(definition, this._proxy);
316
322
  property.on('change', this._onPropertyChange);
317
323
 
@@ -748,7 +754,8 @@ class Entity extends EventEmitter {
748
754
  obj[property.name] = property.rawValue;
749
755
  return obj;
750
756
  }
751
- const mapStack = property.mapping.split('.'),
757
+ const
758
+ mapStack = property.mapping.split('.'),
752
759
  rawValue = property.getRawValue();
753
760
 
754
761
  // Build up the hierarchy
@@ -806,7 +813,8 @@ class Entity extends EventEmitter {
806
813
  * @return {array|boolean} diff - Array of property names that have changed, or false
807
814
  */
808
815
  getChanged = () => {
809
- const original = this._originalDataParsed,
816
+ const
817
+ original = this._originalDataParsed,
810
818
  current = this.getParsedRawValues(),
811
819
  diff = Object.keys(original).reduce((result, key) => { // from https://stackoverflow.com/a/40610459/9163076
812
820
  if (current && !current.hasOwnProperty(key)) {
@@ -826,7 +834,8 @@ class Entity extends EventEmitter {
826
834
  * @return {object} changedPropertyValues - Object representing each changed field and both its original and current value
827
835
  */
828
836
  getChangedValues = () => {
829
- const original = this._originalDataParsed,
837
+ const
838
+ original = this._originalDataParsed,
830
839
  current = this.getRawValues(),
831
840
  names = this.getChanged();
832
841
  const changedPropertyValues = {};
@@ -870,9 +879,7 @@ class Entity extends EventEmitter {
870
879
  if (this.isDestroyed) {
871
880
  throw Error('this.getIdProperty is no longer valid. Entity has been destroyed.');
872
881
  }
873
- const schema = this.getSchema(),
874
- model = schema.model,
875
- idProperty = model && model.idProperty ? model.idProperty : null;
882
+ const idProperty = this.getSchema().model?.idProperty || null;
876
883
  if (!idProperty) {
877
884
  throw new Error('No idProperty found for ' + schema.name);
878
885
  }
@@ -926,7 +933,8 @@ class Entity extends EventEmitter {
926
933
  if (this.isDestroyed) {
927
934
  throw Error('this.getDisplayProperty is no longer valid. Entity has been destroyed.');
928
935
  }
929
- const schema = this.getSchema(),
936
+ const
937
+ schema = this.getSchema(),
930
938
  model = schema.model,
931
939
  displayProperty = model && model.displayProperty ? model.displayProperty : null;
932
940
  if (!displayProperty) {
@@ -0,0 +1,190 @@
1
+ /** @module Entity */
2
+
3
+ import Entity from './Entity.js';
4
+ import _ from 'lodash';
5
+
6
+ /**
7
+ * Class represents a TreeNode which adds Tree methods to Entity
8
+ * TreeNode is hierarchical, so other TreeNodes can appear in this.children
9
+ *
10
+ * @extends Entity
11
+ */
12
+ class TreeNode extends Entity {
13
+ constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false, isRemotePhantomMode = false, isRoot = false) {
14
+ super(...arguments);
15
+
16
+ if (!schema.model.parentIdProperty) {
17
+ throw new Error('parentIdProperty cannot be empty');
18
+ }
19
+
20
+ /**
21
+ * @member {boolean} isTreeNode - Whether this Entity is a TreeNode
22
+ */
23
+ this.isTreeNode = true;
24
+
25
+ /**
26
+ * @member {boolean} isRoot - Whether this TreeNode is the root TreeNode
27
+ */
28
+ this.isRoot = isRoot;
29
+
30
+ /**
31
+ * @member {TreeNode} parent - The parent TreeNode for this TreeNode
32
+ */
33
+ this.parent = null;
34
+
35
+ /**
36
+ * @member {array} children - Contains any children of this TreeNode
37
+ */
38
+ this.children = [];
39
+
40
+ /**
41
+ * @member {boolean} isChildrenLoaded - Whether child TreeNodes have loaded for this TreeNode
42
+ */
43
+ this.isChildrenLoaded = false;
44
+
45
+
46
+ // UI State
47
+ this.isVisible = false;
48
+
49
+ this.isExpanded = false;
50
+ }
51
+
52
+ /**
53
+ * Gets the "parentId" Property object for this TreeNode.
54
+ * This is the Property whose value represents the id for the parent TreeNode.
55
+ * @return {Property} parentId Property
56
+ */
57
+ getParentIdProperty = () => {
58
+ if (this.isDestroyed) {
59
+ throw Error('this.getParentIdProperty is no longer valid. TreeNode has been destroyed.');
60
+ }
61
+ const parentIdProperty = this.getSchema().model.parentIdProperty;
62
+ if (!parentIdProperty) {
63
+ throw new Error('No parentIdProperty found for ' + schema.name);
64
+ }
65
+ return this.getProperty(parentIdProperty);
66
+ }
67
+
68
+ /**
69
+ * Gets the parentId for this TreeNode.
70
+ * @return {any} parentId - The parentId
71
+ */
72
+ getParentId = () => {
73
+ if (this.isDestroyed) {
74
+ throw Error('this.getParentId is no longer valid. TreeNode has been destroyed.');
75
+ }
76
+ return this.geParentIdProperty().getSubmitValue();
77
+ }
78
+
79
+ /**
80
+ * Getter of the parentId for this TreeNode.
81
+ * @return {any} parentId - The parentId
82
+ */
83
+ get parentId() {
84
+ return this.getParentId();
85
+ }
86
+
87
+ /**
88
+ * Getter of hasParent
89
+ * Returns true if this.parent is truthy
90
+ * @return {boolean} hasParent
91
+ */
92
+ get hasParent() {
93
+ return !!this.parent;
94
+ }
95
+
96
+ getParent = () => {
97
+ if (this.isDestroyed) {
98
+ throw Error('this.getParent is no longer valid. TreeNode has been destroyed.');
99
+ }
100
+ return this.parent;
101
+ }
102
+
103
+ /**
104
+ * Getter of hasChildren
105
+ * @return {boolean} hasParent
106
+ */
107
+ get hasChildren() {
108
+ return !_.isEmpty(this.children);
109
+ }
110
+
111
+ getChildren = async () => {
112
+ if (this.isDestroyed) {
113
+ throw Error('this.getChildren is no longer valid. TreeNode has been destroyed.');
114
+ }
115
+ if (!this.isChildrenLoaded) {
116
+ await this.loadChildren();
117
+ }
118
+ return this.children;
119
+ }
120
+
121
+ loadChidren = async () => {
122
+ if (this.isDestroyed) {
123
+ throw Error('this.loadChidren is no longer valid. TreeNode has been destroyed.');
124
+ }
125
+ this.children = await this.repository.loadChildTreeNodes(this); // populates the children with a reference to this in child.parent
126
+ this.isChildrenLoaded = true;
127
+ }
128
+
129
+ getPrevousSibling = async () => {
130
+ if (this.isDestroyed) {
131
+ throw Error('this.getPrevousSibling is no longer valid. TreeNode has been destroyed.');
132
+ }
133
+ const
134
+ parent = this.getParent(),
135
+ siblings = await parent.getChildren();
136
+ let previous;
137
+ _.each(siblings, (treeNode) => {
138
+ if (treeNode === this) {
139
+ return false;
140
+ }
141
+ previous = treeNode;
142
+ })
143
+ return previous;
144
+ }
145
+
146
+ getNextSibling = async () => {
147
+ if (this.isDestroyed) {
148
+ throw Error('this.getNextSibling is no longer valid. TreeNode has been destroyed.');
149
+ }
150
+ const
151
+ parent = this.getParent(),
152
+ siblings = await parent.getChildren();
153
+ let returnNext = false,
154
+ next = null;
155
+ _.each(siblings, (treeNode) => {
156
+ if (returnNext) {
157
+ next = treeNode;
158
+ return false;
159
+ }
160
+ if (treeNode === this) {
161
+ returnNext = true;
162
+ }
163
+ })
164
+ return next;
165
+ }
166
+
167
+ getChildAt = (ix) => {
168
+ if (this.isDestroyed) {
169
+ throw Error('this.getChildAt is no longer valid. TreeNode has been destroyed.');
170
+ }
171
+ return this.children[ix];
172
+ }
173
+
174
+ getFirstChild = () => {
175
+ if (this.isDestroyed) {
176
+ throw Error('this.getFirstChild is no longer valid. TreeNode has been destroyed.');
177
+ }
178
+ return this.children[0];
179
+ }
180
+
181
+ getLastChild = () => {
182
+ if (this.isDestroyed) {
183
+ throw Error('this.getLastChild is no longer valid. TreeNode has been destroyed.');
184
+ }
185
+ return this.children.slice(-1)[0]
186
+ }
187
+
188
+ }
189
+
190
+ export default TreeNode;
package/src/OneHatData.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  import EventEmitter from '@onehat/events';
4
4
  import CoreRepositoryTypes from './Repository/index.js';
5
- import Entity from './Entity.js';
5
+ import Entity from './Entity/Entity.js';
6
6
  import {
7
7
  MODE_LOCAL_MIRROR,
8
8
  MODE_COMMAND_QUEUE,
@@ -1,7 +1,7 @@
1
1
  /** @module Repository */
2
2
 
3
3
  import Repository from './Repository.js';
4
- import Entity from '../Entity.js';
4
+ import Entity from '../Entity/Entity.js';
5
5
  import natsort from 'natsort';
6
6
  import _ from 'lodash';
7
7
 
@@ -1,7 +1,7 @@
1
1
  /** @module Repository */
2
2
 
3
3
  import Repository from './Repository.js';
4
- import Entity from '../Entity.js';
4
+ import Entity from '../Entity/Entity.js';
5
5
  import _ from 'lodash';
6
6
 
7
7
  /**
@@ -1,7 +1,7 @@
1
1
  /** @module Repository */
2
2
 
3
3
  import EventEmitter from '@onehat/events';
4
- import Entity from '../Entity.js'
4
+ import Entity from '../Entity/Entity.js'
5
5
  import PropertyTypes from '../Property/index.js';
6
6
  import {
7
7
  v4 as uuid,
@@ -1,7 +1,7 @@
1
1
  import moment from 'moment';
2
2
  import momentAlt from 'relative-time-parser'; // Notice this version of moment is imported from 'relative-time-parser', and may be out of sync with our general 'moment' package
3
3
  import accounting from 'accounting-js';
4
- // import * as chrono from 'chrono-node'; // Doesn't yet work in React Native ("SyntaxError: Invalid RegExp: Quantifier has nothing to repeat, js engine: hermes") Github ticket: https://github.com/facebook/hermes/blob/main/doc/RegExp.md
4
+ import * as chrono from 'chrono-node'; // Doesn't yet work in React Native ("SyntaxError: Invalid RegExp: Quantifier has nothing to repeat, js engine: hermes") Github ticket: https://github.com/facebook/hermes/blob/main/doc/RegExp.md
5
5
  import _ from 'lodash';
6
6
 
7
7
  class Parsers {