mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 18:44:16 +00:00
added wrapper dev mode
This commit is contained in:
parent
c21a4af3cc
commit
b128df2551
@ -6,6 +6,7 @@
|
||||
"scripts": {
|
||||
"postinstall": "npm rebuild @tensorflow/tfjs-node --build-from-source && node ./scripts/postinstall.js",
|
||||
"release": "node ./scripts/release.js",
|
||||
"wrapper:dev": "node ./packages/wrapper/src/index.js --dev",
|
||||
"dev": "concurrently -k -n Client,Server,MarketplaceServer,ChatServer,FileServer,MusicServer -c bgCyan,auto \"yarn dev:client\" \"yarn dev:server\" \"yarn dev:marketplace_server\" \"yarn dev:chat_server\" \"yarn dev:file_server\" \"yarn dev:music_server\"",
|
||||
"dev:file_server": "cd packages/file_server && yarn dev",
|
||||
"dev:music_server": "cd packages/music_server && yarn dev",
|
||||
|
@ -9,10 +9,14 @@
|
||||
"dependencies": {
|
||||
"7zip-min": "^1.4.3",
|
||||
"@octokit/rest": "^19.0.4",
|
||||
"cors": "2.8.5",
|
||||
"axios": "^0.27.2",
|
||||
"chalk": "4.1.2",
|
||||
"cors": "2.8.5",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.1"
|
||||
"express": "^4.18.1",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"module-alias": "^2.2.3",
|
||||
"pm2": "^5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"corenode": "^0.28.26"
|
||||
|
1
packages/wrapper/src/ascii.js
Normal file
1
packages/wrapper/src/ascii.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = " _ \r\n | | \r\n ___ ___ _ __ ___ | |_ _ _ \r\n \/ __\/ _ \\| \'_ ` _ \\| __| | | |\r\n | (_| (_) | | | | | | |_| |_| |\r\n \\___\\___\/|_| |_| |_|\\__|\\__, |\r\n __\/ |\r\n |___\/ "
|
22
packages/wrapper/src/globals.js
Normal file
22
packages/wrapper/src/globals.js
Normal file
@ -0,0 +1,22 @@
|
||||
require("dotenv").config()
|
||||
|
||||
const path = require("path")
|
||||
const moduleAlias = require("module-alias")
|
||||
|
||||
global.packagejson = require("../package.json")
|
||||
global.__root = path.resolve(__dirname)
|
||||
global.isProduction = process.env.NODE_ENV === "production"
|
||||
global.remoteRepo = "ragestudio/comty"
|
||||
global.cachePath = path.join(process.cwd(), "cache")
|
||||
global.distPath = path.join(process.cwd(), "dist")
|
||||
|
||||
const aliases = {
|
||||
"@shared-classes": path.resolve(__dirname, "_shared/classes"),
|
||||
"@shared-lib": path.resolve(__dirname, "_shared/lib"),
|
||||
}
|
||||
|
||||
if (!global.isProduction) {
|
||||
aliases["@shared-classes"] = path.resolve(__dirname, "shared-classes")
|
||||
}
|
||||
|
||||
moduleAlias.addAliases(aliases)
|
@ -1,91 +1,331 @@
|
||||
require("dotenv").config()
|
||||
require("./globals")
|
||||
|
||||
const packagejson = require("../package.json")
|
||||
const pm2 = require("pm2")
|
||||
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
const express = require("express")
|
||||
const cors = require("cors")
|
||||
const chalk = require("chalk")
|
||||
const { exec, spawn, fork } = require("child_process")
|
||||
|
||||
const getInternalIp = require("./lib/getInternalIp")
|
||||
const comtyAscii = require("./ascii")
|
||||
|
||||
const useLogger = require("./lib/useLogger")
|
||||
const { createProxyMiddleware } = require("http-proxy-middleware")
|
||||
|
||||
const { setupLatestRelease } = require("./lib/setupDist")
|
||||
|
||||
global.remoteRepo = "ragestudio/comty"
|
||||
global.cachePath = path.join(process.cwd(), "cache")
|
||||
global.distPath = path.join(process.cwd(), "dist")
|
||||
const developmentServers = [
|
||||
{
|
||||
name: "WebAPP",
|
||||
color: "bgRed",
|
||||
cwd: path.resolve(global.__root, "../../app"),
|
||||
},
|
||||
{
|
||||
name: "MainAPI",
|
||||
color: "bgBlue",
|
||||
cwd: path.resolve(global.__root, "../../server"),
|
||||
},
|
||||
{
|
||||
name: "ChatAPI",
|
||||
color: "bgMagenta",
|
||||
cwd: path.resolve(global.__root, "../../chat_server"),
|
||||
},
|
||||
{
|
||||
name: "MarketplaceAPI",
|
||||
color: "bgCyan",
|
||||
cwd: path.resolve(global.__root, "../../marketplace_server"),
|
||||
},
|
||||
{
|
||||
name: "MusicAPI",
|
||||
color: "bgGreen",
|
||||
cwd: path.resolve(global.__root, "../../music_server")
|
||||
},
|
||||
{
|
||||
name: "FileAPI",
|
||||
color: "bgYellow",
|
||||
cwd: path.resolve(global.__root, "../../file_server"),
|
||||
},
|
||||
]
|
||||
|
||||
function checkDistIntegrity() {
|
||||
// check if dist folder exists
|
||||
if (!fs.existsSync(global.distPath)) {
|
||||
return false
|
||||
const ApiServers = [
|
||||
{
|
||||
name: "default",
|
||||
remote: ({
|
||||
address,
|
||||
protocol,
|
||||
port
|
||||
} = {}) => `${protocol ?? "http"}://${address ?? process.env.LOCALHOST}:${port ?? 3010}`,
|
||||
},
|
||||
{
|
||||
name: "chat",
|
||||
remote: ({
|
||||
address,
|
||||
protocol,
|
||||
port
|
||||
} = {}) => `${protocol ?? "http"}://${address ?? process.env.LOCALHOST}:${port ?? 3020}`,
|
||||
},
|
||||
{
|
||||
name: "livestreaming",
|
||||
remote: ({
|
||||
address,
|
||||
protocol,
|
||||
port
|
||||
} = {}) => `${protocol ?? "http"}://${address ?? process.env.LOCALHOST}:${port ?? 3030}`,
|
||||
},
|
||||
{
|
||||
name: "marketplace",
|
||||
remote: ({
|
||||
address,
|
||||
protocol,
|
||||
port
|
||||
} = {}) => `${protocol ?? "http"}://${address ?? process.env.LOCALHOST}:${port ?? 3040}`
|
||||
},
|
||||
{
|
||||
name: "music",
|
||||
remote: ({
|
||||
address,
|
||||
protocol,
|
||||
port
|
||||
} = {}) => `${protocol ?? "http"}://${address ?? process.env.LOCALHOST}:${port ?? 3050}`
|
||||
},
|
||||
{
|
||||
name: "files",
|
||||
remote: ({
|
||||
address,
|
||||
protocol,
|
||||
port
|
||||
} = {}) => `${protocol ?? "http"}://${address ?? process.env.LOCALHOST}:${port ?? 3060}`
|
||||
}
|
||||
]
|
||||
|
||||
// TODO: check the dist checksum with oficial server checksum
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
function fetchDistManifest() {
|
||||
if (!fs.existsSync(global.distPath)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const pkgPath = path.join(global.distPath, "manifest.json")
|
||||
|
||||
if (!fs.existsSync(pkgPath)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const pkg = require(pkgPath)
|
||||
|
||||
return pkg
|
||||
}
|
||||
|
||||
async function runServer() {
|
||||
const app = express()
|
||||
|
||||
const portFromArgs = process.argv[2]
|
||||
let portListen = portFromArgs ? portFromArgs : 9000
|
||||
|
||||
app.use(cors({
|
||||
origin: "*",
|
||||
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
|
||||
preflightContinue: true,
|
||||
optionsSuccessStatus: 204
|
||||
}))
|
||||
|
||||
app.use(express.static(global.distPath))
|
||||
|
||||
app.get("/_dist_manifest", async (req, res) => {
|
||||
const manifest = fetchDistManifest()
|
||||
|
||||
if (!manifest) {
|
||||
return res.status(500).send("Dist not found")
|
||||
class Main {
|
||||
static checkDistIntegrity() {
|
||||
// check if dist folder exists
|
||||
if (!fs.existsSync(global.distPath)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return res.json(manifest)
|
||||
})
|
||||
// TODO: check the dist checksum with oficial server checksum
|
||||
|
||||
app.get("*", function (req, res) {
|
||||
res.sendFile(path.join(global.distPath, "index.html"))
|
||||
})
|
||||
|
||||
app.listen(portListen)
|
||||
|
||||
console.log(`Running Wrapper v${packagejson.version}`)
|
||||
console.log(`🌐 Listening app in port [${portListen}]`)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// check if dist is valid
|
||||
if (!checkDistIntegrity()) {
|
||||
console.log("DistIntegrity is not valid, downloading latest release...")
|
||||
await setupLatestRelease()
|
||||
return true
|
||||
}
|
||||
|
||||
// start app
|
||||
await runServer()
|
||||
static fetchDistManifest() {
|
||||
if (!fs.existsSync(global.distPath)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const pkgPath = path.join(global.distPath, "manifest.json")
|
||||
|
||||
if (!fs.existsSync(pkgPath)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const pkg = require(pkgPath)
|
||||
|
||||
return pkg
|
||||
}
|
||||
|
||||
constructor(process) {
|
||||
this.process = process
|
||||
this.args = this.getArgs()
|
||||
|
||||
this.registerExitHandlers()
|
||||
this.initialize()
|
||||
}
|
||||
|
||||
initialize = async () => {
|
||||
console.clear()
|
||||
console.log(comtyAscii)
|
||||
console.log(`${chalk.bgBlue(`Running Wrapper`)} ${chalk.bgMagenta(`[v${global.packagejson.version}]`)}`)
|
||||
|
||||
this.internalIp = await getInternalIp()
|
||||
|
||||
this.webapp_port = this.args.web_port ?? 9000
|
||||
this.api_port = this.args.api_proxy_port ?? 5000
|
||||
|
||||
if (this.args.dev === true) {
|
||||
console.log(`🔧 Running in ${chalk.bgYellow("DEVELOPMENT")} mode \n\n`)
|
||||
|
||||
//this.runDevelopmentServers()
|
||||
this.runDevelopmentScript()
|
||||
this.initializeAPIProxyServer()
|
||||
|
||||
return this
|
||||
} else {
|
||||
if (!Main.checkDistIntegrity()) {
|
||||
await setupLatestRelease()
|
||||
}
|
||||
}
|
||||
|
||||
this.initializeWebAppServer()
|
||||
this.initializeAPIProxyServer()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
runDevelopmentScript = async () => {
|
||||
const devScript = spawn("npm", ["run", "dev"], {
|
||||
cwd: path.resolve(global.__root, "../../../"),
|
||||
shell: true,
|
||||
stdio: "inherit"
|
||||
})
|
||||
|
||||
// devScript.stdout.on("data", (data) => {
|
||||
// console.log(`${chalk.bgYellow("[WebAPP]")} ${data.toString()}`)
|
||||
// })
|
||||
|
||||
devScript.on("exit", (code) => {
|
||||
console.log(`🔧 ${chalk.bgYellow("WebAPP")} exited with code ${code}`)
|
||||
})
|
||||
}
|
||||
|
||||
runDevelopmentServers = async () => {
|
||||
this.dev_servers = []
|
||||
|
||||
// start all development servers
|
||||
for (let i = 0; i < developmentServers.length; i++) {
|
||||
const server = developmentServers[i]
|
||||
|
||||
console.log(`🔧 Starting ${chalk.bgYellow(server.name)}...`)
|
||||
|
||||
const serverProcess = spawn("npm", ["run", "dev"], {
|
||||
cwd: server.cwd,
|
||||
shell: true
|
||||
})
|
||||
|
||||
let chalkInstance = chalk[server.color]
|
||||
|
||||
if (typeof chalkInstance === undefined) {
|
||||
chalkInstance = chalk.bgWhite
|
||||
}
|
||||
|
||||
// log output of server
|
||||
serverProcess.stdout.on("data", (data) => {
|
||||
console.log(`${chalkInstance(`[${server.name}]`)} ${data.toString()}`)
|
||||
})
|
||||
|
||||
serverProcess.on("exit", (code) => {
|
||||
console.log(`🔧 ${chalk.bgYellow(server.name)} exited with code ${code}`)
|
||||
})
|
||||
|
||||
this.dev_servers.push({
|
||||
name: server.name,
|
||||
process: serverProcess
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
registerExitHandlers() {
|
||||
this.process.on("exit", this.onExit)
|
||||
this.process.on("SIGINT", this.onExit)
|
||||
this.process.on("SIGUSR1", this.onExit)
|
||||
this.process.on("SIGUSR2", this.onExit)
|
||||
this.process.on("uncaughtException", this.onExit)
|
||||
}
|
||||
|
||||
onExit = async () => {
|
||||
console.clear()
|
||||
console.log(comtyAscii)
|
||||
console.log(`Closing wrapper... \n\n`)
|
||||
|
||||
setTimeout(() => {
|
||||
console.log(`Wrapper did not close in time, forcefully closing...`)
|
||||
process.exit(0)
|
||||
}, 5000)
|
||||
|
||||
if (Array.isArray(this.dev_servers)) {
|
||||
for await (const server of this.dev_servers) {
|
||||
console.log(`Killing ${chalk.bgYellow(server.name)}...`)
|
||||
|
||||
server.process.kill()
|
||||
}
|
||||
}
|
||||
|
||||
return process.exit(0)
|
||||
}
|
||||
|
||||
getArgs = () => {
|
||||
let args = {}
|
||||
|
||||
for (let i = 0; i < this.process.argv.length; i++) {
|
||||
const arg = this.process.argv[i]
|
||||
|
||||
if (arg.startsWith("--")) {
|
||||
const argName = arg.replace("--", "")
|
||||
const argValue = this.process.argv[i + 1]
|
||||
|
||||
args[argName] = argValue ?? true
|
||||
}
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
initializeWebAppServer = async () => {
|
||||
this.webapp_server = express()
|
||||
|
||||
this.webapp_server.use(cors({
|
||||
origin: "*",
|
||||
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
|
||||
preflightContinue: true,
|
||||
optionsSuccessStatus: 204
|
||||
}))
|
||||
|
||||
if (!this.forwardAppPort) {
|
||||
this.webapp_server.use(express.static(global.distPath))
|
||||
|
||||
this.webapp_server.get("*", (req, res) => {
|
||||
return res.sendFile(path.join(global.distPath, "index.html"))
|
||||
})
|
||||
} else {
|
||||
this.webapp_server.use(createProxyMiddleware({
|
||||
target: `http://${this.internalIp}:${this.forwardAppPort}`,
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
pathRewrite: {
|
||||
"^/": ""
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
this.webapp_server.listen(this.webapp_port)
|
||||
|
||||
console.log(`🌐 WEB-APP Listening on > `, `${this.internalIp}:${this.webapp_port}`)
|
||||
|
||||
return this.webapp_server
|
||||
}
|
||||
|
||||
initializeAPIProxyServer = async () => {
|
||||
this.apiproxy_server = express()
|
||||
|
||||
this.apiproxy_server.use(useLogger)
|
||||
|
||||
ApiServers.forEach((server) => {
|
||||
const remote = server.remote({
|
||||
address: "eu02.ragestudio.net", //this.internalIp,
|
||||
protocol: this.forceApiHttps ? "https" : "http",
|
||||
})
|
||||
|
||||
this.apiproxy_server.use(`/${server.name}`, createProxyMiddleware({
|
||||
target: `${remote}`,
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
pathRewrite: {
|
||||
[`^/${server.name}`]: ""
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
||||
this.apiproxy_server.listen(this.api_port)
|
||||
|
||||
console.log(`🌐 API-PROXY Listening on >`, `${this.internalIp}:${this.api_port}`)
|
||||
|
||||
return this.apiproxy_server
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(`[FATAL ERROR] >`, err)
|
||||
})
|
||||
new Main(process)
|
12
packages/wrapper/src/lib/getInternalIp.js
Normal file
12
packages/wrapper/src/lib/getInternalIp.js
Normal file
@ -0,0 +1,12 @@
|
||||
const dns = require("dns")
|
||||
const os = require("os")
|
||||
|
||||
module.exports = () => new Promise((resolve, reject) => {
|
||||
dns.lookup(os.hostname(), (err, address, family) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
|
||||
resolve(address)
|
||||
})
|
||||
})
|
20
packages/wrapper/src/lib/useLogger/index.js
Normal file
20
packages/wrapper/src/lib/useLogger/index.js
Normal file
@ -0,0 +1,20 @@
|
||||
// just works with express
|
||||
module.exports = (req, res, next) => {
|
||||
const startHrTime = process.hrtime()
|
||||
|
||||
res.on("finish", () => {
|
||||
const elapsedHrTime = process.hrtime(startHrTime)
|
||||
const elapsedTimeInMs = elapsedHrTime[0] * 1000 + elapsedHrTime[1] / 1e6
|
||||
|
||||
res._responseTimeMs = elapsedTimeInMs
|
||||
|
||||
// cut req.url if is too long
|
||||
if (req.url.length > 100) {
|
||||
req.url = req.url.substring(0, 100) + "..."
|
||||
}
|
||||
|
||||
console.log(`${req.method} ${res._status_code ?? res.statusCode ?? 200} ${req.url} ${elapsedTimeInMs}ms`)
|
||||
})
|
||||
|
||||
next()
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user