Ship configurator updates with catalog DB included for server deploy.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
lejay
2026-10-07 17:13:03 +02:00
co-authored by Cursor
parent 6c0d7e47b8
commit 30921aade6
75 changed files with 15618 additions and 1300 deletions
+111
View File
@@ -0,0 +1,111 @@
import pool, { run } from '../db/index.js';
const MAX_NAME_LENGTH = 100;
function parseDesign(row) {
if (!row) return null;
try {
return { ...row, config: JSON.parse(row.config) };
} catch {
return { ...row, config: null };
}
}
export async function getSavedDesigns(req, res) {
try {
const { rows } = await pool.query(
`SELECT id, name, config, created_at, updated_at
FROM saved_designs
ORDER BY updated_at DESC, id DESC`
);
res.json(rows.map(parseDesign));
} catch (err) {
res.status(500).json({ error: err.message });
}
}
export async function createSavedDesign(req, res) {
try {
const name = String(req.body?.name || '').trim();
const config = req.body?.config;
if (!name) return res.status(400).json({ error: 'Le nom est requis.' });
if (name.length > MAX_NAME_LENGTH) {
return res.status(400).json({ error: `Le nom ne peut pas dépasser ${MAX_NAME_LENGTH} caractères.` });
}
if (!config || typeof config !== 'object' || Array.isArray(config)) {
return res.status(400).json({ error: 'Configuration invalide.' });
}
await run(
`INSERT INTO saved_designs (name, config)
VALUES ($1, $2)`,
[name, JSON.stringify(config)]
);
const { rows } = await pool.query(
`SELECT id, name, config, created_at, updated_at
FROM saved_designs
ORDER BY id DESC
LIMIT 1`
);
res.status(201).json(parseDesign(rows[0]));
} catch (err) {
res.status(500).json({ error: err.message });
}
}
export async function updateSavedDesign(req, res) {
try {
const id = Number(req.params.id);
const name = String(req.body?.name || '').trim();
const config = req.body?.config;
if (!Number.isInteger(id) || id < 1) {
return res.status(400).json({ error: 'Identifiant invalide.' });
}
if (!name) return res.status(400).json({ error: 'Le nom est requis.' });
if (name.length > MAX_NAME_LENGTH) {
return res.status(400).json({ error: `Le nom ne peut pas dépasser ${MAX_NAME_LENGTH} caractères.` });
}
if (!config || typeof config !== 'object' || Array.isArray(config)) {
return res.status(400).json({ error: 'Configuration invalide.' });
}
const { rows } = await pool.query('SELECT id FROM saved_designs WHERE id = $1 LIMIT 1', [id]);
if (rows.length === 0) return res.status(404).json({ error: 'Armoire sauvegardée introuvable.' });
await run(
`UPDATE saved_designs
SET name = $1, config = $2, updated_at = datetime('now')
WHERE id = $3`,
[name, JSON.stringify(config), id]
);
const { rows: updatedRows } = await pool.query(
`SELECT id, name, config, created_at, updated_at
FROM saved_designs
WHERE id = $1
LIMIT 1`,
[id]
);
res.json(parseDesign(updatedRows[0]));
} catch (err) {
res.status(500).json({ error: err.message });
}
}
export async function deleteSavedDesign(req, res) {
try {
const id = Number(req.params.id);
if (!Number.isInteger(id) || id < 1) {
return res.status(400).json({ error: 'Identifiant invalide.' });
}
const { rows } = await pool.query('SELECT id FROM saved_designs WHERE id = $1 LIMIT 1', [id]);
if (rows.length === 0) return res.status(404).json({ error: 'Armoire sauvegardée introuvable.' });
await run('DELETE FROM saved_designs WHERE id = $1', [id]);
res.status(204).end();
} catch (err) {
res.status(500).json({ error: err.message });
}
}