@onehat/data 1.16.10 → 1.17.2

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.
Files changed (38) hide show
  1. package/cypress/{integration/Entity.spec.js → e2e/Entity.cy.js} +1 -1
  2. package/cypress/{integration/Property/Property.spec.js → e2e/Property/Property.cy.js} +1 -1
  3. package/cypress/plugins/index.js +2 -32
  4. package/cypress.config.js +42 -0
  5. package/package.json +22 -22
  6. package/src/{Entity.js → Entity/Entity.js} +344 -12
  7. package/src/OneHatData.js +1 -1
  8. package/src/Repository/Ajax.js +13 -3
  9. package/src/Repository/Memory.js +1 -1
  10. package/src/Repository/Null.js +1 -1
  11. package/src/Repository/OneBuild.js +80 -0
  12. package/src/Repository/Repository.js +119 -31
  13. package/src/Schema/Schema.js +33 -0
  14. package/cypress/cypress.json +0 -177
  15. package/cypress.json +0 -1
  16. /package/cypress/{integration/Async.spec.js → e2e/Async.cy.js} +0 -0
  17. /package/cypress/{integration/Config.spec.js → e2e/Config.cy.js} +0 -0
  18. /package/cypress/{integration/OneHatData.spec.js → e2e/OneHatData.cy.js} +0 -0
  19. /package/cypress/{integration/Property/Base64.spec.js → e2e/Property/Base64.cy.js} +0 -0
  20. /package/cypress/{integration/Property/Boolean.spec.js → e2e/Property/Boolean.cy.js} +0 -0
  21. /package/cypress/{integration/Property/Currency.spec.js → e2e/Property/Currency.cy.js} +0 -0
  22. /package/cypress/{integration/Property/Date.spec.js → e2e/Property/Date.cy.js} +0 -0
  23. /package/cypress/{integration/Property/DateTime.spec.js → e2e/Property/DateTime.cy.js} +0 -0
  24. /package/cypress/{integration/Property/Float.spec.js → e2e/Property/Float.cy.js} +0 -0
  25. /package/cypress/{integration/Property/Integer.spec.js → e2e/Property/Integer.cy.js} +0 -0
  26. /package/cypress/{integration/Property/Json.spec.js → e2e/Property/Json.cy.js} +0 -0
  27. /package/cypress/{integration/Property/Percent.spec.js → e2e/Property/Percent.cy.js} +0 -0
  28. /package/cypress/{integration/Property/PercentInt.spec.js → e2e/Property/PercentInt.cy.js} +0 -0
  29. /package/cypress/{integration/Property/String.spec.js → e2e/Property/String.cy.js} +0 -0
  30. /package/cypress/{integration/Property/Time.spec.js → e2e/Property/Time.cy.js} +0 -0
  31. /package/cypress/{integration/Property/Uuid.spec.js → e2e/Property/Uuid.cy.js} +0 -0
  32. /package/cypress/{integration/Repository/Ajax.spec.js → e2e/Repository/Ajax.cy.js} +0 -0
  33. /package/cypress/{integration/Repository/LocalFromRemote.spec.js → e2e/Repository/LocalFromRemote.cy.js} +0 -0
  34. /package/cypress/{integration/Repository/Memory.spec.js → e2e/Repository/Memory.cy.js} +0 -0
  35. /package/cypress/{integration/Repository/OneBuild.spec.js → e2e/Repository/OneBuild.cy.js} +0 -0
  36. /package/cypress/{integration/Repository/Repository.spec.js → e2e/Repository/Repository.cy.js} +0 -0
  37. /package/cypress/{integration/Schema.spec.js → e2e/Schema.cy.js} +0 -0
  38. /package/cypress/support/{index.js → e2e.js} +0 -0
