Improve API controllers: case-insensitive search, scoped queries, cleanup
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-05-15 21:41:27 +02:00
parent cc0c5233eb
commit c4c95fa972
4 changed files with 45 additions and 44 deletions
-8
View File
@@ -1,13 +1,5 @@
const db = require('../config/db');
const axios = require('axios');
// Use your existing insertCardImage for initial URL insert
const { insertCardImage } = require('../models/cardImageModel');
/**
* GET /cardImage/:cardId
* Returns the image blob of a card. If not stored, downloads from image_url, saves to DB.
*/
async function getCardImage(req, res) {
const { cardId } = req.params;
+35 -20
View File
@@ -1,33 +1,48 @@
const db = require('../config/db');
/**
* GET /exportCards
* Returns all cards with their printings and amount_owned
*/
async function exportCards(req, res) {
try {
// Fetch all cards
const [cards] = await db.execute(`
SELECT id, name, card_type AS type, frame_type, level, race, attribute, link_val, tcg_date, ocg_date
FROM cards
`);
const { search, type } = req.query;
// Fetch all printings with sets and rarities
const [printings] = await db.execute(`
SELECT csr.card_id, csr.set_id, csr.card_set_code AS set_code, csr.amount_owned,
try {
const conditions = [];
const cardParams = [];
if (search?.trim()) {
conditions.push('LOWER(name) LIKE ?');
cardParams.push(`%${search.trim().toLowerCase()}%`);
}
if (type?.trim()) {
conditions.push('LOWER(card_type) LIKE ?');
cardParams.push(`%${type.trim().toLowerCase()}%`);
}
const where = conditions.length ? `WHERE ${conditions.join(' AND ')}` : '';
const [cards] = await db.execute(
`SELECT id, name, card_type AS type, frame_type, level, race, attribute, link_val, tcg_date, ocg_date
FROM cards ${where}`,
cardParams
);
if (cards.length === 0) return res.json([]);
// Only fetch printings for the cards we actually returned
const cardIds = cards.map(c => c.id);
const placeholders = cardIds.map(() => '?').join(', ');
const [printings] = await db.execute(
`SELECT csr.card_id, csr.set_id, csr.card_set_code AS set_code, csr.amount_owned,
s.set_name,
r.id AS rarity_id, r.rarity_name, r.rarity_code
FROM card_sets_rarity csr
JOIN sets s ON csr.set_id = s.id
JOIN rarities r ON csr.rarity_id = r.id
`);
WHERE csr.card_id IN (${placeholders})`,
cardIds
);
// Map printings to cards
const cardMap = {};
cards.forEach(card => {
cardMap[card.id] = { ...card, printings: [] };
});
cards.forEach(card => { cardMap[card.id] = { ...card, printings: [] }; });
printings.forEach(p => {
if (cardMap[p.card_id]) {
cardMap[p.card_id].printings.push({
@@ -37,7 +52,7 @@ async function exportCards(req, res) {
rarity_id: p.rarity_id,
rarity_name: p.rarity_name,
rarity_code: p.rarity_code,
amount_owned: p.amount_owned || 0
amount_owned: p.amount_owned ?? 0,
});
}
});
+1 -1
View File
@@ -122,6 +122,7 @@ async function importCardsInternal() {
await conn.execute(`
INSERT INTO card_images (card_id, image_url)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE image_url = VALUES(image_url)
`, [card.id, img.image_url]);
addedImages++;
}
@@ -136,7 +137,6 @@ async function importCardsInternal() {
conn.release();
}
batch.length = 0;
}
const durationSeconds = ((Date.now() - startTime) / 1000).toFixed(2);
+4 -10
View File
@@ -1,16 +1,10 @@
const db = require('../config/db');
const { getLocalDBVersion } = require('../models/dbVersionModel');
async function getDatabaseVersion(req, res) {
try {
const [rows] = await db.execute(`
SELECT database_version, last_update
FROM db_version
ORDER BY last_update DESC
LIMIT 1
`);
if (!rows.length) return res.json({ database_version: 'unknown' });
res.json({ database_version: rows[0].database_version });
const version = await getLocalDBVersion();
if (!version) return res.json({ database_version: 'unknown' });
res.json({ database_version: version.database_version });
} catch (err) {
console.error('Failed to fetch DB version:', err);
res.status(500).json({ error: 'Failed to fetch database version' });