@coaction/valtio 2.0.0 → 2.1.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.
package/README.md CHANGED
@@ -1,17 +1,15 @@
1
1
  # @coaction/valtio
2
2
 
3
- ![Node CI](https://github.com/coactionjs/coaction/workflows/Node%20CI/badge.svg)
4
- [![npm](https://img.shields.io/npm/v/@coaction/valtio.svg)](https://www.npmjs.com/package/@coaction/valtio)
5
- ![license](https://img.shields.io/npm/l/@coaction/valtio)
3
+ ![Node CI](https://github.com/coactionjs/coaction/workflows/Node%20CI/badge.svg) [![npm](https://img.shields.io/npm/v/@coaction/valtio.svg)](https://www.npmjs.com/package/@coaction/valtio) ![license](https://img.shields.io/npm/l/@coaction/valtio)
6
4
 
7
5
  A Coaction integration tool for Valtio.
8
6
 
9
7
  ## Installation
10
8
 
11
- You can install it via npm, yarn or pnpm.
9
+ Install it with pnpm:
12
10
 
13
11
  ```sh
14
- npm install coaction @coaction/valtio valtio
12
+ pnpm add coaction @coaction/valtio valtio
15
13
  ```
16
14
 
17
15
  ## Usage
@@ -37,6 +35,12 @@ store.getState().increment();
37
35
 
38
36
  - `@coaction/valtio` only supports binding a whole Valtio store.
39
37
  - Coaction `Slices` mode is not supported in this adapter.
38
+ - Shared main/client mode is supported for Coaction method execution; direct
39
+ writes to mirrored schema fields on the client-side Valtio proxy are restored
40
+ to the authoritative snapshot.
41
+ - Unknown root properties written directly to the Valtio proxy are ignored by
42
+ Coaction's fixed schema. They are not promoted into Coaction raw/public state,
43
+ and this adapter does not guarantee pruning them from the Valtio proxy.
40
44
 
41
45
  ## Documentation
42
46
 
package/dist/index.js CHANGED
@@ -1,107 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#endregion
3
- let mutability = require("mutability");
4
3
  let coaction = require("coaction");
5
4
  let valtio_vanilla = require("valtio/vanilla");
6
5
  //#region packages/coaction-valtio/src/index.ts
7
6
  const instancesMap = /* @__PURE__ */ new WeakMap();
8
- const getOwnEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));
9
- const isUnsafeKey = (key) => typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
10
- const isArrayIndexKey = (key) => {
11
- if (typeof key !== "string") return false;
12
- const index = Number(key);
13
- return Number.isInteger(index) && index >= 0 && index < 2 ** 32 - 1 && String(index) === key;
14
- };
15
- const isObjectRecord = (value) => Object.prototype.toString.call(value) === "[object Object]";
16
- const replaceMutableState = (rawState, mutableState, publicState, source) => {
17
- const nextKeys = /* @__PURE__ */ new Set();
18
- for (const key of getOwnEnumerableKeys(source)) {
19
- if (isUnsafeKey(key)) continue;
20
- if (typeof source[key] === "function") continue;
21
- nextKeys.add(key);
22
- }
23
- for (const key of getOwnEnumerableKeys(rawState)) {
24
- if (isUnsafeKey(key)) {
25
- delete rawState[key];
26
- delete mutableState[key];
27
- delete publicState[key];
28
- continue;
29
- }
30
- if (typeof rawState[key] === "function") continue;
31
- if (!nextKeys.has(key)) {
32
- delete rawState[key];
33
- delete mutableState[key];
34
- delete publicState[key];
35
- }
36
- }
37
- const rawSeen = /* @__PURE__ */ new WeakMap();
38
- const mutableSeen = /* @__PURE__ */ new WeakMap();
39
- const publicSeen = /* @__PURE__ */ new WeakMap();
40
- rawSeen.set(source, rawState);
41
- mutableSeen.set(source, mutableState);
42
- publicSeen.set(source, publicState);
43
- nextKeys.forEach((key) => {
44
- rawState[key] = (0, coaction.sanitizeReplacementState)(source[key], rawSeen);
45
- mutableState[key] = (0, coaction.sanitizeReplacementState)(source[key], mutableSeen);
46
- publicState[key] = (0, coaction.sanitizeReplacementState)(source[key], publicSeen);
47
- });
48
- };
49
- const toSnapshot = (value, visited = /* @__PURE__ */ new WeakMap()) => {
50
- if (Array.isArray(value)) {
51
- if (visited.has(value)) return visited.get(value);
52
- const next = [];
53
- next.length = value.length;
54
- visited.set(value, next);
55
- for (let index = 0; index < value.length; index += 1) if (Object.prototype.hasOwnProperty.call(value, index)) next[index] = toSnapshot(value[index], visited);
56
- const source = value;
57
- const target = next;
58
- for (const key of getOwnEnumerableKeys(value)) {
59
- if (isArrayIndexKey(key) || isUnsafeKey(key)) continue;
60
- const child = source[key];
61
- if (typeof child !== "function") target[key] = toSnapshot(child, visited);
62
- }
63
- return next;
64
- }
65
- if (typeof value === "object" && value !== null) {
66
- if (!isObjectRecord(value)) return value;
67
- if (visited.has(value)) return visited.get(value);
68
- const next = {};
69
- visited.set(value, next);
70
- for (const key of getOwnEnumerableKeys(value)) {
71
- if (isUnsafeKey(key)) continue;
72
- const child = value[key];
73
- if (typeof child !== "function") next[key] = toSnapshot(child, visited);
74
- }
75
- return next;
76
- }
77
- return value;
78
- };
79
- const snapshotPureState = (store) => toSnapshot(store.getPureState());
80
- const isEqualSnapshot = (left, right, visited = /* @__PURE__ */ new WeakMap()) => {
81
- if (Object.is(left, right)) return true;
82
- if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
83
- const leftIsArray = Array.isArray(left);
84
- const rightIsArray = Array.isArray(right);
85
- if (leftIsArray || rightIsArray) {
86
- if (!leftIsArray || !rightIsArray || left.length !== right.length) return false;
87
- } else if (!isObjectRecord(left) || !isObjectRecord(right)) return false;
88
- let seenTargets = visited.get(left);
89
- if (!seenTargets) {
90
- seenTargets = /* @__PURE__ */ new WeakSet();
91
- visited.set(left, seenTargets);
92
- } else if (seenTargets.has(right)) return true;
93
- seenTargets.add(right);
94
- const leftRecord = left;
95
- const rightRecord = right;
96
- const leftKeys = getOwnEnumerableKeys(left);
97
- const rightKeys = getOwnEnumerableKeys(right);
98
- if (leftKeys.length !== rightKeys.length) return false;
99
- for (const key of leftKeys) {
100
- if (!Object.prototype.hasOwnProperty.call(rightRecord, key)) return false;
101
- if (!isEqualSnapshot(leftRecord[key], rightRecord[key], visited)) return false;
102
- }
103
- return true;
104
- };
105
7
  const handleStore = (store, rawState, state, internal) => {
106
8
  if (!internal.toMutableRaw) {
107
9
  internal.toMutableRaw = (key) => instancesMap.get(key);
@@ -111,20 +13,20 @@ const handleStore = (store, rawState, state, internal) => {
111
13
  const restoreClientState = (snapshot) => {
112
14
  isApplyingCoactionState = true;
113
15
  try {
114
- replaceMutableState(internal.rootState ?? rawState, getMutableState(), store.getState(), snapshot);
16
+ (0, coaction.replaceMutableAdapterState)(internal.rootState ?? rawState, getMutableState(), store.getState(), snapshot);
115
17
  } finally {
116
- lastSnapshot = snapshotPureState(store);
18
+ lastSnapshot = (0, coaction.snapshotMutableAdapterPureState)(store);
117
19
  isApplyingCoactionState = false;
118
20
  }
119
21
  };
120
22
  const syncSharedExternalChange = () => {
121
- const currentSnapshot = snapshotPureState(store);
23
+ const currentSnapshot = (0, coaction.snapshotMutableAdapterPureState)(store);
122
24
  if (isApplyingCoactionState) {
123
25
  lastSnapshot = currentSnapshot;
124
26
  return "handled";
125
27
  }
126
28
  if (store.share === "client" && lastSnapshot) {
127
- if (!isEqualSnapshot(currentSnapshot, lastSnapshot)) restoreClientState(lastSnapshot);
29
+ if (!(0, coaction.isEqualMutableAdapterSnapshot)(currentSnapshot, lastSnapshot)) restoreClientState(lastSnapshot);
128
30
  return "ignored";
129
31
  }
130
32
  if (store.share === "main" && lastSnapshot) {
@@ -145,8 +47,8 @@ const handleStore = (store, rawState, state, internal) => {
145
47
  store._listeners = /* @__PURE__ */ new Set();
146
48
  let unsubscribeExternal;
147
49
  const cancelReadySubscription = (0, coaction.onStoreReady)(store, () => {
148
- replaceMutableState(internal.rootState ?? rawState, getMutableState(), store.getState(), (0, coaction.sanitizeInitialStateValue)(snapshotPureState(store)));
149
- lastSnapshot = snapshotPureState(store);
50
+ (0, coaction.replaceMutableAdapterState)(internal.rootState ?? rawState, getMutableState(), store.getState(), (0, coaction.sanitizeInitialStateValue)((0, coaction.snapshotMutableAdapterPureState)(store)));
51
+ lastSnapshot = (0, coaction.snapshotMutableAdapterPureState)(store);
150
52
  unsubscribeExternal = (0, valtio_vanilla.subscribe)(getMutableState(), () => {
151
53
  const change = syncSharedExternalChange();
152
54
  if (change === "ignored") return;
@@ -155,6 +57,7 @@ const handleStore = (store, rawState, state, internal) => {
155
57
  });
156
58
  });
157
59
  Object.assign(store, { subscribe: (listener) => {
60
+ internal.assertAlive?.("subscribe");
158
61
  store._listeners.add(listener);
159
62
  return () => {
160
63
  store._listeners?.delete(listener);
@@ -175,16 +78,17 @@ const handleStore = (store, rawState, state, internal) => {
175
78
  store._destroyers = void 0;
176
79
  baseDestroy();
177
80
  };
178
- store.apply = (state = store.getState(), patches) => {
81
+ store.apply = (state = store.getPureState(), patches) => {
82
+ internal.assertAlive?.("apply");
179
83
  isApplyingCoactionState = true;
180
84
  try {
181
85
  if (!patches) {
182
- replaceMutableState(internal.rootState ?? rawState, getMutableState(), store.getState(), state);
86
+ (0, coaction.replaceMutableAdapterState)(internal.rootState ?? rawState, getMutableState(), store.getState(), state);
183
87
  return;
184
88
  }
185
- (0, mutability.apply)(state, patches);
89
+ (0, coaction.applyMutableAdapterPatches)(state, patches, internal.rootState ?? rawState, getMutableState(), store.getState());
186
90
  } finally {
187
- lastSnapshot = snapshotPureState(store);
91
+ lastSnapshot = (0, coaction.snapshotMutableAdapterPureState)(store);
188
92
  isApplyingCoactionState = false;
189
93
  internal.notifyStateChange?.();
190
94
  }
package/dist/index.mjs CHANGED
@@ -1,107 +1,9 @@
1
- import { apply } from "mutability";
2
- import { createBinder, onStoreReady, replaceExternalStoreState, sanitizeInitialStateValue, sanitizeReplacementState } from "coaction";
1
+ import { applyMutableAdapterPatches, createBinder, isEqualMutableAdapterSnapshot, onStoreReady, replaceExternalStoreState, replaceMutableAdapterState, sanitizeInitialStateValue, snapshotMutableAdapterPureState } from "coaction";
3
2
  import { proxy, subscribe } from "valtio/vanilla";
4
3
  export * from "valtio/vanilla";
5
4
  //#endregion
6
5
  //#region packages/coaction-valtio/src/index.ts
7
6
  const instancesMap = /* @__PURE__ */ new WeakMap();
8
- const getOwnEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));
9
- const isUnsafeKey = (key) => typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
10
- const isArrayIndexKey = (key) => {
11
- if (typeof key !== "string") return false;
12
- const index = Number(key);
13
- return Number.isInteger(index) && index >= 0 && index < 2 ** 32 - 1 && String(index) === key;
14
- };
15
- const isObjectRecord = (value) => Object.prototype.toString.call(value) === "[object Object]";
16
- const replaceMutableState = (rawState, mutableState, publicState, source) => {
17
- const nextKeys = /* @__PURE__ */ new Set();
18
- for (const key of getOwnEnumerableKeys(source)) {
19
- if (isUnsafeKey(key)) continue;
20
- if (typeof source[key] === "function") continue;
21
- nextKeys.add(key);
22
- }
23
- for (const key of getOwnEnumerableKeys(rawState)) {
24
- if (isUnsafeKey(key)) {
25
- delete rawState[key];
26
- delete mutableState[key];
27
- delete publicState[key];
28
- continue;
29
- }
30
- if (typeof rawState[key] === "function") continue;
31
- if (!nextKeys.has(key)) {
32
- delete rawState[key];
33
- delete mutableState[key];
34
- delete publicState[key];
35
- }
36
- }
37
- const rawSeen = /* @__PURE__ */ new WeakMap();
38
- const mutableSeen = /* @__PURE__ */ new WeakMap();
39
- const publicSeen = /* @__PURE__ */ new WeakMap();
40
- rawSeen.set(source, rawState);
41
- mutableSeen.set(source, mutableState);
42
- publicSeen.set(source, publicState);
43
- nextKeys.forEach((key) => {
44
- rawState[key] = sanitizeReplacementState(source[key], rawSeen);
45
- mutableState[key] = sanitizeReplacementState(source[key], mutableSeen);
46
- publicState[key] = sanitizeReplacementState(source[key], publicSeen);
47
- });
48
- };
49
- const toSnapshot = (value, visited = /* @__PURE__ */ new WeakMap()) => {
50
- if (Array.isArray(value)) {
51
- if (visited.has(value)) return visited.get(value);
52
- const next = [];
53
- next.length = value.length;
54
- visited.set(value, next);
55
- for (let index = 0; index < value.length; index += 1) if (Object.prototype.hasOwnProperty.call(value, index)) next[index] = toSnapshot(value[index], visited);
56
- const source = value;
57
- const target = next;
58
- for (const key of getOwnEnumerableKeys(value)) {
59
- if (isArrayIndexKey(key) || isUnsafeKey(key)) continue;
60
- const child = source[key];
61
- if (typeof child !== "function") target[key] = toSnapshot(child, visited);
62
- }
63
- return next;
64
- }
65
- if (typeof value === "object" && value !== null) {
66
- if (!isObjectRecord(value)) return value;
67
- if (visited.has(value)) return visited.get(value);
68
- const next = {};
69
- visited.set(value, next);
70
- for (const key of getOwnEnumerableKeys(value)) {
71
- if (isUnsafeKey(key)) continue;
72
- const child = value[key];
73
- if (typeof child !== "function") next[key] = toSnapshot(child, visited);
74
- }
75
- return next;
76
- }
77
- return value;
78
- };
79
- const snapshotPureState = (store) => toSnapshot(store.getPureState());
80
- const isEqualSnapshot = (left, right, visited = /* @__PURE__ */ new WeakMap()) => {
81
- if (Object.is(left, right)) return true;
82
- if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
83
- const leftIsArray = Array.isArray(left);
84
- const rightIsArray = Array.isArray(right);
85
- if (leftIsArray || rightIsArray) {
86
- if (!leftIsArray || !rightIsArray || left.length !== right.length) return false;
87
- } else if (!isObjectRecord(left) || !isObjectRecord(right)) return false;
88
- let seenTargets = visited.get(left);
89
- if (!seenTargets) {
90
- seenTargets = /* @__PURE__ */ new WeakSet();
91
- visited.set(left, seenTargets);
92
- } else if (seenTargets.has(right)) return true;
93
- seenTargets.add(right);
94
- const leftRecord = left;
95
- const rightRecord = right;
96
- const leftKeys = getOwnEnumerableKeys(left);
97
- const rightKeys = getOwnEnumerableKeys(right);
98
- if (leftKeys.length !== rightKeys.length) return false;
99
- for (const key of leftKeys) {
100
- if (!Object.prototype.hasOwnProperty.call(rightRecord, key)) return false;
101
- if (!isEqualSnapshot(leftRecord[key], rightRecord[key], visited)) return false;
102
- }
103
- return true;
104
- };
105
7
  const handleStore = (store, rawState, state, internal) => {
106
8
  if (!internal.toMutableRaw) {
107
9
  internal.toMutableRaw = (key) => instancesMap.get(key);
@@ -111,20 +13,20 @@ const handleStore = (store, rawState, state, internal) => {
111
13
  const restoreClientState = (snapshot) => {
112
14
  isApplyingCoactionState = true;
113
15
  try {
114
- replaceMutableState(internal.rootState ?? rawState, getMutableState(), store.getState(), snapshot);
16
+ replaceMutableAdapterState(internal.rootState ?? rawState, getMutableState(), store.getState(), snapshot);
115
17
  } finally {
116
- lastSnapshot = snapshotPureState(store);
18
+ lastSnapshot = snapshotMutableAdapterPureState(store);
117
19
  isApplyingCoactionState = false;
118
20
  }
119
21
  };
120
22
  const syncSharedExternalChange = () => {
121
- const currentSnapshot = snapshotPureState(store);
23
+ const currentSnapshot = snapshotMutableAdapterPureState(store);
122
24
  if (isApplyingCoactionState) {
123
25
  lastSnapshot = currentSnapshot;
124
26
  return "handled";
125
27
  }
126
28
  if (store.share === "client" && lastSnapshot) {
127
- if (!isEqualSnapshot(currentSnapshot, lastSnapshot)) restoreClientState(lastSnapshot);
29
+ if (!isEqualMutableAdapterSnapshot(currentSnapshot, lastSnapshot)) restoreClientState(lastSnapshot);
128
30
  return "ignored";
129
31
  }
130
32
  if (store.share === "main" && lastSnapshot) {
@@ -145,8 +47,8 @@ const handleStore = (store, rawState, state, internal) => {
145
47
  store._listeners = /* @__PURE__ */ new Set();
146
48
  let unsubscribeExternal;
147
49
  const cancelReadySubscription = onStoreReady(store, () => {
148
- replaceMutableState(internal.rootState ?? rawState, getMutableState(), store.getState(), sanitizeInitialStateValue(snapshotPureState(store)));
149
- lastSnapshot = snapshotPureState(store);
50
+ replaceMutableAdapterState(internal.rootState ?? rawState, getMutableState(), store.getState(), sanitizeInitialStateValue(snapshotMutableAdapterPureState(store)));
51
+ lastSnapshot = snapshotMutableAdapterPureState(store);
150
52
  unsubscribeExternal = subscribe(getMutableState(), () => {
151
53
  const change = syncSharedExternalChange();
152
54
  if (change === "ignored") return;
@@ -155,6 +57,7 @@ const handleStore = (store, rawState, state, internal) => {
155
57
  });
156
58
  });
157
59
  Object.assign(store, { subscribe: (listener) => {
60
+ internal.assertAlive?.("subscribe");
158
61
  store._listeners.add(listener);
159
62
  return () => {
160
63
  store._listeners?.delete(listener);
@@ -175,16 +78,17 @@ const handleStore = (store, rawState, state, internal) => {
175
78
  store._destroyers = void 0;
176
79
  baseDestroy();
177
80
  };
178
- store.apply = (state = store.getState(), patches) => {
81
+ store.apply = (state = store.getPureState(), patches) => {
82
+ internal.assertAlive?.("apply");
179
83
  isApplyingCoactionState = true;
180
84
  try {
181
85
  if (!patches) {
182
- replaceMutableState(internal.rootState ?? rawState, getMutableState(), store.getState(), state);
86
+ replaceMutableAdapterState(internal.rootState ?? rawState, getMutableState(), store.getState(), state);
183
87
  return;
184
88
  }
185
- apply(state, patches);
89
+ applyMutableAdapterPatches(state, patches, internal.rootState ?? rawState, getMutableState(), store.getState());
186
90
  } finally {
187
- lastSnapshot = snapshotPureState(store);
91
+ lastSnapshot = snapshotMutableAdapterPureState(store);
188
92
  isApplyingCoactionState = false;
189
93
  internal.notifyStateChange?.();
190
94
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coaction/valtio",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "A Coaction integration tool for Valtio",
5
5
  "keywords": [
6
6
  "coaction",
@@ -28,9 +28,14 @@
28
28
  "types": "dist/index.d.ts",
29
29
  "exports": {
30
30
  ".": {
31
- "types": "./dist/index.d.ts",
32
- "import": "./dist/index.mjs",
33
- "require": "./dist/index.js",
31
+ "import": {
32
+ "types": "./dist/index.d.mts",
33
+ "default": "./dist/index.mjs"
34
+ },
35
+ "require": {
36
+ "types": "./dist/index.d.ts",
37
+ "default": "./dist/index.js"
38
+ },
34
39
  "default": "./dist/index.mjs"
35
40
  },
36
41
  "./package.json": "./package.json"
@@ -43,12 +48,13 @@
43
48
  "mutability": "^1.2.1"
44
49
  },
45
50
  "devDependencies": {
51
+ "data-transport": "^5.0.3",
46
52
  "mutative": "^1.3.0",
47
53
  "valtio": "^2.3.1",
48
- "coaction": "2.0.0"
54
+ "coaction": "2.1.0"
49
55
  },
50
56
  "peerDependencies": {
51
- "coaction": "^2.0.0",
57
+ "coaction": ">=2.1.0 <3",
52
58
  "valtio": "^2.0.0"
53
59
  },
54
60
  "authors": [