@@ -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() {
@@ -1,32 +1,2 @@
1
- const webpack = require('@cypress/webpack-preprocessor'),
2
- webpackOptions = {
3
- mode: 'development',
4
- devtool: 'cheap-module-source-map', // See https://survivejs.com/webpack/building/source-maps/
5
- module: {
6
- rules: [
7
- {
8
- test: /\.(js|jsx|mjs)$/,
9
- exclude: /node_modules\/(?!(@onehat)\/).*/,
10
- loader: 'babel-loader',
11
- options: {
12
- cacheDirectory: false,
13
- presets: [
14
- '@babel/preset-env'
15
- ],
16
- plugins: [
17
- '@babel/plugin-proposal-class-properties',
18
- '@babel/plugin-transform-runtime'
19
- ],
20
- sourceType: 'unambiguous',
21
- },
22
- }
23
- ]
24
- }
25
- };
26
-
27
- module.exports = (on, config) => {
28
- on('file:preprocessor', webpack({
29
- webpackOptions,
30
- watchOptions: {},
31
- }));
32
- };
1
+ module.exports = (on) => {
2
+ }
@@ -0,0 +1,42 @@
1
+ import { defineConfig } from "cypress";
2
+ import webpackPreprocessor from "@cypress/webpack-preprocessor";
3
+ import Webpack from "webpack";
4
+
5
+ export default defineConfig({
6
+ e2e: {
7
+ experimentalRunAllSpecs: true,
8
+ chromeWebSecurity: false,
9
+ setupNodeEvents(on) {
10
+ const options = webpackPreprocessor.defaultOptions;
11
+ if (!options.module) {
12
+ options.module = {
13
+ rules: [],
14
+ }
15
+ }
16
+ if (!options.module.rules) {
17
+ options.module.rules = [];
18
+ }
19
+ options.module.rules.push({
20
+ test: /\.(js|jsx|mjs)$/,
21
+ exclude: [/node_modules\/(?!(@onehat)\/).*/],
22
+ use: [{
23
+ loader: 'babel-loader',
24
+ options: {
25
+ cacheDirectory: false,
26
+ presets: [
27
+ '@babel/preset-env'
28
+ ],
29
+ plugins: [
30
+ '@babel/plugin-transform-class-properties',
31
+ '@babel/plugin-transform-runtime'
32
+ ],
33
+ sourceType: 'unambiguous',
34
+ },
35
+ }],
36
+
37
+ });
38
+
39
+ on('file:preprocessor', webpackPreprocessor(options));
40
+ },
41
+ }
42
+ });
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@onehat/data",
3
- "version": "1.16.10",
3
+ "version": "1.17.2",
4
4
  "description": "JS data modeling package with adapters for many storage mediums.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
7
7
  "scripts": {
8
- "test": "npx cypress open --config-file ../cypress.json",
8
+ "test": "npx cypress open",
9
+ "test2": "DEBUG=cypress:* npx cypress open",
9
10
  "docs": "jsdoc -c ./jsdoc.json -t ./node_modules/ink-docstrap/template -R README.md"
10
11
  },
11
12
  "repository": {
@@ -35,37 +36,36 @@
35
36
  },
36
37
  "homepage": "https://github.com/OneHatRepo/data#readme",
37
38
  "dependencies": {
38
- "@onehat/events": "^1.6.5",
39
+ "@onehat/events": "^1.6.6",
39
40
  "accounting-js": "^1.1.1",
40
- "axios": "^1.2.1",
41
- "chrono-node": "^2.4.2",
42
- "fast-xml-parser": "^4.0.12",
41
+ "axios": "^1.4.0",
42
+ "chrono-node": "^2.6.3",
43
+ "fast-xml-parser": "^4.2.2",
43
44
  "he": "^1.2.0",
44
- "js-base64": "^3.7.3",
45
+ "js-base64": "^3.7.5",
45
46
  "lodash": "^4.17.21",
46
47
  "moment": "^2.29.4",
47
48
  "natsort": "^2.0.3",
48
49
  "numeral": "^2.0.6",
49
- "qs": "^6.11.0",
50
+ "qs": "^6.11.2",
50
51
  "relative-time-parser": "^1.0.15",
51
52
  "uuid": "^9.0.0"
52
53
  },
53
54
  "devDependencies": {
54
- "@babel/core": "^7.20.5",
55
- "@babel/node": "^7.20.5",
56
- "@babel/plugin-proposal-class-properties": "^7.18.6",
55
+ "@babel/core": "^7.22.1",
56
+ "@babel/node": "^7.22.1",
57
+ "@babel/plugin-transform-class-properties": "^7.22.3",
57
58
  "@babel/plugin-transform-runtime": "^7.19.6",
58
- "@babel/preset-env": "^7.20.2",
59
- "@babel/register": "^7.18.9",
60
- "@babel/runtime": "^7.20.6",
61
- "@cypress/webpack-preprocessor": "^5.16.0",
62
- "babel-loader": "^8.0.2",
63
- "cypress": "5.2.0",
59
+ "@babel/preset-env": "^7.22.4",
60
+ "@babel/register": "^7.21.0",
61
+ "@babel/runtime": "^7.22.3",
62
+ "@cypress/webpack-preprocessor": "^5.17.1",
63
+ "babel-loader": "^9.1.2",
64
+ "cypress": "12.13.0",
64
65
  "ink-docstrap": "^1.3.2",
65
- "jsdoc": "^4.0.0",
66
- "webpack": "^5.76.0",
67
- "joi": "^17.7.0",
68
- "yup": "^0.32.11"
69
-
66
+ "joi": "^17.9.2",
67
+ "jsdoc": "^4.0.2",
68
+ "webpack": "^5.85.0",
69
+ "yup": "^1.2.0"
70
70
  }
71
71
  }
@@ -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
 
