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

@gigster/module-redux-models

v2.0.0

Published

Role | Name | Email | Slack ---- | ---- | ----- | ----- *Product Owner* | Frances Haugen | [[email protected]](mailto:[email protected]) | [@frances] *Maintainer* | Geoff Kinder | [[email protected]](mailto:[email protected]) | [@geoff]

Downloads

10

Readme

redux-models

Role | Name | Email | Slack ---- | ---- | ----- | ----- Product Owner | Frances Haugen | [email protected] | [@frances] Maintainer | Geoff Kinder | [email protected] | [@geoff] Developer | Alice Wang | [email protected] | [@alicebot] Developer | Dan Isaza | [email protected] | [@dan] Developer | Mark Miyashita | [email protected] | [@mark]

Overview

Adds a redux data layer based on the schema defined in the gig.yaml. The generated redux data layer includes:

  • Actions
  • Action Creators
  • API (data fetching)
  • Reducers
  • Selectors

Usage

Specification

Name | Status | Description ---- | ------ | ----------- generateTests | true/false | Set to true if you would like generated tests to be created for you for the redux layer.

Dependencies

This module depends on these frontend modules:

  • create-react-app block, located here
  • react-base module, located here
  • redux-request module, located here

This module also integrates with the loopback-models module, located here, for generation of RESTful endpoints for each model. If it is not used, then your API will need to provide these RESTful endpoints.

To run the generated tests, you must also use the react-jest module located here.

Example Scenario: Generated Code

Gig.yaml (schema definition)

Models section of gig.yaml

...
models:
  - name: user
    properties:
      - name: id
        type: number
        id: true
      - name: email
        type: string
      - name: password
        type: string
        hidden: true
        obscured: true
 ...

Generated Users Reducer

import createReducer from './createReducer';
import utils from './utils';

import {
  USERS_REQUEST,
  USERS_OK,
  USERS_ERROR,
  USERS_RESET,
} from '../actions/users';

const initialState = {
  loading: false,
  request: undefined,
  data: {},
  error: undefined,
};

const handlers = {
  [USERS_REQUEST]: (state, { payload }) => ({
    ...state,
    loading: true,
    request: payload,
  }),
  [USERS_OK]: (state, { payload }) => ({
    ...state,
    loading: false,
    data: {
      ...state.data,
      ...utils.arrayToMap(payload.response),
    },
  }),
  [USERS_ERROR]: (state, { payload }) => ({
    ...state,
    loading: false,
    error: payload.error,
  }),
  [USERS_RESET]: () => ({
    ...initialState,
  }),
};

export default createReducer(handlers, initialState);

Generated Users Actions (actions/users.js)

  • USERS_REQUEST: dispatched before a request to track params of the request and to denote a request is in flight
  • USERS_OK: dispatched when a request is successful to track the response and denote that a request is complete
  • USERS_ERROR: dispatched when a request has errored to track the error response
  • USERS_RESET: dispatched to reset data back to initial values
...
/* eslint-disable no-unused-vars */
export const USERS_REQUEST = 'USERS_REQUEST';
export const USERS_OK = 'USERS_OK';
export const USERS_ERROR = 'USERS_ERROR';
export const USERS_RESET = 'USERS_RESET';

const usersRequest = value => ({
  type: USERS_REQUEST,
  payload: value,
});

const usersOk = value => ({
  type: USERS_OK,
  payload: value,
});

const usersError = value => ({
  type: USERS_ERROR,
  payload: value,
});

const usersReset = value => ({
  type: USERS_RESET,
  payload: value,
});
/* eslint-enable */
...

Generated Users Action Creators (actions/users.js)

All action creators except for reset follow the pattern:

  • dispatch USERS_REQUEST initially to track the start of the request
  • dispatch USERS_OK upon a successful response
  • dispatch USERS_ERROR if the response contains an error

Reset action creators do not send a request and only dispatch USERS_RESET.

Generated Action Creators:

  • fetchUsers: fetches multiple users
  • fetchUser: fetches a single user, by id
  • createUser: creates a single user
  • updateUser: updates a single user
  • deleteUser: deletes a single user
  • resetUsers: resets the user data in global state to initial values
...
const fetchUsers = (args = {}) => (dispatch, getState) => {
  const state = getState();
  const token = getAuthToken(state);

  args.token = token;

  if (!args.include) {
    args.include = [];
  }

  const query = args.query || {};
  delete args.query;

  const include = Object.keys(query);
  args.include = args.include.concat(include);

  dispatch(usersRequest(args));

  return UsersApi.fetchUsers(args)
    .then((response) => {
      const requests = fetchNestedData({
        list: response,
        dispatch,
        token,
        query,
        actionCreatorMap,
      });

      const out = {
        request: args,
        response,
      };

      requests.push(dispatch(usersOk(out)));

      return Promise.all(requests);
    })
    .catch((error) => {
      const out = {
        request: args,
        error,
      };

      return dispatch(usersError(out));
    });
};

