@exodus/atoms 5.7.3 → 6.0.1

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 (74) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/lib/countdown-lock.d.ts +5 -0
  3. package/lib/countdown-lock.js +24 -0
  4. package/lib/effects/wait-until.d.ts +11 -0
  5. package/lib/effects/wait-until.js +28 -0
  6. package/lib/enforce-rules.d.ts +8 -0
  7. package/lib/enforce-rules.js +59 -0
  8. package/lib/enhancers/block-until.d.ts +12 -0
  9. package/lib/enhancers/block-until.js +20 -0
  10. package/lib/enhancers/combine.d.ts +8 -0
  11. package/lib/enhancers/combine.js +47 -0
  12. package/lib/enhancers/compute.d.ts +7 -0
  13. package/lib/enhancers/compute.js +28 -0
  14. package/lib/enhancers/dedupe.d.ts +3 -0
  15. package/lib/enhancers/dedupe.js +29 -0
  16. package/lib/enhancers/difference.d.ts +9 -0
  17. package/lib/enhancers/difference.js +16 -0
  18. package/lib/enhancers/optimistic-notifier.d.ts +3 -0
  19. package/lib/enhancers/optimistic-notifier.js +48 -0
  20. package/lib/enhancers/read-only.d.ts +3 -0
  21. package/lib/enhancers/read-only.js +10 -0
  22. package/lib/enhancers/swallow-observer-errors.d.ts +12 -0
  23. package/lib/enhancers/swallow-observer-errors.js +18 -0
  24. package/lib/enhancers/timeout-observers.d.ts +7 -0
  25. package/lib/enhancers/timeout-observers.js +20 -0
  26. package/lib/enhancers/warn-on-same-value-set.d.ts +8 -0
  27. package/lib/enhancers/warn-on-same-value-set.js +30 -0
  28. package/lib/enhancers/with-serialization.d.ts +8 -0
  29. package/lib/enhancers/with-serialization.js +19 -0
  30. package/lib/event-emitter.d.ts +11 -0
  31. package/lib/event-emitter.js +15 -0
  32. package/lib/factories/keystore.d.ts +14 -0
  33. package/lib/factories/keystore.js +23 -0
  34. package/lib/factories/memory.d.ts +6 -0
  35. package/lib/factories/memory.js +35 -0
  36. package/lib/factories/observer.d.ts +13 -0
  37. package/lib/factories/observer.js +28 -0
  38. package/lib/factories/remote-config.d.ts +13 -0
  39. package/lib/factories/remote-config.js +34 -0
  40. package/lib/factories/sequenced-keystore.d.ts +15 -0
  41. package/lib/factories/sequenced-keystore.js +71 -0
  42. package/lib/factories/storage.d.ts +12 -0
  43. package/lib/factories/storage.js +46 -0
  44. package/lib/index.d.ts +22 -0
  45. package/{src → lib}/index.js +21 -24
  46. package/lib/simple-observer.d.ts +8 -0
  47. package/lib/simple-observer.js +18 -0
  48. package/lib/utils/guards.d.ts +2 -0
  49. package/lib/utils/guards.js +3 -0
  50. package/lib/utils/types.d.ts +24 -0
  51. package/lib/utils/types.js +1 -0
  52. package/package.json +10 -4
  53. package/src/countdown-lock.js +0 -29
  54. package/src/effects/wait-until.js +0 -29
  55. package/src/enforce-rules.js +0 -74
  56. package/src/enhancers/block-until.js +0 -23
  57. package/src/enhancers/combine.js +0 -59
  58. package/src/enhancers/compute.js +0 -31
  59. package/src/enhancers/dedupe.js +0 -31
  60. package/src/enhancers/difference.js +0 -20
  61. package/src/enhancers/optimistic-notifier.js +0 -60
  62. package/src/enhancers/read-only.js +0 -12
  63. package/src/enhancers/swallow-observer-errors.js +0 -22
  64. package/src/enhancers/timeout-observers.js +0 -27
  65. package/src/enhancers/warn-on-same-value-set.js +0 -49
  66. package/src/enhancers/with-serialization.js +0 -23
  67. package/src/event-emitter.js +0 -19
  68. package/src/factories/keystore.js +0 -40
  69. package/src/factories/memory.js +0 -46
  70. package/src/factories/observer.js +0 -33
  71. package/src/factories/remote-config.js +0 -50
  72. package/src/factories/sequenced-keystore.js +0 -108
  73. package/src/factories/storage.js +0 -60
  74. package/src/simple-observer.js +0 -23