@@ -35,7 +35,7 @@ class Entity extends EventEmitter {
35
35
  * @param {boolean} originalIsMapped - Has data already been mapped according to schema?
36
36
  * @param {boolean} isDelayedSave - Should the repository skip autosave when immediately adding the record?
37
37
  */
38
- constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false, isRemotePhantomMode = false) {
38
+ constructor(schema, rawData = {}, repository = null, originalIsMapped = false, isDelayedSave = false, isRemotePhantomMode = false, isRoot = false) {
39
39
  super(...arguments);
40
40
 
41
41
  if (!schema) {
@@ -103,6 +103,45 @@ class Entity extends EventEmitter {
103
103
  */
104
104
  this.properties = [];
105
105
 
106
+ /**
107
+ * @member {boolean} isTree - Whether this Entity is a TreeNode
108
+ */
109
+ this.isTree = schema.model.isTree || false;
110
+
111
+ if (this.isTree && !schema.model.parentIdProperty) {
112
+ throw new Error('parentIdProperty cannot be empty for a TreeNode');
113
+ }
114
+ if (this.isTree && this.repository?.isClosureTable && !schema.model.depthProperty) {
115
+ throw new Error('depthProperty cannot be empty for a Closure Table TreeNode');
116
+ }
117
+ if (this.isTree && !schema.model.hasChildrenProperty) {
118
+ throw new Error('hasChildrenProperty cannot be empty for a TreeNode');
119
+ }
120
+
121
+ /**
122
+ * @member {boolean} isRoot - Whether this TreeNode is the root TreeNode
123
+ * For trees only
124
+ */
125
+ this.isRoot = false;
126
+
127
+ /**
128
+ * @member {TreeNode} parent - The parent TreeNode for this TreeNode
129
+ * For trees only
130
+ */
131
+ this.parent = null;
132
+
133
+ /**
134
+ * @member {array} children - Contains any children of this TreeNode
135
+ * For trees only
136
+ */
137
+ this.children = this._originalData.children && !_.isEmpty(this._originalData.children) ? this._originalData.children : [];
138
+
139
+ /**
140
+ * @member {boolean} isChildrenLoaded - Whether child TreeNodes have loaded for this TreeNode
141
+ * For trees only
142
+ */
143
+ this.isChildrenLoaded = this._originalData.isChildrenLoaded || false;
144
+
106
145
  /**
107
146
  * @member {boolean} isPersisted - Whether this object has been persisted in a storage medium
108
147
  * @public
@@ -217,7 +256,7 @@ class Entity extends EventEmitter {
217
256
  return this._proxy; // Return the Proxy, not 'this'
218
257
  }
219
258
 
220
- initialize = () => {
259
+ initialize() {
221
260
  this.properties = this._createProperties();
222
261
  this._createMethods();
223
262
  this._createStatics();
@@ -311,7 +350,8 @@ class Entity extends EventEmitter {
311
350
  definition = _.clone(definition); // Clone it so you don't alter original in schema
312
351
  definition.mapping = definition.name;
313
352
  }
314
- const Property = PropertyTypes[type],
353
+ const
354
+ Property = PropertyTypes[type],
315
355
  property = new Property(definition, this._proxy);
316
356
  property.on('change', this._onPropertyChange);
317
357
 
@@ -344,7 +384,7 @@ class Entity extends EventEmitter {
344
384
  * Assumes (and sets) isTempId === false.
345
385
  * @param {array} originalData - Raw data to load into entity.
346
386
  */
347
- loadOriginalData = (originalData) => {
387
+ loadOriginalData = (originalData, assembleTreeNodes = true) => {
348
388
  if (this.isDestroyed) {
349
389
  throw Error('this.loadOriginalData is no longer valid. Entity has been destroyed.');
350
390
  }
@@ -352,6 +392,10 @@ class Entity extends EventEmitter {
352
392
  this._originalData = originalData || {};
353
393
  this.reset();
354
394
  this.getIdProperty().isTempId = false;
395
+
396
+ if (this.isTree && this.repository && assembleTreeNodes) {
397
+ this.repository.assembleTreeNodes(); // rebuilds them all
398
+ }
355
399
  }
356
400
 
357
401
  /**
@@ -748,7 +792,8 @@ class Entity extends EventEmitter {
748
792
  obj[property.name] = property.rawValue;
749
793
  return obj;
750
794
  }
751
- const mapStack = property.mapping.split('.'),
795
+ const
796
+ mapStack = property.mapping.split('.'),
752
797
  rawValue = property.getRawValue();
753
798
 
754
799
  // Build up the hierarchy
@@ -806,7 +851,8 @@ class Entity extends EventEmitter {
806
851
  * @return {array|boolean} diff - Array of property names that have changed, or false
807
852
  */
808
853
  getChanged = () => {
809
- const original = this._originalDataParsed,
854
+ const
855
+ original = this._originalDataParsed,
810
856
  current = this.getParsedRawValues(),
811
857
  diff = Object.keys(original).reduce((result, key) => { // from https://stackoverflow.com/a/40610459/9163076
812
858
  if (current && !current.hasOwnProperty(key)) {
@@ -826,7 +872,8 @@ class Entity extends EventEmitter {
826
872
  * @return {object} changedPropertyValues - Object representing each changed field and both its original and current value
827
873
  */
828
874
  getChangedValues = () => {
829
- const original = this._originalDataParsed,
875
+ const
876
+ original = this._originalDataParsed,
830
877
  current = this.getRawValues(),
831
878
  names = this.getChanged();
832
879
  const changedPropertyValues = {};
@@ -870,9 +917,7 @@ class Entity extends EventEmitter {
870
917
  if (this.isDestroyed) {
871
918
  throw Error('this.getIdProperty is no longer valid. Entity has been destroyed.');
872
919
  }
873
- const schema = this.getSchema(),
874
- model = schema.model,
875
- idProperty = model && model.idProperty ? model.idProperty : null;
920
+ const idProperty = this.getSchema().model?.idProperty || null;
876
921
  if (!idProperty) {
877
922
  throw new Error('No idProperty found for ' + schema.name);
878
923
  }
@@ -926,7 +971,8 @@ class Entity extends EventEmitter {
926
971
  if (this.isDestroyed) {
927
972
  throw Error('this.getDisplayProperty is no longer valid. Entity has been destroyed.');
928
973
  }
929
- const schema = this.getSchema(),
974
+ const
975
+ schema = this.getSchema(),
930
976
  model = schema.model,
931
977
  displayProperty = model && model.displayProperty ? model.displayProperty : null;
932
978
  if (!displayProperty) {
@@ -1424,6 +1470,292 @@ class Entity extends EventEmitter {
1424
1470
  }
1425
1471
 
1426
1472
 
1473
+
1474
+ // ______
1475
+ // /_ __/_______ ___ _____
1476
+ // / / / ___/ _ \/ _ \/ ___/
1477
+ // / / / / / __/ __(__ )
1478
+ // /_/ /_/ \___/\___/____/
1479
+
1480
+ /**
1481
+ * Gets the "parentId" Property object for this TreeNode.
1482
+ * This is the Property whose value represents the id for the parent TreeNode.
1483
+ * @return {Property} parentId Property
1484
+ */
1485
+ getParentIdProperty = () => {
1486
+ this.ensureTree();
1487
+ if (this.isDestroyed) {
1488
+ throw Error('this.getParentIdProperty is no longer valid. TreeNode has been destroyed.');
1489
+ }
1490
+
1491
+ const parentIdProperty = this.getSchema().model.parentIdProperty;
1492
+ return this.getProperty(parentIdProperty);
1493
+ }
1494
+
1495
+ /**
1496
+ * Gets the parentId for this TreeNode.
1497
+ * It does this by getting the parentId property's submitValue.
1498
+ * It doesn't look at some value created by client on the TreeNode.
1499
+ * @return {any} parentId - The parentId
1500
+ */
1501
+ getParentId = () => {
1502
+ this.ensureTree();
1503
+ if (this.isDestroyed) {
1504
+ throw Error('this.getParentId is no longer valid. TreeNode has been destroyed.');
1505
+ }
1506
+
1507
+ return this.geParentIdProperty().getSubmitValue();
1508
+ }
1509
+
1510
+ /**
1511
+ * Getter of parentId for this TreeNode.
1512
+ * @return {any} parentId - The parentId
1513
+ */
1514
+ get parentId() {
1515
+ return this.getParentId();
1516
+ }
1517
+
1518
+ /**
1519
+ * Getter of hasParent
1520
+ * Returns true if this is not a root node
1521
+ * @return {boolean} hasParent
1522
+ */
1523
+ get hasParent() {
1524
+ this.ensureTree();
1525
+
1526
+ return !this.isRoot;
1527
+ }
1528
+
1529
+ /**
1530
+ * Gets the "depth" Property object for this TreeNode.
1531
+ * This is the Property whose value represents the depth of the TreeNode.
1532
+ * @return {Property} parentId Property
1533
+ */
1534
+ getDepthProperty = () => {
1535
+ this.ensureTree();
1536
+ if (this.isDestroyed) {
1537
+ throw Error('this.getDepthProperty is no longer valid. TreeNode has been destroyed.');
1538
+ }
1539
+
1540
+ const depthProperty = this.getSchema().model.depthProperty;
1541
+ return this.getProperty(depthProperty);
1542
+ }
1543
+
1544
+ /**
1545
+ * Gets the depth for this TreeNode.
1546
+ * It does this by getting the depth property's submitValue.
1547
+ * @return {any} depth - The depth
1548
+ */
1549
+ getDepth = () => {
1550
+ this.ensureTree();
1551
+ if (this.isDestroyed) {
1552
+ throw Error('this.getDepth is no longer valid. TreeNode has been destroyed.');
1553
+ }
1554
+
1555
+ return this.getDepthProperty().getSubmitValue();
1556
+ }
1557
+
1558
+ /**
1559
+ * Getter of depth for this TreeNode.
1560
+ * @return {any} depth - The depth
1561
+ */
1562
+ get depth() {
1563
+ return this.getDepth();
1564
+ }
1565
+
1566
+ /**
1567
+ * Gets the "hasChildren" Property object for this TreeNode.
1568
+ * This is the Property whose value represents whether this TreeNode has any children.
1569
+ * @return {Property} parentId Property
1570
+ */
1571
+ getHasChildrenProperty = () => {
1572
+ this.ensureTree();
1573
+ if (this.isDestroyed) {
1574
+ throw Error('this.getHasChildrenProperty is no longer valid. TreeNode has been destroyed.');
1575
+ }
1576
+
1577
+ const hasChildrenProperty = this.getSchema().model.hasChildrenProperty;
1578
+ return this.getProperty(hasChildrenProperty);
1579
+ }
1580
+
1581
+ /**
1582
+ * Gets the hasChildren value for this TreeNode.
1583
+ * It does this by getting the hasChildren property's submitValue.
1584
+ * It doesn't look at some value created by client on the TreeNode.
1585
+ * @return {any} parentId - The parentId
1586
+ */
1587
+ getHasChildren = () => {
1588
+ this.ensureTree();
1589
+ if (this.isDestroyed) {
1590
+ throw Error('this.getHasChildren is no longer valid. TreeNode has been destroyed.');
1591
+ }
1592
+
1593
+ return this.getHasChildrenProperty().getSubmitValue();
1594
+ }
1595
+
1596
+ /**
1597
+ * Getter of hasChildren for this TreeNode.
1598
+ * @return {any} parentId - The parentId
1599
+ */
1600
+ get hasChildren() {
1601
+ return this.getHasChildren();
1602
+ }
1603
+
1604
+ /**
1605
+ * Getter of parent TreeNode for this TreeNode.
1606
+ * @return {TreeNode} parent - The parent TreeNode
1607
+ */
1608
+ getParent = () => {
1609
+ this.ensureTree();
1610
+ if (this.isDestroyed) {
1611
+ throw Error('this.getParent is no longer valid. TreeNode has been destroyed.');
1612
+ }
1613
+
1614
+ if (!this.hasParent) {
1615
+ return null;
1616
+ }
1617
+ return this.parent;
1618
+ }
1619
+
1620
+ /**
1621
+ * Getter of child TreeNodes for this TreeNode.
1622
+ * @return {array} children - The children
1623
+ */
1624
+ getChildren = async () => {
1625
+ this.ensureTree();
1626
+ if (this.isDestroyed) {
1627
+ throw Error('this.getChildren is no longer valid. TreeNode has been destroyed.');
1628
+ }
1629
+
1630
+ if (!this.isChildrenLoaded) {
1631
+ await this.loadChildren();
1632
+ }
1633
+ return this.children;
1634
+ }
1635
+
1636
+ /**
1637
+ * Loads the children of this TreeNode from repository.
1638
+ */
1639
+ loadChildren = async (depth) => {
1640
+ this.ensureTree();
1641
+ if (this.isDestroyed) {
1642
+ throw Error('this.loadChildren is no longer valid. TreeNode has been destroyed.');
1643
+ }
1644
+ if (!this.repository?.loadChildren) {
1645
+ throw Error('repository.loadChildren is not defined.');
1646
+ }
1647
+
1648
+ this.children = await this.repository.loadChildren(this, depth); // populates the children with a reference to this in child.parent
1649
+ this.isChildrenLoaded = true;
1650
+ }
1651
+
1652
+ /**
1653
+ * Alias for loadChildren
1654
+ */
1655
+ reloadChildren = () => { // alias
1656
+ return this.loadChildren();
1657
+ }
1658
+
1659
+ /**
1660
+ * Gets the previous sibling of this TreeNode from repository.
1661
+ * @return {TreeNode} sibling
1662
+ */
1663
+ getPrevousSibling = async () => {
1664
+ this.ensureTree();
1665
+ if (this.isDestroyed) {
1666
+ throw Error('this.getPrevousSibling is no longer valid. TreeNode has been destroyed.');
1667
+ }
1668
+
1669
+ const
1670
+ parent = this.getParent(),
1671
+ siblings = await parent.getChildren();
1672
+ let previous;
1673
+ _.each(siblings, (treeNode) => {
1674
+ if (treeNode === this) {
1675
+ return false;
1676
+ }
1677
+ previous = treeNode;
1678
+ })
1679
+ return previous;
1680
+ }
1681
+
1682
+ /**
1683
+ * Gets the next sibling of this TreeNode from repository.
1684
+ * @return {TreeNode} sibling
1685
+ */
1686
+ getNextSibling = async () => {
1687
+ this.ensureTree();
1688
+ if (this.isDestroyed) {
1689
+ throw Error('this.getNextSibling is no longer valid. TreeNode has been destroyed.');
1690
+ }
1691
+
1692
+ const
1693
+ parent = this.getParent(),
1694
+ siblings = await parent.getChildren();
1695
+ let returnNext = false,
1696
+ next = null;
1697
+ _.each(siblings, (treeNode) => {
1698
+ if (returnNext) {
1699
+ next = treeNode;
1700
+ return false;
1701
+ }
1702
+ if (treeNode === this) {
1703
+ returnNext = true;
1704
+ }
1705
+ })
1706
+ return next;
1707
+ }
1708
+
1709
+ /**
1710
+ * Gets the child of this TreeNode at index ix from repository.
1711
+ * @return {TreeNode} child
1712
+ */
1713
+ getChildAt = (ix) => {
1714
+ this.ensureTree();
1715
+ if (this.isDestroyed) {
1716
+ throw Error('this.getChildAt is no longer valid. TreeNode has been destroyed.');
1717
+ }
1718
+
1719
+ return this.children[ix];
1720
+ }
1721
+
1722
+ /**
1723
+ * Gets the first child of this TreeNode from repository.
1724
+ * @return {TreeNode} child
1725
+ */
1726
+ getFirstChild = () => {
1727
+ this.ensureTree();
1728
+ if (this.isDestroyed) {
1729
+ throw Error('this.getFirstChild is no longer valid. TreeNode has been destroyed.');
1730
+ }
1731
+
1732
+ return this.children[0];
1733
+ }
1734
+
1735
+ /**
1736
+ * Gets the last child of this TreeNode from repository.
1737
+ * @return {TreeNode} child
1738
+ */
1739
+ getLastChild = () => {
1740
+ this.ensureTree();
1741
+ if (this.isDestroyed) {
1742
+ throw Error('this.getLastChild is no longer valid. TreeNode has been destroyed.');
1743
+ }
1744
+
1745
+ return this.children.slice(-1)[0]
1746
+ }
1747
+
1748
+ /**
1749
+ * Helper to make sure this Repository is a tree
1750
+ * @private
1751
+ */
1752
+ ensureTree = async () => {
1753
+ if (!this.isTree) {
1754
+ this.throwError('This Repository is not a tree!');
1755
+ }
1756
+ }
1757
+
1758
+
1427
1759
  /**
1428
1760
  * Destroy this object.
1429
1761
  * - Removes all circular references to parent objects
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,
@@ -430,6 +430,10 @@ class AjaxRepository extends Repository {
430
430
  this._relayEntityEvents(entity);
431
431
  return entity;
432
432
  });
433
+
434
+ if (this.isTree) {
435
+ this.assembleTreeNodes();
436
+ }
433
437
 
434
438
  // Set the total records that pass filter
435
439
  this.total = total;
@@ -492,7 +496,7 @@ class AjaxRepository extends Repository {
492
496
  }
493
497
 
494
498
  const updatedData = root[0];
495
- entity.loadOriginalData(updatedData, true);
499
+ entity.loadOriginalData(updatedData);
496
500
  entity.emit('reload', entity);
497
501
 
498
502
  this.markLoaded();
@@ -638,11 +642,14 @@ class AjaxRepository extends Repository {
638
642
  // Reload each entity with new data
639
643
  // TODO: Check this
640
644
  _.each(entities, (entity, ix) => {
641
- entity.loadOriginalData(root[ix]);
645
+ entity.loadOriginalData(root[ix], false); // false to not assembleTreeNodes
642
646
  if (entity.isRemotePhantomMode) {
643
647
  entity.isRemotePhantom = true;
644
648
  }
645
649
  });
650
+ if (this.isTree) {
651
+ this.assembleTreeNodes();
652
+ }
646
653
  });
647
654
  }
648
655
 
@@ -748,11 +755,14 @@ class AjaxRepository extends Repository {
748
755
  // Reload each entity with new data
749
756
  // TODO: Check this
750
757
  _.each(entities, (entity, ix) => {
751
- entity.loadOriginalData(root[ix]);
758
+ entity.loadOriginalData(root[ix], false); // false to not assembleTreeNodes
752
759
  if (entity.isRemotePhantomMode && entity.isRemotePhantom) {
753
760
  entity.isRemotePhantom = false;
754
761
  }
755
762
  });
763
+ if (this.isTree) {
764
+ this.assembleTreeNodes();
765
+ }
756
766
  });
757
767
  }
758
768
 
@@ -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
  /**
@@ -404,6 +404,86 @@ class OneBuildRepository extends AjaxRepository {
404
404
  });
405
405
  }
406
406
 
407
+
408
+ // ______
409
+ // /_ __/_______ ___ _____
410
+ // / / / ___/ _ \/ _ \/ ___/
411
+ // / / / / / __/ __(__ )
412
+ // /_/ /_/ \___/\___/____/
413
+
414
+ /**
415
+ * Gets the root nodes of this tree.
416
+ */
417
+ getRootNodes = async (getChildren = false, depth) => {
418
+ this.ensureTree();
419
+ if (this.isDestroyed) {
420
+ this.throwError('this.setRootNode is no longer valid. Repository has been destroyed.');
421
+ return;
422
+ }
423
+
424
+ // Clear all entities, if any exist
425
+ _.each(this.entities, (entity) => {
426
+ entity.destroy();
427
+ });
428
+ this.entities = [];
429
+
430
+ // TODO: Load root nodes (and possibly their children)
431
+
432
+
433
+ }
434
+
435
+ /**
436
+ * Loads the children of the supplied treeNode
437
+ */
438
+ loadChildren = async (treeNode, depth = 1) => {
439
+ this.ensureTree();
440
+ if (this.isDestroyed) {
441
+ this.throwError('this.setRootNode is no longer valid. Repository has been destroyed.');
442
+ return;
443
+ }
444
+
445
+
446
+ // If children already exist, remove them from the repository
447
+ // This way, we can reload just a portion of the tree
448
+ if (!_.isEmpty(treeNode.children)) {
449
+ const children = treeNode.children;
450
+ treeNode.children = [];
451
+
452
+ _.each(children, (child) => {
453
+ this.removeNode(child);
454
+ });
455
+ }
456
+
457
+
458
+ // TODO: load children here
459
+
460
+
461
+
462
+ }
463
+
464
+ /**
465
+ * Alias for loadChildren
466
+ */
467
+ reloadChildren = (treeNode, depth) => {
468
+ return this.loadChildren(treeNode, depth);
469
+ }
470
+
471
+ /**
472
+ * Moves the supplied treeNode to a new position on the tree
473
+ */
474
+ moveTreeNode = async (treeNode, newParentId) => {
475
+ this.ensureTree();
476
+ if (this.isDestroyed) {
477
+ this.throwError('this.moveTreeNode is no longer valid. Repository has been destroyed.');
478
+ return;
479
+ }
480
+
481
+ // TODO: move node here
482
+
483
+
484
+
485
+ }
486
+
407
487
  }
408
488
 
409
489
 
@@ -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,
@@ -108,7 +108,7 @@ export default class Repository extends EventEmitter {
108
108
  */
109
109
  pageSize: 10,
110
110
 
111
- sorters: (schema && schema.model && schema.model.sorters) ? schema.model.sorters : [],
111
+ sorters: schema.model.sorters || [],
112
112
 
113
113
  /**
114
114
  * @member {string} batchOrder - Comma-separated ordering of add, edit, and delete batch operations
@@ -189,22 +189,28 @@ export default class Repository extends EventEmitter {
189
189
  this.total = 0;
190
190
 
191
191
  /**
192
- * @member {Boolean} isFiltered - State: whether or not any filters are currently applied to entities
192
+ * @member {boolean} isFiltered - State: whether or not any filters are currently applied to entities
193
193
  */
194
194
  this.isFiltered = false;
195
195
 
196
196
  /**
197
- * @member {Boolean} isInitialized - State: whether or not this repository has been completely initialized
197
+ * @member {boolean} isInitialized - State: whether or not this repository has been completely initialized
198
198
  */
199
199
  this.isInitialized = false;
200
200
 
201
201
  /**
202
- * @member {Boolean} isLoaded - State: whether or not entities have been loaded at least once
202
+ * @member {boolean} isTree - Whether this Repository contains TreeNodes
203
+ * @readonly
204
+ */
205
+ this.isTree = schema.model.isTree || false;
206
+
207
+ /**
208
+ * @member {boolean} isLoaded - State: whether or not entities have been loaded at least once
203
209
  */
204
210
  this.isLoaded = false;
205
211
 
206
212
  /**
207
- * @member {Boolean} isLoading - State: whether or not entities are currently being loaded
213
+ * @member {boolean} isLoading - State: whether or not entities are currently being loaded
208
214
  */
209
215
  this.isLoading = false;
210
216
 
@@ -214,12 +220,12 @@ export default class Repository extends EventEmitter {
214
220
  this.lastLoaded = null;
215
221
 
216
222
  /**
217
- * @member {Boolean} isSaving - State: whether or not entities are currently being saved
223
+ * @member {boolean} isSaving - State: whether or not entities are currently being saved
218
224
  */
219
225
  this.isSaving = false;
220
226
 
221
227
  /**
222
- * @member {Boolean} isSorted - State: whether or not any sorting is currently applied to entities
228
+ * @member {boolean} isSorted - State: whether or not any sorting is currently applied to entities
223
229
  */
224
230
  this.isSorted = false;
225
231
 
@@ -412,7 +418,7 @@ export default class Repository extends EventEmitter {
412
418
  // /____/\____/_/ \__/
413
419
 
414
420
  /**
415
- * @member {Boolean} hasSorters - Whether or not any sorters are applied
421
+ * @member {boolean} hasSorters - Whether or not any sorters are applied
416
422
  */
417
423
  get hasSorters() {
418
424
  if (this.isDestroyed) {
@@ -501,22 +507,20 @@ export default class Repository extends EventEmitter {
501
507
  return;
502
508
  }
503
509
  let sorters = [];
504
- if (this.schema?.model) {
505
- if (_.size(this.schema.model.sorters) > 0) {
506
- sorters = this.schema.model.sorters
507
- } else if (!_.isNil(this.schema.model.sortProperty)) {
508
- sorters = [{
509
- name: this.schema.model.sortProperty,
510
- direction: 'ASC',
511
- fn: 'default',
512
- }];
513
- } else if (!_.isNil(this.schema.model.displayProperty)) {
514
- sorters = [{
515
- name: this.schema.model.displayProperty,
516
- direction: 'ASC',
517
- fn: 'default',
518
- }];
519
- }
510
+ if (_.size(this.schema.model.sorters) > 0) {
511
+ sorters = this.schema.model.sorters
512
+ } else if (!_.isNil(this.schema.model.sortProperty)) {
513
+ sorters = [{
514
+ name: this.schema.model.sortProperty,
515
+ direction: 'ASC',
516
+ fn: 'default',
517
+ }];
518
+ } else if (!_.isNil(this.schema.model.displayProperty)) {
519
+ sorters = [{
520
+ name: this.schema.model.displayProperty,
521
+ direction: 'ASC',
522
+ fn: 'default',
523
+ }];
520
524
  }
521
525
  return sorters;
522
526
  }
@@ -576,7 +580,7 @@ export default class Repository extends EventEmitter {
576
580
  // /_/ /_/_/\__/\___/_/
577
581
 
578
582
  /**
579
- * @member {Boolean} hasFilters - Whether or not any filters are applied
583
+ * @member {boolean} hasFilters - Whether or not any filters are applied
580
584
  */
581
585
  get hasFilters() {
582
586
  if (this.isDestroyed) {
@@ -1459,10 +1463,10 @@ export default class Repository extends EventEmitter {
1459
1463
  }
1460
1464
 
1461
1465
  const schema = this.getSchema();
1462
- if (!schema.model.associations.hasOne.includes(repositoryName) &&
1463
- !schema.model.associations.hasMany.includes(repositoryName) &&
1464
- !schema.model.associations.belongsTo.includes(repositoryName) &&
1465
- !schema.model.associations.belongsToMany.includes(repositoryName)
1466
+ if (!schema.model.associations?.hasOne.includes(repositoryName) &&
1467
+ !schema.model.associations?.hasMany.includes(repositoryName) &&
1468
+ !schema.model.associations?.belongsTo.includes(repositoryName) &&
1469
+ !schema.model.associations?.belongsToMany.includes(repositoryName)
1466
1470
  ) {
1467
1471
  this.throwError(repositoryName + ' is not associated with this schema');
1468
1472
  return;
@@ -1821,7 +1825,7 @@ export default class Repository extends EventEmitter {
1821
1825
  * Mainly used for phantom Entities
1822
1826
  * Helper for delete()
1823
1827
  */
1824
- removeEntity(entity) { // standard function notation so it can be called by child class
1828
+ removeEntity(entity) { // standard function notation so it can be called by child class via super.removeEntity
1825
1829
  this.entities = _.filter(this.entities, e => e !== entity);
1826
1830
  entity.destroy();
1827
1831
  }
@@ -1931,6 +1935,90 @@ export default class Repository extends EventEmitter {
1931
1935
  }
1932
1936
 
1933
1937
 
1938
+ // ______
1939
+ // /_ __/_______ ___ _____
1940
+ // / / / ___/ _ \/ _ \/ ___/
1941
+ // / / / / / __/ __(__ )
1942
+ // /_/ /_/ \___/\___/____/
1943
+
1944
+
1945
+ /**
1946
+ * Gets the root TreeNodes
1947
+ */
1948
+ getRootNodes = () => {
1949
+ this.ensureTree();
1950
+ if (this.isDestroyed) {
1951
+ this.throwError('this.getRootNodes is no longer valid. Repository has been destroyed.');
1952
+ return;
1953
+ }
1954
+
1955
+ // Look through all entities and pull out the root nodes.
1956
+ // Subclasses of Repository will override this method to get root nodes from server
1957
+ const entities = _.filter(this.getEntities(), (entity) => {
1958
+ return entity.isRoot;
1959
+ })
1960
+ return entities;
1961
+ }
1962
+
1963
+ /**
1964
+ * Populates the TreeNodes with .parent and .children references
1965
+ */
1966
+ assembleTreeNodes = () => {
1967
+ this.ensureTree();
1968
+ if (this.isDestroyed) {
1969
+ this.throwError('this.assembleTreeNodes is no longer valid. Repository has been destroyed.');
1970
+ return;
1971
+ }
1972
+
1973
+ const treeNodes = this.getEntities();
1974
+
1975
+ // Reset all parent/child relationships
1976
+ _.each(treeNodes, (treeNode) => {
1977
+ treeNode.parent = null;
1978
+ treeNode.children = [];
1979
+ });
1980
+
1981
+ // Rebuild all parent/child relationships
1982
+ _.each(treeNodes, (treeNode) => {
1983
+ const parent = this.getById(treeNode.parentId);
1984
+ if (parent) {
1985
+ treeNode.parent = parent;
1986
+ parent.children.push(treeNode);
1987
+ }
1988
+ });
1989
+ }
1990
+
1991
+ /**
1992
+ * Removes the treeNode and all of its children from repository
1993
+ * without deleting anything on the server
1994
+ */
1995
+ removeTreeNode = (treeNode) => {
1996
+ if (!_.isEmpty(treeNode.children)) {
1997
+ const children = treeNode.children;
1998
+ treeNode.parent = null;
1999
+ treeNode.children = [];
2000
+
2001
+ _.each(children, (child) => {
2002
+ this.removeTreeNode(child);
2003
+ });
2004
+ }
2005
+
2006
+ this.removeEntity(treeNode);
2007
+ }
2008
+
2009
+ /**
2010
+ * Helper to make sure this Repository is a tree
2011
+ * @private
2012
+ */
2013
+ ensureTree = async () => {
2014
+ if (!this.isTree) {
2015
+ this.throwError('This Repository is not a tree!');
2016
+ }
2017
+ }
2018
+
2019
+
2020
+
2021
+
1934
2022
 
1935
2023
 
1936
2024
  // ____ __ _
@@ -64,6 +64,39 @@ export default class Schema extends EventEmitter {
64
64
  */
65
65
  sortProperty: null,
66
66
 
67
+ /**
68
+ * @member {string} parentIdProperty - name of parent_id Property (e.g. 'categories__parent_id' for Adjacency Lists, and parent_id for Closure Tables)
69
+ * For trees only
70
+ */
71
+ parentIdProperty: null,
72
+
73
+ /**
74
+ * @member {string} depthIdProperty - name of depth Property (e.g. 'categories__depth' for Adjacency Lists, and depth for Closure Tables)
75
+ * For trees only
76
+ */
77
+ depthProperty: null,
78
+
79
+ /**
80
+ * @member {string} hasChildrenProperty - name of hasChildren Property (e.g. 'categories__has_children' for Adjacency Lists, and has_children for Closure Tables)
81
+ * For trees only
82
+ */
83
+ hasChildrenProperty: null,
84
+
85
+ /**
86
+ * @member {boolean} isTree - Whether this model has hierarchical tree data
87
+ */
88
+ isTree: false,
89
+
90
+ /**
91
+ * @member {boolean} isAdjacencyList - Whether this tree is an Adjacency List
92
+ */
93
+ isAdjacencyList: false,
94
+
95
+ /**
96
+ * @member {boolean} isClosureTable - Whether this tree is a Closure Table
97
+ */
98
+ isClosureTable: false,
99
+
67
100
  /**
68
101
  * @member {array} properties - Array of Property definition objects
69
102
  */
@@ -1,177 +0,0 @@
1
- {
2
- "title": "JSON schema for https://cypress.io test runner cypress.json file. Details at https://on.cypress.io/configuration",
3
- "$schema": "http://json-schema.org/draft-04/schema#",
4
- "type": "object",
5
- "properties": {
6
- "baseUrl" : {
7
- "type": "string",
8
- "description": "Url used as prefix for cy.visit() or cy.request() command’s url. Example http://localhost:3030 or https://test.my-domain.com"
9
- },
10
- "env": {
11
- "type": "object",
12
- "description": "Any values to be set as environment variables",
13
- "body": {}
14
- },
15
- "ignoreTestFiles": {
16
- "type": ["string", "array"],
17
- "items": {
18
- "type": "string"
19
- },
20
- "description": "A String or Array of glob patterns used to ignore test files that would otherwise be shown in your list of tests. Cypress uses minimatch with the options: {dot: true, matchBase: true}. We suggest using http://globtester.com to test what files would match."
21
- },
22
- "numTestsKeptInMemory": {
23
- "type": "number",
24
- "default": 50,
25
- "description": "The number of tests for which snapshots and command data are kept in memory. Reduce this number if you are experiencing high memory consumption in your browser during a test run."
26
- },
27
- "port": {
28
- "type": "number",
29
- "default": null,
30
- "description": "Port used to host Cypress. Normally this is a randomly generated port"
31
- },
32
- "reporter": {
33
- "type": "string",
34
- "default": "spec",
35
- "description": "The reporter used when running headlessly or in CI. See https://on.cypress.io/reporters"
36
- },
37
- "reporterOptions": {
38
- "type": "object",
39
- "default": null,
40
- "description": "The reporter options used. Supported options depend on the reporter. See https://on.cypress.io/reporters#Reporter-Options"
41
- },
42
- "watchForFileChanges": {
43
- "type": "boolean",
44
- "default": true,
45
- "description": "Whether Cypress will watch and restart tests on test file changes"
46
- },
47
- "defaultCommandTimeout": {
48
- "type": "number",
49
- "default": 4000,
50
- "description": "Time, in milliseconds, to wait until most DOM based commands are considered timed out"
51
- },
52
- "execTimeout": {
53
- "type": "number",
54
- "default": 60000,
55
- "description": "Time, in milliseconds, to wait for a system command to finish executing during a cy.exec() command"
56
- },
57
- "pageLoadTimeout": {
58
- "type": "number",
59
- "default": 60000,
60
- "description": "Time, in milliseconds, to wait for page transition events or cy.visit(), cy.go(), cy.reload() commands to fire their page load events"
61
- },
62
- "requestTimeout": {
63
- "type": "number",
64
- "default": 5000,
65
- "description": "Time, in milliseconds, to wait for an XHR request to go out in a cy.wait() command"
66
- },
67
- "responseTimeout": {
68
- "type": "number",
69
- "default": 30000,
70
- "description": "Time, in milliseconds, to wait until a response in a cy.request(), cy.wait(), cy.fixture(), cy.getCookie(), cy.getCookies(), cy.setCookie(), cy.clearCookie(), cy.clearCookies(), and cy.screenshot() commands"
71
- },
72
- "fileServerFolder": {
73
- "type": "string",
74
- "default": "root project folder",
75
- "description": "Path to folder where application files will attempt to be served from"
76
- },
77
- "fixturesFolder": {
78
- "type": ["string", "boolean"],
79
- "default": "cypress/fixtures",
80
- "description": "Path to folder containing fixture files (Pass false to disable)"
81
- },
82
- "integrationFolder": {
83
- "type": "string",
84
- "default": "cypress/integration",
85
- "description": "Path to folder containing integration test files"
86
- },
87
- "pluginsFile": {
88
- "type": ["string", "boolean"],
89
- "default": "cypress/plugins/index.js",
90
- "description": "Path to plugins file. (Pass false to disable)"
91
- },
92
- "screenshotsFolder": {
93
- "type": "string",
94
- "default": "cypress/screenshots",
95
- "description": "Path to folder where screenshots will be saved from cy.screenshot() command or after a headless or CI run’s test failure"
96
- },
97
- "supportFile": {
98
- "type": ["string", "boolean"],
99
- "default": "cypress/support/index.js",
100
- "description": "Path to file to load before test files load. This file is compiled and bundled. (Pass false to disable)"
101
- },
102
- "videosFolder": {
103
- "type": "string",
104
- "default": "cypress/videos",
105
- "description": "Path to folder where videos will be saved after a headless or CI run"
106
- },
107
- "trashAssetsBeforeRuns": {
108
- "type": "boolean",
109
- "default": true,
110
- "description": "Whether Cypress will trash assets within the screenshotsFolder and videosFolder before headless test runs."
111
- },
112
- "videoCompression": {
113
- "type": ["number", "boolean"],
114
- "default": 32,
115
- "description": "The quality setting for the video compression, in Constant Rate Factor (CRF). The value can be false to disable compression or a value between 0 and 51, where a lower value results in better quality (at the expense of a higher file size)."
116
- },
117
- "video": {
118
- "type": "boolean",
119
- "default": true,
120
- "description": "Whether Cypress will record a video of the test run when running headlessly."
121
- },
122
- "videoUploadOnPasses": {
123
- "type": "boolean",
124
- "default": true,
125
- "description": "Whether Cypress will upload the video to the Dashboard even if all tests are passing. This applies only when recording your runs to the Dashboard. Turn this off if you’d like the video uploaded only when there are failing tests."
126
- },
127
- "chromeWebSecurity": {
128
- "type": "boolean",
129
- "default": true,
130
- "description": "Whether Chrome Web Security for same-origin policy and insecure mixed content is enabled. Read more about this at https://on.cypress.io/web-security"
131
- },
132
- "userAgent": {
133
- "type": "string",
134
- "default": null,
135
- "description": "Enables you to override the default user agent the browser sends in all request headers. User agent values are typically used by servers to help identify the operating system, browser, and browser version. See User-Agent MDN Documentation for example user agent values here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent"
136
- },
137
- "blacklistHosts": {
138
- "type": ["string", "array"],
139
- "items": {
140
- "type": "string"
141
- },
142
- "default": null,
143
- "description": "A String or Array of hosts that you wish to block traffic for. Please read the notes for examples on using this https://on.cypress.io/configuration#blacklistHosts"
144
- },
145
- "modifyObstructiveCode": {
146
- "type": "boolean",
147
- "default": true,
148
- "description": "Whether Cypress will search for and replace obstructive JS code found in .js or .html files that prevents Cypress from working. Please read the notes for more information on this setting. https://on.cypress.io/configuration#modifyObstructiveCode"
149
- },
150
- "viewportHeight": {
151
- "type": "number",
152
- "default": 660,
153
- "description": "Default height in pixels for the application under tests’ viewport (Override with cy.viewport() command)"
154
- },
155
- "viewportWidth": {
156
- "type": "number",
157
- "default": 1000,
158
- "description": "Default width in pixels for the application under tests’ viewport. (Override with cy.viewport() command)"
159
- },
160
- "animationDistanceThreshold": {
161
- "type": "number",
162
- "default": 5,
163
- "description": "The distance in pixels an element must exceed over time to be considered animating"
164
- },
165
- "waitForAnimations": {
166
- "type": "boolean",
167
- "default": true,
168
- "description": "Whether to wait for elements to finish animating before executing commands"
169
- },
170
- "projectId": {
171
- "type": "string",
172
- "default": null,
173
- "description": "A 6 character string to identify this project with Dashboard service. See https://on.cypress.io/dashboard-service#Identification"
174
- }
175
- }
176
- }
177
-
package/cypress.json DELETED
@@ -1 +0,0 @@
1
- {}
File without changes