{"id":15934482,"url":"https://github.com/neo4j-devtools/tapestry","last_synced_at":"2025-03-24T21:32:04.896Z","repository":{"id":44011138,"uuid":"227850614","full_name":"neo4j-devtools/tapestry","owner":"neo4j-devtools","description":null,"archived":false,"fork":false,"pushed_at":"2023-07-18T20:40:07.000Z","size":676,"stargazers_count":4,"open_issues_count":22,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-29T08:03:22.162Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neo4j-devtools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-12-13T13:51:52.000Z","updated_at":"2020-06-24T11:48:57.000Z","dependencies_parsed_at":"2023-12-29T09:23:41.514Z","dependency_job_id":"6e292768-a8ee-4af4-ae7c-337b0480a4f2","html_url":"https://github.com/neo4j-devtools/tapestry","commit_stats":null,"previous_names":["huboneo/tapestry"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neo4j-devtools%2Ftapestry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neo4j-devtools%2Ftapestry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neo4j-devtools%2Ftapestry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neo4j-devtools%2Ftapestry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neo4j-devtools","download_url":"https://codeload.github.com/neo4j-devtools/tapestry/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245355490,"owners_count":20601731,"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":[],"created_at":"2024-10-07T03:03:20.085Z","updated_at":"2025-03-24T21:32:04.524Z","avatar_url":"https://github.com/neo4j-devtools.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tapestry\nA neo4j driver spike illustrating an RxJS based monadic driver with full typescript support and a pluggable packstream.\n\nHelp keep the dream alive!\n\n## ToC\n1. [Basic usage](#basic-usage)\n    - [Initialisation](#initialisation)\n    - [Queries](#queries)\n    - [Transactions](#transactions)\n    - [Routing](#routing)\n    - [Routing + Transactions](#routing--transactions)\n2. [Custom unpackers](#custom-unpackers)\n3. [Configuration](#configuration)\n\n\n## Basic Usage\n### Initialisation\n```Typescript\nimport {Driver} from '.';\n\nconst driver = new Driver({\n    connectionConfig: {\n        authToken: {\n            scheme: 'basic',\n            principal: 'neo4j',\n            credentials: 'neo4j'\n        }\n    }\n});\n```\n\n### Queries\n```Typescript\nimport {Driver} from '.';\n\nconst driver = new Driver({});\n\n// Reactive\ndriver.query('RETURN $foo', {foo: true}).subscribe({\n    next: console.log,\n    complete: () =\u003e driver.shutDown().toPromise(),\n    error: (err) =\u003e {\n        console.error(err);\n        \n        driver.shutDown().toPromise();\n    }\n})\n\n// Promise\ndriver.query('RETURN $foo', {foo: true})\n    .toPromise()\n    .then(console.log)\n    .catch(console.error)\n    .finally(() =\u003e driver.shutDown().toPromise());\n```\n\n### Transactions\nOnly for 4.X\n```Typescript\nimport {flatMap, reduce, tap} from 'rxjs/operators';\n\nimport {Driver, List, Num, Result} from '.';\n\nconst driver = new Driver\u003cResult\u003e({});\n\n// Reactive\ndriver.transaction().pipe(\n    flatMap((tx) =\u003e tx.query('CREATE (n {foo: $foo}) RETURN n', {foo: true}).pipe(\n        reduce((agg, next) =\u003e agg.concat(next), List.of\u003cResult\u003e([])),\n        tap(() =\u003e tx.rollback().toPromise())\n    ))\n).subscribe({\n    next: console.log,\n    complete: () =\u003e driver.shutDown().toPromise(),\n    error: (err) =\u003e {\n        console.error(err);\n\n        driver.shutDown().toPromise();\n    }\n});\n\n// Promise\ngetResults()\n    .then(console.log)\n    .catch(console.error)\n    .finally(() =\u003e driver.shutDown().toPromise())\n\nasync function getResults()  {\n    const tx = await driver.transaction().toPromise();\n    const q1 = await tx.query('CREATE (n {foo: $foo}) RETURN n', {foo: true}).toPromise();\n\n    if (q1.data.length.equals(Num.ZERO)) {\n        await tx.rollback().toPromise();\n\n        return;\n    }\n\n    await tx.commit().toPromise();\n\n    return q1;\n}\n```\n\n## Routing\nOnly for 4.X\n```TypeScript\nimport {forkJoin} from 'rxjs';\nimport {filter, reduce} from 'rxjs/operators';\nimport _ from 'lodash'\n\nimport {Driver, DRIVER_RESULT_TYPE, List, Result} from '.';\n\nconst driver = new Driver\u003cResult\u003e({\n    useRouting: true,\n    maxPoolSize: 10\n});\n\nconst query = driver.query('RETURN 1', {}).pipe(\n    filter(({type}) =\u003e type === DRIVER_RESULT_TYPE.RECORD),\n    reduce((agg, next) =\u003e agg.concat(next), List.of\u003cResult\u003e([]))\n);\n\n// Reactive\nconst result = forkJoin(_.map(Array(10), () =\u003e query));\n\nresult.subscribe({\n    next: console.log,\n    complete: () =\u003e driver.shutDown().toPromise(),\n    error: (err) =\u003e {\n        console.error(err);\n\n        driver.shutDown().toPromise();\n    }\n})\n\n// Promise\nconst result = Promise.all(_.map(Array(10), () =\u003e query.toPromise()));\n\nresult\n    .then(console.log)\n    .catch(console.error)\n    .finally(() =\u003e driver.shutDown().toPromise())\n```\n\n## Routing + Transactions\nOnly for 4.X\n```TypeScript\nimport {filter, reduce} from 'rxjs/operators';\n\nimport {DBMS_DB_ROLE, Driver, DRIVER_RESULT_TYPE, List, Result} from '.';\n\nconst driver = new Driver\u003cResult\u003e({\n    useRouting: true,\n    maxPoolSize: 10\n});\n\ngetResults()\n    .then(console.log)\n    .catch(console.error)\n    .finally(() =\u003e driver.shutDown().toPromise())\n\nasync function getResults()  {\n    // request WRITE transaction for db 'neo4j'\n    const tx = await driver.transaction({role: DBMS_DB_ROLE.LEADER, db: 'neo4j'}).toPromise();\n    const q1 = await tx.query('CREATE (n {foo: $foo}) RETURN n', {foo: true}).pipe(\n       filter(({type}) =\u003e type === DRIVER_RESULT_TYPE.RECORD),\n       reduce((agg, next) =\u003e agg.concat(next), List.of\u003cResult\u003e([]))\n   ).toPromise();\n\n    await tx.commit().toPromise();\n\n    return q1;\n}\n```\n\n## Custom unpackers\nExample using a [custom JSON unpacker](./src/packstream/unpacker/json-unpacker.ts), removing all monads from results.\n```Typescript\nimport {reduce} from 'rxjs/operators';\n\nimport {Driver, DRIVER_HEADERS, JsonUnpacker} from '.';\n\nconst driver = new Driver\u003cany\u003e({\n    connectionConfig: {\n        unpacker: JsonUnpacker,\n        getResponseHeader: (data): DRIVER_HEADERS =\u003e data[0] || DRIVER_HEADERS.FAILURE,\n        getResponseData: (data): any =\u003e data[1] || []\n    },\n    mapToResult: (headerRecord, type, data) =\u003e ({header: headerRecord, type, data})\n});\n\ndriver.query('MATCH (n) RETURN n')\n    .pipe(\n        reduce((agg, next) =\u003e agg.concat(next), [])\n    ).subscribe({\n        next: console.log,\n        complete: () =\u003e driver.shutDown().toPromise(),\n        error: (err) =\u003e {\n            console.error(err);\n            \n            driver.shutDown().toPromise();\n        }\n    })\n```\n\n## Configuration\n```Typescript\nimport {\n    Packer,\n    Unpacker,\n    DRIVER_HEADERS,\n    DRIVER_RESULT_TYPE\n} from '.';\n\nexport interface IAuthToken {\n    scheme: 'basic',\n    principal: string,\n    credentials: string;\n}\n\nexport interface IConnectionConfig\u003cData = any\u003e {\n    secure?: true;\n    authToken: IAuthToken;\n    host: string;\n    port: number;\n    userAgent: string;\n    getResponseHeader?: (unpacked: Data) =\u003e DRIVER_HEADERS,\n    getResponseData?: (unpacked: Data) =\u003e Data,\n    packer?: Packer\u003cData\u003e;\n    unpacker?: Unpacker\u003cData\u003e;\n}\n\nexport interface IDriverConfig\u003cRec = any\u003e {\n    maxPoolSize: number;\n    discoveryIntervalMs: number;\n    useRouting?: boolean;\n    connectionConfig: Partial\u003cIConnectionConfig\u003e; // @todo: Partial is not correct\n    mapToResultHeader: (headerRecord: any) =\u003e any;\n    mapToResult: (headerRecord: any, type: DRIVER_RESULT_TYPE, data: any) =\u003e Rec;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneo4j-devtools%2Ftapestry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneo4j-devtools%2Ftapestry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneo4j-devtools%2Ftapestry/lists"}