UNPKG

@extenshi/mcp

Version:

Extenshi MCP server — bring the extension catalog (search, security, market research) and pre-publish scanning into your AI tools

48 lines • 1.99 kB
/** * Minimal Server-Sent Events frame parser for the scan progress stream. * * Vendored from `@extenshi/cli` (tools/extenshi-cli/src/sse.ts) so this package * stays a clean standalone npm publish with no cross-workspace dependency * (npm rejects `workspace:*` at publish time — see scripts/publish.sh in the * CLI). The scan backend emits `text/event-stream` with named events * (`progress`, `result`, `error`) plus keep-alive comment frames (`:ping`). * * Pure (no I/O): feed it the accumulated buffer, get back the complete events * plus the unconsumed tail to carry into the next chunk. */ /** * Split an accumulated SSE buffer into complete events. Frames are delimited by * a blank line (`\n\n`); a partial trailing frame is returned as `rest`. * Comment frames (lines starting with `:`) and dataless frames are skipped. */ export function parseSseFrames(buffer) { let buf = buffer.replace(/\r\n/g, '\n'); const events = []; while (true) { const boundary = buf.indexOf('\n\n'); if (boundary === -1) break; const frame = buf.slice(0, boundary); buf = buf.slice(boundary + 2); let eventName = 'message'; const dataLines = []; for (const line of frame.split('\n')) { if (line === '' || line.startsWith(':')) continue; // blank or comment (keep-alive) const colon = line.indexOf(':'); const field = colon === -1 ? line : line.slice(0, colon); let value = colon === -1 ? '' : line.slice(colon + 1); if (value.startsWith(' ')) value = value.slice(1); if (field === 'event') eventName = value; else if (field === 'data') dataLines.push(value); } if (dataLines.length > 0) { events.push({ event: eventName, data: dataLines.join('\n') }); } } return { events, rest: buf }; } //# sourceMappingURL=sse.js.map