@homebound/form-state 2.25.0 → 2.25.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.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Our own `deepEquals` because either `fast-deep-equals` or `dequal` or etc actually
3
+ * handle cyclic data structures, despite ChatGTP's assertions/hallucinations.
4
+ *
5
+ * Ported from https://github.com/KoryNunn/cyclic-deep-equal which is ISC.
6
+ */
7
+ export declare function deepEquals(a: any, b: any, visited?: Set<any>): boolean;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deepEquals = void 0;
4
+ /**
5
+ * Our own `deepEquals` because either `fast-deep-equals` or `dequal` or etc actually
6
+ * handle cyclic data structures, despite ChatGTP's assertions/hallucinations.
7
+ *
8
+ * Ported from https://github.com/KoryNunn/cyclic-deep-equal which is ISC.
9
+ */
10
+ function deepEquals(a, b, visited = new Set()) {
11
+ const aType = typeof a;
12
+ if (aType !== typeof b)
13
+ return false;
14
+ if (a == null || b == null || !(aType === "object" || aType === "function")) {
15
+ if (aType === "number" && isNaN(a) && isNaN(b))
16
+ return true;
17
+ return a === b;
18
+ }
19
+ if (Array.isArray(a) !== Array.isArray(b))
20
+ return false;
21
+ const aKeys = Object.keys(a), bKeys = Object.keys(b);
22
+ if (aKeys.length !== bKeys.length)
23
+ return false;
24
+ let equal = true;
25
+ for (const key of aKeys) {
26
+ if (!(key in b)) {
27
+ equal = false;
28
+ break;
29
+ }
30
+ if (a[key] && a[key] instanceof Object) {
31
+ if (visited.has(a[key]))
32
+ break;
33
+ visited.add(a[key]);
34
+ }
35
+ if (!deepEquals(a[key], b[key], visited)) {
36
+ equal = false;
37
+ break;
38
+ }
39
+ }
40
+ return equal;
41
+ }
42
+ exports.deepEquals = deepEquals;
@@ -1,3 +1,3 @@
1
- declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react/dist/types-0a347bb9").R, import("@storybook/types").Args>;
1
+ declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react/dist/types-0fc72a6d").R, import("@storybook/types").Args>;
2
2
  export default _default;
3
3
  export declare function AppExample(): import("react/jsx-runtime").JSX.Element;
@@ -1468,6 +1468,22 @@ describe("formState", () => {
1468
1468
  a.address.set({ street: "123", city: "nyc" });
1469
1469
  expect(a.value).toEqual({ address: { street: "123", city: "nyc" } });
1470
1470
  });