const fetchUser = (args = {}) => (dispatch) => {
  args.where = args.where || {};
  args.where = {
    ...args.where,
    id: {
      inq: [args.id],
    },
  };

  delete args.id;

  return dispatch(fetchUsers(args));
};

const createUser = (args = {}) => (dispatch, getState) => {
  const state = getState();
  const token = getAuthToken(state);

  args.token = token;

  dispatch(usersRequest(args));

  return UsersApi.createUser(args)
    .then((response) => {
      const out = {
        request: args,
        response,
      };

      return dispatch(usersOk(out));
    })
    .catch((error) => {
      const out = {
        request: args,
        error,
      };

      return dispatch(usersError(out));
    });
};

const updateUser = (args = {}) => (dispatch, getState) => {
  const state = getState();
  const token = getAuthToken(state);

  args.token = token;

  dispatch(usersRequest(args));

  return UsersApi.updateUser(args)
    .then((response) => {
      const out = {
        request: args,
        response,
      };

      return dispatch(usersOk(out));
    })
    .catch((error) => {
      const out = {
        request: args,
        error,
      };

      return dispatch(usersError(out));
    });
};

const deleteUser = (args = {}) => (dispatch, getState) => {
  const state = getState();
  const token = getAuthToken(state);

  args.token = token;

  dispatch(usersRequest(args));

  return UsersApi.deleteUser(args)
    .then((response) => {
      const out = {
        request: args,
        response,
      };

      return dispatch(usersOk(out));
    })
    .catch((error) => {
      const out = {
        request: args,
        error,
      };

      return dispatch(usersError(out));
    });
};

const resetUsers = (args = {}) => (dispatch) =>
  Promise.resolve(dispatch(usersReset(args)));
...

Generated Users API (api/users.js)

import requestCreator, { Loopback } from './request';

const request = requestCreator(Loopback);
const url = `${window.location.origin}/api/users`;

const fetchUsers = ({
  token,
  where,
  order,
  limit,
  skip,
  include,
}) =>
  request().withAuth(token)
    .where(where)
    .order(order)
    .limit(limit)
    .skip(skip)
    .include(include)
    .get(url)
    .then((response) => response.data);

const createUser = ({ token, ...params }) =>
  request().withAuth(token).post(url, params)
    .then((response) => response.data);

const updateUser = ({ token, ...params }) =>
  request().withAuth(token).patch(url, params)
    .then((response) => response.data);

const deleteUser = ({ token, id }) =>
  request().withAuth(token).delete(`${url}/${id}`)
    .then((response) => response.data);
...

Generated Users Selectors (selectors/users.js)

import utils from './utils';

const model = 'users';

const getUsers = (state, { ids } = {}) =>
  utils.getList({ state, model, ids });

const getUser = (state, key) =>
  utils.getItem({ state, model, key });

Example Scenario: Fetching Nested Data

Gig.yaml (schema definition)

Models section of gig.yaml

...
models:
  - name: user
    properties:
      - name: id
        type: number
        id: true
      - name: email
        type: string
      - name: password
        type: string
        hidden: true
        obscured: true
    relations:
      - name: platform
        type: belongsTo
        model: platform
        foreignKey: platformId
  - name: platform
    properties:
      - name: id
        type: number
        id: true
      - name: name
        type: string
        required: true
        min: 2
        max: 50
    relations:
      - name: user
        type: hasOne
        model: user
        foreignKey: userId
 ...

Users Fetch Action Creator (actions/users.js)

To fetch a user's associated platform data, pass a custom query param to the fetchUsers action creator.

const query = {
  platform: {},
};

fetchUsers({ query });

actions/users.js

A mapping is generated between associated models and their fetch action creator

const actionCreatorMap = {
  platforms: fetchPlatforms,
};

...

const fetchUsers = (args = {}) => (dispatch, getState) => {

Include filters are defined based on the query param

  if (!args.include) {
    args.include = [];
  }

  const query = args.query || {};
  delete args.query;

  const include = Object.keys(query);
  args.include = args.include.concat(include);

  /* Nested Data
   *  - platform [platform]
   */

  dispatch(usersRequest(args));

  return UsersApi.fetchUsers(args)
    .then((response) => {

This utilty call returns the requests to fetch the associated data in the query param

      const requests = fetchNestedData({
        list: response,
        dispatch,
        token,
        query,
        actionCreatorMap,
      });

      const out = {
        request: args,
        response,
      };

      requests.push(dispatch(usersOk(out)));

      return Promise.all(requests);
    })
    .catch((error) => {
      const out = {
        request: args,
        error,
      };

      return dispatch(usersError(out));
    });
};