0.8.1 • Published 7 years ago

redux-crud-async v0.8.1

Weekly downloads
3
License
GPL-3.0
Repository
github
Last release
7 years ago

redux-crud-async

Build Status

redux-crud-async will create CRUD async actions and states automatically, just for you. The configuration is minimalist.

It currently uses axios or sails.io websocket (custom socket.io) for XHR. It allows you to use a REST API with authentication with a Bearer Token. In a near future, I will implement the possibility to create random actions like sign_in, sign_out or tranformThisLeadInGold Redux-crud-async is built against 150+ tests. Unfortunately this does not mean that redux-crud-async is bug free, please send issues if you find one !

Table of Contents

  1. Setup
  2. Conventions a. Routes b. Authentication c. Socket
  3. Configuration
  4. Actions a. Names b. Additionnal Actions
  5. States (Reducers)
  6. Todo
  7. Change Log

Setup

NPM

you can find it on NPM

npm i -S redux-crud-async

ActionTypes

// redux/actionTypes/index.js
  var reduxCrudAsync = require('redux-crud-async')
  var crud = new reduxCrudAsync()

  module.exports = {
    ...crud.primaryActionTypesFor('channel'),
    ...crud.primaryActionTypesFor('tag'),

    ...crud.associationActionTypesFor('channel', 'tag')
  }

Actions

// redux/actions/index.js
  var reduxCrudAsync = require('redux-crud-async')

  var hostConfig = {
    host            : 'https://my-api.com',
    prefix          : 'v1', // Optional - default to ''
    pluralizeModels : false, // Optional - default to true

  }

  var crud = new reduxCrudAsync(hostConfig) // hostConfig is mandatory for actionsGenerator

  module.exports = {
    ...crud.primaryActionsFor('channel'),
    ...crud.primaryActionsFor('tag'),

    ...crud.associationActionsFor('channel', 'tag')
  }

Reducers

// redux/reducers/index.js
  var reduxCrudAsync = require('redux-crud-async')
  var crud = new reduxCrudAsync()

  module.exports = {
    ...crud.primaryReducerFor('user'),
    ...crud.primaryReducerFor('pet'),

    ...crud.associationReducerFor('user', 'pet')
  }

EXEMPLE USAGE Click here to see how much it is easy to use this module


Conventions

General

It might be obvious but all models returned by your database need to have an unique id.

Routes

This module is built to work with sails.js blueprints routes using sails-rest-api conventions. It differentiate singular and plural model name : findUser !== findUsers IMPORTANT ! As sails.js, this module uses pluralize module which pluralize words grammaticaly.

some exemples : channel -> channels person -> people coach -> coaches

By default, all your routes will be pluralized, Person model will have the following :

state : person - a single person people - all your "persons"

actions : findPerson -> will hit GET /people/:id findPeople -> will hit GET /people

You can unpluralize your urls by setting it in the config

Authentication

redux-crud-async uses a Bearer Token to authenticate requests. It is store in window.localStorage. Every request which need authentication is sent with the token in the header following this convention :

Token is set in Authorization header as :

// Config sent to axios or socket.io
{
    headers : {
      Authorization : 'Bearer '+ JWT_Token_from_localStorage
    }
}

Socket

We use the io.socket.request to communicate to the server. Make sure that your server can use it if you don't use sails.js on server side.


##Configuration

Config file

NameTypeDefaultDescription
hostStringnullYour API host - must be defined
prefixStringnullA prefix for all your routes. Don't add the slash / on the prefix it will be automatically added.
pluralizeModelsBooleantrueUse pluralized model names in url. This has no affect on action names.
socketBooleanfalseUse socket.io for actions
localStorageNameString"JWT"The key for retrieving your JWT Token from window.localStorage
headerContentString"Bearer {{JWT}}"The format of your header content The format is affected by localStorageName
headerFormatString"Authorization"The format of your header authorization key
apiSpecsObjectnullRoutes where you want to use the JWT_Token
responseSchemasObject{http: {success : 'data', error : 'data'}, socket : {success : null, error : null}}schemas of your API's responses. Where the data can be found in your response object

The format of headerContent is affected by localStorageName if you change the default value

{
  localStorageName : 'myJWT',
  headerContent : 'MyContent {{myJWT}}'
}

For apiSpecs you just have to set the unpluralized modelName or primarymodelAssociatedmodels with an auth property inside which contains an array of actions to authenticate. Just follow conventions given above.