package/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
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
+ ## [6.0.1](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/atoms@6.0.0...@exodus/atoms@6.0.1) (2023-10-25)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **atom:** valueEmittedFromGet is not cleared in the observe ([#4566](https://github.com/ExodusMovement/exodus-hydra/issues/4566)) ([e1eb8a0](https://github.com/ExodusMovement/exodus-hydra/commit/e1eb8a0e690614c154c48cfed5dc5471eb06400a))
11
+
12
+ ## [6.0.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/atoms@5.7.3...@exodus/atoms@6.0.0) (2023-10-21)
13
+
14
+ ### ⚠ BREAKING CHANGES
15
+
16
+ - atoms to typescript (#4505)
17
+
18
+ ### Bug Fixes
19
+
20
+ - dedupe enhancer when `set` called with function ([#4515](https://github.com/ExodusMovement/exodus-hydra/issues/4515)) ([ac63578](https://github.com/ExodusMovement/exodus-hydra/commit/ac6357880b5d14238bdcb1bd6a4d06a2b698fb58))
21
+
22
+ ### Code Refactoring
23
+
24
+ - atoms to typescript ([#4505](https://github.com/ExodusMovement/exodus-hydra/issues/4505)) ([3873134](https://github.com/ExodusMovement/exodus-hydra/commit/3873134baacd69602d13e228be797eb7a96ad13e))
25
+
6
26
  ## [5.7.3](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/atoms@5.7.2...@exodus/atoms@5.7.3) (2023-10-20)
7
27
 
8
28
  ### Bug Fixes
@@ -0,0 +1,5 @@
1
+ declare const createCountdownLock: (keys: string[]) => {
2
+ promise: Promise<unknown>;
3
+ unlock: (key: string) => boolean;
4
+ };
5
+ export default createCountdownLock;
@@ -0,0 +1,24 @@
1
+ import pDefer from 'p-defer';
2
+ const createCountdownLock = (keys) => {
3
+ if (!Array.isArray(keys))
4
+ throw new TypeError('lock keys must be an array');
5
+ for (const key of keys) {
6
+ if (typeof key !== 'string')
7
+ throw new TypeError(`lock keys must be all strings. Invalid ${key}`);
8
+ }
9
+ const deferred = pDefer();
10
+ const unlockedKeys = [];
11
+ return {
12
+ promise: deferred.promise,
13
+ unlock: (key) => {
14
+ if (!unlockedKeys.includes(key))
15
+ unlockedKeys.push(key);
16
+ if (unlockedKeys.length === keys.length) {
17
+ deferred.resolve();
18
+ return true;
19
+ }
20
+ return false;
21
+ },
22
+ };
23
+ };
24
+ export default createCountdownLock;
@@ -0,0 +1,11 @@
1
+ import { Atom } from '../utils/types';
2
+ type Params<T> = {
3
+ atom: Atom<T>;
4
+ predicate: (value: T) => boolean;
5
+ rejectAfter?: number;
6
+ };
7
+ type UnobservablePromise<T> = Promise<T> & {
8
+ unobserve: () => void;
9
+ };
10
+ declare const waitUntil: <T>({ atom, predicate, rejectAfter }: Params<T>) => UnobservablePromise<T>;
11
+ export default waitUntil;
@@ -0,0 +1,28 @@
1
+ const waitUntil = ({ atom, predicate, rejectAfter }) => {
2
+ let unobserve;
3
+ let timeout;
4
+ const promise = new Promise((resolve, reject) => {
5
+ unobserve = atom.observe((v) => {
6
+ if (predicate(v)) {
7
+ clearTimeout(timeout);
8
+ unobserve();
9
+ resolve(v);
10
+ }
11
+ });
12
+ if (rejectAfter) {
13
+ timeout = setTimeout(() => {
14
+ unobserve();
15
+ reject(new Error('rejected by timeout'));
16
+ }, rejectAfter);
17
+ }
18
+ });
19
+ Object.defineProperty(promise, 'unobserve', {
20
+ value: () => {
21
+ unobserve();
22
+ clearTimeout(timeout);
23
+ },
24
+ writable: false,
25
+ });
26
+ return promise;
27
+ };
28
+ export default waitUntil;
@@ -0,0 +1,8 @@
1
+ import { Atom } from './utils/types';
2
+ type Params<T> = {
3
+ getInitialized?: () => boolean;
4
+ defaultValue?: T;
5
+ set: (value: T) => Promise<void>;
6
+ } & Omit<Atom<T>, 'set'>;
7
+ declare const enforceObservableRules: <T>({ defaultValue, getInitialized, ...atom }: Params<T>) => Atom<T>;
8
+ export default enforceObservableRules;
@@ -0,0 +1,59 @@
1
+ import makeConcurrent from 'make-concurrent';
2
+ import proxyFreeze from 'proxy-freeze';
3
+ import { isSetter } from './utils/guards';
4
+ const withChangeDetection = (listener) => {
5
+ let currentValue;
6
+ let called = false;
7
+ return async (value) => {
8
+ if (called && value === currentValue)
9
+ return;
10
+ called = true;
11
+ currentValue = value;
12
+ await listener(currentValue);
13
+ };
14
+ };
15
+ const enforceObservableRules = ({ defaultValue, getInitialized = () => true, ...atom }) => {
16
+ const enqueue = makeConcurrent((fn) => fn(), { concurrency: 1 });
17
+ const postProcessValue = (value = defaultValue) => value && typeof value === 'object' ? proxyFreeze(value) : value;
18
+ const get = () => atom.get().then(postProcessValue);
19
+ const observe = (listener) => {
20
+ let called = false;
21
+ let valueEmittedFromGet;
22
+ listener = withChangeDetection(listener);
23
+ const publishSerially = (value) => {
24
+ called = true;
25
+ return enqueue(() => listener(value));
26
+ };
27
+ get().then((value) => {
28
+ if (!called) {
29
+ valueEmittedFromGet = value;
30
+ publishSerially(value);
31
+ }
32
+ });
33
+ return atom.observe((value) => {
34
+ if (valueEmittedFromGet) {
35
+ const isAlreadyEmitted = value === valueEmittedFromGet;
36
+ valueEmittedFromGet = undefined;
37
+ if (isAlreadyEmitted) {
38
+ return;
39
+ }
40
+ }
41
+ return publishSerially(postProcessValue(value));
42
+ });
43
+ };
44
+ const set = makeConcurrent(async (value) => {
45
+ if (isSetter(value)) {
46
+ const current = getInitialized() ? await get() : defaultValue;
47
+ value = await value(current);
48
+ if (current === value)
49
+ return;
50
+ }
51
+ await atom.set(value);
52
+ });
53
+ return {
54
+ get,
55
+ set,
56
+ observe,
57
+ };
58
+ };
59
+ export default enforceObservableRules;
@@ -0,0 +1,12 @@
1
+ import { Atom, Listener } from '../utils/types';
2
+ type Params<T> = {
3
+ atom: Atom<T>;
4
+ unblock: () => Promise<unknown>;
5
+ };
6
+ export default function blockUntil<T>({ atom, unblock }: Params<T>): {
7
+ get: () => Promise<T>;
8
+ observe: (listener: Listener<T>) => () => void;
9
+ set(value: T): Promise<void>;
10
+ set(setter: import("../utils/types").Setter<T>): Promise<void>;
11
+ };
12
+ export {};
@@ -0,0 +1,20 @@
1
+ export default function blockUntil({ atom, unblock }) {
2
+ const get = async () => unblock().then(atom.get);
3
+ return {
4
+ ...atom,
5
+ get,
6
+ observe: (listener) => {
7
+ let isSubscribed = true;
8
+ let unsubscribe = () => { };
9
+ unblock().then(() => {
10
+ if (isSubscribed) {
11
+ unsubscribe = atom.observe(listener);
12
+ }
13
+ });
14
+ return () => {
15
+ isSubscribed = false;
16
+ unsubscribe();
17
+ };
18
+ },
19
+ };
20
+ }
@@ -0,0 +1,8 @@
1
+ import { Atom, ReadonlyAtom } from '../utils/types';
2
+ type CombinedValue<T> = {
3
+ [Key in keyof T]: T[Key] extends Atom<infer U> ? U : never;
4
+ };
5
+ declare const combine: <T, U extends {
6
+ [key: string]: Atom<T>;
7
+ }>(atoms: U) => ReadonlyAtom<CombinedValue<U>>;
8
+ export default combine;
@@ -0,0 +1,47 @@
1
+ import createCountdownLock from '../countdown-lock';
2
+ import createSimpleObserver from '../simple-observer';
3
+ import enforceObservableRules from '../enforce-rules';
4
+ const combine = (atoms) => {
5
+ const { notify, observe: observeSimpleObserver } = createSimpleObserver();
6
+ const countdownLock = createCountdownLock(Object.keys(atoms));
7
+ let values = {};
8
+ let subscriptions = [];
9
+ let subscribers = 0;
10
+ const maybeUnsubscribeSourceObservables = () => {
11
+ subscribers -= 1;
12
+ if (subscribers > 0)
13
+ return;
14
+ subscriptions.forEach((unsubscribe) => unsubscribe());
15
+ subscriptions = [];
16
+ };
17
+ const observe = (callback) => {
18
+ subscribers += 1;
19
+ if (subscribers === 1) {
20
+ subscriptions = Object.entries(atoms).map(([name, atom]) => atom.observe(async (value) => {
21
+ values = {
22
+ ...values,
23
+ [name]: value,
24
+ };
25
+ if (countdownLock.unlock(name))
26
+ await notify(values);
27
+ }));
28
+ }
29
+ const unsubscribe = observeSimpleObserver(callback);
30
+ return () => {
31
+ unsubscribe();
32
+ maybeUnsubscribeSourceObservables();
33
+ };
34
+ };
35
+ const get = async () => {
36
+ return Object.fromEntries(await Promise.all(Object.entries(atoms).map(async ([name, atom]) => [name, await atom.get()])));
37
+ };
38
+ const set = async () => {
39
+ throw new Error('combine does not support method: set');
40
+ };
41
+ return enforceObservableRules({
42
+ get,
43
+ set,
44
+ observe,
45
+ });
46
+ };
47
+ export default combine;
@@ -0,0 +1,7 @@
1
+ import { Atom, ReadonlyAtom } from '../utils/types';
2
+ type Params<T, V> = {
3
+ atom: Atom<T>;
4
+ selector: (value: T) => V;
5
+ };
6
+ declare const compute: <T, V>({ atom, selector }: Params<T, V>) => ReadonlyAtom<V>;
7
+ export default compute;
@@ -0,0 +1,28 @@
1
+ const compute = ({ atom, selector }) => {
2
+ const get = async () => {
3
+ const values = await atom.get();
4
+ return selector(values);
5
+ };
6
+ const set = async () => {
7
+ throw new Error('selected atom does not support set');
8
+ };
9
+ const observe = (callback) => {
10
+ let prev;
11
+ let called;
12
+ return atom.observe((values) => {
13
+ const selected = selector(values);
14
+ if (called && prev === selected)
15
+ return;
16
+ called = true;
17
+ prev = selected;
18
+ return callback(selected);
19
+ });
20
+ };
21
+ return {
22
+ ...atom,
23
+ get,
24
+ set,
25
+ observe,
26
+ };
27
+ };
28
+ export default compute;
@@ -0,0 +1,3 @@
1
+ import { Atom } from '../utils/types';
2
+ declare const dedupe: <T>(atom: Atom<T>) => Atom<T>;
3
+ export default dedupe;
@@ -0,0 +1,29 @@
1
+ import { isEqual } from 'lodash';
2
+ import { isSetter } from '../utils/guards';
3
+ const dedupe = (atom) => {
4
+ const set = (value) => {
5
+ if (value === undefined)
6
+ return atom.set(value);
7
+ return atom.set(async (previous) => {
8
+ const newValue = isSetter(value) ? await value(previous) : value;
9
+ return isEqual(previous, newValue) ? previous : newValue;
10
+ });
11
+ };
12
+ const observe = (callback) => {
13
+ let called = false;
14
+ let previous;
15
+ return atom.observe(async (value) => {
16
+ if (called && isEqual(previous, value))
17
+ return;
18
+ called = true;
19
+ previous = value;
20
+ return callback(value);
21
+ });
22
+ };
23
+ return {
24
+ ...atom,
25
+ set,
26
+ observe,
27
+ };
28
+ };
29
+ export default dedupe;
@@ -0,0 +1,9 @@
1
+ import { Atom, Listener } from '../utils/types';
2
+ type Diff<T> = {
3
+ previous?: T;
4
+ current: T;
5
+ };
6
+ declare const difference: <T>(atom: Atom<T>) => Omit<Atom<T>, "observe"> & {
7
+ observe: (listener: Listener<Diff<T>>) => import("../utils/types").Unsubscribe;
8
+ };
9
+ export default difference;
@@ -0,0 +1,16 @@
1
+ const difference = (atom) => {
2
+ const observe = (callback) => {
3
+ let prev;
4
+ const selector = (value) => {
5
+ const p = prev;
6
+ prev = value;
7
+ return { previous: p, current: value };
8
+ };
9
+ return atom.observe((value) => callback(selector(value)));
10
+ };
11
+ return {
12
+ ...atom,
13
+ observe,
14
+ };
15
+ };
16
+ export default difference;
@@ -0,0 +1,3 @@
1
+ import { Atom } from '../utils/types';
2
+ declare const optimisticNotifier: <T>(atom: Atom<T>) => Atom<T | undefined>;
3
+ export default optimisticNotifier;
@@ -0,0 +1,48 @@
1
+ import makeConcurrent from 'make-concurrent';
2
+ import createInMemoryAtom from '../factories/memory';
3
+ const optimisticNotifier = (atom) => {
4
+ const memoryAtom = createInMemoryAtom();
5
+ const set = makeConcurrent(async (newValue) => {
6
+ let previous;
7
+ await memoryAtom.set((previousValue) => {
8
+ previous = previousValue;
9
+ return newValue;
10
+ });
11
+ atom
12
+ .set(newValue)
13
+ .catch(() => memoryAtom.set((value) => (value === newValue ? previous : value)));
14
+ });
15
+ let unsubscribeSource;
16
+ let subscribers = 0;
17
+ const maybeUnsubscribeSource = () => {
18
+ subscribers -= 1;
19
+ if (subscribers > 0)
20
+ return;
21
+ unsubscribeSource();
22
+ unsubscribeSource = undefined;
23
+ };
24
+ const observe = (callback) => {
25
+ if (subscribers === 0) {
26
+ unsubscribeSource = atom.observe(set);
27
+ }
28
+ subscribers += 1;
29
+ const unsubscribe = memoryAtom.observe(callback);
30
+ return () => {
31
+ unsubscribe();
32
+ maybeUnsubscribeSource();
33
+ };
34
+ };
35
+ const get = async () => {
36
+ if (subscribers === 0) {
37
+ return atom.get();
38
+ }
39
+ return memoryAtom.get();
40
+ };
41
+ return {
42
+ ...memoryAtom,
43
+ set,
44
+ get,
45
+ observe,
46
+ };
47
+ };
48
+ export default optimisticNotifier;
@@ -0,0 +1,3 @@
1
+ import { Atom, ReadonlyAtom } from '../utils/types';
2
+ declare const readOnly: <T>(atom: Atom<T>) => ReadonlyAtom<T>;
3
+ export default readOnly;
@@ -0,0 +1,10 @@
1
+ const readOnly = (atom) => {
2
+ const set = async () => {
3
+ throw new Error('selected atom does not support set');
4
+ };
5
+ return {
6
+ ...atom,
7
+ set,
8
+ };
9
+ };
10
+ export default readOnly;
@@ -0,0 +1,12 @@
1
+ import { Atom, Listener, Logger } from '../utils/types';
2
+ type Params<T> = {
3
+ atom: Atom<T>;
4
+ logger: Logger;
5
+ };
6
+ declare const swallowObserverErrors: <T>({ atom, logger }: Params<T>) => {
7
+ observe: (observer: Listener<T>) => import("../utils/types").Unsubscribe;
8
+ get(): Promise<T>;
9
+ set(value: T): Promise<void>;
10
+ set(setter: import("../utils/types").Setter<T>): Promise<void>;
11
+ };
12
+ export default swallowObserverErrors;
@@ -0,0 +1,18 @@
1
+ import assert from 'minimalistic-assert';
2
+ const swallowObserverErrors = ({ atom, logger }) => {
3
+ assert(atom, 'expected "atom');
4
+ assert(typeof logger?.error === 'function', 'expected logger with ".error" function');
5
+ const observe = (observer) => atom.observe(async (...args) => {
6
+ try {
7
+ await observer(...args);
8
+ }
9
+ catch (err) {
10
+ logger.error('Observer threw error', err);
11
+ }
12
+ });
13
+ return {
14
+ ...atom,
15
+ observe,
16
+ };
17
+ };
18
+ export default swallowObserverErrors;
@@ -0,0 +1,7 @@
1
+ import { Atom } from '../utils/types';
2
+ type Params<T> = {
3
+ atom: Atom<T>;
4
+ timeout: number;
5
+ };
6
+ declare const timeoutObservers: <T>({ atom, timeout }: Params<T>) => Atom<T>;
7
+ export default timeoutObservers;
@@ -0,0 +1,20 @@
1
+ import delay from 'delay';
2
+ import assert from 'minimalistic-assert';
3
+ const timeoutObservers = ({ atom, timeout }) => {
4
+ assert(atom, 'expected "atom');
5
+ assert(typeof timeout === 'number', 'expected number "timeout"');
6
+ const observe = (observer) => atom.observe(async (...args) => {
7
+ const timeoutPromise = delay.reject(timeout, {
8
+ value: new Error('Observer timed out!'),
9
+ });
10
+ await Promise.race([
11
+ observer(...args),
12
+ timeoutPromise,
13
+ ]).then(() => timeoutPromise.clear());
14
+ });
15
+ return {
16
+ ...atom,
17
+ observe,
18
+ };
19
+ };
20
+ export default timeoutObservers;
@@ -0,0 +1,8 @@
1
+ import { Atom, Logger } from '../utils/types';
2
+ type Params<T> = {
3
+ atom: Atom<T>;
4
+ logger: Logger;
5
+ isEqual?: (a: unknown, b: unknown) => boolean;
6
+ };
7
+ declare const warnOnSameValueSet: <T>({ atom, isEqual, logger }: Params<T>) => Atom<T>;
8
+ export default warnOnSameValueSet;
@@ -0,0 +1,30 @@
1
+ import assert from 'minimalistic-assert';
2
+ import { isEqual as deepEqual } from 'lodash';
3
+ const STRINGIFY_LIMIT = 1000;
4
+ const limitedStringify = (obj, limit = STRINGIFY_LIMIT) => {
5
+ let count = 0;
6
+ return JSON.stringify(obj, (_, value) => {
7
+ if (count > limit) {
8
+ return;
9
+ }
10
+ if (count === limit) {
11
+ count++;
12
+ return '...more properties not shown';
13
+ }
14
+ count++;
15
+ return value;
16
+ });
17
+ };
18
+ const warnOnSameValueSet = ({ atom, isEqual = deepEqual, logger }) => {
19
+ assert(atom, 'expected "atom');
20
+ assert(typeof logger?.warn === 'function', 'expected logger with ".warn" function');
21
+ let previousValue;
22
+ atom.observe((value) => {
23
+ if (value !== undefined && isEqual(value, previousValue)) {
24
+ logger.warn(`Atom was called with the same value it currently holds: ${limitedStringify(value)}`);
25
+ }
26
+ previousValue = value;
27
+ });
28
+ return atom;
29
+ };
30
+ export default warnOnSameValueSet;
@@ -0,0 +1,8 @@
1
+ import { Atom } from '../utils/types';
2
+ type Params<T, S> = {
3
+ atom: Atom<S>;
4
+ serialize: (value: T) => S;
5
+ deserialize: (serialized: S) => T;
6
+ };
7
+ declare const withSerialization: <T, S>({ atom, serialize, deserialize }: Params<T, S>) => Atom<T>;
8
+ export default withSerialization;
@@ -0,0 +1,19 @@
1
+ import { isSetter } from '../utils/guards';
2
+ const withSerialization = ({ atom, serialize, deserialize }) => {
3
+ const get = async () => {
4
+ const serialized = await atom.get();
5
+ return deserialize(serialized);
6
+ };
7
+ const set = async (value) => {
8
+ if (isSetter(value)) {
9
+ return atom.set(async (previousValue) => serialize(await value(deserialize(previousValue))));
10
+ }
11
+ const serialized = serialize(value);
12
+ return atom.set(serialized);
13
+ };
14
+ const observe = (callback) => {
15
+ return atom.observe((value) => callback(deserialize(value), value));
16
+ };
17
+ return { ...atom, get, set, observe };
18
+ };
19
+ export default withSerialization;
@@ -0,0 +1,11 @@
1
+ import { EventEmitter } from './utils/types';
2
+ type Params<T> = {
3
+ emitter: EventEmitter;
4
+ event: string;
5
+ set: (value: T) => Promise<void>;
6
+ get: () => Promise<T>;
7
+ defaultValue?: T;
8
+ getInitialized?: () => boolean;
9
+ };
10
+ declare const fromEventEmitter: <T>({ emitter, event, get, set, defaultValue, getInitialized, }: Params<T>) => import("./utils/types").Atom<T>;
11
+ export default fromEventEmitter;
@@ -0,0 +1,15 @@
1
+ import enforceObservableRules from './enforce-rules';
2
+ const fromEventEmitter = ({ emitter, event, get, set, defaultValue, getInitialized, }) => {
3
+ const observe = (listener) => {
4
+ emitter.on(event, listener);
5
+ return () => emitter.removeListener(event, listener);
6
+ };
7
+ return enforceObservableRules({
8
+ getInitialized,
9
+ get,
10
+ set,
11
+ observe,
12
+ defaultValue,
13
+ });
14
+ };
15
+ export default fromEventEmitter;
@@ -0,0 +1,14 @@
1
+ import { Atom, Keystore, KeystoreValue } from '../utils/types';
2
+ type Params = {
3
+ keystore: Keystore;
4
+ config: {
5
+ key: string;
6
+ defaultValue?: KeystoreValue;
7
+ isSoleWriter?: boolean;
8
+ getOpts?: object;
9
+ setOpts?: object;
10
+ deleteOpts?: object;
11
+ };
12
+ };
13
+ declare const createKeystoreAtom: ({ keystore, config: { key, defaultValue, isSoleWriter, getOpts, setOpts, deleteOpts, }, }: Params) => Atom<KeystoreValue | null>;
14
+ export default createKeystoreAtom;
@@ -0,0 +1,23 @@
1
+ import enforceObservableRules from '../enforce-rules';
2
+ import createSimpleObserver from '../simple-observer';
3
+ const createKeystoreAtom = ({ keystore, config: { key, defaultValue, isSoleWriter, getOpts, setOpts, deleteOpts, }, }) => {
4
+ const { notify, observe } = createSimpleObserver({ enable: isSoleWriter });
5
+ const set = async (value) => {
6
+ if (value == null) {
7
+ await keystore.deleteSecret(key, deleteOpts);
8
+ }
9
+ else {
10
+ await keystore.setSecret(key, value, setOpts);
11
+ }
12
+ if (isSoleWriter)
13
+ await notify(value);
14
+ };
15
+ const get = () => keystore.getSecret(key, getOpts);
16
+ return enforceObservableRules({
17
+ get,
18
+ set,
19
+ observe,
20
+ defaultValue,
21
+ });
22
+ };
23
+ export default createKeystoreAtom;
@@ -0,0 +1,6 @@
1
+ import { Atom } from '../utils/types';
2
+ type Params<T> = {
3
+ defaultValue?: T;
4
+ };
5
+ declare const createAtomMock: <T>(options?: Params<T>) => Atom<T>;
6
+ export default createAtomMock;