:DDDDDDDDDDDDDDDdDDDD
This commit is contained in:
parent
38ed92abdf
commit
d8931427dc
|
|
@ -0,0 +1,14 @@
|
|||
RCCSERVICE=
|
||||
|
||||
BASE_URL=
|
||||
|
||||
RENDER_FORMAT=
|
||||
|
||||
RENDER_USER_WIDTH=
|
||||
RENDER_USER_HEIGHT=
|
||||
|
||||
RENDER_ASSET_WIDTH=
|
||||
RENDER_ASSET_HEIGHT=
|
||||
|
||||
RENDER_PLACE_WIDTH=
|
||||
RENDER_PLACE_HEIGHT=
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
node_modules
|
||||
build
|
||||
build
|
||||
.env
|
||||
|
|
@ -1 +1,7 @@
|
|||
# bingle-arbiter
|
||||
|
||||
The Bingle arbiter is designed to be used with almost any revival backend.
|
||||
|
||||
It comes preloaded with some Lua scripts made by kinery.
|
||||
|
||||
Set your desired settings in `.env.example`, then rename it to `.env`.
|
||||
|
|
|
|||
2
dev.bat
2
dev.bat
|
|
@ -1,2 +0,0 @@
|
|||
set RCCSERVICE_PATH=D:\\Projects\\Roblox\\Source\\UploadBits\\Win32-Release-RCCService\\
|
||||
npm run dev
|
||||
2
dev.sh
2
dev.sh
|
|
@ -1,2 +0,0 @@
|
|||
export RCCSERVICE_PATH=/run/media/calones/32531f99-d721-4297-90c7-f91e56851060/ICCService/
|
||||
npm run dev
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.2",
|
||||
"soap": "^1.0.0",
|
||||
"wait-port": "^1.0.4"
|
||||
|
|
@ -305,6 +306,14 @@
|
|||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
|
||||
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.2",
|
||||
"soap": "^1.0.0",
|
||||
"wait-port": "^1.0.4"
|
||||
|
|
|
|||
17
src/index.js
17
src/index.js
|
|
@ -1,13 +1,18 @@
|
|||
const logger = require("./lib/logger.js")
|
||||
require("dotenv").config()
|
||||
const express = require("express")
|
||||
const app = express()
|
||||
|
||||
app.use("/game/start", require("./routes/game/start.js"))
|
||||
app.use("/game/stop", require("./routes/game/stop.js"))
|
||||
app.use("/game/execute", require("./routes/game/execute.js"))
|
||||
const logger = require("./lib/logger.js")
|
||||
|
||||
if (process.platform == "linux") logger.warn("Game hosting might not fully compatible with Linux")
|
||||
|
||||
app.use("/place/start", require("./routes/place/start.js"))
|
||||
app.use("/place/stop", require("./routes/place/stop.js"))
|
||||
app.use("/place/execute", require("./routes/place/execute.js"))
|
||||
app.use("/place/renew", require("./routes/place/renew.js"))
|
||||
|
||||
app.use("/render/asset", require("./routes/render/asset.js"))
|
||||
app.use("/render/game", require("./routes/render/game.js"))
|
||||
app.use("/render/place", require("./routes/render/place.js"))
|
||||
app.use("/render/headshot", require("./routes/render/headshot.js"))
|
||||
app.use("/render/bodyshot", require("./routes/render/bodyshot.js"))
|
||||
|
||||
|
|
@ -18,5 +23,5 @@ app.listen(process.env.PORT || 64989, () => {
|
|||
})
|
||||
|
||||
process.on("uncaughtException", (err) => {
|
||||
logger.error(err)
|
||||
logger.error(err.message)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
const RCCService = require("./RCCService.js")
|
||||
const soap = require("soap")
|
||||
const { randomUUID } = require("crypto")
|
||||
|
||||
const RCCService = require("./RCCService.js")
|
||||
|
||||
class Job extends RCCService {
|
||||
constructor(id, port, expirationInSeconds = 10, category = 0, cores = 1) {
|
||||
super(port)
|
||||
constructor({ id = randomUUID(), expirationInSeconds = 10, category = 0, cores = 1 } = {}) {
|
||||
super()
|
||||
this.id = id
|
||||
this.expirationInSeconds = expirationInSeconds
|
||||
this.category = category
|
||||
|
|
@ -15,7 +17,7 @@ class Job extends RCCService {
|
|||
return this.client
|
||||
}
|
||||
|
||||
async Open(script) {
|
||||
async OpenJobEx(script) {
|
||||
if (!this.client) throw new Error("There is no client")
|
||||
return await this.client.OpenJobExAsync({
|
||||
job: {
|
||||
|
|
@ -28,16 +30,19 @@ class Job extends RCCService {
|
|||
})
|
||||
}
|
||||
|
||||
async Close() {
|
||||
async CloseJob() {
|
||||
if (!this.client) return true
|
||||
return await this.client.CloseAllJobsAsync({})
|
||||
return await this.client.CloseJobAsync({ jobID: this.id })
|
||||
}
|
||||
|
||||
async RenewLease(expirationInSeconds) {
|
||||
return await this.client.RenewLeaseAsync({
|
||||
jobID: this.id,
|
||||
expirationInSeconds,
|
||||
})
|
||||
if (!this.client) throw new Error("There is no client")
|
||||
return await this.client.RenewLeaseAsync({ jobID: this.id, expirationInSeconds })
|
||||
}
|
||||
|
||||
async Execute(name, script) {
|
||||
if (!this.client) throw new Error("There is no client")
|
||||
return await this.client.ExecuteAsync({ jobID: this.id, script: { name, script, arguments: {} } })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,30 +1,31 @@
|
|||
const EventEmitter = require("events")
|
||||
const child_process = require("child_process")
|
||||
const waitPort = require("wait-port")
|
||||
|
||||
const logger = require("../../lib/logger.js")
|
||||
const randport = require("../../lib/randport.js")
|
||||
|
||||
class RCCService extends EventEmitter {
|
||||
constructor(port, path = process.env.RCCSERVICE_PATH) {
|
||||
constructor() {
|
||||
super()
|
||||
this.path = path
|
||||
this.port = port
|
||||
}
|
||||
|
||||
Start(options = { cwd: this.path }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Start() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
this.port = await randport.tcp()
|
||||
|
||||
if (process.platform == "win32") {
|
||||
this.proc = child_process.spawn("RCCService.exe", ["-Console", "-PlaceId:-1", `-Port`, this.port], options)
|
||||
this.proc = child_process.spawn("RCCService.exe", ["-Console", "-PlaceId:-1", `-Port`, this.port], { cwd: process.env.RCCSERVICE })
|
||||
} else {
|
||||
this.proc = child_process.spawn("wine", ["RCCService.exe", "-Console", "-PlaceId:-1", `-Port`, this.port], options)
|
||||
this.proc = child_process.spawn("wine", ["RCCService.exe", "-Console", "-PlaceId:-1", `-Port`, this.port], { cwd: process.env.RCCSERVICE })
|
||||
}
|
||||
|
||||
this.proc.once("spawn", async () => {
|
||||
logger.info(`[${this.port}] RCCService instance spawned`)
|
||||
const { open } = await waitPort({ host: "127.0.0.1", port: this.port, timeout: 5000, output: "silent" }).catch((e) => console.log(e))
|
||||
if (!open || this.proc.exitCode !== null) {
|
||||
logger.error(`[${this.port}] RCCService could not listen, exiting`)
|
||||
this.Close()
|
||||
logger.error(`[${this.port}] RCCService could not listen`)
|
||||
return resolve(false)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,152 @@
|
|||
const { readFileSync } = require("fs")
|
||||
|
||||
const Job = require("./Job.js")
|
||||
const logger = require("../logger.js")
|
||||
|
||||
class RenderJob extends Job {
|
||||
constructor() {}
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
async RenderHeadshot(id, base64 = false) {
|
||||
const started = await this.Start()
|
||||
if (!started) throw new Error("RCCService failed to start")
|
||||
if (!this.client) await this.CreateClient()
|
||||
|
||||
logger.info(`[${this.id}] Headshot RenderJob started for ${id}`)
|
||||
|
||||
const result = await this.OpenJobEx({
|
||||
name: this.id,
|
||||
script: readFileSync(__dirname + "/../../lua/headshot.lua", { encoding: "utf-8" }),
|
||||
arguments: {
|
||||
LuaValue: [
|
||||
{ type: "LUA_TSTRING", value: this.id },
|
||||
|
||||
{ type: "LUA_TSTRING", value: "Headshot" },
|
||||
{ type: "LUA_TSTRING", value: process.env.RENDER_FORMAT },
|
||||
|
||||
{ type: "LUA_TNUMBER", value: process.env.RENDER_USER_WIDTH },
|
||||
{ type: "LUA_TNUMBER", value: process.env.RENDER_USER_HEIGHT },
|
||||
|
||||
{ type: "LUA_TSTRING", value: process.env.BASE_URL },
|
||||
{ type: "LUA_TNUMBER", value: id },
|
||||
],
|
||||
},
|
||||
}).catch((e) => false)
|
||||
|
||||
logger.info(`[${this.id}] Headshot RenderJob finished for ${id}`)
|
||||
|
||||
await this.Stop()
|
||||
|
||||
if (!result) return false
|
||||
if (base64) return result[0].OpenJobExResult.LuaValue[0].value
|
||||
return Buffer.from(result[0]?.OpenJobExResult?.LuaValue[0]?.value, "base64")
|
||||
}
|
||||
|
||||
async RenderBodyshot(id, base64 = false) {
|
||||
const started = await this.Start()
|
||||
if (!started) throw new Error("RCCService failed to start")
|
||||
if (!this.client) await this.CreateClient()
|
||||
|
||||
logger.info(`[${this.id}] Bodyshot RenderJob started for ${id}`)
|
||||
|
||||
const result = await this.OpenJobEx({
|
||||
name: this.id,
|
||||
script: readFileSync(__dirname + "/../../lua/bodyshot.lua", { encoding: "utf-8" }),
|
||||
arguments: {
|
||||
LuaValue: [
|
||||
{ type: "LUA_TSTRING", value: this.id },
|
||||
|
||||
{ type: "LUA_TSTRING", value: "Bodyshot" },
|
||||
{ type: "LUA_TSTRING", value: process.env.RENDER_FORMAT },
|
||||
|
||||
{ type: "LUA_TNUMBER", value: process.env.RENDER_USER_WIDTH },
|
||||
{ type: "LUA_TNUMBER", value: process.env.RENDER_USER_HEIGHT },
|
||||
|
||||
{ type: "LUA_TSTRING", value: process.env.BASE_URL },
|
||||
{ type: "LUA_TNUMBER", value: id },
|
||||
],
|
||||
},
|
||||
}).catch((e) => false)
|
||||
|
||||
logger.info(`[${this.id}] Bodyshot RenderJob finished for ${id}`)
|
||||
|
||||
await this.Stop()
|
||||
|
||||
if (!result) return false
|
||||
if (base64) return result[0].OpenJobExResult.LuaValue[0].value
|
||||
return Buffer.from(result[0]?.OpenJobExResult?.LuaValue[0]?.value, "base64")
|
||||
}
|
||||
|
||||
async RenderAsset(id, base64 = false) {
|
||||
const started = await this.Start()
|
||||
if (!started) throw new Error("RCCService failed to start")
|
||||
if (!this.client) await this.CreateClient()
|
||||
|
||||
logger.info(`[${this.id}] Asset RenderJob started for ${id}`)
|
||||
|
||||
const result = await this.OpenJobEx({
|
||||
name: this.id,
|
||||
script: readFileSync(__dirname + "/../../lua/xml.lua", { encoding: "utf-8" }),
|
||||
arguments: {
|
||||
LuaValue: [
|
||||
{ type: "LUA_TSTRING", value: this.id },
|
||||
|
||||
{ type: "LUA_TSTRING", value: "Asset" },
|
||||
{ type: "LUA_TSTRING", value: process.env.RENDER_FORMAT },
|
||||
|
||||
{ type: "LUA_TNUMBER", value: process.env.RENDER_ASSET_WIDTH },
|
||||
{ type: "LUA_TNUMBER", value: process.env.RENDER_ASSET_HEIGHT },
|
||||
|
||||
{ type: "LUA_TSTRING", value: process.env.BASE_URL },
|
||||
{ type: "LUA_TNUMBER", value: id },
|
||||
],
|
||||
},
|
||||
}).catch((e) => false)
|
||||
|
||||
logger.info(`[${this.id}] Asset RenderJob finished for ${id}`)
|
||||
|
||||
await this.Stop()
|
||||
|
||||
if (!result) return false
|
||||
if (base64) return result[0].OpenJobExResult.LuaValue[0].value
|
||||
return Buffer.from(result[0]?.OpenJobExResult?.LuaValue[0]?.value, "base64")
|
||||
}
|
||||
|
||||
async RenderPlace(id, base64 = false) {
|
||||
const started = await this.Start()
|
||||
if (!started) throw new Error("RCCService failed to start")
|
||||
if (!this.client) await this.CreateClient()
|
||||
|
||||
logger.info(`[${this.id}] Place RenderJob started for ${id}`)
|
||||
|
||||
const result = await this.OpenJobEx({
|
||||
name: this.id,
|
||||
script: readFileSync(__dirname + "/../../lua/place.lua", { encoding: "utf-8" }),
|
||||
arguments: {
|
||||
LuaValue: [
|
||||
{ type: "LUA_TSTRING", value: this.id },
|
||||
|
||||
{ type: "LUA_TSTRING", value: "Place" },
|
||||
{ type: "LUA_TSTRING", value: process.env.RENDER_FORMAT },
|
||||
|
||||
{ type: "LUA_TNUMBER", value: process.env.RENDER_PLACE_WIDTH },
|
||||
{ type: "LUA_TNUMBER", value: process.env.RENDER_PLACE_HEIGHT },
|
||||
|
||||
{ type: "LUA_TSTRING", value: process.env.BASE_URL },
|
||||
{ type: "LUA_TNUMBER", value: id },
|
||||
],
|
||||
},
|
||||
}).catch((e) => false)
|
||||
|
||||
logger.info(`[${this.id}] Place RenderJob finished for ${id}`)
|
||||
|
||||
await this.Stop()
|
||||
|
||||
if (!result) return false
|
||||
if (base64) return result[0].OpenJobExResult.LuaValue[0].value
|
||||
return Buffer.from(result[0]?.OpenJobExResult?.LuaValue[0]?.value, "base64")
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RenderJob
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const net = require("net")
|
||||
const dgram = require("dgram")
|
||||
|
||||
module.exports = () => {
|
||||
exports.tcp = () => {
|
||||
return new Promise((resolve) => {
|
||||
const server = net.createServer()
|
||||
server.listen(0, () => {
|
||||
|
|
@ -9,3 +10,13 @@ module.exports = () => {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
exports.udp = () => {
|
||||
return new Promise((resolve) => {
|
||||
const server = dgram.createSocket()
|
||||
server.bind(0, () => {
|
||||
const port = server.address().port
|
||||
server.close((err) => resolve(port))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = (ms) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms)
|
||||
})
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ asset.Parent = workspace
|
|||
|
||||
local thumbnailCamera = asset:FindFirstChild("ThumbnailCamera")
|
||||
if thumbnailCamera ~= nil and thumbnailCamera.ClassName == "Camera" then
|
||||
workspace.CurrentCamera = ModelCamera
|
||||
workspace.CurrentCamera = thumbnailCamera
|
||||
end
|
||||
|
||||
print(("[%s] Rendering ..."):format(jobId))
|
||||
|
|
|
|||
|
|
@ -1,45 +1,14 @@
|
|||
const { readFileSync } = require("fs")
|
||||
const { randomUUID } = require("crypto")
|
||||
const logger = require("../../lib/logger.js")
|
||||
const randport = require("../../lib/randport.js")
|
||||
const Job = require("../../lib/classes/Job.js")
|
||||
|
||||
const express = require("express")
|
||||
const app = express.Router()
|
||||
|
||||
const RenderJob = require("../../lib/classes/RenderJob.js")
|
||||
|
||||
app.get("/:id", async (request, response) => {
|
||||
const job = new Job(randomUUID(), await randport())
|
||||
const started = await job.Start()
|
||||
if (!started) return response.status(500).json({ error: "RCCService failed to start" })
|
||||
const job = new RenderJob()
|
||||
const result = await job.RenderAsset(request.params.id).catch((_) => _)
|
||||
|
||||
logger.info(`[${job.id}] Job opened`)
|
||||
await job.CreateClient()
|
||||
const result = await job
|
||||
.Open({
|
||||
name: job.id,
|
||||
script: readFileSync(__dirname + "/../../lua/xml.lua", { encoding: "utf-8" }),
|
||||
arguments: {
|
||||
LuaValue: [
|
||||
{ type: "LUA_TSTRING", value: job.id },
|
||||
{ type: "LUA_TSTRING", value: "XML" },
|
||||
{ type: "LUA_TSTRING", value: "PNG" },
|
||||
|
||||
// change this to 1920x when we finish the arbiter
|
||||
{ type: "LUA_TNUMBER", value: "420" },
|
||||
{ type: "LUA_TNUMBER", value: "420" },
|
||||
|
||||
{ type: "LUA_TSTRING", value: "https://economy.ittblox.gay" },
|
||||
{ type: "LUA_TNUMBER", value: request.params.id },
|
||||
],
|
||||
},
|
||||
})
|
||||
.catch((e) => false)
|
||||
|
||||
logger.info(`[${job.id}] Job closed`)
|
||||
await job.Stop()
|
||||
|
||||
if (result) return response.end(Buffer.from(result[0]?.OpenJobExResult?.LuaValue[0]?.value, "base64"))
|
||||
else return response.status(500).end()
|
||||
if (result?.message) return response.status(500).json({ error: result.message })
|
||||
else return response.end(result)
|
||||
})
|
||||
|
||||
module.exports = app
|
||||
|
|
|
|||
|
|
@ -1,45 +1,14 @@
|
|||
const { readFileSync } = require("fs")
|
||||
const { randomUUID } = require("crypto")
|
||||
const logger = require("../../lib/logger.js")
|
||||
const randport = require("../../lib/randport.js")
|
||||
const Job = require("../../lib/classes/Job.js")
|
||||
|
||||
const express = require("express")
|
||||
const app = express.Router()
|
||||
|
||||
const RenderJob = require("../../lib/classes/RenderJob.js")
|
||||
|
||||
app.get("/:id", async (request, response) => {
|
||||
const job = new Job(randomUUID(), await randport())
|
||||
const started = await job.Start()
|
||||
if (!started) return response.status(500).json({ error: "RCCService failed to start" })
|
||||
const job = new RenderJob()
|
||||
const result = await job.RenderBodyshot(request.params.id).catch((_) => _)
|
||||
|
||||
logger.info(`[${job.id}] Job opened`)
|
||||
await job.CreateClient()
|
||||
const result = await job
|
||||
.Open({
|
||||
name: job.id,
|
||||
script: readFileSync(__dirname + "/../../lua/bodyshot.lua", { encoding: "utf-8" }),
|
||||
arguments: {
|
||||
LuaValue: [
|
||||
{ type: "LUA_TSTRING", value: job.id },
|
||||
{ type: "LUA_TSTRING", value: "Bodyshot" },
|
||||
{ type: "LUA_TSTRING", value: "PNG" },
|
||||
|
||||
// change this to 1920x when we finish the arbiter
|
||||
{ type: "LUA_TNUMBER", value: "420" },
|
||||
{ type: "LUA_TNUMBER", value: "420" },
|
||||
|
||||
{ type: "LUA_TSTRING", value: "https://economy.ittblox.gay" },
|
||||
{ type: "LUA_TNUMBER", value: request.params.id },
|
||||
],
|
||||
},
|
||||
})
|
||||
.catch((e) => false)
|
||||
|
||||
logger.info(`[${job.id}] Job closed`)
|
||||
await job.Stop()
|
||||
|
||||
if (result) return response.end(Buffer.from(result[0]?.OpenJobExResult?.LuaValue[0]?.value, "base64"))
|
||||
else return response.status(500).end()
|
||||
if (result?.message) return response.status(500).json({ error: result.message })
|
||||
else return response.end(result)
|
||||
})
|
||||
|
||||
module.exports = app
|
||||
|
|
|
|||
|
|
@ -1,45 +1,14 @@
|
|||
const { readFileSync } = require("fs")
|
||||
const { randomUUID } = require("crypto")
|
||||
const logger = require("../../lib/logger.js")
|
||||
const randport = require("../../lib/randport.js")
|
||||
const Job = require("../../lib/classes/Job.js")
|
||||
|
||||
const express = require("express")
|
||||
const app = express.Router()
|
||||
|
||||
const RenderJob = require("../../lib/classes/RenderJob.js")
|
||||
|
||||
app.get("/:id", async (request, response) => {
|
||||
const job = new Job(randomUUID(), await randport())
|
||||
const started = await job.Start()
|
||||
if (!started) return response.status(500).json({ error: "RCCService failed to start" })
|
||||
const job = new RenderJob()
|
||||
const result = await job.RenderHeadshot(request.params.id).catch((_) => _)
|
||||
|
||||
logger.info(`[${job.id}] Job opened`)
|
||||
await job.CreateClient()
|
||||
const result = await job
|
||||
.Open({
|
||||
name: job.id,
|
||||
script: readFileSync(__dirname + "/../../lua/headshot.lua", { encoding: "utf-8" }),
|
||||
arguments: {
|
||||
LuaValue: [
|
||||
{ type: "LUA_TSTRING", value: job.id },
|
||||
{ type: "LUA_TSTRING", value: "Headshot" },
|
||||
{ type: "LUA_TSTRING", value: "PNG" },
|
||||
|
||||
// change this to 1920x when we finish the arbiter
|
||||
{ type: "LUA_TNUMBER", value: "420" },
|
||||
{ type: "LUA_TNUMBER", value: "420" },
|
||||
|
||||
{ type: "LUA_TSTRING", value: "https://economy.ittblox.gay" },
|
||||
{ type: "LUA_TNUMBER", value: request.params.id },
|
||||
],
|
||||
},
|
||||
})
|
||||
.catch((e) => false)
|
||||
|
||||
logger.info(`[${job.id}] Job closed`)
|
||||
await job.Stop()
|
||||
|
||||
if (result) return response.end(Buffer.from(result[0]?.OpenJobExResult?.LuaValue[0]?.value, "base64"))
|
||||
else return response.status(500).end()
|
||||
if (result?.message) return response.status(500).json({ error: result.message })
|
||||
else return response.end(result)
|
||||
})
|
||||
|
||||
module.exports = app
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
const express = require("express")
|
||||
const app = express.Router()
|
||||
|
||||
app.all("*", (request, response) => response.status(404).json({ status: 404 }))
|
||||
|
||||
module.exports = app
|
||||
Loading…
Reference in New Issue