const PUBLIC_PAGE_LIMIT_KEY = 'public_page_limit'; function asPositiveInteger(value, fallback) { const parsed = Number(value); if (!Number.isFinite(parsed) || parsed < 1) return fallback; return Math.floor(parsed); } async function ensureConfigTable(pool) { await pool.query(` CREATE TABLE IF NOT EXISTS mindspace_config ( \`key\` VARCHAR(64) PRIMARY KEY, value TEXT NOT NULL, description VARCHAR(255) NULL, updated_at BIGINT NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci `); } export function defaultMindSpaceConfig(env = process.env) { return { publicPageLimit: asPositiveInteger(env.MINDSPACE_FREE_PUBLIC_PAGE_LIMIT ?? 5, 5), }; } async function readConfigRows(pool) { const [rows] = await pool.query( 'SELECT `key`, value FROM mindspace_config', ); return rows; } export async function ensureMindSpaceConfig(pool, { env = process.env, seedDefault = true } = {}) { await ensureConfigTable(pool); if (!seedDefault) return; const [rows] = await pool.query('SELECT COUNT(*) AS count FROM mindspace_config'); if (Number(rows[0]?.count ?? 0) > 0) return; const now = Date.now(); const defaults = defaultMindSpaceConfig(env); await pool.query( `INSERT INTO mindspace_config (\`key\`, value, description, updated_at) VALUES (?, ?, ?, ?)`, [PUBLIC_PAGE_LIMIT_KEY, String(defaults.publicPageLimit), '公开页面数量上限', now], ); } export async function loadMindSpaceConfig(pool, { env = process.env } = {}) { const config = defaultMindSpaceConfig(env); try { const rows = await readConfigRows(pool); for (const row of rows) { if (row.key === PUBLIC_PAGE_LIMIT_KEY) { config.publicPageLimit = asPositiveInteger(row.value, config.publicPageLimit); } } } catch (error) { if (error?.code === 'ER_NO_SUCH_TABLE') return config; throw error; } return config; } export async function updateMindSpaceConfig(pool, patch, { env = process.env } = {}) { await ensureConfigTable(pool); const updates = []; if (patch?.publicPageLimit !== undefined) { const publicPageLimit = asPositiveInteger(patch.publicPageLimit, null); if (!publicPageLimit) { throw Object.assign(new Error('公开页面数量上限必须是大于 0 的整数'), { code: 'invalid_mindspace_config', }); } updates.push([PUBLIC_PAGE_LIMIT_KEY, String(publicPageLimit), '公开页面数量上限']); } if (updates.length === 0) return loadMindSpaceConfig(pool, { env }); const now = Date.now(); for (const [key, value, description] of updates) { await pool.query( `INSERT INTO mindspace_config (\`key\`, value, description, updated_at) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value), description = VALUES(description), updated_at = VALUES(updated_at)`, [key, value, description, now], ); } return loadMindSpaceConfig(pool, { env }); } export const mindspaceConfigInternals = { PUBLIC_PAGE_LIMIT_KEY, };