restructure project
This commit is contained in:
parent
20bbfd4239
commit
7cfe244127
23
.vscode/launch.json
vendored
Normal file
23
.vscode/launch.json
vendored
Normal 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
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"window.title": "Natsu Project",
|
||||
}
|
8
.vscode/tasks.json
vendored
Normal file
8
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "something"
|
||||
}
|
||||
]
|
||||
}
|
57
launcher/package.json
Normal file
57
launcher/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
92
launcher/src/Haru.Utils.ts
Normal file
92
launcher/src/Haru.Utils.ts
Normal 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
14
launcher/src/Haru.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
import { Program } from "./Haru";
|
||||
|
||||
import { Program } from "./Haru";
|
||||
|
||||
Program.main(process.argv);
|
4157
package-lock.json
generated
4157
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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"
|
@ -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 = [];
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
3
server/src/main.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { Program } from "./Haru";
|
||||
|
||||
Program.main(process.argv);
|
15
server/tsconfig.json
Normal file
15
server/tsconfig.json
Normal 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"
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user