1471
+ it("can have child object states with cycles", () => {
1472
+ // Given an author with an address child
1473
+ // And two addresses that are basically identical and both have cycles
1474
+ const address1 = { city: "city2" };
1475
+ address1.someCycle = address1;
1476
+ const address2 = { city: "city2" };
1477
+ address2.someCycle = address2;
1478
+ const a = (0, objectField_1.createObjectState)({
1479
+ id: { type: "value" },
1480
+ address: { type: "value" },
1481
+ }, { address: address1 });
1482
+ // When we change the address
1483
+ a.address.set(address2);
1484
+ // Then it doesn't error on dirty checks
1485
+ expect(a.address.dirty).toBe(false);
1486
+ });
1471
1487
  it("provides isNewEntity", () => {
1472
1488
  // Given an author without an id
1473
1489
  const formState = (0, objectField_1.createObjectState)(authorWithAddressConfig, {
package/dist/utils.js CHANGED
@@ -1,12 +1,9 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.deepClone = exports.hasToJSON = exports.areEqual = exports.isEmpty = exports.isNotUndefined = exports.pickFields = exports.isQuery = exports.isInput = exports.initValue = exports.assertNever = exports.fail = void 0;
7
- const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
8
4
  const is_plain_object_1 = require("is-plain-object");
9
5
  const mobx_1 = require("mobx");
6
+ const deepEquals_1 = require("./fields/deepEquals");
10
7
  function fail(message) {
11
8
  throw new Error(message || "Failed");
12
9
  }
@@ -108,16 +105,16 @@ exports.isEmpty = isEmpty;
108
105
  */
109
106
  function areEqual(a, b, strictOrder) {
110
107
  if ((0, is_plain_object_1.isPlainObject)(a)) {
111
- return (0, fast_deep_equal_1.default)((0, mobx_1.toJS)(a), (0, mobx_1.toJS)(b));
108
+ return (0, deepEquals_1.deepEquals)((0, mobx_1.toJS)(a), (0, mobx_1.toJS)(b));
112
109
  }
113
110
  if (hasToJSON(a) || hasToJSON(b)) {
114
111
  const a1 = hasToJSON(a) ? a.toJSON() : a;
115
112
  const b1 = hasToJSON(b) ? b.toJSON() : b;
116
- return (0, fast_deep_equal_1.default)(a1, b1);
113
+ return (0, deepEquals_1.deepEquals)(a1, b1);
117
114
  }
118
115
  if (a && b && a instanceof Array && b instanceof Array) {
119
116
  if (strictOrder !== false) {
120
- return (0, fast_deep_equal_1.default)(a, b);
117
+ return (0, deepEquals_1.deepEquals)(a, b);
121
118
  }
122
119
  if (a.length !== b.length)
123
120
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homebound/form-state",
3
- "version": "2.25.0",
3
+ "version": "2.25.1",
4
4
  "author": "Homebound",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -30,7 +30,6 @@
30
30
  "src/**/*.{ts,tsx,css,md}": "prettier --write"
31
31
  },
32
32
  "dependencies": {
33
- "fast-deep-equal": "^3.1.3",
34
33
  "is-plain-object": "^5.0.0"
35
34
  },
36
35
  "peerDependencies": {
@@ -42,17 +41,17 @@
42
41
  "@babel/preset-env": "^7.22.15",
43
42
  "@babel/preset-react": "^7.22.15",
44
43
  "@babel/preset-typescript": "^7.22.15",
45
- "@homebound/rtl-utils": "2.65.0",
44
+ "@homebound/rtl-utils": "2.65.2",
46
45
  "@semantic-release/exec": "^6.0.3",
47
46
  "@semantic-release/git": "^10.0.1",
48
- "@storybook/addon-essentials": "^7.4.0",
49
- "@storybook/addon-links": "^7.4.0",
50
- "@storybook/addons": "^7.4.0",
51
- "@storybook/react": "^7.4.0",
52
- "@storybook/react-webpack5": "^7.4.0",
53
- "@testing-library/dom": "^9.3.1",
54
- "@testing-library/jest-dom": "^6.1.3",
55
- "@testing-library/react": "^14.0.0",
47
+ "@storybook/addon-essentials": "^7.6.5",
48
+ "@storybook/addon-links": "^7.6.5",
49
+ "@storybook/addons": "^7.6.5",
50
+ "@storybook/react": "^7.6.5",
51
+ "@storybook/react-webpack5": "^7.6.5",
52
+ "@testing-library/dom": "^9.3.3",
53
+ "@testing-library/jest-dom": "^6.1.5",
54
+ "@testing-library/react": "^14.1.2",
56
55
  "@tsconfig/recommended": "^1.0.2",
57
56
  "@types/jest": "^29.5.4",
58
57
  "@types/react": "^18.2.21",
@@ -71,7 +70,7 @@
71
70
  "eslint-plugin-react": "^7.22.0",
72
71
  "eslint-plugin-react-hooks": "^4.2.0",
73
72
  "husky": "^3.1.0",
74
- "jest": "^29.6.4",
73
+ "jest": "^29.7.0",
75
74
  "jest-environment-jsdom": "^29.6.4",
76
75
  "lint-staged": "^14.0.1",
77
76
  "mobx": "^6.10.2",
@@ -80,13 +79,13 @@
80
79
  "prettier-plugin-organize-imports": "^3.2.3",
81
80
  "react": "^18.2.0",
82
81
  "react-dom": "^18.2.0",
83
- "semantic-release": "^21.1.1",
84
- "storybook": "^7.4.0",
82
+ "semantic-release": "^22.0.12",
83
+ "storybook": "^7.6.5",
85
84
  "ts-jest": "^29.1.1",
86
- "ts-node": "^10.9.1",
87
- "ts-patch": "^3.0.2",
85
+ "ts-node": "^10.9.2",
86
+ "ts-patch": "^3.1.1",
88
87
  "tslib": "^2.6.2",
89
- "typescript": "^5.2.2",
88
+ "typescript": "^5.3.3",
90
89
  "typescript-transform-paths": "^3.4.6"
91
90
  },
92
91
  "packageManager": "yarn@3.6.3"