restructure project

This commit is contained in:
Merijn Hendriks 2021-12-26 17:20:59 +01:00
parent 20bbfd4239
commit 7cfe244127
100 changed files with 461 additions and 4428 deletions

23
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,23 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run-script",
"launch"
],
"cwd": "${workspaceFolder}",
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"skipFiles": [
"**/node_modules/**"
]
}
]
}

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"window.title": "Natsu Project",
}

8
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,8 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "something"
}
]
}

57
launcher/package.json Normal file
View File

@ -0,0 +1,57 @@
{
"name": "haru-launcher",
"author": "senko-san",
"version": "1.0.0",
"license": "NCSA",
"main": "src/main.js",
"scripts": {
"lint:fix": "npx eslint --fix \"./src/**/*.ts\"",
"lint:check": "npx eslint \"./src/**/*.ts\"",
"build:ts": "npx babel src --extensions \".ts\" --out-dir obj/babel",
"build:bundle": "npx browserify --debug --node obj/babel/main.js > obj/bundle.js",
"launch:node": "node --trace-warnings obj/bundle.js",
"launch": "npm run build:ts && npm run build:bundle && npm run launch:node"
},
"dependencies": {
"source-map-support": "^0.5.0"
},
"devDependencies": {
"@babel/cli": "^7.16.0",
"@babel/core": "^7.16.0",
"@babel/eslint-parser": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.16.0",
"@babel/preset-env": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@types/node": "^14.0.0",
"babel-plugin-source-map-support": "^2.1.0",
"browserify": "^17.0.0",
"core-js": "^3.20.0",
"eslint": "^8.5.0",
"typescript": "^4.5.0"
},
"babel": {
"presets": [
[ "@babel/env", { "targets": { "node": "14.0.0" }, "useBuiltIns": "usage", "corejs": "3.20.0" } ],
"@babel/preset-typescript"
],
"plugins": [
"@babel/plugin-transform-runtime",
"@babel/plugin-transform-typescript",
"source-map-support"
],
"sourceMaps": "inline"
},
"eslintConfig": {
"parser": "@babel/eslint-parser",
"extends": "eslint:recommended",
"rules": {
"brace-style": [ "error", "allman" ],
"indent": [ "error", 4, { "VariableDeclarator": 0, "SwitchCase": 1 } ],
"quotes": [ "error", "double" ],
"semi": [ "error", "always" ],
"no-var": "error",
"no-unused-vars": "off",
"no-undef": "off"
}
}
}

View File

@ -0,0 +1,92 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
export class Json
{
public static deserialize<T>(s: string): T
{
return JSON.parse(s);
}
public static serialize<T>(o: T, indent: boolean = false): string
{
return (indent) ? JSON.stringify(o, null, 2) : JSON.stringify(o);
}
}
export class Vfs
{
public static getExtension(filepath: string): string
{
return filepath.split(".").pop() || "";
}
public static exists(filepath: string): boolean
{
return existsSync(filepath);
}
public static createDirectory(filepath: string): void
{
const path = filepath.substring(0, filepath.lastIndexOf("/"));
mkdirSync(path, { "recursive": true });
}
public static readFile(filepath: string): any
{
return readFileSync(filepath);
}
public static writeFile(filepath: string, data: Buffer | string, append: boolean = false): void
{
if (!Vfs.exists(filepath))
{
Vfs.createDirectory(filepath);
}
return writeFileSync(filepath, data, { "flag": (append) ? "a" : "w" });
}
}
export class Log
{
private static filepath: string;
public static init(filepath: string)
{
Log.filepath = filepath;
// clear existing log
if (Vfs.exists(Log.filepath))
{
Vfs.writeFile(Log.filepath, "");
}
// log exceptions
process.on("uncaughtException", (error, promise) =>
{
Log.error("Trace:");
Log.write(error.toString());
});
}
public static write(text: string): void
{
console.log(text);
Vfs.writeFile(Log.filepath, `${text}\n`, true);
}
public static info(text: string): void
{
Log.write(`[INFO] ${text}`);
}
public static warn(text: string): void
{
Log.write(`[WARN] ${text}`);
}
public static error(text: string): void
{
Log.write(`[ERROR] ${text}`);
}
}

14
launcher/src/Haru.ts Normal file
View File

@ -0,0 +1,14 @@
import { Log } from "./Haru.Utils";
export class Program
{
public static main(args: string[])
{
Log.init("./Logs/Haru.log");
for (const command of args)
{
Log.info(command);
}
}
}

View File

@ -1,3 +1,3 @@
import { Program } from "./Haru";
import { Program } from "./Haru";
Program.main(process.argv);

