npm package: @mvarble/postgres-planar-graph
Description: Interface planar graphs with a postgres database.
Author: Matthew Varble
Latest version: 0.0.0

# postgres-planar-graph

Interface planar graphs with a postgres database.

## Schema

This package assumes we are interacting with tables that have been generated by:

```sql
CREATE TABLE graph_node(
  id SERIAL PRIMARY KEY,
  graph INTEGER NOT NULL,
  x FLOAT,
  y FLOAT
);

CREATE TABLE graph_edge(
  id SERIAL PRIMARY KEY,
  graph INTEGER NOT NULL,
  head INTEGER REFERENCES graph_node(id) NOT NULL,
  tail INTEGER REFERENCES graph_node(id) NOT NULL,
  index INTEGER
);
```

## REST API

We will suppose we are dealing with a server that has the following request/response structure.

### GET requests

By performing a GET request with a `graph` parameter for querying a planar graph, you will get an object of the form:

```js
{
  id,
  nodes: [
    { id, graph, location? },
    ...,
    { id, graph, location? },
  ],
  edges: [
    { id, graph, head, tail, index? },
    ...,
    { id, graph, head, tail, index? },
  ]
}
```

corresponding to a parsed version of the rows of the tables `graph_node` and `graph_edge` in which the `graph.id` matches the query parameter of the GET request.
The parsing is such that `*.dbKey` corresponds to `graph_*.id`, `node.location` corresponds to the array `[graph_node.x, graph_node.y]`, and the others `*.*` match the database `graph_*.*`.

### POST requests

We will assume that performing a POST request to the server with the following body shape will resolve the associated CRUD operations on the server.

```js
{
  createNodes: [
    { tempId, graph, location? },
    ...
    { tempId, graph, location? },
  ],
  updateNodes: [
    { id, graph, location? },
    ...
    { id, graph, location? },
  ],
  deleteNodes: [id, ..., id],
  createEdges: [
    { graph, head/tempHead, tail/tempTail, index? },
    ...
    { graph, head/tempHead, tail/tempTail, index? },
  ],
  updateEdges: [
    { id, graph, head/tempHead, tail/tempTail, index? },
    ...
    { id, graph, head/tempHead, tail/tempTail, index? },
  ],
  deleteNodes: [id, ..., id],
}
```

The purpose of `node.tempId` is to allow edges to be defined from `edge.tempHead` and `edge.tempTail` when the head and tail nodes are not yet resolved in the database, respectively.
In other words, the server will run:

```sql
INSERT INTO route_node (graph, x, y)
VALUES (...), (...), ... (...)
RETURNING id;
```

and then convert any `edge.tempHead`/`edge.tempTail` to `edge.head`/`edge.tail` by comparing `node.tempId` to the returned value of the operation above.

## API

With the discussion above, one can see how the following functions exported by this module are helpful for interacting applications like [viewport-planar-graph](https://github.com/mvarble/viewport-planar-graph) with such a database.

### createRequest

```js
requestBody = createRequest(oldGraph, graph)
```

This function will compare two objects `oldGraph` and `graph`, where `oldGraph` is of the shape provided by a [GET request](#get-requests) to the API, and `graph` is the same, except in regards to the `id`/`head`/`tail` attributes possibly being their `tempId`/`tempHead`/`tempTail` counterparts.
The returned `requestBody` is that of the [POST request](#post-requests).

### isPOSTRequest

```js
bool = isPOSTRequest(request)
```

This function will return the truth value of `request` having the shape of the [POST request](#post-requests).

### isDBGraph

```js
bool = isDBGraph(dbGraph)
```

This function will return the truth value of `dbGraph` having the shape of the [GET request](#get-requests).
It also checks if each of the `edge.head` and `edge.tail` attributes match some `node.id`.

### isGraph

```js
bool = isGraph(Graph)
```

This function will return the truth value of `graph` having the shape of the [GET request](#get-requests), except in regards to the `id`/`head`/`tail` keys potentially being their `tempId`/`tempHead`/`tempTail` counterparts.
It also performs the checks of whether (1) each `edge.head` and `edge.tail` attributes match to some `node.id` and (2) each `edge.tempHead` and `edge.tempTail` attributes match to some `node.tempId`.

### mapIds

```js
newRequest = mapIds(request, rows)
```

This function does the job of getting the array `rows` returned by

```sql
INSERT INTO route_node (graph, x, y)
VALUES (...) /* data of request.createNodes */
RETURNING id;
```

and returning and object `newRequest` in which the edges with `edge.tempHead`/`edge.tempTail` will have the corresponding `edge.head`/`edge.tail` resolved.