{"id":42724,"library":"express-crud-router","title":"express-crud-router","description":"A minimal Express.js middleware that automatically exposes CRUD (Create, Read, Update, Delete) routes compatible with React Admin's Simple Rest Data Provider. Version 8.1.0 is current, with a stable release cadence (major updates every few months). ORM-agnostic: works with any data source via connectors (e.g., Sequelize, Mongoose, Knex). Key differentiators: one line per resource, automatic route generation, built-in pagination with X-Total-Count header, and custom filter support. Ships TypeScript types. Peer dependency on Express ^4.0.0.","status":"active","version":"8.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/nicgirault/express-crud-router","tags":["javascript","react-admin","crud","express","typescript"],"install":[{"cmd":"npm install express-crud-router","lang":"bash","label":"npm"},{"cmd":"yarn add express-crud-router","lang":"bash","label":"yarn"},{"cmd":"pnpm add express-crud-router","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency; required to mount CRUD routes.","package":"express","optional":false}],"imports":[{"note":"Package exposes a default export (ESM). CJS require works but may not infer TypeScript types.","wrong":"const crud = require('express-crud-router')","symbol":"default","correct":"import crud from 'express-crud-router'"},{"note":"Type-only import for TypeScript users; CrudOptions defines the actions object shape.","wrong":"","symbol":"crud (type)","correct":"import type { CrudOptions } from 'express-crud-router'"},{"note":"Type for the request object passed to action handlers, contains filter, limit, offset, order.","wrong":"","symbol":"CrudRequest","correct":"import type { CrudRequest } from 'express-crud-router'"}],"quickstart":{"code":"import express from 'express';\nimport crud from 'express-crud-router';\n\nconst app = express();\napp.use(express.json());\n\n// In-memory data store for demonstration\nconst users = [\n  { id: 1, name: 'John' },\n  { id: 2, name: 'Jane' },\n];\n\napp.use(\n  crud('/admin/users', {\n    get: ({ filter, limit, offset, order }) => {\n      const filtered = users.filter(u =>\n        filter ? u.name.includes(filter.name) : true\n      );\n      const total = filtered.length;\n      const rows = filtered.slice(offset, offset + limit);\n      return { rows, total };\n    },\n    create: (body) => {\n      const id = users.length + 1;\n      users.push({ id, ...body });\n      return { id };\n    },\n    update: (id, body) => {\n      const index = users.findIndex(u => u.id === Number(id));\n      if (index === -1) throw new Error('Not found');\n      users[index] = { ...users[index], ...body };\n      return users[index];\n    },\n    destroy: (id) => {\n      const index = users.findIndex(u => u.id === Number(id));\n      if (index === -1) throw new Error('Not found');\n      users.splice(index, 1);\n      return { id };\n    },\n  })\n);\n\nconst PORT = process.env.PORT ?? 3000;\napp.listen(PORT, () => console.log(`Server running on port ${PORT}`));","lang":"typescript","description":"Demonstrates basic CRUD route setup with in-memory data store, including get, create, update, and destroy handlers."},"warnings":[{"fix":"Upgrade to >=8.0.0 or ensure your connector returns total in X-Total-Count header.","message":"Using Content-Range header instead of X-Total-Count may cause issues in Chrome/Safari. Always use X-Total-Count for pagination with React Admin.","severity":"gotcha","affected_versions":"<8.0.0"},{"fix":"Use X-Total-Count header; content-range is ignored unless Range request header is present.","message":"The older Content-Range header behavior is deprecated in favor of X-Total-Count.","severity":"deprecated","affected_versions":">=8.0.0"},{"fix":"Set destroy handler to null explicitly to disable; ensure other actions are not null inadvertently.","message":"Destroy action returning null disables the route; can cause confusion if you expect the route to exist but return 404.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Avoid returning same key from multiple filter handlers; merge manually if needed.","message":"Custom filters with conflicting keys will override each other; order is not guaranteed.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Use import syntax or enable ESM in your project (type: module in package.json).","message":"Package is ESM-only since v8; require() will fail if using older Node or CJS projects.","severity":"gotcha","affected_versions":">=8.0.0"}],"env_vars":null,"search_vec":"'4.0.0':85 '8.1.0':28 'admin':21,89 'agnost':43 'automat':10,61 'built':65 'built-in':64 'cadenc':35 'compat':18 'connector':50 'count':72 'creat':13 'crud':3,12,90 'current':30 'custom':75 'data':25,47 'delet':16 'depend':82 'differenti':56 'e.g':51 'everi':38 'expos':11 'express':2,84,91 'express-crud-rout':1 'express.js':7 'filter':76 'generat':63 'header':73 'javascript':86 'key':55 'knex':54 'line':58 'major':36 'middlewar':8 'minim':6 'mongoos':53 'month':40 'one':57 'orm':42 'orm-agnost':41 'pagin':67 'peer':81 'per':59 'provid':26 'react':20,88 'react-admin':87 'read':14 'releas':34 'resourc':60 'rest':24 'rout':17,62 'router':4 'sequel':52 'ship':78 'simpl':23 'sourc':48 'stabl':33 'support':77 'total':71 'type':80 'typescript':79,92 'updat':15,37 'version':27 'via':49 'work':44 'x':70 'x-total-count':69","created_at":"2026-06-05T16:56:21.289429+00:00","updated_at":"2026-06-05T16:56:21.289429+00:00","problems":[{"fix":"Run 'npm install express-crud-router' and ensure it's in dependencies.","cause":"Package not installed or not in node_modules.","error":"Cannot find module 'express-crud-router'"},{"fix":"Use 'import crud from \"express-crud-router\"' (default import) or 'const crud = require(\"express-crud-router\").default' if in CJS environment.","cause":"Using default import incorrectly or package is CJS parsed as ESM.","error":"TypeError: crud is not a function"},{"fix":"Ensure get handler returns an object with 'rows' (array) and 'total' (number).","cause":"Action handler for 'get' returns incorrect shape.","error":"Property 'rows' is missing in type 'Promise<{ total: number; rows: any[] }>'"},{"fix":"Check that app.use(crud(...)) is called with correct path and that actions object includes 'create' handler.","cause":"Destroy handler set to null preventing creation? Actually, create and destroy are separate; likely route not mounted correctly.","error":"Route not found for method POST /admin/users"}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":null,"cli_version":null,"type":"library","homepage":"https://github.com/nicgirault/express-crud-router#readme","github":"https://github.com/nicgirault/express-crud-router","docs":null,"changelog":null,"pypi":null,"npm":"express-crud-router","openapi_spec":null,"status_page":null,"smithery":null,"categories":["devops"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-05","next_check":"2026-09-03","install_tag":null}}