mrfrys-node-server/src/utils/utils.ts

311 lines
8.2 KiB
TypeScript
Executable file

/* ----------------------------------------------------------------------------
Question Server
GitLab: <https://gitlab.com/MrFry/mrfrys-node-server>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
------------------------------------------------------------------------- */
export default {
ReadFile: ReadFile,
ReadJSON: ReadJSON,
WriteFile: WriteFile,
writeFileAsync: writeFileAsync,
AppendToFile: AppendToFile,
FileExists: FileExists,
CreatePath: CreatePath,
WatchFile: WatchFile,
ReadDir: ReadDir,
CopyFile: CopyFile,
GetDateString: GetDateString,
formatUrl: formatUrl,
deleteFile: deleteFile,
uploadFile: uploadFile,
statFile: statFile,
renameFile: renameFile,
deleteDir: deleteDir,
formatBytes: formatBytes,
}
import fs from 'fs'
import { v4 as uuidv4 } from 'uuid'
import logger from '../utils/logger'
import { Request } from '../types/basicTypes'
interface URLFormatOptions {
pathname?: string
query?: { [key: string]: string }
}
function formatUrl(options: URLFormatOptions): string {
const path = options.pathname || ''
if (!options.query || Object.keys(options.query).length === 0) {
return path
}
const queryString =
'?' +
Object.keys(options.query)
.map((key) => {
return `${key}=${encodeURIComponent(options.query[key])}`
})
.join('&')
return path + queryString
}
function GetDateString(
referenceDate?: Date | string,
noTime?: boolean
): string {
const date = referenceDate ? new Date(referenceDate) : new Date()
if (noTime) {
return (
date.getFullYear() +
'-' +
('0' + (date.getMonth() + 1)).slice(-2) +
'-' +
('0' + date.getDate()).slice(-2)
)
} else {
return (
date.getFullYear() +
'-' +
('0' + (date.getMonth() + 1)).slice(-2) +
'-' +
('0' + date.getDate()).slice(-2) +
' ' +
('0' + date.getHours()).slice(-2) +
':' +
('0' + date.getMinutes()).slice(-2) +
':' +
('0' + date.getSeconds()).slice(-2)
)
}
}
function CopyFile(from: string, to: string): void {
CreatePath(to)
fs.copyFileSync(from, to)
}
function ReadDir(path: string, listHidden?: boolean): Array<string> {
if (listHidden) {
return fs.readdirSync(path)
} else {
return fs.readdirSync(path).filter((file) => {
return !file.startsWith('.')
})
}
}
function ReadJSON(name: string): any {
try {
return JSON.parse(ReadFile(name))
} catch (err) {
console.error(err)
throw new Error('Coulndt parse JSON in "ReadJSON", file: ' + name)
}
}
function ReadFile(name: string): string {
if (!FileExists(name)) {
throw new Error('No such file: ' + name)
}
return fs.readFileSync(name, 'utf8')
}
function FileExists(path: string): boolean {
return fs.existsSync(path)
}
function WatchFile(file: string, callback: Function): void {
if (FileExists(file)) {
fs.watchFile(file, () => {
fs.readFile(file, 'utf8', (err, data) => {
if (err) {
// console.log(err)
} else {
callback(data)
}
})
})
} else {
throw new Error(`${file} does not exits to watch`)
}
}
function CreatePath(path: string, onlyPath?: boolean): void {
if (FileExists(path)) {
return
}
const spath = path.split('/')
let currDir = spath[0]
for (let i = 1; i < spath.length; i++) {
if (currDir !== '' && !fs.existsSync(currDir)) {
try {
fs.mkdirSync(currDir)
} catch (err) {
console.log('Failed to make ' + currDir + ' directory... ')
console.error(err)
}
}
currDir += '/' + spath[i]
}
if (onlyPath) {
fs.mkdirSync(path)
}
}
function WriteFile(content: string, path: string): void {
CreatePath(path)
fs.writeFileSync(path, content)
}
function writeFileAsync(content: string, path: string): void {
CreatePath(path)
fs.writeFile(path, content, function (err) {
if (err) {
logger.Log(
'Error writing file: ' + path + ' (sync)',
logger.GetColor('redbg')
)
}
})
}
function AppendToFile(data: string, file: string): void {
CreatePath(file)
try {
fs.appendFileSync(file, '\n' + data)
} catch (err) {
logger.Log(
'Error appendig to file log file: ' + file + ' (sync)',
logger.GetColor('redbg')
)
logger.Log(data)
console.error(err)
}
}
function deleteFile(fname: string): Boolean {
if (FileExists(fname)) {
fs.unlinkSync(fname)
return true
}
return false
}
function deleteDir(dirName: string): Boolean {
if (FileExists(dirName)) {
fs.rmSync(dirName, { recursive: true })
return true
}
return false
}
function uploadFile(
req: Request,
path: string
): Promise<{
body: Request['body']
fileName: string
filePath: string
}> {
return new Promise((resolve, reject) => {
try {
if (!req.files) {
logger.Log(
`Unable to upload file, req.files is undefined`,
logger.GetColor('redbg')
)
return
}
const file = req.files.file
// FIXME: Object.keys(req.files).forEach((file) => { saveFile() })
CreatePath(path, true)
let fileName = file.name.replace(/\.+/g, '.').replace(/\/+/g, '/')
let fileDestination = path + '/' + fileName
if (FileExists(fileDestination)) {
const id = uuidv4().split('-')[0]
const temp = file.name.split('.')
const extension = temp.pop()
fileName = temp.join('.') + '_' + id + '.' + extension
fileDestination = path + '/' + fileName
}
file.mv(fileDestination, (err: Error) => {
if (err) {
logger.Log(
`Unable to upload file!`,
logger.GetColor('redbg')
)
console.error(err)
reject(err)
} else {
logger.Log(
`Uploaded: ${fileName} to ${fileDestination}`,
logger.GetColor('blue')
)
resolve({
body: req.body,
fileName: fileName,
filePath: fileDestination,
})
}
})
} catch (err) {
logger.Log(
`Unable to upload file, error on stderr`,
logger.GetColor('redbg')
)
console.error(err)
reject(err)
}
})
}
function statFile(file: string): fs.Stats {
if (FileExists(file)) {
return fs.statSync(file)
} else {
return null
}
}
function renameFile(oldPath: string, newPath: string): string {
if (FileExists(oldPath)) {
fs.renameSync(oldPath, newPath)
return newPath
} else {
return null
}
}
function formatBytes(number: number, unit: 'MB' | 'GB' = 'MB'): string {
let res = number / 1024 / 1024 // MB
if (unit === 'MB') {
return `${res} MB`
}
res = res / 1024
if (unit === 'GB') {
return `${res} GB`
}
return `${number} byte`
}