atom.io 0.21.0 → 0.22.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.
Files changed (99) hide show
  1. package/data/dist/index.cjs +139 -66
  2. package/data/dist/index.d.ts +6 -0
  3. package/data/dist/index.js +3 -3
  4. package/data/src/join.ts +135 -56
  5. package/data/src/struct-family.ts +2 -2
  6. package/dist/{chunk-RT43TVKP.js → chunk-GVHKIJ3G.js} +1 -1
  7. package/dist/{chunk-KGZGBCYS.js → chunk-JA4V7TJY.js} +135 -62
  8. package/dist/index.cjs +2 -7
  9. package/dist/index.d.ts +29 -14
  10. package/dist/index.js +4 -8
  11. package/ephemeral/dist/index.cjs +11 -0
  12. package/ephemeral/dist/index.js +9 -0
  13. package/ephemeral/package.json +16 -0
  14. package/ephemeral/src/index.ts +1 -0
  15. package/eslint-plugin/dist/index.cjs +156 -1
  16. package/eslint-plugin/dist/index.js +156 -1
  17. package/eslint-plugin/src/rules/index.ts +1 -0
  18. package/eslint-plugin/src/rules/lifespan.ts +204 -0
  19. package/eslint-plugin/src/rules/synchronous-selector-dependencies.ts +1 -65
  20. package/eslint-plugin/src/walk.ts +73 -0
  21. package/immortal/dist/index.cjs +100 -0
  22. package/immortal/dist/index.js +97 -0
  23. package/immortal/package.json +16 -0
  24. package/immortal/src/index.ts +2 -0
  25. package/immortal/src/molecule.ts +134 -0
  26. package/immortal/src/seek-state.ts +60 -0
  27. package/internal/dist/index.cjs +211 -194
  28. package/internal/dist/index.d.ts +30 -14
  29. package/internal/dist/index.js +210 -194
  30. package/internal/src/atom/dispose-atom.ts +4 -1
  31. package/internal/src/families/create-readonly-selector-family.ts +9 -9
  32. package/internal/src/families/create-regular-atom-family.ts +15 -20
  33. package/internal/src/families/create-writable-selector-family.ts +6 -7
  34. package/internal/src/families/find-in-store.ts +11 -5
  35. package/internal/src/families/index.ts +2 -0
  36. package/internal/src/families/init-family-member.ts +91 -0
  37. package/internal/src/families/seek-in-store.ts +106 -0
  38. package/internal/src/future.ts +6 -20
  39. package/internal/src/get-state/get-from-store.ts +2 -3
  40. package/internal/src/mutable/create-mutable-atom-family.ts +17 -23
  41. package/internal/src/mutable/create-mutable-atom.ts +3 -1
  42. package/internal/src/mutable/get-json-family.ts +2 -2
  43. package/internal/src/mutable/get-json-token.ts +27 -12
  44. package/internal/src/mutable/tracker-family.ts +14 -12
  45. package/internal/src/mutable/tracker.ts +2 -24
  46. package/internal/src/not-found-error.ts +11 -3
  47. package/internal/src/operation.ts +0 -1
  48. package/internal/src/selector/create-readonly-selector.ts +2 -2
  49. package/internal/src/selector/create-writable-selector.ts +2 -2
  50. package/internal/src/selector/dispose-selector.ts +40 -23
  51. package/internal/src/selector/register-selector.ts +8 -5
  52. package/internal/src/set-state/set-into-store.ts +2 -2
  53. package/internal/src/store/index.ts +0 -1
  54. package/internal/src/store/store.ts +18 -5
  55. package/internal/src/subscribe/recall-state.ts +3 -3
  56. package/internal/src/subscribe/subscribe-to-state.ts +18 -5
  57. package/internal/src/transaction/build-transaction.ts +7 -2
  58. package/introspection/dist/index.cjs +39 -65
  59. package/introspection/dist/index.js +39 -65
  60. package/introspection/src/attach-atom-index.ts +38 -48
  61. package/introspection/src/attach-introspection-states.ts +0 -1
  62. package/introspection/src/attach-selector-index.ts +45 -50
  63. package/introspection/src/attach-timeline-family.ts +2 -17
  64. package/json/dist/index.cjs +38 -4
  65. package/json/dist/index.js +40 -6
  66. package/json/src/select-json-family.ts +46 -7
  67. package/package.json +31 -11
  68. package/react/dist/index.cjs +1 -1
  69. package/react/dist/index.js +1 -1
  70. package/react/src/use-json.ts +1 -1
  71. package/react-devtools/dist/index.cjs +11 -10
  72. package/react-devtools/dist/index.js +2 -1
  73. package/react-devtools/src/StateIndex.tsx +2 -1
  74. package/react-devtools/src/TimelineIndex.tsx +2 -1
  75. package/react-devtools/src/TransactionIndex.tsx +7 -7
  76. package/realtime-client/dist/index.cjs +3 -3
  77. package/realtime-client/dist/index.js +3 -3
  78. package/realtime-client/src/pull-mutable-atom-family-member.ts +1 -1
  79. package/realtime-client/src/pull-mutable-atom.ts +1 -1
  80. package/realtime-client/src/sync-continuity.ts +1 -2
  81. package/realtime-react/dist/index.cjs +1 -1
  82. package/realtime-react/dist/index.js +1 -1
  83. package/realtime-server/dist/index.cjs +18 -17
  84. package/realtime-server/dist/index.js +7 -6
  85. package/realtime-server/src/realtime-continuity-synchronizer.ts +5 -3
  86. package/realtime-server/src/realtime-mutable-family-provider.ts +2 -1
  87. package/realtime-server/src/realtime-mutable-provider.ts +1 -1
  88. package/realtime-testing/dist/index.cjs +6 -2
  89. package/realtime-testing/dist/index.js +8 -5
  90. package/realtime-testing/src/setup-realtime-test.tsx +5 -2
  91. package/src/atom.ts +10 -4
  92. package/src/index.ts +1 -2
  93. package/src/selector.ts +10 -4
  94. package/src/silo.ts +3 -3
  95. package/src/transaction.ts +5 -2
  96. package/src/validators.ts +0 -6
  97. package/internal/src/store/withdraw-new-family-member.ts +0 -69
  98. /package/{src → ephemeral/src}/find-state.ts +0 -0
  99. /package/src/{dispose.ts → dispose-state.ts} +0 -0
