
Research
2025 Report: Destructive Malware in Open Source Packages
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.
xstream-store-resource
Advanced tools
A module for removing the repetitive work in configuring asynchronous requests in xstream-store.
xstream-store-resource has xstream and xstream-store as peer dependencies.
$ npm i xstream xstream-store xstream-store-resource
import createResource from 'xstream-store-resource';
const config = {
// create, find, get, patch, remove, update
effects: ['create', 'get'],
name: 'users',
url: '/api/users',
};
const {actions, actionTypes, streamCreator, effectCreators} = createResource(config);
const actions = {...xs, ...ats};
export {actions, effectCreators, streamCreator};
// store.js
import createStore from 'xstream-store';
import {user$Creator, userEffectCreators} from './streams/user';
const streamCreators = {
users: user$Creator,
};
const effectCreators = [
...userEffectCreators,
];
const store = createStore(streamCreators, effectCreators);
export default store;
import store from './store';
import {actions as userActions} from './user-resource';
const subs = store.state$.subscribe({
next({users}) {
console.log(users)
},
});
/* console.log: initial user state
{
entity: null,
items: [],
requestState: 'idle',
requestEffect: 'idle',
lastError: {},
}
*/
// get user with id '1'
store.dispatch(userActions.get('1')
/* console.log: user request made, response pending
{
entity: null,
items: [],
requestState: 'REQUESTING',
requestEffect: 'GETTING',
lastError: {},
}
*/
/* console.log: user response received
{
entity: {id: 1, name: 'Joe Soap', ...},
items: [],
requestState: 'SUCCESS',
requestEffect: 'IDLE',
lastError: {},
}
*/
// create a user
store.dispatch(userActions.create({username: 'someone@me.com', name: 'Jane Doe'})
/* console.log: user request made, response pending
{
entity: {...currUserDetails},
items: [],
requestState: 'REQUESTING',
requestEffect: 'CREATING',
lastError: {},
}
*/
/* console.log: user response received
{
entity: {id: 2, name: 'Jane Doe', ...},
items: [],
requestState: 'SUCCESS',
requestEffect: 'IDLE',
lastError: {},
}
*/
createResource takes a single config object, and returns generated actions, action types, and a stream and effects creator that must be passed to an xstream-store.
import createResource from 'xstream-store-resource';
// defaults
const config = {
// required configs
name: 'my-resource-name',
url: '/my-resource-endpoint/:with/:params',
// optional configs
// base URL to append url config to, e.g. http://my-domain.com
baseUrl: '',
// custom effect creators you want subscribed to this state stream
customEffectCreators: [],
// types of requests to create subscriptions for
effects: [
'create', // POST a new entity
'find', // GET a list of resource entities
'get', // GET a single entity
'patch', // PATCH an entity
'remove', // DELETE an entity
'update' // PUT an entity
],
// How requests will be made, i.e. fetch, jQuery, axios, etc.
// Uses a fetch provider by default
provider: (requestUrl, data, config) => {...},
// configure requests based on the effect, e.g. custom headers for POST
requestConfig: (effect) => {},
};
// createResource returns the following object
const {
// an object containing actions to dispatch for this resource
actions,
// The generated actionTypes used by the above actions
// Useful if you want to create your own action creators to dispatch,
// or if you are creating your own effect creators
actionTypes,
// the stream creator that must be passed to xstream-store's createStore
streamCreator,
// an array of effect creators that must be passed to xstream-store's createStore
effectCreators,
} = createResource(config);
Similarly to Redux, xstream-store relies on dispatched actions to update the state stream. xstream-store-resource generates all the actions and action types necessary to make HTTP requests:
import {actions, actionTypes} from './user-resource'
// the following action types can be used to filter other streams in the store
/*
actionTypes = {
CREATE: '@users/create',
CREATE_SUCCESS: '@user/createSuccess',
CREATE_FAILURE: '@user/createFailure',
FIND: '@users/find',
FIND_SUCCESS: '@users/findSuccess',
FIND_FAILURE: '@users/findFailure',
GET: '@users/get',
GET_SUCCESS: '@users/getSuccess',
GET_FAILURE: '@users/getFailure',
PATCH: '@users/patch',
PATCH_SUCCESS: '@users/patchSuccess',
PATCH_FAILURE: '@users/patchFailure',
REMOVE: '@users/remove',
REMOVE_SUCCESS: '@users/removeSuccess',
REMOVE_FAILURE: '@users/removeFailure',
UPDATE: '@users/update',
UPDATE_SUCCESS: '@users/updateSuccess',
UPDATE_FAILURE: '@users/updateFailure',
}
*/
// action creators that can be dispatched for your resource using store.dispatch
/*
const actions = {
reset: () => {...},
create: (data, params, extra) => {...},
find: (params, extra) => {...},
get: (id, params, extra) => {...},
patch: (id, data, params, extra) => {...},
update: (id, data, params, extra) => {...},
remove: (id, data, params, extra) => {...},
});
*/
The above actions are the actions that are important as an end user, but a full list can be found in src/action-creators.ts.
| Parameter | Description |
|---|---|
| id | appended to url e.g. for the endpoint /users userActions.get(1) will make a request for /users/1 |
| data | data sent as the payload of the request |
| params | url parameters to replace. e.g. for the endpoint /articles/:articleId/comments articleComments.get(1, {articleId: 2}) will make a request for /articles/2/comments/1 |
| extra | additional data to send with the request. Currently supports adding query parameters via the query property e.g. for the endpoint /users userActions.get(1, {}, {query: {name: true; age: true}) will make a request for /users/1?name=true&age=true |
Effects map to HTTP functions to make it easy to define what to do with a resource. The config allows only specific effects to be specified for a resource. Each effect requires its own subscription, it's best to specify in the config which effects to create subscriptions for.
Each effect's subscription updates the resource's state stream when a related action for that effect is dispatched.
When the create, find, get, patch, remove, and update action creators are dispatched, the resource will immediately be in a state indicating that a response is pending:
// dispatch patch on a user
{
entity: {...userDetails},
items: [],
requestState: 'REQUESTING',
requestEffect: 'PATCHING',
lastError: {},
}
Once the request is resolved or rejected, the resource's state will be updated:
// success
{
entity: {...userDetails},
items: [],
requestState: 'SUCCESS',
requestEffect: 'IDLE',
lastError: {},
}
// failure
{
entity: {...userDetails},
items: [],
requestState: 'FAILURE',
requestEffect: 'IDLE',
lastError: {message: 'request failed'},
}
FAQs
A module for making requests in xstream-store easy to build
The npm package xstream-store-resource receives a total of 0 weekly downloads. As such, xstream-store-resource popularity was classified as not popular.
We found that xstream-store-resource 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
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.

Research
/Security News
A five-month operation turned 27 npm packages into durable hosting for browser-run lures that mimic document-sharing portals and Microsoft sign-in, targeting 25 organizations across manufacturing, industrial automation, plastics, and healthcare for credential theft.