Appearance
@fc/swagger-nuxt-module
Módulo Nuxt especializado em Swagger / OpenAPI. Concentra-se em duas responsabilidades:
- gerar specs (individual e opcionalmente agregada por namespace) a partir de blocos
@swaggere tipos TypeScript, com validação de referências e diagnóstico detalhado; - fornecer o componente
<SwaggerUi />— um wrapper genérico em torno doswagger-uicomo componente Vue 3 reativo, com estilos compatíveis com modo escuro.
Toda a UI de portal (landing page, cabeçalho, cards, alternador de tema, tokens visuais) é de responsabilidade da aplicação que consome o módulo (ex.: @fc/docs-api).
Instalação
bash
pnpm add @fc/swagger-nuxt-moduleConfiguração básica
ts
export default defineNuxtConfig({
modules: ['@fc/swagger-nuxt-module'],
swagger: {
info: {
title: 'Minha API',
description: 'Descrição da API.',
version: '1.0.0',
},
apis: ['./server/routes/**/*.ts'],
routes: {
json: '/_openapi.json',
ui: '/_swagger',
},
uiDisponibilidade: 'dev-local',
// Opcional e sem default: declare um scheme apenas se alguma operação for
// referenciá-lo no `@swagger`. A proteção por chave de API não precisa
// disto — é anotada em runtime a partir de `apiPublica.apiKey`.
securitySchemes: {
ApiKeyAuth: {
type: 'apiKey',
in: 'header',
name: 'x-api-key',
},
},
types: [
{
name: 'MinhaRespostaApi',
src: './server/utils/tipos.ts',
},
],
},
})Agregação por namespace
Na app hospedeira, adicione swagger.agregador. Cada documento agregado informa o id, o conteúdo exibido e as fontes de onde os paths serão lidos.
ts
export default defineNuxtConfig({
modules: ['@fc/swagger-nuxt-module'],
swagger: {
info: { title: 'Portal', description: '...', version: '1.0.0' },
apis: [],
agregador: {
documentos: [
{
id: 'rgps',
titulo: 'RGPS',
descricao: 'Endpoints previdenciários públicos.',
fontes: [
{ app: '../prev-api', prefixosPath: ['/rgps/api/v1/', '/api/v1/'] },
{ app: '../rmi-api', prefixosPath: ['/rgps/api/v1/'] },
],
},
],
},
},
})O núcleo puro usado nessa agregação também é uma superfície pública para runtimes de servidor:
ts
import { agregarDocumentoSwagger } from '@fc/swagger-nuxt-module/agregador'Ele aplica a mesma filtragem e validação do CLI, rejeitando colisões de path, schema e securityScheme, além de $ref interno quebrado. A ordem das fontes não altera o documento produzido nem o diagnóstico.
Metadados de um mesmo PathItem (parameters, $ref, servers, summary e description) só podem reaparecer com conteúdo estruturalmente idêntico. Conteúdo divergente falha com diagnóstico estável, em vez de depender da ordem das fontes.
Componente <SwaggerUi />
O módulo registra globalmente o componente SwaggerUi, que inicializa programaticamente o swagger-ui no DOM. Ele recebe as props:
urlSpec— URL (relativa ou absoluta) da spec OpenAPI a renderizar;tema—'claro' | 'escuro'; aplicada ao wrapper para acompanhar o tema da aplicação;layout— layout do Swagger UI; por padrão,StandaloneLayout;opcoes— opções extras repassadas aoSwaggerUI(...);plugins— plugins adicionais do Swagger UI.
Eventos emitidos:
pronto(instancia)— emitido quando o Swagger UI foi inicializado; a instância expõegetStore()especActionspara quem precisar interagir com o store do Swagger UI;erro(erro)— emitido em caso de falha na inicialização.
Exemplo mínimo:
vue
<script setup lang="ts">
const urlSpec = '/_swagger/specs/principal.json'
const tema = 'escuro'
</script>
<template>
<SwaggerUi :url-spec="urlSpec" :tema="tema" />
</template>Modo escuro
O componente importa automaticamente swagger-ui-escuro.css, que aplica overrides quando a aplicação define o atributo data-fc-swagger-tema="escuro" em <html>. Recomenda-se repassar o mesmo estado via prop tema.
Extensões
O módulo não injeta plugins nem estado adicional. Para estender o Swagger UI (selectors, reducers, wrapComponents), passe um plugin próprio pela prop plugins e, se necessário, use o evento pronto para despachar ações no store via instancia.getStore().dispatch(...).
CLI
O módulo expõe dois binários:
generate-swagger-spec— lê a configuraçãoswaggerda app atual e grava apenas a spec individual em./.swagger/principal.json(ou no caminho informado via--out). Uso típico em apps que expõem sua própria OpenAPI (ex.:prev-api,rmi-api,backoffice).generate-swagger-spec-agregado— executa fluxo completo: gera a spec principal, gera uma spec por documento configurado emswagger.agregadore emite omanifest.json. Uso típico no app hospedeiro do portal (ex.:docs-api).
bash
generate-swagger-spec
generate-swagger-spec --out ./public/_swagger/specs/principal.json
generate-swagger-spec-agregadoEstrutura gerada pelo binário agregado (em public/_swagger/ por padrão):
specs/principal.json: spec agregada com todos os endpoints do portal;specs/<id>.json: spec por documento configurado (ex.:specs/rgps.json);manifest.json: manifesto dos documentos, com URLs relativas (./specs/<id>.json).
O diretório dos artefatos é sempre public/_swagger/; configurar outro valor em swagger.artefatos.diretorio é rejeitado antes de qualquer escrita. IDs de documento aceitam somente letras minúsculas, números e hífens, sem repetição. A publicação é atômica e o gerador só substitui uma saída identificada pelo marcador interno .fc-swagger. Ao migrar uma saída antiga ainda sem marcador, remova apenas public/_swagger/ uma vez e execute novamente o comando.
Runtime
Após executar spec:gen, a app expõe:
/_openapi.json: handler dinâmico com a spec individual eserversderivados da requisição atual (registrado pelo módulo);/_swagger/specs/*.json,/_swagger/manifest.json: servidos estaticamente porpublic/_swagger/via Nitro.
O contrato público canônico é /_openapi.json. O arquivo principal.json é somente a base imutável produzida no build: o runtime o lê e interpreta uma vez por processo, cria uma cópia independente para cada requisição e então aplica origem, autenticação e schemas do envelope de erro PDPJ. Essa cópia evita que dados derivados de um host ou de uma configuração contaminem a resposta seguinte. Rotas dos namespaces internos não entram no contrato gerado nem no documento servido.
Como a resposta depende da origem e da configuração em execução, /_openapi.json usa Cache-Control: no-store. Se a base não puder ser carregada, o consumidor recebe uma mensagem estável, sem caminho de arquivo ou detalhe do sistema; o diagnóstico completo fica restrito ao log do servidor.
A UI (landing, visualizador, rotas /_swagger e /_swagger/:documento) fica por conta da aplicação.
O runtime público recebe somente info, routes e uiDisponibilidade, usados pela UI automática. Globs, tipos, fontes do agregador, schemes e caminhos de geração não são serializados no payload do cliente. O handler OpenAPI usa diretamente o diretório padrão compartilhado com o gerador.
Quando uma operação já exige autenticação e seu path também exige chave de API, o transformador inclui ApiKeyAuth no mesmo requisito. Em OpenAPI isso significa que os dois controles são obrigatórios; objetos separados no array significariam alternativas e publicariam incorretamente “um ou outro”.
UI automática (/_swagger)
Quando uiAutomatica não é desativado, o módulo serve uma página HTML em routes.ui que carrega swagger-ui-dist do CDN unpkg.com. A dependência de CDN é intencional. Se os assets externos não carregarem (CDN indisponível, rede corporativa/proxy bloqueando, CSP restritiva) ou se o SwaggerUIBundle não inicializar dentro de 8 segundos, a página exibe um painel de erro nativo com:
- explicação do problema e causas prováveis;
- botão para recarregar a página;
- link direto para
routes.json, permitindo consumir a spec bruta por qualquer ferramenta externa.
A página também contém <noscript> com orientação equivalente para navegadores sem JavaScript.
Disponibilidade da UI automática
Use uiDisponibilidade para controlar quando a rota routes.ui deve responder:
sempre— comportamento legado; publica a UI em qualquer ambiente.dev— publica apenas quando a aplicação está em modo de desenvolvimento.dev-local— publica apenas em desenvolvimento local e host local (localhost,127.0.0.1,::1).
Fora do contexto permitido, a rota responde 404. Esse é o modo recomendado para apps que usam docs-api como portal público e querem manter /_swagger apenas como ferramenta local.
Diagnóstico de erros
O gerador falha com relatório consolidado quando encontra problemas como:
- YAML/JSDoc inválido em blocos
@swagger; - tipo raiz ausente ou schema TypeScript não serializável;
$refinterno quebrado;securitySchemereferenciado, mas não declarado;- conflito de
path + method, metadado dePathItem, schema ousecuritySchemedurante agregação.
O relatório sempre aponta app, arquivo, tipo e trecho relevante para correção.