├── resources
├── final.png
├── light
│ ├── document.svg
│ ├── edit.svg
│ ├── folder.svg
│ ├── boolean.svg
│ ├── dependency.svg
│ ├── refresh.svg
│ ├── number.svg
│ └── string.svg
└── dark
│ ├── edit.svg
│ ├── document.svg
│ ├── folder.svg
│ ├── boolean.svg
│ ├── dependency.svg
│ ├── refresh.svg
│ ├── number.svg
│ └── string.svg
├── .gitignore
├── DOCUMENTATION
├── Trinity-Logo.png
├── gifs
│ └── basicDemo.gif
└── docs
│ ├── featureRequest.md
│ ├── bugReport.md
│ └── contributing.md
├── .vscodeignore
├── .trinity.json
├── .vscode
├── extensions.json
├── tasks.json
├── settings.json
└── launch.json
├── CHANGELOG.md
├── src
├── server
│ └── neo4j
│ │ ├── sampleOutput
│ │ ├── labelsAndPropertySummary.json
│ │ ├── relationshipSummary.json
│ │ └── movie.cypher
│ │ ├── types
│ │ ├── query-runner.d.ts
│ │ ├── transaction.d.ts
│ │ ├── result-rx.d.ts
│ │ ├── transaction-rx.d.ts
│ │ ├── spatial-types.d.ts
│ │ ├── error.d.ts
│ │ ├── result.d.ts
│ │ ├── record.d.ts
│ │ ├── session-rx.d.ts
│ │ ├── session.d.ts
│ │ ├── graph-types.d.ts
│ │ ├── result-summary.d.ts
│ │ ├── driver.d.ts
│ │ ├── temporal-types.d.ts
│ │ ├── integer.d.ts
│ │ └── index.d.ts
│ │ └── graphdb-outline-ts.ts
├── test
│ ├── runTest.ts
│ └── suite
│ │ ├── index.ts
│ │ └── extension.test.ts
├── extension.ts
└── modules
│ ├── queryRunner.ts
│ ├── parseExtract.ts
│ ├── readConfig.ts
│ └── OutlineProvider.ts
├── .eslintrc.json
├── tsconfig.json
├── LICENSE
├── webpack.config.js
├── vsc-extension-quickstart.md
├── package.json
└── README.md
/resources/final.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/Trinity/HEAD/resources/final.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
3 | .vscode-test/
4 | *.vsix
5 | .DS_Store
6 | Trinity.code-workspace
7 |
--------------------------------------------------------------------------------
/DOCUMENTATION/Trinity-Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/Trinity/HEAD/DOCUMENTATION/Trinity-Logo.png
--------------------------------------------------------------------------------
/DOCUMENTATION/gifs/basicDemo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/Trinity/HEAD/DOCUMENTATION/gifs/basicDemo.gif
--------------------------------------------------------------------------------
/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | .vscode-test/**
3 | out/test/**
4 | src/**
5 | .gitignore
6 | vsc-extension-quickstart.md
7 | **/tsconfig.json
8 | **/.eslintrc.json
9 | **/*.map
10 | **/*.ts
11 |
--------------------------------------------------------------------------------
/.trinity.json:
--------------------------------------------------------------------------------
1 | {
2 | "dbAddress": "bolt://localhost",
3 | "username": "neo4j",
4 | "password": "test",
5 | "readOnly": true,
6 | "clearChannelOnSave": false,
7 | "cearChannelOnSave": false
8 | }
9 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "dbaeumer.vscode-eslint"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to the "trinity" extension will be documented in this file.
4 |
5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6 |
7 | ## [Unreleased]
8 |
9 | - Initial release
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | // See https://go.microsoft.com/fwlink/?LinkId=733558
2 | // for the documentation about the tasks.json format
3 | {
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "type": "npm",
8 | "script": "watch",
9 | "problemMatcher": "$tsc-watch",
10 | "isBackground": true,
11 | "presentation": {
12 | "reveal": "never"
13 | },
14 | "group": {
15 | "kind": "build",
16 | "isDefault": true
17 | }
18 | }
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/src/server/neo4j/sampleOutput/labelsAndPropertySummary.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "label": "Database",
4 | "properties": ["name"]
5 | },
6 | {
7 | "label": "Message",
8 | "properties": ["name"]
9 | },
10 | {
11 | "label": "Movie",
12 | "properties": ["title", "tagline", "released"]
13 | },
14 | {
15 | "label": "PERSON",
16 | "properties": ["name"]
17 | },
18 | {
19 | "label": "Person",
20 | "properties": ["born", "name"]
21 | }
22 | ]
23 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | // Place your settings in this file to overwrite default and user settings.
2 | {
3 | "files.exclude": {
4 | "out": false // set this to true to hide the "out" folder with the compiled JS files
5 | },
6 | "search.exclude": {
7 | "out": true // set this to false to include "out" folder in search results
8 | },
9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10 | "typescript.tsc.autoDetect": "off"
11 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "parserOptions": {
5 | "ecmaVersion": 6,
6 | "sourceType": "module"
7 | },
8 | "plugins": [
9 | "@typescript-eslint"
10 | ],
11 | "rules": {
12 | "@typescript-eslint/class-name-casing": "warn",
13 | "@typescript-eslint/semi": "warn",
14 | "curly": "warn",
15 | "eqeqeq": "warn",
16 | "no-throw-literal": "warn",
17 | "semi": "off"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/resources/light/document.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/dark/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es6",
5 | "outDir": "out",
6 | "lib": [
7 | "es6"
8 | ],
9 | "sourceMap": true,
10 | "rootDir": "src",
11 | "strict": true /* enable all strict type-checking options */
12 | /* Additional Checks */
13 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
14 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
15 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
16 | },
17 | "exclude": [
18 | "node_modules",
19 | ".vscode-test"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/resources/dark/document.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/test/runTest.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 |
3 | import { runTests } from 'vscode-test';
4 |
5 | async function main() {
6 | try {
7 | // The folder containing the Extension Manifest package.json
8 | // Passed to `--extensionDevelopmentPath`
9 | const extensionDevelopmentPath = path.resolve(__dirname, '../../');
10 |
11 | // The path to test runner
12 | // Passed to --extensionTestsPath
13 | const extensionTestsPath = path.resolve(__dirname, './suite/index');
14 |
15 | // Download VS Code, unzip it and run the integration test
16 | await runTests({ extensionDevelopmentPath, extensionTestsPath });
17 | } catch (err) {
18 | console.error('Failed to run tests');
19 | process.exit(1);
20 | }
21 | }
22 |
23 | main();
24 |
--------------------------------------------------------------------------------
/resources/light/folder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DOCUMENTATION/docs/featureRequest.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 |
12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
13 |
14 |
15 | **Describe the solution you'd like**
16 |
17 | A clear and concise description of what you want to happen.
18 |
19 |
20 | **Describe alternatives you've considered**
21 |
22 | A clear and concise description of any alternative solutions or features you've considered.
23 |
24 |
25 | **Additional context**
26 |
27 | Add any other context or screenshots about the feature request here.
28 |
29 |
--------------------------------------------------------------------------------
/resources/dark/folder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/dark/boolean.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/dark/dependency.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/boolean.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/dependency.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DOCUMENTATION/docs/bugReport.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG] "
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Version [e.g. 22]
29 | - VS Code Version
30 |
31 | **Additional context**
32 | Add any other context about the problem here.
33 |
--------------------------------------------------------------------------------
/src/server/neo4j/sampleOutput/relationshipSummary.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "originNode": ["Person"],
4 | "relationship": "ACTED_IN",
5 | "dependentNode": ["Movie"]
6 | },
7 | {
8 | "originNode": ["Person"],
9 | "relationship": "DIRECTED",
10 | "dependentNode": ["Movie"]
11 | },
12 | {
13 | "originNode": ["Person"],
14 | "relationship": "PRODUCED",
15 | "dependentNode": ["Movie"]
16 | },
17 | {
18 | "originNode": ["Person"],
19 | "relationship": "WROTE",
20 | "dependentNode": ["Movie"]
21 | },
22 | {
23 | "originNode": ["Person"],
24 | "relationship": "FOLLOWS",
25 | "dependentNode": ["Person"]
26 | },
27 | {
28 | "originNode": ["Person"],
29 | "relationship": "REVIEWED",
30 | "dependentNode": ["Movie"]
31 | },
32 | {
33 | "originNode": ["Database"],
34 | "relationship": "SAYS",
35 | "dependentNode": ["Message"]
36 | }
37 | ]
38 |
--------------------------------------------------------------------------------
/src/test/suite/index.ts:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import * as Mocha from 'mocha';
3 | import * as glob from 'glob';
4 |
5 | export function run(): Promise {
6 | // Create the mocha test
7 | const mocha = new Mocha({
8 | ui: 'tdd',
9 | });
10 | mocha.useColors(true);
11 |
12 | const testsRoot = path.resolve(__dirname, '..');
13 |
14 | return new Promise((c, e) => {
15 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
16 | if (err) {
17 | return e(err);
18 | }
19 |
20 | // Add files to the test suite
21 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
22 |
23 | try {
24 | // Run the mocha test
25 | mocha.run(failures => {
26 | if (failures > 0) {
27 | e(new Error(`${failures} tests failed.`));
28 | } else {
29 | c();
30 | }
31 | });
32 | } catch (err) {
33 | console.error(err);
34 | e(err);
35 | }
36 | });
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/resources/dark/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/query-runner.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import Result from "./result";
21 |
22 | declare type Parameters = { [key: string]: any };
23 |
24 | declare interface QueryRunner {
25 | run(query: string, parameters?: Parameters): Result;
26 | }
27 |
28 | export { Parameters };
29 |
30 | export default QueryRunner;
31 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/transaction.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import Result from "./result";
21 | import QueryRunner from "./query-runner";
22 |
23 | declare interface Transaction extends QueryRunner {
24 | commit(): Promise;
25 |
26 | rollback(): Promise;
27 |
28 | isOpen(): boolean;
29 | }
30 |
31 | export default Transaction;
32 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/result-rx.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | import { Observable } from "rxjs";
20 | import ResultSummary from "./result-summary";
21 | import Record from "./record";
22 |
23 | declare interface RxResult {
24 | keys(): Observable;
25 |
26 | records(): Observable;
27 |
28 | summary(): Observable;
29 | }
30 |
31 | export default RxResult;
32 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/transaction-rx.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | import { Observable } from "rxjs";
20 | import { Parameters } from "./query-runner";
21 | import RxResult from "./result-rx";
22 |
23 | declare interface RxTransaction {
24 | run(query: string, parameters?: Parameters): RxResult;
25 |
26 | commit(): Observable;
27 |
28 | rollback(): Observable;
29 | }
30 |
31 | export default RxTransaction;
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 OSLabs Beta
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | // A launch configuration that compiles the extension and then opens it inside a new window
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | {
6 | "version": "0.2.0",
7 | "configurations": [
8 | {
9 | "name": "Run Extension",
10 | "type": "extensionHost",
11 | "request": "launch",
12 | "runtimeExecutable": "${execPath}",
13 | "args": [
14 | "--extensionDevelopmentPath=${workspaceFolder}"
15 | ],
16 | "outFiles": [
17 | "${workspaceFolder}/out/**/*.js"
18 | ],
19 | "preLaunchTask": "${defaultBuildTask}"
20 | },
21 | {
22 | "name": "Extension Tests",
23 | "type": "extensionHost",
24 | "request": "launch",
25 | "runtimeExecutable": "${execPath}",
26 | "args": [
27 | "--extensionDevelopmentPath=${workspaceFolder}",
28 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
29 | ],
30 | "outFiles": [
31 | "${workspaceFolder}/out/test/**/*.js"
32 | ],
33 | "preLaunchTask": "${defaultBuildTask}"
34 | }
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/spatial-types.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import { NumberOrInteger } from "./graph-types";
21 | import Integer from "./integer";
22 |
23 | declare class Point {
24 | readonly srid: T;
25 | readonly x: number;
26 | readonly y: number;
27 | readonly z?: number;
28 |
29 | constructor(srid: T, x: number, y: number, z?: number);
30 | }
31 |
32 | declare function isPoint(obj: object): boolean;
33 |
34 | export { Point, isPoint };
35 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/error.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | declare const SERVICE_UNAVAILABLE: string;
21 | declare const SESSION_EXPIRED: string;
22 | declare const PROTOCOL_ERROR: string;
23 |
24 | declare function newError(message: any, code?: string): Neo4jError;
25 |
26 | declare class Neo4jError extends Error {
27 | code: string;
28 | message: string;
29 |
30 | constructor(message: any, code?: string);
31 | }
32 |
33 | export {
34 | newError,
35 | Neo4jError,
36 | SERVICE_UNAVAILABLE,
37 | SESSION_EXPIRED,
38 | PROTOCOL_ERROR
39 | };
40 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/result.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import ResultSummary from "./result-summary";
21 | import Record from "./record";
22 |
23 | declare type QueryResult = {
24 | records: Record[];
25 | summary: ResultSummary;
26 | };
27 |
28 | declare type ResultObserver = {
29 | onKeys?(keys: string[]): void;
30 | onNext?(record: Record): void;
31 | onCompleted?(summary: ResultSummary): void;
32 | onError?(error: Error): void;
33 | };
34 |
35 | declare interface Result extends Promise {
36 | subscribe(observer: ResultObserver): void;
37 | }
38 |
39 | export { QueryResult, ResultObserver };
40 | export default Result;
41 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/record.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | declare type Visitor = (value: any, key: string, record: Record) => void;
21 |
22 | declare type MapVisitor = (value: any, key: string, record: Record) => T;
23 |
24 | declare class Record {
25 | keys: string[];
26 | length: number;
27 | _fields: any[];
28 |
29 | constructor(
30 | keys: string[],
31 | fields: any[],
32 | fieldLookup?: { [index: string]: string }
33 | );
34 |
35 | forEach(visitor: Visitor): void;
36 |
37 | map(visitor: MapVisitor): T[];
38 |
39 | toObject(): object;
40 |
41 | get(key: string | number): any;
42 |
43 | has(key: string | number): boolean;
44 | }
45 |
46 | export default Record;
47 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | //@ts-check
2 |
3 | 'use strict';
4 |
5 | const path = require('path');
6 |
7 | /**
8 | * @type {import('webpack').Configuration}
9 | *
10 | * */
11 |
12 | const config = {
13 | target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
14 |
15 | entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
16 | output: {
17 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
18 | path: path.resolve(__dirname, 'dist'),
19 | filename: 'extension.js',
20 | libraryTarget: 'commonjs2',
21 | devtoolModuleFilenameTemplate: '../[resource-path]'
22 | },
23 | devtool: 'source-map',
24 | externals: {
25 | vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
26 | },
27 | resolve: {
28 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
29 | extensions: ['.ts', '.js']
30 | },
31 | module: {
32 | rules: [
33 | {
34 | test: /\.ts$/,
35 | exclude: /node_modules/,
36 | use: [
37 | {
38 | loader: 'ts-loader'
39 | }
40 | ]
41 | }
42 | ]
43 | }
44 | };
45 | module.exports = config;
--------------------------------------------------------------------------------
/src/server/neo4j/types/session-rx.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | import RxResult from "./result-rx";
20 | import RxTransaction from "./transaction-rx";
21 | import { TransactionConfig } from "./session";
22 | import { Parameters } from "./query-runner";
23 | import { Observable } from "rxjs";
24 |
25 | declare type RxTransactionWork = (tx: RxTransaction) => Observable;
26 |
27 | declare interface RxSession {
28 | run(
29 | query: string,
30 | parameters?: Parameters,
31 | config?: TransactionConfig
32 | ): RxResult;
33 |
34 | beginTransaction(config?: TransactionConfig): Observable;
35 |
36 | lastBookmark(): string | null;
37 |
38 | readTransaction(
39 | work: RxTransactionWork,
40 | config?: TransactionConfig
41 | ): Observable;
42 |
43 | writeTransaction(
44 | work: RxTransactionWork,
45 | config?: TransactionConfig
46 | ): Observable;
47 |
48 | close(): Observable;
49 | }
50 |
51 | export default RxSession;
52 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/session.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import Transaction from "./transaction";
21 | import QueryRunner, { Parameters } from "./query-runner";
22 | import Result from "./result";
23 | import { NumberOrInteger } from "./graph-types";
24 |
25 | declare type TransactionWork = (tx: Transaction) => T | Promise;
26 |
27 | declare interface TransactionConfig {
28 | timeout?: NumberOrInteger;
29 | metadata?: object;
30 | }
31 |
32 | declare interface Session extends QueryRunner {
33 | run(
34 | query: string,
35 | parameters?: Parameters,
36 | config?: TransactionConfig
37 | ): Result;
38 |
39 | beginTransaction(config?: TransactionConfig): Transaction;
40 |
41 | lastBookmark(): string | null;
42 |
43 | readTransaction(
44 | work: TransactionWork,
45 | config?: TransactionConfig
46 | ): Promise;
47 |
48 | writeTransaction(
49 | work: TransactionWork,
50 | config?: TransactionConfig
51 | ): Promise;
52 |
53 | close(): Promise;
54 | }
55 |
56 | export { TransactionConfig };
57 |
58 | export default Session;
59 |
--------------------------------------------------------------------------------
/src/extension.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from "vscode";
2 | import { QueryRunner } from "./modules/queryRunner";
3 | const { OutlineProvider }=require("./modules/OutlineProvider");
4 | import { TrinityConfig } from "./modules/readConfig";
5 |
6 | // this required method is called when your extension is activated
7 | export function activate(context: vscode.ExtensionContext) {
8 | vscode.commands.registerCommand("extension.runTrinity", () => {
9 | vscode.window.showInformationMessage(
10 | "Trinity is now running! Add your workspace at the search bar at top of window."
11 | );
12 | });
13 |
14 | // Load configuration and event watcher
15 | const trinityConfig: TrinityConfig=new TrinityConfig();
16 | // Trigger event watcher
17 | trinityConfig.getActiveWorkspace().then(() => {
18 | // Loading outline provider with active settings
19 | const OP=new OutlineProvider(context, trinityConfig);
20 | // displaying view
21 | OP.show();
22 | vscode.window.registerTreeDataProvider("trinityOutline", OP);
23 | vscode.commands.registerCommand("trinityOutline.refresh", () =>
24 | OP.createGraphStructure()
25 | );
26 | vscode.commands.registerCommand("trinityOutline.show", () => {
27 | OP.show();
28 | });
29 | // Create a new setup Extension to handle live querying and
30 | // create a Trinity Channel
31 | const queryRunner=new QueryRunner(trinityConfig);
32 | // functionality executed every time the active document is saved
33 | vscode.workspace.onDidSaveTextDocument(event =>
34 | queryRunner.handleSave(event)
35 | );
36 |
37 | // deactivate functionality
38 | vscode.commands.registerCommand("extension.deactivateTrinity", () => {
39 | // this command will restart window automatically and Trinity extension will not be running
40 | vscode.commands.executeCommand("workbench.action.reloadWindow");
41 | });
42 | });
43 | }
44 |
45 | export function deactivate() { }
46 |
--------------------------------------------------------------------------------
/DOCUMENTATION/docs/contributing.md:
--------------------------------------------------------------------------------
1 | ## Contributing to Trinity
2 |
3 | We would appreciate any input on making Trinity better. To contribute for any bugs please follow the instructions below.
4 |
5 | ### Reporting a bug
6 |
7 | Discussing the current state of the code
8 | Submitting a fix
9 | Proposing new features
10 | We Develop with Github
11 | We use Github to host code, to track issues and feature requests, as well as accept pull requests.
12 |
13 | All Code Changes Happen Through Pull Requests
14 | Pull requests are the best way to propose changes to Trinity. We actively welcome your pull requests:
15 |
16 | Fork the repo and create your branch from dev.
17 | If you've added code that should be tested, add tests.
18 | If you've changed APIs, update the documentation.
19 | Ensure the test suite passes.
20 | Make sure your code lints.
21 | Issue that pull request!
22 | Any contributions you make will be under the MIT Software License
23 | In short, when you submit code changes, your submissions are understood to be under the same that covers the project. Feel free to contact the maintainers if that's a concern.
24 |
25 | ### Report bugs using Github's issues
26 |
27 | We use GitHub issues to track public bugs. Report a bug by opening a new issue; it's that easy!
28 |
29 | Write bug reports with detail, background, and sample code
30 | Great Bug Reports tend to have:
31 |
32 | ### A quick summary and/or background
33 |
34 | Steps to reproduce
35 | Be specific!
36 | Give sample code if you can. Include sample code that anyone can run to reproduce what you are experiencing
37 | What you expected would happen
38 | What actually happens
39 | Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
40 | People love thorough bug reports. I'm not even kidding.
41 |
42 | ### Use a Consistent Coding Style (Airbnb)
43 |
44 | We have our included our eslint setup in this repo to make this as painless as possible. Please also install the VS Code [Eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) extension.
45 |
46 | #### License
47 |
48 | By contributing, you agree that your contributions will be licensed under its MIT License.
49 |
50 | #### References
51 |
52 | This document was adapted from the open-source contribution guidelines for Facebook's Draft
53 |
--------------------------------------------------------------------------------
/vsc-extension-quickstart.md:
--------------------------------------------------------------------------------
1 | # Welcome to your VS Code Extension
2 |
3 | ## What's in the folder
4 |
5 | * This folder contains all of the files necessary for your extension.
6 | * `package.json` - this is the manifest file in which you declare your extension and command.
7 | * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin.
8 | * `src/extension.ts` - this is the main file where you will provide the implementation of your command.
9 | * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
10 | * We pass the function containing the implementation of the command as the second parameter to `registerCommand`.
11 |
12 | ## Get up and running straight away
13 |
14 | * Press `F5` to open a new window with your extension loaded.
15 | * Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`.
16 | * Set breakpoints in your code inside `src/extension.ts` to debug your extension.
17 | * Find output from your extension in the debug console.
18 |
19 | ## Make changes
20 |
21 | * You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`.
22 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
23 |
24 |
25 | ## Explore the API
26 |
27 | * You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`.
28 |
29 | ## Run tests
30 |
31 | * Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`.
32 | * Press `F5` to run the tests in a new window with your extension loaded.
33 | * See the output of the test result in the debug console.
34 | * Make changes to `src/test/suite/extension.test.ts` or create new test files inside the `test/suite` folder.
35 | * The provided test runner will only consider files matching the name pattern `**.test.ts`.
36 | * You can create folders inside the `test` folder to structure your tests any way you want.
37 |
38 | ## Go further
39 |
40 | * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension).
41 | * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace.
42 | * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration).
43 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "trinity",
3 | "displayName": "Trinity",
4 | "description": "VSCode extension for Cypher and Neo4j",
5 | "version": "0.2.0",
6 | "publisher": "Trinity",
7 | "icon": "resources/final.png",
8 | "engines": {
9 | "vscode": "^1.42.0"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/oslabs-beta/Trinity"
14 | },
15 | "categories": [
16 | "Extension Packs",
17 | "Language Packs",
18 | "Other"
19 | ],
20 | "activationEvents": [
21 | "onCommand:extension.runTrinity",
22 | "onCommand:extension.deactivateTrinity"
23 | ],
24 | "main": "./out/extension.js",
25 | "contributes": {
26 | "commands": [
27 | {
28 | "command": "extension.runTrinity",
29 | "title": "Trinity: Run Trinity"
30 | },
31 | {
32 | "command": "extension.deactivateTrinity",
33 | "title": "Trinity: Deactivate Trinity"
34 | },
35 | {
36 | "command": "trinityOutline.refresh",
37 | "title": "Refresh",
38 | "icon": {
39 | "light": "resources/light/refresh.svg",
40 | "dark": "resources/dark/refresh.svg"
41 | }
42 | }
43 | ],
44 | "views": {
45 | "explorer": [
46 | {
47 | "id": "trinityOutline",
48 | "name": "Trinity Outline",
49 | "when": "trinityOutlineEnabled"
50 | }
51 | ]
52 | },
53 | "menus": {
54 | "view/title": [
55 | {
56 | "command": "trinityOutline.refresh",
57 | "when": "view == trinityOutline",
58 | "group": "navigation"
59 | }
60 | ]
61 | }
62 | },
63 | "scripts": {
64 | "vscode:prepublish": "webpack --mode production",
65 | "compile": "tsc -p ./",
66 | "lint": "eslint src --ext ts",
67 | "watch": "tsc -watch -p ./",
68 | "pretest": "npm run compile && npm run lint",
69 | "test": "node ./out/test/runTest.js",
70 | "webpack": "webpack --mode development",
71 | "webpack-dev": "webpack --mode development -watch",
72 | "test-compile": "tsc -p ./"
73 | },
74 | "devDependencies": {
75 | "@types/find": "^0.2.1",
76 | "@types/glob": "^7.1.1",
77 | "@types/mocha": "^7.0.1",
78 | "@types/node": "^12.12.28",
79 | "@types/vscode": "^1.42.0",
80 | "@typescript-eslint/eslint-plugin": "^2.18.0",
81 | "@typescript-eslint/parser": "^2.18.0",
82 | "eslint": "^6.8.0",
83 | "glob": "^7.1.6",
84 | "mocha": "^7.0.1",
85 | "ts-loader": "^6.2.1",
86 | "typescript": "^3.7.5",
87 | "vscode-test": "^1.3.0",
88 | "webpack": "^4.41.6",
89 | "webpack-cli": "^3.3.11"
90 | },
91 | "dependencies": {
92 | "find": "^0.3.0",
93 | "neo4j-driver": "^4.0.1",
94 | "parcel-bundler": "^1.12.4",
95 | "parcel-plugin-typescript": "^1.0.0",
96 | "walk": "^2.3.14"
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/graph-types.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import Integer from "./integer";
21 |
22 | declare type StandardDate = Date;
23 | declare type NumberOrInteger = number | Integer;
24 |
25 | declare class Node {
26 | identity: T;
27 | labels: string[];
28 | properties: object;
29 |
30 | constructor(identity: T, labels: string[], properties: object);
31 |
32 | toString(): string;
33 | }
34 |
35 | declare class Relationship {
36 | identity: T;
37 | start: T;
38 | end: T;
39 | type: string;
40 | properties: object;
41 |
42 | constructor(identity: T, start: T, end: T, type: string, properties: object);
43 |
44 | toString(): string;
45 | }
46 |
47 | declare class UnboundRelationship {
48 | identity: T;
49 | type: string;
50 | properties: object;
51 |
52 | constructor(identity: T, type: string, properties: object);
53 |
54 | bind(start: T, end: T): Relationship;
55 |
56 | toString(): string;
57 | }
58 |
59 | declare class PathSegment {
60 | start: Node;
61 | relationship: Relationship;
62 | end: Node;
63 |
64 | constructor(start: Node, rel: Relationship, end: Node);
65 | }
66 |
67 | declare class Path {
68 | start: Node;
69 | end: Node;
70 | segments: PathSegment[];
71 | length: number;
72 |
73 | constructor(start: Node, end: Node, segments: PathSegment[]);
74 | }
75 |
76 | declare function isNode(obj: object): boolean;
77 |
78 | declare function isRelationship(obj: object): boolean;
79 |
80 | declare function isUnboundRelationship(obj: object): boolean;
81 |
82 | declare function isPath(obj: object): boolean;
83 |
84 | declare function isPathSegment(obj: object): boolean;
85 |
86 | export {
87 | Node,
88 | Relationship,
89 | UnboundRelationship,
90 | Path,
91 | PathSegment,
92 | isNode,
93 | isRelationship,
94 | isUnboundRelationship,
95 | isPath,
96 | isPathSegment,
97 | NumberOrInteger,
98 | StandardDate
99 | };
100 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/result-summary.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import Integer from "./integer";
21 | import { NumberOrInteger } from "./graph-types";
22 |
23 | declare interface ResultSummary {
24 | query: { text: string; parameters: { [key: string]: any } };
25 | queryType: string;
26 | counters: QueryStatistic;
27 | plan: Plan;
28 | profile: ProfiledPlan;
29 | notifications: Notification[];
30 | server: ServerInfo;
31 | resultConsumedAfter: T;
32 | resultAvailableAfter: T;
33 |
34 | hasPlan(): boolean;
35 |
36 | hasProfile(): boolean;
37 | }
38 |
39 | declare interface Plan {
40 | operatorType: string;
41 | identifiers: string[];
42 | arguments: { [key: string]: string };
43 | children: Plan[];
44 | }
45 |
46 | declare interface ProfiledPlan {
47 | operatorType: string;
48 | identifiers: string[];
49 | arguments: { [key: string]: string };
50 | dbHits: number;
51 | rows: number;
52 | pageCacheMisses: number;
53 | pageCacheHits: number;
54 | pageCacheHitRatio: number;
55 | time: number;
56 |
57 | hasPageCacheStats(): boolean;
58 |
59 | children: ProfiledPlan[];
60 | }
61 |
62 | declare interface QueryStatistic {
63 | containsUpdates(): boolean;
64 |
65 | containsSystemUpdates(): boolean;
66 |
67 | updates(): { [key: string]: number };
68 |
69 | systemUpdates(): number;
70 | }
71 |
72 | declare type NotificationPosition = {
73 | offset: number;
74 | line: number;
75 | column: number;
76 | };
77 |
78 | declare interface Notification {
79 | code: string;
80 | title: string;
81 | description: string;
82 | severity: string;
83 | position: NotificationPosition | {};
84 | }
85 |
86 | declare interface ServerInfo {
87 | address: string;
88 | version: string;
89 | }
90 |
91 | declare const queryType: {
92 | READ_ONLY: "r";
93 | READ_WRITE: "rw";
94 | WRITE_ONLY: "w";
95 | SCHEMA_WRITE: "s";
96 | };
97 |
98 | export {
99 | queryType,
100 | Plan,
101 | ProfiledPlan,
102 | QueryStatistic,
103 | Notification,
104 | ServerInfo,
105 | NotificationPosition
106 | };
107 |
108 | export default ResultSummary;
109 |
--------------------------------------------------------------------------------
/src/test/suite/extension.test.ts:
--------------------------------------------------------------------------------
1 | import * as assert from "assert";
2 |
3 | const { parseExtract } = require("../../modules/parseExtract");
4 | const { extract } = require("../../modules/parseExtract");
5 | const { OutlineProvider } = require("../../modules/OutlineProvider");
6 |
7 | //import { expect } from "chai";
8 |
9 | // You can import and use all API from the 'vscode' module
10 | // as well as import your extension to test it
11 | import * as vscode from "vscode";
12 | // import * as myExtension from '../extension';
13 |
14 | suite("Extension Test Suite", () => {
15 | vscode.window.showInformationMessage("Start all tests.");
16 |
17 | const exResultData = {
18 | graphOutline: [
19 | { label: "Movie", properties: ["title", "tagline", "released"] },
20 | { label: "Person", properties: ["born", "name"] }
21 | ],
22 | uniDirectionalRelationship: [
23 | {
24 | originNode: ["Person"],
25 | relationship: "ACTED_IN",
26 | dependentNode: ["Movie"]
27 | },
28 | {
29 | originNode: ["Person"],
30 | relationship: "ACTED_IN",
31 | dependentNode: ["Movie"]
32 | }
33 | ],
34 | biDirectionalRelationship: []
35 | };
36 |
37 | const testConfig = {
38 | activeSettings: {
39 | dbAddress: "bolt://localhost",
40 | username: "neo4j",
41 | password: "test"
42 | }
43 | };
44 |
45 | test("Sample test", () => {
46 | assert.equal(-1, [1, 2, 3].indexOf(5));
47 | assert.equal(-1, [1, 2, 3].indexOf(0));
48 | });
49 |
50 | test("Extract functionality", () => {
51 | const extractObj = extract("Trinity('Test') stuff");
52 | assert.equal(extractObj.queryString, "Test");
53 | assert.equal(extractObj.currIndex, 14);
54 | });
55 |
56 | test("parseExtract functionality", () => {
57 | const queryArray = parseExtract(
58 | "Trinity('Test') stuff Trinity('anotherTest')"
59 | );
60 | assert.equal(queryArray[0], "Test");
61 | assert.equal(queryArray[1], "anotherTest");
62 | });
63 | //Testing OutlineProvier methods
64 |
65 | const outlineProvider = new OutlineProvider(undefined, testConfig);
66 | const exResultObj = outlineProvider.createResultObj(exResultData);
67 |
68 | test("OutlineProvider class", () => {
69 | assert.equal(exResultObj.Person.Properties[0], "born");
70 | assert.equal(exResultObj.Movie.Properties[1], "tagline");
71 | assert.equal(exResultObj.Person["Uni-Directional"].ACTED_IN[0], "Movie");
72 | });
73 |
74 | // testing setUpData method
75 |
76 | const treeData = outlineProvider.setUpData(exResultObj);
77 |
78 | test("setUpData method", () => {
79 | assert.equal(treeData[0].label, "Person");
80 | assert.equal(treeData[0].children[0].label, "Uni-Directional");
81 | assert.equal(treeData[0].children[0].children[0].label, "ACTED_IN");
82 | assert.equal(
83 | treeData[0].children[0].children[0].children[0].label,
84 | "Movie"
85 | );
86 | });
87 | });
88 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/driver.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import Session from "./session";
21 | import RxSession from "./session-rx";
22 | import { Parameters } from "./query-runner";
23 | import { Neo4jError } from "./error";
24 | import { ServerInfo } from "./result-summary";
25 |
26 | declare interface AuthToken {
27 | scheme: string;
28 | principal: string;
29 | credentials: string;
30 | realm?: string;
31 | parameters?: Parameters;
32 | }
33 |
34 | declare type EncryptionLevel = "ENCRYPTION_ON" | "ENCRYPTION_OFF";
35 | declare type TrustStrategy =
36 | | "TRUST_ALL_CERTIFICATES"
37 | | "TRUST_CUSTOM_CA_SIGNED_CERTIFICATES"
38 | | "TRUST_SYSTEM_CA_SIGNED_CERTIFICATES";
39 |
40 | declare type LogLevel = "error" | "warn" | "info" | "debug";
41 |
42 | declare interface LoggingConfig {
43 | level?: LogLevel;
44 | logger: (level: LogLevel, message: string) => void;
45 | }
46 |
47 | declare interface Config {
48 | encrypted?: boolean | EncryptionLevel;
49 | trust?: TrustStrategy;
50 | trustedCertificates?: string[];
51 | knownHosts?: string;
52 | fetchSize?: number;
53 | maxConnectionPoolSize?: number;
54 | maxTransactionRetryTime?: number;
55 | maxConnectionLifetime?: number;
56 | connectionAcquisitionTimeout?: number;
57 | connectionTimeout?: number;
58 | disableLosslessIntegers?: boolean;
59 | logging?: LoggingConfig;
60 | resolver?: (address: string) => string[] | Promise;
61 | }
62 |
63 | declare type SessionMode = "READ" | "WRITE";
64 |
65 | declare const READ: SessionMode;
66 | declare const WRITE: SessionMode;
67 |
68 | declare interface Driver {
69 | session({
70 | defaultAccessMode,
71 | bookmarks,
72 | database,
73 | fetchSize
74 | }?: {
75 | defaultAccessMode?: SessionMode;
76 | bookmarks?: string | string[];
77 | fetchSize?: number;
78 | database?: string;
79 | }): Session;
80 |
81 | rxSession({
82 | defaultAccessMode,
83 | bookmarks,
84 | database,
85 | fetchSize
86 | }?: {
87 | defaultAccessMode?: SessionMode;
88 | bookmarks?: string | string[];
89 | fetchSize?: number;
90 | database?: string;
91 | }): RxSession;
92 |
93 | close(): Promise;
94 |
95 | verifyConnectivity(): Promise;
96 |
97 | supportsMultiDb(): Promise;
98 | }
99 |
100 | export {
101 | Driver,
102 | READ,
103 | WRITE,
104 | AuthToken,
105 | Config,
106 | EncryptionLevel,
107 | TrustStrategy,
108 | SessionMode
109 | };
110 |
111 | export default Driver;
112 |
--------------------------------------------------------------------------------
/src/modules/queryRunner.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from "vscode";
2 | import { TrinityConfig } from "./readConfig";
3 | const fs=require("fs");
4 | const { parseExtract, extract }=require("./parseExtract");
5 | import neo4j from "neo4j-driver";
6 | const path=require("path");
7 |
8 | export class QueryRunner {
9 | tChannel: vscode.OutputChannel;
10 | trinityConfig: TrinityConfig;
11 |
12 | constructor(trinityConfig: TrinityConfig) {
13 | this.trinityConfig=trinityConfig;
14 | this.tChannel=vscode.window.createOutputChannel("Trinity");
15 | }
16 | // executes each the active file is saved
17 | handleSave(event: vscode.TextDocument) {
18 | // read in the active file
19 | const result=parseExtract(fs.readFileSync(event.fileName).toString());
20 | // destructure the active settings from the .trinity.json file
21 | const {
22 | dbAddress,
23 | username,
24 | password,
25 | clearChannelOnSave,
26 | JSONOutputAbsolutePath,
27 | outputFilename
28 | }=this.trinityConfig.activeSettings||{};
29 | // if required settings are not present, notify the user and end early
30 | if (!dbAddress||!username||!password) {
31 | vscode.window.showInformationMessage(
32 | "Trinity: Unable to run Trinity Queries. Please check your login credentials in the .trinity.json file."
33 | );
34 | return;
35 | }
36 | // initialize connection to Neo4j DB
37 | const driver=neo4j.driver(
38 | dbAddress,
39 | neo4j.auth.basic(username, password)
40 | );
41 | // clear tChanel based on active settigs
42 | if (clearChannelOnSave) {
43 | this.tChannel.clear();
44 | }
45 | // create array to store return values from queries
46 | const promises=[];
47 | // define output file location
48 | const outputPath=path.resolve(JSONOutputAbsolutePath, outputFilename);
49 | // iterate across the queries
50 | for (let query of result) {
51 | // create a Neo4j session to submit the query to
52 | const session=driver.session({ defaultAccessMode: neo4j.session.READ });
53 | // only run valid queries
54 | if (!query) {
55 | this.tChannel.appendLine("Query skipped");
56 | continue;
57 | }
58 | // push the query into promises array, once all queries are returned
59 | // the promises array will be written to a json file at the outputPath.
60 | promises.push(
61 | session
62 | .readTransaction(tx => tx.run(query))
63 | .then(result => {
64 | this.tChannel.appendLine(query);
65 | this.tChannel.appendLine(
66 | `Result: ${JSON.stringify(result.records, null, 2)}`
67 | );
68 | return result;
69 | })
70 | .catch((err: Error): void => {
71 | vscode.window.showInformationMessage(
72 | "Trinity: Please check your query syntax."
73 | );
74 | })
75 | );
76 | }
77 |
78 | Promise.all(promises).then(values => {
79 | const stringObj=JSON.stringify(values, null, 2);
80 |
81 | // only writes non empty objects to the outputPath.
82 | if (stringObj!=="[]") {
83 | fs.writeFile(outputPath, stringObj, "utf8", (err: Error) => {
84 | if (!err) {
85 | return;
86 | }
87 | vscode.window.showInformationMessage(
88 | "Trinity: Unable to save queries to output file"
89 | );
90 | });
91 | }
92 | });
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/resources/dark/number.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/number.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/dark/string.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/resources/light/string.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/temporal-types.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import { NumberOrInteger, StandardDate } from "./graph-types";
21 | import Integer from "./integer";
22 |
23 | declare class Duration {
24 | readonly months: T;
25 | readonly days: T;
26 | readonly seconds: T;
27 | readonly nanoseconds: T;
28 |
29 | constructor(months: T, days: T, seconds: T, nanoseconds: T);
30 | }
31 |
32 | declare class LocalTime {
33 | readonly hour: T;
34 | readonly minute: T;
35 | readonly second: T;
36 | readonly nanosecond: T;
37 |
38 | constructor(hour: T, minute: T, second: T, nanosecond: T);
39 |
40 | static fromStandardDate(
41 | standardDate: StandardDate,
42 | nanosecond?: number
43 | ): LocalTime;
44 | }
45 |
46 | declare class Time {
47 | readonly hour: T;
48 | readonly minute: T;
49 | readonly second: T;
50 | readonly nanosecond: T;
51 | readonly timeZoneOffsetSeconds: T;
52 |
53 | constructor(
54 | hour: T,
55 | minute: T,
56 | second: T,
57 | nanosecond: T,
58 | timeZoneOffsetSeconds: T
59 | );
60 |
61 | static fromStandardDate(
62 | standardDate: StandardDate,
63 | nanosecond?: number
64 | ): Time;
65 | }
66 |
67 | declare class Date {
68 | readonly year: T;
69 | readonly month: T;
70 | readonly day: T;
71 |
72 | constructor(year: T, month: T, day: T);
73 |
74 | static fromStandardDate(standardDate: StandardDate): Date;
75 | }
76 |
77 | declare class LocalDateTime {
78 | readonly year: T;
79 | readonly month: T;
80 | readonly day: T;
81 | readonly hour: T;
82 | readonly minute: T;
83 | readonly second: T;
84 | readonly nanosecond: T;
85 |
86 | constructor(
87 | year: T,
88 | month: T,
89 | day: T,
90 | hour: T,
91 | minute: T,
92 | second: T,
93 | nanosecond: T
94 | );
95 |
96 | static fromStandardDate(
97 | standardDate: StandardDate,
98 | nanosecond?: number
99 | ): LocalDateTime;
100 | }
101 |
102 | declare class DateTime {
103 | readonly year: T;
104 | readonly month: T;
105 | readonly day: T;
106 | readonly hour: T;
107 | readonly minute: T;
108 | readonly second: T;
109 | readonly nanosecond: T;
110 | readonly timeZoneOffsetSeconds?: T;
111 | readonly timeZoneId?: string;
112 |
113 | constructor(
114 | year: T,
115 | month: T,
116 | day: T,
117 | hour: T,
118 | minute: T,
119 | second: T,
120 | nanosecond: T,
121 | timeZoneOffsetSeconds?: T,
122 | timeZoneId?: string
123 | );
124 |
125 | static fromStandardDate(
126 | standardDate: StandardDate,
127 | nanosecond?: number
128 | ): DateTime;
129 | }
130 |
131 | declare function isDuration(obj: object): boolean;
132 |
133 | declare function isLocalTime(obj: object): boolean;
134 |
135 | declare function isTime(obj: object): boolean;
136 |
137 | declare function isDate(obj: object): boolean;
138 |
139 | declare function isLocalDateTime(obj: object): boolean;
140 |
141 | declare function isDateTime(obj: object): boolean;
142 |
143 | export {
144 | Duration,
145 | LocalTime,
146 | Time,
147 | Date,
148 | LocalDateTime,
149 | DateTime,
150 | isDuration,
151 | isLocalTime,
152 | isTime,
153 | isDate,
154 | isLocalDateTime,
155 | isDateTime
156 | };
157 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/integer.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | declare class Integer {
21 | low: number;
22 | high: number;
23 |
24 | constructor(low?: number, high?: number);
25 |
26 | inSafeRange(): boolean;
27 |
28 | toInt(): number;
29 |
30 | toNumber(): number;
31 |
32 | toString(radix: number): string;
33 |
34 | getHighBits(): number;
35 |
36 | getLowBits(): number;
37 |
38 | getNumBitsAbs(): number;
39 |
40 | isZero(): boolean;
41 |
42 | isNegative(): boolean;
43 |
44 | isPositive(): boolean;
45 |
46 | isOdd(): boolean;
47 |
48 | isEven(): boolean;
49 |
50 | equals(other: Integer | number | string): boolean;
51 |
52 | notEquals(other: Integer | number | string): boolean;
53 |
54 | lessThan(other: Integer | number | string): boolean;
55 |
56 | lessThanOrEqual(other: Integer | number | string): boolean;
57 |
58 | greaterThan(other: Integer | number | string): boolean;
59 |
60 | greaterThanOrEqual(other: Integer | number | string): boolean;
61 |
62 | compare(other: Integer | number | string): number;
63 |
64 | negate(): Integer;
65 |
66 | add(addend: Integer | number | string): Integer;
67 |
68 | subtract(subtrahend: Integer | number | string): Integer;
69 |
70 | multiply(multiplier: Integer | number | string): Integer;
71 |
72 | div(divisor: Integer | number | string): Integer;
73 |
74 | modulo(divisor: Integer | number | string): Integer;
75 |
76 | not(): Integer;
77 |
78 | and(other: Integer | number | string): Integer;
79 |
80 | or(other: Integer | number | string): Integer;
81 |
82 | xor(other: Integer | number | string): Integer;
83 |
84 | shiftLeft(numBits: Integer | number): Integer;
85 |
86 | shiftRight(numBits: Integer | number): Integer;
87 |
88 | static __isInteger__: true;
89 |
90 | static isInteger(obj: object): boolean;
91 |
92 | static fromInt(value: number): Integer;
93 |
94 | static fromNumber(value: number): Integer;
95 |
96 | static fromBits(lowBits: number, highBits: number): Integer;
97 |
98 | static fromString(str: string, radix?: number): Integer;
99 |
100 | static fromValue(
101 | value: Integer | number | string | { low: number; high: number }
102 | ): Integer;
103 |
104 | static toNumber(
105 | value: Integer | number | string | { low: number; high: number }
106 | ): number;
107 |
108 | static toString(
109 | value: Integer | number | string | { low: number; high: number },
110 | radix?: number
111 | ): string;
112 |
113 | static inSafeRange(
114 | value: Integer | number | string | { low: number; high: number }
115 | ): boolean;
116 |
117 | static ZERO: Integer;
118 | static ONE: Integer;
119 | static NEG_ONE: Integer;
120 | static MAX_VALUE: Integer;
121 | static MIN_VALUE: Integer;
122 | static MIN_SAFE_VALUE: Integer;
123 | static MAX_SAFE_VALUE: Integer;
124 | }
125 |
126 | declare function int(
127 | value: Integer | number | string | { low: number; high: number }
128 | ): Integer;
129 |
130 | declare function isInt(obj: object): boolean;
131 |
132 | declare function inSafeRange(
133 | val: Integer | number | string | { low: number; high: number }
134 | ): boolean;
135 |
136 | declare function toNumber(
137 | val: Integer | number | string | { low: number; high: number }
138 | ): number;
139 |
140 | declare function toString(
141 | val: Integer | number | string | { low: number; high: number },
142 | radix?: number
143 | ): string;
144 |
145 | export { int, isInt, inSafeRange, toNumber, toString };
146 |
147 | export default Integer;
148 |
--------------------------------------------------------------------------------
/src/modules/parseExtract.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * ParseExtract accepts file contents as giant string and recursively calls extract function until Trinity queries are not found
3 | * within the string argument and returns an array of Cypher queries.
4 | *
5 | * findQuery: locates each instance of Trinity keyword (which contains a query) and recursively calls extract until Trinity queries are not found
6 | *
7 | * Extract: processes each query within Trinity function
8 | * @param string
9 | *
10 | */
11 |
12 | function parseExtract(string: string): Array {
13 | // Array for storing the Queries inside the string
14 | let array: Array = [];
15 |
16 | // Find queries inside of string, push them on to array
17 | const findQuery = (string: string) => {
18 | // find the location of trinity in the string
19 | const tlocation: number = string.search("Trinity");
20 |
21 | // if 0, Trinity hasn't been typed into the string
22 | if (tlocation !== -1) {
23 | // Create new string, which will be result of slicing from 'T' in Trinity
24 | let newString: string = string.slice(tlocation, string.length);
25 |
26 | //Create new variable for the query and end location
27 | //extract(newString) returns an object
28 | let queryNLocation: {
29 | queryString: string | boolean;
30 | currIndex: number;
31 | } = extract(newString);
32 |
33 | // push the query onto the main array
34 | array.push(queryNLocation.queryString);
35 |
36 | // recursively call the function find Query on the new string based on the location
37 | let remainingString: string = newString.slice(
38 | queryNLocation.currIndex + 1
39 | );
40 |
41 | // recursively call the function on the new string
42 | findQuery(remainingString);
43 | }
44 | };
45 |
46 | findQuery(string);
47 | return array;
48 | }
49 |
50 | const extract = (
51 | string: string
52 | ): { queryString: string | boolean; currIndex: number } => {
53 | const brackets: { [key: string]: string } = {
54 | "[": "PUSH TO STACK",
55 | "{": "PUSH TO STACK",
56 | "(": "PUSH TO STACK",
57 | "'": "'",
58 | '"': '"',
59 | "`": "`",
60 | "]": "[",
61 | "}": "{",
62 | ")": "("
63 | };
64 |
65 | // extract the query
66 | let stack: Array = [string[8]];
67 | let currIndex: number = 9;
68 | let queryString: string | boolean = "";
69 |
70 | // iterate until empty the stack, or find incorrect brackets
71 | while (stack.length > 0) {
72 | // store current char
73 | const currChar: string = string[currIndex];
74 | // store the brack[curChar]
75 | const bracket: string | undefined = brackets[currChar];
76 | // If the variable in brackets obj
77 | // CASE: Not a bracket => Go to next loop
78 | if (!bracket) {
79 | queryString += currChar;
80 | currIndex += 1;
81 | continue;
82 | }
83 | // CASE: PUSH TO STACK => Push it to the stack
84 | else if (bracket === "PUSH TO STACK") {
85 | stack.push(currChar);
86 | }
87 | // CASE: Else => pop it
88 | // CASE: currChar is quote and top of stack is not the same quote -> push it to stack
89 | else if (currChar === '"' || currChar === "'" || currChar === "`") {
90 | // CASE: currChar is quote and top of stack is the same quote -> pop from stack
91 | if (stack[stack.length - 1] === currChar) {
92 | stack.pop();
93 | } else {
94 | stack.push(currChar);
95 | }
96 | }
97 | // CASE: Closing Bracket & compliments top of stack -> pop from stack
98 | else if (currChar === "]" || currChar === "}" || currChar === ")") {
99 | if (stack[stack.length - 1] === bracket) {
100 | stack.pop();
101 | } else {
102 | // CASE: Closing Bracket & does not compliment top of stack -> return false and curr location
103 | queryString = false;
104 | break;
105 | }
106 | }
107 | // prepare for next iteration
108 | currIndex += 1;
109 | if (stack.length > 0) {
110 | queryString += currChar;
111 | }
112 | }
113 | return {
114 | queryString: queryString,
115 | currIndex: currIndex
116 | };
117 | };
118 |
119 | module.exports = { parseExtract, extract };
120 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Trinity
6 |
7 | ## What is Trinity?
8 |
9 | Trinity is a VS Code extension for previewing Neo4j queries and database structure within the VS Code environment. Trinity intends to remove the need for switching between VS Code and Neo4j Desktop or Neo4j Browser during the development process.
10 |
11 | ## Features
12 |
13 | ### **Core Features**
14 |
15 | 1. Connects to a user's Neo4j database and displays the graph database structure (Node Labels, Properties and Unidirectional/Bidirectional relationships).
16 | 2. Parses Neo4j/Cypher queries/mutations that are typed into the current open document in VS Code.
17 | 3. Sends the queries/mutations to a database as defined in the user's configuration file .
18 | 4. Renders the responses to the Trinity output channel on VS Code.
19 | 5. Optionally writes the output to a local JSON file based on the user's configuration.
20 |
21 |
22 |
23 | ## Getting Started
24 |
25 | ### **Installation**
26 |
27 | Trinity can be installed from the VS Code Extensions marketplace [here](https://marketplace.visualstudio.com/items?itemName=Trinity.trinity).
28 |
29 | ### **Setting up the config file**
30 |
31 | In your working directory create a
32 | `.trinity.json` file. The following configuration options are available for setup by the user:
33 |
34 | ```json
35 | {
36 | "dbAddress": "bolt://localhost",
37 | "username": "neo4j",
38 | "password": "test",
39 | "clearChannelOnSave": true,
40 | "writeOutputToJSON": true,
41 | "JSONOutputRelativePath": "./",
42 | "outputFilename": "output.json"
43 | }
44 | ```
45 |
46 | Required Settings: `dbAddess`, `username` and `password`.
47 |
48 | Default settings when not defined in the configuration file:
49 |
50 | ```json
51 | {
52 | "clearChannelOnSave": false,
53 | "writeOutputToJSON": false,
54 | "JSONOutputRelativePath": "./",
55 | "outputFilename": "output.json"
56 | }
57 | ```
58 |
59 | ## Write and Invoking your first Trinity query
60 |
61 | To activate the extension and connect to your Neo4j Database:
62 |
63 | 1. Search for Trinity from the command palette in VS Code (Cmd/Ctrl + Shift + P) and run the _`Trinity: Run Trinity`_ command.
64 | 2. To deactivate, search for Trinity from the command palette in VS Code (Cmd/Ctrl + Shift + P) and run the _`Trinity: Deactivate Trinity`_ command.
65 |
66 | The following steps are required to setup a `Trinity` query inside your working file.
67 |
68 | 1. Create a function declaration for your `Trinity` query
69 | 2. Invoke your Cypher Query within a Trinity function invocation\*
70 | 3. On every save, Trinity will send any requests inside of the `Trinity` functions to your Neo4j Database and show responses in the Trinity Output Channel. To send another request, create a new invocation of the `Trinity` function and put the new request as the argument. Output will also be saved to a JSON file if setup in the configuration file.
71 |
72 | _\*Multiple queries may be invoked within a single file. Current functionality does not support the passing of variables or parameterized queries._
73 |
74 | ---
75 |
76 | ### Sample Python Setup
77 |
78 | ```python
79 | # Create a Trinity function definition in your working file.
80 | def Trinity ():
81 | return
82 |
83 | # Anywhere in your open file, put a Neo4j Cypher query inside the Trinity function. For example:
84 | Trinity('Match (n{name: "Carrie-Anne Moss"}) Return n')
85 | ```
86 |
87 | ### Sample JavaScript Setup
88 |
89 | ```javascript
90 | // Create a Trinity function definition in your working file.
91 | function Trinity() {}
92 |
93 | // Anywhere in your open file, put a Neo4j Cypher query inside the Trinity function. For example:
94 | Trinity('Match (n{name: "Carrie-Anne Moss"}) Return n');
95 | ```
96 |
97 | On every save, Trinity will send any requests inside of the `Trinity` functions to your Neo4j Database and show responses in the Trinity Output Channel. To send another request, create a new invocation of the `Trinity` function and put the new request as the argument.
98 |
99 | ---
100 |
101 | ## Contributing and Issues
102 |
103 | We are always looking to improve. If there are any contributions, feature requests or issues/bugs you have, please check out our documentation on [contributions](./DOCUMENTATION/docs/contributing.md), [feature requests](./DOCUMENTATION/docs/featureRequest.md) or [issues/bugs](./DOCUMENTATION/docs/bugReport.md).
104 |
105 | ## Release Notes
106 |
107 | Created by: Alex Bednarek, Alex Drew, Connor Bovino, Olena Danykh
108 |
109 | 0.0.1 | Initial release of Trinity, More to come!
110 |
--------------------------------------------------------------------------------
/src/server/neo4j/graphdb-outline-ts.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from "vscode";
2 | import neo4j from "neo4j-driver";
3 | import { QueryResult } from "./types/index";
4 | import { Driver } from "./types/driver";
5 | import Session from "./types/session";
6 | import Transaction from "./types/transaction";
7 |
8 | interface GraphOutline {
9 | label: string;
10 | properties: string[];
11 | }
12 |
13 | interface Relationships {
14 | originNode: string[];
15 | relationship: string;
16 | dependentNode: string[];
17 | }
18 |
19 | export interface GraphStructure {
20 | graphOutline: Array;
21 | uniDirectionalRelationship: Array;
22 | biDirectionalRelationship: Array;
23 | }
24 |
25 | /**
26 | * * Graph DB Concepts:
27 | * https://neo4j.com/docs/getting-started/current/graphdb-concepts/
28 | *
29 | * * One Directional Relationships:
30 | * https://stackoverflow.com/questions/44481032/find-only-single-direction-relation-in-neo4j
31 | * MATCH (a) -[r] -> (b)
32 | * WHERE NOT (b) -[]-> (a)
33 | * RETURN DISTINCT labels(a), type(r), labels(b)
34 | *
35 | * * Two Directional Relationships:
36 | * MATCH (a) -[r] -> (b)
37 | * WHERE (b) -[]-> (a)
38 | * RETURN DISTINCT labels(a), type(r), labels(b)
39 | *
40 | * * Get all Properties and keys for an entire graph
41 | * https://stackoverflow.com/questions/48993061/how-can-i-get-all-property-keys-for-all-nodes-or-for-a-given-label-with-cypher
42 | * MATCH(n)
43 | * WITH LABELS(n) AS labels , KEYS(n) AS keys
44 | * UNWIND labels AS label
45 | * UNWIND keys AS key
46 | * RETURN DISTINCT label, COLLECT(DISTINCT key) AS props
47 | * ORDER BY label
48 | *
49 | * * High Level Inventory
50 | * https://neo4j.com/developer/kb/how-to-get-a-high-level-inventory-of-objects-in-your-graph/
51 | *
52 | * * Parameterized neo4j Queries in Node.js
53 | * * (not currently used. will be for trinity function)
54 | * https://www.youtube.com/watch?v=snjnJCZhXUM&t=905s
55 | */
56 |
57 | /**
58 | * connects to a neo4j database and return a promis that resolves to
59 | * an object containing the following:
60 | * - labels & property keys
61 | * - unidirectional relationships
62 | * - bidrection relationship
63 | *
64 | * @param {String} dbAddress - location of the neo4j database
65 | * @param {String} user - username to access database
66 | * @param {String} pass - password to access database
67 | */
68 | export const getGraphStructure=async (
69 | dbAddress: string,
70 | user: string,
71 | pass: string
72 | ): Promise => {
73 | // create a connection to your neo4j database
74 | // handles basic authentication and connects to a local host
75 | const driver: any=neo4j.driver(dbAddress, neo4j.auth.basic(user, pass));
76 |
77 | // initialize a query session
78 | const session: Session=driver.session();
79 | // begin a transaction in order to send multiple queries
80 | // in a single session.
81 | const txc: Transaction=session.beginTransaction();
82 |
83 | const queries: { [key: string]: string }={
84 | getOutline: `
85 | MATCH(n)
86 | WITH LABELS(n) AS labels , KEYS(n) AS keys
87 | UNWIND labels AS label
88 | UNWIND keys AS key
89 | RETURN DISTINCT label, COLLECT(DISTINCT key) AS props
90 | ORDER BY label`,
91 | getUniDirectionalRelationships: `
92 | MATCH (a) -[r] -> (b)
93 | WHERE NOT (b) -[]-> (a)
94 | RETURN DISTINCT labels(a), type(r), labels(b)`,
95 | getBiDirectionalRelationships: `
96 | MATCH (a) -[r] -> (b)
97 | WHERE (b) -[]-> (a)
98 | RETURN DISTINCT labels(a), type(r), labels(b)`
99 | };
100 |
101 | try {
102 | //get graph outline of labels and properties
103 | const graphOutlineRaw: QueryResult=await txc.run(queries.getOutline);
104 | const graphOutlineFormat: Array=graphOutlineRaw.records.map(
105 | el => ({
106 | label: el._fields[0],
107 | properties: el._fields[1]
108 | })
109 | );
110 |
111 | //get uni-directional relationships
112 | const uniDirectionalRaw: QueryResult=await txc.run(
113 | queries.getUniDirectionalRelationships
114 | );
115 | const uniDirectionalFormat: Array=uniDirectionalRaw.records.map(
116 | el => ({
117 | originNode: el._fields[0],
118 | relationship: el._fields[1],
119 | dependentNode: el._fields[2]
120 | })
121 | );
122 |
123 | //get bi-directional relationships
124 | const biDirectionalRaw: QueryResult=await txc.run(
125 | queries.getBiDirectionalRelationships
126 | );
127 | const biDirectionalFormat: Array=biDirectionalRaw.records.map(
128 | el => ({
129 | originNode: el._fields[0],
130 | relationship: el._fields[1],
131 | dependentNode: el._fields[2]
132 | })
133 | );
134 |
135 | // Return quieried data in a single object
136 | return {
137 | graphOutline: graphOutlineFormat,
138 | uniDirectionalRelationship: uniDirectionalFormat,
139 | biDirectionalRelationship: biDirectionalFormat
140 | };
141 | } catch (error) {
142 | vscode.window.showInformationMessage(
143 | "Please confirm your database is up and running and restart your Trinity Extension."
144 | );
145 | } finally {
146 | // to end exucution we must close the driver and session
147 | // otherwise execution context will be left hanging
148 | session.close();
149 | driver.close();
150 | vscode.window.showInformationMessage(
151 | "Trinity: Your Graph Outline is up to Date!"
152 | );
153 | }
154 | };
155 |
--------------------------------------------------------------------------------
/src/modules/readConfig.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable curly */
2 | import * as vscode from "vscode";
3 | import * as path from "path";
4 | import * as fs from "fs";
5 | import * as find from "find";
6 |
7 | interface TrinitySettings {
8 | dbAddress: string;
9 | username: string;
10 | password: string;
11 | clearChannelOnSave?: boolean; // -> Default to false
12 | writeOutputToJSON?: boolean; // -> Default to false
13 | JSONOutputRelativePath?: string; // -> Default to './'
14 | JSONOutputAbsolutePath?: string; // -> relative to the config file
15 | outputFilename?: string; // -> default to the output.json
16 | }
17 |
18 | export class TrinityConfig {
19 | activeWorkspaceName?: string;
20 | activeWorkspacePath?: string;
21 | configFilePath?: string;
22 | configFilePathRoot?: string;
23 | configWatcher?: fs.FSWatcher;
24 | activeSettings?: TrinitySettings;
25 |
26 | constructor() {
27 | this.getSettings = this.getSettings.bind(this);
28 | }
29 |
30 | findFileInParentDirectory(
31 | startingDirectory: string,
32 | fileName: string
33 | ): string | undefined {
34 | let currPath: string = startingDirectory;
35 | const rootDir: string = path.parse(process.cwd()).root;
36 | // iterate through parent directory untill reach the root
37 | while (currPath !== rootDir) {
38 | // get all files and folders in current directory
39 | const files: string[] = fs.readdirSync(currPath, {
40 | encoding: "utf8",
41 | withFileTypes: false
42 | });
43 | // iterate through files, looking for the configuration file
44 | for (let file of files) {
45 | if (file === fileName) {
46 | return path.resolve(currPath, file);
47 | }
48 | }
49 | // if config file is not in the current directory,
50 | // then check current directory's parents
51 | currPath = path.resolve(currPath, "../");
52 | }
53 | // will return undefined if config file is not found
54 | }
55 |
56 | getSettingsPath(directoryName: string, fileName: string): string | undefined {
57 | //recursively look for config file inside sub directories
58 | let configPathSubdirectory: string[] = find.fileSync(
59 | fileName,
60 | directoryName
61 | );
62 | if (configPathSubdirectory.length > 0) {
63 | return configPathSubdirectory[0];
64 | }
65 | //if config is not in sub directory recursively look in the parent directories
66 | return this.findFileInParentDirectory(directoryName, fileName);
67 | }
68 |
69 | getSettings(): void {
70 | const filePath = this.configFilePath;
71 | if (!filePath) return;
72 | const trinityConfigString: string = fs.readFileSync(filePath, "utf-8");
73 | const trinityConfig: TrinitySettings = JSON.parse(trinityConfigString);
74 |
75 | this.activeSettings = trinityConfig;
76 | // default settings
77 | if (!this.activeSettings.clearChannelOnSave) {
78 | this.activeSettings.clearChannelOnSave = false;
79 | }
80 | if (!this.activeSettings.writeOutputToJSON) {
81 | this.activeSettings.writeOutputToJSON = false;
82 | }
83 | if (!this.activeSettings.JSONOutputRelativePath) {
84 | this.activeSettings.JSONOutputRelativePath = "./";
85 | }
86 | if (!this.activeSettings.outputFilename) {
87 | this.activeSettings.outputFilename = "output.json";
88 | }
89 | if (
90 | this.configFilePathRoot &&
91 | this.activeSettings &&
92 | this.activeSettings.JSONOutputRelativePath
93 | ) {
94 | trinityConfig.JSONOutputAbsolutePath = path.resolve(
95 | this.configFilePathRoot,
96 | this.activeSettings.JSONOutputRelativePath
97 | );
98 | }
99 | }
100 |
101 | watchConfig(): void {
102 | // Kill current watch if already in progress
103 | if (this.configWatcher) this.configWatcher.close();
104 |
105 | // Initialize new watcher and store as this.configWatcher
106 | if (!this.configFilePath) return;
107 | this.configWatcher = fs.watch(this.configFilePath, () => {
108 | // each time config file save, refresh configuration settigs
109 | this.getSettings();
110 | });
111 | }
112 |
113 | async getActiveWorkspace(): Promise {
114 | // find all the current active workspaces
115 | const activeWorkspaces: vscode.WorkspaceFolder[] | undefined =
116 | vscode.workspace.workspaceFolders;
117 | let quickPicks: string[] = [];
118 |
119 | // convert active workspaces to format for quickpick dropdown
120 | if (activeWorkspaces) {
121 | quickPicks = activeWorkspaces.map(
122 | (el, index) => `${index + 1}. ${el.name}`
123 | );
124 | }
125 |
126 | // prompt the user for the current active workspace
127 | vscode.window.showInformationMessage(
128 | "Trinity: Please select your Active Workspace"
129 | );
130 | return vscode.window
131 | .showQuickPick(quickPicks, {
132 | placeHolder: "Trinity: Please Select the Active Workspace"
133 | })
134 | .then(res => {
135 | if (!res || !activeWorkspaces) return;
136 | // stores user's selection and path on 'this'
137 | this.quickPickHandler(res, activeWorkspaces);
138 | });
139 | }
140 |
141 | quickPickHandler(res: string, activeWorkspaces: vscode.WorkspaceFolder[]) {
142 | // get index of user's selection
143 | const index: number = parseInt(res.split(".")[0]) - 1;
144 |
145 | // store workspace name and filepath
146 | this.activeWorkspaceName = res;
147 | this.activeWorkspacePath = activeWorkspaces[index]["uri"]["fsPath"];
148 |
149 | // find the closest config file
150 | this.configFilePath = this.getSettingsPath(
151 | this.activeWorkspacePath,
152 | ".trinity.json"
153 | );
154 | // get file path of the config file
155 | if (this.configFilePath) {
156 | this.configFilePathRoot = this.configFilePath.replace(
157 | ".trinity.json",
158 | ""
159 | );
160 | }
161 | // begin watching the config file
162 | this.watchConfig();
163 | this.getSettings();
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/server/neo4j/types/index.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2002-2019 "Neo4j,"
3 | * Neo4j Sweden AB [http://neo4j.com]
4 | *
5 | * This file is part of Neo4j.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | import Integer, {
21 | inSafeRange,
22 | int,
23 | isInt,
24 | toNumber,
25 | toString
26 | } from "./integer";
27 | import {
28 | Node,
29 | Path,
30 | PathSegment,
31 | Relationship,
32 | UnboundRelationship
33 | } from "./graph-types";
34 | import { isPoint, Point } from "./spatial-types";
35 | import {
36 | Date,
37 | DateTime,
38 | Duration,
39 | isDate,
40 | isDateTime,
41 | isDuration,
42 | isLocalDateTime,
43 | isLocalTime,
44 | isTime,
45 | LocalDateTime,
46 | LocalTime,
47 | Time
48 | } from "./temporal-types";
49 | import {
50 | Neo4jError,
51 | PROTOCOL_ERROR,
52 | SERVICE_UNAVAILABLE,
53 | SESSION_EXPIRED
54 | } from "./error";
55 | import Result, { ResultObserver, QueryResult } from "./result";
56 | import ResultSummary, {
57 | Notification,
58 | NotificationPosition,
59 | Plan,
60 | ProfiledPlan,
61 | ServerInfo,
62 | QueryStatistic
63 | } from "./result-summary";
64 | import Record from "./record";
65 | import Session from "./session";
66 | import {
67 | AuthToken,
68 | Config,
69 | Driver,
70 | EncryptionLevel,
71 | READ,
72 | SessionMode,
73 | TrustStrategy,
74 | WRITE
75 | } from "./driver";
76 | import Transaction from "./transaction";
77 | import { Parameters } from "./query-runner";
78 |
79 | declare const auth: {
80 | basic: (username: string, password: string, realm?: string) => AuthToken;
81 |
82 | kerberos: (base64EncodedTicket: string) => AuthToken;
83 |
84 | custom: (
85 | principal: string,
86 | credentials: string,
87 | realm: string,
88 | scheme: string,
89 | parameters?: Parameters
90 | ) => AuthToken;
91 | };
92 |
93 | declare function driver(
94 | url: string,
95 | authToken?: AuthToken,
96 | config?: Config
97 | ): Driver;
98 |
99 | declare const types: {
100 | Node: Node;
101 | Relationship: Relationship;
102 | UnboundRelationship: UnboundRelationship;
103 | PathSegment: PathSegment;
104 | Path: Path;
105 | Result: Result;
106 | ResultSummary: ResultSummary;
107 | Record: Record;
108 | Point: typeof Point;
109 | Duration: typeof Duration;
110 | LocalTime: typeof LocalTime;
111 | Time: typeof Time;
112 | Date: typeof Date;
113 | LocalDateTime: typeof LocalDateTime;
114 | DateTime: typeof DateTime;
115 | Integer: typeof Integer;
116 | };
117 |
118 | declare const session: {
119 | READ: typeof READ;
120 | WRITE: typeof WRITE;
121 | };
122 |
123 | declare const error: {
124 | SERVICE_UNAVAILABLE: typeof SERVICE_UNAVAILABLE;
125 | SESSION_EXPIRED: typeof SESSION_EXPIRED;
126 | PROTOCOL_ERROR: typeof PROTOCOL_ERROR;
127 | };
128 |
129 | declare const integer: {
130 | toNumber: typeof toNumber;
131 | toString: typeof toString;
132 | inSafeRange: typeof inSafeRange;
133 | };
134 |
135 | declare const spatial: {
136 | isPoint: typeof isPoint;
137 | };
138 |
139 | declare const temporal: {
140 | isDuration: typeof isDuration;
141 | isLocalTime: typeof isLocalTime;
142 | isTime: typeof isTime;
143 | isDate: typeof isDate;
144 | isLocalDateTime: typeof isLocalDateTime;
145 | isDateTime: typeof isDateTime;
146 | };
147 |
148 | /*
149 | Both default and non-default exports declare all visible types so that they can be used in client code like this:
150 |
151 | import neo4j from "neo4j-driver";
152 | const driver: neo4j.Driver = neo4j.driver("bolt://localhost");
153 | const session: neo4j.Session = driver.session();
154 | ...
155 | */
156 |
157 | declare const forExport: {
158 | driver: typeof driver;
159 | int: typeof int;
160 | isInt: typeof isInt;
161 | integer: typeof integer;
162 | auth: typeof auth;
163 | types: typeof types;
164 | session: typeof session;
165 | error: typeof error;
166 | spatial: typeof spatial;
167 | temporal: typeof temporal;
168 | Driver: Driver;
169 | AuthToken: AuthToken;
170 | Config: Config;
171 | EncryptionLevel: EncryptionLevel;
172 | TrustStrategy: TrustStrategy;
173 | SessionMode: SessionMode;
174 | Neo4jError: Neo4jError;
175 | Node: Node;
176 | Relationship: Relationship;
177 | UnboundRelationship: UnboundRelationship;
178 | PathSegment: PathSegment;
179 | Path: Path;
180 | Integer: Integer;
181 | Record: Record;
182 | Result: Result;
183 | QueryResult: QueryResult;
184 | ResultObserver: ResultObserver;
185 | ResultSummary: ResultSummary;
186 | Plan: Plan;
187 | ProfiledPlan: ProfiledPlan;
188 | QueryStatistic: QueryStatistic;
189 | Notification: Notification;
190 | ServerInfo: ServerInfo;
191 | NotificationPosition: NotificationPosition;
192 | Session: Session;
193 | Transaction: Transaction;
194 | Point: Point;
195 | isPoint: typeof isPoint;
196 | Duration: Duration;
197 | LocalTime: LocalTime;
198 | Time: Time;
199 | Date: Date;
200 | LocalDateTime: LocalDateTime;
201 | DateTime: DateTime;
202 | isDuration: typeof isDuration;
203 | isLocalTime: typeof isLocalTime;
204 | isTime: typeof isTime;
205 | isDate: typeof isDate;
206 | isLocalDateTime: typeof isLocalDateTime;
207 | isDateTime: typeof isDateTime;
208 | };
209 |
210 | export {
211 | driver,
212 | int,
213 | isInt,
214 | integer,
215 | auth,
216 | types,
217 | session,
218 | error,
219 | spatial,
220 | temporal,
221 | Driver,
222 | AuthToken,
223 | Config,
224 | EncryptionLevel,
225 | TrustStrategy,
226 | SessionMode,
227 | Neo4jError,
228 | Node,
229 | Relationship,
230 | UnboundRelationship,
231 | PathSegment,
232 | Path,
233 | Integer,
234 | Record,
235 | Result,
236 | QueryResult,
237 | ResultObserver,
238 | ResultSummary,
239 | Plan,
240 | ProfiledPlan,
241 | QueryStatistic,
242 | Notification,
243 | ServerInfo,
244 | NotificationPosition,
245 | Session,
246 | Transaction,
247 | Point,
248 | isPoint,
249 | Duration,
250 | LocalTime,
251 | Time,
252 | Date,
253 | LocalDateTime,
254 | DateTime,
255 | isDuration,
256 | isLocalTime,
257 | isTime,
258 | isDate,
259 | isLocalDateTime,
260 | isDateTime
261 | };
262 |
263 | export default forExport;
264 |
--------------------------------------------------------------------------------
/src/modules/OutlineProvider.ts:
--------------------------------------------------------------------------------
1 | import * as vscode from "vscode";
2 | import {
3 | getGraphStructure,
4 | GraphStructure
5 | } from "../server/neo4j/graphdb-outline-ts";
6 |
7 | /**
8 | * Relation: Interface for all properties and dependent nodes
9 | *
10 | * ResultObject: Interface for all nodes and their properties and relationships
11 | *
12 | */
13 |
14 | interface Relation {
15 | [key: string]: string[];
16 | }
17 |
18 | interface ResultObject {
19 | [index: string]: {
20 | Properties: string[];
21 | "Uni-Directional": Relation;
22 | "Bi-Directional": Relation;
23 | };
24 | }
25 |
26 | /**
27 | *
28 | * OutlineProvider Class: Models outline structure utlilizing both VSCode methods and our own methods. Within this object
29 | * an asyncronous call is made to database, after which we used the createResultObj method to format our data.
30 | * Finally, we use the TreeTask class to create the exact format for VSCode to provide an outline view.
31 | *
32 | * TreeTask Class: Extends vscode tree item and allows us to create types for the specific items that will make up our outline view
33 | *
34 | */
35 | export class OutlineProvider implements vscode.TreeDataProvider {
36 | // The following methods must be fired whenever tree data changes in order to see the change in our outline view
37 | // Private referring to the fact that it cannot be accessed outside the object
38 | private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter();
39 | // Readonly referring to the fact that it cannot be changed
40 | readonly onDidChangeTreeData: vscode.Event = this
41 | ._onDidChangeTreeData.event;
42 | // Array of tree tasks used to populate outline view
43 | data: TreeTask[] = [];
44 |
45 | /**
46 | * Trinity config inherits the class that reads the user's login/database information
47 | * Constructor executes create graph structure which fills the OutlineProvider with data
48 | */
49 | trinityConfig: any;
50 | constructor(private context: vscode.ExtensionContext, trinityConfig: any) {
51 | this.trinityConfig = trinityConfig;
52 | this.createGraphStructure();
53 | }
54 |
55 | /**
56 | * createResultObj method accepts result data as arg from call to database and re-structures the returned data so that it can be easily
57 | * manipulated to create outline view
58 | * @param resultData
59 | */
60 |
61 | createResultObj(resultData: GraphStructure) {
62 | // Create Result Obj
63 | const resultObj: ResultObject = {};
64 | // UniDirectional
65 | for (let i = 0; i < resultData.uniDirectionalRelationship.length; i += 1) {
66 | // for each unique item in origin array, create a key on result obj
67 | let originNodes: string[] =
68 | resultData.uniDirectionalRelationship[i].originNode;
69 | let uniRelation: string =
70 | resultData.uniDirectionalRelationship[i].relationship;
71 | let dependentNode: string[] =
72 | resultData.uniDirectionalRelationship[i].dependentNode;
73 | if (originNodes.length > 0) {
74 | for (let x = 0; x < originNodes.length; x += 1) {
75 | if (!resultObj[originNodes[x]]) {
76 | resultObj[originNodes[x]] = {
77 | "Uni-Directional": {},
78 | "Bi-Directional": {},
79 | Properties: []
80 | };
81 | }
82 | resultObj[originNodes[x]]["Uni-Directional"][
83 | uniRelation
84 | ] = dependentNode;
85 | }
86 | }
87 | }
88 | // BiDirectional
89 | for (let y = 0; y < resultData.biDirectionalRelationship.length; y += 1) {
90 | // Array of all the origin nodes in relationship object
91 | let originNodes = resultData.biDirectionalRelationship[y].originNode;
92 | // Relationship between origin nodes and depenent node
93 | let biRelation = resultData.biDirectionalRelationship[y].relationship;
94 | // Array of depend Nodes
95 | let dependentNode = resultData.biDirectionalRelationship[y].dependentNode;
96 | // for each origin node
97 | for (let z = 0; z < originNodes.length; z += 1) {
98 | // if the node is on the result obj, check if the bi relationship is on the node
99 | resultObj[originNodes[z]]["Bi-Directional"][biRelation] = dependentNode;
100 | }
101 | }
102 | // Properties
103 | for (let q = 0; q < resultData.graphOutline.length; q += 1) {
104 | let nameNode: string = resultData.graphOutline[q].label;
105 | let propsNode: string[] = resultData.graphOutline[q].properties;
106 |
107 | if (!resultObj[nameNode]) {
108 | resultObj[nameNode] = {
109 | "Uni-Directional": {},
110 | "Bi-Directional": {},
111 | Properties: []
112 | };
113 | }
114 |
115 | if (resultObj[nameNode]) {
116 | resultObj[nameNode].Properties = propsNode;
117 | }
118 | }
119 | return resultObj;
120 | }
121 | /**
122 | * createGraphStructure method is called in constructor and utilizes the boundGetGraphStructure and setUpData methods to populate
123 | * OutlineProvider with correct format for data
124 | */
125 | createGraphStructure() {
126 | const boundGetGraphStructure = getGraphStructure.bind(this);
127 |
128 | const { dbAddress, username, password } = this.trinityConfig.activeSettings;
129 |
130 | boundGetGraphStructure(dbAddress, username, password).then(
131 | (res: GraphStructure | undefined) => {
132 | if (res !== undefined) {
133 | const resultObject: ResultObject = this.createResultObj(res);
134 | this.data = this.setUpData(resultObject);
135 | this._onDidChangeTreeData.fire();
136 | }
137 | }
138 | );
139 | }
140 | /**
141 | * setUpData method accepts resultObj from the createResultObj method and constructs an array of tree tasks that will be used
142 | * to populate the outline view
143 | * @param resultObj
144 | */
145 | setUpData(resultObj: ResultObject) {
146 | let array: TreeTask[] = [];
147 |
148 | // For each Node in result Object
149 | Object.keys(resultObj).forEach(element => {
150 | let elementArray: TreeTask[] = [];
151 |
152 | // For each Item inside node of Result Objectresult Object
153 | Object.keys(resultObj[element]).forEach(innerEl => {
154 | let innerElArray: TreeTask[] = [];
155 |
156 | // check if person.uni or properties etc is an array
157 | if (innerEl === "Properties") {
158 | resultObj[element].Properties.forEach(innerMostEL => {
159 | innerElArray.push(new TreeTask(innerMostEL));
160 | });
161 | } else {
162 | if (innerEl === "Bi-Directional" || innerEl === "Uni-Directional") {
163 | if (resultObj[element][innerEl] !== undefined) {
164 | Object.keys(resultObj[element][innerEl]).forEach(newInnerEl => {
165 | let dependents: TreeTask[] = [];
166 |
167 | resultObj[element][innerEl][newInnerEl].forEach(el => {
168 | dependents.push(new TreeTask(el));
169 | });
170 |
171 | innerElArray.push(new TreeTask(newInnerEl, dependents));
172 | });
173 | }
174 | }
175 | }
176 | let innerTreeTask = new TreeTask(innerEl, innerElArray);
177 |
178 | elementArray.push(innerTreeTask);
179 | });
180 |
181 | let elementTreeTask = new TreeTask(element, elementArray);
182 | array.push(elementTreeTask);
183 | });
184 | console.log(array);
185 | return array;
186 | }
187 |
188 | // Executes command showing outline provider
189 | show() {
190 | vscode.commands.executeCommand("setContext", "trinityOutlineEnabled", true);
191 | }
192 | /**
193 | * VSCode API uses getChildren AND getTreeItem methods to aid in construction of tree task outline view
194 | * @param element
195 | *
196 | */
197 | getChildren(
198 | element?: TreeTask | undefined
199 | ): vscode.ProviderResult {
200 | if (element === undefined) {
201 | return this.data;
202 | }
203 | return element.children;
204 | }
205 |
206 | getTreeItem(element: TreeTask): vscode.TreeItem | Thenable {
207 | return element;
208 | }
209 | }
210 | class TreeTask extends vscode.TreeItem {
211 | children: TreeTask[] | undefined;
212 |
213 | constructor(label: string, children?: TreeTask[]) {
214 | const collapsed =
215 | children === undefined
216 | ? vscode.TreeItemCollapsibleState.None
217 | : vscode.TreeItemCollapsibleState.Collapsed;
218 | super(label, collapsed);
219 | this.children = children;
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/src/server/neo4j/sampleOutput/movie.cypher:
--------------------------------------------------------------------------------
1 | CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})
2 | CREATE (Keanu:Person {name:'Keanu Reeves', born:1964})
3 | CREATE (Carrie:Person {name:'Carrie-Anne Moss', born:1967})
4 | CREATE (Laurence:Person {name:'Laurence Fishburne', born:1961})
5 | CREATE (Hugo:Person {name:'Hugo Weaving', born:1960})
6 | CREATE (LillyW:Person {name:'Lilly Wachowski', born:1967})
7 | CREATE (LanaW:Person {name:'Lana Wachowski', born:1965})
8 | CREATE (JoelS:Person {name:'Joel Silver', born:1952})
9 | CREATE
10 | (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrix),
11 | (Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrix),
12 | (Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrix),
13 | (Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrix),
14 | (LillyW)-[:DIRECTED]->(TheMatrix),
15 | (LanaW)-[:DIRECTED]->(TheMatrix),
16 | (JoelS)-[:PRODUCED]->(TheMatrix)
17 |
18 | CREATE (Emil:Person {name:"Emil Eifrem", born:1978})
19 | CREATE (Emil)-[:ACTED_IN {roles:["Emil"]}]->(TheMatrix)
20 |
21 | CREATE (TheMatrixReloaded:Movie {title:'The Matrix Reloaded', released:2003, tagline:'Free your mind'})
22 | CREATE
23 | (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrixReloaded),
24 | (Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrixReloaded),
25 | (Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrixReloaded),
26 | (Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrixReloaded),
27 | (LillyW)-[:DIRECTED]->(TheMatrixReloaded),
28 | (LanaW)-[:DIRECTED]->(TheMatrixReloaded),
29 | (JoelS)-[:PRODUCED]->(TheMatrixReloaded)
30 |
31 | CREATE (TheMatrixRevolutions:Movie {title:'The Matrix Revolutions', released:2003, tagline:'Everything that has a beginning has an end'})
32 | CREATE
33 | (Keanu)-[:ACTED_IN {roles:['Neo']}]->(TheMatrixRevolutions),
34 | (Carrie)-[:ACTED_IN {roles:['Trinity']}]->(TheMatrixRevolutions),
35 | (Laurence)-[:ACTED_IN {roles:['Morpheus']}]->(TheMatrixRevolutions),
36 | (Hugo)-[:ACTED_IN {roles:['Agent Smith']}]->(TheMatrixRevolutions),
37 | (LillyW)-[:DIRECTED]->(TheMatrixRevolutions),
38 | (LanaW)-[:DIRECTED]->(TheMatrixRevolutions),
39 | (JoelS)-[:PRODUCED]->(TheMatrixRevolutions)
40 |
41 | CREATE (TheDevilsAdvocate:Movie {title:"The Devil's Advocate", released:1997, tagline:'Evil has its winning ways'})
42 | CREATE (Charlize:Person {name:'Charlize Theron', born:1975})
43 | CREATE (Al:Person {name:'Al Pacino', born:1940})
44 | CREATE (Taylor:Person {name:'Taylor Hackford', born:1944})
45 | CREATE
46 | (Keanu)-[:ACTED_IN {roles:['Kevin Lomax']}]->(TheDevilsAdvocate),
47 | (Charlize)-[:ACTED_IN {roles:['Mary Ann Lomax']}]->(TheDevilsAdvocate),
48 | (Al)-[:ACTED_IN {roles:['John Milton']}]->(TheDevilsAdvocate),
49 | (Taylor)-[:DIRECTED]->(TheDevilsAdvocate)
50 |
51 | CREATE (AFewGoodMen:Movie {title:"A Few Good Men", released:1992, tagline:"In the heart of the nation's capital, in a courthouse of the U.S. government, one man will stop at nothing to keep his honor, and one will stop at nothing to find the truth."})
52 | CREATE (TomC:Person {name:'Tom Cruise', born:1962})
53 | CREATE (JackN:Person {name:'Jack Nicholson', born:1937})
54 | CREATE (DemiM:Person {name:'Demi Moore', born:1962})
55 | CREATE (KevinB:Person {name:'Kevin Bacon', born:1958})
56 | CREATE (KieferS:Person {name:'Kiefer Sutherland', born:1966})
57 | CREATE (NoahW:Person {name:'Noah Wyle', born:1971})
58 | CREATE (CubaG:Person {name:'Cuba Gooding Jr.', born:1968})
59 | CREATE (KevinP:Person {name:'Kevin Pollak', born:1957})
60 | CREATE (JTW:Person {name:'J.T. Walsh', born:1943})
61 | CREATE (JamesM:Person {name:'James Marshall', born:1967})
62 | CREATE (ChristopherG:Person {name:'Christopher Guest', born:1948})
63 | CREATE (RobR:Person {name:'Rob Reiner', born:1947})
64 | CREATE (AaronS:Person {name:'Aaron Sorkin', born:1961})
65 | CREATE
66 | (TomC)-[:ACTED_IN {roles:['Lt. Daniel Kaffee']}]->(AFewGoodMen),
67 | (JackN)-[:ACTED_IN {roles:['Col. Nathan R. Jessup']}]->(AFewGoodMen),
68 | (DemiM)-[:ACTED_IN {roles:['Lt. Cdr. JoAnne Galloway']}]->(AFewGoodMen),
69 | (KevinB)-[:ACTED_IN {roles:['Capt. Jack Ross']}]->(AFewGoodMen),
70 | (KieferS)-[:ACTED_IN {roles:['Lt. Jonathan Kendrick']}]->(AFewGoodMen),
71 | (NoahW)-[:ACTED_IN {roles:['Cpl. Jeffrey Barnes']}]->(AFewGoodMen),
72 | (CubaG)-[:ACTED_IN {roles:['Cpl. Carl Hammaker']}]->(AFewGoodMen),
73 | (KevinP)-[:ACTED_IN {roles:['Lt. Sam Weinberg']}]->(AFewGoodMen),
74 | (JTW)-[:ACTED_IN {roles:['Lt. Col. Matthew Andrew Markinson']}]->(AFewGoodMen),
75 | (JamesM)-[:ACTED_IN {roles:['Pfc. Louden Downey']}]->(AFewGoodMen),
76 | (ChristopherG)-[:ACTED_IN {roles:['Dr. Stone']}]->(AFewGoodMen),
77 | (AaronS)-[:ACTED_IN {roles:['Man in Bar']}]->(AFewGoodMen),
78 | (RobR)-[:DIRECTED]->(AFewGoodMen),
79 | (AaronS)-[:WROTE]->(AFewGoodMen)
80 |
81 | CREATE (TopGun:Movie {title:"Top Gun", released:1986, tagline:'I feel the need, the need for speed.'})
82 | CREATE (KellyM:Person {name:'Kelly McGillis', born:1957})
83 | CREATE (ValK:Person {name:'Val Kilmer', born:1959})
84 | CREATE (AnthonyE:Person {name:'Anthony Edwards', born:1962})
85 | CREATE (TomS:Person {name:'Tom Skerritt', born:1933})
86 | CREATE (MegR:Person {name:'Meg Ryan', born:1961})
87 | CREATE (TonyS:Person {name:'Tony Scott', born:1944})
88 | CREATE (JimC:Person {name:'Jim Cash', born:1941})
89 | CREATE
90 | (TomC)-[:ACTED_IN {roles:['Maverick']}]->(TopGun),
91 | (KellyM)-[:ACTED_IN {roles:['Charlie']}]->(TopGun),
92 | (ValK)-[:ACTED_IN {roles:['Iceman']}]->(TopGun),
93 | (AnthonyE)-[:ACTED_IN {roles:['Goose']}]->(TopGun),
94 | (TomS)-[:ACTED_IN {roles:['Viper']}]->(TopGun),
95 | (MegR)-[:ACTED_IN {roles:['Carole']}]->(TopGun),
96 | (TonyS)-[:DIRECTED]->(TopGun),
97 | (JimC)-[:WROTE]->(TopGun)
98 |
99 | CREATE (JerryMaguire:Movie {title:'Jerry Maguire', released:2000, tagline:'The rest of his life begins now.'})
100 | CREATE (ReneeZ:Person {name:'Renee Zellweger', born:1969})
101 | CREATE (KellyP:Person {name:'Kelly Preston', born:1962})
102 | CREATE (JerryO:Person {name:"Jerry O'Connell", born:1974})
103 | CREATE (JayM:Person {name:'Jay Mohr', born:1970})
104 | CREATE (BonnieH:Person {name:'Bonnie Hunt', born:1961})
105 | CREATE (ReginaK:Person {name:'Regina King', born:1971})
106 | CREATE (JonathanL:Person {name:'Jonathan Lipnicki', born:1996})
107 | CREATE (CameronC:Person {name:'Cameron Crowe', born:1957})
108 | CREATE
109 | (TomC)-[:ACTED_IN {roles:['Jerry Maguire']}]->(JerryMaguire),
110 | (CubaG)-[:ACTED_IN {roles:['Rod Tidwell']}]->(JerryMaguire),
111 | (ReneeZ)-[:ACTED_IN {roles:['Dorothy Boyd']}]->(JerryMaguire),
112 | (KellyP)-[:ACTED_IN {roles:['Avery Bishop']}]->(JerryMaguire),
113 | (JerryO)-[:ACTED_IN {roles:['Frank Cushman']}]->(JerryMaguire),
114 | (JayM)-[:ACTED_IN {roles:['Bob Sugar']}]->(JerryMaguire),
115 | (BonnieH)-[:ACTED_IN {roles:['Laurel Boyd']}]->(JerryMaguire),
116 | (ReginaK)-[:ACTED_IN {roles:['Marcee Tidwell']}]->(JerryMaguire),
117 | (JonathanL)-[:ACTED_IN {roles:['Ray Boyd']}]->(JerryMaguire),
118 | (CameronC)-[:DIRECTED]->(JerryMaguire),
119 | (CameronC)-[:PRODUCED]->(JerryMaguire),
120 | (CameronC)-[:WROTE]->(JerryMaguire)
121 |
122 | CREATE (StandByMe:Movie {title:"Stand By Me", released:1986, tagline:"For some, it's the last real taste of innocence, and the first real taste of life. But for everyone, it's the time that memories are made of."})
123 | CREATE (RiverP:Person {name:'River Phoenix', born:1970})
124 | CREATE (CoreyF:Person {name:'Corey Feldman', born:1971})
125 | CREATE (WilW:Person {name:'Wil Wheaton', born:1972})
126 | CREATE (JohnC:Person {name:'John Cusack', born:1966})
127 | CREATE (MarshallB:Person {name:'Marshall Bell', born:1942})
128 | CREATE
129 | (WilW)-[:ACTED_IN {roles:['Gordie Lachance']}]->(StandByMe),
130 | (RiverP)-[:ACTED_IN {roles:['Chris Chambers']}]->(StandByMe),
131 | (JerryO)-[:ACTED_IN {roles:['Vern Tessio']}]->(StandByMe),
132 | (CoreyF)-[:ACTED_IN {roles:['Teddy Duchamp']}]->(StandByMe),
133 | (JohnC)-[:ACTED_IN {roles:['Denny Lachance']}]->(StandByMe),
134 | (KieferS)-[:ACTED_IN {roles:['Ace Merrill']}]->(StandByMe),
135 | (MarshallB)-[:ACTED_IN {roles:['Mr. Lachance']}]->(StandByMe),
136 | (RobR)-[:DIRECTED]->(StandByMe)
137 |
138 | CREATE (AsGoodAsItGets:Movie {title:'As Good as It Gets', released:1997, tagline:'A comedy from the heart that goes for the throat.'})
139 | CREATE (HelenH:Person {name:'Helen Hunt', born:1963})
140 | CREATE (GregK:Person {name:'Greg Kinnear', born:1963})
141 | CREATE (JamesB:Person {name:'James L. Brooks', born:1940})
142 | CREATE
143 | (JackN)-[:ACTED_IN {roles:['Melvin Udall']}]->(AsGoodAsItGets),
144 | (HelenH)-[:ACTED_IN {roles:['Carol Connelly']}]->(AsGoodAsItGets),
145 | (GregK)-[:ACTED_IN {roles:['Simon Bishop']}]->(AsGoodAsItGets),
146 | (CubaG)-[:ACTED_IN {roles:['Frank Sachs']}]->(AsGoodAsItGets),
147 | (JamesB)-[:DIRECTED]->(AsGoodAsItGets)
148 |
149 | CREATE (WhatDreamsMayCome:Movie {title:'What Dreams May Come', released:1998, tagline:'After life there is more. The end is just the beginning.'})
150 | CREATE (AnnabellaS:Person {name:'Annabella Sciorra', born:1960})
151 | CREATE (MaxS:Person {name:'Max von Sydow', born:1929})
152 | CREATE (WernerH:Person {name:'Werner Herzog', born:1942})
153 | CREATE (Robin:Person {name:'Robin Williams', born:1951})
154 | CREATE (VincentW:Person {name:'Vincent Ward', born:1956})
155 | CREATE
156 | (Robin)-[:ACTED_IN {roles:['Chris Nielsen']}]->(WhatDreamsMayCome),
157 | (CubaG)-[:ACTED_IN {roles:['Albert Lewis']}]->(WhatDreamsMayCome),
158 | (AnnabellaS)-[:ACTED_IN {roles:['Annie Collins-Nielsen']}]->(WhatDreamsMayCome),
159 | (MaxS)-[:ACTED_IN {roles:['The Tracker']}]->(WhatDreamsMayCome),
160 | (WernerH)-[:ACTED_IN {roles:['The Face']}]->(WhatDreamsMayCome),
161 | (VincentW)-[:DIRECTED]->(WhatDreamsMayCome)
162 |
163 | CREATE (SnowFallingonCedars:Movie {title:'Snow Falling on Cedars', released:1999, tagline:'First loves last. Forever.'})
164 | CREATE (EthanH:Person {name:'Ethan Hawke', born:1970})
165 | CREATE (RickY:Person {name:'Rick Yune', born:1971})
166 | CREATE (JamesC:Person {name:'James Cromwell', born:1940})
167 | CREATE (ScottH:Person {name:'Scott Hicks', born:1953})
168 | CREATE
169 | (EthanH)-[:ACTED_IN {roles:['Ishmael Chambers']}]->(SnowFallingonCedars),
170 | (RickY)-[:ACTED_IN {roles:['Kazuo Miyamoto']}]->(SnowFallingonCedars),
171 | (MaxS)-[:ACTED_IN {roles:['Nels Gudmundsson']}]->(SnowFallingonCedars),
172 | (JamesC)-[:ACTED_IN {roles:['Judge Fielding']}]->(SnowFallingonCedars),
173 | (ScottH)-[:DIRECTED]->(SnowFallingonCedars)
174 |
175 | CREATE (YouveGotMail:Movie {title:"You've Got Mail", released:1998, tagline:'At odds in life... in love on-line.'})
176 | CREATE (ParkerP:Person {name:'Parker Posey', born:1968})
177 | CREATE (DaveC:Person {name:'Dave Chappelle', born:1973})
178 | CREATE (SteveZ:Person {name:'Steve Zahn', born:1967})
179 | CREATE (TomH:Person {name:'Tom Hanks', born:1956})
180 | CREATE (NoraE:Person {name:'Nora Ephron', born:1941})
181 | CREATE
182 | (TomH)-[:ACTED_IN {roles:['Joe Fox']}]->(YouveGotMail),
183 | (MegR)-[:ACTED_IN {roles:['Kathleen Kelly']}]->(YouveGotMail),
184 | (GregK)-[:ACTED_IN {roles:['Frank Navasky']}]->(YouveGotMail),
185 | (ParkerP)-[:ACTED_IN {roles:['Patricia Eden']}]->(YouveGotMail),
186 | (DaveC)-[:ACTED_IN {roles:['Kevin Jackson']}]->(YouveGotMail),
187 | (SteveZ)-[:ACTED_IN {roles:['George Pappas']}]->(YouveGotMail),
188 | (NoraE)-[:DIRECTED]->(YouveGotMail)
189 |
190 | CREATE (SleeplessInSeattle:Movie {title:'Sleepless in Seattle', released:1993, tagline:'What if someone you never met, someone you never saw, someone you never knew was the only someone for you?'})
191 | CREATE (RitaW:Person {name:'Rita Wilson', born:1956})
192 | CREATE (BillPull:Person {name:'Bill Pullman', born:1953})
193 | CREATE (VictorG:Person {name:'Victor Garber', born:1949})
194 | CREATE (RosieO:Person {name:"Rosie O'Donnell", born:1962})
195 | CREATE
196 | (TomH)-[:ACTED_IN {roles:['Sam Baldwin']}]->(SleeplessInSeattle),
197 | (MegR)-[:ACTED_IN {roles:['Annie Reed']}]->(SleeplessInSeattle),
198 | (RitaW)-[:ACTED_IN {roles:['Suzy']}]->(SleeplessInSeattle),
199 | (BillPull)-[:ACTED_IN {roles:['Walter']}]->(SleeplessInSeattle),
200 | (VictorG)-[:ACTED_IN {roles:['Greg']}]->(SleeplessInSeattle),
201 | (RosieO)-[:ACTED_IN {roles:['Becky']}]->(SleeplessInSeattle),
202 | (NoraE)-[:DIRECTED]->(SleeplessInSeattle)
203 |
204 | CREATE (JoeVersustheVolcano:Movie {title:'Joe Versus the Volcano', released:1990, tagline:'A story of love, lava and burning desire.'})
205 | CREATE (JohnS:Person {name:'John Patrick Stanley', born:1950})
206 | CREATE (Nathan:Person {name:'Nathan Lane', born:1956})
207 | CREATE
208 | (TomH)-[:ACTED_IN {roles:['Joe Banks']}]->(JoeVersustheVolcano),
209 | (MegR)-[:ACTED_IN {roles:['DeDe', 'Angelica Graynamore', 'Patricia Graynamore']}]->(JoeVersustheVolcano),
210 | (Nathan)-[:ACTED_IN {roles:['Baw']}]->(JoeVersustheVolcano),
211 | (JohnS)-[:DIRECTED]->(JoeVersustheVolcano)
212 |
213 | CREATE (WhenHarryMetSally:Movie {title:'When Harry Met Sally', released:1998, tagline:'Can two friends sleep together and still love each other in the morning?'})
214 | CREATE (BillyC:Person {name:'Billy Crystal', born:1948})
215 | CREATE (CarrieF:Person {name:'Carrie Fisher', born:1956})
216 | CREATE (BrunoK:Person {name:'Bruno Kirby', born:1949})
217 | CREATE
218 | (BillyC)-[:ACTED_IN {roles:['Harry Burns']}]->(WhenHarryMetSally),
219 | (MegR)-[:ACTED_IN {roles:['Sally Albright']}]->(WhenHarryMetSally),
220 | (CarrieF)-[:ACTED_IN {roles:['Marie']}]->(WhenHarryMetSally),
221 | (BrunoK)-[:ACTED_IN {roles:['Jess']}]->(WhenHarryMetSally),
222 | (RobR)-[:DIRECTED]->(WhenHarryMetSally),
223 | (RobR)-[:PRODUCED]->(WhenHarryMetSally),
224 | (NoraE)-[:PRODUCED]->(WhenHarryMetSally),
225 | (NoraE)-[:WROTE]->(WhenHarryMetSally)
226 |
227 | CREATE (ThatThingYouDo:Movie {title:'That Thing You Do', released:1996, tagline:'In every life there comes a time when that thing you dream becomes that thing you do'})
228 | CREATE (LivT:Person {name:'Liv Tyler', born:1977})
229 | CREATE
230 | (TomH)-[:ACTED_IN {roles:['Mr. White']}]->(ThatThingYouDo),
231 | (LivT)-[:ACTED_IN {roles:['Faye Dolan']}]->(ThatThingYouDo),
232 | (Charlize)-[:ACTED_IN {roles:['Tina']}]->(ThatThingYouDo),
233 | (TomH)-[:DIRECTED]->(ThatThingYouDo)
234 |
235 | CREATE (TheReplacements:Movie {title:'The Replacements', released:2000, tagline:'Pain heals, Chicks dig scars... Glory lasts forever'})
236 | CREATE (Brooke:Person {name:'Brooke Langton', born:1970})
237 | CREATE (Gene:Person {name:'Gene Hackman', born:1930})
238 | CREATE (Orlando:Person {name:'Orlando Jones', born:1968})
239 | CREATE (Howard:Person {name:'Howard Deutch', born:1950})
240 | CREATE
241 | (Keanu)-[:ACTED_IN {roles:['Shane Falco']}]->(TheReplacements),
242 | (Brooke)-[:ACTED_IN {roles:['Annabelle Farrell']}]->(TheReplacements),
243 | (Gene)-[:ACTED_IN {roles:['Jimmy McGinty']}]->(TheReplacements),
244 | (Orlando)-[:ACTED_IN {roles:['Clifford Franklin']}]->(TheReplacements),
245 | (Howard)-[:DIRECTED]->(TheReplacements)
246 |
247 | CREATE (RescueDawn:Movie {title:'RescueDawn', released:2006, tagline:"Based on the extraordinary true story of one man's fight for freedom"})
248 | CREATE (ChristianB:Person {name:'Christian Bale', born:1974})
249 | CREATE (ZachG:Person {name:'Zach Grenier', born:1954})
250 | CREATE
251 | (MarshallB)-[:ACTED_IN {roles:['Admiral']}]->(RescueDawn),
252 | (ChristianB)-[:ACTED_IN {roles:['Dieter Dengler']}]->(RescueDawn),
253 | (ZachG)-[:ACTED_IN {roles:['Squad Leader']}]->(RescueDawn),
254 | (SteveZ)-[:ACTED_IN {roles:['Duane']}]->(RescueDawn),
255 | (WernerH)-[:DIRECTED]->(RescueDawn)
256 |
257 | CREATE (TheBirdcage:Movie {title:'The Birdcage', released:1996, tagline:'Come as you are'})
258 | CREATE (MikeN:Person {name:'Mike Nichols', born:1931})
259 | CREATE
260 | (Robin)-[:ACTED_IN {roles:['Armand Goldman']}]->(TheBirdcage),
261 | (Nathan)-[:ACTED_IN {roles:['Albert Goldman']}]->(TheBirdcage),
262 | (Gene)-[:ACTED_IN {roles:['Sen. Kevin Keeley']}]->(TheBirdcage),
263 | (MikeN)-[:DIRECTED]->(TheBirdcage)
264 |
265 | CREATE (Unforgiven:Movie {title:'Unforgiven', released:1992, tagline:"It's a hell of a thing, killing a man"})
266 | CREATE (RichardH:Person {name:'Richard Harris', born:1930})
267 | CREATE (ClintE:Person {name:'Clint Eastwood', born:1930})
268 | CREATE
269 | (RichardH)-[:ACTED_IN {roles:['English Bob']}]->(Unforgiven),
270 | (ClintE)-[:ACTED_IN {roles:['Bill Munny']}]->(Unforgiven),
271 | (Gene)-[:ACTED_IN {roles:['Little Bill Daggett']}]->(Unforgiven),
272 | (ClintE)-[:DIRECTED]->(Unforgiven)
273 |
274 | CREATE (JohnnyMnemonic:Movie {title:'Johnny Mnemonic', released:1995, tagline:'The hottest data on earth. In the coolest head in town'})
275 | CREATE (Takeshi:Person {name:'Takeshi Kitano', born:1947})
276 | CREATE (Dina:Person {name:'Dina Meyer', born:1968})
277 | CREATE (IceT:Person {name:'Ice-T', born:1958})
278 | CREATE (RobertL:Person {name:'Robert Longo', born:1953})
279 | CREATE
280 | (Keanu)-[:ACTED_IN {roles:['Johnny Mnemonic']}]->(JohnnyMnemonic),
281 | (Takeshi)-[:ACTED_IN {roles:['Takahashi']}]->(JohnnyMnemonic),
282 | (Dina)-[:ACTED_IN {roles:['Jane']}]->(JohnnyMnemonic),
283 | (IceT)-[:ACTED_IN {roles:['J-Bone']}]->(JohnnyMnemonic),
284 | (RobertL)-[:DIRECTED]->(JohnnyMnemonic)
285 |
286 | CREATE (CloudAtlas:Movie {title:'Cloud Atlas', released:2012, tagline:'Everything is connected'})
287 | CREATE (HalleB:Person {name:'Halle Berry', born:1966})
288 | CREATE (JimB:Person {name:'Jim Broadbent', born:1949})
289 | CREATE (TomT:Person {name:'Tom Tykwer', born:1965})
290 | CREATE (DavidMitchell:Person {name:'David Mitchell', born:1969})
291 | CREATE (StefanArndt:Person {name:'Stefan Arndt', born:1961})
292 | CREATE
293 | (TomH)-[:ACTED_IN {roles:['Zachry', 'Dr. Henry Goose', 'Isaac Sachs', 'Dermot Hoggins']}]->(CloudAtlas),
294 | (Hugo)-[:ACTED_IN {roles:['Bill Smoke', 'Haskell Moore', 'Tadeusz Kesselring', 'Nurse Noakes', 'Boardman Mephi', 'Old Georgie']}]->(CloudAtlas),
295 | (HalleB)-[:ACTED_IN {roles:['Luisa Rey', 'Jocasta Ayrs', 'Ovid', 'Meronym']}]->(CloudAtlas),
296 | (JimB)-[:ACTED_IN {roles:['Vyvyan Ayrs', 'Captain Molyneux', 'Timothy Cavendish']}]->(CloudAtlas),
297 | (TomT)-[:DIRECTED]->(CloudAtlas),
298 | (LillyW)-[:DIRECTED]->(CloudAtlas),
299 | (LanaW)-[:DIRECTED]->(CloudAtlas),
300 | (DavidMitchell)-[:WROTE]->(CloudAtlas),
301 | (StefanArndt)-[:PRODUCED]->(CloudAtlas)
302 |
303 | CREATE (TheDaVinciCode:Movie {title:'The Da Vinci Code', released:2006, tagline:'Break The Codes'})
304 | CREATE (IanM:Person {name:'Ian McKellen', born:1939})
305 | CREATE (AudreyT:Person {name:'Audrey Tautou', born:1976})
306 | CREATE (PaulB:Person {name:'Paul Bettany', born:1971})
307 | CREATE (RonH:Person {name:'Ron Howard', born:1954})
308 | CREATE
309 | (TomH)-[:ACTED_IN {roles:['Dr. Robert Langdon']}]->(TheDaVinciCode),
310 | (IanM)-[:ACTED_IN {roles:['Sir Leight Teabing']}]->(TheDaVinciCode),
311 | (AudreyT)-[:ACTED_IN {roles:['Sophie Neveu']}]->(TheDaVinciCode),
312 | (PaulB)-[:ACTED_IN {roles:['Silas']}]->(TheDaVinciCode),
313 | (RonH)-[:DIRECTED]->(TheDaVinciCode)
314 |
315 | CREATE (VforVendetta:Movie {title:'V for Vendetta', released:2006, tagline:'Freedom! Forever!'})
316 | CREATE (NatalieP:Person {name:'Natalie Portman', born:1981})
317 | CREATE (StephenR:Person {name:'Stephen Rea', born:1946})
318 | CREATE (JohnH:Person {name:'John Hurt', born:1940})
319 | CREATE (BenM:Person {name: 'Ben Miles', born:1967})
320 | CREATE
321 | (Hugo)-[:ACTED_IN {roles:['V']}]->(VforVendetta),
322 | (NatalieP)-[:ACTED_IN {roles:['Evey Hammond']}]->(VforVendetta),
323 | (StephenR)-[:ACTED_IN {roles:['Eric Finch']}]->(VforVendetta),
324 | (JohnH)-[:ACTED_IN {roles:['High Chancellor Adam Sutler']}]->(VforVendetta),
325 | (BenM)-[:ACTED_IN {roles:['Dascomb']}]->(VforVendetta),
326 | (JamesM)-[:DIRECTED]->(VforVendetta),
327 | (LillyW)-[:PRODUCED]->(VforVendetta),
328 | (LanaW)-[:PRODUCED]->(VforVendetta),
329 | (JoelS)-[:PRODUCED]->(VforVendetta),
330 | (LillyW)-[:WROTE]->(VforVendetta),
331 | (LanaW)-[:WROTE]->(VforVendetta)
332 |
333 | CREATE (SpeedRacer:Movie {title:'Speed Racer', released:2008, tagline:'Speed has no limits'})
334 | CREATE (EmileH:Person {name:'Emile Hirsch', born:1985})
335 | CREATE (JohnG:Person {name:'John Goodman', born:1960})
336 | CREATE (SusanS:Person {name:'Susan Sarandon', born:1946})
337 | CREATE (MatthewF:Person {name:'Matthew Fox', born:1966})
338 | CREATE (ChristinaR:Person {name:'Christina Ricci', born:1980})
339 | CREATE (Rain:Person {name:'Rain', born:1982})
340 | CREATE
341 | (EmileH)-[:ACTED_IN {roles:['Speed Racer']}]->(SpeedRacer),
342 | (JohnG)-[:ACTED_IN {roles:['Pops']}]->(SpeedRacer),
343 | (SusanS)-[:ACTED_IN {roles:['Mom']}]->(SpeedRacer),
344 | (MatthewF)-[:ACTED_IN {roles:['Racer X']}]->(SpeedRacer),
345 | (ChristinaR)-[:ACTED_IN {roles:['Trixie']}]->(SpeedRacer),
346 | (Rain)-[:ACTED_IN {roles:['Taejo Togokahn']}]->(SpeedRacer),
347 | (BenM)-[:ACTED_IN {roles:['Cass Jones']}]->(SpeedRacer),
348 | (LillyW)-[:DIRECTED]->(SpeedRacer),
349 | (LanaW)-[:DIRECTED]->(SpeedRacer),
350 | (LillyW)-[:WROTE]->(SpeedRacer),
351 | (LanaW)-[:WROTE]->(SpeedRacer),
352 | (JoelS)-[:PRODUCED]->(SpeedRacer)
353 |
354 | CREATE (NinjaAssassin:Movie {title:'Ninja Assassin', released:2009, tagline:'Prepare to enter a secret world of assassins'})
355 | CREATE (NaomieH:Person {name:'Naomie Harris'})
356 | CREATE
357 | (Rain)-[:ACTED_IN {roles:['Raizo']}]->(NinjaAssassin),
358 | (NaomieH)-[:ACTED_IN {roles:['Mika Coretti']}]->(NinjaAssassin),
359 | (RickY)-[:ACTED_IN {roles:['Takeshi']}]->(NinjaAssassin),
360 | (BenM)-[:ACTED_IN {roles:['Ryan Maslow']}]->(NinjaAssassin),
361 | (JamesM)-[:DIRECTED]->(NinjaAssassin),
362 | (LillyW)-[:PRODUCED]->(NinjaAssassin),
363 | (LanaW)-[:PRODUCED]->(NinjaAssassin),
364 | (JoelS)-[:PRODUCED]->(NinjaAssassin)
365 |
366 | CREATE (TheGreenMile:Movie {title:'The Green Mile', released:1999, tagline:"Walk a mile you'll never forget."})
367 | CREATE (MichaelD:Person {name:'Michael Clarke Duncan', born:1957})
368 | CREATE (DavidM:Person {name:'David Morse', born:1953})
369 | CREATE (SamR:Person {name:'Sam Rockwell', born:1968})
370 | CREATE (GaryS:Person {name:'Gary Sinise', born:1955})
371 | CREATE (PatriciaC:Person {name:'Patricia Clarkson', born:1959})
372 | CREATE (FrankD:Person {name:'Frank Darabont', born:1959})
373 | CREATE
374 | (TomH)-[:ACTED_IN {roles:['Paul Edgecomb']}]->(TheGreenMile),
375 | (MichaelD)-[:ACTED_IN {roles:['John Coffey']}]->(TheGreenMile),
376 | (DavidM)-[:ACTED_IN {roles:['Brutus "Brutal" Howell']}]->(TheGreenMile),
377 | (BonnieH)-[:ACTED_IN {roles:['Jan Edgecomb']}]->(TheGreenMile),
378 | (JamesC)-[:ACTED_IN {roles:['Warden Hal Moores']}]->(TheGreenMile),
379 | (SamR)-[:ACTED_IN {roles:['"Wild Bill" Wharton']}]->(TheGreenMile),
380 | (GaryS)-[:ACTED_IN {roles:['Burt Hammersmith']}]->(TheGreenMile),
381 | (PatriciaC)-[:ACTED_IN {roles:['Melinda Moores']}]->(TheGreenMile),
382 | (FrankD)-[:DIRECTED]->(TheGreenMile)
383 |
384 | CREATE (FrostNixon:Movie {title:'Frost/Nixon', released:2008, tagline:'400 million people were waiting for the truth.'})
385 | CREATE (FrankL:Person {name:'Frank Langella', born:1938})
386 | CREATE (MichaelS:Person {name:'Michael Sheen', born:1969})
387 | CREATE (OliverP:Person {name:'Oliver Platt', born:1960})
388 | CREATE
389 | (FrankL)-[:ACTED_IN {roles:['Richard Nixon']}]->(FrostNixon),
390 | (MichaelS)-[:ACTED_IN {roles:['David Frost']}]->(FrostNixon),
391 | (KevinB)-[:ACTED_IN {roles:['Jack Brennan']}]->(FrostNixon),
392 | (OliverP)-[:ACTED_IN {roles:['Bob Zelnick']}]->(FrostNixon),
393 | (SamR)-[:ACTED_IN {roles:['James Reston, Jr.']}]->(FrostNixon),
394 | (RonH)-[:DIRECTED]->(FrostNixon)
395 |
396 | CREATE (Hoffa:Movie {title:'Hoffa', released:1992, tagline:"He didn't want law. He wanted justice."})
397 | CREATE (DannyD:Person {name:'Danny DeVito', born:1944})
398 | CREATE (JohnR:Person {name:'John C. Reilly', born:1965})
399 | CREATE
400 | (JackN)-[:ACTED_IN {roles:['Hoffa']}]->(Hoffa),
401 | (DannyD)-[:ACTED_IN {roles:['Robert "Bobby" Ciaro']}]->(Hoffa),
402 | (JTW)-[:ACTED_IN {roles:['Frank Fitzsimmons']}]->(Hoffa),
403 | (JohnR)-[:ACTED_IN {roles:['Peter "Pete" Connelly']}]->(Hoffa),
404 | (DannyD)-[:DIRECTED]->(Hoffa)
405 |
406 | CREATE (Apollo13:Movie {title:'Apollo 13', released:1995, tagline:'Houston, we have a problem.'})
407 | CREATE (EdH:Person {name:'Ed Harris', born:1950})
408 | CREATE (BillPax:Person {name:'Bill Paxton', born:1955})
409 | CREATE
410 | (TomH)-[:ACTED_IN {roles:['Jim Lovell']}]->(Apollo13),
411 | (KevinB)-[:ACTED_IN {roles:['Jack Swigert']}]->(Apollo13),
412 | (EdH)-[:ACTED_IN {roles:['Gene Kranz']}]->(Apollo13),
413 | (BillPax)-[:ACTED_IN {roles:['Fred Haise']}]->(Apollo13),
414 | (GaryS)-[:ACTED_IN {roles:['Ken Mattingly']}]->(Apollo13),
415 | (RonH)-[:DIRECTED]->(Apollo13)
416 |
417 | CREATE (Twister:Movie {title:'Twister', released:1996, tagline:"Don't Breathe. Don't Look Back."})
418 | CREATE (PhilipH:Person {name:'Philip Seymour Hoffman', born:1967})
419 | CREATE (JanB:Person {name:'Jan de Bont', born:1943})
420 | CREATE
421 | (BillPax)-[:ACTED_IN {roles:['Bill Harding']}]->(Twister),
422 | (HelenH)-[:ACTED_IN {roles:['Dr. Jo Harding']}]->(Twister),
423 | (ZachG)-[:ACTED_IN {roles:['Eddie']}]->(Twister),
424 | (PhilipH)-[:ACTED_IN {roles:['Dustin "Dusty" Davis']}]->(Twister),
425 | (JanB)-[:DIRECTED]->(Twister)
426 |
427 | CREATE (CastAway:Movie {title:'Cast Away', released:2000, tagline:'At the edge of the world, his journey begins.'})
428 | CREATE (RobertZ:Person {name:'Robert Zemeckis', born:1951})
429 | CREATE
430 | (TomH)-[:ACTED_IN {roles:['Chuck Noland']}]->(CastAway),
431 | (HelenH)-[:ACTED_IN {roles:['Kelly Frears']}]->(CastAway),
432 | (RobertZ)-[:DIRECTED]->(CastAway)
433 |
434 | CREATE (OneFlewOvertheCuckoosNest:Movie {title:"One Flew Over the Cuckoo's Nest", released:1975, tagline:"If he's crazy, what does that make you?"})
435 | CREATE (MilosF:Person {name:'Milos Forman', born:1932})
436 | CREATE
437 | (JackN)-[:ACTED_IN {roles:['Randle McMurphy']}]->(OneFlewOvertheCuckoosNest),
438 | (DannyD)-[:ACTED_IN {roles:['Martini']}]->(OneFlewOvertheCuckoosNest),
439 | (MilosF)-[:DIRECTED]->(OneFlewOvertheCuckoosNest)
440 |
441 | CREATE (SomethingsGottaGive:Movie {title:"Something's Gotta Give", released:2003})
442 | CREATE (DianeK:Person {name:'Diane Keaton', born:1946})
443 | CREATE (NancyM:Person {name:'Nancy Meyers', born:1949})
444 | CREATE
445 | (JackN)-[:ACTED_IN {roles:['Harry Sanborn']}]->(SomethingsGottaGive),
446 | (DianeK)-[:ACTED_IN {roles:['Erica Barry']}]->(SomethingsGottaGive),
447 | (Keanu)-[:ACTED_IN {roles:['Julian Mercer']}]->(SomethingsGottaGive),
448 | (NancyM)-[:DIRECTED]->(SomethingsGottaGive),
449 | (NancyM)-[:PRODUCED]->(SomethingsGottaGive),
450 | (NancyM)-[:WROTE]->(SomethingsGottaGive)
451 |
452 | CREATE (BicentennialMan:Movie {title:'Bicentennial Man', released:1999, tagline:"One robot's 200 year journey to become an ordinary man."})
453 | CREATE (ChrisC:Person {name:'Chris Columbus', born:1958})
454 | CREATE
455 | (Robin)-[:ACTED_IN {roles:['Andrew Marin']}]->(BicentennialMan),
456 | (OliverP)-[:ACTED_IN {roles:['Rupert Burns']}]->(BicentennialMan),
457 | (ChrisC)-[:DIRECTED]->(BicentennialMan)
458 |
459 | CREATE (CharlieWilsonsWar:Movie {title:"Charlie Wilson's War", released:2007, tagline:"A stiff drink. A little mascara. A lot of nerve. Who said they couldn't bring down the Soviet empire."})
460 | CREATE (JuliaR:Person {name:'Julia Roberts', born:1967})
461 | CREATE
462 | (TomH)-[:ACTED_IN {roles:['Rep. Charlie Wilson']}]->(CharlieWilsonsWar),
463 | (JuliaR)-[:ACTED_IN {roles:['Joanne Herring']}]->(CharlieWilsonsWar),
464 | (PhilipH)-[:ACTED_IN {roles:['Gust Avrakotos']}]->(CharlieWilsonsWar),
465 | (MikeN)-[:DIRECTED]->(CharlieWilsonsWar)
466 |
467 | CREATE (ThePolarExpress:Movie {title:'The Polar Express', released:2004, tagline:'This Holiday Season… Believe'})
468 | CREATE
469 | (TomH)-[:ACTED_IN {roles:['Hero Boy', 'Father', 'Conductor', 'Hobo', 'Scrooge', 'Santa Claus']}]->(ThePolarExpress),
470 | (RobertZ)-[:DIRECTED]->(ThePolarExpress)
471 |
472 | CREATE (ALeagueofTheirOwn:Movie {title:'A League of Their Own', released:1992, tagline:'Once in a lifetime you get a chance to do something different.'})
473 | CREATE (Madonna:Person {name:'Madonna', born:1954})
474 | CREATE (GeenaD:Person {name:'Geena Davis', born:1956})
475 | CREATE (LoriP:Person {name:'Lori Petty', born:1963})
476 | CREATE (PennyM:Person {name:'Penny Marshall', born:1943})
477 | CREATE
478 | (TomH)-[:ACTED_IN {roles:['Jimmy Dugan']}]->(ALeagueofTheirOwn),
479 | (GeenaD)-[:ACTED_IN {roles:['Dottie Hinson']}]->(ALeagueofTheirOwn),
480 | (LoriP)-[:ACTED_IN {roles:['Kit Keller']}]->(ALeagueofTheirOwn),
481 | (RosieO)-[:ACTED_IN {roles:['Doris Murphy']}]->(ALeagueofTheirOwn),
482 | (Madonna)-[:ACTED_IN {roles:['"All the Way" Mae Mordabito']}]->(ALeagueofTheirOwn),
483 | (BillPax)-[:ACTED_IN {roles:['Bob Hinson']}]->(ALeagueofTheirOwn),
484 | (PennyM)-[:DIRECTED]->(ALeagueofTheirOwn)
485 |
486 | CREATE (PaulBlythe:Person {name:'Paul Blythe'})
487 | CREATE (AngelaScope:Person {name:'Angela Scope'})
488 | CREATE (JessicaThompson:Person {name:'Jessica Thompson'})
489 | CREATE (JamesThompson:Person {name:'James Thompson'})
490 |
491 | CREATE
492 | (JamesThompson)-[:FOLLOWS]->(JessicaThompson),
493 | (AngelaScope)-[:FOLLOWS]->(JessicaThompson),
494 | (PaulBlythe)-[:FOLLOWS]->(AngelaScope)
495 |
496 | CREATE
497 | (JessicaThompson)-[:REVIEWED {summary:'An amazing journey', rating:95}]->(CloudAtlas),
498 | (JessicaThompson)-[:REVIEWED {summary:'Silly, but fun', rating:65}]->(TheReplacements),
499 | (JamesThompson)-[:REVIEWED {summary:'The coolest football movie ever', rating:100}]->(TheReplacements),
500 | (AngelaScope)-[:REVIEWED {summary:'Pretty funny at times', rating:62}]->(TheReplacements),
501 | (JessicaThompson)-[:REVIEWED {summary:'Dark, but compelling', rating:85}]->(Unforgiven),
502 | (JessicaThompson)-[:REVIEWED {summary:"Slapstick redeemed only by the Robin Williams and Gene Hackman's stellar performances", rating:45}]->(TheBirdcage),
503 | (JessicaThompson)-[:REVIEWED {summary:'A solid romp', rating:68}]->(TheDaVinciCode),
504 | (JamesThompson)-[:REVIEWED {summary:'Fun, but a little far fetched', rating:65}]->(TheDaVinciCode),
505 | (JessicaThompson)-[:REVIEWED {summary:'You had me at Jerry', rating:92}]->(JerryMaguire)
506 |
507 | WITH TomH as a
508 | MATCH (a)-[:ACTED_IN]->(m)<-[:DIRECTED]-(d) RETURN a,m,d LIMIT 10;
--------------------------------------------------------------------------------