{"id":20145140,"url":"https://github.com/howard-e/node-pg-crud","last_synced_at":"2026-05-04T23:39:53.082Z","repository":{"id":55248550,"uuid":"326072350","full_name":"howard-e/node-pg-crud","owner":"howard-e","description":"Lightweight easy-to-use PostgreSQL CRUD handlers + utilities.","archived":false,"fork":false,"pushed_at":"2021-02-01T15:43:22.000Z","size":572,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-09T12:15:59.716Z","etag":null,"topics":["api","crud","easy","lightweight","node","node-pg","pg","postgres","postgresql","postgresql-crud-handlers","postgresql-database","wrapper"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/node-pg-crud","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/howard-e.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-01-01T23:17:51.000Z","updated_at":"2021-02-17T00:52:28.000Z","dependencies_parsed_at":"2022-08-14T17:50:57.922Z","dependency_job_id":null,"html_url":"https://github.com/howard-e/node-pg-crud","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/howard-e/node-pg-crud","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howard-e%2Fnode-pg-crud","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howard-e%2Fnode-pg-crud/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howard-e%2Fnode-pg-crud/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howard-e%2Fnode-pg-crud/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/howard-e","download_url":"https://codeload.github.com/howard-e/node-pg-crud/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howard-e%2Fnode-pg-crud/sbom","scorecard":{"id":469831,"data":{"date":"2025-08-11","repo":{"name":"github.com/howard-e/node-pg-crud","commit":"c2984790b229aa6029c9e05696b9912472a8b631"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/npm-publish.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npm-publish.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/howard-e/node-pg-crud/npm-publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/npm-publish.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/howard-e/node-pg-crud/npm-publish.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/npm-publish.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/howard-e/node-pg-crud/npm-publish.yml/main?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/npm-publish.yml:16","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"36 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-ww39-953v-wcq6","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-qgmg-gppg-76g5","Warn: Project is vulnerable to: GHSA-xx4c-jj58-r7x6","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T13:34:54.319Z","repository_id":55248550,"created_at":"2025-08-19T13:34:54.319Z","updated_at":"2025-08-19T13:34:54.319Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32629537,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","crud","easy","lightweight","node","node-pg","pg","postgres","postgresql","postgresql-crud-handlers","postgresql-database","wrapper"],"created_at":"2024-11-13T22:14:29.245Z","updated_at":"2026-05-04T23:39:53.061Z","avatar_url":"https://github.com/howard-e.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# node-pg-crud\n\n[![Build Status](https://travis-ci.com/howard-e/node-pg-crud.svg?branch=main)](https://travis-ci.com/howard-e/node-pg-crud)\n[![Dependency Status](https://david-dm.org/howard-e/node-pg-crud.svg?branch=main)](https://david-dm.org/howard-e/node-pg-crud?branch=main)\n\nLightweight easy-to-use PostgreSQL CRUD handlers + utilities built. [node-postgres](https://node-postgres.com) is\nrequired.\n\n## Installation\n\n```bash\n$ npm install node-pg-crud\n```\n\n## Usage\n\n```javascript\nconst CRUDBuilder = require('node-pg-crud')\n```\n\n### CRUDBuilder\n\nThe `CRUDBuilder` object exposes a builder method to create a PostgreSQL Model, `CRUDModel` to be used to call typical\nCRUD Methods (`get`, `getById`, `getByQuery`, `insert`, `put`, `delete`).\n\n#### CRUDBuilder.setLevel(limit: number | 'all')\n\nSets the default limit for the number of results when the `CRUDModel.get()` method is called.\n\n#### CRUDBuilder.build()\n\nReturns `CRUDModel` Type.\n\n### CRUDModel\n\n```javascript\nconst CRUDModel = new CRUDBuilder(\n    POOL, // Pool or Client instance from 'pg' library\n    MODEL_NAME, // Name of CRUDModel instance (typically the name of the table)\n    TABLE_NAME, // Name of table in PostgreSQL database\n    DEFAULT_SELECT_QUERY, // Default query to be used when querying data if no custom query is specified\n    DEFAULT_SELECT_WHERE_QUERY, // Default filter to be used when querying data if no custom where clause is specified\n    TABLE_KEY // Optional key to set when aliasing main referenced table, eg. 'select * from users u' where 'u' is the table key\n).build()\n```\n\n#### CRUDModel.get(query: {search, customSearch, filter}, pagination: {page, limit, sort}, searchFields, selectQueryText)\n\nReturns Promise for a dataset matching the query requested with the following result structure.\n\n###### Example:\n\n```javascript\n{\n   total, // total amount of results for specific query\n   page, // current page\n   pageSize, // max number of items to be returned in data; can be 'all' or a number\n   results, // number of items returned in data\n   pages, // amount of pages given query\n   data: [ // results\n      {id: ..., ...},\n      {},\n      ...\n   ]\n}\n```\n\n##### query.search: String\n\nThe search parameter(s).\n\n##### query.customSearch: String\n\nA custom search query which is passed directly to the database.\n\n##### query.filter: Object\n\nSearch filter options to be combined with the other filter options, and the search query where applicable.\n\n###### Example:\n\n```javascript \n{ status: 'active', enabled: true }\n```\n\n##### pagination.page: Integer\n\nThe requested page.\n\n##### pagination.sort: Object\n\nThe different attributes which can be used to sort the results.\n\n###### Example:\n\n```javascript \n{ id: 'asc', first_name: 'desc' }\n```\n\n##### searchFields: [String]\n\nField names used to define what the search value is used to search through.\n\n##### selectQueryText: String\n\nUsed to define what is being queried and to also define the structure with which the data is returned for the result's\nobjects.\n\n\u003cbr\u003e\n\n#### CRUDModel.getById(id, selectQueryText, whereQueryText)\n\nReturns Promise for a single object returned from the database.\n\n##### id: String | Integer\n\nObject ID being referenced.\n\n##### selectQueryText: String\n\nUsed to define what is being queried and to also define the structure with which the data is returned for the result's\nobjects.\n\n##### whereQueryText: String\n\nUsed to define a custom `where` clause.\n\n\u003cbr\u003e\n\n#### CRUDModel.getByQuery(queryData, selectQueryText, returnAll)\n\nReturns Promise for a single or all matching objects from the table based on a constructed query.\n\n##### queryData: [Any]\n\nUsed to define the keys and variables being used to query.\n\n###### Example:\n\n```javascript\n[{key: 'name', value: nameVariable}, {status: true, value: statusVariable}]\n```\n\n##### selectQueryText: String\n\nUsed to define what is being queried and to also define the structure with which the data is returned for the result's\nobjects.\n\n##### returnAll: Boolean\n\nUsed to define whether the data returned is a single option or multiple.\n\n\u003cbr\u003e\n\n#### CRUDModel.insert(queryText, values)\n\nReturns Promise for the object that was inserted.\n\n##### queryText: String\n\nDefines the structure with which the data is inserted.\n\n##### values: [Any]\n\nDefines the values for the object to be inserted.\n\n\u003cbr\u003e\n\n#### CRUDModel.update(id, queryText, values)\n\nReturns Promise for the updated object.\n\n##### id: String | Integer\n\nObject ID being referenced.\n\n##### queryText: String\n\nDefines the query text for the data being updated.\n\n##### values: [Any]\n\nDefines the values for the object to be updated.\n\n\u003cbr\u003e\n\n#### CRUDModel.remove(id, queryText, values)\n\nReturns Promise for the updated object.\n\n##### id: String | Integer\n\nObject ID being referenced.\n\n##### queryText: String\n\nDefines the query text for the data being removed.\n\n##### values: [Any]\n\nDefines the values for the object to be removed.\n\n## Examples\n\n### Model\n\n```javascript\nconst CRUDBuilder = require('node-pg-crud').default\nconst { buildValuesEntries, buildUpdateEntries } = require('node-pg-crud')\n\nconst TABLES = require('../tables')\nconst { pool } = require('../../loaders/postgresql')\n\nconst MODEL_NAME = 'User'\nconst TABLE_NAME = TABLES.USERS\nconst TABLE_KEY = 'u'\n\nconst DEFAULT_SELECT_QUERY = `\n${TABLE_KEY}.id,\n${TABLE_KEY}.first_name,\n${TABLE_KEY}.last_name,\n${TABLE_KEY}.email\nfrom ${TABLE_NAME} ${TABLE_KEY}\n`\nconst DEFAULT_SELECT_WHERE_QUERY = `where ${TABLE_KEY}.id = $1 limit 1`\n\n// create instance of PG CRUD Model\nconst CRUD = new CRUDBuilder(pool, MODEL_NAME, TABLE_NAME, DEFAULT_SELECT_QUERY, DEFAULT_SELECT_WHERE_QUERY, TABLE_KEY).build()\n\nconst get = (query = {}, pagination = {}) =\u003e {\n    // use search \u0026 filter to create WHERE clause; search to do a text search across multiple columns, filter expects a where clause on a particular column\n    const searchFields = [ // single and concatenated columns to search through with search parameter\n        `${TABLE_KEY}.first_name || ' ' || ${TABLE_KEY}.last_name`,\n        `${TABLE_KEY}.email`\n    ]\n    return CRUD.get(query, pagination, searchFields, DEFAULT_SELECT_QUERY)\n}\n\nconst getById = id =\u003e CRUD.getById(id, DEFAULT_SELECT_QUERY, DEFAULT_SELECT_WHERE_QUERY)\n\nconst insert = ({ first_name, last_name, email }) =\u003e {\n    const values = [first_name, last_name, email]\n    const valuesText = buildValuesEntries(values)\n    const queryText = `insert into ${TABLE_NAME} (first_name, last_name, email) VALUES (${valuesText}) returning id`\n\n    return CRUD.insert(queryText, values)\n}\n\nconst update = async (id, { first_name, last_name, email }) =\u003e {\n    const updateParams = {\n        first_name,\n        last_name,\n        email\n    }\n\n    const { updateSetQueryText, updateValues } = buildUpdateEntries(updateParams)\n    if (!updateSetQueryText) throw Error({\n        id: `${MODEL_NAME.toLowerCase()}.update.error.no.input`,\n        message: `Failed to update ${MODEL_NAME}. No update values found.`,\n    })\n\n    const values = [id, ...updateValues]\n    const queryText = `update ${TABLE_NAME} ${updateSetQueryText} where id = $1`\n\n    return CRUD.update(id, queryText, values)\n}\n\nconst remove = id =\u003e {\n    const values = [id]\n    const queryText = `delete from ${TABLE_NAME} where id = $1`\n\n    return CRUD.remove(id, queryText, values)\n}\n\nmodule.exports = {\n    get,\n    getById,\n    insert,\n    update,\n    remove\n}\n```\n\n### Route\n\n```javascript\nconst express = require('express')\nconst httpStatus = require('http-status-codes')\nconst { UserModel } = require('../../models')\nconst { validate, validateRules } = require('./validator')\n\nconst router = express.Router()\n\nrouter.get('/', validateRules('getUsers'), validate, async (req, res) =\u003e {\n    const {search, filter} = req.query\n    const {page, limit, sort} = req.query\n\n    try {\n        const result = await UserModel.get({ search, filter }, { page, limit, sort })\n        res.send(result)\n    } catch (error) {\n        // log error\n        return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })\n    }\n})\n\nrouter.get('/:id', validateRules('getUserById'), validate, async (req, res) =\u003e {\n    const {id} = req.params\n\n    try {\n        const result = await UserModel.getById(id)\n        res.send(result)\n    } catch (error) {\n        // log error\n        return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })\n    }\n})\n\nrouter.post('/', validateRules('createUser'), async (req, res) =\u003e {\n    const params = req.body\n\n    try {\n        const result = await UserModel.insert(params)\n        res.send(result)\n    } catch (error) {\n        // log error\n        return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })\n    }\n})\n\nrouter.put('/:id', validateRules('updateUser'), async (req, res) =\u003e {\n    const { id } = req.params\n    const params = req.body\n\n    try {\n        const result = await UserModel.update(id, params)\n        res.send(result)\n    } catch (error) {\n        // log error\n        return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })\n    }\n})\n\nrouter.delete('/:id', validateRules('deleteUser'), async (req, res) =\u003e {\n    const { id } = req.params\n\n    try {\n        const result = await UserModel.remove(id)\n        res.status(httpStatus.NO_CONTENT).send()\n    } catch (error) {\n        // log error\n        return res.status(httpStatus.SERVICE_UNAVAILABLE).send({ error: error.message })\n    }\n})\n\nmodule.exports = router\n```\n\n## Running Locally\n\n1. `git clone https://github.com/howard-e/node-pg-crud.git`\n\n### Build\n\n1. `cd node-pg-crud`\n1. `npm install`\n1. `npm run build`\n\n### Example Project\n\n1. `cd example/scrips`\n1. Run `./db-populate-local.sh` to populate a PostgreSQL Database. (This script assumes a PostgreSQL database is running\n   locally on PORT: `5432`, with the username: `admin`, password: `Passw0rd1` and a database called `database`)\n1. `cd ..`\n1. Create a `.env` file with the structure shown in the `.env.example` file. `POSTGRES_CONNECTION_STRING` MUST BE SET.\n1. `npm install`\n1. `npm start`\n1. The application should now be running locally on PORT `4040` by default. This can be adjusted by overwriting\n   the `PORT` variable in the `.env` file.\n\n## Why Use node-pg-crud?\n\n**Because it's easy to use.**\n\n## License\n\n[**Apache 2.0**](https://opensource.org/licenses/Apache-2.0)\n\n## TODO\n\n- [x] Provide Usage Instructions\n- [x] Provide Documentation\n- [x] Provide Example Project\n- [x] Provide Example Project Documentation\n- [x] Provide \"Why Use This?\" Section\n- [ ] Add Tests\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoward-e%2Fnode-pg-crud","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhoward-e%2Fnode-pg-crud","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhoward-e%2Fnode-pg-crud/lists"}