Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@animus-bi/redxs
Advanced tools
A super lightweight redux implementation, inspired by NGXS that can run in React, Angular, Express, or anywhere!
RedXS is a super lightweight redux implementation, inspired by NGXS that can run anywhere! Asynchronous state management is a first class concept.
- Very simple composition
- Very little boilerplate
- Very easy to use and grasp
Type
they are attached to (No more large switch statements in reducers!!). Handlers given 2 parameters when executed:
getState()
getRootState()
setState(obj: any)
state$
and rootState$
subscriptionspatchState(obj: Partial<any>)
obj
on the store's slice of statestate$
and rootState$
subscriptionsdispatch(action: any)
type
or Type
property.Run npm install --save @animus-bi/redxs
to install the redxs library.
Define an Action
type
or Type
type
property, the constructor name is used// store/todo/actions.ts
export const Intent = 'todo';
export class CreateTodo {
static Type = `[${Intent}] Create A TODO`;
constructor(public task: string) { }
}
// store/todo/actions.ts
export const Intent = 'todo';
export const CreateTodo = (task) => ({
type: `[${Intent}] Create A TODO`,
task
})
actions.ts
Intent
for our actions.
Define a default state for your store
// store/todo/state.ts
export class TodoState {
list: any[] = [];
hash: any = {};
}
Define a Store
with a StoreConfig
// store/todo/store.ts
export TodoStore = Store.Create<TodoState>(
/* StoreConfig */
)
StoreConfig
is what drives the Store
implementation.
StoreConfig
using an object literal
// store/todo/store.ts
import * as TodosActions from './todos.actions'
export TodoStore = Store.Create<TodoState>({
name: TodosActions.Intent,
initialState: new TodoState(),
handlers: { }
});
StoreConfig
using the static StoreConfig.create
method
// store/todo/store.ts
import { Store, StoreConfig } from '@animus-bi/redxs';
import * as TodosActions from './actions';
import { TodoState } from './state';
const storeConfig = StoreConfig.create(
TodosActions.Intent,
new TodoState(),
{ }
);
export TodoStore = Store.Create<TodoState>(storeConfig);
You may have noticed, the Intent
for a set of actions has become the name of our store, tying together our set of actions with our slice of application state.
Store
instance has the following methods/properties:
state$: Observable<any>
setState()
or patchState()
are calledrootState$: Observable<any>
setState()
or patchState()
are calledcurrentState(): any
currentRootState(): any
dispatch(action: any|{type: string}): Observable<void>
Type
or type
.Now we can wire up some handlers in our store so that we can do things when Actions are dispatched.
Handlers are not called directly by your code; instead, they are invoked when an Action of a matching Type
is dispatched.
Each handler is passed 2 arguments:
StateContext<T>
, which provides some operations to interact with state at the time the handler is executed.// store/todo/store.ts
import { Store, StateContext, StoreConfig } from '@animus-bi/redxs';
import * as TodosActions from './actions';
import { TodoState } from './state';
const createTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
const { list, hash } = ctx.getState();
list.push(action.payload);
hash[action.payload.task] = action.payload;
return ctx.patchState({ list, hash });
}
export TodoStore = Store.Create<TodoState>({
/* ... */
});
In order that the createTodo
function is called when the Action is dispatched, we must add it to our store's StateConfig so that our Action type
is the key name for the handler.
Note: you are not calling the handler in the config, but rather, you're passing a reference to the handler. To avoid any lexical problems, use .bind(this)
// store/todo.ts
import { Store, StateContext, StoreConfig } from '@animus-bi/redxs';
import * as TodosActions from './actions';
import { TodoState } from './state';
const createTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
const { list, hash } = ctx.getState();
list.push(action.payload);
hash[action.payload.task] = action.payload;
return ctx.patchState({ list, hash });
}
export TodoStore = Store.Create<TodoState>({
name: TodosActions.Intent,
initialState: new TodoState(),
handlers: {
[TodosActions.CreateTodo.Type]: createTodo.bind(this)
}
});
You may also attach multiple handlers to a single dispatched action:
// store/todo.ts
import { Store, StateContext, StoreConfig } from '@animus-bi/redxs';
import * as TodosActions from './actions';
import { TodoState } from './state';
const preCreateTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
console.log('intend to create a todo');
}
const createTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
const { list, hash } = ctx.getState();
list.push(action.payload);
hash[action.payload.task] = action.payload;
return ctx.patchState({ list, hash });
}
export TodoStore = Store.Create<TodoState>({
name: TodosActions.Intent,
initialState: new TodoState(),
handlers: {
//
// Good/Ok
//
[TodosActions.CreateTodo.Type]: [
preCreateTodo.bind(this)
createTodo.bind(this)
]
}
});
You should NOT list the same key twice in a store's action handler config (this is standard js stuff).
// store/todo.ts
import { Store, StateContext, StoreConfig } from '@animus-bi/redxs';
import * as TodosActions from './actions';
import { TodoState } from './state';
const preCreateTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
console.log('intend to create a todo');
}
const createTodo = (ctx: StateContext<TodoState>, action: TodosActions.CreateTodo) => {
const { list, hash } = ctx.getState();
list.push(action.payload);
hash[action.payload.task] = action.payload;
return ctx.patchState({ list, hash });
}
export TodoStore = Store.Create<TodoState>({
name: TodosActions.Intent,
initialState: new TodoState(),
handlers: {
//
// !!!!!!BAD!!!!!!!!!!!!!!
//
[TodosActions.CreateTodo.Type]: preCreateTodo.bind(this),
[TodosActions.CreateTodo.Type]: createTodo.bind(this)
}
});
To access state in anything, simply subscribe to your store's state$
property wherever you want to receive state updates.
import { TodoStore } from '../store/todo';
export class SomeComponent {
constructor() {
this.subscription = TodoStore.state$.subscribe((todoState) => {
this.todoState = todoState;
})
}
}
currentState()
method, which will return the current state of your slice (NOT NECESSARILY INITIAL STATE).
import { TodoStore } from '../store/todo';
export class SomeComponent {
constructor() {
this.todoState = TodoStore.currentState();
this.subscription = TodoStore.state$.subscribe((todoState) => {
this.todoState = todoState;
})
}
}
import { TodoStore } from '../store/todo';
export class SomeComponent {
todoState = TodoStore.currentState();
constructor() {
this.subscription = TodoStore.state$.subscribe((todoState) => {
this.todoState = todoState;
});
}
}
Dispatch Actions from anywhere
import { TodoStore } from '../store/todo';
import * as TodosActions from './store/todo/actions';
export class SomeComponent {
addTodo(_e) {
const text = document.getElementById('todo-input').value
store.dispatch(new TodosActions.CreateTodo(text));
}
render() {
return <div>
<input type="text" id="todo-input" value="" />
<button onClick={this.addTodo}>add todo</button>
</div>
}
}
import { Component } from '@angular/core';
import { TodoStore } from '../store/todo';
import * as TodosActions from './store/todo/actions';
@Component({
selector: "some-component",
template: `
<div>
<input type="text" id="todo-input" value="" />
<button (click)="addTodo()">add todo</button>
</div>
`})
export class SomeComponent {
addTodo() {
const text = document.getElementById('todo-input').value
store.dispatch(new TodosActions.CreateTodo(text));
}
}
Combine dispatching and subscribing as needed for an overall async pub/sub model. See examples above for more info.
FAQs
A super lightweight redux implementation, inspired by NGXS that can run in React, Angular, Express, or anywhere!
The npm package @animus-bi/redxs receives a total of 35 weekly downloads. As such, @animus-bi/redxs popularity was classified as not popular.
We found that @animus-bi/redxs 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’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.