{"id":18470365,"url":"https://github.com/aliencreations/alien-node-pg-utils","last_synced_at":"2025-07-30T23:37:58.287Z","repository":{"id":57176100,"uuid":"101230591","full_name":"AlienCreations/alien-node-pg-utils","owner":"AlienCreations","description":"Helper functions for Postgresql on NodeJS","archived":false,"fork":false,"pushed_at":"2023-09-13T21:24:25.000Z","size":43,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-20T09:48:43.906Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlienCreations.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-08-23T22:36:24.000Z","updated_at":"2023-09-13T15:07:04.000Z","dependencies_parsed_at":"2024-11-06T10:13:50.018Z","dependency_job_id":"a3e848a8-61da-4ab1-a53f-1e0a96f57393","html_url":"https://github.com/AlienCreations/alien-node-pg-utils","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AlienCreations/alien-node-pg-utils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlienCreations%2Falien-node-pg-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlienCreations%2Falien-node-pg-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlienCreations%2Falien-node-pg-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlienCreations%2Falien-node-pg-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlienCreations","download_url":"https://codeload.github.com/AlienCreations/alien-node-pg-utils/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlienCreations%2Falien-node-pg-utils/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267960983,"owners_count":24172513,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-06T10:13:44.117Z","updated_at":"2025-07-30T23:37:58.262Z","avatar_url":"https://github.com/AlienCreations.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# alien-node-pg-utils\nHelper functions for Postgresql on NodeJS. The functions are pure and curried with Ramda.\n\n[![Build Status](https://travis-ci.org/AlienCreations/alien-node-pg-utils.svg?branch=master)](https://travis-ci.org/AlienCreations/alien-node-pg-utils) [![Coverage Status](https://coveralls.io/repos/AlienCreations/alien-node-pg-utils/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/AlienCreations/alien-node-pg-utils?branch=master) [![npm version](http://img.shields.io/npm/v/alien-node-pg-utils.svg)](https://npmjs.org/package/alien-node-pg-utils) [![Dependency Status](https://david-dm.org/AlienCreations/alien-node-pg-utils.svg)](https://david-dm.org/AlienCreations/alien-node-pg-utils)\n\n## Install\n\n```\n$ npm install alien-node-pg-utils --save\n```\n\nRun the specs\n\n```\n$ npm test\n```\n\n## Methods\n\n#### query()\nMake a SQL query in which you expect zero or more results. Returns a promise which\neither resolves to an object containing an array (data) containing found records (as objects) or rejects if no records found. \n\n#### querySafe()\nSame as query but resolves with an empty array if no records found.\n\n##### Suggested model usage: \n```js\n\n'use strict';\n\nconst { Pool } = require('pg'),\n      dbPool   = new Pool();\n    \nconst DB                  = require('alien-node-pg-utils')(dbPool),\n      validateAccountData = require('../some-validator');\n\nconst createAndExecuteQuery = status =\u003e {\n  const query = 'SELECT * FROM accounts WHERE status = $1',\n        queryStatement = [query, [status]];\n\n  return DB.query(queryStatement);\n};\n\n/**\n * Query accounts based on status\n * @param {Number} status\n * @returns {Promise}\n */\nconst getAccountsByStatus = status =\u003e {\n  validateAccountData({ status });\n  return createAndExecuteQuery(status);\n}\n\nmodule.exports = getAccountsByStatus;\n```\n\n##### Suggested controller usage \n\n*(using DB.query)*\n\n```js\n\nconst getAccountsByStatus = require('../models/getAccountsByStatus');\n\ngetAccountsByStatus('active').then(({ data : accounts }) =\u003e {\n    // handle array of accounts here\n  })\n  .catch(err =\u003e {\n    // handle \"No records found\" or other errors here\n  });\n  \n```\n\n*(using DB.querySafe)*\n\n```js\n\nconst getAccountsByStatus = require('../models/getAccountsByStatus');\n\ngetAccountsByStatus('active').then(({ data : maybeAccounts }) =\u003e {\n    // handle array of accounts or empty array here\n  })\n  .catch(err =\u003e {\n    // handle errors here\n  });\n  \n```\n\n#### lookup()\nMake a SQL query in which you expect zero or one result. Returns a promise which\neither resolves to an object containing a matching row (data) or rejects if no records found. \n\n#### lookupSafe()\nSame as lookup, but resolves with `{data:undefined ...}` if no records are found. \n\n```js\n\n'use strict';\n\nconst { Pool } = require('pg'),\n      dbPool   = new Pool();\n    \nconst DB                  = require('alien-node-pg-utils')(dbPool),\n      validateAccountData = require('../some-validator');\n\nconst createAndExecuteQuery = id =\u003e {\n  const query = 'SELECT * FROM accounts WHERE id = $1',\n        queryStatement = [query, [id]];\n\n  return DB.lookup(queryStatement);\n};\n\n/**\n * Lookup account by id\n * @param {Number} id\n * @returns {Promise}\n */\nconst getAccountById = id =\u003e {\n  validateAccountData({ id });\n  return createAndExecuteQuery(id);\n}\n\nmodule.exports = getAccountById;\n```\n\n##### Suggested controller usage\n\n*(using DB.lookup)*\n\n```js\n\nconst getAccountById = require('../models/getAccountById');\n\n\ngetAccountById(1234).then(({ data : account }) =\u003e {\n    // handle account object here\n  })\n  .catch(err =\u003e {\n    // handle \"No records found\" or other errors here\n  });\n  \n```\n\n*(using DB.lookupSafe)*\n\n```js\n\nconst getAccountById = require('../models/getAccountById');\n\n\ngetAccountById(1234).then(({ data : maybeAccount }) =\u003e {\n    // handle account object or undefined here\n  })\n  .catch(err =\u003e {\n    // handle errors here\n  });\n  \n```\n\n## Transactions\nThis library supports some simple transaction abstractions to play nicely with your promise chains. \n\nThe three methods you need to care about are : \n - DB.beginTransaction()\n - DB.addQueryToTransaction()\n - DB.commit()\n \nThese methods have a unique signature compared to the other methods for querying. Let's break them down: \n \n**DB.beginTransaction()** : `() -\u003e Promise(connection)`\n\nThis method will use the curried `dbPool` object provided during require...\n\n```js\nconst DB = require('alien-node-pg-utils')(dbPool);\n```\n\n... and internally call `getConnection()` on it, then resolve the connection on its promise.\n \nThis connection needs to be provided to the subsequent methods so the transaction knows how to commit and rollback. \n \n**DB.addQueryToTransaction()** : `connection -\u003e query -\u003e Promise({ data, connection })`\n\nThis method accepts the connection object which you should have gotten from `DB.beginTransaction()`, along with the typical query which you give to \nany other query method in this library. It behaves like `DB.querySafe()` in that it lets you \ndeal with all the data scrubbing and null-checks (resolves zero-or-more result sets and all `SELECT` statements\nreturn an array). \n\nPlease notice that this method returns the connection along with the data, so in the spirit of \nkeeping the unary promise chain data flow in mind, the promise will resolve a single object, \nwhere the data lives in a `data` property, and the connection on a `connection` property.\n\n**DB.commit()** : `connection`\n\nThis method accepts the connection object which you should have gotten from `DB.beginTransaction()`. It simply \nresolves `true` if there are no errors, otherwise it rejects the promise with whatever error may happen to ruin your day.\n\n##### Suggested wrapper-model usage for transactions\n\n```js\nconst DB = require('alien-node-pg-utils')(dbPool);\n\nconst getUserBalance = id =\u003e connection =\u003e {\n    const query          = 'SELECT balance FROM users WHERE id =$1',\n          queryStatement = [query, [id]];\n  \n    return DB.addQueryToTransaction(connection, queryStatement);\n};\n\nconst updateUserBalance = (id, amount) =\u003e connection =\u003e {\n    const query          = 'UPDATE users SET balance = balance + $1 WHERE id = $2',\n          queryStatement = [query, [amount, id]];\n  \n    return DB.addQueryToTransaction(connection, queryStatement);\n};\n\nconst ensurePositiveTransfer = amount =\u003e connection =\u003e {\n  if (amount \u003e 0) {\n    return connection;\n  } else {\n      throw { \n        error : new Error('What are you doing?'),\n        connection\n      };\n  };\n};\n\nconst ensureEnoughMoney = amount =\u003e transaction =\u003e {\n  const data    = transaction.data || [{ balance : 0 }],\n        balance = data[0].balance  || 0;\n  \n  if (amount \u003c= balance) {\n    return transaction;\n  } else {\n    throw { \n      error      : new Error('Broke ass' ),\n      connection : transaction.connection\n    };\n  }\n};\n\nconst senderUserId   = 1234,\n      receiverUserId = 5678,\n      amountToSend   = 500.45;\n\nconst resolveConnection = o =\u003e o.connection;\n\nDB.beginTransaction()\n  .then(ensurePositiveTransfer(amountToSend))\n  .then(getUserBalance(senderUserId))\n  .then(ensureEnoughMoney(amountToSend))\n  .then(resolveConnection)\n  .then(updateUserBalance(senderUserId, amountToSend * -1))\n  .then(resolveConnection)\n  .then(updateUserBalance(receiverUserId, amountToSend))\n  .then(resolveConnection)\n  .then(DB.commit)\n  .catch(exception =\u003e {\n    exception.connection.rollback();\n    logger.error(exception.error);\n  });\n \n```\n## TODO \n - Make the transform to/from column methods unbiased with decorator injection\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faliencreations%2Falien-node-pg-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faliencreations%2Falien-node-pg-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faliencreations%2Falien-node-pg-utils/lists"}