New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@xstate/store

Package Overview
Dependencies
Maintainers
0
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@xstate/store - npm Package Compare versions

Comparing version 3.0.1 to 3.1.0

dist/store-5c2c0abc.cjs.js

2

dist/declarations/src/index.d.ts
export { shallowEqual } from "./shallowEqual.js";
export { fromStore } from "./fromStore.js";
export { createStore, createStoreWithProducer } from "./store.js";
export { createStore, createStoreWithProducer, createStoreConfig } from "./store.js";
export * from "./types.js";

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

import { SnapshotFromStore, AnyStore } from "./types.js";
import { SnapshotFromStore, AnyStore, StoreContext, EventPayloadMap, StoreConfig, Store, ExtractEvents } from "./types.js";
/**

@@ -24,1 +24,5 @@ * A React hook that subscribes to the `store` and selects a value from the

export declare function useSelector<TStore extends AnyStore, T>(store: TStore, selector: (snapshot: SnapshotFromStore<TStore>) => T, compare?: (a: T | undefined, b: T) => boolean): T;
export declare const useStore: {
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>): Store<TContext, ExtractEvents<TEventPayloadMap>, ExtractEvents<TEmitted>>;
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>): Store<TContext, ExtractEvents<TEventPayloadMap>, ExtractEvents<TEmitted>>;
};

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

import { EnqueueObject, EventObject, EventPayloadMap, ExtractEvents, Store, StoreAssigner, StoreContext, StoreEffect, StoreSnapshot } from "./types.js";
import { EnqueueObject, EventObject, EventPayloadMap, ExtractEvents, Store, StoreAssigner, StoreContext, StoreConfig, StoreEffect, StoreSnapshot } from "./types.js";
export type TransitionsFromEventPayloadMap<TEventPayloadMap extends EventPayloadMap, TContext extends StoreContext, TEmitted extends EventObject> = {

@@ -7,20 +7,44 @@ [K in keyof TEventPayloadMap & string]: StoreAssigner<TContext, {

};
type CreateStoreParameterTypes<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap> = [
definition: {
context: TContext;
emits?: {
[K in keyof TEmitted & string]: (payload: TEmitted[K]) => void;
};
on: {
[K in keyof TEventPayloadMap & string]: StoreAssigner<NoInfer<TContext>, {
type: K;
} & TEventPayloadMap[K], ExtractEvents<TEmitted>>;
};
}
];
type CreateStoreParameterTypes<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap> = [definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>];
type CreateStoreReturnType<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap> = Store<TContext, ExtractEvents<TEventPayloadMap>, ExtractEvents<TEmitted>>;
export declare const createStore: {
/**
* Creates a **store** that has its own internal state and can be sent events
* that update its internal state based on transitions.
*
* @example
*
* ```ts
* const store = createStore({
* context: { count: 0, name: 'Ada' },
* on: {
* inc: (context, event: { by: number }) => ({
* ...context,
* count: context.count + event.by
* })
* }
* });
*
* store.subscribe((snapshot) => {
* console.log(snapshot);
* });
*
* store.send({ type: 'inc', by: 5 });
* // Logs { context: { count: 5, name: 'Ada' }, status: 'active', ... }
* ```
*
* @param config - The store configuration object
* @param config.context - The initial state of the store
* @param config.on - An object mapping event types to transition functions
* @param config.emits - An object mapping emitted event types to handlers
* @returns A store instance with methods to send events and subscribe to
* state changes
*/
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(...args: CreateStoreParameterTypes<TContext, TEventPayloadMap, TEmitted>): CreateStoreReturnType<TContext, TEventPayloadMap, TEmitted>;
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(...args: CreateStoreParameterTypes<TContext, TEventPayloadMap, TEmitted>): CreateStoreReturnType<TContext, TEventPayloadMap, TEmitted>;
};
export declare const createStoreConfig: {
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>): StoreConfig<TContext, TEventPayloadMap, TEmitted>;
<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap>(definition: StoreConfig<TContext, TEventPayloadMap, TEmitted>): StoreConfig<TContext, TEventPayloadMap, TEmitted>;
};
/**

@@ -59,2 +83,5 @@ * Creates a `Store` with a provided producer (such as Immer's `producer(…)` A

};
emits?: {
[K in keyof TEmittedPayloadMap & string]: (payload: TEmittedPayloadMap[K]) => void;
};
}): Store<TContext, ExtractEvents<TEventPayloadMap>, ExtractEvents<TEmittedPayloadMap>>;

@@ -61,0 +88,0 @@ declare global {

@@ -76,2 +76,13 @@ export type EventPayloadMap = Record<string, {} | null | undefined>;

}
export type StoreConfig<TContext extends StoreContext, TEventPayloadMap extends EventPayloadMap, TEmitted extends EventPayloadMap> = {
context: TContext;
emits?: {
[K in keyof TEmitted & string]: (payload: TEmitted[K]) => void;
};
on: {
[K in keyof TEventPayloadMap & string]: StoreAssigner<TContext, {
type: K;
} & TEventPayloadMap[K], ExtractEvents<TEmitted>>;
};
};
export type IsEmptyObject<T> = T extends Record<string, never> ? true : false;

@@ -78,0 +89,0 @@ export type AnyStore = Store<any, any, any>;

@@ -5,2 +5,4 @@ 'use strict';

var store = require('./store-5c2c0abc.cjs.js');
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts

@@ -30,282 +32,3 @@ function is(x, y) {

const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
function toObserver(nextHandler, errorHandler, completionHandler) {
const isObserver = typeof nextHandler === 'object';
const self = isObserver ? nextHandler : undefined;
return {
next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
};
}
/**
* Updates a context object using a recipe function.
*
* @param context - The current context
* @param recipe - A function that describes how to update the context
* @returns The updated context
*/
function setter(context, recipe) {
return recipe(context);
}
const inspectionObservers = new WeakMap();
function createStoreCore(initialContext, transitions, producer) {
let observers;
let listeners;
const initialSnapshot = {
context: initialContext,
status: 'active',
output: undefined,
error: undefined
};
let currentSnapshot = initialSnapshot;
const emit = ev => {
if (!listeners) {
return;
}
const type = ev.type;
const typeListeners = listeners.get(type);
if (typeListeners) {
typeListeners.forEach(listener => listener(ev));
}
};
const transition = createStoreTransition(transitions, producer);
function receive(event) {
let effects;
[currentSnapshot, effects] = transition(currentSnapshot, event);
inspectionObservers.get(store)?.forEach(observer => {
observer.next?.({
type: '@xstate.snapshot',
event,
snapshot: currentSnapshot,
actorRef: store,
rootId: store.sessionId
});
});
observers?.forEach(o => o.next?.(currentSnapshot));
for (const effect of effects) {
if (typeof effect === 'function') {
effect();
} else {
emit(effect);
}
}
}
const store = {
on(emittedEventType, handler) {
if (!listeners) {
listeners = new Map();
}
let eventListeners = listeners.get(emittedEventType);
if (!eventListeners) {
eventListeners = new Set();
listeners.set(emittedEventType, eventListeners);
}
const wrappedHandler = handler.bind(undefined);
eventListeners.add(wrappedHandler);
return {
unsubscribe() {
eventListeners.delete(wrappedHandler);
}
};
},
sessionId: uniqueId(),
send(event) {
inspectionObservers.get(store)?.forEach(observer => {
observer.next?.({
type: '@xstate.event',
event,
sourceRef: undefined,
actorRef: store,
rootId: store.sessionId
});
});
receive(event);
},
getSnapshot() {
return currentSnapshot;
},
getInitialSnapshot() {
return initialSnapshot;
},
subscribe(observerOrFn) {
const observer = toObserver(observerOrFn);
observers ??= new Set();
observers.add(observer);
return {
unsubscribe() {
return observers?.delete(observer);
}
};
},
[symbolObservable]() {
return this;
},
inspect: observerOrFn => {
const observer = toObserver(observerOrFn);
inspectionObservers.set(store, inspectionObservers.get(store) ?? new Set());
inspectionObservers.get(store).add(observer);
observer.next?.({
type: '@xstate.actor',
actorRef: store,
rootId: store.sessionId
});
observer.next?.({
type: '@xstate.snapshot',
snapshot: initialSnapshot,
event: {
type: '@xstate.init'
},
actorRef: store,
rootId: store.sessionId
});
return {
unsubscribe() {
return inspectionObservers.get(store)?.delete(observer);
}
};
},
trigger: new Proxy({}, {
get: (_, eventType) => {
return payload => {
store.send({
type: eventType,
...payload
});
};
}
})
};
return store;
}
/**
* Creates a **store** that has its own internal state and can be sent events
* that update its internal state based on transitions.
*
* @example
*
* ```ts
* const store = createStore({
* context: { count: 0 },
* on: {
* inc: (context, event: { by: number }) => ({
* count: context.count + event.by
* })
* }
* });
*
* store.subscribe((snapshot) => {
* console.log(snapshot);
* });
*
* store.send({ type: 'inc', by: 5 });
* // Logs { context: { count: 5 }, status: 'active', ... }
* ```
*
* @param config - The store configuration object
* @param config.context - The initial state of the store
* @param config.on - An object mapping event types to transition functions
* @returns A store instance with methods to send events and subscribe to state
* changes
*/
function _createStore(...[{
context,
on
}]) {
return createStoreCore(context, on);
}
const createStore = _createStore;
/**
* Creates a `Store` with a provided producer (such as Immer's `producer(…)` A
* store has its own internal state and can receive events.
*
* @example
*
* ```ts
* import { produce } from 'immer';
*
* const store = createStoreWithProducer(produce, {
* context: { count: 0 },
* on: {
* inc: (context, event: { by: number }) => {
* context.count += event.by;
* }
* }
* });
*
* store.subscribe((snapshot) => {
* console.log(snapshot);
* });
*
* store.send({ type: 'inc', by: 5 });
* // Logs { context: { count: 5 }, status: 'active', ... }
* ```
*/
function createStoreWithProducer(producer, config) {
return createStoreCore(config.context, config.on, producer);
}
/**
* Creates a store transition function that handles state updates based on
* events.
*
* @param transitions - An object mapping event types to transition functions
* @param producer - Optional producer function (e.g., Immer's produce) for
* immutable updates
* @returns A transition function that takes a snapshot and event and returns a
* new snapshot with effects
*/
function createStoreTransition(transitions, producer) {
return (snapshot, event) => {
let currentContext = snapshot.context;
const assigner = transitions?.[event.type];
const effects = [];
const enqueue = {
emit: new Proxy({}, {
get: (_, eventType) => {
return payload => {
effects.push({
...payload,
type: eventType
});
};
}
}),
effect: fn => {
effects.push(fn);
}
};
if (!assigner) {
return [snapshot, effects];
}
if (typeof assigner === 'function') {
currentContext = producer ? producer(currentContext, draftContext => assigner(draftContext, event, enqueue)) : setter(currentContext, draftContext => Object.assign({}, currentContext, assigner?.(draftContext, event,
// TODO: help me
enqueue)));
} else {
const partialUpdate = {};
for (const key of Object.keys(assigner)) {
const propAssignment = assigner[key];
partialUpdate[key] = typeof propAssignment === 'function' ? propAssignment(currentContext, event, enqueue) : propAssignment;
}
currentContext = Object.assign({}, currentContext, partialUpdate);
}
return [{
...snapshot,
context: currentContext
}, effects];
};
}
/**
* Generates a unique 6-character identifier.
*
* @returns A random string identifier
*/
function uniqueId() {
return Math.random().toString(36).slice(6);
}
/**
* An actor logic creator which creates store [actor

@@ -324,3 +47,3 @@ * logic](https://stately.ai/docs/actors#actor-logic) for use with XState.

const transitionsObj = config.on;
const transition = createStoreTransition(transitionsObj);
const transition = store.createStoreTransition(transitionsObj);
return {

@@ -351,5 +74,6 @@ transition: (snapshot, event, actorScope) => {

exports.createStore = createStore;
exports.createStoreWithProducer = createStoreWithProducer;
exports.createStore = store.createStore;
exports.createStoreConfig = store.createStoreConfig;
exports.createStoreWithProducer = store.createStoreWithProducer;
exports.fromStore = fromStore;
exports.shallowEqual = shallowEqual;

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

import { c as createStoreTransition } from './store-d1bc1e92.esm.js';
export { a as createStore, d as createStoreConfig, b as createStoreWithProducer } from './store-d1bc1e92.esm.js';
// From https://github.com/reduxjs/react-redux/blob/720f0ba79236cdc3e1115f4ef9a7760a21784b48/src/utils/shallowEqual.ts

@@ -25,282 +28,3 @@ function is(x, y) {

const symbolObservable = (() => typeof Symbol === 'function' && Symbol.observable || '@@observable')();
function toObserver(nextHandler, errorHandler, completionHandler) {
const isObserver = typeof nextHandler === 'object';
const self = isObserver ? nextHandler : undefined;
return {
next: (isObserver ? nextHandler.next : nextHandler)?.bind(self),
error: (isObserver ? nextHandler.error : errorHandler)?.bind(self),
complete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)
};
}
/**
* Updates a context object using a recipe function.
*
* @param context - The current context
* @param recipe - A function that describes how to update the context
* @returns The updated context
*/
function setter(context, recipe) {
return recipe(context);
}
const inspectionObservers = new WeakMap();
function createStoreCore(initialContext, transitions, producer) {
let observers;
let listeners;
const initialSnapshot = {
context: initialContext,
status: 'active',
output: undefined,
error: undefined
};
let currentSnapshot = initialSnapshot;
const emit = ev => {
if (!listeners) {
return;
}
const type = ev.type;
const typeListeners = listeners.get(type);
if (typeListeners) {
typeListeners.forEach(listener => listener(ev));
}
};
const transition = createStoreTransition(transitions, producer);
function receive(event) {
let effects;
[currentSnapshot, effects] = transition(currentSnapshot, event);
inspectionObservers.get(store)?.forEach(observer => {
observer.next?.({
type: '@xstate.snapshot',
event,
snapshot: currentSnapshot,
actorRef: store,
rootId: store.sessionId
});
});
observers?.forEach(o => o.next?.(currentSnapshot));
for (const effect of effects) {
if (typeof effect === 'function') {
effect();
} else {
emit(effect);
}
}
}
const store = {
on(emittedEventType, handler) {
if (!listeners) {
listeners = new Map();
}
let eventListeners = listeners.get(emittedEventType);
if (!eventListeners) {
eventListeners = new Set();
listeners.set(emittedEventType, eventListeners);
}
const wrappedHandler = handler.bind(undefined);
eventListeners.add(wrappedHandler);
return {
unsubscribe() {
eventListeners.delete(wrappedHandler);
}
};
},
sessionId: uniqueId(),
send(event) {
inspectionObservers.get(store)?.forEach(observer => {
observer.next?.({
type: '@xstate.event',
event,
sourceRef: undefined,
actorRef: store,
rootId: store.sessionId
});
});
receive(event);
},
getSnapshot() {
return currentSnapshot;
},
getInitialSnapshot() {
return initialSnapshot;
},
subscribe(observerOrFn) {
const observer = toObserver(observerOrFn);
observers ??= new Set();
observers.add(observer);
return {
unsubscribe() {
return observers?.delete(observer);
}
};
},
[symbolObservable]() {
return this;
},
inspect: observerOrFn => {
const observer = toObserver(observerOrFn);
inspectionObservers.set(store, inspectionObservers.get(store) ?? new Set());
inspectionObservers.get(store).add(observer);
observer.next?.({
type: '@xstate.actor',
actorRef: store,
rootId: store.sessionId
});
observer.next?.({
type: '@xstate.snapshot',
snapshot: initialSnapshot,
event: {
type: '@xstate.init'
},
actorRef: store,
rootId: store.sessionId
});
return {
unsubscribe() {
return inspectionObservers.get(store)?.delete(observer);
}
};
},
trigger: new Proxy({}, {
get: (_, eventType) => {
return payload => {
store.send({
type: eventType,
...payload
});
};
}
})
};
return store;
}
/**
* Creates a **store** that has its own internal state and can be sent events
* that update its internal state based on transitions.
*
* @example
*
* ```ts
* const store = createStore({
* context: { count: 0 },
* on: {
* inc: (context, event: { by: number }) => ({
* count: context.count + event.by
* })
* }
* });
*
* store.subscribe((snapshot) => {
* console.log(snapshot);
* });
*
* store.send({ type: 'inc', by: 5 });
* // Logs { context: { count: 5 }, status: 'active', ... }
* ```
*
* @param config - The store configuration object
* @param config.context - The initial state of the store
* @param config.on - An object mapping event types to transition functions
* @returns A store instance with methods to send events and subscribe to state
* changes
*/
function _createStore(...[{
context,
on
}]) {
return createStoreCore(context, on);
}
const createStore = _createStore;
/**
* Creates a `Store` with a provided producer (such as Immer's `producer(…)` A
* store has its own internal state and can receive events.
*
* @example
*
* ```ts
* import { produce } from 'immer';
*
* const store = createStoreWithProducer(produce, {
* context: { count: 0 },
* on: {
* inc: (context, event: { by: number }) => {
* context.count += event.by;
* }
* }
* });
*
* store.subscribe((snapshot) => {
* console.log(snapshot);
* });
*
* store.send({ type: 'inc', by: 5 });
* // Logs { context: { count: 5 }, status: 'active', ... }
* ```
*/
function createStoreWithProducer(producer, config) {
return createStoreCore(config.context, config.on, producer);
}
/**
* Creates a store transition function that handles state updates based on
* events.
*
* @param transitions - An object mapping event types to transition functions
* @param producer - Optional producer function (e.g., Immer's produce) for
* immutable updates
* @returns A transition function that takes a snapshot and event and returns a
* new snapshot with effects
*/
function createStoreTransition(transitions, producer) {
return (snapshot, event) => {
let currentContext = snapshot.context;
const assigner = transitions?.[event.type];
const effects = [];
const enqueue = {
emit: new Proxy({}, {
get: (_, eventType) => {
return payload => {
effects.push({
...payload,
type: eventType
});
};
}
}),
effect: fn => {
effects.push(fn);
}
};
if (!assigner) {
return [snapshot, effects];
}
if (typeof assigner === 'function') {
currentContext = producer ? producer(currentContext, draftContext => assigner(draftContext, event, enqueue)) : setter(currentContext, draftContext => Object.assign({}, currentContext, assigner?.(draftContext, event,
// TODO: help me
enqueue)));
} else {
const partialUpdate = {};
for (const key of Object.keys(assigner)) {
const propAssignment = assigner[key];
partialUpdate[key] = typeof propAssignment === 'function' ? propAssignment(currentContext, event, enqueue) : propAssignment;
}
currentContext = Object.assign({}, currentContext, partialUpdate);
}
return [{
...snapshot,
context: currentContext
}, effects];
};
}
/**
* Generates a unique 6-character identifier.
*
* @returns A random string identifier
*/
function uniqueId() {
return Math.random().toString(36).slice(6);
}
/**
* An actor logic creator which creates store [actor

@@ -345,2 +69,2 @@ * logic](https://stately.ai/docs/actors#actor-logic) for use with XState.

export { createStore, createStoreWithProducer, fromStore, shallowEqual };
export { fromStore, shallowEqual };
{
"name": "@xstate/store",
"version": "3.0.1",
"version": "3.1.0",
"description": "Simple stores",

@@ -67,4 +67,4 @@ "keywords": [

"solid-testing-library": "^0.3.0",
"@xstate/vue": "^4.0.2",
"@xstate/react": "^5.0.2",
"@xstate/vue": "^4.0.2",
"xstate": "^5.19.2"

@@ -71,0 +71,0 @@ },

@@ -6,2 +6,3 @@ 'use strict';

var react = require('react');
var store = require('../../dist/store-5c2c0abc.cjs.js');

@@ -44,3 +45,11 @@ function defaultCompare(a, b) {

}
const useStore = function useStoreImpl(definition) {
const storeRef = react.useRef();
if (!storeRef.current) {
storeRef.current = store.createStore(definition);
}
return storeRef.current;
};
exports.useSelector = useSelector;
exports.useStore = useStore;
import { useSyncExternalStore, useCallback, useRef } from 'react';
import { a as createStore } from '../../dist/store-d1bc1e92.esm.js';

@@ -39,3 +40,10 @@ function defaultCompare(a, b) {

}
const useStore = function useStoreImpl(definition) {
const storeRef = useRef();
if (!storeRef.current) {
storeRef.current = createStore(definition);
}
return storeRef.current;
};
export { useSelector };
export { useSelector, useStore };

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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