@buoy-gg/jotai 7.0.16 → 7.0.17

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.
@@ -93,6 +93,7 @@ Object.defineProperty(exports, "watchDefaultStoreAtoms", {
93
93
  return _watchAtoms.watchDefaultStoreAtoms;
94
94
  }
95
95
  });
96
+ require("./jotai/utils/snapshotProvider");
96
97
  var _preset = require("./preset");
97
98
  var _watchAtoms = require("./jotai/utils/watchAtoms");
98
99
  var _useJotaiAtomChanges = require("./jotai/hooks/useJotaiAtomChanges");
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+
3
+ var _sharedUi = require("@buoy-gg/shared-ui");
4
+ var _jotaiStateStore = require("./jotaiStateStore");
5
+ /**
6
+ * Time Machine snapshot provider for Jotai.
7
+ *
8
+ * Registered into @buoy-gg/shared-ui's stateSnapshotRegistry at module init;
9
+ * consumed by @buoy-gg/time-machine.
10
+ *
11
+ * Coverage is opt-in by nature: only atoms the app passed to `watchAtoms` /
12
+ * `watchDefaultStoreAtoms` are visible. Derived (read-only) atoms are captured
13
+ * for inspection but never restored — they recompute from their sources.
14
+ * Caveat (documented): atoms with custom write functions (`atomWithReducer`)
15
+ * receive ACTIONS through `store.set`, so restoring a raw value can misbehave;
16
+ * nothing in the registry distinguishes them from plain atoms.
17
+ */
18
+
19
+ function status() {
20
+ const atoms = _jotaiStateStore.jotaiStateStore.getAtoms();
21
+ if (atoms.length === 0) {
22
+ return {
23
+ canCapture: false,
24
+ canRestore: false,
25
+ detail: "No Jotai atoms registered — pass your atoms to watchAtoms() / watchDefaultStoreAtoms()"
26
+ };
27
+ }
28
+ const writable = atoms.filter(a => a.setValue).length;
29
+ return {
30
+ canCapture: true,
31
+ canRestore: writable > 0,
32
+ detail: writable < atoms.length ? `${atoms.length - writable} derived atom(s) recompute automatically and are not restored` : undefined
33
+ };
34
+ }
35
+ async function capture() {
36
+ const warnings = [];
37
+ const atoms = {};
38
+ let derived = 0;
39
+ for (const info of _jotaiStateStore.jotaiStateStore.getAtoms()) {
40
+ try {
41
+ const value = info.getValue();
42
+ if (typeof value === "function") {
43
+ warnings.push(`atom "${info.label}": function value not capturable`);
44
+ continue;
45
+ }
46
+ if (!info.setValue) derived += 1;
47
+ atoms[info.label] = {
48
+ value,
49
+ writable: Boolean(info.setValue)
50
+ };
51
+ } catch (e) {
52
+ warnings.push(`atom "${info.label}": capture failed (${String(e)})`);
53
+ }
54
+ }
55
+ if (derived > 0) {
56
+ warnings.push(`${derived} derived atom(s) captured for inspection only (recompute on restore)`);
57
+ }
58
+ return {
59
+ data: {
60
+ atoms
61
+ },
62
+ warnings
63
+ };
64
+ }
65
+ async function restore(data) {
66
+ const snapshot = data;
67
+ const result = {
68
+ ok: true,
69
+ applied: 0,
70
+ skipped: [],
71
+ warnings: []
72
+ };
73
+ if (!snapshot?.atoms) {
74
+ return {
75
+ ok: false,
76
+ applied: 0,
77
+ skipped: [],
78
+ warnings: ["empty jotai snapshot"]
79
+ };
80
+ }
81
+ let derived = 0;
82
+ for (const [label, entry] of Object.entries(snapshot.atoms)) {
83
+ if (!entry.writable) {
84
+ derived += 1;
85
+ continue;
86
+ }
87
+ const info = _jotaiStateStore.jotaiStateStore.getAtom(label);
88
+ if (!info) {
89
+ result.skipped.push({
90
+ id: label,
91
+ reason: "atom not registered (renamed, or unwatched since snapshot?)"
92
+ });
93
+ continue;
94
+ }
95
+ if (!info.setValue) {
96
+ result.skipped.push({
97
+ id: label,
98
+ reason: "atom is now read-only (derived)"
99
+ });
100
+ continue;
101
+ }
102
+ try {
103
+ info.setValue(entry.value);
104
+ result.applied += 1;
105
+ } catch (e) {
106
+ result.skipped.push({
107
+ id: label,
108
+ reason: String(e)
109
+ });
110
+ result.ok = false;
111
+ }
112
+ }
113
+ if (derived > 0) {
114
+ result.warnings.push(`${derived} derived atom(s) left to recompute`);
115
+ }
116
+ return result;
117
+ }
118
+ (0, _sharedUi.registerStateSnapshotProvider)({
119
+ id: "jotai",
120
+ label: "Jotai",
121
+ status,
122
+ capture,
123
+ restore
124
+ });
@@ -61,9 +61,11 @@ function watchAtoms(store, atoms, options) {
61
61
  }
