
Research
Security News
Malicious PyPI Package Exploits Deezer API for Coordinated Music Piracy
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
frint-store
Advanced tools
Store package of Frint
With npm:
$ npm install --save frint-store
Via unpkg CDN:
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.0/Rx.min.js"></script>
<script src="https://unpkg.com/frint-store@latest/dist/frint-store.min.js"></script>
<script>
// available as `window.FrintStore`
</script>
Store
: The object that holds state, with additional methods.State
: Plain object that holds the state.Action
: A plain object/payload telling Store to do something.Action Type
: All action payloads are required to have a type
key.Action Creator
: A function that returns the Action payload.Reducer
: Function that returns a new updated state based on Action.Epic
: Function that accepts and returns an Observable of Actions.Let's import the necessary functions from the library first:
const FrintStore = require('frint-store');
const { createStore, combineReducers } = FrintStore;
We can start by defining our Action Types:
const INCREMENT_COUNTER = 'INCREMENT_COUNTER';
const DECREMENT_COUNTER = 'DECREMENT_COUNTER';
Then we can proceed with writing our Action Creator functions:
function incrementCounter() {
return {
type: INCREMENT_COUNTER
};
}
function decrementCounter() {
return {
type: DECREMENT_COUNTER
};
}
Let's follow up with a Reducer now:
const INITIAL_COUNTER_STATE = {
value: 0
};
function counterReducer(state = INITIAL_COUNTER_STATE, action) {
switch (action.type) {
case 'INCREMENT_COUNTER':
return Object.assign({}, {
value: state.value + 1
});
case 'DECREMENT_COUNTER':
return Object.assign({}, {
value: state.value - 1
});
default:
return state;
}
}
Over time, it is likely the number of reducers that you have would increase. In that case, you can combine them via combineReducers
function:
const rootReducer = combineReducers({
counter: counterReducer
});
Now we can create our Store class:
const Store = createStore({
reducer: rootReducer
});
const store = new Store();
const state$ = store.getState$();
// every time state changes, it will log the latest output
state$.subscribe((state) => console.log(state));
You can now dispatch actions via:
store.dispatch(incrementCounter());
// would print latest state in console:
// `{ counter: { value: 1 } }`
Not all actions may trigger a synchronous change in state. For those, you can return a function from your action creator.
function incrementCounterAsync() {
// instead of returning an object, we return a function
return function (dispatch, getState) {
// `dispatch` is a function you can call with you action payload
// `getState` would give you the most recent state in a synchronous way
setTimeout(function () {
dispatch(incrementCounter());
}, 3000); // update state after 3 seconds
};
}
Epic is a concept borrowed from redux-observable
.
It is a function that accepts an Observable of actions, and returns an Observable of actions which are then dispatched to the Store.
An example can be this:
function myEpic(action$, store) {
return action$;
}
But doing just like above would cause an infinite loop, it will keep dispatching the same action over and over again.
We can use an example of PING/PONG here. Let's first define the constants and reducers:
import { combineReducers } from 'frint-store';
const PING = 'PING';
const PONG = 'PONG';
const INITIAL_STATE = {
isPinging: false,
};
function pingReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case PING:
return {
isPinging: true,
};
case PONG:
return {
isPinging: false,
};
default:
return state;
}
}
const rootReducer = combineReducers({
ping: pingReducer,
});
So far we have created a reducer only, with no action creators. We can process them via epic as follows:
import { filter } from 'rxjs/operators/filter';
import { delay } from 'rxjs/operators/delay';
import { map } from 'rxjs/operators/map';
function pingEpic(action$) {
return action$
.pipe(
filter(action.type === PING), // we only want PING actions here
delay(100), // lets wait for 100ms asynchronously
map(() => ({ type: PONG })) // after waiting, dispatch a PONG action
);
}
Now just like our root reducer, we can create a root epic by combining them all:
import { combineEpics } from 'frint-store';
const rootEpic = combineEpics(pingEpic, someOtherEpic, ...andMoreEpics);
We have everything ready to create our Store now:
import { createStore } from 'frint-store';
const Store = createStore({
reducer: rootReducer,
epic: rootEpic,
});
const store = new Store();
Now dispatching a PING
would trigger our pingEpic which would wait for 100ms before dispatching a PONG:
store.dispatch({ type: PING });
The state would stream like this over time:
store.getState$().subscribe(state => console.log(state));
// initial: { ping: { isLoading: false } }
// PING: { ping: { isLoading: true } }
//
// ...wait 100ms
//
// PONG: { ping: { isLoading: false } }
Epics allow you to take full advantage of RxJS, and it makes it easier to handle complex operations like cancellation of asynchronous side effects for example.
You can use the deps
option when defining your Store:
const Store = createStore({
reducer: rootReducer,
epic: rootEpic,
deps: { foo: 'some value' }
});
Now in your async actions, you can access foo
as:
function incrementCounterAsync() {
return function (dispatch, getState, { foo }) {
// `foo` is `some value` here
dispatch(incrementCounter());
};
}
And also, in your Epics you can access them as:
function myEpic(action$, store, { foo }) {
return action$;
}
This package is a close implementation of the APIs introduced by the awesome redux
and redux-observable
.
createStore(options)
options
(Object
)
options.reducer
(Function
): The reducer function, that returns updated state.options.epic
(Function
): Function receiving and returning an Observable of Actions.options.initialState
(Any
): Default state to start with, defaults to null
.options.console
: Override global console with something custom for logging.options.appendAction
(Object
): Append extra values to Action payload.options.thunkArgument
(Any
): Deprecated, use deps
instead.options.deps
(Any
): Extra argument to pass to async actions.options.enableLogger
(Boolean
): Enable/disable logging in development mode.Store
class.
combineReducers(reducers)
reducers
(Object
): Reducer functions keyed by their namescombineReducers({
counter: counterReducer,
list: listReducer,
});
Function
: The root reducer function.
combineEpics(...epics)
Spread multiple epics as arguments.
combineEpics(counterEpic, listEpic);
Function
: The root epic function.
new Store()
The Store instance.
getState()
Object
: The most recent state, in a synchronous way.
getState$()
Observable
: The state as an observable.
dispatch(action)
Dispatches the action, which will later trigger changes in state.
action
(Object
|Function
): A plain object, with at least a type
key.The action
argument can also be a function:
function (dispatch, getState, deps) {
dispatch(actionPayload);
}
void
.
v5.6.0 (2018-07-13)
frint
frint-react
frint-react-server
, frint-react
FAQs
Store package for Frint
The npm package frint-store receives a total of 50 weekly downloads. As such, frint-store popularity was classified as not popular.
We found that frint-store demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 9 open source maintainers 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 uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.
Security News
Newly introduced telemetry in devenv 1.4 sparked a backlash over privacy concerns, leading to the removal of its AI-powered feature after strong community pushback.