another-express-crud
TypeScript icon, indicating that this package has built-in type declarations

1.3.0 • Public • Published

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 :

operation route
create POST /api/user
read GET /api/user
read by id GET /api/user/:id
update PUT /api/user/:id
update PATCH /api/user/:id
delete DELETE /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 :

property type description
create string policy used for create operations
read string policy used for read operations
update string policy used for update operations
delete string policy used for delete operations
isAuthenticated (CrudOptions) => boolean function to determine if the request is made by an authenticated user
isOwner (CrudOptions) => boolean function to determine if a user is the owner of the ressource
isAdmin (CrudOptions) => boolean function to determine if a user has access to all contents
isDisabled boolean disable 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

Readme

Keywords

none

Package Sidebar

Install

npm i another-express-crud

Weekly Downloads

0

Version

1.3.0

License

MIT

Unpacked Size

54.8 kB

Total Files

28

Last publish

Collaborators

  • chipp972