import swaggerJsdoc from "swagger-jsdoc"; import { createRequire } from "module"; const _require = createRequire(import.meta.url); const { version } = _require("../package.json"); const options: swaggerJsdoc.Options = { definition: { openapi: "3.0.3", info: { title: "DocFast API", version, description: "Convert HTML, Markdown, and URLs to pixel-perfect PDFs. Built-in invoice & receipt templates.\n\n## Authentication\nAll conversion endpoints require an API key via `Authorization: Bearer ` or `X-API-Key: ` header. Get your key at [docfast.dev](https://docfast.dev).\n\n## Rate Limits\n- Demo: 5 conversions/hour, watermarked output\n- Pro tier: 5,000 PDFs/month, 30 req/min\n\nAll rate-limited endpoints return `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` headers. On `429`, a `Retry-After` header indicates seconds until the next allowed request.\n\n## Getting Started\n1. Try the demo endpoints (no auth required, 5/hour limit)\n2. Upgrade to Pro at [docfast.dev](https://docfast.dev) for clean output and higher limits\n3. Use your API key to convert documents", contact: { name: "DocFast", url: "https://docfast.dev", email: "support@docfast.dev", }, }, servers: [{ url: "https://docfast.dev", description: "Production" }], tags: [ { name: "Demo", description: "Try the API without authentication (watermarked, 5/hour)" }, { name: "Conversion", description: "Convert HTML, Markdown, or URLs to PDF" }, { name: "Templates", description: "Built-in document templates" }, { name: "Account", description: "Signup and key recovery" }, { name: "Billing", description: "Stripe-powered subscription management" }, { name: "System", description: "Health checks and usage stats" }, ], components: { securitySchemes: { BearerAuth: { type: "http", scheme: "bearer", description: "API key as Bearer token", }, ApiKeyHeader: { type: "apiKey", in: "header", name: "X-API-Key", description: "API key via X-API-Key header", }, }, headers: { "X-RateLimit-Limit": { description: "The maximum number of requests allowed in the current time window", schema: { type: "integer", example: 30, }, }, "X-RateLimit-Remaining": { description: "The number of requests remaining in the current time window", schema: { type: "integer", example: 29, }, }, "X-RateLimit-Reset": { description: "Unix timestamp (seconds since epoch) when the rate limit window resets", schema: { type: "integer", example: 1679875200, }, }, "Retry-After": { description: "Number of seconds to wait before retrying the request (returned on 429 responses)", schema: { type: "integer", example: 60, }, }, }, schemas: { PdfOptions: { type: "object", properties: { format: { type: "string", enum: ["Letter", "Legal", "Tabloid", "Ledger", "A0", "A1", "A2", "A3", "A4", "A5", "A6"], default: "A4", description: "Page size. Ignored if width/height are set.", }, landscape: { type: "boolean", default: false, description: "Landscape orientation", }, margin: { type: "object", description: "Page margins. Accepts CSS units (e.g. '20mm', '1in', '72px').", properties: { top: { type: "string", example: "20mm" }, bottom: { type: "string", example: "20mm" }, left: { type: "string", example: "15mm" }, right: { type: "string", example: "15mm" }, }, }, printBackground: { type: "boolean", default: true, description: "Print background graphics and colors", }, filename: { type: "string", default: "document.pdf", description: "Suggested filename for the PDF download", }, waitUntil: { type: "string", enum: ["load", "domcontentloaded", "networkidle0", "networkidle2"], description: "Wait condition for page rendering before PDF generation.", }, headerTemplate: { type: "string", description: "HTML template for the page header. Requires displayHeaderFooter: true. Use these CSS classes for dynamic values: date, title, url, pageNumber, totalPages. Maximum size: 100KB. Example: ' / '", }, footerTemplate: { type: "string", description: "HTML template for the page footer. Requires displayHeaderFooter: true. Supports the same CSS classes as headerTemplate. Maximum size: 100KB.", }, displayHeaderFooter: { type: "boolean", default: false, description: "Whether to show header and footer templates. Must be true for headerTemplate/footerTemplate to render.", }, scale: { type: "number", minimum: 0.1, maximum: 2, default: 1, description: "Scale of the webpage rendering. 1 = 100%, 0.5 = 50%, 2 = 200%.", example: 1, }, pageRanges: { type: "string", description: "Paper ranges to print, e.g. '1-5', '1,3,5', '2-4,6'. Empty string means all pages.", example: "1-3", }, preferCSSPageSize: { type: "boolean", default: false, description: "Give any CSS @page size declared in the page priority over the format option.", }, width: { type: "string", description: "Paper width with units. Overrides format. Accepts CSS units (e.g. '10in', '210mm', '8.5in').", example: "8.5in", }, height: { type: "string", description: "Paper height with units. Overrides format. Accepts CSS units (e.g. '11in', '297mm').", example: "11in", }, }, }, Error: { type: "object", properties: { error: { type: "string", description: "Error message" }, }, }, }, }, }, apis: ["./dist/routes/*.js", "./dist/index.js"], }; export const swaggerSpec = swaggerJsdoc(options);