This commit is contained in:
SrGooglo 2023-06-22 21:56:14 +02:00
commit 24f6f3c6d6
15 changed files with 624 additions and 135 deletions

View File

@ -6,6 +6,7 @@
"scripts": { "scripts": {
"postinstall": "npm rebuild @tensorflow/tfjs-node --build-from-source && node ./scripts/postinstall.js", "postinstall": "npm rebuild @tensorflow/tfjs-node --build-from-source && node ./scripts/postinstall.js",
"release": "node ./scripts/release.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": "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:file_server": "cd packages/file_server && yarn dev",
"dev:music_server": "cd packages/music_server && yarn dev", "dev:music_server": "cd packages/music_server && yarn dev",
@ -31,4 +32,4 @@
"pm2": "5.3.0" "pm2": "5.3.0"
}, },
"version": "0.49.0" "version": "0.49.0"
} }

View File

@ -263,26 +263,37 @@ const OpenTagEditor = ({ tag, onFinish = () => app.navigation.softReload() } = {
const TapShareRender = () => { const TapShareRender = () => {
return <div className="tap-share-render"> return <div className="tap-share-render">
{
!app.cores.nfc.scanning && app.isMobile && <antd.Alert
type="warning"
message="NFC is disabled"
description="You can enable it in your device settings."
/>
}
<div className="tap-share-field"> <div className="tap-share-field">
<div className="tap-share-field_header"> <div className="tap-share-field_header">
<h1> <h1>
<Icons.MdSpoke /> Registered Tags <Icons.MdSpoke /> Registered Tags
</h1> </h1>
</div> </div>
<span className="tip"> {
<Icons.MdInfo /> You can quickly edit your tags by tapping them. app.cores.nfc.scanning && <span className="tip">
</span> <Icons.MdInfo /> You can quickly edit your tags by tapping them.
</span>
}
<OwnTags /> <OwnTags />
</div> </div>
<antd.Button {
type="primary" app.isMobile && <antd.Button
icon={<Icons.Plus />} type="primary"
onClick={() => OpenTagEditor()} icon={<Icons.Plus />}
> onClick={() => OpenTagEditor()}
Add new >
</antd.Button> Add new
</antd.Button>
}
</div> </div>
} }

View File

@ -22,13 +22,6 @@ export default (props) => {
return false return false
} }
const nfcInstance = app.cores.nfc.instance()
if (!nfcInstance) {
setError(NFC_ERRORS.NFC_NOT_AVAILABLE)
return false
}
setError(null) setError(null)
setLoading(true) setLoading(true)
@ -40,7 +33,7 @@ export default (props) => {
return false return false
} }
nfcInstance.write({ app.cores.nfc.writeNdef({
records: [{ records: [{
recordType: "url", recordType: "url",
data: context.values.endpoint_url data: context.values.endpoint_url

View File

@ -66,7 +66,6 @@ import loadable from "@loadable/component"
import { StatusBar, Style } from "@capacitor/status-bar" import { StatusBar, Style } from "@capacitor/status-bar"
import { App as CapacitorApp } from "@capacitor/app" import { App as CapacitorApp } from "@capacitor/app"
import { SplashScreen } from "@capacitor/splash-screen"
import { CapacitorUpdater } from "@capgo/capacitor-updater" import { CapacitorUpdater } from "@capgo/capacitor-updater"
import SessionModel from "models/session" import SessionModel from "models/session"
@ -98,6 +97,8 @@ import * as Router from "./router"
import "theme/index.less" import "theme/index.less"
console.log(`REACT VERSION: ${React.version}`)
CapacitorUpdater.notifyAppReady() CapacitorUpdater.notifyAppReady()
class ComtyApp extends React.Component { class ComtyApp extends React.Component {
@ -118,15 +119,10 @@ class ComtyApp extends React.Component {
} }
static splashAwaitEvent = "app.initialization.finish" static splashAwaitEvent = "app.initialization.finish"
static async initialize() { static async initialize() {
SplashScreen.show({
autoHide: false,
})
window.app.splash = SplashScreen
window.app.version = config.package.version window.app.version = config.package.version
window.app.message = antd.message window.app.message = antd.message
window.app.isCapacitor = window.navigator.userAgent === "capacitor"
window.localStorage.setItem("last_version", window.app.version) window.localStorage.setItem("last_version", window.app.version)
@ -492,8 +488,6 @@ class ComtyApp extends React.Component {
this.setState({ initialized: true }) this.setState({ initialized: true })
Utils.handleOpenDevTools() Utils.handleOpenDevTools()
SplashScreen.hide()
} }
onRuntimeStateUpdate = (state) => { onRuntimeStateUpdate = (state) => {

View File

@ -2,8 +2,6 @@ import React from "react"
import classnames from "classnames" import classnames from "classnames"
import * as antd from "antd" import * as antd from "antd"
import { createIconRender } from "components/Icons"
import "./index.less" import "./index.less"
const NavMenu = (props) => { const NavMenu = (props) => {

View File

@ -1,4 +1,5 @@
import Core from "evite/src/core" import Core from "evite/src/core"
import { Haptics } from "@capacitor/haptics"
const vibrationPatterns = { const vibrationPatterns = {
light: [10], light: [10],
@ -19,6 +20,10 @@ export default class HapticsCore extends Core {
} }
async onInitialize() { async onInitialize() {
if (window.navigator.userAgent === "capacitor") {
navigator.vibrate = this.nativeVibrate
}
document.addEventListener("click", this.handleClickEvent) document.addEventListener("click", this.handleClickEvent)
} }
@ -27,6 +32,18 @@ export default class HapticsCore extends Core {
vibrate: this.vibrate.bind(this), vibrate: this.vibrate.bind(this),
} }
nativeVibrate = (pattern) => {
if (!Array.isArray(pattern)) {
pattern = [pattern]
}
for (let i = 0; i < pattern.length; i++) {
Haptics.vibrate({
duration: pattern[i],
})
}
}
handleClickEvent = (event) => { handleClickEvent = (event) => {
const button = event.target.closest("button") || event.target.closest(".ant-btn") const button = event.target.closest("button") || event.target.closest(".ant-btn")

View File

@ -1,40 +1,137 @@
import Core from "evite/src/core" import Core from "evite/src/core"
import TapShareDialog from "components/TapShare/Dialog" import TapShareDialog from "components/TapShare/Dialog"
import { Nfc, NfcUtils, NfcTagTechType } from "@capawesome-team/capacitor-nfc"
const RecordTypes = {
"T": "text",
"U": "url"
}
function decodePayload(record) {
let recordType = nfc.bytesToString(record.type)
let payload = {
recordId: nfc.bytesToHexString(record.id),
recordType: RecordTypes[recordType],
data: null
}
switch (recordType) {
case "T": {
let langCodeLength = record.payload[0]
payload.data = record.payload.slice((1 + langCodeLength), record.payload.length)
payload.data = nfc.bytesToString(text)
break
}
case "U": {
let identifierCode = record.payload.shift()
payload.data = nfc.bytesToString(record.payload)
switch (identifierCode) {
case 4: {
payload.data = `https://${payload.data}`
break
}
case 3: {
payload.data = `http://${payload.data}`
break
}
}
break
}
default: {
payload.data = nfc.bytesToString(record.payload)
break
}
}
return payload
}
function resolveSerialNumber(tag) {
let serialNumber = null
serialNumber = nfc.bytesToHexString(tag.id)
// transform serialNumber to contain a ":" every 2 bytes
serialNumber = serialNumber.replace(/(.{2})/g, "$1:")
// remove the last :
serialNumber = serialNumber.slice(0, -1)
return serialNumber
}
function parseNdefMessage(ndefMessage) {
let message = []
ndefMessage.forEach((ndefRecord) => {
message.push(decodePayload(ndefRecord))
})
return message
}
export default class NFC extends Core { export default class NFC extends Core {
static refName = "NFC" static refName = "NFC"
static namespace = "nfc" static namespace = "nfc"
isNativeMode = false
instance = null instance = null
subscribers = [] subscribers = []
public = { public = {
incompatible: null, incompatible: true,
scanning: false, scanning: false,
startScanning: this.startScanning.bind(this), writeNdef: this.writeNdef.bind(this),
instance: function () { return this.instance }.bind(this), instance: function () { return this.instance }.bind(this),
subscribe: this.subscribe.bind(this), subscribe: this.subscribe.bind(this),
unsubscribe: this.unsubscribe.bind(this), unsubscribe: this.unsubscribe.bind(this),
} }
async onInitialize() { subscribe(callback) {
if ("NDEFReader" in window === false) { // check if scan service is available, if not try to initialize
return this.public.incompatible = true if (this.public.scanning === false) {
this.startScanning()
} }
this.instance = new NDEFReader() this.subscribers.push(callback)
}
this.startScanning() unsubscribe(callback) {
this.subscribers = this.subscribers.filter((subscriber) => {
return subscriber !== callback
})
}
async onInitialize() {
if (window.nfc) {
this.instance = window.nfc
this.isNativeMode = true
return this.startNativeScanning()
}
if ("NDEFReader" in window) {
this.instance = new NDEFReader()
return this.startScanning()
}
return this.public.incompatible = true
} }
async startScanning() { async startScanning() {
try { try {
//await navigator.permissions.query({ name: "nfc" }) await this.instance.scan()
this.instance.scan()
this.public.scanning = true this.public.scanning = true
this.public.incompatible = false this.public.incompatible = false
@ -48,23 +145,11 @@ export default class NFC extends Core {
} }
} }
subscribe(callback) { startNativeScanning() {
// check if scan service is available, if not try to initialize this.public.scanning = true
if (this.public.scanning === false) { this.public.incompatible = false
this.startScanning()
}
this.subscribers.push(callback) return this.registerNativeEventListeners()
console.debug(`[NFC] SUBSCRIBED >`, this.subscribers.length)
}
unsubscribe(callback) {
this.subscribers = this.subscribers.filter((subscriber) => {
return subscriber !== callback
})
console.debug(`[NFC] UNSUBSCRIBED >`, this.subscribers.length)
} }
handleRead(tag) { handleRead(tag) {
@ -75,8 +160,6 @@ export default class NFC extends Core {
subscriber(null, tag) subscriber(null, tag)
}) })
console.log(this.subscribers)
if (this.subscribers.length === 0) { if (this.subscribers.length === 0) {
if (tag.message.records?.length > 0) { if (tag.message.records?.length > 0) {
// open dialog // open dialog
@ -89,6 +172,32 @@ export default class NFC extends Core {
} }
} }
handleNativeRead(tag) {
console.debug(`[NFC] NATIVE READ >`, tag)
tag.serialNumber = resolveSerialNumber(tag)
if (tag.ndefMessage) {
tag.message = {}
tag.message.records = parseNdefMessage(tag.ndefMessage)
}
this.subscribers.forEach((subscriber) => {
subscriber(null, tag)
})
if (this.subscribers.length === 0 && tag.message?.records) {
if (tag.message.records?.length > 0) {
// open dialog
app.DrawerController.open("nfc_card_dialog", TapShareDialog, {
componentProps: {
tag: tag,
}
})
}
}
}
handleError(error) { handleError(error) {
this.subscribers.forEach((subscriber) => { this.subscribers.forEach((subscriber) => {
subscriber(error, null) subscriber(error, null)
@ -99,4 +208,57 @@ export default class NFC extends Core {
this.instance.addEventListener("reading", this.handleRead.bind(this)) this.instance.addEventListener("reading", this.handleRead.bind(this))
this.instance.addEventListener("error", this.handleError.bind(this)) this.instance.addEventListener("error", this.handleError.bind(this))
} }
registerNativeEventListeners() {
nfc.addTagDiscoveredListener(
(e) => this.handleNativeRead(e.tag),
() => {
this.public.scanning = true
this.public.incompatible = false
},
this.handleError
)
nfc.addNdefListener(
(e) => this.handleNativeRead(e.tag),
() => {
this.public.scanning = true
this.public.incompatible = false
},
this.handleError
)
}
async writeNdef(payload, options) {
console.debug(`[NFC] WRITE >`, payload)
if (!this.isNativeMode) {
return this.instance.write(payload, options)
}
let message = []
const { records } = payload
if (!Array.isArray(records)) {
throw new Error("records must be an array")
}
for (const record of records) {
switch (record.recordType) {
case "text": {
message.push(ndef.textRecord(record.data))
break
}
case "url": {
message.push(ndef.uriRecord(record.data))
break
}
}
}
return await new Promise((resolve, reject) => {
this.instance.write(message, resolve, reject)
})
}
} }

View File

@ -1,4 +1,10 @@
function composeRemote(path) { function composeRemote(path) {
if (typeof window !== "undefined") {
if (window.localStorage.getItem("comty:use_indev") || window.location.hostname === "indev.comty.app") {
return envOrigins["indev"][path]
}
}
return envOrigins[process.env.NODE_ENV ?? "production"][path] return envOrigins[process.env.NODE_ENV ?? "production"][path]
} }
@ -19,6 +25,14 @@ const envOrigins = {
music: `http://${getCurrentHostname()}:3050`, music: `http://${getCurrentHostname()}:3050`,
files: `http://${getCurrentHostname()}:3060`, files: `http://${getCurrentHostname()}:3060`,
}, },
"indev": {
default: `https://indev_api.comty.app/default`,
chat: `https://indev_api.comty.app/chat`,
livestreaming: `https://indev_api.comty.app/livestreaming`,
marketplace: `https://indev_api.comty.app/marketplace`,
music: `https://indev_api.comty.app/music`,
files: `https://indev_api.comty.app/files`,
},
"production": { "production": {
default: "https://api.comty.app", default: "https://api.comty.app",
chat: `https://chat_api.comty.app`, chat: `https://chat_api.comty.app`,

View File

@ -9,12 +9,16 @@
"dependencies": { "dependencies": {
"7zip-min": "^1.4.3", "7zip-min": "^1.4.3",
"@octokit/rest": "^19.0.4", "@octokit/rest": "^19.0.4",
"cors": "2.8.5",
"axios": "^0.27.2", "axios": "^0.27.2",
"chalk": "4.1.2",
"cors": "2.8.5",
"dotenv": "^16.0.3", "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": { "devDependencies": {
"corenode": "^0.28.26" "corenode": "^0.28.26"
} }
} }

View File

@ -0,0 +1 @@
module.exports = " _ \r\n | | \r\n ___ ___ _ __ ___ | |_ _ _ \r\n \/ __\/ _ \\| \'_ ` _ \\| __| | | |\r\n | (_| (_) | | | | | | |_| |_| |\r\n \\___\\___\/|_| |_| |_|\\__|\\__, |\r\n __\/ |\r\n |___\/ "

View 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)

View File

@ -1,91 +1,331 @@
require("dotenv").config() require("./globals")
const packagejson = require("../package.json") const pm2 = require("pm2")
const fs = require("fs") const fs = require("fs")
const path = require("path") const path = require("path")
const express = require("express") const express = require("express")
const cors = require("cors") 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") const { setupLatestRelease } = require("./lib/setupDist")
global.remoteRepo = "ragestudio/comty" const developmentServers = [
global.cachePath = path.join(process.cwd(), "cache") {
global.distPath = path.join(process.cwd(), "dist") 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() { const ApiServers = [
// check if dist folder exists {
if (!fs.existsSync(global.distPath)) { name: "default",
return false 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 class Main {
static checkDistIntegrity() {
return true // check if dist folder exists
} if (!fs.existsSync(global.distPath)) {
return false
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")
} }
return res.json(manifest) // TODO: check the dist checksum with oficial server checksum
})
app.get("*", function (req, res) { return true
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()
} }
// start app static fetchDistManifest() {
await runServer() 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) => { new Main(process)
console.error(`[FATAL ERROR] >`, err)
})

View 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)
})
})

View 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()
}