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 🙏

© 2026 – Pkg Stats / Ryan Hefner

another-express-crud

v1.3.0

Published

Easily create an express CRUD router

Readme

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