diff --git a/prisma/backup.ts b/prisma/backup.ts new file mode 100644 index 0000000..28400f8 --- /dev/null +++ b/prisma/backup.ts @@ -0,0 +1,74 @@ +import { Prisma, PrismaClient } from "@prisma/client"; +import * as fs from "fs/promises"; +import { env } from "process"; +import { createLogger } from "winston"; +import winston from "winston"; +import { customCLIFormat } from "../src/Middleware/error/logger"; + +const { errors, combine, timestamp, colorize, json } = winston.format; + +type ModelSelect = { + [k in Prisma.ModelName as Uncapitalize]?: V; +}; + +const logger = createLogger({ + levels: winston.config.syslog.levels, + format: combine(errors(), timestamp()), + silent: env.BACKUP_INFO === "false", + transports: [ + new winston.transports.Console({ level: "debug", format: combine(timestamp(), colorize(), customCLIFormat) }), + new winston.transports.File({ + filename: "/app/backup.log", + level: "debug", + format: combine(timestamp(), json({ space: 2 })), + }), + ], +}); + +async function generatePrismaBackup(models: ModelSelect): Promise<{ [k in keyof ModelSelect]?: any }> { + const prisma = new PrismaClient(); + + const data: { [k in keyof ModelSelect]?: any } = {}; + + for (const [k, v] of Object.entries(models) as [keyof ModelSelect, boolean][]) { + if (v) { + logger.info(`Extracting '${k}'...`); + + const _data = await (prisma[k] as any).findMany(); + + data[k] = _data; + + logger.info(`Finished extracting '${k}'. ${_data.length} records retrieved!`); + } + } + + return data; +} + +export const generateFullBackup = async () => { + logger.info(`Starting full database backup...`); + + return generatePrismaBackup({ + admin: true, + campaign: true, + discipline: true, + event: true, + group: true, + link: true, + media: true, + organisation: true, + participant: true, + role: true, + roleSchema: true, + team: true, + }); +}; + +export const writeFullBackup = async (path: string) => { + const data = await generateFullBackup(); + + logger.info(`Writing backup to file '${path}'`); + await fs.writeFile(path, JSON.stringify(data)); + + logger.info("Backup finished!"); +}; diff --git a/src/Middleware/error/logger.ts b/src/Middleware/error/logger.ts index 9674d1f..a04923d 100644 --- a/src/Middleware/error/logger.ts +++ b/src/Middleware/error/logger.ts @@ -6,7 +6,7 @@ const { const defaultJsonFormat = combine(errors({ stack: true }), timestamp(), json({ space: 2 })); -const customCLIFormat = printf(({ level, message, label, timestamp, stack }) => { +export const customCLIFormat = printf(({ level, message, label, timestamp, stack }) => { let output = `${level}${stack ? `(1/2:message)` : ""} at ${timestamp}${label ? ` (#${label})` : ""}: ${message}${ stack ? "\n" : "" }`;