import path from 'path'; import { fileURLToPath } from 'url'; import swaggerJsdoc from 'swagger-jsdoc'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const root = path.resolve(__dirname, '../..'); export const openApiOptions = { definition: { openapi: '3.0.3', info: { title: 'Dash API', version: '1.0.0', description: 'Backend API for Dash — Google SSO auth, MSSQL, session cookies.\n\n' + 'Browser clients must send cookies (`credentials: \'include\'`) or an `Authorization: Bearer ` header. ' + 'Sessions use an HTTP-only `token` cookie (`Secure`, `SameSite=Strict`, 24h); HTTPS is required for login.', }, servers: [ { url: '/api', description: 'API Base (/api)' }, { url: '/', description: 'Root (/)' }, ], tags: [ { name: 'Auth', description: 'Google SSO and session' }, { name: 'Health', description: 'Connectivity checks' }, { name: 'POS', description: 'POS bind and sync API (/v1)' }, { 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' }, { name: 'CompanySetting', description: 'Company-scoped settings' }, { name: 'Unit', description: 'Company-scoped units of measure' }, { name: 'Brand', description: 'Company-scoped brands' }, { name: 'Supplier', description: 'Company-scoped suppliers (Lieferanten)' }, { name: 'Delivery', description: 'Company-scoped goods receipts (Lieferungen)' }, { name: 'Quote', description: 'Company-scoped quotes (Angebote)' }, { name: 'Order', description: 'Company-scoped sales orders (Aufträge)' }, { name: 'Customergroup', description: 'Company-scoped customer groups' }, { name: 'Entity', description: 'Company-scoped entities, addresses, and contacts' }, { name: 'Image', description: 'Content-addressed AVIF by fullHash' }, { name: 'Posterminal', description: 'Company-scoped POS terminals' }, { name: 'Printer', description: 'Company-scoped receipt and label printers' }, { name: 'Ledger', description: 'Append-only ledger transactions' }, { name: 'Stock', description: 'Manual stock additions and removals' }, { name: 'Warehouse', description: 'Company-scoped warehouses' }, { name: 'Serper', description: 'Serper Google image search and thumbnail streaming' }, { name: 'PublicCatalog', description: 'Public product catalog API' }, ], }, apis: [ path.join(root, 'src/api/openapi.js'), path.join(root, 'src/api/routes/**/*.js'), path.join(root, 'src/v1/**/*.js'), ], }; let cachedSpec = null; /** * Returns the parsed OpenAPI 3.0 specification object, cached in memory. * @param {boolean} [refresh=false] - Force rebuild of the spec * @returns {object} */ export function getOpenApiSpec(refresh = false) { if (!cachedSpec || refresh) { cachedSpec = swaggerJsdoc(openApiOptions); } return cachedSpec; }