{"id":20555878,"url":"https://github.com/conjurelabs/pg-dot-template","last_synced_at":"2026-05-10T05:47:44.275Z","repository":{"id":57103689,"uuid":"230828116","full_name":"ConjureLabs/pg-dot-template","owner":"ConjureLabs","description":"query postgres using templatized sql files","archived":false,"fork":false,"pushed_at":"2023-04-22T22:56:25.000Z","size":49,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-05T00:34:18.077Z","etag":null,"topics":["javascript-template-literals","node","postgres","query","templates"],"latest_commit_sha":null,"homepage":"","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/ConjureLabs.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":"2019-12-30T01:47:00.000Z","updated_at":"2023-04-22T22:55:33.000Z","dependencies_parsed_at":"2022-08-20T17:10:38.230Z","dependency_job_id":null,"html_url":"https://github.com/ConjureLabs/pg-dot-template","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ConjureLabs%2Fpg-dot-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ConjureLabs%2Fpg-dot-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ConjureLabs%2Fpg-dot-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ConjureLabs%2Fpg-dot-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ConjureLabs","download_url":"https://codeload.github.com/ConjureLabs/pg-dot-template/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242163849,"owners_count":20082224,"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","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":["javascript-template-literals","node","postgres","query","templates"],"created_at":"2024-11-16T03:21:39.924Z","updated_at":"2026-05-10T05:47:44.242Z","avatar_url":"https://github.com/ConjureLabs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pg-dot-template\n\nextends [`dot-template`](https://github.com/ConjureLabs/dot-template#readme), with added niceties specific to [the pg module](https://node-postgres.com/)\n\n## install\n\n```sh\n# peer dependencies\nnpm install @conjurelabs/dot-template\n\n# required if using .query methods\nnpm install pg\n\n# library\nnpm install @conjurelabs/pg-dot-template\n```\n\n## use\n\n`pg-dot-template` uses [`dot-tempalte`](https://github.com/ConjureLabs/dot-template) to add extra utilities for dealing with postgres queries\n\n_activity-query.sql_\n```sql\nselect *\nfrom activity\nwhere added $PG{added}\nlimit $PG{limit}\n```\n\n```js\nconst pgDotTemplate = require('@conjurelabs/pg-dot-template')\n\nconst client = new Client()\nclient.connect()\n\n// required setup if using .query\npgDotTemplate.handleQuery = (queryString, queryArgs) =\u003e {\n  return client.query(queryString, queryArgs)\n}\n\nasync function main() {\n  // pulls in template\n  const template = pgDotTemplate('activity-query')\n\n  // replace expressions\n  const queryString = await template({\n    added: '\u003e= NOW() - interval 1 day',\n    limit: 10\n  })\n\n  // prints:\n  /*\n    select *\n    from activity\n    where added \u003e= NOW() - interval 1 day\n    limit 10\n   */\n  console.log(queryString)\n\n  // queries:\n  /*\n    select *\n    from activity\n    where added \u003e= $1\n    limit $2\n   */\n  // with query args:\n  /*\n    ['\u003e= NOW() - interval 1 day', 10]\n   */\n  const result = await queryString.query()\n\n  console.log(result.rows)\n}\nmain()\n```\n\n### postgres expression handlers\n\nthis library adds two unique handlers\n\n#### $PG{expression}\n\n`$PG{expression}` prints the value of `expression` to console, while passing an index reference (like `$1`) in the literal query\n\nas expressions are evaluated, the library will construct an array of query arguments that are passed to the postgres client\n\n```sql\nselect *\nfrom authors\nwhere name ilike '$PG{namePrefix}'\n```\n\n```js\nconst template = pgDotTemplate('authors')\n\nconst queryString = template({\n  namePrefix: 'clint '\n})\n\nconsole.log(queryString)\n\n// prints:\n/*\n  select *\n  from authors\n  where name ilike 'clint '\n */\n```\n\n#### !PG{expression}\n\n`!PG{expression}` prints a `\u003cREDACTED\u003e` message to console, while passing an index reference (like `$1`) in the literal query\n\nthis is to be used with PII, like names and email addresses\n\n```sql\nselect *\nfrom authors\nwhere email = '!PG{email}'\n```\n\n```js\nconst template = pgDotTemplate('authors')\n\nconst queryString = template({\n  email: 'example@gmail.com'\n})\n\nconsole.log(queryString)\n\n// prints:\n/*\n  select *\n  from authors\n  where email = '\u003cREDACTED\u003e'\n */\n```\n\n### .query()\n\nthere are two ways you can call `.query()`\n\n```js\nconst template = pgDotTemplate('activity-query')\n\n// calling .query() via a template\nconst result1 = await template.query({\n  added: '\u003e= NOW() - interval 1 day',\n  limit: 10\n})\n\n// calling .query() via a filled-in template\nconst queryString = template({\n  added: '\u003e= NOW() - interval 1 day',\n  limit: 10\n})\nconst result2 = await queryString.query()\n````\n\nalso, if you need it, you will have access to the passed `queryArgs`\n\nthis will be an empty `[]` array until `.query()` is called\n\nthis attribute is only available when executing `.query()` on a filled-in query string\n\n```js\nconst template = pgDotTemplate('activity-query')\n\nconst queryString = template({\n  added: '\u003e= NOW() - interval 1 day',\n  limit: 10\n})\n\nconst result = await queryString.query()\n\n// prints:\n/*\n  ['\u003e= NOW() - interval 1 day', 10]\n */\nconsole.log(result.queryArgs)\n```\n\n### types\n\nthis library supports:\n\n- strings\n- numbers\n- bigints\n- booleans\n- `null`\n- arrays of the above\n\nit does not support `undefined` or nested arrays\n\nany unexpected values will trigger an error to be thrown\n\narrays will not be auto-wrapped in `()`s\n\n### using pg's Pool\n\nif you plan to use [`Pool`](https://node-postgres.com/features/pooling) to connect, you will want to call `.connect()` before each query, and then `release()` when finished:\n\n```js\nconst pool = new Pool()\n\npgDotTemplate.handleQuery = async (queryString, queryArgs) =\u003e {\n  const connection = await pool.connect()\n\n  return new Promise(async (resolve, reject) =\u003e {\n    let result, err\n    \n    try {\n      result = await connection.query(queryString, queryArgs)\n    } catch(tryErr) {\n      err = tryErr\n    } finally {\n      connection.release()\n    }\n\n    if (err) {\n      return reject(err)\n    }\n    resolve(result)\n  })\n}\n```\n\n### changing the redacted message\n\nby default any redaction will show in terminal as `\u003cREDACTED\u003e`\n\nyou can change this string by setting the enironment variable `PG_DOT_TEMPLATE_REDACTION_MESSAGE`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconjurelabs%2Fpg-dot-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconjurelabs%2Fpg-dot-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconjurelabs%2Fpg-dot-template/lists"}