From 735079c9ec0d42acbf68c79e08f6416ea572d6ad Mon Sep 17 00:00:00 2001 From: Lendruk Date: Mon, 10 Jun 2024 21:54:17 +0100 Subject: [PATCH] Change vault instance data structure --- backend/src/db/VaultController.ts | 7 +-- backend/src/db/master/schema.ts | 15 ++--- backend/src/db/vault/db.ts | 6 +- backend/src/routes/images/createImage.ts | 58 +++++++++---------- backend/src/routes/images/getImage.ts | 20 +++---- .../src/routes/images/getImageThumbnail.ts | 20 +++---- backend/src/routes/images/index.ts | 6 +- backend/src/routes/media/createMediaItems.ts | 6 +- backend/src/routes/media/deleteMediaItem.ts | 6 +- backend/src/routes/videos/getVideo.ts | 2 +- 10 files changed, 71 insertions(+), 75 deletions(-) diff --git a/backend/src/db/VaultController.ts b/backend/src/db/VaultController.ts index dd88adf..760665b 100644 --- a/backend/src/db/VaultController.ts +++ b/backend/src/db/VaultController.ts @@ -6,10 +6,7 @@ import * as vaultSchema from './vault/schema'; export type VaultDb = BetterSQLite3Database; -export type VaultInstance = { - vault: Vault; - db: VaultDb; -} +export type VaultInstance = Vault & { db: VaultDb }; export class VaultController { public static vaults: Map = new Map(); @@ -19,7 +16,7 @@ export class VaultController { const newDb = new Database(`${vault.path}/vault.sqlite`); const db = drizzle(newDb, { schema: vaultSchema }); await migrate(db, { migrationsFolder: 'migrations/vault' }); - this.vaults.set(vault.id, { vault, db }); + this.vaults.set(vault.id, { ...vault, db }); } public static getVault(vaultId: string) { diff --git a/backend/src/db/master/schema.ts b/backend/src/db/master/schema.ts index 73bc2dc..70ecb7e 100644 --- a/backend/src/db/master/schema.ts +++ b/backend/src/db/master/schema.ts @@ -1,11 +1,12 @@ -import type { InferSelectModel } from "drizzle-orm"; -import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; +import type { InferSelectModel } from 'drizzle-orm'; +import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'; -export const vaults = sqliteTable("vaults", { - id: text("id").primaryKey(), - name: text("name"), - path: text("path").notNull(), - createdAt: integer("createdAt").notNull().default(Date.now()), +export const vaults = sqliteTable('vaults', { + id: text('id').primaryKey(), + name: text('name'), + path: text('path').notNull(), + createdAt: integer('createdAt').notNull().default(Date.now()), + hasInstalledSD: integer('has_installed_sd').notNull().default(0) }); export type Vault = InferSelectModel; \ No newline at end of file diff --git a/backend/src/db/vault/db.ts b/backend/src/db/vault/db.ts index 4476674..4bad058 100644 --- a/backend/src/db/vault/db.ts +++ b/backend/src/db/vault/db.ts @@ -1,7 +1,7 @@ import Database from 'better-sqlite3'; import { drizzle } from 'drizzle-orm/better-sqlite3'; -import * as schema from './schema' -const sqlite = new Database("vault.sqlite"); +import * as schema from './schema'; +const sqlite = new Database('vault.sqlite'); export const db = drizzle(sqlite, { schema }); -console.log("db init"); +console.log('db init'); diff --git a/backend/src/routes/images/createImage.ts b/backend/src/routes/images/createImage.ts index 2125583..1c3efce 100644 --- a/backend/src/routes/images/createImage.ts +++ b/backend/src/routes/images/createImage.ts @@ -1,6 +1,5 @@ import { FastifyReply, RouteOptions } from 'fastify'; import { Request } from '../../types/Request'; -import { db } from '../../db/vault/db'; import { TagTableSchema, mediaItems, tags as tagsTable, tagsToMediaItems } from '../../db/vault/schema'; import { randomUUID } from 'crypto'; import path from 'path'; @@ -9,39 +8,38 @@ import { eq } from 'drizzle-orm'; import { checkVault } from '../../hooks/checkVault'; const createImage = async (request: Request, reply: FastifyReply) => { - const vaultInstance = request.vault; - - if(!vaultInstance) { - return reply.status(400).send('No vault provided'); - } - - const { vault } = vaultInstance; - - const body = request.body as { image: string, tags: TagTableSchema[] }; - const imageBase64 = body.image; - const tags: TagTableSchema[] = body.tags; - - const id = randomUUID(); - const imageBuffer = Buffer.from(imageBase64.replace(/^data:image\/\w+;base64,/, ""), 'base64'); - await fs.writeFile(path.join(vault.path, "media", 'images', `${id}.png`), imageBuffer); - // TODO - Use fs.stat instead - const fileSize = imageBuffer.byteLength; - console.log(id); - const mediaItem = await db.insert(mediaItems).values({ fileName: id, extension: "png", type: "image", fileSize, createdAt: Date.now() }).returning(); - - if(tags && tags.length > 0) { - await db.insert(tagsToMediaItems).values(tags.map(tag => ({ tagId: tag.id, mediaItemId: mediaItem[0].id }))).returning(); - for(const tag of tags) { - await db.update(tagsTable).set({ mediaCount: tag.mediaCount + 1 }).where(eq(tagsTable.id, tag.id)); - } - } - - return reply.send({ message: "Image registered", id }); + const vault = request.vault; + + if(!vault) { + return reply.status(400).send('No vault provided'); + } + + const { db } = vault; + const body = request.body as { image: string, tags: TagTableSchema[] }; + const imageBase64 = body.image; + const tags: TagTableSchema[] = body.tags; + + const id = randomUUID(); + const imageBuffer = Buffer.from(imageBase64.replace(/^data:image\/\w+;base64,/, ''), 'base64'); + await fs.writeFile(path.join(vault.path, 'media', 'images', `${id}.png`), imageBuffer); + // TODO - Use fs.stat instead + const fileSize = imageBuffer.byteLength; + console.log(id); + const mediaItem = await db.insert(mediaItems).values({ fileName: id, extension: 'png', type: 'image', fileSize, createdAt: Date.now() }).returning(); + + if(tags && tags.length > 0) { + await db.insert(tagsToMediaItems).values(tags.map(tag => ({ tagId: tag.id, mediaItemId: mediaItem[0].id }))).returning(); + for(const tag of tags) { + await db.update(tagsTable).set({ mediaCount: tag.mediaCount + 1 }).where(eq(tagsTable.id, tag.id)); + } + } + + return reply.send({ message: 'Image registered', id }); }; export default { method: 'POST', url: '/images', handler: createImage, - onRequest: checkVault, + onRequest: checkVault, } as RouteOptions; \ No newline at end of file diff --git a/backend/src/routes/images/getImage.ts b/backend/src/routes/images/getImage.ts index 04ad02e..2fe4760 100644 --- a/backend/src/routes/images/getImage.ts +++ b/backend/src/routes/images/getImage.ts @@ -4,19 +4,19 @@ import * as fs from 'fs/promises'; import { VaultController } from '../../db/VaultController'; const getImageThumbnail = async (request: FastifyRequest, reply: FastifyReply) => { - const params = request.params as { fileName: string; vaultId: string }; + const params = request.params as { fileName: string; vaultId: string }; - const vaultId = params.vaultId; - if(!vaultId) { - return reply.status(400).send("Vault ID is required"); - } + const vaultId = params.vaultId; + if(!vaultId) { + return reply.status(400).send('Vault ID is required'); + } - const fileName = params.fileName; - const { vault } = VaultController.getVault(vaultId); - const imagePath = path.join(vault.path, "media", 'images', `${fileName}`); - const image = await fs.readFile(imagePath); + const fileName = params.fileName; + const vault = VaultController.getVault(vaultId); + const imagePath = path.join(vault.path, 'media', 'images', `${fileName}`); + const image = await fs.readFile(imagePath); - return reply.header('Content-Type', 'image/jpg').send(image); + return reply.header('Content-Type', 'image/jpg').send(image); }; export default { diff --git a/backend/src/routes/images/getImageThumbnail.ts b/backend/src/routes/images/getImageThumbnail.ts index 31814ab..dba9cd6 100644 --- a/backend/src/routes/images/getImageThumbnail.ts +++ b/backend/src/routes/images/getImageThumbnail.ts @@ -4,20 +4,20 @@ import * as fs from 'fs/promises'; import { VaultController } from '../../db/VaultController'; const getImageThumbnail = async (request: FastifyRequest, reply: FastifyReply) => { - const params = request.params as { fileName: string; vaultId: string }; + const params = request.params as { fileName: string; vaultId: string }; - const vaultId = params.vaultId; - if(!vaultId) { - return reply.status(400).send("Vault ID is required"); - } + const vaultId = params.vaultId; + if(!vaultId) { + return reply.status(400).send('Vault ID is required'); + } - const fileName = params.fileName; - const { vault } = VaultController.getVault(vaultId); + const fileName = params.fileName; + const vault = VaultController.getVault(vaultId); - const imagePath = path.join(vault.path, 'media', 'images', '.thumb', `${fileName}`); - const image = await fs.readFile(imagePath); + const imagePath = path.join(vault.path, 'media', 'images', '.thumb', `${fileName}`); + const image = await fs.readFile(imagePath); - return reply.header('Content-Type', 'image/jpg').send(image); + return reply.header('Content-Type', 'image/jpg').send(image); }; export default { diff --git a/backend/src/routes/images/index.ts b/backend/src/routes/images/index.ts index 2a39d72..257ef97 100644 --- a/backend/src/routes/images/index.ts +++ b/backend/src/routes/images/index.ts @@ -1,5 +1,5 @@ -import createImage from "./createImage"; -import getImage from "./getImage"; -import getImageThumbnail from "./getImageThumbnail"; +import createImage from './createImage'; +import getImage from './getImage'; +import getImageThumbnail from './getImageThumbnail'; export default [createImage, getImage, getImageThumbnail]; \ No newline at end of file diff --git a/backend/src/routes/media/createMediaItems.ts b/backend/src/routes/media/createMediaItems.ts index e0cb513..1291c1e 100644 --- a/backend/src/routes/media/createMediaItems.ts +++ b/backend/src/routes/media/createMediaItems.ts @@ -16,13 +16,13 @@ const { pipeline } = require('node:stream'); const pump = util.promisify(pipeline); const createMediaItems = async (request: Request, reply: FastifyReply) => { - const vaultInstance = request.vault; + const vault = request.vault; - if(!vaultInstance) { + if(!vault) { return reply.status(400).send('No vault provided'); } - const { db, vault } = vaultInstance; + const { db } = vault; const parts = request.parts(); for await (const part of parts) { if (part.type === 'file') { diff --git a/backend/src/routes/media/deleteMediaItem.ts b/backend/src/routes/media/deleteMediaItem.ts index 64984ea..1d31d4f 100644 --- a/backend/src/routes/media/deleteMediaItem.ts +++ b/backend/src/routes/media/deleteMediaItem.ts @@ -7,14 +7,14 @@ import * as fs from 'fs/promises'; import { checkVault } from '../../hooks/checkVault'; const deleteMediaItem = async (request: Request, reply: FastifyReply) => { - const vaultInstance = request.vault; - if(!vaultInstance) { + const vault = request.vault; + if(!vault) { return reply.status(400).send('No vault provided'); } const { ids } = request.params as { ids: string }; const parsedIdArray: string[] = JSON.parse(ids); - const { vault, db } = vaultInstance; + const { db } = vault; try { for (const rawId of parsedIdArray) { const parsedId = Number.parseInt(rawId ?? ''); diff --git a/backend/src/routes/videos/getVideo.ts b/backend/src/routes/videos/getVideo.ts index 8b3bfdf..d62bf07 100644 --- a/backend/src/routes/videos/getVideo.ts +++ b/backend/src/routes/videos/getVideo.ts @@ -12,7 +12,7 @@ const getVideo = async (request: FastifyRequest, reply: FastifyReply) => { } const fileName = params.fileName; - const { vault } = VaultController.getVault(vaultId); + const vault = VaultController.getVault(vaultId); const videoPath = path.join(vault.path, 'media', 'videos', fileName!); const videoStream = createReadStream(videoPath);