diff --git a/__tests__/neovis.tests.ts b/__tests__/neovis.tests.ts index 3529ae3..8e51d19 100644 --- a/__tests__/neovis.tests.ts +++ b/__tests__/neovis.tests.ts @@ -603,19 +603,19 @@ describe('Neovis', () => { yield record; } }, - } as Partial], ['Async Iterable', { + } as Partial], ['Async Iterable', { ...dataFunctionSharedConfig, async dataFunction() { return retData; }, - } as Partial], ['ASync Generator', { + } as Partial], ['ASync Generator', { ...dataFunctionSharedConfig, async *dataFunction() { for (const record of retData) { yield record; } }, - } as Partial]])('neovis dataFunction %s test', (configName: string, config) => { + } as Partial]])('neovis dataFunction %s test', (configName: string, config) => { beforeEach(() => { neovis = new Neovis(config as NonFlatNeovisConfig | NeovisConfig); }); diff --git a/package.json b/package.json index 4c72ee1..6ffc04d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "neovis.js", - "version": "2.1.0-alpha7", + "version": "2.1.0-alpha8", "description": "Graph visualizations powered by vis.js with data from Neo4j.", "main": "./dist/neovis.js", "module": "./dist/neovis-without-dependencies.js", @@ -11,7 +11,9 @@ "test": "`__tests__" }, "scripts": { - "test": "jest __tests__/neovis.tests.ts", + "test": "run-p test:*", + "test:jest": "jest __tests__/neovis.tests.ts", + "test:types": "tsc --esModuleInterop --allowSyntheticDefaultImports --moduleResolution Node --target esnext --noemit ./__tests__/neovis.tests.ts", "eslint": "eslint .", "prepublishOnly": "run-s typedoc build", "clean": "rimraf ./dist", diff --git a/src/neovis.ts b/src/neovis.ts index 678ae1e..d52c95f 100644 --- a/src/neovis.ts +++ b/src/neovis.ts @@ -11,6 +11,7 @@ import deepmerge from 'deepmerge'; import type * as VisNetwork from 'vis-network'; import { Cypher, + DataFunctionType, Edge, LabelConfig, Neo4jConfig, @@ -560,19 +561,19 @@ export class NeoVis { /** * Renders the network */ - render(query?: Cypher, parameters?: unknown): void { - if (this.#config.dataFunction) { - this.#runFunctionDataGetter(parameters); + render(query_or_function?: Cypher | DataFunctionType, parameters?: unknown): void { + if (this.#config.dataFunction || typeof query_or_function === 'function') { + this.#runFunctionDataGetter(typeof query_or_function === 'function' ? query_or_function : this.#config.dataFunction, parameters); } else { - this.#runNeo4jDataGetter(query, parameters); + this.#runNeo4jDataGetter(query_or_function as Cypher, parameters); } } - async #runFunctionDataGetter(parameters?: unknown) { + async #runFunctionDataGetter(func: DataFunctionType, parameters: unknown) { let recordCount = 0; try { const dataBuildPromises: Promise[] = []; - for await (const record of await this.#config.dataFunction(parameters)) { + for await (const record of await func(parameters)) { dataBuildPromises.push(this.#createSingleRecord(record)); recordCount++; } @@ -733,17 +734,17 @@ export class NeoVis { * Reset the config object and reload data * @param config */ - reinit(config: NeovisConfig | NonFlatNeovisConfig): void { + reinit(config: NeovisConfig | NonFlatNeovisConfig, parameter?: unknown): void { this.#init(config); - this.render(); + this.render(undefined, parameter); } /** * Clear the network and fetch live data form the server and reload the visualization */ - reload(): void { + reload(parameter?: unknown): void { this.clearNetwork(); - this.render(); + this.render(undefined, parameter); } /** @@ -757,21 +758,42 @@ export class NeoVis { /** * Execute an arbitrary Cypher query and re-render the visualization * @param query + * @param parameters - parameters to send to the cypher */ - renderWithCypher(query: Cypher): void { + renderWithCypher(query: Cypher, parameters?: unknown): void { // this._config.initialCypher = query; this.clearNetwork(); this.#query = query; - this.render(); + this.render(undefined, parameters); + } + + /** + * Execute an arbitrary function and re-render the visualization + * @param func + * @param parameters - parameters to send to the function + */ + renderWithFunction(func: DataFunctionType, parameters?: unknown): void { + this.clearNetwork(); + this.render(func, parameters); } /** * Execute an arbitrary Cypher query and update the current visualization, retaning current nodes - * This function will not change the original query given by renderWithCypher or the inital cypher. - * @param query + * This function will not change the original query given by renderWithCypher or the inital cypher. + * @param parameters - parameters to send to the cypher + * + */ + updateWithCypher(query: Cypher, parameters?: unknown): void { + this.render(query, parameters); + } + + /** + * Execute an arbitrary function and update the visualization + * @param func + * @param parameters - parameters to send to the function */ - updateWithCypher(query: Cypher): void { - this.render(query); + updateWithFunction(func: DataFunctionType, parameters?: unknown): void { + this.render(func, parameters); } } diff --git a/src/types.ts b/src/types.ts index a594e93..09e767b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,6 +7,7 @@ export const NEOVIS_ADVANCED_CONFIG = Symbol(); export type NumberOrInteger = number | Neo4jTypes.Integer; export type RecursiveMapToDist = T extends object ? RecursiveMapTo : New +export type DataFunctionType = (any?: unknown) => AsyncIterable | Promise> | Iterable; /** * Maps a type recursively and replace each non object type with the new type @@ -115,10 +116,13 @@ export interface BaseNeovisConfig { /** - * function to get the data instead of neo4j driver - * @returns list of neo4j data + * function to get fetch data instead of neo4j driver + * + * it needs to return a list of records + * + * example in examples/simple-dataFunction-example.html */ - dataFunction?: (any?: unknown) => AsyncIterable | Promise> | Iterable + dataFunction?: DataFunctionType /** * The Cypher query that will get the data