{"id":19223730,"url":"https://github.com/wmfs/pg-model","last_synced_at":"2025-06-27T06:33:01.849Z","repository":{"id":21527088,"uuid":"136925847","full_name":"wmfs/pg-model","owner":"wmfs","description":null,"archived":false,"fork":false,"pushed_at":"2025-06-18T18:39:29.000Z","size":580,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-06-18T19:44:08.455Z","etag":null,"topics":["package","postgresql","tymly"],"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/wmfs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"zenodo":null}},"created_at":"2018-06-11T12:51:31.000Z","updated_at":"2025-06-18T18:39:33.000Z","dependencies_parsed_at":"2024-01-05T21:28:16.432Z","dependency_job_id":"92974df6-ce04-4405-848d-12c13033cffc","html_url":"https://github.com/wmfs/pg-model","commit_stats":null,"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/wmfs/pg-model","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wmfs%2Fpg-model","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wmfs%2Fpg-model/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wmfs%2Fpg-model/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wmfs%2Fpg-model/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wmfs","download_url":"https://codeload.github.com/wmfs/pg-model/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wmfs%2Fpg-model/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260624172,"owners_count":23038138,"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":["package","postgresql","tymly"],"created_at":"2024-11-09T15:09:23.159Z","updated_at":"2025-06-27T06:33:01.825Z","avatar_url":"https://github.com/wmfs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pg-model\n[![Tymly Package](https://img.shields.io/badge/tymly-package-blue.svg)](https://tymly.io/)\n[![npm (scoped)](https://img.shields.io/npm/v/@wmfs/pg-model.svg)](https://www.npmjs.com/package/@wmfs/pg-model)\n[![Build Status](https://travis-ci.org/wmfs/pg-model.svg?branch=master)](https://travis-ci.org/wmfs/pg-model)\n[![codecov](https://codecov.io/gh/wmfs/pg-model/branch/master/graph/badge.svg)](https://codecov.io/gh/wmfs/pg-model)\n[![CodeFactor](https://www.codefactor.io/repository/github/wmfs/pg-model/badge)](https://www.codefactor.io/repository/github/wmfs/pg-model)\n[![Dependabot badge](https://img.shields.io/badge/Dependabot-active-brightgreen.svg)](https://dependabot.com/)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)\n[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/wmfs/tymly/blob/master/packages/pg-concat/LICENSE)\n\n\n\n\u003e Takes a relational database structure and returns model objects for noSQL-like abilities.\n\n## \u003ca name=\"install\"\u003e\u003c/a\u003eInstall\n```bash\n$ npm install pg-model --save\n```\n\n## \u003ca name=\"usage\"\u003e\u003c/a\u003eUsage\n\n```javascript\nconst pg = require('pg')\nconst pgInfo = require('pg-info')\n\n// Make a new Postgres client\nconst client = new pg.Client('postgres://postgres:postgres@localhost:5432/my_test_db')\nclient.connect()\n\n//Now get the structure of the 'space' database schema\npgInfo(\n  {\n    client: client,\n    schemas: [\n      'space',\n    ]    \n  },\n  function (err, dbStructure) {\n    \n    // 'dbStructure' describes the content of the 'space' schema\n    // (i.e. tables, columns, indexes, foreign-key constraints etc.)\n    \n    // Now make some models from that description...\n    \n    models = pgModel(\n      {\n        client: client,\n        dbStructure: dbStructure\n      }\n    )\n    \n    // We've now one-model-per table.\n    // So, assuming the 'space' schema contained tables named 'planets', 'moons' and 'craters'...\n    // This sort of thing is possible...\n    models.space.planets.create(\n      {\n        name: 'mars',\n        title: 'Mars',\n        type: 'Terrestrial',\n        diameter: 6700,\n        color: 'red',\n        url: 'http://en.wikipedia.org/wiki/Mars',\n        moons: [\n          {\n            title: 'Phobos',\n            discoveredBy: 'Asaph Hall',\n            discoveryYear: 1875,\n            craters: [\n              {\n                title: 'Stickney',\n                diameter: 10\n              }\n            ]\n          },\n          {\n            title: 'Deimos',\n            discoveredBy: 'Asaph Hall',\n            discoveryYear: 1875\n          }\n        ]\n      },\n      {}\n    ).then(() =\u003e {{\n      //  * Four rows have been inserted amongst the 'space.planets', 'space.moons' and 'space.craters' tables\n      //  * PostgreSQL's column defaults have been used to populate the missing primary key values\n      //  * The foreign-key values for 'space.moons' and 'space.craters' have been auto-filled by\n      //    inspecting FK constraints\n      }\n    )   \n  }\n)\n```\n\n## \u003ca name=\"api\"\u003e\u003c/a\u003eAPI\n\nEach model offers the following methods.\n\n### create (`jsonData`, `options`)\n\nInserts the supplied JSON documents into relational tables.  \nResolves to the document's id properties.\n\n__Example__\n\n```javascript\nmodels.hr.people.create(\n    {\n      employeeNo: 1\n      firstName: 'Homer',\n      lastName: 'Simpson',\n      age: 39\n    },\n    {}\n  ).then(idProperties =\u003e {\n    // idProperties ==\n    // {\n    //   idProperties:\n    //     {\n    //       employeeNo: 1\n    //     }\n    // }\n    }\n  )\n```\n\n### findById (`id`)\n\nFinds one 'document' by ID - all nested docs will be assembled too.\n\n__Example__\n\n```javascript\nmodels.hr.people.findById(1)\n  .then(doc =\u003e {\n    // doc ==\n    // {\n    //   employeeNo: 1,\n    //   firstName: 'Homer',\n    //   lastName: 'Simpson',\n    //   age: 39,\n    //   created: 2017-06-02T22:00:55.221Z,\n    //   createdBy: null,\n    //   modified: 2017-06-02T22:00:55.221Z,\n    //   modifiedBy: null \n    // }\n    }\n  )\n```\n\n### find (`options`)\n\nFind zero-or-more docs - can be filtered, ordered, paginated etc. \nResolves to the found document array.\n\n__Example__\n\n```javascript\nmodels.hr.people.find(\n    {\n      where: {\n        firstName: {equals: 'Homer'},\n        lastName: {equals: 'Simpson'}\n      }\n    }\n  ).then(docs =\u003e {\n    // docs ==\n    // [\n    //   {\n    //     employeeNo: 1,\n    //     firstName: 'Homer',\n    //     lastName: 'Simpson',\n    //     age: 39,\n    //     created: 2017-06-02T22:00:55.221Z,\n    //     createdBy: null,\n    //     modified: 2017-06-02T22:00:55.221Z,\n    //     modifiedBy: null \n    //   }\n    // ]\n    }\n  )\n```\n\n### findOne (`options`)\n\nLike `find` but resolves to a single doc.\n\n__Example__\n\n```javascript\nmodels.hr.people.findOne(\n    {\n      orderBy: ['age'],\n      nullsLast: true,\n      offset: 1\n    }\n  ).then(doc =\u003e {\n    // doc ==\n    // {\n    //   employeeNo: 1,\n    //   firstName: 'Homer',\n    //   lastName: 'Simpson',\n    //   age: 39,\n    //   created: 2017-06-02T22:00:55.221Z,\n    //   createdBy: null,\n    //   modified: 2017-06-02T22:00:55.221Z,\n    //   modifiedBy: null \n    // }\n    }\n  )\n```\n\n### update (`doc`, `options`)\n\nUpdates a single 'document'. The top-level primary key is inferred from the data - automatically inserts/updates/deletes nested docs.  \n\n__Example__\n\n```javascript\nmodels.hr.people.update(\n    {\n      employeeNo: 1,\n      firstName: 'Homer',\n      lastName: 'Simpson',\n      age: 39\n    },\n    {}\n  ).then(() =\u003e { /* All done */ })\n```\n\n### patch (`doc`, `options`)\n\nSame as `update`, but any omitted properties will be retained (i.e. they won't be turned into `null` values like `update` will). \n\n__Example__\n\n```javascript\nmodels.hr.people.patch(\n    {\n      employeeNo: 1,\n      age: 39\n    },\n    {}\n  ).then(() =\u003e { /* All done */ })\n```\n\n### upsert (`doc`, `options`)\n\nA combination of `create` and `update`. If a document already exists then `upsert` will _update_ it, else it'll _create_ it.\n\n__Example__\n\n```javascript\nmodels.hr.people.upsert(\n    {\n      employeeNo: 1,\n      firstName: 'Homer',\n      lastName: 'Simpson',\n      age: 39\n    },\n    {}\n  ).then(idProperties =\u003e {\n    // idProperties ==\n    // {\n    //   idProperties:\n    //     {\n    //       employeeNo: 1\n    //     }\n    // }  \n    }\n  )\n```\n\n### destroyById (`id`)\n\nDeletes one 'document' by ID - all nested docs will be cascade-deleted too.\n\n__Example__\n\n```javascript\nmodels.hr.people.destroyById(1)\n  .then(() =\u003e { /* All done */ })\n```\n\n### parseDoc (`doc`, `options`)\n\nTakes a single doc and parses it into a form that's usable by several of the other methods.\n\n__Example__\n\n```javascript\nconst parsedDoc = models.hr.people.parseDoc(\n  {\n    employeeNo: 1,\n    firstName: 'Homer',\n    lastName: 'Simpson',\n    age: 39\n  },\n  {\n    includeNullFks: false\n  }\n)\n```\n\n## \u003ca name=\"test\"\u003e\u003c/a\u003eTesting\n\nBefore running these tests, you'll need a test PostgreSQL database available and set a `PG_CONNECTION_STRING` environment variable to point to it, for example:\n\n```PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/my_test_db```\n\n```bash\n$ npm test\n```\n\n## \u003ca name=\"license\"\u003e\u003c/a\u003eLicense\n[MIT](https://github.com/wmfs/pg-model/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwmfs%2Fpg-model","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwmfs%2Fpg-model","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwmfs%2Fpg-model/lists"}