import { database, withTransaction, type QueryContext } from '../database.js'; import type { NoteImage } from '../../shared/types.js'; interface ImageRow extends Omit { id: number | string; note_id: number | string; order_index: number | string } function toImage(row: ImageRow): NoteImage { return { ...row, id: Number(row.id), note_id: Number(row.note_id), order_index: Number(row.order_index), url: /^https?:\/\//.test(row.url) || row.url.startsWith('/') ? row.url : `/uploads/${row.url}` }; } export const imagesRepository = { async listByNote(noteId: number, versionNumber?: number): Promise { const rows = await database.all(`SELECT id, note_id, url, width, height, order_index, storage_provider, storage_key FROM images WHERE note_id = ?${versionNumber ? ' AND version_number = ?' : ''} ORDER BY order_index ASC, id ASC`, versionNumber ? [noteId, versionNumber] : [noteId]); return rows.map(toImage); }, async createMany(noteId: number, images: { url: string; width: number; height: number; storageProvider: 'local' | 'tencent_cos' | 'external'; storageKey: string }[], versionNumber = 1, existing?: QueryContext): Promise { const insert = async (tx: QueryContext) => { const ids: number[] = []; for (let index = 0; index < images.length; index += 1) { const image = images[index]; ids.push(await tx.insertId('INSERT INTO images (note_id, url, width, height, order_index, storage_provider, storage_key, version_number) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [noteId, image.url, image.width, image.height, index, image.storageProvider, image.storageKey, versionNumber])); } return ids; }; return existing ? insert(existing) : withTransaction(insert); }, async findById(id: number): Promise { const row = await database.one('SELECT id, note_id, url, width, height, order_index, storage_provider, storage_key FROM images WHERE id = ?', [id]); return row ? toImage(row) : null; }, };