Lightweight easy-to-use PostgreSQL CRUD handlers + utilities built. node-postgres is required.
$ npm install node-pg-crud
const CRUDBuilder = require('node-pg-crud')
The CRUDBuilder
object exposes a builder method to create a PostgreSQL Model, CRUDModel
to be used to call typical
CRUD Methods (get
, getById
, getByQuery
, insert
, put
, delete
).
Sets the default limit for the number of results when the CRUDModel.get()
method is called.
Returns CRUDModel
Type.
const CRUDModel = new CRUDBuilder(
POOL, // Pool or Client instance from 'pg' library
MODEL_NAME, // Name of CRUDModel instance (typically the name of the table)
TABLE_NAME, // Name of table in PostgreSQL database
DEFAULT_SELECT_QUERY, // Default query to be used when querying data if no custom query is specified
DEFAULT_SELECT_WHERE_QUERY, // Default filter to be used when querying data if no custom where clause is specified
TABLE_KEY // Optional key to set when aliasing main referenced table, eg. 'select * from users u' where 'u' is the table key
).build()
CRUDModel.get(query: {search, customSearch, filter}, pagination: {page, limit, sort}, searchFields, selectQueryText)
Returns Promise for a dataset matching the query requested with the following result structure.
{
total, // total amount of results for specific query
page, // current page
pageSize, // max number of items to be returned in data; can be 'all' or a number
results, // number of items returned in data
pages, // amount of pages given query
data: [ // results
{id: ..., ...},
{},
...
]
}
The search parameter(s).
A custom search query which is passed directly to the database.
Search filter options to be combined with the other filter options, and the search query where applicable.
{ status: 'active', enabled: true }
The requested page.
The different attributes which can be used to sort the results.
{ id: 'asc', first_name: 'desc' }
Field names used to define what the search value is used to search through.
Used to define what is being queried and to also define the structure with which the data is returned for the result's objects.
Returns Promise for a single object returned from the database.
Object ID being referenced.
Used to define what is being queried and to also define the structure with which the data is returned for the result's objects.
Used to define a custom where
clause.
Returns Promise for a single or all matching objects from the table based on a constructed query.
Used to define the keys and variables being used to query.
[{key: 'name', value: nameVariable}, {status: true, value: statusVariable}]
Used to define what is being queried and to also define the structure with which the data is returned for the result's objects.
Used to define whether the data returned is a single option or multiple.
Returns Promise for the object that was inserted.
Defines the structure with which the data is inserted.
Defines the values for the object to be inserted.
Returns Promise for the updated object.
Object ID being referenced.
Defines the query text for the data being updated.
Defines the values for the object to be updated.
Returns Promise for the updated object.
Object ID being referenced.
Defines the query text for the data being removed.
Defines the values for the object to be removed.
const CRUDBuilder = require('node-pg-crud').default
const { buildValuesEntries, buildUpdateEntries } = require('node-pg-crud')
const TABLES = require('../tables')
const { pool } = require('../../loaders/postgresql')
const MODEL_NAME = 'User'
const TABLE_NAME = TABLES.USERS
const TABLE_KEY = 'u'
const DEFAULT_SELECT_QUERY = `
${TABLE_KEY}.id,
${TABLE_KEY}.first_name,
${TABLE_KEY}.last_name,
${TABLE_KEY}.email
from ${TABLE_NAME} ${TABLE_KEY}
`
const DEFAULT_SELECT_WHERE_QUERY = `where ${TABLE_KEY}.id = $1 limit 1`
// create instance of PG CRUD Model
const CRUD = new CRUDBuilder(pool, MODEL_NAME, TABLE_NAME, DEFAULT_SELECT_QUERY, DEFAULT_SELECT_WHERE_QUERY, TABLE_KEY).build()
const get = (query = {}, pagination = {}) => {
// use search & filter to create WHERE clause; search to do a text search across multiple columns, filter expects a where clause on a particular column
const searchFields = [ // single and concatenated columns to search through with search parameter
`${TABLE_KEY}.first_name || ' ' || ${TABLE_KEY}.last_name`,
`${TABLE_KEY}.email`
]
return CRUD.get(query, pagination, searchFields, DEFAULT_SELECT_QUERY)
}
const getById = id => CRUD.getById(id, DEFAULT_SELECT_QUERY, DEFAULT_SELECT_WHERE_QUERY)
const insert = ({ first_name, last_name, email }) => {
const values = [first_name, last_name, email]
const valuesText = buildValuesEntries(values)
const queryText = `insert into ${TABLE_NAME} (first_name, last_name, email) VALUES (${valuesText}) returning id`
return CRUD.insert(queryText, values)
}
const update = async (id, { first_name, last_name, email }) => {
const updateParams = {
first_name,
last_name,
email
}
const { updateSetQueryText, updateValues } = buildUpdateEntries(updateParams)
if (!updateSetQueryText) throw Error({
id: `${MODEL_NAME.toLowerCase()}.update.error.no.input`,
message: `Failed to update ${MODEL_NAME}. No update values found.`,
})
const values = [id, ...updateValues]
const queryText = `update ${TABLE_NAME} ${updateSetQueryText} where id = $1`
return CRUD.update(id, queryText, values)
}
const remove = id => {
const values = [id]
const queryText = `delete from ${TABLE_NAME} where id = $1`
return CRUD.remove(id, queryText, values)
}
module.exports = {
get,
getById,
insert,
update,
remove
}
const express = require('express')
const httpStatus = require('http-status-codes')
const { UserModel } = require('../../models')
const { validate, validateRules } = require('./validator')
const router = express.Router()
router.get('/', validateRules('getUsers'), validate, async (req, res) => {
const {search, filter} = req.query
const {page, limit, sort} = req.query
try {
const result = await UserModel.get({ search, filter }, { page, limit, sort })
res.send(result)
} catch (error) {
// log error
return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })
}
})
router.get('/:id', validateRules('getUserById'), validate, async (req, res) => {
const {id} = req.params
try {
const result = await UserModel.getById(id)
res.send(result)
} catch (error) {
// log error
return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })
}
})
router.post('/', validateRules('createUser'), async (req, res) => {
const params = req.body
try {
const result = await UserModel.insert(params)
res.send(result)
} catch (error) {
// log error
return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })
}
})
router.put('/:id', validateRules('updateUser'), async (req, res) => {
const { id } = req.params
const params = req.body
try {
const result = await UserModel.update(id, params)
res.send(result)
} catch (error) {
// log error
return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })
}
})
router.delete('/:id', validateRules('deleteUser'), async (req, res) => {
const { id } = req.params
try {
const result = await UserModel.remove(id)
res.status(httpStatus.NO_CONTENT).send()
} catch (error) {
// log error
return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })
}
})
module.exports = router
git clone https://github.com/howard-e/node-pg-crud.git
cd node-pg-crud
npm install
npm run build
cd example/scrips
- Run
./db-populate-local.sh
to populate a PostgreSQL Database. (This script assumes a PostgreSQL database is running locally on PORT:5432
, with the username:admin
, password:Passw0rd1
and a database calleddatabase
) cd ..
- Create a
.env
file with the structure shown in the.env.example
file.POSTGRES_CONNECTION_STRING
MUST BE SET. npm install
npm start
- The application should now be running locally on PORT
4040
by default. This can be adjusted by overwriting thePORT
variable in the.env
file.
Because it's easy to use.
- Provide Usage Instructions
- Provide Documentation
- Provide Example Project
- Provide Example Project Documentation
- Provide "Why Use This?" Section
- Add Tests