@@ -31,55 +31,45 @@ var attachAtomIndex = (store = IMPLICIT.STORE) => {
31
31
  },
32
32
  effects: [
33
33
  ({ setSelf }) => {
34
- const unsubscribeFromAtomCreation = store.on.atomCreation.subscribe(
35
- `introspection`,
36
- (atomToken) => {
37
- if (atomToken.key.includes(`\u{1F441}\u200D\u{1F5E8}`)) {
38
- return;
39
- }
40
- setSelf((self) => {
41
- if (atomToken.family) {
42
- const { key: familyKey, subKey } = atomToken.family;
43
- let familyNode = self.get(familyKey);
44
- if (familyNode === void 0 || !(`familyMembers` in familyNode)) {
45
- familyNode = {
46
- key: familyKey,
47
- familyMembers: /* @__PURE__ */ new Map()
48
- };
49
- self.set(familyKey, familyNode);
50
- }
51
- familyNode.familyMembers.set(subKey, atomToken);
52
- } else {
53
- self.set(atomToken.key, atomToken);
54
- }
55
- return self;
56
- });
34
+ store.on.atomCreation.subscribe(`introspection`, (atomToken) => {
35
+ if (atomToken.key.includes(`\u{1F441}\u200D\u{1F5E8}`)) {
36
+ return;
57
37
  }
58
- );
59
- const unsubscribeFromAtomDisposal = store.on.atomDisposal.subscribe(
60
- `introspection`,
61
- (atomToken) => {
62
- setSelf((self) => {
63
- if (atomToken.family) {
64
- const { key: familyKey, subKey } = atomToken.family;
65
- const familyNode = self.get(familyKey);
66
- if (familyNode && `familyMembers` in familyNode) {
67
- familyNode.familyMembers.delete(subKey);
68
- if (familyNode.familyMembers.size === 0) {
69
- self.delete(familyKey);
70
- }
38
+ setSelf((self) => {
39
+ if (atomToken.family) {
40
+ const { key: familyKey, subKey } = atomToken.family;
41
+ let familyNode = self.get(familyKey);
42
+ if (familyNode === void 0 || !(`familyMembers` in familyNode)) {
43
+ familyNode = {
44
+ key: familyKey,
45
+ familyMembers: /* @__PURE__ */ new Map()
46
+ };
47
+ self.set(familyKey, familyNode);
48
+ }
49
+ familyNode.familyMembers.set(subKey, atomToken);
50
+ } else {
51
+ self.set(atomToken.key, atomToken);
52
+ }
53
+ return self;
54
+ });
55
+ });
56
+ store.on.atomDisposal.subscribe(`introspection`, (atomToken) => {
57
+ setSelf((self) => {
58
+ if (atomToken.family) {
59
+ const { key: familyKey, subKey } = atomToken.family;
60
+ const familyNode = self.get(familyKey);
61
+ if (familyNode && `familyMembers` in familyNode) {
62
+ familyNode.familyMembers.delete(subKey);
63
+ if (familyNode.familyMembers.size === 0) {
64
+ self.delete(familyKey);
71
65
  }
72
- } else {
73
- self.delete(atomToken.key);
74
66
  }
75
- return self;
76
- });
77
- }
78
- );
79
- return () => {
80
- unsubscribeFromAtomCreation();
81
- unsubscribeFromAtomDisposal();
82
- };
67
+ } else {
68
+ self.delete(atomToken.key);
69
+ }
70
+ return self;
71
+ });
72
+ });
83
73
  }
84
74
  ]
85
75
  },
@@ -124,7 +114,7 @@ var attachSelectorIndex = (store = IMPLICIT.STORE) => {
124
114
  },
125
115
  effects: [
126
116
  ({ setSelf }) => {
127
- const unsubscribeFromSelectorCreation = store.on.selectorCreation.subscribe(
117
+ store.on.selectorCreation.subscribe(
128
118
  `introspection`,
129
119
  (selectorToken) => {
130
120
  if (selectorToken.key.includes(`\u{1F441}\u200D\u{1F5E8}`)) {
@@ -149,7 +139,7 @@ var attachSelectorIndex = (store = IMPLICIT.STORE) => {
149
139
  });
150
140
  }
151
141
  );
152
- const unsubscribeFromSelectorDisposal = store.on.selectorDisposal.subscribe(
142
+ store.on.selectorDisposal.subscribe(
153
143
  `introspection`,
154
144
  (selectorToken) => {
155
145
  setSelf((self) => {
@@ -169,10 +159,6 @@ var attachSelectorIndex = (store = IMPLICIT.STORE) => {
169
159
  });
170
160
  }
171
161
  );
172
- return () => {
173
- unsubscribeFromSelectorCreation();
174
- unsubscribeFromSelectorDisposal();
175
- };
176
162
  }
177
163
  ]
178
164
  },
@@ -210,19 +196,7 @@ var attachTimelineFamily = (store = IMPLICIT.STORE) => {
210
196
  ({ setSelf }) => {
211
197
  const tl = store.timelines.get(key);
212
198
  tl == null ? void 0 : tl.subject.subscribe(`introspection`, (_) => {
213
- if (store.operation.open === true) {
214
- const unsubscribe = store.on.operationClose.subscribe(
215
- `introspection`,
216
- (operationClose) => {
217
- if (operationClose.open === false) {
218
- unsubscribe();
219
- setSelf(__spreadValues({}, tl));
220
- }
221
- }
222
- );
223
- } else {
224
- setSelf(__spreadValues({}, tl));
225
- }
199
+ setSelf(__spreadValues({}, tl));
226
200
  });
227
201
  }
228
202
  ]
@@ -41,59 +41,49 @@ export const attachAtomIndex = (
41
41
  },
42
42
  effects: [
43
43
  ({ setSelf }) => {
44
- const unsubscribeFromAtomCreation = store.on.atomCreation.subscribe(
45
- `introspection`,
46
- (atomToken) => {
47
- if (atomToken.key.includes(`👁‍🗨`)) {
48
- return
49
- }
44
+ store.on.atomCreation.subscribe(`introspection`, (atomToken) => {
45
+ if (atomToken.key.includes(`👁‍🗨`)) {
46
+ return
47
+ }
50
48
 
51
- setSelf((self) => {
52
- if (atomToken.family) {
53
- const { key: familyKey, subKey } = atomToken.family
54
- let familyNode = self.get(familyKey)
55
- if (
56
- familyNode === undefined ||
57
- !(`familyMembers` in familyNode)
58
- ) {
59
- familyNode = {
60
- key: familyKey,
61
- familyMembers: new Map(),
62
- }
63
- self.set(familyKey, familyNode)
49
+ setSelf((self) => {
50
+ if (atomToken.family) {
51
+ const { key: familyKey, subKey } = atomToken.family
52
+ let familyNode = self.get(familyKey)
53
+ if (
54
+ familyNode === undefined ||
55
+ !(`familyMembers` in familyNode)
56
+ ) {
57
+ familyNode = {
58
+ key: familyKey,
59
+ familyMembers: new Map(),
64
60
  }
65
- familyNode.familyMembers.set(subKey, atomToken)
66
- } else {
67
- self.set(atomToken.key, atomToken)
61
+ self.set(familyKey, familyNode)
68
62
  }
69
- return self
70
- })
71
- },
72
- )
73
- const unsubscribeFromAtomDisposal = store.on.atomDisposal.subscribe(
74
- `introspection`,
75
- (atomToken) => {
76
- setSelf((self) => {
77
- if (atomToken.family) {
78
- const { key: familyKey, subKey } = atomToken.family
79
- const familyNode = self.get(familyKey)
80
- if (familyNode && `familyMembers` in familyNode) {
81
- familyNode.familyMembers.delete(subKey)
82
- if (familyNode.familyMembers.size === 0) {
83
- self.delete(familyKey)
84
- }
63
+ familyNode.familyMembers.set(subKey, atomToken)
64
+ } else {
65
+ self.set(atomToken.key, atomToken)
66
+ }
67
+ return self
68
+ })
69
+ })
70
+ store.on.atomDisposal.subscribe(`introspection`, (atomToken) => {
71
+ setSelf((self) => {
72
+ if (atomToken.family) {
73
+ const { key: familyKey, subKey } = atomToken.family
74
+ const familyNode = self.get(familyKey)
75
+ if (familyNode && `familyMembers` in familyNode) {
76
+ familyNode.familyMembers.delete(subKey)
77
+ if (familyNode.familyMembers.size === 0) {
78
+ self.delete(familyKey)
85
79
  }
86
- } else {
87
- self.delete(atomToken.key)
88
80
  }
89
- return self
90
- })
91
- },
92
- )
93
- return () => {
94
- unsubscribeFromAtomCreation()
95
- unsubscribeFromAtomDisposal()
96
- }
81
+ } else {
82
+ self.delete(atomToken.key)
83
+ }
84
+ return self
85
+ })
86
+ })
97
87
  },
98
88
  ],
99
89
  },
@@ -1,6 +1,5 @@
1
1
  import type {
2
2
  Func,
3
- ReadonlySelectorFamily,
4
3
  ReadonlySelectorFamilyToken,
5
4
  ReadonlySelectorToken,
6
5
  TimelineToken,
@@ -44,61 +44,56 @@ export const attachSelectorIndex = (
44
44
  },
45
45
  effects: [
46
46
  ({ setSelf }) => {
47
- const unsubscribeFromSelectorCreation =
48
- store.on.selectorCreation.subscribe(
49
- `introspection`,
50
- (selectorToken) => {
51
- if (selectorToken.key.includes(`👁‍🗨`)) {
52
- return
53
- }
47
+ store.on.selectorCreation.subscribe(
48
+ `introspection`,
49
+ (selectorToken) => {
50
+ if (selectorToken.key.includes(`👁‍🗨`)) {
51
+ return
52
+ }
54
53
 
55
- setSelf((self) => {
56
- if (selectorToken.family) {
57
- const { key: familyKey, subKey } = selectorToken.family
58
- let familyNode = self.get(familyKey)
59
- if (
60
- familyNode === undefined ||
61
- !(`familyMembers` in familyNode)
62
- ) {
63
- familyNode = {
64
- key: familyKey,
65
- familyMembers: new Map(),
66
- }
67
- self.set(familyKey, familyNode)
54
+ setSelf((self) => {
55
+ if (selectorToken.family) {
56
+ const { key: familyKey, subKey } = selectorToken.family
57
+ let familyNode = self.get(familyKey)
58
+ if (
59
+ familyNode === undefined ||
60
+ !(`familyMembers` in familyNode)
61
+ ) {
62
+ familyNode = {
63
+ key: familyKey,
64
+ familyMembers: new Map(),
68
65
  }
69
- familyNode.familyMembers.set(subKey, selectorToken)
70
- } else {
71
- self.set(selectorToken.key, selectorToken)
66
+ self.set(familyKey, familyNode)
72
67
  }
73
- return self
74
- })
75
- },
76
- )
77
- const unsubscribeFromSelectorDisposal =
78
- store.on.selectorDisposal.subscribe(
79
- `introspection`,
80
- (selectorToken) => {
81
- setSelf((self) => {
82
- if (selectorToken.family) {
83
- const { key: familyKey, subKey } = selectorToken.family
84
- const familyNode = self.get(familyKey)
85
- if (familyNode && `familyMembers` in familyNode) {
86
- familyNode.familyMembers.delete(subKey)
87
- if (familyNode.familyMembers.size === 0) {
88
- self.delete(familyKey)
89
- }
68
+ familyNode.familyMembers.set(subKey, selectorToken)
69
+ } else {
70
+ self.set(selectorToken.key, selectorToken)
71
+ }
72
+ return self
73
+ })
74
+ },
75
+ )
76
+
77
+ store.on.selectorDisposal.subscribe(
78
+ `introspection`,
79
+ (selectorToken) => {
80
+ setSelf((self) => {
81
+ if (selectorToken.family) {
82
+ const { key: familyKey, subKey } = selectorToken.family
83
+ const familyNode = self.get(familyKey)
84
+ if (familyNode && `familyMembers` in familyNode) {
85
+ familyNode.familyMembers.delete(subKey)
86
+ if (familyNode.familyMembers.size === 0) {
87
+ self.delete(familyKey)
90
88
  }
91
- } else {
92
- self.delete(selectorToken.key)
93
89
  }
94
- return self
95
- })
96
- },
97
- )
98
- return () => {
99
- unsubscribeFromSelectorCreation()
100
- unsubscribeFromSelectorDisposal()
101
- }
90
+ } else {
91
+ self.delete(selectorToken.key)
92
+ }
93
+ return self
94
+ })
95
+ },
96
+ )
102
97
  },
103
98
  ],
104
99
  },
@@ -1,7 +1,4 @@
1
- import type {
2
- ReadonlySelectorFamily,
3
- ReadonlySelectorFamilyToken,
4
- } from "atom.io"
1
+ import type { ReadonlySelectorFamilyToken } from "atom.io"
5
2
  import type { Store, Timeline } from "atom.io/internal"
6
3
  import {
7
4
  createRegularAtomFamily,
@@ -35,19 +32,7 @@ export const attachTimelineFamily = (
35
32
  ({ setSelf }) => {
36
33
  const tl = store.timelines.get(key)
37
34
  tl?.subject.subscribe(`introspection`, (_) => {
38
- if (store.operation.open === true) {
39
- const unsubscribe = store.on.operationClose.subscribe(
40
- `introspection`,
41
- (operationClose) => {
42
- if (operationClose.open === false) {
43
- unsubscribe()
44
- setSelf({ ...tl })
45
- }
46
- },
47
- )
48
- } else {
49
- setSelf({ ...tl })
50
- }
35
+ setSelf({ ...tl })
51
36
  })
52
37
  },
53
38
  ],
@@ -19,9 +19,43 @@ function selectJsonFamily(family, transform, store = internal.IMPLICIT.STORE) {
19
19
  const jsonFamily = internal.createSelectorFamily(
20
20
  {
21
21
  key: `${family.key}:JSON`,
22
- get: (key) => ({ get }) => transform.toJson(get(family(key))),
23
- set: (key) => ({ set }, newValue) => {
24
- set(family(key), transform.fromJson(newValue));
22
+ get: (key) => ({ seek, get }) => {
23
+ const existingState = seek(family, key);
24
+ if (existingState) {
25
+ return transform.toJson(get(existingState));
26
+ }
27
+ const stringKey = stringifyJson(key);
28
+ const molecule = store.molecules.get(stringKey);
29
+ if (molecule) {
30
+ const atom = molecule.bond(family);
31
+ return transform.toJson(get(atom));
32
+ }
33
+ if (store.config.lifespan === `immortal`) {
34
+ throw new Error(`No molecule found for key "${stringKey}"`);
35
+ }
36
+ const newToken = internal.initFamilyMember(family, key, store);
37
+ return transform.toJson(get(newToken));
38
+ },
39
+ set: (key) => ({ seek, set }, newValue) => {
40
+ const existingState = seek(family, key);
41
+ if (existingState) {
42
+ set(existingState, transform.fromJson(newValue));
43
+ } else {
44
+ const stringKey = stringifyJson(key);
45
+ const molecule = store.molecules.get(stringKey);
46
+ if (molecule) {
47
+ const atom = molecule.bond(family);
48
+ set(atom, transform.fromJson(newValue));
49
+ } else {
50
+ if (store.config.lifespan === `immortal`) {
51
+ throw new Error(`No molecule found for key "${stringKey}"`);
52
+ }
53
+ set(
54
+ internal.initFamilyMember(family, key, store),
55
+ transform.fromJson(newValue)
56
+ );
57
+ }
58
+ }
25
59
  }
26
60
  },
27
61
  store
@@ -30,7 +64,7 @@ function selectJsonFamily(family, transform, store = internal.IMPLICIT.STORE) {
30
64
  `store=${store.config.name}::json-selector-family`,
31
65
  (token) => {
32
66
  if (token.family) {
33
- jsonFamily(parseJson(token.family.subKey));
67
+ internal.seekInStore(jsonFamily, parseJson(token.family.subKey), store);
34
68
  }
35
69
  }
36
70
  );
@@ -1,7 +1,7 @@
1
- import { parseJson } from '../../dist/chunk-BF4MVQF6.js';
1
+ import { stringifyJson, parseJson } from '../../dist/chunk-BF4MVQF6.js';
2
2
  export { JSON_DEFAULTS, JSON_TYPE_NAMES, isBoolean, isNull, isNumber, isPrimitive, isString, parseJson, stringSetJsonInterface, stringifyJson } from '../../dist/chunk-BF4MVQF6.js';
3
3
  import '../../dist/chunk-F2X4B4VY.js';
4
- import { createStandaloneSelector, IMPLICIT, createSelectorFamily } from 'atom.io/internal';
4
+ import { createStandaloneSelector, IMPLICIT, createSelectorFamily, initFamilyMember, seekInStore } from 'atom.io/internal';
5
5
 
6
6
  var selectJson = (atom, transform, store = IMPLICIT.STORE) => {
7
7
  return createStandaloneSelector(
@@ -19,9 +19,43 @@ function selectJsonFamily(family, transform, store = IMPLICIT.STORE) {
19
19
  const jsonFamily = createSelectorFamily(
20
20
  {
21
21
  key: `${family.key}:JSON`,
22
- get: (key) => ({ get }) => transform.toJson(get(family(key))),
23
- set: (key) => ({ set }, newValue) => {
24
- set(family(key), transform.fromJson(newValue));
22
+ get: (key) => ({ seek, get }) => {
23
+ const existingState = seek(family, key);
24
+ if (existingState) {
25
+ return transform.toJson(get(existingState));
26
+ }
27
+ const stringKey = stringifyJson(key);
28
+ const molecule = store.molecules.get(stringKey);
29
+ if (molecule) {
30
+ const atom = molecule.bond(family);
31
+ return transform.toJson(get(atom));
32
+ }
33
+ if (store.config.lifespan === `immortal`) {
34
+ throw new Error(`No molecule found for key "${stringKey}"`);
35
+ }
36
+ const newToken = initFamilyMember(family, key, store);
37
+ return transform.toJson(get(newToken));
38
+ },
39
+ set: (key) => ({ seek, set }, newValue) => {
40
+ const existingState = seek(family, key);
41
+ if (existingState) {
42
+ set(existingState, transform.fromJson(newValue));
43
+ } else {
44
+ const stringKey = stringifyJson(key);
45
+ const molecule = store.molecules.get(stringKey);
46
+ if (molecule) {
47
+ const atom = molecule.bond(family);
48
+ set(atom, transform.fromJson(newValue));
49
+ } else {
50
+ if (store.config.lifespan === `immortal`) {
51
+ throw new Error(`No molecule found for key "${stringKey}"`);
52
+ }
53
+ set(
54
+ initFamilyMember(family, key, store),
55
+ transform.fromJson(newValue)
56
+ );
57
+ }
58
+ }
25
59
  }
26
60
  },
27
61
  store
@@ -30,7 +64,7 @@ function selectJsonFamily(family, transform, store = IMPLICIT.STORE) {
30
64
  `store=${store.config.name}::json-selector-family`,
31
65
  (token) => {
32
66
  if (token.family) {
33
- jsonFamily(parseJson(token.family.subKey));
67
+ seekInStore(jsonFamily, parseJson(token.family.subKey), store);
34
68
  }
35
69
  }
36
70
  );
@@ -1,9 +1,14 @@
1
1
  import type * as AtomIO from "atom.io"
2
2
  import type { Store, Transceiver } from "atom.io/internal"
3
- import { createSelectorFamily, IMPLICIT } from "atom.io/internal"
3
+ import {
4
+ createSelectorFamily,
5
+ IMPLICIT,
6
+ initFamilyMember,
7
+ seekInStore,
8
+ } from "atom.io/internal"
4
9
 
5
10
  import type { Json, JsonInterface } from "."
6
- import { parseJson } from "."
11
+ import { parseJson, stringifyJson } from "."
7
12
 
8
13
  export function selectJsonFamily<
9
14
  T extends Transceiver<any>,
@@ -39,12 +44,46 @@ export function selectJsonFamily<
39
44
  key: `${family.key}:JSON`,
40
45
  get:
41
46
  (key) =>
42
- ({ get }) =>
43
- transform.toJson(get(family(key))),
47
+ ({ seek, get }) => {
48
+ const existingState = seek(family, key)
49
+ if (existingState) {
50
+ return transform.toJson(get(existingState))
51
+ }
52
+ const stringKey = stringifyJson(key)
53
+ const molecule = store.molecules.get(stringKey)
54
+ if (molecule) {
55
+ const atom = molecule.bond(family)
56
+ return transform.toJson(get(atom))
57
+ }
58
+ if (store.config.lifespan === `immortal`) {
59
+ throw new Error(`No molecule found for key "${stringKey}"`)
60
+ }
61
+ const newToken = initFamilyMember(family, key, store)
62
+ return transform.toJson(get(newToken))
63
+ },
44
64
  set:
45
65
  (key) =>
46
- ({ set }, newValue) => {
47
- set(family(key), transform.fromJson(newValue))
66
+ ({ seek, set }, newValue) => {
67
+ // set(seek(family, key), transform.fromJson(newValue))
68
+ const existingState = seek(family, key)
69
+ if (existingState) {
70
+ set(existingState, transform.fromJson(newValue))
71
+ } else {
72
+ const stringKey = stringifyJson(key)
73
+ const molecule = store.molecules.get(stringKey)
74
+ if (molecule) {
75
+ const atom = molecule.bond(family)
76
+ set(atom, transform.fromJson(newValue))
77
+ } else {
78
+ if (store.config.lifespan === `immortal`) {
79
+ throw new Error(`No molecule found for key "${stringKey}"`)
80
+ }
81
+ set(
82
+ initFamilyMember(family, key, store),
83
+ transform.fromJson(newValue),
84
+ )
85
+ }
86
+ }
48
87
  },
49
88
  },
50
89
  store,
@@ -53,7 +92,7 @@ export function selectJsonFamily<
53
92
  `store=${store.config.name}::json-selector-family`,
54
93
  (token) => {
55
94
  if (token.family) {
56
- jsonFamily(parseJson(token.family.subKey) as K)
95
+ seekInStore(jsonFamily, parseJson(token.family.subKey) as K, store)
57
96
  }
58
97
  },
59
98
  )