1.3.0 • Published 6 years ago

another-express-crud v1.3.0

Weekly downloads
3
License
MIT
Repository
github
Last release
6 years ago

another-express-crud

Let you avoid all the boilerplates to create a crud route

Installation

npm i --save another-express-crud

Example usage

import express from 'express';
import { crud } from 'another-express-crud';

const app = express();

type CrudData = {
  id?: string,
  data: any,
  user?: any,
  files?: any,
  fancyParam?: string
}

const getRequestData = (req) => ({
  id: req.params.id || (req.body && req.body._id),
  data: req.body || {},
  user: req.user,
  files: req.files,
  fancyParam: req.fancyParam
})

const operations = {
  create: (params: CrudData) => ...,
  read: (params: CrudData) => ...,
  update: (params: CrudData) => ...,
  delete: (params: CrudData) => ...,
}

const crudRoutes = crud({
  path: '/user',
  operations,
  getRequestData,
  policy: {
    update: 'owner',
    delete: 'owner'
  },
  hooks: {
    before: {
      create: (params: CrudData) => { success: true },
    },
    after: {
      update: (result, req) => { message: 'update done' },
    }
  }
});
app.use('/api', crudRoutes);

This resulting app is :

operationroute
createPOST /api/user
readGET /api/user
read by idGET /api/user/:id
updatePUT /api/user/:id
updatePATCH /api/user/:id
deleteDELETE /api/user/:id

Path

A string to provide a path prefix to the route. Default is '/'.

Request data

The parameter getRequestData is a function to get data provided by the express request that will be passed to most hooks and policy checks. It should be of the form :

type CrudOptions = {
  id: string,
  data: any,
  user: any,
  files: any
}

const getRequestData: (req: Request) => CrudOptions

Notes: No middleware is integrated to parse the body of the requests. You could use for example

import formData from 'express-form-data';
import bodyParser from 'body-parser';
import express from 'express';

const app = express();

// multi-part form data
app.use(formData.parse({ autoFiles: true }));
app.use(formData.format());
app.use(formData.stream());
app.use(formData.union());

// json body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

Operations

You should provide an object with at least theese 4 functions:

  • create
  • read
  • update
  • delete

All 4 functions should implement the interface : (CrudOptions) => Promise<any>

Note: If you want a good REST implementation you should differentiate the case when:

  • read receives id parameters (/test/id) to return only 1 result (if the result is undefined, the route will pass an error to the next middleware with message 'NotFound')
  • read receives query parameter (/test?name=john) to return an array of result

Note2: The result of the operation should be returned in the promise (an object or a list of object). If undefined is returned, an error with a message 'NotFound' will be passed to the next middleware.

Hooks

Before

All before hooks take an object CrudOptions in parameter and should return an object indicating if everything is fine and if it's not, the error associated to pass to the next middleware: { success: boolean, error?: Error }

After

All after middlewares take the result of the operation and the request object. They should return a new result or undefined to pass to the afterAll middleware or the response formatter. If the result is undefined the previous result will be used.

Policies

The optional policy object should contain :

propertytypedescription
createstringpolicy used for create operations
readstringpolicy used for read operations
updatestringpolicy used for update operations
deletestringpolicy used for delete operations
isAuthenticated(CrudOptions) => booleanfunction to determine if the request is made by an authenticated user
isOwner(CrudOptions) => booleanfunction to determine if a user is the owner of the ressource
isAdmin(CrudOptions) => booleanfunction to determine if a user has access to all contents
isDisabledbooleandisable all policies (if you need to disable policies with an environment variable for example)

All arguments are optional. Just specify what you need.

You can specify 4 types of policies :

  • guest: no permission needed to use the operation
  • user: only an authenticated user can access the operation
  • owner: only the owner of the ressource can access it
  • admin: the ressource is restricted to admin privilege

You can provide isAuthenticated, isOwner and isAdmin functions to customize when the access should be granted.

You can also

By default, all policies are guest if no policy is provided.

Note: By default, if the user object is not undefined, the permission of the request will be at least user (see Request data to know how to get user from request)

Todo

  • More Policy tests
  • Response formatter tests
  • Clearer README with more examples
1.3.0

6 years ago

1.2.0

6 years ago

1.1.2

6 years ago

1.1.1

6 years ago

1.1.0

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago