()
| 91 | return result |
| 92 | } |
| 93 | |
| 94 | async function generateOpenAPI() { |
| 95 | // Stub env for OpenAPI generation when missing (e.g. Vercel Next build) |
| 96 | const stubs: Record<string, string> = { |
| 97 | ANTHROPIC_API_KEY: 'sk-ant-dummy-for-openapi-generation', |
| 98 | OLLAMA_BASE_URL: 'https://ollama.example.com', |
| 99 | OPEN_ROUTER_API_KEY: 'sk-or-v1-dummy-for-openapi-generation', |
| 100 | PGLITE: 'true', |
| 101 | ENCRYPTION_KEY: 'deadbeef'.repeat(8), // 64-char hex (valid, not weak) |
| 102 | JWT_SECRET: 'openapi-gen-jwt-secret-placeholder-32ch', |
| 103 | ALLOWED_ORIGINS: 'https://openapi-gen.example', |
| 104 | APP_NAME: 'OpenAPI Generation', |
| 105 | WEB_APP_URL: 'https://openapi-gen.example', |
| 106 | } |
| 107 | for (const [k, v] of Object.entries(stubs)) if (!process.env[k]) process.env[k] = v |
| 108 | |
| 109 | const { default: app } = await import('../src/app.js') |
| 110 | |
| 111 | // Create Fastify instance (same as production) |
| 112 | const fastify = Fastify({ |
| 113 | logger: false, // Disable logging for generation |
| 114 | pluginTimeout: 30000, // Increase timeout for plugin loading (30 seconds) |
| 115 | }) |
| 116 | |
| 117 | try { |
| 118 | // Register @fastify/swagger FIRST (before routes) |
| 119 | // Swagger needs to scan routes as they're registered |
| 120 | await fastify.register(swagger, { |
| 121 | openapi: { |
| 122 | info: { |
| 123 | title: 'Basilic API', |
| 124 | version: '1.0.0', |
| 125 | description: 'Basilic API documentation', |
| 126 | }, |
| 127 | ...openapiSecurity, |
| 128 | }, |
| 129 | }) |
| 130 | |
| 131 | // Register app (which autoloads plugins + routes) |
| 132 | // Swagger will automatically scan route schemas as they're registered |
| 133 | await fastify.register(app, { allowTest: false }) |
| 134 | |
| 135 | // Wait for Fastify to be ready before generating OpenAPI |
| 136 | await fastify.ready() |
| 137 | |
| 138 | // Generate OpenAPI JSON |
| 139 | const openApiDocument = fastify.swagger() |
| 140 | |
| 141 | // Post-process to remove default-valued fields from required arrays |
| 142 | const processedDocument = removeDefaultsFromRequired(openApiDocument) as typeof openApiDocument |
| 143 | |
| 144 | // Write to openapi.json |
| 145 | const outputPath = join(scriptDir, '../openapi/openapi.json') |
| 146 | await writeFile(outputPath, JSON.stringify(processedDocument, null, 2), 'utf-8') |
| 147 | |
| 148 | console.log('OpenAPI spec generated:', outputPath) |
| 149 | } catch (error) { |
| 150 | console.error('Failed to generate OpenAPI spec', error) |
no test coverage detected