Add article history by SKU and SSE update signals for live clients.
Expose getHistoryBySku as GET /article/:sku/history, and document mutation-emitted company signals via GET /events.
This commit is contained in:
@@ -30,6 +30,7 @@ const options = {
|
||||
tags: [
|
||||
{ name: 'Auth', description: 'Google SSO and session' },
|
||||
{ name: 'Health', description: 'Connectivity checks' },
|
||||
{ name: 'Events', description: 'SSE update signals for live clients' },
|
||||
{ name: 'Article', description: 'Articles under categories' },
|
||||
{ name: 'Category', description: 'Category tree and membership' },
|
||||
{ name: 'Company', description: 'Company CRUD' },
|
||||
@@ -211,6 +212,16 @@ function renderOperation(apiPath, method, operation) {
|
||||
if (bodyLines) lines.push(...bodyLines);
|
||||
}
|
||||
|
||||
const signals = operation['x-signals'];
|
||||
if (Array.isArray(signals) && signals.length) {
|
||||
lines.push('## Signals');
|
||||
lines.push('');
|
||||
lines.push(
|
||||
`On success, emits SSE signal${signals.length === 1 ? '' : 's'}: ${signals.map((s) => `\`${s}\``).join(', ')} (see [\`GET /events\`](../events.md)).`,
|
||||
);
|
||||
lines.push('');
|
||||
}
|
||||
|
||||
const responses = operation.responses || {};
|
||||
const successCodes = Object.keys(responses)
|
||||
.filter((c) => c.startsWith('2'))
|
||||
@@ -305,6 +316,35 @@ function renderReadme(operations) {
|
||||
lines.push('');
|
||||
lines.push('Machine-readable spec: [`openapi.json`](openapi.json).');
|
||||
lines.push('');
|
||||
lines.push('## Signals (SSE)');
|
||||
lines.push('');
|
||||
lines.push(
|
||||
'Clients subscribe via [`GET /events`](routes/events.md) (`text/event-stream`). After a successful mutation, the API emits a named SSE event (signal) to subscribers of the same selected company.',
|
||||
);
|
||||
lines.push('');
|
||||
lines.push('| Signal | Emitted by |');
|
||||
lines.push('|--------|------------|');
|
||||
|
||||
/** @type {Map<string, string[]>} */
|
||||
const bySignal = new Map();
|
||||
for (const op of operations) {
|
||||
const signals = spec.paths[op.path]?.[op.method]?.['x-signals'];
|
||||
if (!Array.isArray(signals)) continue;
|
||||
const label = `\`${op.method.toUpperCase()} ${op.path}\``;
|
||||
for (const signal of signals) {
|
||||
if (!bySignal.has(signal)) bySignal.set(signal, []);
|
||||
bySignal.get(signal).push(label);
|
||||
}
|
||||
}
|
||||
const signalNames = [...bySignal.keys()].sort();
|
||||
if (signalNames.length === 0) {
|
||||
lines.push('| — | _(none yet)_ |');
|
||||
} else {
|
||||
for (const signal of signalNames) {
|
||||
lines.push(`| \`${signal}\` | ${bySignal.get(signal).join(', ')} |`);
|
||||
}
|
||||
}
|
||||
lines.push('');
|
||||
lines.push('## DESIGN');
|
||||
lines.push('');
|
||||
lines.push('- for every route we have a file in /src/api/routes');
|
||||
|
||||
Reference in New Issue
Block a user