1
0
forked from noxious/server

Path fixes for all environments, npm run format, removed redundant imports

This commit is contained in:
Dennis Postma 2024-10-01 00:10:30 +02:00
parent 4cbd62cbb0
commit ce1708a55e
24 changed files with 82 additions and 87 deletions

View File

@ -1,15 +1,15 @@
import path from 'path'
import fs from 'fs'
import sharp from 'sharp'
import { commandLogger } from '../utilities/logger'
import { Server } from 'socket.io'
import { getPublicPath } from '../utilities/utilities'
export default class TilesCommand {
constructor(private readonly io: Server) {}
public async execute(): Promise<void> {
// Get all tiles
const tilesDir = path.join(process.cwd(), 'public', 'tiles')
const tilesDir = getPublicPath('tiles')
const tiles = fs.readdirSync(tilesDir).filter((file) => file.endsWith('.png'))
// Create output directory if it doesn't exist
@ -19,14 +19,14 @@ export default class TilesCommand {
for (const tile of tiles) {
// Check if tile is already 66x34
const metadata = await sharp(path.join(tilesDir, tile)).metadata()
const metadata = await sharp(getPublicPath('tiles', tile)).metadata()
if (metadata.width === 66 && metadata.height === 34) {
commandLogger.info(`Tile ${tile} already processed`)
continue
}
const inputPath = path.join(tilesDir, tile)
const outputPath = path.join(tilesDir, tile)
const inputPath = getPublicPath('tiles', tile)
const outputPath = getPublicPath('tiles', tile)
try {
await sharp(inputPath)

View File

@ -3,7 +3,7 @@ import * as fs from 'fs'
import * as path from 'path'
import { Server } from 'socket.io'
import { commandLogger } from '../utilities/logger'
import config from '../utilities/config'
import { getAppPath } from '../utilities/utilities'
class CommandManager {
private commands: Map<string, any> = new Map()
@ -20,8 +20,6 @@ class CommandManager {
this.rl.on('close', () => {
this.rlClosed = true
})
console.log(process.cwd())
}
public async boot(io: Server) {
@ -63,34 +61,34 @@ class CommandManager {
}
private async loadCommands() {
const commandsDir = path.join(process.cwd(), 'commands');
commandLogger.info(`Loading commands from: ${commandsDir}`);
const directory = getAppPath('commands')
commandLogger.info(`Loading commands from: ${directory}`)
try {
const files = await fs.promises.readdir(commandsDir, { withFileTypes: true });
const files = await fs.promises.readdir(directory, { withFileTypes: true })
for (const file of files) {
if (!file.isFile() || (!file.name.endsWith('.ts') && !file.name.endsWith('.js'))) {
continue;
continue
}
const fullPath = path.join(commandsDir, file.name);
const commandName = path.basename(file.name, path.extname(file.name));
const fullPath = getAppPath('commands', file.name)
const commandName = path.basename(file.name, path.extname(file.name))
try {
const module = await import(fullPath);
const module = await import(fullPath)
if (typeof module.default !== 'function') {
commandLogger.warn(`Unrecognized export in ${file.name}`);
continue;
commandLogger.warn(`Unrecognized export in ${file.name}`)
continue
}
this.registerCommand(commandName, module.default);
this.registerCommand(commandName, module.default)
} catch (error) {
commandLogger.error(`Error loading command ${file.name}: ${error instanceof Error ? error.message : String(error)}`);
commandLogger.error(`Error loading command ${file.name}: ${error instanceof Error ? error.message : String(error)}`)
}
}
} catch (error) {
commandLogger.error(`Failed to read commands directory: ${error instanceof Error ? error.message : String(error)}`);
commandLogger.error(`Failed to read commands directory: ${error instanceof Error ? error.message : String(error)}`)
}
}

View File

@ -5,7 +5,7 @@ import { Server as SocketServer } from 'socket.io'
import { TSocket } from '../utilities/types'
import { queueLogger } from '../utilities/logger'
import fs from 'fs'
import path from 'path'
import { getAppPath } from '../utilities/utilities'
class QueueManager {
private connection!: IORedis
@ -52,9 +52,9 @@ class QueueManager {
const { jobName, params, socketId } = job.data
try {
const jobsDir = path.join(process.cwd(), 'jobs')
const jobsDir = getAppPath('jobs')
const extension = config.ENV === 'development' ? '.ts' : '.js'
const jobPath = path.join(jobsDir, `${jobName}${extension}`)
const jobPath = getAppPath('jobs', `${jobName}${extension}`)
if (!fs.existsSync(jobPath)) {
queueLogger.warn(`Job file not found: ${jobPath}`)

View File

@ -1,7 +1,5 @@
import { Zone } from '@prisma/client'
import zoneRepository from '../repositories/zoneRepository'
import characterManager from '../managers/characterManager'
import { ExtendedCharacter } from '../utilities/types'
class LoadedZone {
private readonly zone: Zone

View File

@ -1,5 +1,5 @@
import prisma from '../utilities/prisma' // Import the global Prisma instance
import { Sprite, SpriteAction } from '@prisma/client'
import { SpriteAction } from '@prisma/client'
class SpriteRepository {
async getById(id: string) {

View File

@ -1,5 +1,4 @@
import fs from 'fs'
import path from 'path'
import express, { Application } from 'express'
import config from './utilities/config'
import { createServer as httpServer, Server as HTTPServer } from 'http'
@ -9,13 +8,13 @@ import { Server as SocketServer } from 'socket.io'
import { Authentication } from './middleware/authentication'
import { TSocket } from './utilities/types'
import prisma from './utilities/prisma'
import { Dirent } from 'node:fs'
import { appLogger, watchLogs } from './utilities/logger'
import ZoneManager from './managers/zoneManager'
import UserManager from './managers/userManager'
import CommandManager from './managers/commandManager'
import CharacterManager from './managers/characterManager'
import QueueManager from './managers/queueManager'
import { getAppPath } from './utilities/utilities'
export class Server {
private readonly app: Application
@ -86,46 +85,46 @@ export class Server {
* @private
*/
private async handleConnection(socket: TSocket) {
const eventsPath = path.join(__dirname, 'socketEvents')
try {
await this.loadEventHandlers(eventsPath, socket)
await this.loadEventHandlers('socketEvents', '', socket)
} catch (error: any) {
appLogger.error(`Failed to load event handlers: ${error.message}`)
}
}
private async loadEventHandlers(dir: string, socket: TSocket) {
private async loadEventHandlers(baseDir: string, subDir: string, socket: TSocket) {
try {
const files = await fs.promises.readdir(dir, { withFileTypes: true });
const fullDir = getAppPath(baseDir, subDir)
const files = await fs.promises.readdir(fullDir, { withFileTypes: true })
for (const file of files) {
const fullPath = path.join(dir, file.name);
const filePath = getAppPath(baseDir, subDir, file.name)
if (file.isDirectory()) {
await this.loadEventHandlers(fullPath, socket);
continue;
await this.loadEventHandlers(baseDir, `${subDir}/${file.name}`, socket)
continue
}
if (!file.isFile() || (!file.name.endsWith('.ts') && !file.name.endsWith('.js'))) {
continue;
continue
}
try {
const module = await import(fullPath);
const module = await import(filePath)
if (typeof module.default !== 'function') {
appLogger.warn(`Unrecognized export in ${file.name}`);
continue;
appLogger.warn(`Unrecognized export in ${file.name}`)
continue
}
const EventClass = module.default;
const eventInstance = new EventClass(this.io, socket);
eventInstance.listen();
const EventClass = module.default
const eventInstance = new EventClass(this.io, socket)
eventInstance.listen()
} catch (error) {
appLogger.error(`Error loading event handler ${file.name}: ${error instanceof Error ? error.message : String(error)}`);
appLogger.error(`Error loading event handler ${file.name}: ${error instanceof Error ? error.message : String(error)}`)
}
}
} catch (error) {
appLogger.error(`Error reading directory ${dir}: ${error instanceof Error ? error.message : String(error)}`);
appLogger.error(`Error reading directory: ${error instanceof Error ? error.message : String(error)}`)
}
}
}

View File

@ -1,3 +0,0 @@
class AssetService {}
export default AssetService

View File

@ -1,5 +0,0 @@
import { Character } from '@prisma/client'
class CharacterService {}
export default CharacterService

View File

@ -1,7 +1,6 @@
import { Server } from 'socket.io'
import { TSocket, ExtendedCharacter } from '../../utilities/types'
import { TSocket } from '../../utilities/types'
import CharacterRepository from '../../repositories/characterRepository'
import CharacterManager from '../../managers/characterManager'
type SocketResponseT = {
character_id: number

View File

@ -2,7 +2,6 @@ import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import { Object } from '@prisma/client'
import ObjectRepository from '../../../../repositories/objectRepository'
import CharacterManager from '../../../../managers/characterManager'
import characterRepository from '../../../../repositories/characterRepository'
interface IPayload {}

View File

@ -1,10 +1,9 @@
import fs from 'fs'
import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import path from 'path'
import fs from 'fs'
import prisma from '../../../../utilities/prisma'
import CharacterManager from '../../../../managers/characterManager'
import characterRepository from '../../../../repositories/characterRepository'
import { getPublicPath } from '../../../../utilities/utilities'
interface IPayload {
object: string
@ -36,10 +35,10 @@ export default class ObjectRemoveEvent {
})
// get root path
const public_folder = path.join(process.cwd(), 'public', 'objects')
const public_folder = getPublicPath('objects')
// remove the tile from the disk
const finalFilePath = path.join(public_folder, data.object + '.png')
const finalFilePath = getPublicPath('objects', data.object + '.png')
fs.unlink(finalFilePath, (err) => {
if (err) {
console.log(err)

View File

@ -1,7 +1,6 @@
import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import prisma from '../../../../utilities/prisma'
import CharacterManager from '../../../../managers/characterManager'
import characterRepository from '../../../../repositories/characterRepository'
type Payload = {

View File

@ -1,12 +1,12 @@
import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import { writeFile } from 'node:fs/promises'
import path from 'path'
import fs from 'fs/promises'
import prisma from '../../../../utilities/prisma'
import sharp from 'sharp'
import characterRepository from '../../../../repositories/characterRepository'
import { gameMasterLogger } from '../../../../utilities/logger'
import { getPublicPath } from '../../../../utilities/utilities'
interface IObjectData {
[key: string]: Buffer
@ -30,7 +30,7 @@ export default class ObjectUploadEvent {
if (character.role !== 'gm') {
return callback(false)
}
const public_folder = path.join(process.cwd(), 'public', 'objects')
const public_folder = getPublicPath('objects')
// Ensure the folder exists
await fs.mkdir(public_folder, { recursive: true })
@ -54,7 +54,7 @@ export default class ObjectUploadEvent {
const uuid = object.id
const filename = `${uuid}.png`
const finalFilePath = path.join(public_folder, filename)
const finalFilePath = getPublicPath('objects', filename)
await writeFile(finalFilePath, objectData)
gameMasterLogger.info('gm:object:upload', `Object ${key} uploaded with id ${uuid}`)

View File

@ -1,10 +1,9 @@
import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import path from 'path'
import fs from 'fs/promises'
import prisma from '../../../../utilities/prisma'
import CharacterManager from '../../../../managers/characterManager'
import characterRepository from '../../../../repositories/characterRepository'
import { getPublicPath } from '../../../../utilities/utilities'
export default class SpriteCreateEvent {
constructor(
@ -25,7 +24,7 @@ export default class SpriteCreateEvent {
return callback(false)
}
const public_folder = path.join(process.cwd(), 'public', 'sprites')
const public_folder = getPublicPath('sprites')
// Ensure the folder exists
await fs.mkdir(public_folder, { recursive: true })
@ -38,7 +37,7 @@ export default class SpriteCreateEvent {
const uuid = sprite.id
// Create folder with uuid
const sprite_folder = path.join(public_folder, uuid)
const sprite_folder = getPublicPath('sprites', uuid)
await fs.mkdir(sprite_folder, { recursive: true })
callback(true)

View File

@ -1,10 +1,10 @@
import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import fs from 'fs'
import path from 'path'
import prisma from '../../../../utilities/prisma'
import CharacterManager from '../../../../managers/characterManager'
import { gameMasterLogger } from '../../../../utilities/logger'
import { getPublicPath } from '../../../../utilities/utilities'
type Payload = {
id: string
@ -17,7 +17,7 @@ export default class GMSpriteDeleteEvent {
private readonly io: Server,
private readonly socket: TSocket
) {
this.public_folder = path.join(process.cwd(), 'public', 'sprites')
this.public_folder = getPublicPath('sprites')
}
public listen(): void {
@ -43,7 +43,7 @@ export default class GMSpriteDeleteEvent {
}
private async deleteSpriteFolder(spriteId: string): Promise<void> {
const finalFilePath = path.join(this.public_folder, spriteId)
const finalFilePath = getPublicPath('sprites', spriteId)
if (fs.existsSync(finalFilePath)) {
await fs.promises.rmdir(finalFilePath, { recursive: true })

View File

@ -2,7 +2,6 @@ import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import { Sprite } from '@prisma/client'
import SpriteRepository from '../../../../repositories/spriteRepository'
import CharacterManager from '../../../../managers/characterManager'
import characterRepository from '../../../../repositories/characterRepository'
interface IPayload {}

View File

@ -2,10 +2,10 @@ import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import prisma from '../../../../utilities/prisma'
import type { Prisma, SpriteAction } from '@prisma/client'
import path from 'path'
import { writeFile, mkdir } from 'node:fs/promises'
import sharp from 'sharp'
import CharacterManager from '../../../../managers/characterManager'
import { getPublicPath } from '../../../../utilities/utilities'
type SpriteActionInput = Omit<SpriteAction, 'id' | 'spriteId' | 'frameWidth' | 'frameHeight'> & {
sprites: string[]
@ -123,7 +123,7 @@ export default class SpriteUpdateEvent {
}
async function saveSpritesToDisk(id: string, processedActions: ProcessedSpriteAction[]) {
const publicFolder = path.join(process.cwd(), 'public', 'sprites', id)
const publicFolder = getPublicPath('sprites', id)
await mkdir(publicFolder, { recursive: true })
await Promise.all(
@ -146,7 +146,7 @@ export default class SpriteUpdateEvent {
.png()
.toBuffer()
const filename = path.join(publicFolder, `${action}.png`)
const filename = getPublicPath('sprites', id, `${action}.png`)
await writeFile(filename, combinedImage)
})
)

View File

@ -1,10 +1,10 @@
import path from 'path'
import fs from 'fs/promises'
import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import prisma from '../../../../utilities/prisma'
import characterRepository from '../../../../repositories/characterRepository'
import { gameMasterLogger } from '../../../../utilities/logger'
import { getPublicPath } from '../../../../utilities/utilities'
type Payload = {
id: string
@ -17,7 +17,7 @@ export default class GMTileDeleteEvent {
private readonly io: Server,
private readonly socket: TSocket
) {
this.public_folder = path.join(process.cwd(), 'public', 'tiles')
this.public_folder = getPublicPath('tiles')
}
public listen(): void {
@ -54,7 +54,7 @@ export default class GMTileDeleteEvent {
}
private async deleteTileFile(tileId: string): Promise<void> {
const finalFilePath = path.join(this.public_folder, `${tileId}.png`)
const finalFilePath = getPublicPath('tiles', `${tileId}.png`)
try {
await fs.unlink(finalFilePath)
} catch (error: any) {

View File

@ -2,7 +2,6 @@ import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import { Tile } from '@prisma/client'
import TileRepository from '../../../../repositories/tileRepository'
import CharacterManager from '../../../../managers/characterManager'
import characterRepository from '../../../../repositories/characterRepository'
interface IPayload {}

View File

@ -1,7 +1,6 @@
import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import prisma from '../../../../utilities/prisma'
import CharacterManager from '../../../../managers/characterManager'
import characterRepository from '../../../../repositories/characterRepository'
type Payload = {

View File

@ -1,11 +1,11 @@
import { Server } from 'socket.io'
import { TSocket } from '../../../../utilities/types'
import { writeFile } from 'node:fs/promises'
import path from 'path'
import fs from 'fs/promises'
import prisma from '../../../../utilities/prisma'
import characterRepository from '../../../../repositories/characterRepository'
import { gameMasterLogger } from '../../../../utilities/logger'
import { getPublicPath } from '../../../../utilities/utilities'
interface ITileData {
[key: string]: Buffer
@ -30,7 +30,7 @@ export default class TileUploadEvent {
return
}
const public_folder = path.join(process.cwd(), 'public', 'tiles')
const public_folder = getPublicPath('tiles')
// Ensure the folder exists
await fs.mkdir(public_folder, { recursive: true })
@ -43,7 +43,7 @@ export default class TileUploadEvent {
})
const uuid = tile.id
const filename = `${uuid}.png`
const finalFilePath = path.join(public_folder, filename)
const finalFilePath = getPublicPath('tiles', filename)
await writeFile(finalFilePath, tileData)
})

View File

@ -12,6 +12,7 @@ import fs from 'fs'
import zoneRepository from '../repositories/zoneRepository'
import zoneManager from '../managers/zoneManager'
import { httpLogger } from './logger'
import { getPublicPath } from './utilities'
async function addHttpRoutes(app: Application) {
/**
@ -117,9 +118,9 @@ async function addHttpRoutes(app: Application) {
let assetPath
if (assetType === 'sprites' && spriteId) {
assetPath = path.join(process.cwd(), 'public', assetType, spriteId, fileName)
assetPath = getPublicPath(assetType, spriteId, fileName)
} else {
assetPath = path.join(process.cwd(), 'public', assetType, fileName)
assetPath = getPublicPath(assetType, fileName)
}
if (!fs.existsSync(assetPath)) {

View File

@ -1,6 +1,6 @@
import pino from 'pino'
import fs from 'fs'
import path from 'path'
import { getRootPath } from './utilities'
// Array of log types
const LOG_TYPES = ['http', 'game', 'gameMaster', 'app', 'queue', 'command'] as const
@ -30,7 +30,7 @@ const loggers = Object.fromEntries(LOG_TYPES.map((type) => [type, createLogger(t
const watchLogs = () => {
LOG_TYPES.forEach((type) => {
const logFile = path.join(__dirname, '../../logs', `${type}.log`)
const logFile = getRootPath('logs', `${type}.log`)
fs.watchFile(logFile, (curr, prev) => {
if (curr.size > prev.size) {

View File

@ -0,0 +1,15 @@
import config from './config'
import path from 'path'
export function getRootPath(folder: string, ...additionalSegments: string[]) {
return path.join(process.cwd(), folder, ...additionalSegments)
}
export function getAppPath(folder: string, ...additionalSegments: string[]) {
const baseDir = config.ENV === 'development' ? 'src' : 'dist'
return path.join(process.cwd(), baseDir, folder, ...additionalSegments)
}
export function getPublicPath(folder: string, ...additionalSegments: string[]) {
return path.join(process.cwd(), 'public', folder, ...additionalSegments)
}