62
62
 
63
63
  // Register the atom for the browser view. A setter is captured only when
64
- // the store supports `set` (writable atoms); read-only/derived atoms throw
65
- // at set time and are reported as read-only.
66
- const setter = store.set ? value => {
64
+ // the store supports `set` AND the atom itself is writable (has a `write`
65
+ // function — primitive atoms get a default one, read-only derived atoms
66
+ // have none). Deriveds used to get a setter that threw inside jotai at
67
+ // set time; now they're correctly reported as read-only up front.
68
+ const setter = store.set && typeof atom.write === "function" ? value => {
67
69
  store.set(atom, value);
68
70
  } : undefined;
69
71
  _jotaiStateStore.jotaiStateStore.registerAtom(label, () => {
@@ -32,6 +32,9 @@
32
32
  * ```
33
33
  */
34
34
 
35
+ // Side-effect: registers the Time Machine snapshot provider
36
+ import "./jotai/utils/snapshotProvider";
37
+
35
38
  // =============================================================================
36
39
  // PRESET (Primary entry point for FloatingDevTools)
37
40
  // =============================================================================
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Time Machine snapshot provider for Jotai.
5
+ *
6
+ * Registered into @buoy-gg/shared-ui's stateSnapshotRegistry at module init;
7
+ * consumed by @buoy-gg/time-machine.
8
+ *
9
+ * Coverage is opt-in by nature: only atoms the app passed to `watchAtoms` /
10
+ * `watchDefaultStoreAtoms` are visible. Derived (read-only) atoms are captured
11
+ * for inspection but never restored — they recompute from their sources.
12
+ * Caveat (documented): atoms with custom write functions (`atomWithReducer`)
13
+ * receive ACTIONS through `store.set`, so restoring a raw value can misbehave;
14
+ * nothing in the registry distinguishes them from plain atoms.
15
+ */
16
+ import { registerStateSnapshotProvider } from "@buoy-gg/shared-ui";
17
+ import { jotaiStateStore } from "./jotaiStateStore";
18
+ function status() {
19
+ const atoms = jotaiStateStore.getAtoms();
20
+ if (atoms.length === 0) {
21
+ return {
22
+ canCapture: false,
23
+ canRestore: false,
24
+ detail: "No Jotai atoms registered — pass your atoms to watchAtoms() / watchDefaultStoreAtoms()"
25
+ };
26
+ }
27
+ const writable = atoms.filter(a => a.setValue).length;
28
+ return {
29
+ canCapture: true,
30
+ canRestore: writable > 0,
31
+ detail: writable < atoms.length ? `${atoms.length - writable} derived atom(s) recompute automatically and are not restored` : undefined
32
+ };
33
+ }
34
+ async function capture() {
35
+ const warnings = [];
36
+ const atoms = {};
37
+ let derived = 0;
38
+ for (const info of jotaiStateStore.getAtoms()) {
39
+ try {
40
+ const value = info.getValue();
41
+ if (typeof value === "function") {
42
+ warnings.push(`atom "${info.label}": function value not capturable`);
43
+ continue;
44
+ }
45
+ if (!info.setValue) derived += 1;
46
+ atoms[info.label] = {
47
+ value,
48
+ writable: Boolean(info.setValue)
49
+ };
50
+ } catch (e) {
51
+ warnings.push(`atom "${info.label}": capture failed (${String(e)})`);
52
+ }
53
+ }
54
+ if (derived > 0) {
55
+ warnings.push(`${derived} derived atom(s) captured for inspection only (recompute on restore)`);
56
+ }
57
+ return {
58
+ data: {
59
+ atoms
60
+ },
61
+ warnings
62
+ };
63
+ }
64
+ async function restore(data) {
65
+ const snapshot = data;
66
+ const result = {
67
+ ok: true,
68
+ applied: 0,
69
+ skipped: [],
70
+ warnings: []
71
+ };
72
+ if (!snapshot?.atoms) {
73
+ return {
74
+ ok: false,
75
+ applied: 0,
76
+ skipped: [],
77
+ warnings: ["empty jotai snapshot"]
78
+ };
79
+ }
80
+ let derived = 0;
81
+ for (const [label, entry] of Object.entries(snapshot.atoms)) {
82
+ if (!entry.writable) {
83
+ derived += 1;
84
+ continue;
85
+ }
86
+ const info = jotaiStateStore.getAtom(label);
87
+ if (!info) {
88
+ result.skipped.push({
89
+ id: label,
90
+ reason: "atom not registered (renamed, or unwatched since snapshot?)"
91
+ });
92
+ continue;
93
+ }
94
+ if (!info.setValue) {
95
+ result.skipped.push({
96
+ id: label,
97
+ reason: "atom is now read-only (derived)"
98
+ });
99
+ continue;
100
+ }
101
+ try {
102
+ info.setValue(entry.value);
103
+ result.applied += 1;
104
+ } catch (e) {
105
+ result.skipped.push({
106
+ id: label,
107
+ reason: String(e)
108
+ });
109
+ result.ok = false;
110
+ }
111
+ }
112
+ if (derived > 0) {
113
+ result.warnings.push(`${derived} derived atom(s) left to recompute`);
114
+ }
115
+ return result;
116
+ }
117
+ registerStateSnapshotProvider({
118
+ id: "jotai",
119
+ label: "Jotai",
120
+ status,
121
+ capture,
122
+ restore
123
+ });
@@ -56,9 +56,11 @@ export function watchAtoms(store, atoms, options) {
56
56
  }
57
57
 
58
58
  // Register the atom for the browser view. A setter is captured only when
59
- // the store supports `set` (writable atoms); read-only/derived atoms throw
60
- // at set time and are reported as read-only.
61
- const setter = store.set ? value => {
59
+ // the store supports `set` AND the atom itself is writable (has a `write`
60
+ // function — primitive atoms get a default one, read-only derived atoms
61
+ // have none). Deriveds used to get a setter that threw inside jotai at
62
+ // set time; now they're correctly reported as read-only up front.
63
+ const setter = store.set && typeof atom.write === "function" ? value => {
62
64
  store.set(atom, value);
63
65
  } : undefined;
64
66
  jotaiStateStore.registerAtom(label, () => {
@@ -29,6 +29,7 @@
29
29
  * watchAtoms(myStore, { countAtom, authAtom });
30
30
  * ```
31
31
  */
32
+ import "./jotai/utils/snapshotProvider";
32
33
  export { jotaiToolPreset, createJotaiTool } from "./preset";
33
34
  export { watchAtoms } from "./jotai/utils/watchAtoms";
34
35
  export { watchDefaultStoreAtoms } from "./jotai/utils/watchAtoms";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAKH,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAK5D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAKtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAKlE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAK9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,YAAY,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAOnF,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EACL,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAK3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,YAAY,EACV,eAAe,EACf,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAKvB,gBAAgB;AAChB,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,gCAAgC,CAAC;AAKxC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAK5D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAKtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAKlE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAK9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,YAAY,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAOnF,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EACL,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAK3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,YAAY,EACV,eAAe,EACf,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAKvB,gBAAgB;AAChB,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=snapshotProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshotProvider.d.ts","sourceRoot":"","sources":["../../../../src/jotai/utils/snapshotProvider.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"watchAtoms.d.ts","sourceRoot":"","sources":["../../../../src/jotai/utils/watchAtoms.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,+DAA+D;AAC/D,KAAK,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;AAE7B,mFAAmF;AACnF,UAAU,aAAa;IACrB,GAAG,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;IACzC,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IACzD,mFAAmF;IACnF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;CACtD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,IAAI,CAwEZ;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,IAAI,CA2BZ;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,YAAY,EAAE,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"watchAtoms.d.ts","sourceRoot":"","sources":["../../../../src/jotai/utils/watchAtoms.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAElC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAElD,+DAA+D;AAC/D,KAAK,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;AAE7B,mFAAmF;AACnF,UAAU,aAAa;IACrB,GAAG,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;IACzC,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IACzD,mFAAmF;IACnF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;CACtD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,IAAI,CA2EZ;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,MAAM,IAAI,CA2BZ;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,YAAY,EAAE,aAAa,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-gg/jotai",
3
- "version": "7.0.16",
3
+ "version": "7.0.17",
4
4
  "description": "Jotai devtools inside your React Native app — every atom write shows prev → next, with per-atom history & live values. Part of Buoy devtools.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -24,10 +24,13 @@
24
24
  "files": [
25
25
  "lib"
26
26
  ],
27
- "sideEffects": false,
27
+ "sideEffects": [
28
+ "**/snapshotProvider.js",
29
+ "**/snapshotProvider.ts"
30
+ ],
28
31
  "dependencies": {
29
- "@buoy-gg/shared-ui": "^7.0.16",
30
- "@buoy-gg/license": "^7.0.16"
32
+ "@buoy-gg/license": "^7.0.17",
33
+ "@buoy-gg/shared-ui": "^7.0.17"
31
34
  },
32
35
  "peerDependencies": {
33
36
  "jotai": ">=2.0.0",