Compare commits
No commits in common. "196cc8783b577a4ed80b7e56a9d669f9d88df0c9" and "d20d981190dbb6d2bf71bfd4861f0fe8bea626a6" have entirely different histories.
196cc8783b
...
d20d981190
@ -1,25 +0,0 @@
|
|||||||
name: Run Jest tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run-tests:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
container:
|
|
||||||
image: ghcr.io/catthehacker/ubuntu:act-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup up Node
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 20
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Run Tests
|
|
||||||
run: npm test
|
|
@ -1,6 +0,0 @@
|
|||||||
export default {
|
|
||||||
transform: {
|
|
||||||
"^.+\\.tsx?$": ["ts-jest", { useESM: true }]
|
|
||||||
},
|
|
||||||
extensionsToTreatAsEsm: [".ts"],
|
|
||||||
};
|
|
3833
package-lock.json
generated
3833
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,9 +3,8 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "TypeScript client for the OwlBoard API",
|
"description": "TypeScript client for the OwlBoard API",
|
||||||
"main": "index.ts",
|
"main": "index.ts",
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -14,12 +13,6 @@
|
|||||||
"author": "Frederick Boniface",
|
"author": "Frederick Boniface",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.14",
|
|
||||||
"jest": "^29.7.0",
|
|
||||||
"ts-jest": "^29.2.6",
|
|
||||||
"typescript": "^5.6.3"
|
"typescript": "^5.6.3"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"uuid": "^11.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
src/clients/LocationReferenceClientV2.ts
Normal file
9
src/clients/LocationReferenceClientV2.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { BaseOwlBoardClient } from "./client";
|
||||||
|
|
||||||
|
export class LocationReferenceClientV2 {
|
||||||
|
private client: BaseOwlBoardClient;
|
||||||
|
|
||||||
|
constructor(client: BaseOwlBoardClient) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +0,0 @@
|
|||||||
import { validateReasonCode } from "../inputValidation/inputValidation";
|
|
||||||
import { ReferenceV2_LocationReferenceCodes, ReferenceV2_LocationReferenceCodeType, ReferenceV2_ReasonCode } from "../types/reference/ReferenceTypesV2";
|
|
||||||
import { BaseOwlBoardClient } from "./client";
|
|
||||||
|
|
||||||
export class ReferenceClientV2 {
|
|
||||||
private client: BaseOwlBoardClient;
|
|
||||||
|
|
||||||
constructor(client: BaseOwlBoardClient) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
async defineReasonCode(reasonCode: number): Promise<ReferenceV2_ReasonCode> {
|
|
||||||
validateReasonCode(reasonCode);
|
|
||||||
const path = `/api/v2/ref/reasonCode/${reasonCode}`
|
|
||||||
return this.client.makeRequest("GET", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
async lookupLocationReference(type: ReferenceV2_LocationReferenceCodeType, referenceCode: string): Promise<ReferenceV2_LocationReferenceCodes> {
|
|
||||||
// Validation Required Here
|
|
||||||
const path = `/api/v2/ref/locationCode/${type}/${referenceCode}`
|
|
||||||
return this.client.makeRequest("GET", path);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,3 @@
|
|||||||
import { validateUuid } from "../inputValidation/inputValidation";
|
|
||||||
import { UserV2_RegistrationResponse } from "../types/user/UserTypesV2";
|
|
||||||
import { BaseOwlBoardClient } from "./client";
|
import { BaseOwlBoardClient } from "./client";
|
||||||
|
|
||||||
export class UserClientV2 {
|
export class UserClientV2 {
|
||||||
@ -8,15 +6,4 @@ export class UserClientV2 {
|
|||||||
constructor(client: BaseOwlBoardClient) {
|
constructor(client: BaseOwlBoardClient) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUser(uuid: string): Promise<UserV2_RegistrationResponse> {
|
|
||||||
validateUuid(uuid);
|
|
||||||
const path = `/api/v2/user/${uuid}`;
|
|
||||||
return this.client.makeRequest("GET", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkAuth(): Promise<any> {
|
|
||||||
const path = '/api/v2/checkAuth'
|
|
||||||
return this.client.makeRequest("GET", path);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import { version } from "../constants";
|
import { version } from "../constants";
|
||||||
import { LdbClientV2 } from "./LdbClientV2";
|
import { LdbClientV2 } from "./LdbClientV2";
|
||||||
import { ReferenceClientV2 } from "./ReferenceClientV2";
|
import { LocationReferenceClientV2 } from "./LocationReferenceClientV2";
|
||||||
import { MiscClientV2 } from "./MiscClientV2";
|
import { MiscClientV2 } from "./MiscClientV2";
|
||||||
import { PisClientV2 } from "./PisClientV2";
|
import { PisClientV2 } from "./PisClientV2";
|
||||||
import { TrainClientV2 } from "./TrainClientV2";
|
import { TrainClientV2 } from "./TrainClientV2";
|
||||||
@ -80,7 +80,7 @@ export class OwlBoardClientV2 extends BaseOwlBoardClient {
|
|||||||
pis: PisClientV2;
|
pis: PisClientV2;
|
||||||
train: TrainClientV2;
|
train: TrainClientV2;
|
||||||
user: UserClientV2;
|
user: UserClientV2;
|
||||||
reference: ReferenceClientV2;
|
locationReference: LocationReferenceClientV2;
|
||||||
misc: MiscClientV2;
|
misc: MiscClientV2;
|
||||||
ldb: LdbClientV2;
|
ldb: LdbClientV2;
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ export class OwlBoardClientV2 extends BaseOwlBoardClient {
|
|||||||
this.pis = new PisClientV2(this);
|
this.pis = new PisClientV2(this);
|
||||||
this.train = new TrainClientV2(this);
|
this.train = new TrainClientV2(this);
|
||||||
this.user = new UserClientV2(this);
|
this.user = new UserClientV2(this);
|
||||||
this.reference = new ReferenceClientV2(this);
|
this.locationReference = new LocationReferenceClientV2(this);
|
||||||
this.misc = new MiscClientV2(this);
|
this.misc = new MiscClientV2(this);
|
||||||
this.ldb = new LdbClientV2(this);
|
this.ldb = new LdbClientV2(this);
|
||||||
}
|
}
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
|
|
||||||
import { validateCrs,
|
|
||||||
validatePisCode,
|
|
||||||
validateReasonCode,
|
|
||||||
validateTiploc,
|
|
||||||
validateUuid } from "./inputValidation";
|
|
||||||
import { ValidationError } from "../errors";
|
|
||||||
|
|
||||||
describe("PIS Validation Tests", () => {
|
|
||||||
test("PIS inputs of the correct format should return true", () => {
|
|
||||||
expect(validatePisCode(1234)).toBe(true);
|
|
||||||
expect(validatePisCode("0999")).toBe(true);
|
|
||||||
expect(validatePisCode(9343)).toBe(true);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("PIS inputs of an invalid format should throw a ValidationError", () => {
|
|
||||||
expect(() => validatePisCode(21)).toThrow(ValidationError);
|
|
||||||
expect(() => validatePisCode("hoo")).toThrow(ValidationError);
|
|
||||||
expect(() => validatePisCode({test: "Value"})).toThrow(ValidationError);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("TIPLOC Validation Tests", () => {
|
|
||||||
test("TIPLOC inputs of the correct format should return true", () => {
|
|
||||||
expect(validateTiploc("elyy")).toBe(true);
|
|
||||||
expect(validateTiploc("STROUD")).toBe(true);
|
|
||||||
expect(validateTiploc("GLOSTER")).toBe(true);
|
|
||||||
expect(validateTiploc("PaDtOn")).toBe(true);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("TIPLOC inputs of an invalid format should throw a ValidationError", () => {
|
|
||||||
expect(() => validateTiploc("wey")).toThrow(ValidationError);
|
|
||||||
expect(() => validateTiploc("PMS")).toThrow(ValidationError);
|
|
||||||
expect(() => validateTiploc(89)).toThrow(ValidationError);
|
|
||||||
expect(() => validateTiploc(["STROUD", "GLOSTER"])).toThrow(ValidationError);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("CRS Validation Tests", () => {
|
|
||||||
test("CRS inputs of the correct format should return true", () => {
|
|
||||||
expect(validateCrs("bth")).toBe(true);
|
|
||||||
expect(validateCrs("BTH")).toBe(true);
|
|
||||||
expect(validateCrs("PoA")).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("CRS inputs of an invalid format should throw a ValidationError", () => {
|
|
||||||
expect(() => validateCrs("BATHSPA")).toThrow(ValidationError);
|
|
||||||
expect(() => validateCrs("popo")).toThrow(ValidationError);
|
|
||||||
expect(() => validateCrs("BT")).toThrow(ValidationError);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("CRS inputs that are not strings should throw ValidationError", () => {
|
|
||||||
expect(() => validateCrs(34)).toThrow(ValidationError);
|
|
||||||
expect(() => validateCrs([])).toThrow(ValidationError);
|
|
||||||
expect(() => validateCrs({})).toThrow(ValidationError);
|
|
||||||
expect(() => validateCrs(null)).toThrow(ValidationError);
|
|
||||||
expect(() => validateCrs(undefined)).toThrow(ValidationError);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("UUID Validation Tests", () => {
|
|
||||||
test("UUID inputs that are valid v4-UUIDs should return true", () => {
|
|
||||||
expect(validateUuid("5c5db50b-91c8-440c-80af-afc7bb375b4b")).toBe(true);
|
|
||||||
expect(validateUuid("9a9a3849-bbcb-452c-a0db-599a53cb27f3")).toBe(true);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("UUID inputs that are valid v1-UUIDs should return true", () => {
|
|
||||||
expect(validateUuid("e7dd36f0-ff86-11ef-9cd2-0242ac120002")).toBe(true);
|
|
||||||
expect(validateUuid("e052e8b6-ff87-11ef-9cd2-0242ac120002")).toBe(true);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("UUID inputs that are valid v7-UUIDs should return true", () => {
|
|
||||||
expect(validateUuid("01958c36-8b96-7ff1-be2c-d1488273f5e0")).toBe(true);
|
|
||||||
expect(validateUuid("01958c3a-f9d0-7c6a-b510-6de0dd36a49a")).toBe(true);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("UUID inputs that are a nil UUID should return true", () => {
|
|
||||||
expect(validateUuid("00000000-0000-0000-0000-000000000000")).toBe(true);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("UUID inputs that are actually not UUIDs should throw ValidationError", () => {
|
|
||||||
expect(() => validateUuid("thisisjustastring")).toThrow(ValidationError);
|
|
||||||
expect(() => validateUuid(789)).toThrow(ValidationError);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("Reason Code Validation Tests", () => {
|
|
||||||
test("Reason codes that are valid numbers or strings should return true", () => {
|
|
||||||
expect(validateReasonCode("999")).toBe(true);
|
|
||||||
expect(validateReasonCode("100")).toBe(true);
|
|
||||||
expect(validateReasonCode(402)).toBe(true);
|
|
||||||
expect(validateReasonCode(100)).toBe(true);
|
|
||||||
expect(validateReasonCode(999)).toBe(true);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("Reason codes that are out of range numbers should throw ValidationError", () => {
|
|
||||||
expect(() => validateReasonCode(99)).toThrow(ValidationError);
|
|
||||||
expect(() => validateReasonCode("1000")).toThrow(ValidationError);
|
|
||||||
expect(() => validateReasonCode(1000)).toThrow(ValidationError);
|
|
||||||
expect(() => validateReasonCode("99")).toThrow(ValidationError);
|
|
||||||
})
|
|
||||||
|
|
||||||
test("Reason code inputs that are non numeric values should throw ValidationError", () => {
|
|
||||||
expect(() => validateReasonCode("19f")).toThrow(ValidationError);
|
|
||||||
expect(() => validateReasonCode(null)).toThrow(ValidationError);
|
|
||||||
expect(() => validateReasonCode(true)).toThrow(ValidationError);
|
|
||||||
expect(() => validateReasonCode([])).toThrow(ValidationError);
|
|
||||||
expect(() => validateReasonCode({})).toThrow(ValidationError);
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,13 +1,6 @@
|
|||||||
import { ValidationError } from "../errors";
|
import { ValidationError } from "../errors";
|
||||||
import { validate as uuidlibValidate, version as uuidlibVersion } from 'uuid'
|
|
||||||
|
|
||||||
export function validatePisCode(code: unknown): boolean {
|
export function validatePisCode(code: string): boolean {
|
||||||
if (typeof code == "number") {
|
|
||||||
code = code.toString();
|
|
||||||
}
|
|
||||||
if (typeof code !== "string") {
|
|
||||||
throw new ValidationError("Invalid input: code must be a four digit number or string")
|
|
||||||
}
|
|
||||||
const codeRegex = /^\d{4}$/;
|
const codeRegex = /^\d{4}$/;
|
||||||
if (!codeRegex.test(code)) {
|
if (!codeRegex.test(code)) {
|
||||||
throw new ValidationError("Invalid input: code must be a four-character string consisting of only numerals");
|
throw new ValidationError("Invalid input: code must be a four-character string consisting of only numerals");
|
||||||
@ -15,56 +8,18 @@ export function validatePisCode(code: unknown): boolean {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateTiploc(tiploc: unknown): boolean {
|
export function validateTiploc(tiploc: string): boolean {
|
||||||
if (typeof tiploc !== "string") {
|
const tiplocRegex = /[a-zA-z0-9]{4,7}/;
|
||||||
throw new ValidationError("Invalid input: TIPLOC must be a string");
|
|
||||||
}
|
|
||||||
const tiplocRegex = /[a-zA-Z0-9]{4,7}/;
|
|
||||||
if (!tiplocRegex.test(tiploc)) {
|
if (!tiplocRegex.test(tiploc)) {
|
||||||
throw new ValidationError("Invalid input: TIPLOC must be between four and seven characters");
|
throw new ValidationError("Invalid input: TIPLOC must be between four and seven characters");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateCrs(crs: unknown): boolean {
|
export function validateCrs(crs: string): boolean {
|
||||||
if (typeof crs !== "string") {
|
const crsRegex = /[a-zA-z]{3}/;
|
||||||
throw new ValidationError("Invalid input: CRS/3ALPHA must be a string")
|
|
||||||
}
|
|
||||||
|
|
||||||
const crsRegex = /^[a-zA-Z]{3}$/;
|
|
||||||
if (!crsRegex.test(crs)) {
|
if (!crsRegex.test(crs)) {
|
||||||
throw new ValidationError("Invalid input: CRS/3ALPHA must be exactly three letters")
|
throw new ValidationError("Invalid input: CRS/3ALPHA must be exactly three letters")
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
export function validateUuid(uuid: unknown): boolean {
|
|
||||||
if (typeof uuid !== "string") {
|
|
||||||
throw new ValidationError("Invalid input: The UUID/api_key should be a string");
|
|
||||||
}
|
|
||||||
if (!uuidlibValidate(uuid)) {
|
|
||||||
throw new ValidationError("Invalid input: The UUID/api_key is the expexted value")
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function validateReasonCode(code: unknown): boolean {
|
|
||||||
if (typeof code === "number") {
|
|
||||||
// Ensure it's a 3-digit number (100-999)
|
|
||||||
if (!Number.isInteger(code) || code < 100 || code > 999) {
|
|
||||||
throw new ValidationError("Invalid input: Reason code must be a three-digit number (100-999).");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof code === "string") {
|
|
||||||
// Ensure it consists of exactly 3 numeric characters
|
|
||||||
if (!/^\d{3}$/.test(code)) {
|
|
||||||
throw new ValidationError("Invalid input: Reason code must be a string of three digits.");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's neither a number nor a string, throw an error
|
|
||||||
throw new ValidationError("Invalid input: Reason code must be a number or a string of three digits.");
|
|
||||||
}
|
}
|
@ -1,22 +0,0 @@
|
|||||||
// Location Reference codes are returned as an array containing one object
|
|
||||||
interface ReferenceV2_LocationReferenceCodesObject {
|
|
||||||
"3ALPHA": string;
|
|
||||||
NLC: number;
|
|
||||||
NLCDESC: string;
|
|
||||||
STANOX: string;
|
|
||||||
TIPLOC: string;
|
|
||||||
UIC: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ReferenceV2_LocationReferenceCodes = ReferenceV2_LocationReferenceCodesObject[];
|
|
||||||
|
|
||||||
// Reason codes are returned as an array containing one object
|
|
||||||
interface ReferenceV2_ReasonCodeObject {
|
|
||||||
code: string;
|
|
||||||
lateReason: string;
|
|
||||||
cancReason: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ReferenceV2_ReasonCode = ReferenceV2_ReasonCodeObject[]
|
|
||||||
|
|
||||||
export type ReferenceV2_LocationReferenceCodeType = "tiploc" | "crs" | "stanox" | "nlc"
|
|
@ -1,5 +0,0 @@
|
|||||||
export interface UserV2_RegistrationResponse {
|
|
||||||
status: number;
|
|
||||||
message: string;
|
|
||||||
api_key: string;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user