Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/wmfs/pg-model


https://github.com/wmfs/pg-model

package postgresql tymly

Last synced: 3 months ago
JSON representation

Awesome Lists containing this project

README

        

# pg-model
[![Tymly Package](https://img.shields.io/badge/tymly-package-blue.svg)](https://tymly.io/)
[![npm (scoped)](https://img.shields.io/npm/v/@wmfs/pg-model.svg)](https://www.npmjs.com/package/@wmfs/pg-model)
[![Build Status](https://travis-ci.org/wmfs/pg-model.svg?branch=master)](https://travis-ci.org/wmfs/pg-model)
[![codecov](https://codecov.io/gh/wmfs/pg-model/branch/master/graph/badge.svg)](https://codecov.io/gh/wmfs/pg-model)
[![CodeFactor](https://www.codefactor.io/repository/github/wmfs/pg-model/badge)](https://www.codefactor.io/repository/github/wmfs/pg-model)
[![Dependabot badge](https://img.shields.io/badge/Dependabot-active-brightgreen.svg)](https://dependabot.com/)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/wmfs/tymly/blob/master/packages/pg-concat/LICENSE)

> Takes a relational database structure and returns model objects for noSQL-like abilities.

## Install
```bash
$ npm install pg-model --save
```

## Usage

```javascript
const pg = require('pg')
const pgInfo = require('pg-info')

// Make a new Postgres client
const client = new pg.Client('postgres://postgres:postgres@localhost:5432/my_test_db')
client.connect()

//Now get the structure of the 'space' database schema
pgInfo(
{
client: client,
schemas: [
'space',
]
},
function (err, dbStructure) {

// 'dbStructure' describes the content of the 'space' schema
// (i.e. tables, columns, indexes, foreign-key constraints etc.)

// Now make some models from that description...

models = pgModel(
{
client: client,
dbStructure: dbStructure
}
)

// We've now one-model-per table.
// So, assuming the 'space' schema contained tables named 'planets', 'moons' and 'craters'...
// This sort of thing is possible...
models.space.planets.create(
{
name: 'mars',
title: 'Mars',
type: 'Terrestrial',
diameter: 6700,
color: 'red',
url: 'http://en.wikipedia.org/wiki/Mars',
moons: [
{
title: 'Phobos',
discoveredBy: 'Asaph Hall',
discoveryYear: 1875,
craters: [
{
title: 'Stickney',
diameter: 10
}
]
},
{
title: 'Deimos',
discoveredBy: 'Asaph Hall',
discoveryYear: 1875
}
]
},
{}
).then(() => {{
// * Four rows have been inserted amongst the 'space.planets', 'space.moons' and 'space.craters' tables
// * PostgreSQL's column defaults have been used to populate the missing primary key values
// * The foreign-key values for 'space.moons' and 'space.craters' have been auto-filled by
// inspecting FK constraints
}
)
}
)
```

## API

Each model offers the following methods.

### create (`jsonData`, `options`)

Inserts the supplied JSON documents into relational tables.
Resolves to the document's id properties.

__Example__

```javascript
models.hr.people.create(
{
employeeNo: 1
firstName: 'Homer',
lastName: 'Simpson',
age: 39
},
{}
).then(idProperties => {
// idProperties ==
// {
// idProperties:
// {
// employeeNo: 1
// }
// }
}
)
```

### findById (`id`)

Finds one 'document' by ID - all nested docs will be assembled too.

__Example__

```javascript
models.hr.people.findById(1)
.then(doc => {
// doc ==
// {
// employeeNo: 1,
// firstName: 'Homer',
// lastName: 'Simpson',
// age: 39,
// created: 2017-06-02T22:00:55.221Z,
// createdBy: null,
// modified: 2017-06-02T22:00:55.221Z,
// modifiedBy: null
// }
}
)
```

### find (`options`)

Find zero-or-more docs - can be filtered, ordered, paginated etc.
Resolves to the found document array.

__Example__

```javascript
models.hr.people.find(
{
where: {
firstName: {equals: 'Homer'},
lastName: {equals: 'Simpson'}
}
}
).then(docs => {
// docs ==
// [
// {
// employeeNo: 1,
// firstName: 'Homer',
// lastName: 'Simpson',
// age: 39,
// created: 2017-06-02T22:00:55.221Z,
// createdBy: null,
// modified: 2017-06-02T22:00:55.221Z,
// modifiedBy: null
// }
// ]
}
)
```

### findOne (`options`)

Like `find` but resolves to a single doc.

__Example__

```javascript
models.hr.people.findOne(
{
orderBy: ['age'],
nullsLast: true,
offset: 1
}
).then(doc => {
// doc ==
// {
// employeeNo: 1,
// firstName: 'Homer',
// lastName: 'Simpson',
// age: 39,
// created: 2017-06-02T22:00:55.221Z,
// createdBy: null,
// modified: 2017-06-02T22:00:55.221Z,
// modifiedBy: null
// }
}
)
```

### update (`doc`, `options`)

Updates a single 'document'. The top-level primary key is inferred from the data - automatically inserts/updates/deletes nested docs.

__Example__

```javascript
models.hr.people.update(
{
employeeNo: 1,
firstName: 'Homer',
lastName: 'Simpson',
age: 39
},
{}
).then(() => { /* All done */ })
```

### patch (`doc`, `options`)

Same as `update`, but any omitted properties will be retained (i.e. they won't be turned into `null` values like `update` will).

__Example__

```javascript
models.hr.people.patch(
{
employeeNo: 1,
age: 39
},
{}
).then(() => { /* All done */ })
```

### upsert (`doc`, `options`)

A combination of `create` and `update`. If a document already exists then `upsert` will _update_ it, else it'll _create_ it.

__Example__

```javascript
models.hr.people.upsert(
{
employeeNo: 1,
firstName: 'Homer',
lastName: 'Simpson',
age: 39
},
{}
).then(idProperties => {
// idProperties ==
// {
// idProperties:
// {
// employeeNo: 1
// }
// }
}
)
```

### destroyById (`id`)

Deletes one 'document' by ID - all nested docs will be cascade-deleted too.

__Example__

```javascript
models.hr.people.destroyById(1)
.then(() => { /* All done */ })
```

### parseDoc (`doc`, `options`)

Takes a single doc and parses it into a form that's usable by several of the other methods.

__Example__

```javascript
const parsedDoc = models.hr.people.parseDoc(
{
employeeNo: 1,
firstName: 'Homer',
lastName: 'Simpson',
age: 39
},
{
includeNullFks: false
}
)
```

## Testing

Before 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:

```PG_CONNECTION_STRING=postgres://postgres:postgres@localhost:5432/my_test_db```

```bash
$ npm test
```

## License
[MIT](https://github.com/wmfs/pg-model/blob/master/LICENSE)