TimetableAPI-Upgrade (#64)
Partial implementation of: #47 The 2022.2.1 release currently live is based off of the TimetableAPI-Upgrade branch. Partial PIS code matching is now implemented in cases where x number of stops need skipping at the start of a route. Reviewed-on: #64
This commit is contained in:
parent
90baf1b13a
commit
c147d9c50c
36
app.js
36
app.js
@ -19,23 +19,12 @@ const cors = require("cors");
|
|||||||
const authenticate = require("./src/middlewares/auth.middlewares");
|
const authenticate = require("./src/middlewares/auth.middlewares");
|
||||||
|
|
||||||
// Internal Requires
|
// Internal Requires
|
||||||
const version = require("./src/configs/version.configs"); /*
|
const version = require("./src/configs/version.configs");
|
||||||
{}{}{} REMOVE THESE FILES - THEY ARE NO LONGER REQUIRED - {}{}{}
|
const pis2Rtr = require("./src/routes/pis.routes"); // API Version 2 Routes
|
||||||
const listRtr = require("./src/routes/list.routes");
|
const ref2Rtr = require("./src/routes/ref.routes"); // API Version 2 Routes
|
||||||
const ldbRtr = require("./src/routes/ldb.routes");
|
const live2Rtr = require("./src/routes/live.routes"); // API Version 2 Routes
|
||||||
const ldbsRtr = require("./src/routes/ldbs.routes");
|
const tt2Rtr = require("./src/routes/timetable.routes"); // API Version 2
|
||||||
const kubeRtr = require("./src/routes/kube.routes");
|
const user2Rtr = require("./src/routes/user.routes"); // API Version 2 Routes
|
||||||
const findRtr = require("./src/routes/find.routes");
|
|
||||||
const issueRtr = require("./src/routes/issue.routes");
|
|
||||||
const statRtr = require("./src/routes/stats.routes");
|
|
||||||
const regRtr = require("./src/routes/registration.routes");
|
|
||||||
const pisRtr = require("./src/routes/pis.routes");*/
|
|
||||||
const trainRtr = require("./src/routes/train.routes");
|
|
||||||
const pis2Rtr = require("./src/routes/pis2.routes"); // API Version 2 Routes
|
|
||||||
const ref2Rtr = require("./src/routes/ref2.routes"); // API Version 2 Routes
|
|
||||||
const live2Rtr = require("./src/routes/live2.routes"); // API Version 2 Routes
|
|
||||||
const tt2Rtr = require("./src/routes/timetable2.routes"); // API Version 2
|
|
||||||
const user2Rtr = require("./src/routes/user2.routes"); // API Version 2 Routes
|
|
||||||
const miscRtr = require("./src/routes/misc.routes"); // Non-Public API Routes
|
const miscRtr = require("./src/routes/misc.routes"); // Non-Public API Routes
|
||||||
|
|
||||||
// Set Server Configurations
|
// Set Server Configurations
|
||||||
@ -82,25 +71,12 @@ app.use("/api/v2/timetable", tt2Rtr); // API Version 2
|
|||||||
app.use("/api/v2/user", user2Rtr); // API Version 2
|
app.use("/api/v2/user", user2Rtr); // API Version 2
|
||||||
app.use("/misc", miscRtr); // Non public-api endpoints (Stats, Issue, etc.)
|
app.use("/misc", miscRtr); // Non public-api endpoints (Stats, Issue, etc.)
|
||||||
|
|
||||||
// Unauthenticated Routes
|
|
||||||
//app.use("/api/v1/list", listRtr); - Remove v1 List API - list.routes
|
|
||||||
//app.use("/api/v1/ldb", ldbRtr); - Remove v1 LDB API
|
|
||||||
//app.use("/api/v1/kube", kubeRtr); - Remove v1 Kube API
|
|
||||||
//app.use("/api/v1/find", findRtr); - Remove v1 Find API
|
|
||||||
//app.use("/api/v1/issue", issueRtr); - Remove v1 Issue API
|
|
||||||
//app.use("/api/v1/stats", statRtr); - Remove v1 Stats API
|
|
||||||
//app.use("/api/v1/register", regRtr); - Remove v1 Register API
|
|
||||||
|
|
||||||
// Authented Routes
|
|
||||||
//app.use("/api/v1/ldbs", authenticate, ldbsRtr); - Remove v1 LDBS API
|
|
||||||
//app.use("/api/v1/pis", authenticate, pisRtr); - Remove v1 PIS API
|
|
||||||
app.use("/api/v1/auth/test", authenticate, (req, res) =>
|
app.use("/api/v1/auth/test", authenticate, (req, res) =>
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
status: "ok",
|
status: "ok",
|
||||||
message: "Authentication successful",
|
message: "Authentication successful",
|
||||||
})
|
})
|
||||||
); // Returns 401 if auth failed, 200 if successful.
|
); // Returns 401 if auth failed, 200 if successful.
|
||||||
app.use("/api/v1/train", authenticate, trainRtr);
|
|
||||||
|
|
||||||
// Number of proxies:
|
// Number of proxies:
|
||||||
app.set("trust proxy", 4);
|
app.set("trust proxy", 4);
|
||||||
|
143
package-lock.json
generated
143
package-lock.json
generated
@ -24,7 +24,8 @@
|
|||||||
"zlib": "^1.0.5"
|
"zlib": "^1.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@owlboard/ts-types": "^0.0.9",
|
"@owlboard/ts-types": "^0.1.8",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
"@types/jest": "^29.5.3",
|
"@types/jest": "^29.5.3",
|
||||||
"eslint": "^8.39.0",
|
"eslint": "^8.39.0",
|
||||||
"jest": "^29.6.2",
|
"jest": "^29.6.2",
|
||||||
@ -839,12 +840,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@babel/generator": {
|
"node_modules/@babel/generator": {
|
||||||
"version": "7.22.15",
|
"version": "7.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
|
||||||
"integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
|
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.22.15",
|
"@babel/types": "^7.23.0",
|
||||||
"@jridgewell/gen-mapping": "^0.3.2",
|
"@jridgewell/gen-mapping": "^0.3.2",
|
||||||
"@jridgewell/trace-mapping": "^0.3.17",
|
"@jridgewell/trace-mapping": "^0.3.17",
|
||||||
"jsesc": "^2.5.1"
|
"jsesc": "^2.5.1"
|
||||||
@ -879,13 +880,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-function-name": {
|
"node_modules/@babel/helper-function-name": {
|
||||||
"version": "7.22.5",
|
"version": "7.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
|
||||||
"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
|
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.22.5",
|
"@babel/template": "^7.22.15",
|
||||||
"@babel/types": "^7.22.5"
|
"@babel/types": "^7.23.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@ -1094,9 +1095,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.22.16",
|
"version": "7.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
|
||||||
"integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==",
|
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
@ -1297,19 +1298,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.22.20",
|
"version": "7.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.20.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
|
||||||
"integrity": "sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==",
|
"integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.22.13",
|
"@babel/code-frame": "^7.22.13",
|
||||||
"@babel/generator": "^7.22.15",
|
"@babel/generator": "^7.23.0",
|
||||||
"@babel/helper-environment-visitor": "^7.22.20",
|
"@babel/helper-environment-visitor": "^7.22.20",
|
||||||
"@babel/helper-function-name": "^7.22.5",
|
"@babel/helper-function-name": "^7.23.0",
|
||||||
"@babel/helper-hoist-variables": "^7.22.5",
|
"@babel/helper-hoist-variables": "^7.22.5",
|
||||||
"@babel/helper-split-export-declaration": "^7.22.6",
|
"@babel/helper-split-export-declaration": "^7.22.6",
|
||||||
"@babel/parser": "^7.22.16",
|
"@babel/parser": "^7.23.0",
|
||||||
"@babel/types": "^7.22.19",
|
"@babel/types": "^7.23.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"globals": "^11.1.0"
|
"globals": "^11.1.0"
|
||||||
},
|
},
|
||||||
@ -1350,13 +1351,13 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.22.19",
|
"version": "7.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
|
||||||
"integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==",
|
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.22.5",
|
"@babel/helper-string-parser": "^7.22.5",
|
||||||
"@babel/helper-validator-identifier": "^7.22.19",
|
"@babel/helper-validator-identifier": "^7.22.20",
|
||||||
"to-fast-properties": "^2.0.0"
|
"to-fast-properties": "^2.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -1983,9 +1984,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@owlboard/ts-types": {
|
"node_modules/@owlboard/ts-types": {
|
||||||
"version": "0.0.9",
|
"version": "0.1.8",
|
||||||
"resolved": "https://git.fjla.uk/api/packages/OwlBoard/npm/%40owlboard%2Fts-types/-/0.0.9/ts-types-0.0.9.tgz",
|
"resolved": "https://git.fjla.uk/api/packages/OwlBoard/npm/%40owlboard%2Fts-types/-/0.1.8/ts-types-0.1.8.tgz",
|
||||||
"integrity": "sha512-kdystFqrfj6SF8jchv4OoaBIFfJF4YoM7m09POZfuEWrdj69IXZG41k0cfYadft1wZs8L6mcZIunu8t/S5Q82Q==",
|
"integrity": "sha512-GNwaaAiP9MJKvDODg6C3U9GSwm1+BodkAndFRWoZXN+rU1KUFoxMEp2k1ThnCrrJHktVYDWk9dkyl1PlgSKtaw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "GPL-3.0-or-later"
|
"license": "GPL-3.0-or-later"
|
||||||
},
|
},
|
||||||
@ -2636,6 +2637,49 @@
|
|||||||
"@babel/types": "^7.20.7"
|
"@babel/types": "^7.20.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/body-parser": {
|
||||||
|
"version": "1.19.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
|
||||||
|
"integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/connect": "*",
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/connect": {
|
||||||
|
"version": "3.4.38",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
|
||||||
|
"integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/express": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/body-parser": "*",
|
||||||
|
"@types/express-serve-static-core": "^4.17.33",
|
||||||
|
"@types/qs": "*",
|
||||||
|
"@types/serve-static": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/express-serve-static-core": {
|
||||||
|
"version": "4.17.43",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.43.tgz",
|
||||||
|
"integrity": "sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/qs": "*",
|
||||||
|
"@types/range-parser": "*",
|
||||||
|
"@types/send": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/graceful-fs": {
|
"node_modules/@types/graceful-fs": {
|
||||||
"version": "4.1.6",
|
"version": "4.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
|
||||||
@ -2645,6 +2689,12 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/http-errors": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/istanbul-lib-coverage": {
|
"node_modules/@types/istanbul-lib-coverage": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
|
||||||
@ -2679,11 +2729,50 @@
|
|||||||
"pretty-format": "^29.0.0"
|
"pretty-format": "^29.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/mime": {
|
||||||
|
"version": "1.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
|
||||||
|
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.6.2",
|
"version": "20.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.2.tgz",
|
||||||
"integrity": "sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw=="
|
"integrity": "sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/qs": {
|
||||||
|
"version": "6.9.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz",
|
||||||
|
"integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@types/range-parser": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
|
||||||
|
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@types/send": {
|
||||||
|
"version": "0.17.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
|
||||||
|
"integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mime": "^1",
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/serve-static": {
|
||||||
|
"version": "1.15.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz",
|
||||||
|
"integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/http-errors": "*",
|
||||||
|
"@types/mime": "*",
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/stack-utils": {
|
"node_modules/@types/stack-utils": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "owlboard",
|
"name": "owlboard",
|
||||||
"version": "1.2.0-dev",
|
"version": "2024.2.1",
|
||||||
"description": "OwlBoard is an API and PWA for live rail departure board in the UK.",
|
"description": "OwlBoard is an API and PWA for live rail departure board in the UK.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -12,6 +12,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"run": "tsc && node dist/app.js",
|
"run": "tsc && node dist/app.js",
|
||||||
|
"dev": "tsc && NODE_ENV=development node dist/app.js",
|
||||||
"start": "node app.js",
|
"start": "node app.js",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"format": "npx prettier -w ."
|
"format": "npx prettier -w ."
|
||||||
@ -32,7 +33,8 @@
|
|||||||
"zlib": "^1.0.5"
|
"zlib": "^1.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@owlboard/ts-types": "^0.0.9",
|
"@owlboard/ts-types": "^0.1.8",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
"@types/jest": "^29.5.3",
|
"@types/jest": "^29.5.3",
|
||||||
"eslint": "^8.39.0",
|
"eslint": "^8.39.0",
|
||||||
"jest": "^29.6.2",
|
"jest": "^29.6.2",
|
||||||
|
@ -4,8 +4,8 @@ interface versions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const version: versions = {
|
const version: versions = {
|
||||||
api: ["/api/v1/", "/api/v2"],
|
api: ["/api/v2"],
|
||||||
app: "2023.10.1",
|
app: "2024.2.1",
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = version;
|
module.exports = version;
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
const find = require("../services/find.services");
|
|
||||||
|
|
||||||
async function findName(req, res, next) {
|
|
||||||
try {
|
|
||||||
var id = req.params.id;
|
|
||||||
res.json(await find.name(id));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findCrs(req, res, next) {
|
|
||||||
try {
|
|
||||||
var id = req.params.id;
|
|
||||||
res.json(await find.crs(id));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findNlc(req, res, next) {
|
|
||||||
try {
|
|
||||||
var id = req.params.id;
|
|
||||||
res.json(await find.nlc(id));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findTiploc(req, res, next) {
|
|
||||||
try {
|
|
||||||
var id = req.params.id;
|
|
||||||
res.json(await find.tiploc(id));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function findStanox(req, res, next) {
|
|
||||||
try {
|
|
||||||
var id = req.params.id;
|
|
||||||
res.json(await find.stanox(id));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = {
|
|
||||||
findName,
|
|
||||||
findCrs,
|
|
||||||
findNlc,
|
|
||||||
findTiploc,
|
|
||||||
findStanox,
|
|
||||||
};
|
|
@ -1,35 +0,0 @@
|
|||||||
const kube = require("../services/kube.services");
|
|
||||||
|
|
||||||
async function getAlive(req, res, next) {
|
|
||||||
try {
|
|
||||||
var state = kube.getAlive();
|
|
||||||
res.status((await state).code).send((await state).state);
|
|
||||||
} catch (err) {
|
|
||||||
res.status("503").send({ state: "error" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getReady(req, res, next) {
|
|
||||||
try {
|
|
||||||
res.json(await kube.getReady(req.body));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getTime(req, res, next) {
|
|
||||||
try {
|
|
||||||
res.json(await kube.getTime(req.body));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
err.status = 503;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAlive,
|
|
||||||
getReady,
|
|
||||||
getTime,
|
|
||||||
};
|
|
@ -1,17 +1,5 @@
|
|||||||
const ldb = require("../services/ldb.services");
|
const ldb = require("../services/ldb.services");
|
||||||
|
|
||||||
async function get(req, res, next) {
|
|
||||||
// API v1 only
|
|
||||||
try {
|
|
||||||
var id = req.params.id;
|
|
||||||
res.json(await ldb.get(id));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getTrain(req, res, next) {
|
async function getTrain(req, res, next) {
|
||||||
// API v2 Only
|
// API v2 Only
|
||||||
if (!req.isAuthed) {
|
if (!req.isAuthed) {
|
||||||
@ -66,7 +54,6 @@ async function getStation(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
get,
|
|
||||||
getTrain,
|
getTrain,
|
||||||
getStation,
|
getStation,
|
||||||
};
|
};
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
const ldb = require("../services/ldb.services");
|
|
||||||
|
|
||||||
async function get(req, res, next) {
|
|
||||||
try {
|
|
||||||
var id = req.params.id;
|
|
||||||
res.json(await ldb.get(id, true));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getReasonCodeList(req, res, next) {
|
|
||||||
try {
|
|
||||||
res.json(await ldb.getReasonCodeList());
|
|
||||||
} catch (err) {
|
|
||||||
console.error("ERROR", err.message);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getReasonCode(req, res, next) {
|
|
||||||
try {
|
|
||||||
const code = req.params.code;
|
|
||||||
res.json(await ldb.getReasonCode(code));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("ERROR", err.message);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getTrainByRID(req, res, next) {
|
|
||||||
try {
|
|
||||||
const rid = req.params.rid;
|
|
||||||
res.json(await ldb.getServiceByRID(rid));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("ERROR", err);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
get,
|
|
||||||
getReasonCodeList,
|
|
||||||
getReasonCode,
|
|
||||||
getTrainByRID,
|
|
||||||
};
|
|
@ -1,37 +0,0 @@
|
|||||||
const list = require("../services/list.services");
|
|
||||||
|
|
||||||
async function getStations(req, res, next) {
|
|
||||||
try {
|
|
||||||
res.json(await list.getStations(req.body));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Controller Error", err.message);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getCorpus(req, res, next) {
|
|
||||||
try {
|
|
||||||
res.json(await list.getCorpus(req.body));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Controller Error", err.message);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function hits(req, res, next) {
|
|
||||||
try {
|
|
||||||
res.json(await list.hits());
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Controller Error", err);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getStations,
|
|
||||||
getCorpus,
|
|
||||||
hits,
|
|
||||||
};
|
|
@ -1,21 +1,5 @@
|
|||||||
const pis = require("../services/pis.services");
|
const pis = require("../services/pis.services");
|
||||||
|
|
||||||
async function byOrigDest(req, res, next) {
|
|
||||||
if (!req.isAuthed) {
|
|
||||||
const err = new Error("Unauthorized");
|
|
||||||
err.status = 401;
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
let start = req.params.start;
|
|
||||||
let end = req.params.end;
|
|
||||||
res.json(await pis.findPisByOrigDest(start, end));
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Unknown Error", err.message);
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Used in /api/v2 */
|
/* Used in /api/v2 */
|
||||||
async function byStartEndCRS(req, res, next) {
|
async function byStartEndCRS(req, res, next) {
|
||||||
if (!req.isAuthed) {
|
if (!req.isAuthed) {
|
||||||
@ -64,7 +48,6 @@ async function random(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
byOrigDest,
|
|
||||||
byStartEndCRS,
|
byStartEndCRS,
|
||||||
byCode,
|
byCode,
|
||||||
random,
|
random,
|
||||||
|
@ -1,16 +1,5 @@
|
|||||||
const stat = require("../services/stats.services");
|
const stat = require("../services/stats.services");
|
||||||
|
|
||||||
async function get(req, res, next) {
|
|
||||||
// API V1
|
|
||||||
try {
|
|
||||||
res.json(await stat.hits());
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Controller Error", err);
|
|
||||||
err.status = 500;
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function versions(req, res, next) {
|
async function versions(req, res, next) {
|
||||||
// API v2
|
// API v2
|
||||||
try {
|
try {
|
||||||
@ -34,7 +23,6 @@ async function statistics(req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
get,
|
|
||||||
versions,
|
versions,
|
||||||
statistics,
|
statistics,
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
import { logger } from "../utils/logger.utils";
|
||||||
|
|
||||||
const train = require("../services/trainService.services");
|
const train = require("../services/trainService.services");
|
||||||
|
|
||||||
async function getByHeadcodeToday(req, res, next) {
|
async function getByHeadcodeToday(req, res, next) {
|
||||||
|
// Deprecated - for future removal.
|
||||||
|
logger.warn("Deprecated Function Called - trainService.services-getByHeadcodeToday")
|
||||||
if (!req.isAuthed) {
|
if (!req.isAuthed) {
|
||||||
const err = new Error("Unauthorized");
|
const err = new Error("Unauthorized");
|
||||||
err.status = 401;
|
err.status = 401;
|
||||||
@ -28,7 +32,7 @@ async function get(req, res, next) {
|
|||||||
try {
|
try {
|
||||||
switch (searchType) {
|
switch (searchType) {
|
||||||
case "headcode":
|
case "headcode":
|
||||||
res.json(await train.findByHeadcode(date, id));
|
res.json(await train.findByHeadcode(id, date));
|
||||||
break;
|
break;
|
||||||
case "byTrainUid":
|
case "byTrainUid":
|
||||||
res.json(await train.findByTrainUid(id, date));
|
res.json(await train.findByTrainUid(id, date));
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
const utils = require("../utils/auth.utils");
|
|
||||||
const logger = require("../utils/logger.utils");
|
|
||||||
|
|
||||||
module.exports = async function authCheck(req, res, next) {
|
|
||||||
//log.out("authMiddlewares: Checking authentication", "dbug");
|
|
||||||
logger.logger.debug("Auth check starting");
|
|
||||||
try {
|
|
||||||
var uuid = req.headers.uuid;
|
|
||||||
} catch (err) {
|
|
||||||
logger.logger.warn("Unable to read UUID header - Not authenticated");
|
|
||||||
req.isAuthed = false;
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
var result = (await utils.isAuthed(uuid)) || false;
|
|
||||||
if (!result) {
|
|
||||||
req.isAuthed = false;
|
|
||||||
//log.out("authMiddlewares: User !isAuthed", "dbug");
|
|
||||||
logger.logger.debug("Auth denied");
|
|
||||||
} else {
|
|
||||||
req.isAuthed = true;
|
|
||||||
//log.out("authMiddlewares: User isAuthed", "dbug");
|
|
||||||
logger.logger.debug("Auth successful");
|
|
||||||
}
|
|
||||||
return next();
|
|
||||||
} catch (err) {
|
|
||||||
/*log.out(
|
|
||||||
"authMiddlewares: Unable to check auth, default to !isAuthed",
|
|
||||||
"warn"
|
|
||||||
);*/
|
|
||||||
logger.logger.error(err, `Auth check failed`);
|
|
||||||
req.isAuthed = false;
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
};
|
|
50
src/middlewares/auth.middlewares.ts
Normal file
50
src/middlewares/auth.middlewares.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { NextFunction, Request, Response } from "express";
|
||||||
|
|
||||||
|
const utils = require("../utils/auth.utils");
|
||||||
|
const logger = require("../utils/logger.utils");
|
||||||
|
|
||||||
|
module.exports = async function authCheck(
|
||||||
|
req: Request,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
) {
|
||||||
|
logger.logger.debug("auth.middleware: Auth check begun");
|
||||||
|
if (process.env.NODE_ENV === "development") {
|
||||||
|
req.isAuthed = true;
|
||||||
|
logger.logger.warn("auth.middleware: DEV MODE - Access Granted");
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
const id: string | string[] | undefined = req.headers.uuid;
|
||||||
|
if (typeof id === "undefined") {
|
||||||
|
req.isAuthed = false;
|
||||||
|
logger.logger.info("auth.middleware: Authentication failed");
|
||||||
|
next();
|
||||||
|
} else if (typeof id === "string") {
|
||||||
|
const authCheck = (await utils.isAuthed(id)) || false;
|
||||||
|
if (authCheck) {
|
||||||
|
req.isAuthed = true;
|
||||||
|
logger.logger.info("auth.middleware: Authentication Successful");
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
req.isAuthed = false;
|
||||||
|
logger.logger.info("auth.middleware: Authentication Failed");
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(id)) {
|
||||||
|
const authCheck = (await utils.isAuthed(id[0])) || false;
|
||||||
|
if (authCheck) {
|
||||||
|
req.isAuthed = true;
|
||||||
|
logger.logger.warn(
|
||||||
|
"auth.middleware: UUID Passed as Array - Authentication Successful"
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
req.isAuthed = false;
|
||||||
|
logger.logger.warn(
|
||||||
|
"auth.middleware: UUID Passed as Array - Authentication Failed"
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -1,23 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const findController = require("../controllers/find.controllers");
|
|
||||||
|
|
||||||
/* GET programming languages. */
|
|
||||||
//router.get('/', programmingLanguagesController.get);
|
|
||||||
|
|
||||||
/* POST programming language */
|
|
||||||
//router.post('/', programmingLanguagesController.create);
|
|
||||||
|
|
||||||
/* PUT programming language */
|
|
||||||
//router.put('/:id', programmingLanguagesController.update);
|
|
||||||
|
|
||||||
/* DELETE programming language */
|
|
||||||
//router.delete('/:id', programmingLanguagesController.remove);
|
|
||||||
|
|
||||||
router.get("/name/:id", findController.findName);
|
|
||||||
router.get("/crs/:id", findController.findCrs);
|
|
||||||
router.get("/nlc/:id", findController.findNlc);
|
|
||||||
router.get("/tiploc/:id", findController.findTiploc);
|
|
||||||
router.get("/stanox/:id", findController.findStanox);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,7 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const issueController = require("../controllers/issue.controllers");
|
|
||||||
|
|
||||||
router.post("/", issueController.post);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,9 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const kubeController = require("../controllers/kube.controllers");
|
|
||||||
|
|
||||||
router.get("/alive", kubeController.getAlive);
|
|
||||||
router.get("/ready", kubeController.getReady);
|
|
||||||
router.get("/time", kubeController.getTime);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,19 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const ldbController = require("../controllers/ldb.controllers");
|
|
||||||
|
|
||||||
/* GET programming languages. */
|
|
||||||
//router.get('/', programmingLanguagesController.get);
|
|
||||||
|
|
||||||
/* POST programming language */
|
|
||||||
//router.post('/', programmingLanguagesController.create);
|
|
||||||
|
|
||||||
/* PUT programming language */
|
|
||||||
//router.put('/:id', programmingLanguagesController.update);
|
|
||||||
|
|
||||||
/* DELETE programming language */
|
|
||||||
//router.delete('/:id', programmingLanguagesController.remove);
|
|
||||||
|
|
||||||
router.get("/:id", ldbController.get);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,22 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const ldbsController = require("../controllers/ldbs.controllers");
|
|
||||||
|
|
||||||
/* GET programming languages. */
|
|
||||||
//router.get('/', programmingLanguagesController.get);
|
|
||||||
|
|
||||||
/* POST programming language */
|
|
||||||
//router.post('/', programmingLanguagesController.create);
|
|
||||||
|
|
||||||
/* PUT programming language */
|
|
||||||
//router.put('/:id', programmingLanguagesController.update);
|
|
||||||
|
|
||||||
/* DELETE programming language */
|
|
||||||
//router.delete('/:id', programmingLanguagesController.remove);
|
|
||||||
|
|
||||||
router.get("/arrdep/:id", ldbsController.get);
|
|
||||||
router.get("/reasonCode", ldbsController.getReasonCodeList);
|
|
||||||
router.get("/reasonCode/:code", ldbsController.getReasonCode);
|
|
||||||
router.get("/service/rid/:rid", ldbsController.getTrainByRID);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,20 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const listController = require("../controllers/list.controllers");
|
|
||||||
|
|
||||||
/* GET programming languages. */
|
|
||||||
//router.get('/', programmingLanguagesController.get);
|
|
||||||
|
|
||||||
/* POST programming language */
|
|
||||||
//router.post('/', programmingLanguagesController.create);
|
|
||||||
|
|
||||||
/* PUT programming language */
|
|
||||||
//router.put('/:id', programmingLanguagesController.update);
|
|
||||||
|
|
||||||
/* DELETE programming language */
|
|
||||||
//router.delete('/:id', programmingLanguagesController.remove);
|
|
||||||
|
|
||||||
router.get("/stations", listController.getStations);
|
|
||||||
router.get("/corpus", listController.getCorpus);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,9 +1,9 @@
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const pisController = require("../controllers/pis.controllers");
|
const pisCtr = require("../controllers/pis.controllers");
|
||||||
|
|
||||||
router.get("/origdest/:start/:end", pisController.byOrigDest);
|
// PIS
|
||||||
router.get("/code/:code", pisController.byCode);
|
router.get("/byCode/:code", pisCtr.byCode);
|
||||||
router.get("/code/random", pisController.random);
|
router.get("/byStartEnd/:startCrs/:endCrs", pisCtr.byStartEndCRS);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const pisCtr = require("../controllers/pis.controllers");
|
|
||||||
|
|
||||||
// PIS
|
|
||||||
router.get("/byCode/:code", pisCtr.byCode);
|
|
||||||
router.get("/byStartEnd/:startCrs/:endCrs", pisCtr.byStartEndCRS);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,8 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const regController = require("../controllers/registration.controllers");
|
|
||||||
|
|
||||||
router.post("/request", regController.request);
|
|
||||||
router.post("/register", regController.register);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,7 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const statsController = require("../controllers/stats.controllers");
|
|
||||||
|
|
||||||
router.get("/", statsController.get);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -1,19 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const router = express.Router();
|
|
||||||
const trainController = require("../controllers/train.controllers");
|
|
||||||
|
|
||||||
/* GET programming languages. */
|
|
||||||
//router.get('/', programmingLanguagesController.get);
|
|
||||||
|
|
||||||
/* POST programming language */
|
|
||||||
//router.post('/', programmingLanguagesController.create);
|
|
||||||
|
|
||||||
/* PUT programming language */
|
|
||||||
//router.put('/:id', programmingLanguagesController.update);
|
|
||||||
|
|
||||||
/* DELETE programming language */
|
|
||||||
//router.delete('/:id', programmingLanguagesController.remove);
|
|
||||||
|
|
||||||
router.get("/headcode/today/:id", trainController.getByHeadcodeToday);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
@ -4,7 +4,11 @@ const pis = require("../services/pis.services");
|
|||||||
|
|
||||||
import { logger } from "../utils/logger.utils";
|
import { logger } from "../utils/logger.utils";
|
||||||
|
|
||||||
async function findByHeadcodeToday(headcode) {
|
import type { TrainServices, Service, Stop } from "@owlboard/ts-types";
|
||||||
|
|
||||||
|
// This function is deprecated and should no longer be used.
|
||||||
|
// It will be removed in a later version
|
||||||
|
async function findByHeadcodeToday(headcode: string) {
|
||||||
const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode).toUpperCase();
|
const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode).toUpperCase();
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`
|
`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`
|
||||||
@ -39,7 +43,11 @@ async function findByHeadcodeToday(headcode) {
|
|||||||
return preparedData;
|
return preparedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findByHeadcode(date, headcode) {
|
// Finds a train by its headcode value
|
||||||
|
async function findByHeadcode(
|
||||||
|
date: string | Date,
|
||||||
|
headcode: string
|
||||||
|
): Promise<TrainServices[]> {
|
||||||
const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode).toUpperCase();
|
const sanitizedHeadcode = clean.removeNonAlphanumeric(headcode).toUpperCase();
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`
|
`trainServiceServices.findByHeadcode: Searching for headcode ${sanitizedHeadcode}`
|
||||||
@ -77,12 +85,16 @@ async function findByHeadcode(date, headcode) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const queryData = await db.queryAggregate("timetable", pipeline);
|
const queryData: Service[] = await db.queryAggregate("timetable", pipeline);
|
||||||
let filteredData = filterServices(queryData);
|
let filteredData = filterServices(queryData);
|
||||||
return await filteredData;
|
return await filteredData;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findByTrainUid(uid, date = new Date()) {
|
// Finds a train by its trainUid value
|
||||||
|
async function findByTrainUid(
|
||||||
|
uid: string,
|
||||||
|
date: Date | string = new Date()
|
||||||
|
): Promise<TrainServices | null> {
|
||||||
let queryDate;
|
let queryDate;
|
||||||
if (date === "now") {
|
if (date === "now") {
|
||||||
queryDate = new Date();
|
queryDate = new Date();
|
||||||
@ -96,7 +108,7 @@ async function findByTrainUid(uid, date = new Date()) {
|
|||||||
};
|
};
|
||||||
const queryData = await db.query("timetable", query);
|
const queryData = await db.query("timetable", query);
|
||||||
if (queryData.length === 0) {
|
if (queryData.length === 0) {
|
||||||
return [];
|
return queryData;
|
||||||
}
|
}
|
||||||
let services;
|
let services;
|
||||||
services = await filterServices(queryData);
|
services = await filterServices(queryData);
|
||||||
@ -124,7 +136,7 @@ module.exports = {
|
|||||||
|
|
||||||
/* Accepts the 'stops' array from a db query and produces an
|
/* Accepts the 'stops' array from a db query and produces an
|
||||||
array of only public stops as TIPLOCs. */
|
array of only public stops as TIPLOCs. */
|
||||||
async function getPublicStops(data) {
|
async function getPublicStops(data: Stop[]): Promise<string[]> {
|
||||||
let tiplocList = [];
|
let tiplocList = [];
|
||||||
for (const publicStop in data) {
|
for (const publicStop in data) {
|
||||||
if (data[publicStop]["isPublic"]) {
|
if (data[publicStop]["isPublic"]) {
|
||||||
@ -137,23 +149,26 @@ async function getPublicStops(data) {
|
|||||||
/* Takes a single days data from a headcode query and requeries
|
/* Takes a single days data from a headcode query and requeries
|
||||||
using the trainUid, required to ensure any cancellations are
|
using the trainUid, required to ensure any cancellations are
|
||||||
accounted for */
|
accounted for */
|
||||||
async function parseTrains(data) {
|
async function parseTrains(data: TrainServices[]): Promise<TrainServices[]> {
|
||||||
let trainUids = [];
|
let trainUids: string[] = [];
|
||||||
for (const i of data) {
|
for (const i of data) {
|
||||||
const trainUid = i["trainUid"];
|
const trainUid = i["trainUid"];
|
||||||
if (!trainUids.includes(trainUid)) {
|
if (!trainUids.includes(trainUid)) {
|
||||||
trainUids.push(trainUid);
|
trainUids.push(trainUid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let parsedData = [];
|
let parsedData: TrainServices[] = [];
|
||||||
for (const i in trainUids) {
|
for (const i in trainUids) {
|
||||||
const result = await findByTrainUid(trainUids[i]);
|
const result: TrainServices | null = await findByTrainUid(trainUids[i]);
|
||||||
|
if (result) {
|
||||||
parsedData.push(result);
|
parsedData.push(result);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return parsedData;
|
return parsedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function filterServices(data) {
|
// Filters services based on their STP Indicator
|
||||||
|
async function filterServices(data: Service[]): Promise<TrainServices[]> {
|
||||||
let stpIndicators = {},
|
let stpIndicators = {},
|
||||||
filteredServices = [];
|
filteredServices = [];
|
||||||
for (const serviceDetail of data) {
|
for (const serviceDetail of data) {
|
||||||
@ -180,7 +195,7 @@ async function filterServices(data) {
|
|||||||
stpIndicators[trainUid].hasP = true;
|
stpIndicators[trainUid].hasP = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let preparedData;
|
|
||||||
for (const serviceDetail of data) {
|
for (const serviceDetail of data) {
|
||||||
const trainUid = serviceDetail["trainUid"];
|
const trainUid = serviceDetail["trainUid"];
|
||||||
const thisStpIndicators = stpIndicators[trainUid];
|
const thisStpIndicators = stpIndicators[trainUid];
|
@ -7,7 +7,7 @@ const db = require("../services/dbAccess.services");
|
|||||||
|
|
||||||
import { logger } from "../utils/logger.utils";
|
import { logger } from "../utils/logger.utils";
|
||||||
|
|
||||||
import { transform as staffStationTransform } from "../utils/translators/ldb/staffStation";
|
import { transform as staffStationTransform } from "../utils/processors/ldb/staffStation";
|
||||||
import { msgCodes } from "../configs/errorCodes.configs";
|
import { msgCodes } from "../configs/errorCodes.configs";
|
||||||
|
|
||||||
const ldbKey = process.env.OWL_LDB_KEY;
|
const ldbKey = process.env.OWL_LDB_KEY;
|
||||||
|
@ -3,9 +3,17 @@
|
|||||||
const db = require("../services/dbAccess.services");
|
const db = require("../services/dbAccess.services");
|
||||||
const clean = require("../utils/sanitizer.utils");
|
const clean = require("../utils/sanitizer.utils");
|
||||||
|
|
||||||
import { logger } from "../utils/logger.utils";
|
import type { OB_Pis_SimpleObject } from "@owlboard/ts-types";
|
||||||
|
|
||||||
const supported = ["GW", "UK"];
|
import { logger } from "../utils/logger.utils";
|
||||||
|
import { queryAggregate } from "./dbAccess.services";
|
||||||
|
import {
|
||||||
|
getPartialEndTiplocMatchPipeline,
|
||||||
|
getFullTiplocMatchPipeline,
|
||||||
|
} from "../utils/pis.utils";
|
||||||
|
import { Document } from "mongodb";
|
||||||
|
|
||||||
|
export const supported = ["GW", "UK"];
|
||||||
|
|
||||||
async function findPisByOrigDest(start: string, end: string) {
|
async function findPisByOrigDest(start: string, end: string) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
@ -27,11 +35,14 @@ async function findPisByOrigDest(start: string, end: string) {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const search = db.query("pis", query);
|
const search = await db.query("pis", query);
|
||||||
return await search;
|
// Check for results, if none then try partial match
|
||||||
|
return search;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findPisByCode(code: string) {
|
async function findPisByCode(
|
||||||
|
code: string
|
||||||
|
): Promise<OB_Pis_SimpleObject | null> {
|
||||||
logger.debug(`pisServices.findPisByCode: Searching for PIS code: ${code}`);
|
logger.debug(`pisServices.findPisByCode: Searching for PIS code: ${code}`);
|
||||||
const cleanCode = clean.removeNonNumeric(code);
|
const cleanCode = clean.removeNonNumeric(code);
|
||||||
const query = {
|
const query = {
|
||||||
@ -41,25 +52,74 @@ async function findPisByCode(code: string) {
|
|||||||
return await search;
|
return await search;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findByTiplocArray(tiplocArray: string[]) {
|
// Queries the database for PIS codes that match the given TIPLOC array
|
||||||
const query = {
|
export async function findByTiplocArray(
|
||||||
tiplocs: tiplocArray,
|
tiplocArray: string[]
|
||||||
};
|
): Promise<OB_Pis_SimpleObject | null> {
|
||||||
const res = await db.query("pis", query);
|
// Firstly fix errant TIPLOCS such as RDNG4AB which will never return a result
|
||||||
// If res is empty then try to find partial match
|
// currently only works with RDNG4AB - checks for presence of RDNG4AB first to
|
||||||
/* if (res.length) {
|
// avoid iterating over every array ever searched for.
|
||||||
return res;
|
if (tiplocArray.includes("RDNG4AB")) {
|
||||||
|
fixErrantTiplocs(tiplocArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PERFORMANCE NOTE:
|
||||||
|
// The majority of queries will return a full match,
|
||||||
|
// this means that a more performant pipeline is used
|
||||||
|
// to find a full match and only then are more
|
||||||
|
// complicated pipelines used to find partial matches
|
||||||
|
// if the first pipeline returns nothing.
|
||||||
|
try {
|
||||||
|
const exactMatch = await findExactMatchByTiploc(tiplocArray);
|
||||||
|
if (exactMatch) {
|
||||||
|
return convertDocument(exactMatch, "none");
|
||||||
} else {
|
} else {
|
||||||
let partial = await findPartialMatchByTiploc(tiplocArray);
|
const partialEnd = await findPartialEndMatchByTiploc(tiplocArray);
|
||||||
return partial
|
if (partialEnd) {
|
||||||
} */
|
return convertDocument(partialEnd, "first");
|
||||||
return await res;
|
} else {
|
||||||
|
// Here, I should search for a partialStart match. For now return null.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(err, "Error in findByTiplocArray");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findPartialMatchByTiploc(tiplocArray: string[]) {
|
// Uses a pipeline to find an exact match
|
||||||
// Do some magic here, similar to findPisByOrigDest but
|
async function findExactMatchByTiploc(array: string[]): Promise<Document> {
|
||||||
// ensuring that the stops in the array match the last
|
const pipeline = getFullTiplocMatchPipeline(array);
|
||||||
// x number of items in the array.
|
const res = await queryAggregate("pis", pipeline);
|
||||||
|
return res[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uses a pipeline to find a partial match - only supporting
|
||||||
|
// codes ending with the correct stops for now.
|
||||||
|
async function findPartialEndMatchByTiploc(array: string[]): Promise<Document> {
|
||||||
|
const pipeline = getPartialEndTiplocMatchPipeline(array);
|
||||||
|
const res = await queryAggregate("pis", pipeline);
|
||||||
|
return res[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertDocument(doc: Document, skipType: string): OB_Pis_SimpleObject {
|
||||||
|
return {
|
||||||
|
code: doc.code.toString(),
|
||||||
|
toc: doc.toc,
|
||||||
|
skipCount: doc.skipStops,
|
||||||
|
skipType: skipType,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changes any instance of 'RDNG4AB' to 'RDNGSTN'
|
||||||
|
function fixErrantTiplocs(input: string[]): void {
|
||||||
|
input.forEach((value, index, array) => {
|
||||||
|
if (value === "RDNG4AB") {
|
||||||
|
array[index] = "RDNGSTN";
|
||||||
|
}
|
||||||
|
// Additional substitutions can be applied here
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
195
src/services/trainService.services.ts
Normal file
195
src/services/trainService.services.ts
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
import { logger } from "../utils/logger.utils";
|
||||||
|
import { findByTiplocArray, supported } from "./pis.services";
|
||||||
|
import { queryAggregate } from "./dbAccess.services";
|
||||||
|
import {
|
||||||
|
getFindByHeadcodePipeline,
|
||||||
|
getFindByTrainUidPipeline,
|
||||||
|
} from "../utils/trainService.utils";
|
||||||
|
import { removeNonAlphanumeric } from "../utils/sanitizer.utils";
|
||||||
|
import { formatTimetableDetail } from "../utils/processors/timetable/timetableProcessor.utils";
|
||||||
|
|
||||||
|
import type {
|
||||||
|
TrainServices,
|
||||||
|
Service,
|
||||||
|
Stop,
|
||||||
|
SimpleService,
|
||||||
|
OB_Pis_SimpleObject,
|
||||||
|
} from "@owlboard/ts-types";
|
||||||
|
|
||||||
|
export async function findByHeadcode(
|
||||||
|
headcode: string,
|
||||||
|
date: Date | string
|
||||||
|
): Promise<SimpleService[]> {
|
||||||
|
const sanitizedHeadcode = removeNonAlphanumeric(headcode);
|
||||||
|
logger.debug(
|
||||||
|
`trainServices.findByHeadcode: Searching for trains by headcode: ${headcode}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// If 'now' then generate a new Date now, else use the provided date, then set time to 1200.
|
||||||
|
const searchDate = date === "now" ? new Date() : new Date(date);
|
||||||
|
searchDate.setHours(12, 0, 0);
|
||||||
|
|
||||||
|
// Get the 'shortDay'
|
||||||
|
const shortDay = getShortDay(searchDate);
|
||||||
|
|
||||||
|
const query = {
|
||||||
|
headcode: sanitizedHeadcode.toUpperCase(),
|
||||||
|
scheduleStartDate: { $lte: searchDate },
|
||||||
|
scheduleEndDate: { $gte: searchDate },
|
||||||
|
daysRun: { $in: [shortDay] },
|
||||||
|
};
|
||||||
|
const pipeline = getFindByHeadcodePipeline(query);
|
||||||
|
|
||||||
|
const result: SimpleService[] = (await queryAggregate(
|
||||||
|
"timetable",
|
||||||
|
pipeline
|
||||||
|
)) as SimpleService[];
|
||||||
|
|
||||||
|
const services = filterServices(result);
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function findByTrainUid(
|
||||||
|
uid: string,
|
||||||
|
date: Date | string = new Date()
|
||||||
|
) {
|
||||||
|
// Set the correct date - whether a date or "now" was passed to function
|
||||||
|
let queryDate: Date;
|
||||||
|
if (date instanceof Date) {
|
||||||
|
queryDate = date;
|
||||||
|
} else {
|
||||||
|
queryDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build query
|
||||||
|
const query = {
|
||||||
|
trainUid: uid.toUpperCase(),
|
||||||
|
scheduleStartDate: { $lte: queryDate },
|
||||||
|
scheduleEndDate: { $gte: queryDate },
|
||||||
|
daysRun: { $in: [getShortDay(queryDate)] },
|
||||||
|
};
|
||||||
|
const pipeline = getFindByTrainUidPipeline(query);
|
||||||
|
|
||||||
|
const result = (await queryAggregate("timetable", pipeline)) as Service[];
|
||||||
|
|
||||||
|
let services = filterServices(result) as Service[];
|
||||||
|
|
||||||
|
// Check if the operator is on the supported TOC list for PIS Codes - if so, call the fetchPisCode function.
|
||||||
|
let pis: OB_Pis_SimpleObject | null;
|
||||||
|
if (supported.includes(services[0]?.operator)) {
|
||||||
|
pis = await fetchPisCode(services[0]?.stops);
|
||||||
|
} else {
|
||||||
|
pis = null;
|
||||||
|
}
|
||||||
|
// TODO: Format and return data, the function called is not yet complete
|
||||||
|
return formatTimetableDetail(services[0], pis);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal Functions:
|
||||||
|
|
||||||
|
// Filters out non-passenger stops and then uses the stop array to request a PIS code for the service
|
||||||
|
async function fetchPisCode(
|
||||||
|
stops: Stop[]
|
||||||
|
): Promise<OB_Pis_SimpleObject | null> {
|
||||||
|
let tiplocList: string[] = [];
|
||||||
|
for (const stop in stops) {
|
||||||
|
if (stops[stop]["isPublic"]) tiplocList.push(stops[stop]["tiploc"]);
|
||||||
|
}
|
||||||
|
// Check if no public stops - then it should use an ECS headcode
|
||||||
|
let pisData: OB_Pis_SimpleObject | null;
|
||||||
|
if (tiplocList.length) {
|
||||||
|
pisData = await findByTiplocArray(tiplocList);
|
||||||
|
} else {
|
||||||
|
pisData = {
|
||||||
|
toc: "GW",
|
||||||
|
skipCount: 0,
|
||||||
|
code: randomEcsPis(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!pisData) {
|
||||||
|
logger.debug(tiplocList, "No PIS found for service")
|
||||||
|
}
|
||||||
|
return pisData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Picks a random choice of the ECS PIS Codes
|
||||||
|
function randomEcsPis(): string {
|
||||||
|
const options = ["0015", "9997"];
|
||||||
|
const randomValue = Math.floor(Math.random() * 2);
|
||||||
|
return options[randomValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outputs the standard 'shortday' string from a Date.
|
||||||
|
function getShortDay(day: Date): string {
|
||||||
|
const dayMap = ["su", "m", "t", "w", "th", "f", "s"];
|
||||||
|
const shortDay = dayMap[day.getDay()];
|
||||||
|
return shortDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters services using their STP indicator so that over-riding entries are returned correctly
|
||||||
|
function filterServices(services: SimpleService[]): SimpleService[] {
|
||||||
|
let stpIndicators: Record<
|
||||||
|
string,
|
||||||
|
{ hasC: boolean; hasN: boolean; hasO: boolean; hasP: boolean }
|
||||||
|
> = {};
|
||||||
|
let filteredServices: SimpleService[] = [];
|
||||||
|
|
||||||
|
for (const service of services) {
|
||||||
|
const trainUid = service["trainUid"],
|
||||||
|
stpIndicator = service["stpIndicator"];
|
||||||
|
|
||||||
|
// Creates the stpIndicators array:
|
||||||
|
if (!stpIndicators[trainUid]) {
|
||||||
|
stpIndicators[trainUid] = {
|
||||||
|
hasC: false,
|
||||||
|
hasN: false,
|
||||||
|
hasO: false,
|
||||||
|
hasP: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stpIndicator === "C") {
|
||||||
|
stpIndicators[trainUid].hasC = true;
|
||||||
|
}
|
||||||
|
if (stpIndicator === "N") {
|
||||||
|
stpIndicators[trainUid].hasN = true;
|
||||||
|
}
|
||||||
|
if (stpIndicator === "O") {
|
||||||
|
stpIndicators[trainUid].hasO = true;
|
||||||
|
}
|
||||||
|
if (stpIndicator === "P") {
|
||||||
|
stpIndicators[trainUid].hasP = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate each service, and only output one service matching each trainUid,
|
||||||
|
// C > N > O > P is the order, with C being prioritised over other STP types.
|
||||||
|
for (const service of services) {
|
||||||
|
const trainUid = service["trainUid"];
|
||||||
|
const thisStpIndicators = stpIndicators[trainUid];
|
||||||
|
const stpIndicator = service["stpIndicator"];
|
||||||
|
|
||||||
|
if (stpIndicator === "C") {
|
||||||
|
filteredServices.push(service);
|
||||||
|
} else if (stpIndicator === "N" && !thisStpIndicators.hasC) {
|
||||||
|
filteredServices.push(service);
|
||||||
|
} else if (
|
||||||
|
stpIndicator === "O" &&
|
||||||
|
!thisStpIndicators.hasC &&
|
||||||
|
!thisStpIndicators.hasN
|
||||||
|
) {
|
||||||
|
filteredServices.push(service);
|
||||||
|
} else if (
|
||||||
|
stpIndicator === "P" &&
|
||||||
|
!thisStpIndicators.hasC &&
|
||||||
|
!thisStpIndicators.hasN &&
|
||||||
|
!thisStpIndicators.hasO
|
||||||
|
) {
|
||||||
|
filteredServices.push(service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filteredServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local Types:
|
12
src/types/index.d.ts
vendored
Normal file
12
src/types/index.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// src/types/express/index.d.ts
|
||||||
|
|
||||||
|
// to make the file a module and avoid the TypeScript error
|
||||||
|
export {};
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace Express {
|
||||||
|
export interface Request {
|
||||||
|
isAuthed: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
102
src/utils/pis.utils.ts
Normal file
102
src/utils/pis.utils.ts
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
export function getPartialEndTiplocMatchPipeline(query: string[]) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
tiplocs: {
|
||||||
|
$all: query,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$addFields: {
|
||||||
|
reversedTiplocs: {
|
||||||
|
$reverseArray: "$tiplocs",
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
$literal: query,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$addFields: {
|
||||||
|
reversedQuery: {
|
||||||
|
$reverseArray: "$query",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
$expr: {
|
||||||
|
$eq: [
|
||||||
|
{
|
||||||
|
$slice: [
|
||||||
|
"$reversedTiplocs",
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
$size: "$reversedQuery",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"$reversedQuery",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$addFields: {
|
||||||
|
skipStops: {
|
||||||
|
$subtract: [
|
||||||
|
{
|
||||||
|
$size: "$tiplocs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$size: "$reversedQuery",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$sort: {
|
||||||
|
skipStops: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$limit: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
code: 1,
|
||||||
|
skipStops: 1,
|
||||||
|
toc: 1,
|
||||||
|
_id: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFullTiplocMatchPipeline(query: string[]) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
$match: {
|
||||||
|
tiplocs: query,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$limit: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$addFields: {
|
||||||
|
skipStops: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
code: 1,
|
||||||
|
toc: 1,
|
||||||
|
skipStops: 1,
|
||||||
|
_id: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
@ -111,7 +111,10 @@ function transformTrainServices(input: any): TrainServices[] {
|
|||||||
|
|
||||||
function checkIsSupressed(service: TrainServices): string | undefined {
|
function checkIsSupressed(service: TrainServices): string | undefined {
|
||||||
logger.trace("utils/translators/ldb/staffStation.checkIsSupressed: Running");
|
logger.trace("utils/translators/ldb/staffStation.checkIsSupressed: Running");
|
||||||
if (service.serviceIsSupressed === "true" || service.isPassengerService === "false") {
|
if (
|
||||||
|
service.serviceIsSupressed === "true" ||
|
||||||
|
service.isPassengerService === "false"
|
||||||
|
) {
|
||||||
return "true";
|
return "true";
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
76
src/utils/processors/timetable/timetableProcessor.utils.ts
Normal file
76
src/utils/processors/timetable/timetableProcessor.utils.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import type {
|
||||||
|
Service,
|
||||||
|
OB_TrainTT_service,
|
||||||
|
OB_Pis_SimpleObject,
|
||||||
|
OB_TrainTT_stopDetail,
|
||||||
|
Stop,
|
||||||
|
} from "@owlboard/ts-types";
|
||||||
|
import { logger } from "../../logger.utils";
|
||||||
|
|
||||||
|
export function formatTimetableDetail(
|
||||||
|
service: Service,
|
||||||
|
pis: OB_Pis_SimpleObject | null
|
||||||
|
): OB_TrainTT_service {
|
||||||
|
const formattedService: OB_TrainTT_service = {
|
||||||
|
stpIndicator: service.stpIndicator,
|
||||||
|
operator: service.operator,
|
||||||
|
trainUid: service.trainUid,
|
||||||
|
headcode: service.headcode,
|
||||||
|
powerType: service.powerType,
|
||||||
|
planSpeed: convertStringToNumber(service.planSpeed),
|
||||||
|
scheduleStart: service.scheduleStartDate,
|
||||||
|
scheduleEnd: service.scheduleEndDate,
|
||||||
|
daysRun: service.daysRun,
|
||||||
|
stops: formatStops(service.stops),
|
||||||
|
vstp: service.vstp,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pis) {
|
||||||
|
formattedService.pis = pis;
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedService;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatStops(stops: Stop[]): OB_TrainTT_stopDetail[] {
|
||||||
|
// Cleanly coerce Stop[] to OB_TrainTT_stopDetail[]
|
||||||
|
const formattedStops: OB_TrainTT_stopDetail[] = [];
|
||||||
|
|
||||||
|
for (const stop of stops) {
|
||||||
|
formattedStops.push(formatStopTimes(stop));
|
||||||
|
}
|
||||||
|
|
||||||
|
return formattedStops;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatStopTimes(stop: Stop): OB_TrainTT_stopDetail {
|
||||||
|
// Cleanly converts a single stop to a stopdetail object
|
||||||
|
let formattedStop: OB_TrainTT_stopDetail = {
|
||||||
|
tiploc: stop.tiploc,
|
||||||
|
isPublic: false,
|
||||||
|
};
|
||||||
|
if (stop.publicArrival) {
|
||||||
|
formattedStop.publicArrival = stop.publicArrival;
|
||||||
|
formattedStop.isPublic = true;
|
||||||
|
}
|
||||||
|
if (stop.publicDeparture) {
|
||||||
|
formattedStop.publicDeparture = stop.publicDeparture;
|
||||||
|
formattedStop.isPublic = true;
|
||||||
|
}
|
||||||
|
if (stop.wttArrival) {
|
||||||
|
formattedStop.wttArrival = stop.wttArrival;
|
||||||
|
}
|
||||||
|
if (stop.wttDeparture) {
|
||||||
|
formattedStop.wttDeparture = stop.wttDeparture;
|
||||||
|
}
|
||||||
|
return formattedStop;
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertStringToNumber(str: string): number {
|
||||||
|
const number = parseFloat(str);
|
||||||
|
if (isNaN(number)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
}
|
29
src/utils/trainService.utils.ts
Normal file
29
src/utils/trainService.utils.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export function getFindByHeadcodePipeline(query: any) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
$match: query,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$project: {
|
||||||
|
operator: 1,
|
||||||
|
stops: {
|
||||||
|
$concatArrays: [
|
||||||
|
[{ $first: "$stops" }],
|
||||||
|
[{ $arrayElemAt: ["$stops", -1] }],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
trainUid: 1,
|
||||||
|
stpIndicator: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFindByTrainUidPipeline(query: any) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
$match: query,
|
||||||
|
},
|
||||||
|
{ $project: { _id: 0 } },
|
||||||
|
];
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
transform,
|
transform,
|
||||||
calculateLength,
|
calculateLength,
|
||||||
} from "../../../../src/utils/translators/ldb/staffStation";
|
} from "../../../../src/utils/processors/ldb/staffStation";
|
||||||
|
|
||||||
import { inputs } from "./stationInputs";
|
import { inputs } from "./stationInputs";
|
||||||
import { outputs } from "./stationOutputs";
|
import { outputs } from "./stationOutputs";
|
||||||
|
Loading…
Reference in New Issue
Block a user