import * as pages from '../../lib/db/repos/pages.js'; import * as map from '../../lib/db/repos/migration_map.js'; const SYS = { kind: 'system', id: null }; const slugify = (s) => (s || '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '').slice(0, 60) || 'page'; // BookStack REST: list GET /api/pages → {data:[{id,name}]}; detail GET /api/pages/:id // → {id,name,markdown,html}. Auth header: "Token :". export async function importBookstack({ apiUrl = process.env.BOOKSTACK_URL, tokenId = process.env.BOOKSTACK_TOKEN_ID, tokenSecret = process.env.BOOKSTACK_TOKEN_SECRET, spaceId, dryRun = false, fetchImpl = fetch }) { const headers = { Authorization: `Token ${tokenId}:${tokenSecret}` }; const listRes = await fetchImpl(`${apiUrl}/api/pages`, { headers }); if (!listRes.ok) throw new Error(`bookstack list ${listRes.status}`); const { data = [] } = await listRes.json(); let created = 0; for (const item of data) { if (await map.seen('bookstack', `page:${item.id}`, 'page')) continue; created++; if (dryRun) continue; const dRes = await fetchImpl(`${apiUrl}/api/pages/${item.id}`, { headers }); if (!dRes.ok) throw new Error(`bookstack page ${item.id} ${dRes.status}`); const d = await dRes.json(); const body = d.markdown && d.markdown.trim() ? d.markdown : (d.html || ''); const p = await pages.create({ space_id: spaceId, slug: slugify(d.name), title: d.name || 'Untitled', body_md: body }, SYS); await map.record('bookstack', `page:${item.id}`, 'page', p.id); } return { created }; }