{
  host            : 'http://your-api-host',
  prefix          : 'my-prefix',
  pluralizeModels : false,
  socket          : true,
  localStorageName: 'MyJWT',
  headerContent   : 'AuthBearer {{MyJWT}}',
  headerFormat    : 'AuthBearerHeaderKey'
  apiSpecs : {

    coach : {
      // All the following actions will be beared with a JWT
      auth : ['findCoaches', 'createCoach', 'updateCoach']
    },

    coachComments : {
      auth : ['addCommentToCoach', 'removeCommentFromCoach']
    }
  }
}

#### Results findPerson -> will hit GET http://your-api-host/my-prefix/people/:id findPeople -> will hit GET http://your-api-host/my-prefix/people

With pluralizeModels : false findPerson -> will hit GET http://your-api-host/my-prefix/person/:id findPeople -> will hit GET http://your-api-host/my-prefix/person


Actions

Names

There is a maximum of 11 actions for a given model which will be automatically understood by reducers. 3 status actions are dispatched for every redux-crud-async action : START, SUCCESS and ERROR. They are automatically understood by reducers. eg. primary model = channel, associated model = tag

3 primary

actionNameurlparamstatestate Type
findChannelGET channels/:idStringchannelObject
findChannelsGET channels?requestStringchannels[Object]
createChannelPOST channelsObject OR FormDatachannelObject
updateChannelPUT channelsObjectchannelObject
destroyChannelDELETE channelsObjectchannelObject

You can submit a FormData to create but the FormData is transmitted as is and model will not be appended to the state. If you need the model to be appended to the state, use a javascript object instead of a FormData. FormData can be used to send specific CRUD actions like uploading an image

3 association

actionNameurlparametersstatestate TypeComment
findChannelTagsGET channels/:channelId/tags/:tagId?String, StringchannelTags[Object]
addTagToChannelPOST channels/:channelId/tags/:tagId?String, String OR ObjectchannelTagObjectif no tag id is set you must give an object to this function
createChannelPOST channelsString, StringchannelTagObject

#### Additionnal actions

An additionnal action exists which empties reducers. Dispatch manually this action to empty your reducers.

{
  type : 'EMPTY_CHANNEL'
}
{
  type : 'EMPTY_CHANNELS'
}
{
  type : 'EMPTY_PRIMARY_ASSOCIATED_MODELS'
}

Have a look in primaryActionGenerator and associationActionGenerator and Actions Details for more precision about dispatched actions.

States (Reducers)

Reducers return the following states usable in your components

statetype
channelObject
isFindingChannelBoolean
channels[Object]
isFindingChannelsBoolean
channelTags[Object]
isFindingChannelTagsBoolean

See reducers :


## TODO

  • make API endpoints editables
  • add cache for get requests
  • cache timeout by route
  • remove arrow functions in tests
  • comment code
  • find a way to test FormData in createModel
  • add single actions (signup, signin)
  • add coverage
  • move associated record uuid generation from associationActions dispatch to reducer
  • state immutability
  • add tests for caching
  • add some headers tests

## Change Log

0.7.0
  • removed second parameter from update action
0.6.3
  • update and delete primary actions
  • fix bug when building with webpack - io was undefined
  • fix silly bugs and add tests for them
0.5.0
  • API expectation editables
0.4.0
  • add socket.io support through the window.io variable
  • more tests
  • rewrite of the utils/xhr/* module
  • doc changes
  • added EMPTY_CHANNELS action in reducers
0.8.1

7 years ago

0.8.0

7 years ago

0.7.7

7 years ago

0.7.6

7 years ago

0.7.5

7 years ago

0.7.4

7 years ago

0.7.3

7 years ago

0.7.2

7 years ago

0.7.1

7 years ago

0.7.0

7 years ago

0.6.3

7 years ago

0.6.2

7 years ago

0.6.1

7 years ago

0.6.0

7 years ago

0.5.0

7 years ago

0.4.2

8 years ago

0.4.1

8 years ago

0.4.0

8 years ago

0.3.0

8 years ago

0.2.3

8 years ago

0.2.2

8 years ago

0.2.1

8 years ago

0.2.0

8 years ago

0.1.5

8 years ago

0.1.4

8 years ago

0.1.3

8 years ago

0.1.2

8 years ago

0.1.1

8 years ago

0.1.0

8 years ago

0.0.8

8 years ago

0.0.7

8 years ago

0.0.6

8 years ago

0.0.4

8 years ago

0.0.3

8 years ago

0.0.2

8 years ago

0.0.1

8 years ago