diff --git a/.env.example b/.env.example index c1afc97..f7fc1de 100644 --- a/.env.example +++ b/.env.example @@ -4,4 +4,5 @@ POSTGRES_USER="postgres" POSTGRES_PASSWORD="postgres" REDIS_USER="default" REDIS_PASSWORD="" -REDIS_URL="redis://awesome.redis.server:6379" \ No newline at end of file +REDIS_URL="redis://awesome.redis.server:6379" +SERVERAUTH_TEST="1:f9f8fc8c-9185-47a8-8a99-9e3acf6ca007" \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 2da8654..49c5608 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,6 +21,15 @@ "program": "${workspaceFolder}/src/clientMain.ts", "preLaunchTask": "tsc: build - tsconfig.json", "outFiles": ["${workspaceFolder}/out/**/*.js"] + }, + { + "type": "node", + "request": "launch", + "name": "Launch Process API", + "skipFiles": ["/**"], + "program": "${workspaceFolder}/src/processMain.ts", + "preLaunchTask": "tsc: build - tsconfig.json", + "outFiles": ["${workspaceFolder}/out/**/*.js"] } ] } diff --git a/babel.config.js b/babel.config.js index f5c1c3c..7b976f5 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,6 @@ module.exports = { - presets: [['@babel/preset-env', { targets: { node: 'current' } }]] + presets: [ + ['@babel/preset-env', { targets: { node: 'current' } }], + '@babel/preset-typescript' + ] } diff --git a/package-lock.json b/package-lock.json index a83eeee..2121555 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "devDependencies": { "@babel/core": "^7.21.0", "@babel/preset-env": "^7.20.2", + "@babel/preset-typescript": "^7.21.4", "@jest/globals": "^29.4.3", "@types/cors": "^2.8.13", "@types/express": "^4.17.17", @@ -1071,12 +1072,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", + "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1687,6 +1688,24 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz", + "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-typescript": "^7.20.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.18.10", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", @@ -1832,6 +1851,25 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-typescript": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.4.tgz", + "integrity": "sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.21.0", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/plugin-transform-modules-commonjs": "^7.21.2", + "@babel/plugin-transform-typescript": "^7.21.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/regjsgen": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", diff --git a/package.json b/package.json index 8295458..317f3b6 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "devDependencies": { "@babel/core": "^7.21.0", "@babel/preset-env": "^7.20.2", + "@babel/preset-typescript": "^7.21.4", "@jest/globals": "^29.4.3", "@types/cors": "^2.8.13", "@types/express": "^4.17.17", diff --git a/src/clientMain.ts b/src/clientMain.ts index 8f5dc56..580d2a1 100644 --- a/src/clientMain.ts +++ b/src/clientMain.ts @@ -18,10 +18,14 @@ app.get('/', (req, res) => { app.use('/', client) -dbReady().then((e) => { - cacheReady().then((e) => { - app.listen(port, '0.0.0.0', () => { - console.log(`Tone client api listening on port ${port}`) +export default + new Promise((resolve, reject) => { + dbReady().then((e) => { + cacheReady().then((e) => { + const listenServer = app.listen(port, '0.0.0.0', () => { + console.log(`Tone client api listening on port ${port}`) + resolve(listenServer) + }) + }) }) }) -}) diff --git a/src/db/db.ts b/src/db/db.ts index 667f06c..c669b8f 100644 --- a/src/db/db.ts +++ b/src/db/db.ts @@ -1,8 +1,9 @@ +import * as dotenv from 'dotenv' +dotenv.config() import { InsertObject, Kysely, PostgresDialect } from 'kysely' import { Pool } from 'pg' import migrateToLatest from './migrations' import Database, { KillTable } from './model' - const migration = migrateToLatest() const db = new Kysely({ dialect: new PostgresDialect({ diff --git a/src/db/migrations.ts b/src/db/migrations.ts index a0f5555..412b6c6 100644 --- a/src/db/migrations.ts +++ b/src/db/migrations.ts @@ -9,7 +9,6 @@ import * as path from "path"; import { Pool } from "pg"; import Database from "./model"; -console.log(process.env.POSTGRES_HOST); async function migrateToLatest() { const db = new Kysely({ dialect: new PostgresDialect({ diff --git a/src/processMain.ts b/src/processMain.ts index bad0906..76ae4d7 100644 --- a/src/processMain.ts +++ b/src/processMain.ts @@ -4,8 +4,9 @@ import { dbReady } from './db/db' import { cacheReady } from './cache/redis' import processAll from './client/process' -dbReady().then((e) => { - cacheReady().then((e) => { - processAll() - }) -}) +async function startup() { + await dbReady() + await cacheReady() + await processAll() +} +export default startup() \ No newline at end of file diff --git a/src/serverMain.ts b/src/serverMain.ts index 0e649a4..9d861c2 100644 --- a/src/serverMain.ts +++ b/src/serverMain.ts @@ -2,7 +2,7 @@ import * as dotenv from 'dotenv' dotenv.config() import express from 'express' import cors from 'cors' -import { dbReady } from './db/db' +import db, { dbReady } from './db/db' import server from './server/server' const app = express() @@ -17,8 +17,15 @@ app.get('/', (req, res) => { app.use('/', server) -dbReady().then((e) => { - app.listen(port, '0.0.0.0', () => { - console.log(`Tone server api listening on port ${port}`) +export default new Promise((resolve, reject) => { + dbReady().then((e) => { + const listenServer = app.listen(port, '0.0.0.0', () => { + console.log(`Tone server api listening on port ${port}`) + resolve(listenServer) + }) }) }) + +app.on('close', () => { + +}) diff --git a/tests/client.test.ts.disabled b/tests/client.test.ts.disabled new file mode 100644 index 0000000..fbc0cb0 --- /dev/null +++ b/tests/client.test.ts.disabled @@ -0,0 +1,29 @@ +import { afterAll, beforeAll, describe, expect, test } from '@jest/globals' +import clientMain from '../src/clientMain' +import processMain from '../src/processMain' +import cache from '../src/cache/redis' +import db from "../src/db/db" +import * as dotenv from 'dotenv' +dotenv.config() + +let listenServer + +beforeAll(async () => { + /*await cache.FLUSHDB() + await processMain + await cache.quit() + await db.destroy() + listenServer = await clientMain;*/ +}) + +describe('client', () => { + test('fetchServerList', () => { + expect(200).toBe(200) + }) +}) + +afterAll((done) => { + cache.quit().then(() => { + db.destroy().then(() => { done() }) + }) +}) \ No newline at end of file diff --git a/tests/registration.test.ts b/tests/registration.test.ts deleted file mode 100644 index 02ba755..0000000 --- a/tests/registration.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { describe, expect, test } from '@jest/globals' - -describe('registration', () => { - test('garbage body', () => { - expect(3).toBe(3) - }) - test('incorrect data format', () => { - expect(3).toBe(3) - }) - test('duplicate server', () => { - expect(3).toBe(3) - }) - test('invisible server', () => { - expect(3).toBe(3) - }) - test('wrong verification', () => { - expect(3).toBe(3) - }) - test('masterserver unreachable', () => { - expect(3).toBe(3) - }) - test('registration successful', () => { - expect(3).toBe(3) - }) - test('server deletion', () => { - expect(3).toBe(3) - }) -}) diff --git a/tests/server.test.ts b/tests/server.test.ts new file mode 100644 index 0000000..1575ac8 --- /dev/null +++ b/tests/server.test.ts @@ -0,0 +1,130 @@ +import { afterAll, beforeAll, describe, expect, test } from '@jest/globals' +import serverMain from '../src/serverMain' +import db from "../src/db/db" +import * as dotenv from 'dotenv' +dotenv.config() + +let listenServer + +beforeAll(async () => { + listenServer = await serverMain; + await db.deleteFrom('kill').where('attacker_id', '=', '0').orWhere('attacker_id', '=', '1').execute() +}) + +describe('server', () => { + test('server auth prefetch', async () => { + const response = await fetch(`http://127.0.0.1:3001/${process.env.SERVERAUTH_ID}`, { + method: "POST", // *GET, POST, PUT, DELETE, etc. + credentials: "same-origin", // include, *same-origin, omit + headers: { + "Content-Type": "application/json", + 'Authorization': `Basic ${Buffer.from(process.env.SERVERAUTH_ID + ':' + process.env.SERVERAUTH_TOKEN).toString('base64')}` + } + }); + expect(response.status).toBe(200) + }) + + test('register a kill', async () => { + const data = { + attacker_weapon_1_mods: 0, + victim_id: '0', + victim_name: 'TestVictim', + victim_offhand_weapon_2: 0, + attacker_offhand_weapon_3: '0', + victim_weapon_3_mods: 0, + attacker_weapon_2_mods: 0, + attacker_offhand_weapon_1: 0, + attacker_weapon_3_mods: 0, + attacker_offhand_weapon_2: 0, + victim_offhand_weapon_3: '0', + victim_offhand_weapon_1: 0, + attacker_weapon_3: 'defender', + killstat_version: 'ks_3.0.0', + attacker_weapon_1: 'smr', + match_id: '31b1f34d', + distance: 0, + victim_current_weapon: 'smr', + cause_of_death: 'smr', + victim_weapon_2_mods: 0, + victim_current_weapon_mods: 0, + attacker_current_weapon_mods: 0, + game_time: 377.799, + player_count: 1, + attacker_current_weapon: 'smr', + attacker_id: '1', + game_mode: 'tdm', + map: 'thaw', + attacker_weapon_2: 'autopistol', + victim_weapon_1: 'smr', + victim_weapon_2: 'autopistol', + victim_weapon_1_mods: 0, + victim_weapon_3: 'defender', + attacker_name: 'TestAttacker' + } + const response = await fetch(`http://127.0.0.1:3001/${process.env.SERVERAUTH_ID}/kill`, { + method: "POST", // *GET, POST, PUT, DELETE, etc. + credentials: "same-origin", // include, *same-origin, omit + headers: { + "Content-Type": "application/json", + 'Authorization': `Basic ${Buffer.from(process.env.SERVERAUTH_ID + ':' + process.env.SERVERAUTH_TOKEN).toString('base64')}` + }, + body: JSON.stringify(data), // body data type must match "Content-Type" header + }); + expect(response.status).toBe(201) + }) + + + test('register a kill with missing data', async () => { + const data = { + attacker_weapon_1_mods: NaN, + victim_id: '0', + victim_name: 'TestVictim', + victim_offhand_weapon_2: NaN, + attacker_offhand_weapon_3: 'null', + victim_weapon_3_mods: 19, + attacker_weapon_2_mods: NaN, + attacker_offhand_weapon_1: NaN, + attacker_weapon_3_mods: NaN, + attacker_offhand_weapon_2: NaN, + victim_offhand_weapon_3: '0', + victim_offhand_weapon_1: 1, + attacker_weapon_3: 'null', + killstat_version: 'ks_3.0.0', + attacker_weapon_1: 'null', + match_id: '554fa7a3', + distance: 202, + victim_current_weapon: 'car', + cause_of_death: 'satchel', + victim_weapon_2_mods: NaN, + victim_current_weapon_mods: NaN, + attacker_current_weapon_mods: NaN, + game_time: 516.417, + player_count: 13, + attacker_current_weapon: 'null', + attacker_id: '1', + game_mode: 'ps', + map: 'grave', + attacker_weapon_2: 'null', + victim_weapon_1: 'car', + victim_weapon_2: 'autopistol', + victim_weapon_1_mods: NaN, + victim_weapon_3: 'arc_launcher', + attacker_name: 'TestAttacker' + } + const response = await fetch(`http://127.0.0.1:3001/${process.env.SERVERAUTH_ID}/kill`, { + method: "POST", // *GET, POST, PUT, DELETE, etc. + credentials: "same-origin", // include, *same-origin, omit + headers: { + "Content-Type": "application/json", + 'Authorization': `Basic ${Buffer.from(process.env.SERVERAUTH_ID + ':' + process.env.SERVERAUTH_TOKEN).toString('base64')}` + }, + body: JSON.stringify(data), // body data type must match "Content-Type" header + }); + expect(response.status).toBe(201) + }) +}) + +afterAll((done) => { + listenServer.close() + db.destroy().then(() => { done() }) +}) \ No newline at end of file diff --git a/tests/tess.test.ts b/tests/tess.test.ts deleted file mode 100644 index 8430519..0000000 --- a/tests/tess.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { describe, expect, test } from '@jest/globals' - -describe('server', () => { - test('register a kill', () => { - const data = { - attacker_weapon_1_mods: 0, - victim_id: '1005930844007', - victim_name: 'Legonzaur', - victim_offhand_weapon_2: 0, - attacker_offhand_weapon_3: '0', - victim_weapon_3_mods: 0, - attacker_weapon_2_mods: 0, - attacker_offhand_weapon_1: 0, - attacker_weapon_3_mods: 0, - attacker_offhand_weapon_2: 0, - victim_offhand_weapon_3: '0', - victim_offhand_weapon_1: 0, - attacker_weapon_3: 'defender', - killstat_version: 'ks_3.0.0', - attacker_weapon_1: 'smr', - match_id: '31b1f34d', - distance: 0, - victim_current_weapon: 'smr', - cause_of_death: 'smr', - victim_weapon_2_mods: 0, - victim_current_weapon_mods: 0, - attacker_current_weapon_mods: 0, - game_time: 377.799, - player_count: 1, - attacker_current_weapon: 'smr', - attacker_id: '1005930844007', - game_mode: 'tdm', - map: 'thaw', - attacker_weapon_2: 'autopistol', - victim_weapon_1: 'smr', - victim_weapon_2: 'autopistol', - victim_weapon_1_mods: 0, - victim_weapon_3: 'defender', - attacker_name: 'Legonzaur' - } - - expect(3).toBe(3) - }) -})