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 🙏

© 2024 – Pkg Stats / Ryan Hefner

node-pg-crud

v1.1.1

Published

Easy-to-use PostgreSQL CRUD Handlers + Utilities

Downloads

25

Readme

node-pg-crud

Build Status Dependency Status

Lightweight easy-to-use PostgreSQL CRUD handlers + utilities built. node-postgres is required.

Installation

$ npm install node-pg-crud

Usage

const CRUDBuilder = require('node-pg-crud')

CRUDBuilder

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).

CRUDBuilder.setLevel(limit: number | 'all')

Sets the default limit for the number of results when the CRUDModel.get() method is called.

CRUDBuilder.build()

Returns CRUDModel Type.

CRUDModel

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.

Example:
{
   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: ..., ...},
      {},
      ...
   ]
}
query.search: String

The search parameter(s).

query.customSearch: String

A custom search query which is passed directly to the database.

query.filter: Object

Search filter options to be combined with the other filter options, and the search query where applicable.

Example:
{ status: 'active', enabled: true }
pagination.page: Integer

The requested page.

pagination.sort: Object

The different attributes which can be used to sort the results.

Example:
{ id: 'asc', first_name: 'desc' }
searchFields: [String]

Field names used to define what the search value is used to search through.

selectQueryText: String

Used to define what is being queried and to also define the structure with which the data is returned for the result's objects.

CRUDModel.getById(id, selectQueryText, whereQueryText)

Returns Promise for a single object returned from the database.

id: String | Integer

Object ID being referenced.

selectQueryText: String

Used to define what is being queried and to also define the structure with which the data is returned for the result's objects.

whereQueryText: String

Used to define a custom where clause.

CRUDModel.getByQuery(queryData, selectQueryText, returnAll)

Returns Promise for a single or all matching objects from the table based on a constructed query.

queryData: [Any]

Used to define the keys and variables being used to query.

Example:
[{key: 'name', value: nameVariable}, {status: true, value: statusVariable}]
selectQueryText: String

Used to define what is being queried and to also define the structure with which the data is returned for the result's objects.

returnAll: Boolean

Used to define whether the data returned is a single option or multiple.

CRUDModel.insert(queryText, values)

Returns Promise for the object that was inserted.

queryText: String

Defines the structure with which the data is inserted.

values: [Any]

Defines the values for the object to be inserted.

CRUDModel.update(id, queryText, values)

Returns Promise for the updated object.

id: String | Integer

Object ID being referenced.

queryText: String

Defines the query text for the data being updated.

values: [Any]

Defines the values for the object to be updated.

CRUDModel.remove(id, queryText, values)

Returns Promise for the updated object.

id: String | Integer

Object ID being referenced.

queryText: String

Defines the query text for the data being removed.

values: [Any]

Defines the values for the object to be removed.

Examples

Model

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
}

Route

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

Running Locally

  1. git clone https://github.com/howard-e/node-pg-crud.git

Build

  1. cd node-pg-crud
  2. npm install
  3. npm run build

Example Project

  1. cd example/scrips
  2. 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 called database)
  3. cd ..
  4. Create a .env file with the structure shown in the .env.example file. POSTGRES_CONNECTION_STRING MUST BE SET.
  5. npm install
  6. npm start
  7. The application should now be running locally on PORT 4040 by default. This can be adjusted by overwriting the PORT variable in the .env file.

Why Use node-pg-crud?

Because it's easy to use.

License

Apache 2.0

TODO

  • [x] Provide Usage Instructions
  • [x] Provide Documentation
  • [x] Provide Example Project
  • [x] Provide Example Project Documentation
  • [x] Provide "Why Use This?" Section
  • [ ] Add Tests