Research
Security News
Malicious PyPI Package ‘pycord-self’ Targets Discord Developers with Token Theft and Backdoor Exploit
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Consequential redux actions
A small API extracting the goodness of https://github.com/edumentab/talks-redux-patterns by @krawaller.
import {actionCreatorFactory} from 'conduxion'
import produce from 'immer'
import {AppActionMould} from '../../../state.types';
import {STATE_KEY} from '../authentication.state';
import {setAppError} from '../../ui';
type SetIsAuthenticatedPayload = {
isAuthenticated: boolean
}
export type SetIsAuthenticatedAction = AppActionMould<'SET_IS_AUTHENTICATED', SetIsAuthenticatedPayload>
export const [setIsAuthenticated, isSetIsAuthenticated] = actionCreatorFactory<SetIsAuthenticatedAction>({
type: 'SET_IS_AUTHENTICATED',
reducer(state, payload) {
const {isAuthenticated} = payload;
return produce(state, draft => {
draft[STATE_KEY].isAuthenticated = isAuthenticated;
})
},
consequence({action, dispatch}) {
const {isAuthenticated} = action.payload;
if (!isAuthenticated) {
dispatch(setAppError('Not authenticated'));
return;
}
}
});
An alternative approach to redux where we put actions first, and view state as a consequence of them.
Instead of creating singleton reducers responsible for a single state slice, we create reducers for each individual action that can act across the entire state.
Should an action have consequences, they are declared on the action itself (as an event-emitter).
$ npm i -S conduxion
Please note that redux
is a peer-dependency.
Using pre-fab factories.
import {Store} from 'redux';
import {makeStore, RootReducer, ConduxionAction} from 'conduxion';
type AppState = {
// whatever you want
[key: string]: any
}
type AppDependencies = {}
type AppAction = ConduxionAction<AppState, AppDependencies>
const INITIAL_APP_STATE: AppState = {}
const rootReducer: RootReducer<AppState, AppAction, AppDependencies> = (state = INITIAL_APP_STATE, action) => action.reducer
? action.reducer(state, action.payload)
: state;
const store: Store<AppState, AppAction> = makeStore<AppState, AppAction, AppDependencies>(
rootReducer,
INITIAL_APP_STATE
);
export default store;
For your convenience, we also expose a dev version that automatically connects to Redux DevTools
import {Store} from 'redux';
import {createActionLogMiddleware, makeDevStore, RootReducer, ConduxionAction} from 'conduxion';
type AppState = {
// whatever you want
[key: string]: any
}
type AppDependencies = {}
type AppAction = ConduxionAction<AppState, AppDependencies>
const INITIAL_APP_STATE: AppState = {}
const rootReducer: RootReducer<AppState, AppAction, AppDependencies> = (state = INITIAL_APP_STATE, action) => action.reducer
? action.reducer(state, action.payload)
: state;
const actionLog: any[] = [];
const store: Store<AppState, AppAction> = makeDevStore<AppState, AppAction, AppDependencies>(
rootReducer,
INITIAL_APP_STATE,
{
// createActionLogMiddleware mutates actionLog with each action fired
additionalMiddleware: [createActionLogMiddleware(actionLog)]
}
);
export default store;
Using the actionCreatorFactory() factory function.
import {actionCreatorFactory, ConduxionActionMould} from 'conduxion'
import {AppState, AppDependencies} from '../somewhere'
import {setAppError} from '../somewhere-else'
type AppActionMould<T extends string, P> = ConduxionActionMould<
T,
P,
AppState,
AppDependencies
>
type SetIsAuthenticatedPayload = {
isAuthenticated: boolean
}
export type SetIsAuthenticatedAction = AppActionMould<'SET_IS_AUTHENTICATED', SetIsAuthenticatedPayload>
export const [setIsAuthenticated, isSetIsAuthenticated] = actionCreatorFactory<SetIsAuthenticatedAction>({
type: 'SET_IS_AUTHENTICATED',
// optional
reducer(state, payload) {
const {isAuthenticated} = payload;
return {
...state,
isAuthenticated
}
},
// optional
consequence({action, dispatch}) {
const {isAuthenticated} = action.payload;
if (!isAuthenticated) {
dispatch(setAppError('Not authenticated'));
return;
}
}
});
Creates a conduxion redux store with consequence middleware applied.
import {Store} from 'redux'
import {ConduxionAction, RootReducer, MakeStoreOptions} from 'conduxion';
export function makeStore<State extends object, A extends ConduxionAction<State, Dependencies>, Dependencies extends object>(
rootReducer: RootReducer<State, A, Dependencies>,
initialState: State,
opts: MakeStoreOptions<State, Dependencies> = {}
): Store<State, A>;
Creates a conduxion redux store with consequence middleware as well as Redux DevTools middleware applied.
import {Store} from 'redux'
import {ConduxionAction, RootReducer, MakeStoreOptions} from 'conduxion';
export function makeStore<State extends object, A extends ConduxionAction<State, Dependencies>, Dependencies extends object>(
rootReducer: RootReducer<State, A, Dependencies>,
initialState: State,
opts: MakeStoreOptions<State, Dependencies> = {}
): Store<State, A>;
Factory function returning an ActionCreator and ActionGuard for a gived redux action.
import {
Action,
ActionType,
ActionReducer,
ActionState,
ActionPayload,
Consequence,
ActionDeps,
ConduxionAction,
ActionCreator,
ActionGuard
} from 'conduxion'
type CreatorBlueprint<A extends Action<string, any, any, any>> = {
type: ActionType<A>
reducer: ActionReducer<ActionState<A>, ActionPayload<A>>
isError?: boolean
consequence?: Consequence<ActionState<A>, ActionDeps<A>, ActionPayload<A>>
}
export default function actionCreatorFactory<A extends ConduxionAction<any, any>>(
blueprint: CreatorBlueprint<A>
): [ActionCreator<A>, ActionGuard<A>]
There are a lot of types exposed by conduxion, here are a few of them. Please see the root types as well as the core types for a comprehensive list.
Redux root reducer for conduxion.
import {ConduxionAction} from 'conduxion'
export type RootReducer<
State extends object,
A extends ConduxionAction<State, Dependencies>,
Dependencies extends object
> = (state: State | undefined, action: A) => State;
The base interface for all conduxion actions. Enables use of consequence methods.
import {ActionReducer, Consequence} from 'conduxion';
export interface Action<
Type extends string,
Payload extends any,
State extends object,
Dependencies extends object> {
type: Type
error?: boolean
sender?: string
reducer?: ActionReducer<State, Payload>
payload: Payload
consequence?: Consequence<State, Dependencies, Payload> | Consequence<State, Dependencies, Payload>[]
}
An action consequence method.
import {ConsequenceAPI} from 'conduxion'
export type Consequence<State extends object, Dependencies extends object, Payload extends any = any> = ((
api: ConsequenceAPI<State, Dependencies, Payload>
) => void) & {
name: string,
displayName?: string
}
Generic representation of a conduxion action.
import {Action} from 'conduxion';
export type ConduxionActionMould<
Type extends string,
Payload,
State extends object,
Dependencies extends object
> = Action<Type, Payload, State, Dependencies>
Additional configuration for makeStore and makeDevStore.
import {Middleware} from 'redux';
import {ConsequenceGetter, Consequence} from 'conduxion';
export type MakeStoreOptions<State extends object, Dependencies extends object> = {
additionalMiddleware?: Middleware[]
dependencies?: Dependencies
consequenceGetter?: ConsequenceGetter<State, Dependencies>
initConsequence?: Consequence<State, Dependencies>
}
FAQs
Consequential Redux Actions
The npm package conduxion receives a total of 9 weekly downloads. As such, conduxion popularity was classified as not popular.
We found that conduxion demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.
Security News
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.