const { listComposes, getComposeEnv, getContainers } = require('./dokployClient'); const { extractPortalMeta } = require('./portalMeta'); function escapeHtml(value) { return String(value) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } async function buildCards(environmentId) { const composes = await listComposes(environmentId); const settled = await Promise.allSettled( composes.map(async (c) => { const { env, appName } = await getComposeEnv(c.composeId); const meta = extractPortalMeta(env, c.name); if (!meta) return null; let containerState = 'unknown'; try { const containers = await getContainers(appName); containerState = containers[0]?.state || 'stopped'; } catch { containerState = 'unknown'; } return { composeId: c.composeId, appName, composeStatus: c.composeStatus, containerState, meta }; }) ); const cards = []; settled.forEach((result, i) => { if (result.status === 'fulfilled') { if (result.value) cards.push(result.value); } else { cards.push({ error: true, composeId: composes[i].composeId, name: composes[i].name }); } }); return cards; } function renderCard(card) { if (card.error) { return `
状態取得失敗
compose: ${escapeHtml(composeStatus)} / container: ${escapeHtml(containerState)}
${openLink} ${actionButtons}