Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@exodus/atoms

Package Overview
Dependencies
Maintainers
0
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@exodus/atoms - npm Package Compare versions

Comparing version 8.1.1 to 9.0.0

19

CHANGELOG.md

@@ -6,2 +6,21 @@ # Change Log

## [9.0.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/atoms@8.1.1...@exodus/atoms@9.0.0) (2024-09-26)
### ⚠ BREAKING CHANGES
- remove isSoleWriter from storage atom factory (#9423)
### Features
- don't allow get to proceed after unsubscribe ([#9441](https://github.com/ExodusMovement/exodus-hydra/issues/9441)) ([33bc642](https://github.com/ExodusMovement/exodus-hydra/commit/33bc642ad6ec32e1f31711f9dfe435d235eaca56))
- remove isSoleWriter from storage atom factory ([#9423](https://github.com/ExodusMovement/exodus-hydra/issues/9423)) ([ab90ee1](https://github.com/ExodusMovement/exodus-hydra/commit/ab90ee13a819058c0f23c37008da2bebf4439157))
### Bug Fixes
- storage atom race condition ([#9403](https://github.com/ExodusMovement/exodus-hydra/issues/9403)) ([bf30d0c](https://github.com/ExodusMovement/exodus-hydra/commit/bf30d0cc90632459b6b0b9fd76fac191d20ddd0b))
### Performance Improvements
- reduce underlying storage reads ([#9418](https://github.com/ExodusMovement/exodus-hydra/issues/9418)) ([f3c0c23](https://github.com/ExodusMovement/exodus-hydra/commit/f3c0c232b120977a27565636f4d1a6ca9fc90b4a))
## [8.1.1](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/atoms@8.1.0...@exodus/atoms@8.1.1) (2024-09-09)

@@ -8,0 +27,0 @@

2

lib/effects/wait-until.d.ts

@@ -1,2 +0,2 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
type Params<T> = {

@@ -3,0 +3,0 @@ atom: Atom<T>;

@@ -1,4 +0,4 @@

import { Atom } from './utils/types.js';
import type { Atom } from './utils/types.js';
type Params<T> = {
makeGetConcurrent?: boolean;
makeGetNonConcurrent?: boolean;
getInitialized?: () => boolean;

@@ -8,3 +8,3 @@ defaultValue?: T;

} & Omit<Atom<T>, 'set' | 'reset'>;
declare const enforceObservableRules: <T>({ defaultValue, makeGetConcurrent, getInitialized, ...atom }: Params<T>) => Atom<T>;
declare const enforceObservableRules: <T>({ defaultValue, makeGetNonConcurrent, getInitialized, ...atom }: Params<T>) => Atom<T>;
export default enforceObservableRules;

@@ -17,10 +17,13 @@ import makeConcurrent from 'make-concurrent';

};
const enforceObservableRules = ({ defaultValue, makeGetConcurrent = false, getInitialized = () => true, ...atom }) => {
const enforceObservableRules = ({ defaultValue, makeGetNonConcurrent = false, getInitialized = () => true, ...atom }) => {
const enqueue = makeConcurrent((fn) => fn(), { concurrency: 1 });
const postProcessValue = (value = defaultValue) => value && typeof value === 'object' ? freeze(value) : value;
const _get = makeGetConcurrent ? makeConcurrent(atom.get) : atom.get;
const get = () => _get().then(postProcessValue);
const nonConcurrentGet = makeGetNonConcurrent
? makeConcurrent(atom.get)
: atom.get;
const get = () => nonConcurrentGet().then(postProcessValue);
const observe = (listener) => {
let called = false;
let valueEmittedFromGet;
let subscribed = true;
listener = withChangeDetection(listener);

@@ -31,3 +34,5 @@ const publishSerially = (value) => {

};
atom.get().then((value) => {
nonConcurrentGet().then((value) => {
if (!subscribed)
return;
if (!called) {

@@ -38,3 +43,3 @@ valueEmittedFromGet = value;

});
return atom.observe((value) => {
const unsubscribe = atom.observe((value) => {
if (valueEmittedFromGet !== undefined) {

@@ -49,2 +54,6 @@ const isAlreadyEmitted = value === valueEmittedFromGet;

});
return () => {
unsubscribe();
subscribed = false;
};
};

@@ -51,0 +60,0 @@ const set = makeConcurrent(async (value) => {

@@ -1,2 +0,2 @@

import { Atom, Listener } from '../utils/types.js';
import type { Atom, Listener } from '../utils/types.js';
type Params<T> = {

@@ -3,0 +3,0 @@ atom: Atom<T>;

@@ -1,2 +0,2 @@

import { Atom, ReadonlyAtom } from '../utils/types.js';
import type { Atom, ReadonlyAtom } from '../utils/types.js';
type CombinedValue<T> = {

@@ -3,0 +3,0 @@ [Key in keyof T]: T[Key] extends Atom<infer U> ? U : never;

@@ -1,2 +0,2 @@

import { Atom, ReadonlyAtom } from '../utils/types.js';
import type { Atom, ReadonlyAtom } from '../utils/types.js';
type Params<T, V> = {

@@ -3,0 +3,0 @@ atom: Atom<T> | ReadonlyAtom<T>;

@@ -1,3 +0,3 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
declare const dedupe: <T>(atom: Atom<T>) => Atom<T>;
export default dedupe;

@@ -1,2 +0,2 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
type Diff<T> = {

@@ -3,0 +3,0 @@ previous?: T;

@@ -1,2 +0,2 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
export default function filter<T>(atom: Atom<T>, predicate: (value: T) => boolean): Atom<T>;

@@ -1,2 +0,2 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
type Params<T extends object> = {

@@ -3,0 +3,0 @@ atom: Atom<T>;

@@ -1,3 +0,3 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
declare const optimisticNotifier: <T>(atom: Atom<T>) => Atom<T | undefined>;
export default optimisticNotifier;

@@ -1,3 +0,3 @@

import { Atom, ReadonlyAtom } from '../utils/types.js';
import type { Atom, ReadonlyAtom } from '../utils/types.js';
declare const readOnly: <T>(atom: Atom<T>) => ReadonlyAtom<T>;
export default readOnly;

@@ -1,2 +0,2 @@

import { Atom, Listener, Logger } from '../utils/types.js';
import type { Atom, Listener, Logger } from '../utils/types.js';
type Params<T> = {

@@ -3,0 +3,0 @@ atom: Atom<T>;

@@ -1,2 +0,2 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
type Params<T> = {

@@ -3,0 +3,0 @@ atom: Atom<T>;

@@ -1,2 +0,2 @@

import { Atom, Logger } from '../utils/types.js';
import type { Atom, Logger } from '../utils/types.js';
type Params<T> = {

@@ -3,0 +3,0 @@ atom: Atom<T>;

@@ -1,2 +0,2 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
type Params<T, S> = {

@@ -3,0 +3,0 @@ atom: Atom<S>;

@@ -1,3 +0,3 @@

import { Atom } from '../utils/types.js';
import { Storage } from '@exodus/storage-interface';
import type { Atom } from '../utils/types.js';
import type { Storage } from '@exodus/storage-interface';
type Params<T> = {

@@ -4,0 +4,0 @@ atom: Atom<T>;

import createStorageAtomFactory from '../factories/storage.js';
const getCacheAtom = ({ storage, key }) => {
const createStorageAtom = createStorageAtomFactory({ storage });
return createStorageAtom({ key, isSoleWriter: true });
return createStorageAtom({ key });
};

@@ -6,0 +6,0 @@ const enhanceAtom = (params) => {

@@ -1,2 +0,2 @@

import { EventEmitter } from './utils/types.js';
import type { EventEmitter } from './utils/types.js';
type Params<T> = {

@@ -3,0 +3,0 @@ emitter: EventEmitter;

@@ -1,2 +0,2 @@

import { Atom, Keystore, KeystoreValue } from '../utils/types.js';
import type { Atom, Keystore, KeystoreValue } from '../utils/types.js';
type Params = {

@@ -3,0 +3,0 @@ keystore: Keystore;

@@ -1,2 +0,2 @@

import { Atom } from '../utils/types.js';
import type { Atom } from '../utils/types.js';
type Params<T> = {

@@ -3,0 +3,0 @@ defaultValue?: T;

@@ -1,2 +0,2 @@

import { ReadonlyAtom, Port } from '../utils/types.js';
import type { ReadonlyAtom, Port } from '../utils/types.js';
type Params<T> = {

@@ -3,0 +3,0 @@ atom: ReadonlyAtom<T>;

@@ -1,2 +0,2 @@

import { Keystore, KeystoreValue } from '../utils/types.js';
import type { Keystore, KeystoreValue } from '../utils/types.js';
type Params = {

@@ -3,0 +3,0 @@ keystore: Keystore;

@@ -1,3 +0,3 @@

import { Atom } from '../utils/types.js';
import { Storage } from '@exodus/storage-interface';
import type { Atom } from '../utils/types.js';
import type { Storage } from '@exodus/storage-interface';
type FactoryParams<T> = {

@@ -9,3 +9,2 @@ storage: Storage<T>;

defaultValue?: D;
isSoleWriter?: boolean;
};

@@ -12,0 +11,0 @@ declare const createStorageAtomFactory: <T>({ storage }: FactoryParams<T>) => {

import createSimpleObserver from '../simple-observer.js';
import enforceObservableRules from '../enforce-rules.js';
import pDefer from 'p-defer';
const createStorageAtomFactory = ({ storage }) => {
function createStorageAtom({ key, defaultValue, isSoleWriter, }) {
const { notify, observe } = createSimpleObserver({ enable: isSoleWriter });
function createStorageAtom({ key, defaultValue }) {
let version = 0;
const { notify, observe } = createSimpleObserver({ enable: true });
let canUseCached = false;
let cached;
let writePromiseDefer;
let pendingWrite;
const set = async (value) => {
if (value === undefined) {
writePromiseDefer = pDefer();
await storage.delete(key);
}
else {
writePromiseDefer = pDefer();
await storage.set(key, value);
}
writePromiseDefer.resolve();
if (isSoleWriter) {
version++;
pendingWrite = (async () => {
if (value === undefined) {
await storage.delete(key);
canUseCached = false;
}
else {
await storage.set(key, value);
canUseCached = true;
}
cached = value;
canUseCached = value !== undefined;
await notify(value);
}
pendingWrite = undefined;
})();
await pendingWrite;
await notify(value);
};
const get = async () => {
if (canUseCached) {
return cached;
if (pendingWrite) {
await pendingWrite;
}
if (writePromiseDefer) {
await writePromiseDefer.promise;
}
if (canUseCached) {
return cached;
}
const currentVersion = version;
const value = await storage.get(key);
if (isSoleWriter) {
cached = value;
canUseCached = true;
if (currentVersion !== version) {
return get();
}
cached = value;
canUseCached = true;
return value;

@@ -48,3 +48,3 @@ };

defaultValue,
makeGetConcurrent: isSoleWriter,
makeGetNonConcurrent: true,
});

@@ -51,0 +51,0 @@ }

@@ -1,2 +0,2 @@

import { Listener } from './utils/types.js';
import type { Listener } from './utils/types.js';
declare const createSimpleObserver: <T>({ enable }?: {

@@ -3,0 +3,0 @@ enable?: boolean | undefined;

@@ -1,2 +0,2 @@

import { Setter } from './types.js';
import type { Setter } from './types.js';
export declare function isSetter<T>(value: T | Setter<T>): value is Setter<T>;
{
"name": "@exodus/atoms",
"version": "8.1.1",
"version": "9.0.0",
"description": "Abstraction for encapsulating a piece of data behind a simple unified interface: get, set, observe",

@@ -43,3 +43,4 @@ "type": "module",

"@exodus/atom-tests": "^1.0.0",
"@exodus/storage-memory": "^2.2.0",
"@exodus/storage-encrypted": "^1.4.1",
"@exodus/storage-memory": "^2.2.1",
"@types/jest": "^29.5.11",

@@ -51,3 +52,3 @@ "@types/json-stringify-safe": "^5.0.3",

},
"gitHead": "d64de7579b06afe91fbded3d1f7eb29950f82e5a"
"gitHead": "bbcb4c47a53d1770a36213ba77fa1f46bccc8d64"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc