@exodus/atoms 6.0.1 → 7.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/CHANGELOG.md CHANGED
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [7.0.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/atoms@6.0.2...@exodus/atoms@7.0.0) (2023-12-10)
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ - don't call serialize/deserialize on `undefined` in withSerialization (#4896)
11
+
12
+ ### Features
13
+
14
+ - don't call serialize/deserialize on `undefined` in withSerialization ([#4896](https://github.com/ExodusMovement/exodus-hydra/issues/4896)) ([20a7a32](https://github.com/ExodusMovement/exodus-hydra/commit/20a7a321e00a527c94650222e45c0a970164c92c))
15
+
16
+ ## [6.0.2](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/atoms@6.0.1...@exodus/atoms@6.0.2) (2023-11-30)
17
+
18
+ ### Bug Fixes
19
+
20
+ - **atoms:** avoid observe-set loop caused by optimistic notifier ([#4932](https://github.com/ExodusMovement/exodus-hydra/issues/4932)) ([aced29b](https://github.com/ExodusMovement/exodus-hydra/commit/aced29bcd58c3aeb92653c14294cda29897ca3aa))
21
+ - valueEmittedFromGet !== undefined ([#4634](https://github.com/ExodusMovement/exodus-hydra/issues/4634)) ([89d185f](https://github.com/ExodusMovement/exodus-hydra/commit/89d185f7bafa2b604ea76219b3fab14e8845a43d))
22
+
6
23
  ## [6.0.1](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/atoms@6.0.0...@exodus/atoms@6.0.1) (2023-10-25)
7
24
 
8
25
  ### Bug Fixes
package/README.md CHANGED
@@ -18,15 +18,17 @@ An atom is a data source wrapper that exposes a single piece of data through 3 d
18
18
 
19
19
  This library provides helpers for creating atoms from multiple data sources we use in our apps
20
20
 
21
- | | get | set | observe |
22
- | ------------- | --- | ----- | ------- |
23
- | Memory | ✅ | ✅ | ✅ |
24
- | Storage | ✅ | 🟡 \* | ✅ |
25
- | Remote config | ✅ | ❌ | ✅ |
26
- | Local config | ✅ | ✅ | ✅ |
27
- | Event emitter | ✅ | ❌ | ✅ |
28
-
29
- \* A storage atom needs a special `isSoleWriter` param to allow write access. This is because storage instances can overlap, e.g. a parent namespace can mutate a child namespace, and our [storage-spec](https://github.com/ExodusMovement/exodus-hydra/tree/master/modules/storage-spec) doesn't currently provide for detecting changes across those instances.
21
+ | | get | set | observe |
22
+ | ------------- | ----- | ------- | ------- |
23
+ | Memory | ✅ \* | ✅ | ✅ |
24
+ | Storage | ✅ | 🟡 \*\* | ✅ |
25
+ | Remote config | ✅ | ❌ | ✅ |
26
+ | Local config | ✅ | ✅ | ✅ |
27
+ | Event emitter | ✅ | ❌ | ✅ |
28
+
29
+ \* If no `defaultValue` is provided, a memory atom's `get()` method will hang and observers will NOT be called until the first `set()` call.
30
+
31
+ \*\* A storage atom needs a special `isSoleWriter` param to allow write access. This is because storage instances can overlap, e.g. a parent namespace can mutate a child namespace, and our [storage-spec](https://github.com/ExodusMovement/exodus-hydra/tree/master/modules/storage-spec) doesn't currently provide for detecting changes across those instances.
30
32
 
31
33
  ## Usage
32
34
 
@@ -31,7 +31,7 @@ const enforceObservableRules = ({ defaultValue, getInitialized = () => true, ...
31
31
  }
32
32
  });
33
33
  return atom.observe((value) => {
34
- if (valueEmittedFromGet) {
34
+ if (valueEmittedFromGet !== undefined) {
35
35
  const isAlreadyEmitted = value === valueEmittedFromGet;
36
36
  valueEmittedFromGet = undefined;
37
37
  if (isAlreadyEmitted) {
@@ -2,12 +2,14 @@ import makeConcurrent from 'make-concurrent';
2
2
  import createInMemoryAtom from '../factories/memory';
3
3
  const optimisticNotifier = (atom) => {
4
4
  const memoryAtom = createInMemoryAtom();
5
- const set = makeConcurrent(async (newValue) => {
5
+ const set = makeConcurrent(async (newValue, fromRemote) => {
6
6
  let previous;
7
7
  await memoryAtom.set((previousValue) => {
8
8
  previous = previousValue;
9
9
  return newValue;
10
10
  });
11
+ if (fromRemote)
12
+ return;
11
13
  atom
12
14
  .set(newValue)
13
15
  .catch(() => memoryAtom.set((value) => (value === newValue ? previous : value)));
@@ -23,7 +25,7 @@ const optimisticNotifier = (atom) => {
23
25
  };
24
26
  const observe = (callback) => {
25
27
  if (subscribers === 0) {
26
- unsubscribeSource = atom.observe(set);
28
+ unsubscribeSource = atom.observe((value) => set(value, true));
27
29
  }
28
30
  subscribers += 1;
29
31
  const unsubscribe = memoryAtom.observe(callback);
@@ -38,9 +40,10 @@ const optimisticNotifier = (atom) => {
38
40
  }
39
41
  return memoryAtom.get();
40
42
  };
43
+ const _set = (value) => set(value, false);
41
44
  return {
42
45
  ...memoryAtom,
43
- set,
46
+ set: _set,
44
47
  get,
45
48
  observe,
46
49
  };
@@ -4,5 +4,5 @@ type Params<T, S> = {
4
4
  serialize: (value: T) => S;
5
5
  deserialize: (serialized: S) => T;
6
6
  };
7
- declare const withSerialization: <T, S>({ atom, serialize, deserialize }: Params<T, S>) => Atom<T>;
7
+ declare const withSerialization: <T, S>({ atom, serialize: customSerialize, deserialize: customDeserialize, }: Params<T, S>) => Atom<T>;
8
8
  export default withSerialization;
@@ -1,5 +1,7 @@
1
1
  import { isSetter } from '../utils/guards';
2
- const withSerialization = ({ atom, serialize, deserialize }) => {
2
+ const withSerialization = ({ atom, serialize: customSerialize, deserialize: customDeserialize, }) => {
3
+ const serialize = (value) => (value === undefined ? undefined : customSerialize(value));
4
+ const deserialize = (value) => (value === undefined ? undefined : customDeserialize(value));
3
5
  const get = async () => {
4
6
  const serialized = await atom.get();
5
7
  return deserialize(serialized);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/atoms",
3
- "version": "6.0.1",
3
+ "version": "7.0.0",
4
4
  "main": "lib/index.js",
5
5
  "description": "Abstraction for encapsulating a piece of data behind a simple unified interface: get, set, observe",
6
6
  "author": "Exodus Movement Inc.",
@@ -37,11 +37,12 @@
37
37
  "@exodus/atom-tests": "^1.0.0",
38
38
  "@exodus/remote-config": "^2.3.0",
39
39
  "@exodus/storage-memory": "^2.1.1",
40
+ "@types/jest": "^29.5.11",
40
41
  "@types/lodash": "^4.14.200",
41
42
  "@types/minimalistic-assert": "^1.0.2",
42
43
  "delay": "^5.0.0",
43
44
  "eslint": "^8.44.0",
44
45
  "jest": "^29.1.2"
45
46
  },
46
- "gitHead": "7ed0324ad76734e8bd9fddaa9da79ca1e44ad809"
47
+ "gitHead": "e1aadf171d02cc1502ef53f905cd84ab6e307ba3"
47
48
  }