4157
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"name": "haru",
"name": "haru-server",
"author": "senko-san",
"version": "1.0.0",
"license": "NCSA",
@ -37,16 +37,7 @@
},
"babel": {
"presets": [
[
"@babel/env",
{
"targets": {
"node": "14.0.0"
},
"useBuiltIns": "usage",
"corejs": "3.20.0"
}
],
[ "@babel/env", { "targets": { "node": "14.0.0" }, "useBuiltIns": "usage", "corejs": "3.20.0" } ],
"@babel/preset-typescript"
],
"plugins": [
@ -60,26 +51,10 @@
"parser": "@babel/eslint-parser",
"extends": "eslint:recommended",
"rules": {
"brace-style": [
"error",
"allman"
],
"indent": [
"error",
4,
{
"VariableDeclarator": 0,
"SwitchCase": 1
}
],
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
],
"brace-style": [ "error", "allman" ],
"indent": [ "error", 4, { "VariableDeclarator": 0, "SwitchCase": 1 } ],
"quotes": [ "error", "double" ],
"semi": [ "error", "always" ],
"no-var": "error",
"no-unused-vars": "off",
"no-undef": "off"

View File

@ -1,118 +1,118 @@
export class ResponseBody<T>
{
public err: number;
public errcode: string | null;
public data: T;
public constructor(data: T, err: number = 0, errcode: string | null = null)
{
this.err = err;
this.errcode = errcode;
this.data = data;
}
}
export class LogoutResponse
{
public status: string;
public constructor()
{
this.status = "ok";
}
}
export class KeepAliveResponse
{
public msg: string;
public utc_time: number;
public constructor()
{
this.msg = "OK";
// todo: implement this
// value: unix timestamp
this.utc_time = 0;
}
}
export class ServerInfo
{
public ip: string;
public port: number;
public constructor(ip: string = "127.0.0.1", port: number = 8000)
{
this.ip = ip;
this.port = port;
}
}
export class PingNotification
{
public type: string;
public eventId: string;
public constructor()
{
this.type = "ping";
this.eventId = "ping";
}
}
// todo: implement this
export class CheckVersionResponse
{
public isValid: boolean;
public latestVersion: string;
public constructor()
{
this.isValid = true;
this.latestVersion = "";
}
}
export class MiniInfo
{
public Nickname: string;
public Side: string;
public Level: number;
public MemberCategory: number;
public constructor(nickname: string, side: string, level: number, memberCategory: number)
{
this.Nickname = nickname;
this.Side = side;
this.Level = level;
this.MemberCategory = memberCategory;
}
}
export class MiniProfile
{
public _id: string;
public Info: MiniInfo;
public constructor(id: string, info: MiniInfo)
{
this._id = id;
this.Info = info;
}
}
export class FriendList
{
public Friends: MiniProfile[];
public Ignore: string[];
public InIgnoreList: string[];
public constructor()
{
// todo: implement this
this.Friends = [];
this.Ignore = [];
this.InIgnoreList = [];
}
}
export class ResponseBody<T>
{
public err: number;
public errcode: string | null;
public data: T;
public constructor(data: T, err: number = 0, errcode: string | null = null)
{
this.err = err;
this.errcode = errcode;
this.data = data;
}
}
export class LogoutResponse
{
public status: string;
public constructor()
{
this.status = "ok";
}
}
export class KeepAliveResponse
{
public msg: string;
public utc_time: number;
public constructor()
{
this.msg = "OK";
// todo: implement this
// value: unix timestamp
this.utc_time = 0;
}
}
export class ServerInfo
{
public ip: string;
public port: number;
public constructor(ip: string = "127.0.0.1", port: number = 8000)
{
this.ip = ip;
this.port = port;
}
}
export class PingNotification
{
public type: string;
public eventId: string;
public constructor()
{
this.type = "ping";
this.eventId = "ping";
}
}
// todo: implement this
export class CheckVersionResponse
{
public isValid: boolean;
public latestVersion: string;
public constructor()
{
this.isValid = true;
this.latestVersion = "";
}
}
export class MiniInfo
{
public Nickname: string;
public Side: string;
public Level: number;
public MemberCategory: number;
public constructor(nickname: string, side: string, level: number, memberCategory: number)
{
this.Nickname = nickname;
this.Side = side;
this.Level = level;
this.MemberCategory = memberCategory;
}
}
export class MiniProfile
{
public _id: string;
public Info: MiniInfo;
public constructor(id: string, info: MiniInfo)
{
this._id = id;
this.Info = info;
}
}
export class FriendList
{
public Friends: MiniProfile[];
public Ignore: string[];
public InIgnoreList: string[];
public constructor()
{
// todo: implement this
this.Friends = [];
this.Ignore = [];
this.InIgnoreList = [];
}
}

View File

@ -1,111 +1,111 @@
import { PingNotification } from "./Haru.Eft.Models";
import { CachedResponseService, CachedResponseHelper, FileResponseHelper, FileService } from "./Haru.Eft.Services";
import { HttpServer, WsServer, IServer } from "./Haru.Http";
import { Json } from "./Haru.Utils";
export class ServerCluster
{
private readonly servers: IServer[];
public constructor()
{
this.servers = [
new GeneralServer(),
new NotificationServer()
];
}
public start(): void
{
for (const server of this.servers)
{
server.start();
}
}
public stop(): void
{
for (const server of this.servers)
{
server.stop();
}
}
}
export class GeneralServer implements IServer
{
private readonly server: HttpServer;
public constructor()
{
this.server = new HttpServer("localhost", 8000);
// add cached responses
const cachedResponseService = new CachedResponseService();
for (const url in CachedResponseHelper.responses)
{
this.server.addService(url, cachedResponseService);
}
// add file responses
const fileService = new FileService()
for (const url in FileResponseHelper.files)
{
this.server.addService(url, fileService);
}
}
public start(): void
{
this.server.start();
}
public stop(): void
{
this.server.stop();
}
public isListening(): boolean
{
return this.server.isListening();
}
}
export class NotificationServer implements IServer
{
private readonly httpServer: HttpServer;
private readonly wsServer: WsServer;
public constructor()
{
const message = Json.serialize(new PingNotification());
this.httpServer = new HttpServer("localhost", 8001);
this.wsServer = new WsServer(this.httpServer, message);
}
public start(): void
{
this.httpServer.start();
this.wsServer.start();
}
public stop(): void
{
this.httpServer.stop();
this.wsServer.stop();
}
public isListening(): boolean
{
return this.httpServer.isListening() || this.wsServer.isListening();
}
public canSendMessage(sessionId: string): boolean
{
// TODO: use actual url
const url: string = sessionId;
return this.wsServer.canSendMessage(url);
}
import { PingNotification } from "./Haru.Eft.Models";
import { CachedResponseService, CachedResponseHelper, FileResponseHelper, FileService } from "./Haru.Eft.Services";
import { HttpServer, WsServer, IServer } from "./Haru.Http";
import { Json } from "./Haru.Utils";
export class ServerCluster
{
private readonly servers: IServer[];
public constructor()
{
this.servers = [
new GeneralServer(),
new NotificationServer()
];
}
public start(): void
{
for (const server of this.servers)
{
server.start();
}
}
public stop(): void
{
for (const server of this.servers)
{
server.stop();
}
}
}
export class GeneralServer implements IServer
{
private readonly server: HttpServer;
public constructor()
{
this.server = new HttpServer("localhost", 8000);
// add cached responses
const cachedResponseService = new CachedResponseService();
for (const url in CachedResponseHelper.responses)
{
this.server.addService(url, cachedResponseService);
}
// add file responses
const fileService = new FileService()
for (const url in FileResponseHelper.files)
{
this.server.addService(url, fileService);
}
}
public start(): void
{
this.server.start();
}
public stop(): void
{
this.server.stop();
}
public isListening(): boolean
{
return this.server.isListening();
}
}
export class NotificationServer implements IServer
{
private readonly httpServer: HttpServer;
private readonly wsServer: WsServer;
public constructor()
{
const message = Json.serialize(new PingNotification());
this.httpServer = new HttpServer("localhost", 8001);
this.wsServer = new WsServer(this.httpServer, message);
}
public start(): void
{
this.httpServer.start();
this.wsServer.start();
}
public stop(): void
{
this.httpServer.stop();
this.wsServer.stop();
}
public isListening(): boolean
{
return this.httpServer.isListening() || this.wsServer.isListening();
}
public canSendMessage(sessionId: string): boolean
{
// TODO: use actual url
const url: string = sessionId;
return this.wsServer.canSendMessage(url);
}
}

View File

@ -1,11 +1,11 @@
import { ServerCluster } from "./Haru.Eft.Servers";
import { Log } from "./Haru.Utils";
export class Program
{
public static main(args: string[])
{
Log.init("./Logs/Haru.log");
new ServerCluster().start();
}
import { ServerCluster } from "./Haru.Eft.Servers";
import { Log } from "./Haru.Utils";
export class Program
{
public static main(args: string[])
{
Log.init("./Logs/Haru.log");
new ServerCluster().start();
}
}

3
server/src/main.ts Normal file
View File

@ -0,0 +1,3 @@
import { Program } from "./Haru";
Program.main(process.argv);

15
server/tsconfig.json Normal file
View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es2020",
"module": "es2020",
"moduleResolution": "node",
"inlineSourceMap": true,
"inlineSources": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./obj/ts"
},
"include": [
"./src"
]
}