Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/neo4j-devtools/tapestry
https://github.com/neo4j-devtools/tapestry
Last synced: 3 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/neo4j-devtools/tapestry
- Owner: neo4j-devtools
- Created: 2019-12-13T13:51:52.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2023-07-18T20:40:07.000Z (over 1 year ago)
- Last Synced: 2024-10-14T03:31:01.736Z (3 months ago)
- Language: TypeScript
- Size: 660 KB
- Stars: 4
- Watchers: 3
- Forks: 0
- Open Issues: 22
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Tapestry
A neo4j driver spike illustrating an RxJS based monadic driver with full typescript support and a pluggable packstream.Help keep the dream alive!
## ToC
1. [Basic usage](#basic-usage)
- [Initialisation](#initialisation)
- [Queries](#queries)
- [Transactions](#transactions)
- [Routing](#routing)
- [Routing + Transactions](#routing--transactions)
2. [Custom unpackers](#custom-unpackers)
3. [Configuration](#configuration)## Basic Usage
### Initialisation
```Typescript
import {Driver} from '.';const driver = new Driver({
connectionConfig: {
authToken: {
scheme: 'basic',
principal: 'neo4j',
credentials: 'neo4j'
}
}
});
```### Queries
```Typescript
import {Driver} from '.';const driver = new Driver({});
// Reactive
driver.query('RETURN $foo', {foo: true}).subscribe({
next: console.log,
complete: () => driver.shutDown().toPromise(),
error: (err) => {
console.error(err);
driver.shutDown().toPromise();
}
})// Promise
driver.query('RETURN $foo', {foo: true})
.toPromise()
.then(console.log)
.catch(console.error)
.finally(() => driver.shutDown().toPromise());
```### Transactions
Only for 4.X
```Typescript
import {flatMap, reduce, tap} from 'rxjs/operators';import {Driver, List, Num, Result} from '.';
const driver = new Driver({});
// Reactive
driver.transaction().pipe(
flatMap((tx) => tx.query('CREATE (n {foo: $foo}) RETURN n', {foo: true}).pipe(
reduce((agg, next) => agg.concat(next), List.of([])),
tap(() => tx.rollback().toPromise())
))
).subscribe({
next: console.log,
complete: () => driver.shutDown().toPromise(),
error: (err) => {
console.error(err);driver.shutDown().toPromise();
}
});// Promise
getResults()
.then(console.log)
.catch(console.error)
.finally(() => driver.shutDown().toPromise())async function getResults() {
const tx = await driver.transaction().toPromise();
const q1 = await tx.query('CREATE (n {foo: $foo}) RETURN n', {foo: true}).toPromise();if (q1.data.length.equals(Num.ZERO)) {
await tx.rollback().toPromise();return;
}await tx.commit().toPromise();
return q1;
}
```## Routing
Only for 4.X
```TypeScript
import {forkJoin} from 'rxjs';
import {filter, reduce} from 'rxjs/operators';
import _ from 'lodash'import {Driver, DRIVER_RESULT_TYPE, List, Result} from '.';
const driver = new Driver({
useRouting: true,
maxPoolSize: 10
});const query = driver.query('RETURN 1', {}).pipe(
filter(({type}) => type === DRIVER_RESULT_TYPE.RECORD),
reduce((agg, next) => agg.concat(next), List.of([]))
);// Reactive
const result = forkJoin(_.map(Array(10), () => query));result.subscribe({
next: console.log,
complete: () => driver.shutDown().toPromise(),
error: (err) => {
console.error(err);driver.shutDown().toPromise();
}
})// Promise
const result = Promise.all(_.map(Array(10), () => query.toPromise()));result
.then(console.log)
.catch(console.error)
.finally(() => driver.shutDown().toPromise())
```## Routing + Transactions
Only for 4.X
```TypeScript
import {filter, reduce} from 'rxjs/operators';import {DBMS_DB_ROLE, Driver, DRIVER_RESULT_TYPE, List, Result} from '.';
const driver = new Driver({
useRouting: true,
maxPoolSize: 10
});getResults()
.then(console.log)
.catch(console.error)
.finally(() => driver.shutDown().toPromise())async function getResults() {
// request WRITE transaction for db 'neo4j'
const tx = await driver.transaction({role: DBMS_DB_ROLE.LEADER, db: 'neo4j'}).toPromise();
const q1 = await tx.query('CREATE (n {foo: $foo}) RETURN n', {foo: true}).pipe(
filter(({type}) => type === DRIVER_RESULT_TYPE.RECORD),
reduce((agg, next) => agg.concat(next), List.of([]))
).toPromise();await tx.commit().toPromise();
return q1;
}
```## Custom unpackers
Example using a [custom JSON unpacker](./src/packstream/unpacker/json-unpacker.ts), removing all monads from results.
```Typescript
import {reduce} from 'rxjs/operators';import {Driver, DRIVER_HEADERS, JsonUnpacker} from '.';
const driver = new Driver({
connectionConfig: {
unpacker: JsonUnpacker,
getResponseHeader: (data): DRIVER_HEADERS => data[0] || DRIVER_HEADERS.FAILURE,
getResponseData: (data): any => data[1] || []
},
mapToResult: (headerRecord, type, data) => ({header: headerRecord, type, data})
});driver.query('MATCH (n) RETURN n')
.pipe(
reduce((agg, next) => agg.concat(next), [])
).subscribe({
next: console.log,
complete: () => driver.shutDown().toPromise(),
error: (err) => {
console.error(err);
driver.shutDown().toPromise();
}
})
```## Configuration
```Typescript
import {
Packer,
Unpacker,
DRIVER_HEADERS,
DRIVER_RESULT_TYPE
} from '.';export interface IAuthToken {
scheme: 'basic',
principal: string,
credentials: string;
}export interface IConnectionConfig {
secure?: true;
authToken: IAuthToken;
host: string;
port: number;
userAgent: string;
getResponseHeader?: (unpacked: Data) => DRIVER_HEADERS,
getResponseData?: (unpacked: Data) => Data,
packer?: Packer;
unpacker?: Unpacker;
}export interface IDriverConfig {
maxPoolSize: number;
discoveryIntervalMs: number;
useRouting?: boolean;
connectionConfig: Partial; // @todo: Partial is not correct
mapToResultHeader: (headerRecord: any) => any;
mapToResult: (headerRecord: any, type: DRIVER_RESULT_TYPE, data: any) => Rec;
}
```