diff --git a/app.js b/app.js index 6757d54..a04391b 100644 --- a/app.js +++ b/app.js @@ -4,14 +4,25 @@ const dotenv = require('dotenv'); require('dotenv').config(); app.use(express.json()); -const getDataRoute = require('./features/GET_data'); -const postDataRoute = require('./features/POST_data'); -const deleteDataRoute = require('./features/DELETE_data'); +// Data routes +const getDataRoute = require('./features/data/GET_data'); +const postDataRoute = require('./features/data/POST_data'); +const deleteDataRoute = require('./features/data/DELETE_data'); app.use('/get_data', getDataRoute); app.use('/post_data', postDataRoute); app.use('/delete_data', deleteDataRoute); +// People routes +const CreatePersonRoute = require('./features/people/CREATE_people'); + +app.use('/create_person', CreatePersonRoute); + +// Relation routes +const CreateRelationRoute = require('./features/relations/CREATE_friendship'); + +app.use('/create_relationship', CreateRelationRoute) + app.listen(process.env.PORT, () => { console.log(`Server draait op port ${process.env.PORT}`) diff --git a/features/DELETE_data.js b/features/data/DELETE_data.js similarity index 95% rename from features/DELETE_data.js rename to features/data/DELETE_data.js index e5bc4d8..3ba2493 100644 --- a/features/DELETE_data.js +++ b/features/data/DELETE_data.js @@ -1,6 +1,6 @@ const express = require('express'); const router = express.Router(); -const pool = require('../db'); +const pool = require('../../db'); async function delete_data(req, res) { diff --git a/features/GET_data.js b/features/data/GET_data.js similarity index 94% rename from features/GET_data.js rename to features/data/GET_data.js index 248f6b4..002e221 100644 --- a/features/GET_data.js +++ b/features/data/GET_data.js @@ -1,6 +1,6 @@ const express = require('express'); const router = express.Router(); -const pool = require('../db'); +const pool = require('../../db'); async function get_data(req, res) { diff --git a/features/POST_data.js b/features/data/POST_data.js similarity index 95% rename from features/POST_data.js rename to features/data/POST_data.js index d91f0e2..67d0807 100644 --- a/features/POST_data.js +++ b/features/data/POST_data.js @@ -1,6 +1,6 @@ const express = require('express'); const router = express.Router(); -const pool = require('../db'); +const pool = require('../../db'); async function post_data(req, res) { diff --git a/features/people/CREATE_people.js b/features/people/CREATE_people.js new file mode 100644 index 0000000..691f0d9 --- /dev/null +++ b/features/people/CREATE_people.js @@ -0,0 +1,43 @@ +const express = require('express'); +const router = express.Router(); +var driver = require('../../graph_db'); +const pool = require('../../db'); + + + +async function create_people(req, res) { + const { name, age, gender } = req.body; + try { + const { records } = await driver.executeQuery('Create (p:Person {name: $name, age: $age, gender: $gender})', { name: name, age: age, gender: gender }, { database: process.env.GRAPH_DB_NAME}); + } + catch (err) { + console.error('database query failed', { + message: err.message, + code: err.code, + detail: err.detail, + hint: err.hint, + stack: err.stack, + }); + res.status(500).send('Data was not pushed to graph database, request failed'); + } + try { + const { rows } = await pool.query('INSERT INTO people (name, age, gender) VALUES ($1, $2, $3)', [name, age, gender]); + console.log(rows[0]); + res.status(200).send('Data has been pushed to both databases'); + res.json(rows[0]); + } + catch (err) { + console.error('database query failed', { + message: err.message, + code: err.code, + detail: err.detail, + hint: err.hint, + stack: err.stack, + }); + res.status(500).send('Data was not pushed to database, request failed'); + } +}; + + +router.post('/', create_people); +module.exports = router; \ No newline at end of file diff --git a/features/relations/CREATE_friendship.js b/features/relations/CREATE_friendship.js new file mode 100644 index 0000000..4c57623 --- /dev/null +++ b/features/relations/CREATE_friendship.js @@ -0,0 +1,28 @@ +const express = require('express'); +const router = express.Router(); +var driver = require('../../graph_db'); + + + +async function create_friendship(req, res) { + try { + const me = req.query.me; + const them = req.query.them; + const { records } = await driver.executeQuery('MATCH (m:Person {name: $me}) MATCH (t:Person {name: $them}) CREATE (m)-[:FRIENDS_WITH]-> (t) CREATE (t)-[:FRIENDS_WITH]-> (m)', { me: me, them: them }, { database: process.env.GRAPH_DB_NAME}); + res.status(200).send('Relationship has been created'); + } + catch (err) { + console.error('database query failed', { + message: err.message, + code: err.code, + detail: err.detail, + hint: err.hint, + stack: err.stack, + }); + res.status(500).send('Relationship was not created, request failed'); + } +}; + + +router.post('/', create_friendship); +module.exports = router; \ No newline at end of file diff --git a/graph_db.js b/graph_db.js new file mode 100644 index 0000000..954f819 --- /dev/null +++ b/graph_db.js @@ -0,0 +1,18 @@ +const neo4j = require('neo4j-driver'); + +const URI = process.env.GRAPH_DB_URI; +const USER = process.env.GRAPH_DB_USER; +const PASSWORD = process.env.GRAPH_DB_PWD; + +const driver = neo4j.driver(URI, neo4j.auth.basic(USER, PASSWORD)); + +(async () => { + try { + const serverInfo = await driver.getServerInfo(); + console.log('Neo4j Connection established'); + } catch (error) { + console.error('Neo4j Connection failed', error); + } +})(); + +module.exports = driver; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index fe81d13..dde037a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "dotenv": "^17.4.2", "express": "^5.2.1", + "neo4j-driver": "^6.2.0", "pg": "^8.22.0", "router": "^2.2.0" }, @@ -55,6 +56,26 @@ "node": "18 || 20 || >=22" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -131,6 +152,30 @@ "node": ">=8" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -597,6 +642,26 @@ "url": "https://opencollective.com/express" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -757,6 +822,37 @@ "node": ">= 0.6" } }, + "node_modules/neo4j-driver": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/neo4j-driver/-/neo4j-driver-6.2.0.tgz", + "integrity": "sha512-9W/Tk7EyjZHtv87NFpqoIbl0mlQx8bX8phUFzAM9xmeJrRpGDvqkpdQzc11DjwzywQCdhifaZPSvokSnAp7YTg==", + "license": "Apache-2.0", + "dependencies": { + "neo4j-driver-bolt-connection": "6.2.0", + "neo4j-driver-core": "6.2.0", + "rxjs": "^7.8.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/neo4j-driver-bolt-connection": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/neo4j-driver-bolt-connection/-/neo4j-driver-bolt-connection-6.2.0.tgz", + "integrity": "sha512-SEnFSBfumleDxmDAZKkjXxZ5LgL2iZSTx08sO+qXX45ZKaxZJOcg9oxwoXACXZ1RbIq3XbDfHU8I5tExanYEOA==", + "license": "Apache-2.0", + "dependencies": { + "buffer": "^6.0.3", + "neo4j-driver-core": "6.2.0", + "string_decoder": "^1.3.0" + } + }, + "node_modules/neo4j-driver-core": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/neo4j-driver-core/-/neo4j-driver-core-6.2.0.tgz", + "integrity": "sha512-U8PSdvDECWmCgSWyhqNNVzMONXFHWPcTd5gqi12+EDxxt0aETA0m+XCXf9H7q6qQXdisc40rUJEOcVQOu6peEA==", + "license": "Apache-2.0" + }, "node_modules/nodemon": { "version": "3.1.14", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", @@ -1082,6 +1178,35 @@ "node": ">= 18" } }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -1255,6 +1380,15 @@ "node": ">= 0.8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1300,6 +1434,12 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/type-is": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", diff --git a/package.json b/package.json index 0b3cc73..e46d1f6 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dependencies": { "dotenv": "^17.4.2", "express": "^5.2.1", + "neo4j-driver": "^6.2.0", "pg": "^8.22.0", "router": "^2.2.0" },