import { getQuickPlazaFromPublicHtmlStatus, quickPlazaFromChat, quickPlazaFromPublicHtml, } from '../mindspace-chat-plaza.mjs'; function assertRouter(api) { if ( !api || typeof api.get !== 'function' || typeof api.post !== 'function' ) { throw new Error( 'attachPortalMindSpaceChatShareRoutes requires an Express-compatible router', ); } } export function attachPortalMindSpaceChatShareRoutes( api, { h5Root = '', getMindSpacePages = () => null, getMindSpaceChatSave = () => null, getMindSpacePublications = () => null, getPlazaPosts = () => null, resolveChatSaveBundle, resolvePlazaPostUrl, mapPlazaError = () => 500, sendData = (res, _req, data, status = 200) => res.status(status).json({ data }), sendError = (res, _req, status, code, message) => res.status(status).json({ error: { code, message } }), handlePlazaError = (_res, _req, error) => { throw error; }, handleMindSpaceError = (_res, _req, error) => { throw error; }, quickPlazaFromChatFn = quickPlazaFromChat, getQuickPlazaFromPublicHtmlStatusFn = getQuickPlazaFromPublicHtmlStatus, quickPlazaFromPublicHtmlFn = quickPlazaFromPublicHtml, now = Date.now, logger = console, } = {}, ) { assertRouter(api); if ( typeof resolveChatSaveBundle !== 'function' || typeof resolvePlazaPostUrl !== 'function' ) { throw new Error( 'attachPortalMindSpaceChatShareRoutes requires chat and Plaza resolvers', ); } api.post('/mindspace/v1/pages/quick-share-from-chat', async (req, res) => { const chatSave = getMindSpaceChatSave(); if (!getMindSpacePages() || !chatSave) { return res.status(503).json({ message: 'MindSpace 未启用' }); } try { const bundle = await resolveChatSaveBundle( req.currentUser, h5Root, req.body, ); logger.log( '[quick-share] bundle resolved, hasHtml:', Boolean(bundle.resolvedHtml), ); if (!bundle.resolvedHtml) { throw Object.assign(new Error('无法读取链接页面内容'), { code: 'static_page_not_found', }); } const shared = await chatSave.createSharedHtml({ userId: req.currentUser.id, html: bundle.resolvedHtml.content, sourceFilename: bundle.resolvedHtml.filename, }); return res.status(201).json({ data: { publicUrl: shared.publicUrl, filename: shared.filename, }, }); } catch (error) { logger.error('[quick-share] error:', error); return handleMindSpaceError(res, req, error); } }); api.post('/mindspace/v1/pages/quick-plaza-from-chat', async (req, res) => { const pages = getMindSpacePages(); const publications = getMindSpacePublications(); const plazaPosts = getPlazaPosts(); if (!pages || !publications || !plazaPosts) { return sendError( res, req, 503, 'plaza_unavailable', 'Plaza 或 MindSpace 未启用', ); } const startedAt = now(); try { const bundle = await resolveChatSaveBundle( req.currentUser, h5Root, req.body, ); const result = await quickPlazaFromChatFn({ user: req.currentUser, bundle, body: req.body ?? {}, mindSpacePages: pages, mindSpacePublications: publications, plazaPosts, }); logger.info('[quick-plaza] ok', { ms: now() - startedAt, pageId: result.pageId, publicationId: result.publicationId, postId: result.post?.id, }); return sendData(res, req, result, 201); } catch (error) { logger.error('[quick-plaza] error:', { ms: now() - startedAt, error, }); if (error?.code && mapPlazaError(error) !== 500) { return handlePlazaError(res, req, error); } return handleMindSpaceError(res, req, error); } }); api.get( '/mindspace/v1/pages/quick-plaza-from-public-html/status', async (req, res) => { const pages = getMindSpacePages(); const publications = getMindSpacePublications(); const plazaPosts = getPlazaPosts(); if (!pages || !publications || !plazaPosts) { return sendError( res, req, 503, 'plaza_unavailable', 'Plaza 或 MindSpace 未启用', ); } try { const relativePath = String( req.query?.relative_path ?? req.query?.relativePath ?? '', ).trim(); const result = await getQuickPlazaFromPublicHtmlStatusFn({ user: req.currentUser, relativePath, mindSpacePages: pages, mindSpacePublications: publications, plazaPosts, }); const postId = result.post?.id; return sendData(res, req, { ...result, plaza_url: postId ? resolvePlazaPostUrl(postId, req) : null, }); } catch (error) { if (error?.code && mapPlazaError(error) !== 500) { return handlePlazaError(res, req, error); } return handleMindSpaceError(res, req, error); } }, ); api.post( '/mindspace/v1/pages/quick-plaza-from-public-html', async (req, res) => { const pages = getMindSpacePages(); const chatSave = getMindSpaceChatSave(); const publications = getMindSpacePublications(); const plazaPosts = getPlazaPosts(); if ( !pages || !chatSave || !publications || !plazaPosts ) { return sendError( res, req, 503, 'plaza_unavailable', 'Plaza 或 MindSpace 未启用', ); } const startedAt = now(); try { const relativePath = String( req.body?.relative_path ?? req.body?.relativePath ?? '', ).trim(); const result = await quickPlazaFromPublicHtmlFn({ user: req.currentUser, relativePath, mindSpacePages: pages, mindSpacePublications: publications, plazaPosts, readWorkspaceHtml: (input) => chatSave.readWorkspaceHtml(input), }); const plazaUrl = resolvePlazaPostUrl( result.post.id, req, ); logger.info('[quick-plaza-public-html] ok', { ms: now() - startedAt, pageId: result.pageId, publicationId: result.publicationId, postId: result.post?.id, relativePath, }); return sendData( res, req, { ...result, plaza_url: plazaUrl, }, 201, ); } catch (error) { logger.error('[quick-plaza-public-html] error:', { ms: now() - startedAt, error, }); if (error?.code === 'ALREADY_PUBLISHED') { const postId = error?.details?.post_id ?? error?.details?.postId; if (postId) { error.details = { ...(error.details ?? {}), plaza_url: resolvePlazaPostUrl(postId, req), }; } } if (error?.code && mapPlazaError(error) !== 500) { return handlePlazaError(res, req, error); } return handleMindSpaceError(res, req, error); } }, ); }