@exodus/atoms 4.0.1 → 5.0.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 +0 -10
- package/package.json +2 -2
- package/src/enforce-rules.js +22 -17
- package/src/enhancers/block-until.js +1 -9
- package/src/enhancers/combine.js +1 -1
- package/src/enhancers/compute.js +6 -3
- package/src/enhancers/difference.js +13 -8
- package/src/enhancers/read-only.js +4 -3
- package/src/enhancers/swallow-observer-errors.js +4 -2
- package/src/enhancers/timeout-observers.js +4 -2
- package/src/enhancers/with-serialization.js +4 -0
- package/src/event-emitter.js +2 -1
- package/src/factories/memory.js +8 -1
- package/src/factories/remote-config.js +11 -2
- package/src/index.js +0 -2
- package/src/factories/fusion.js +0 -30
- package/src/factories/local-config.js +0 -19
package/README.md
CHANGED
|
@@ -22,7 +22,6 @@ This library provides helpers for creating atoms from multiple data sources we u
|
|
|
22
22
|
| ------------- | --- | ----- | ------- |
|
|
23
23
|
| Memory | ✅ | ✅ | ✅ |
|
|
24
24
|
| Storage | ✅ | 🟡 \* | ✅ |
|
|
25
|
-
| Fusion | ✅ | ✅ | ✅ |
|
|
26
25
|
| Remote config | ✅ | ❌ | ✅ |
|
|
27
26
|
| Local config | ✅ | ✅ | ✅ |
|
|
28
27
|
| Event emitter | ✅ | ❌ | ✅ |
|
|
@@ -35,7 +34,6 @@ This library provides helpers for creating atoms from multiple data sources we u
|
|
|
35
34
|
import {
|
|
36
35
|
createInMemoryAtom,
|
|
37
36
|
createStorageAtomFactory,
|
|
38
|
-
createFusionAtomFactory,
|
|
39
37
|
createRemoteConfigAtomFactory,
|
|
40
38
|
fromEventEmitter,
|
|
41
39
|
} from '@exodus/atoms'
|
|
@@ -54,14 +52,6 @@ const acceptedTermsAtom = storageAtomFactory({
|
|
|
54
52
|
isSoleWriter: true,
|
|
55
53
|
})
|
|
56
54
|
|
|
57
|
-
// Fusion atoms
|
|
58
|
-
const fusionAtomFactory = createFusionAtomFactory({ fusion })
|
|
59
|
-
|
|
60
|
-
const shareActivityAtom = createFusionAtom({
|
|
61
|
-
path: 'shareActivity',
|
|
62
|
-
defaultValue: true,
|
|
63
|
-
})
|
|
64
|
-
|
|
65
55
|
// Remote config atoms
|
|
66
56
|
const createRemoteConfigAtom = createRemoteConfigAtomFactory({ remoteConfig })
|
|
67
57
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/atoms",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"main": "src/index.js",
|
|
5
5
|
"author": "Exodus Movement Inc.",
|
|
6
6
|
"scripts": {
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"eslint": "^8.33.0",
|
|
35
35
|
"jest": "^29.1.2"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "f0a3d249bf994a6d5c106a106b5e4b2b6c61a6e8"
|
|
38
38
|
}
|
package/src/enforce-rules.js
CHANGED
|
@@ -5,22 +5,17 @@ const withChangeDetection = (listener) => {
|
|
|
5
5
|
let currentValue
|
|
6
6
|
let called = false
|
|
7
7
|
|
|
8
|
-
return {
|
|
9
|
-
|
|
10
|
-
if (called && value === currentValue) return
|
|
8
|
+
return async (value) => {
|
|
9
|
+
if (called && value === currentValue) return
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
called = true
|
|
12
|
+
currentValue = value
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
get called() {
|
|
18
|
-
return called
|
|
19
|
-
},
|
|
14
|
+
await listener(currentValue)
|
|
20
15
|
}
|
|
21
16
|
}
|
|
22
17
|
|
|
23
|
-
const enforceObservableRules = ({ defaultValue, logger, ...atom }) => {
|
|
18
|
+
const enforceObservableRules = ({ defaultValue, getInitialized = () => true, logger, ...atom }) => {
|
|
24
19
|
// ensure observers get called in series
|
|
25
20
|
const enqueue = makeConcurrent((fn) => fn(), { concurrency: 1 })
|
|
26
21
|
|
|
@@ -30,18 +25,28 @@ const enforceObservableRules = ({ defaultValue, logger, ...atom }) => {
|
|
|
30
25
|
const get = () => atom.get().then(postProcessValue)
|
|
31
26
|
|
|
32
27
|
const observe = (listener) => {
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
let called = false
|
|
29
|
+
listener = withChangeDetection(listener)
|
|
30
|
+
|
|
31
|
+
const publishSerially = (value) => {
|
|
32
|
+
called = true
|
|
33
|
+
return enqueue(() => listener(value))
|
|
34
|
+
}
|
|
35
|
+
|
|
35
36
|
// note: call observe() first to give it a chance to throw if it's not supported
|
|
36
|
-
const unsubscribe = atom.observe((value) => publishSerially(postProcessValue(value)))
|
|
37
37
|
// if the subscription already fired once, ignore first get
|
|
38
|
-
get().then((value) => !
|
|
39
|
-
return
|
|
38
|
+
get().then((value) => !called && publishSerially(value))
|
|
39
|
+
return atom.observe((value) => publishSerially(postProcessValue(value)))
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const set = async (value) => {
|
|
43
43
|
// support a function a la React's setState(oldState => newState)
|
|
44
|
-
if (typeof value === 'function')
|
|
44
|
+
if (typeof value === 'function') {
|
|
45
|
+
const current = getInitialized() ? await get() : defaultValue
|
|
46
|
+
value = await value(current)
|
|
47
|
+
|
|
48
|
+
if (current === value) return
|
|
49
|
+
}
|
|
45
50
|
|
|
46
51
|
await atom.set(value)
|
|
47
52
|
}
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import enforceObservableRules from '../enforce-rules'
|
|
2
|
-
|
|
3
1
|
export default function blockUntil({ atom, unblock }) {
|
|
4
2
|
const get = async () => unblock().then(atom.get)
|
|
5
3
|
|
|
6
|
-
|
|
4
|
+
return {
|
|
7
5
|
...atom,
|
|
8
6
|
get,
|
|
9
|
-
set: atom.set,
|
|
10
|
-
observe: atom.observe,
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
...rest,
|
|
15
7
|
observe: (callback) => {
|
|
16
8
|
let isSubscribed = true
|
|
17
9
|
let unsubscribe = () => {}
|
package/src/enhancers/combine.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import createCountdownLock from '../countdown-lock'
|
|
2
|
-
import enforceObservableRules from '../enforce-rules'
|
|
3
2
|
import createSimpleObserver from '../simple-observer'
|
|
3
|
+
import enforceObservableRules from '../enforce-rules'
|
|
4
4
|
|
|
5
5
|
const combine = (atoms) => {
|
|
6
6
|
const { notify, observe } = createSimpleObserver()
|
package/src/enhancers/compute.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import enforceObservableRules from '../enforce-rules'
|
|
2
|
-
|
|
3
1
|
const compute = ({ atom, selector }) => {
|
|
4
2
|
const get = async () => {
|
|
5
3
|
const values = await atom.get()
|
|
@@ -14,7 +12,12 @@ const compute = ({ atom, selector }) => {
|
|
|
14
12
|
return atom.observe((values) => callback(selector(values), values))
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
return
|
|
15
|
+
return {
|
|
16
|
+
...atom,
|
|
17
|
+
get,
|
|
18
|
+
set,
|
|
19
|
+
observe,
|
|
20
|
+
}
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
export default compute
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import compute from './compute'
|
|
2
|
-
|
|
3
1
|
const difference = (atom) => {
|
|
4
|
-
|
|
2
|
+
const observe = (callback) => {
|
|
3
|
+
let prev
|
|
4
|
+
|
|
5
|
+
const selector = (value) => {
|
|
6
|
+
const p = prev
|
|
7
|
+
prev = value
|
|
8
|
+
return { previous: p, current: value }
|
|
9
|
+
}
|
|
5
10
|
|
|
6
|
-
|
|
7
|
-
const p = prev
|
|
8
|
-
prev = value
|
|
9
|
-
return { previous: p, current: value }
|
|
11
|
+
return atom.observe((value) => callback(selector(value)))
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
return
|
|
14
|
+
return {
|
|
15
|
+
...atom,
|
|
16
|
+
observe,
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
export default difference
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import enforceObservableRules from '../enforce-rules'
|
|
2
|
-
|
|
3
1
|
const readOnly = (atom) => {
|
|
4
2
|
const set = async () => {
|
|
5
3
|
throw new Error('selected atom does not support set')
|
|
6
4
|
}
|
|
7
5
|
|
|
8
|
-
return
|
|
6
|
+
return {
|
|
7
|
+
...atom,
|
|
8
|
+
set,
|
|
9
|
+
}
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export default readOnly
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import assert from 'minimalistic-assert'
|
|
2
|
-
import enforceObservableRules from '../enforce-rules'
|
|
3
2
|
|
|
4
3
|
const swallowObserverErrors = ({ atom, logger }) => {
|
|
5
4
|
assert(atom, 'expected "atom')
|
|
@@ -14,7 +13,10 @@ const swallowObserverErrors = ({ atom, logger }) => {
|
|
|
14
13
|
}
|
|
15
14
|
})
|
|
16
15
|
|
|
17
|
-
return
|
|
16
|
+
return {
|
|
17
|
+
...atom,
|
|
18
|
+
observe,
|
|
19
|
+
}
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export default swallowObserverErrors
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import delay from 'delay'
|
|
2
2
|
import assert from 'minimalistic-assert'
|
|
3
|
-
import enforceObservableRules from '../enforce-rules'
|
|
4
3
|
|
|
5
4
|
const timeoutObservers = ({ atom, timeout }) => {
|
|
6
5
|
assert(atom, 'expected "atom')
|
|
@@ -19,7 +18,10 @@ const timeoutObservers = ({ atom, timeout }) => {
|
|
|
19
18
|
]).then(() => timeoutPromise.clear())
|
|
20
19
|
})
|
|
21
20
|
|
|
22
|
-
return
|
|
21
|
+
return {
|
|
22
|
+
...atom,
|
|
23
|
+
observe,
|
|
24
|
+
}
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export default timeoutObservers
|
|
@@ -5,6 +5,10 @@ const withSerialization = ({ atom, serialize, deserialize }) => {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
const set = async (value) => {
|
|
8
|
+
if (typeof value === 'function') {
|
|
9
|
+
return atom.set((previousValue) => serialize(value(deserialize(previousValue))))
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
const serialized = serialize(value)
|
|
9
13
|
return atom.set(serialized)
|
|
10
14
|
}
|
package/src/event-emitter.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import enforceObservableRules from './enforce-rules'
|
|
2
2
|
|
|
3
|
-
const fromEventEmitter = ({ emitter, event, get, set, defaultValue, logger }) => {
|
|
3
|
+
const fromEventEmitter = ({ emitter, event, get, set, defaultValue, logger, getInitialized }) => {
|
|
4
4
|
const observe = (listener) => {
|
|
5
5
|
emitter.on(event, listener)
|
|
6
6
|
return () => emitter.removeListener(event, listener)
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
return enforceObservableRules({
|
|
10
|
+
getInitialized,
|
|
10
11
|
get,
|
|
11
12
|
set,
|
|
12
13
|
observe,
|
package/src/factories/memory.js
CHANGED
|
@@ -30,7 +30,14 @@ const createAtomMock = (options = {}) => {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
return fromEventEmitter({
|
|
33
|
+
return fromEventEmitter({
|
|
34
|
+
...options,
|
|
35
|
+
getInitialized: () => initialized.resolved,
|
|
36
|
+
emitter,
|
|
37
|
+
event: 'data',
|
|
38
|
+
get,
|
|
39
|
+
set,
|
|
40
|
+
})
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
export default createAtomMock
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { get as getValueAtPath } from 'lodash'
|
|
1
|
+
import { get as getValueAtPath, isEqual } from 'lodash'
|
|
2
2
|
|
|
3
3
|
import createSimpleObserver from '../simple-observer'
|
|
4
4
|
import enforceObservableRules from '../enforce-rules'
|
|
@@ -30,10 +30,19 @@ const createRemoteConfigAtomFactory =
|
|
|
30
30
|
return notify(data)
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
+
const observeDistinct = (callback) =>
|
|
34
|
+
observe(
|
|
35
|
+
function (value) {
|
|
36
|
+
if (isEqual(this.lastValue, value)) return
|
|
37
|
+
this.lastValue = value
|
|
38
|
+
callback(value)
|
|
39
|
+
}.bind({})
|
|
40
|
+
)
|
|
41
|
+
|
|
33
42
|
return enforceObservableRules({
|
|
34
43
|
get,
|
|
35
44
|
set,
|
|
36
|
-
observe,
|
|
45
|
+
observe: observeDistinct,
|
|
37
46
|
defaultValue,
|
|
38
47
|
})
|
|
39
48
|
}
|
package/src/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export { default as createAtomMock } from './factories/memory'
|
|
2
2
|
export { default as createInMemoryAtom } from './factories/memory'
|
|
3
|
-
export { default as createFusionAtomFactory } from './factories/fusion'
|
|
4
3
|
export { default as createStorageAtomFactory } from './factories/storage'
|
|
5
|
-
export { default as createLocalConfigAtomFactory } from './factories/local-config'
|
|
6
4
|
export { default as createRemoteConfigAtomFactory } from './factories/remote-config'
|
|
7
5
|
export { default as createKeystoreAtom } from './factories/keystore'
|
|
8
6
|
export { default as createSequencedKeystoreAtom } from './factories/sequenced-keystore'
|
package/src/factories/fusion.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { get as getValueAtPath, set as setValueAtPath } from 'lodash'
|
|
2
|
-
|
|
3
|
-
import enforceObservableRules from '../enforce-rules'
|
|
4
|
-
|
|
5
|
-
const createFusionAtomFactory =
|
|
6
|
-
({ fusion, logger }) =>
|
|
7
|
-
({ path, defaultValue }) => {
|
|
8
|
-
const set = async (value) => {
|
|
9
|
-
await fusion.mergeProfile(setValueAtPath({}, path, value))
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const get = async () => {
|
|
13
|
-
const profile = await fusion.getProfile()
|
|
14
|
-
return getValueFromProfile(profile)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const getValueFromProfile = (profile) => getValueAtPath(profile, path)
|
|
18
|
-
|
|
19
|
-
const observe = (listener) => fusion.subscribe(getValueFromProfile, listener)
|
|
20
|
-
|
|
21
|
-
return enforceObservableRules({
|
|
22
|
-
get,
|
|
23
|
-
set,
|
|
24
|
-
observe,
|
|
25
|
-
defaultValue,
|
|
26
|
-
logger,
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default createFusionAtomFactory
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import createSimpleObserver from '../simple-observer'
|
|
2
|
-
import enforceObservableRules from '../enforce-rules'
|
|
3
|
-
|
|
4
|
-
const createLocalConfigAtomFactory =
|
|
5
|
-
({ localConfig }) =>
|
|
6
|
-
({ key, defaultValue }) => {
|
|
7
|
-
const { notify, observe } = createSimpleObserver()
|
|
8
|
-
|
|
9
|
-
localConfig.on(`update:${key}`, ({ current }) => notify(current))
|
|
10
|
-
|
|
11
|
-
return enforceObservableRules({
|
|
12
|
-
get: () => localConfig.get(key),
|
|
13
|
-
set: (value) => localConfig.set(key, value),
|
|
14
|
-
observe,
|
|
15
|
-
defaultValue,
|
|
16
|
-
})
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default createLocalConfigAtomFactory
|