npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

xstream-store-resource

v4.0.0

Published

A module for making requests in xstream-store easy to build

Downloads

23

Readme

xstream-store-resource

Build Status npm version codecov

A module for removing the repetitive work in configuring asynchronous requests in xstream-store.

Installation

xstream-store-resource has xstream and xstream-store as peer dependencies.

$ npm i xstream xstream-store xstream-store-resource

Example

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
{
  response: null,
  requestState: 'idle',
  requestEffect: 'idle',
  lastError: {},
}
*/

// get user with id '1'
store.dispatch(userActions.get('1')

/* console.log: user request made, response pending
{
  response: null,
  requestState: 'REQUESTING',
  requestEffect: 'GETTING',
  lastError: {},
}
*/

/* console.log: user response received
{
  response: {id: 1, name: 'Joe Soap', ...},
  requestState: 'SUCCESS',
  requestEffect: 'IDLE',
  lastError: {},
}
*/

// create a user
store.dispatch(userActions.create({username: '[email protected]', name: 'Jane Doe'})

/* console.log: user request made, response pending
{
  response: {...currUserDetails},
  requestState: 'REQUESTING',
  requestEffect: 'CREATING',
  lastError: {},
}
*/

/* console.log: user response received
{
  response: {id: 2, name: 'Jane Doe', ...},
  requestState: 'SUCCESS',
  requestEffect: 'IDLE',
  lastError: {},
}
*/

Usage

Config

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);

Actions and Types of Actions

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.

Action Parameters

| 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

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
{
  response: {...userDetails},
  requestState: 'REQUESTING',
  requestEffect: 'PATCHING',
  lastError: {},
}

Once the request is resolved or rejected, the resource's state will be updated:

// success
{
  response: {...userDetails},
  requestState: 'SUCCESS',
  requestEffect: 'IDLE',
  lastError: {},
}

// failure
{
  response: {...userDetails},
  requestState: 'FAILURE',
  requestEffect: 'IDLE',
  lastError: {message: 'request failed'},
}

Todo

  • [ ] document API
  • [ ] examples